Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/28/2023 in all areas

  1. When writing API code I often refer to the PW admin to get particular page IDs or field names. And when I'm writing client instructions I often need to insert the labels of particular fields. To make this quicker and more convenient I added some custom JavaScript to the PW admin that copies these things to the clipboard on Alt + click and Ctrl + click. The Page List item and inputfield header are briefly highlighted in yellow to signify that the copying has occurred. This is tested in Windows and I'm not sure if the Alt key / Ctrl key detection is the same for other operating systems but you could adjust the key detection as needed. In /site/ready.php // Add custom JS file to $config->scripts FilenameArray // This adds the custom JS fairly early in the FilenameArray which allows for stopping // event propagation so clicks on InputfieldHeader do not also expand/collapse InputfieldContent $wire->addHookBefore('ProcessController::execute', function(HookEvent $event) { // Optional: for superuser only if(!$event->wire()->user->isSuperuser()) return; $config = $event->wire()->config; $modified = filemtime($config->paths->templates . 'admin-assets/copy-on-click.js'); $js_url = $config->urls->templates . "admin-assets/copy-on-click.js?m=$modified"; $config->scripts->add($js_url); }); In /site/templates/admin-assets/copy-on-click.js $(document).ready(function() { // Copy a string to the clipboard function copyToClipboard(string) { const $temp = $('<input type="text" value="' + string + '">'); $('body').append($temp); $temp.select(); document.execCommand('copy'); $temp.remove(); } // Copy page ID when Page List row is Alt + clicked $(document).on('click', '.PageListItem', function(event) { if(event.altKey) { const classes = $(this).attr('class').split(' '); for(const item of classes) { if(item.startsWith('PageListID')) { const id = item.replace('PageListID', ''); copyToClipboard(id); $(this).effect('highlight', {}, 500); break; } } } }); // When InputfieldHeader is clicked $(document).on('click', '.InputfieldHeader', function(event) { let text = ''; // If Alt + clicked then copy the input name the label is for, or the ID as a fallback if(event.altKey) { event.preventDefault(); event.stopImmediatePropagation(); text = $(this).attr('for'); if(!text) text = $(this).parent().attr('id'); text = text.replace(/^Inputfield_|wrap_Inputfield_|wrap_/, '').trim(); } // If Ctrl + clicked then copy the label text else if(event.ctrlKey) { event.preventDefault(); event.stopImmediatePropagation(); text = $(this).text().trim(); // If AdminOnSteroids is installed use the below instead to exclude text within the AOS field edit link // text = $(this).clone().find('.aos_EditField').remove().end().text().trim(); } if(text) { copyToClipboard(text); $(this).effect('highlight', {}, 500); } }); }); Demo (using the Tracy console only as a convenient place to paste into for demonstration): Copying the field label is useful for getting the name of config fields too, for when you need them in your API code.
    3 points
  2. Good day @bernhard! I was testing @gebeer's PR (see this thread), and I was looking at the code of RockMigrations.module.php. It seems to me that it might be beneficial for supporting this long-time to split the code into submodules. I think that all the code that actually creates fields/templates/users... could be moved to a helper module(s). And the main one would deal with all the admin logic. This way it would be not only easier to add field-specific methods, but also possible to use those great methods in different types of workflows (including them). I would love to see other Pro fileds' specific methods added. Maybe other commercial or just 3rd party modules too. Maybe there could be some plugin system for those?
    2 points
  3. I didn't test includes or imports. As I've never worked with SCSS and LESS has always just worked for me I'd need input from others to make it work. I don't see a reason why RockFrontend should not also support SCSS. It would need some more work though than what I quickly did for this module on Tuesday, so it's not really a top priority ?
    2 points
  4. InputfieldFile has several settings that don't have config fields in the admin. See here: https://github.com/processwire/processwire/blob/5609935e4ee96611965550e57d3139200de95c35/wire/modules/Inputfield/InputfieldFile/InputfieldFile.module#L20-L26 I'm not sure of the reasons why but perhaps the thinking is that they would only needed for specialised uses of the inputfield. You could use a hook in /site/ready.php to add a config field for that setting to all files fields if you want to set it per field: $wire->addHookAfter('InputfieldFile::getConfigInputfields', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->object; /** @var InputfieldWrapper $wrapper */ $wrapper = $event->return; /** @var InputfieldCheckbox $f */ $f = $event->wire()->modules->get('InputfieldCheckbox'); $f->name = 'noShortName'; $f->label = 'Disable abbreviated filenames'; $f->label2 = 'Disable abbreviated filenames in inputfield'; $f->collapsed = Inputfield::collapsedBlank; $f->checked($inputfield->noShortName); $wrapper->add($f); }); Or if you want to disable it for all file fields: $wire->addHookAfter('InputfieldFile::renderReadyHook', function(HookEvent $event) { /** @var InputfieldFile $inputfield */ $inputfield = $event->object; $inputfield->noShortName = true; });
    2 points
  5. The module originated from an idea/discussion in this thread. I hope that helps to see more PRs for improving the PW backend ? https://github.com/baumrock/Scss Watch core files When working on PRs for the ProcessWire backend you'll notice that the core ships with several SCSS files and the corresponding CSS files. To make it easy to work on the SCSS files without the need of adding complicated build tools to your project you can simply install the Scss module and add the following in /site/ready.php $modules->get('Scss')->watchCore(); Now your SCSS files will be watched for changes and once you change something and reload your page you'll get the new CSS on the fly and can commit both changes ?
    1 point
  6. Hi I can anyone help me with manipulating ProFields Table rows? It works ok using first() and last() as per the README, however I can't seem to manipulate specific items, given a selector. I presume I'm doing something wrong when selecting the row(s). $tt = $pages->findOne("template=repeater_basetimetables,title=Silver") // Works - from README $page->of(false); $opday = $page->operatingcalendar_days->last(); $opday->timetable = $tt; $page->save('operatingcalendar_days'); // Doesn't work - set to TableRows is not an allowed type $page->of(false); $opday = $page->operatingcalendar_days("ttdate=2022-08-11"); $opday->timetable = $tt; $page->save('operatingcalendar_days'); // Doesn't work - no error $page->of(false); $opday = $page->operatingcalendar_days("ttdate=2022-08-11")->first(); $opday->timetable = $tt; $page->save('operatingcalendar_days'); Or, do I have to remove and re-create rows I want to modify? Cheers
    1 point
  7. Wow. I'm starting to see a pattern here. Thanks again!
    1 point
  8. I like to do that too - show the page ID and also the template name in the page list. I do that via a private module which isn't installed here as it would just confuse things for this demo. But when I'm entering an ID into some API code I feel safer if I'm copying and pasting rather than memorising and typing the ID in manually, particularly on larger sites where the IDs are getting up into 6 digits and it's easy to misread or transpose the digits.
    1 point
  9. Wouldn't it be enough to add methods to the class through hooks?? And have like: RockMigrationsProfieldsUtilities, instead of refactoring the main module?
    1 point
  10. Yes i see that the lines that handle the languages (148-154) is not checking if the array key is set yet. Will have to add that check to prevent the warning.
    1 point
  11. Hey Robin, thx for the tutorial! I just wanted to mention here, if anybody is reading this and looking for a solution, that RockMigrations has both features on board, as that is a very common need when working with PW from code. Page IDs can not be copied like in your example, but they can be shown in the page tree. Maybe I should change that. I like your solution. But on the other hand sometimes it's nice to just see the ID and with your solution you'd have to paste it somewhere just to see the id. On the other hand my solution pollutes the page tree. Maybe a combination would be ideal - a page tree that shows IDs on shift or alt or something and copies the ID on click. This is the very simple tweak that adds page ids to the page tree in RockMigrations: https://github.com/baumrock/RockMigrations/blob/main/tweaks/PageListShowIds.php Regarding the field names - in RockMigrations I had the problem that I not only needed the field's name but also it's possible values. Sometimes that's not as easy as just a 0/1. Sometimes there are string values or sometimes it is -1. I came up with adding a tooltip that shows the field name on hover plus the value of the hovered input element:
    1 point
  12. Don't forget that, when working with RockMigrations, you can still solve problems without RockMigrations ? So you have all the PW magic available, that means you could for example just use $files->copy() to copy files, or you could use exec("cp -r /foo /bar"); That all depends on your system and situation. RockMigrations just helps with an easy API for all the things that usually have to be done manually in the PW backend.
    1 point
  13. Following recent discussion about the Latte templating language, I figured I'd give it a try too and put together a Latte renderer for Wireframe: GitHub repository at https://github.com/wireframe-framework/WireframeRendererLatte Composer installation: composer require wireframe-framework/wireframe-renderer-latte In case anyone wants to try this, it would be interesting to hear your thoughts. I'm honestly not sure if I'll be using it much myself, and I built the module without any real Latte experience under my belt, so it's possible that it does things in surprising ways. Let me know if you run into any issues ? Syntax wise, Latte doesn't differ much from regular PHP templates — you just write your PHP code within {curly brackets}, and it gets automatically escaped (with what they call context-aware escaping). They have this thing called n:attributes though, which is actually quite nice shortcut, especially if you happen to dislike if..else and foreach: <ul n:if="$page->numChildren(true)" class="menu"> <li n:foreach="$page->children as $child"> <a n:tag-if="!$child->hide_from_menu" href="{$child->url}"> {$item->title} </a> </li> </ul> You can read more about Latte from https://latte.nette.org/en/. For more details about Wireframe renderers and how they are enabled and used, check out https://wireframe-framework.com/docs/view/renderers/.
    1 point
  14. Hi @Stefanowitsch, Are you using the javascript from the README? I think the UIkit ajax() function has changed so that could be the issue. You could try: fetch(window.location.href, { headers: { 'X-Requested-With': 'XMLHttpRequest', }, cache: 'no-store', }) .then(response => { if (response.ok) { return response.json(); } UIkit.util.addClass(instagram.$loading, 'uk-hidden'); console.error(response.statusText); // ERROR return []; }) .then(data => { // Hide spinner UIkit.util.addClass(instagram.$loading, 'uk-hidden'); if (!UIkit.util.isArray(data) || !data.length) return; // If no items do not render const items = []; data.forEach(item => { switch (item.type) { case 'VIDEO': items.push(instagram.renderItem(item.poster, item.alt, item.src)); break; case 'CAROUSEL_ALBUM': // If 4 or greater items, display a grid of the first 4 images with the rest hidden // Otherwise display the main image (no break, moves to default) if (item.children.length >= 4) { let out = ''; for (let i = 0; i < item.children.length; i++) { out += `<div${i < 4 ? '' : ' class=uk-hidden'}> ${instagram.renderItem(item.children[i].src, item.alt)} </div>`; } items.push(`<div class="uk-grid-collapse uk-child-width-1-2" data-uk-grid>${out}</div>`); break; } default: // IMAGE items.push(instagram.renderItem(item.src, item.alt)); break; } }); const count = items.length; if (count) { // Wrap all items with a div let out = ''; for (let i = 0; i < count; i++) { out += `<div id=instagram-item-${instagram.total + i}> ${items[i]} </div>`; } // Append items to the container UIkit.util.append(instagram.$el, out); // Attach scrollspy listener on last item of second last row if (count > 5) { UIkit.util.on(`#instagram-item-${instagram.total + count - 6}`, 'inview', () => instagram.get()); } // Update total instagram.total = instagram.total + count; } }); The next thing to do would be to try and get the full output that the script is returning. I'm not familiar enough with fetch() to know for certain but you could try console.log(response.text()); after the error log to see if that gives you it. My experience with the errors you've mentioned is that the first is caused by HTML being output/echoed before the JSON, and the second is usually caused by a deprecation notice being output. If you've got $config->debug enabled, try switching that off - if that works then check your logs to see what is triggering the notice and see if it can be resolved. Hope that helps, Chris
    1 point
  15. yes of course, I remember now Thanks!
    1 point
  16. Yeah that's why I'm asking ? I'm always using LESS and I've built all the tools to easily compile LESS to CSS on the fly. That's not the case for SCSS. I've just pushed an update and updated the readme to support what you need: https://github.com/baumrock/Scss
    1 point
  17. @bernhard Thanks! ? I was looking for a nice way to compile some SCSS (Bootstrap in my case) the other day and as Sassify has not been updated for almost 4 years I had a look into your Scss module. It might not have been your intention, but as this a viable wrapper for scssphp I could use it for my case as well. Maybe this can be a starting point for somebody else looking for a way to compile something else than the PW core: <?php $compiler = $modules->get('Scss')->compiler; $input_scss = $this->wire->config->paths->templates."scss/custom.scss"; $bootstrap_scss_path = $this->wire->config->paths->templates."bootstrap/scss"; $output_css = $this->wire->config->paths->templates."css/bootstrap_custom.css"; $output_map = $this->wire->config->paths->templates."css/bootstrap_custom.map"; $compiler->setSourceMap($compiler::SOURCE_MAP_FILE); $compiler->setSourceMapOptions([ // relative or full url to the above .map file 'sourceMapURL' => $output_map, // (optional) relative or full url to the .css file 'sourceMapFilename' => $output_css, // partial path (server root) removed (normalized) to create a relative url 'sourceMapBasepath' => $this->wire->config->paths->root, // (optional) prepended to 'source' field entries for relocating source files 'sourceRoot' => '/', ]); $compiler->addImportPath($bootstrap_scss_path); $compiler->setOutputStyle("compressed"); $result = $compiler->compileString('@import "'.$input_scss.'";', $this->wire->config->paths->templates."scss"); file_put_contents($output_map, $result->getSourceMap()); file_put_contents($output_css, $result->getCss()); ?>
    1 point
  18. Hi Jan Thanks for the welcome. $award->timetable is an artefact of me copy and pasting wrong, it should be $opday->timetable, which is a Page reference field in the table. $tt is a Page, the comment at the end that explains how I've assigned it ($pages->findOne). However I'm having the same problem if the field is a plain text. Your example (from the README) works correctly for me (it's essentially the first block in my code) however that's only the first() or last()) item - I'm needing to edit a specific filtered row (or set of rows) - those with a specific field value. I think this is what I'm struggling with - capturing those rows and editing them in a way the module will write back to the database table. Cheers
    1 point
  19. nice module. Could you also make it possible to just copy the current url? What I mean is add another button that when clicked copies the current url to the clipboard. I'm trying to accomplish that with the current options of the module but no luck. Maybe if I could hook the function before rendering there would be a chance…
    1 point
  20. I made it work with the instructions in Github. $config->MarkupSocialShareButtonsServices = array( "example" => array( "example_url" => "http://exampleurl.com/", "example_params" => "?url={url}&description={text}", "example_icon" => "<img src='{themeUrl}png/example.png'>", ) ); Using: https://api.whatsapp.com/send?text={url} Thank you!
    1 point
  21. Hello, I have something similar I hope you can adapt it to your needs. Mine is for user templates: <?php //adds a button to the end of the user edit page: $this->addHook('ProcessPageEdit::buildForm', function (HookEvent $event) { $current_page = $event->object->getPage(); if ($current_page->template->name != 'user') return; // this button is for the user edit page only if (empty($current_page->user_family_name)) return; // custom field is not yet filled in, which means the new User has not been saved but still being edited in the admin $id = (int) $current_page->id; if ($id != 0) { if ($current_page->hasRole('mycustomrole')) { $href = createLink($current_page); // this is a custom function to be implemented, it must generate and return the required URL $field = $this->modules->get('InputfieldButton'); $field->attr('class', $field->class . " my-custom-css-class-if-needed"); // this is just opitional, I left it here as an example $field->attr('value', 'Copy URL to clipboard...'); $field->attr('data-clipboard-text', $href); // data-clipboard-text is needed by https://clipboardjs.com/ $field->attr('href', ''); // $href $event->return = $event->return->append($field); } } }); The copy to clipboard action is performed by https://clipboardjs.com/ which can be loaded by the admin using various techniques or free modules (such as AdminOnSteroids or Admin Custom Files) or one can simply put this line into config.php: $config->scripts->add($config->urls->templates . "clipboard.min.js"); where clipboard.min.js is in the templates directory, for example. EDIT: I forgot to note that the hook goes into init.php
    1 point
×
×
  • Create New...