Jump to content

Robin S

Members
  • Posts

    4,928
  • Joined

  • Days Won

    321

Everything posted by Robin S

  1. @mel47, currently the PW core does not support showIf or requiredIf in custom fields for files/images. See this issue: https://github.com/processwire/processwire-issues/issues/1889 And even if that issue is resolved, the way the core is handling showIf/requiredIf at the moment means that it will only evaluate the showIf/requiredIf based on values of other custom fields for the image/file item, not fields in the page that is open in Page Edit. But I've just updated the CustomInputfieldDependencies module so that it should handle your case. Please update the module to v0.3.0 and test it again.
  2. When $config->debug and $config->advanced are true there is an "Autoload disabled" checkbox available in the module info for any autoload module. Checking this box disables the module in the same way as Tracy's Module Disabler panel, but might be useful on a site that doesn't have Tracy installed.
  3. For a case like this you can use the hookable method to return any markup you like, including an image. It won't work for a UIkit tooltip though because that only supports text. Example: $wire->addHookAfter('PageFieldInfo::getPageInfo', function(HookEvent $event) { $page = $event->arguments(0); // The page $inputfield = $event->arguments(1); // InputfieldPage $field = $event->arguments(2); // The Page Reference field // Return custom markup if($field->name === 'colour') { $image = $page->get('image[0]'); if($image) $event->return = "<img src='$image->url' alt='$image->description' style='max-width:200px; max-height:200px; margin-top:10px;'>"; } });
  4. Ryan said in the previous announcement that you can use a hook to set which pages become editable. So you could use this to make the grandchildren editable, or the children and the grandchildren if you wanted the child pages to serve as a kind of visual divider between the categories of options. Edit: example... // Define custom "children" for PageEditChildren $wire->addHookAfter('PageEditChildren::getChildren', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); if($page->template == 'blank') { $items = new PageArray(); foreach($page->children as $child) { $items->add($child); foreach($child->children as $grandchild) { $items->add($grandchild); } } $event->return = $items; } }); // Hook rendering of PageEditChildren "child" fieldsets // to apply a data attribute for identifying the template // It would be cool if PageEditChildren did this by default $wire->addHookBefore('InputfieldFieldset::render', function(HookEvent $event) { /* @var $fieldset InputfieldFieldset */ $fieldset = $event->object; $wrap_class = $fieldset->wrapClass(); if($wrap_class !== 'PageEditChild') return; $attr = $fieldset->wrapAttr(); if(!isset($attr['data-page'])) return; $p = $event->wire()->pages->get($attr['data-page']); if(!$p->id) return; $fieldset->wrapAttr('data-template', $p->template->name); }); Custom admin SCSS: li.PageEditChild[data-template="references"] { > .InputfieldHeader { background-color:#f0f3f7 !important; } }
  5. Since ProcessWire v3.0.152 we have been able to use custom Page classes: https://processwire.com/blog/posts/pw-3.0.152/#new-ability-to-specify-custom-page-classes Some PW users have said that they would like to have all their hooks relating to a particular Page class contained within their custom Page class file (in /site/classes/), to keep things tidy and organised. But custom Page classes do not have methods that fire on states like "init" or "ready", and it also wouldn't be ideal to attach hooks within a Page class because the class can be instantiated multiple times and therefore such hooks would be attached multiple times. I understand @bernhard has a feature that addresses this need built into his RockMigrations module, so check that out. And here's another approach, where hooks are attached in the places where you would normally attach them (e.g. in /site/ready.php or /site/init.php, or in the init() or ready() methods of some custom module) but the method that executes in the hook exists within your custom Page classes. Step 1 In /site/classes/DefaultPage.php, add the method shown below: class DefaultPage extends Page { // Call any Page methods with names that match the HookEvent object and method public function callHookMethods(HookEvent $event) { $objectName = $event->object->className; $methodName = $objectName . '_' . $event->method; if(!method_exists($this, $methodName)) return; $this->$methodName($event); } } This method looks for other Page method names that match the HookEvent object and method and if any exist it calls them. Hooks are attached using the format "Class::method" and this format wouldn't be valid for a method name, so an underscore is used instead of the two colons. E.g. "ProcessPageEdit::buildFormContent" would become "ProcessPageEdit_buildFormContent". Step 2 In any of your custom Page class files, add methods named to match the hookable methods you want to target. These custom Page classes should extend DefaultPage. In the example below I'm targeting hookable methods Pages::saveReady and ProcessPageEdit::buildFormContent in the BasicPagePage class. class BasicPagePage extends DefaultPage { public function Pages_saveReady(HookEvent $event) { // Show a message in the PW admin $this->wire()->message("About to save page named: $this->name"); } public function ProcessPageEdit_buildFormContent(HookEvent $event) { /** @var InputfieldWrapper $wrapper */ $wrapper = $event->return; // Add a custom markup field to Page Edit /** @var InputfieldMarkup $f */ $f = $this->wire()->modules->get('InputfieldMarkup'); $f->label = 'My custom markup'; $f->value = 'Hello!'; $wrapper->insertAfter($f, 'title'); } } Step 3 Attach hooks in the places where you normally would. You need to attach a hook for each hookable method you are targeting in your custom Page classes, but the hook code itself is minimal and where multiple Page classes target the same hookable method you only need it attach it once. In the example below I'm attaching hooks in /site/ready.php. $pages->addHookAfter('saveReady', function(HookEvent $event) { /** @var DefaultPage $page */ $page = $event->arguments(0); if($page instanceof DefaultPage) $page->callHookMethods($event); }); $wire->addHookAfter('ProcessPageEdit::buildFormContent', function(HookEvent $event) { /** @var ProcessPageEdit $ppe */ $ppe = $event->object; /** @var DefaultPage $page */ $page = $ppe->getPage(); if($page instanceof DefaultPage) $page->callHookMethods($event); }); Each hook only need to establish a $page object (often this is available as an argument to the hookable method) and if it's an instance of DefaultPage then it simply calls $page->callHookMethods($event), and any relevant hook-targeting methods for that particular Page class will fire. Here's the result of my two hook-targeting methods in BasicPagePage.php when I save a page of this class in Page Edit:
  6. @ryan, that sounds great, thanks!
  7. Just wondering, have you (or anyone else) ever needed to put anything into those files? What scenarios are they useful in? I use status files for "init", "readySite" and "readyAdmin", and I think once or twice I've used "finished", but I don't have a grasp on what the files you mentioned would be useful for.
  8. The header action feature is cool, thanks @ryan! Is there a way that a header action can be added through the PHP API rather than through the Inputfield JS API? A couple of reasons this could be useful: 1. I can imagine a module that would add some header action feature to every inputfield (or every inputfield of a particular type) and it would be simpler to do this via a hook before Inputfield::render(). 2. Sometimes the inputfield you want to target doesn't exist in the DOM when the page loads (e.g. Repeater subfields or other Ajax-loaded scenarios) and so the JS code to add the header action would also need to watch for other events like "reloaded" or "ajaxComplete", and again it would be easier to add the action in a before render hook. I was thinking that if the PHP API supported header actions then JS actions could be handled via an "event" property. So something like this... $action->event = 'myAction'; ...which means that clicking the icon would trigger a "myAction" event, and the developer would use JS like... $(document).on('myAction', '.Inputfield', function(event) { const $inputfield = $(event.target); // Do something involving the inputfield... }); And in case the action doesn't need JS but should instead be PHP-based or just link to some URL there could also be an "href" property which would make the icon into a link, perhaps to be used with URL hooks... $action->href = "/my-action/$page->id/$field->name"; ...and... $wire->addHook('/my-action/{page_id}/{field_name}', function($event) { // Do something with $event->page_id and $event->field_name here... }); What do you think?
  9. @Mats, I've released the module I mentioned above: If you want to use Media Lister to find an image and then copy it to a field in Page Edit you can follow these steps: Open Media Lister in one browser tab, and Page Edit for the page you want to copy an image to in another browser tab. Find the image you want to copy in Media Lister. Click the link in the Page column - this will open the page that contains the image in Page Edit and will focus the containing field. Use File Mover to select the image you want to copy. Switch to the browser tab that contains the page you want to copy the image to. In the destination field use File Mover to copy across the image you selected in the previous step.
  10. File Mover Allows the selection of files or images for moving or copying to a different field. The destination field can be on the same page as the source field or on a different page. Screencast For convenience in the screencast this demonstration shows moving and copying images and files between fields on the same page, but you can also move/copy between pages by following the same process. Usage In any Images or Files field, hover on the field label to show the File Mover icon. Clicking on the icon will reveal the File Mover buttons. If no items are yet selected you'll see a button labelled "Select items to later move or copy". Click the button to enter selection mode. While in selection mode, click one or more images/files to select them. When you have finished selecting items click the "Done" button. Note: you can only select from one Images and one Files field at a time before completing the move/copy step. In the Images or Files field that you want to move/copy the items to, hover the label to show the File Mover icon and click it to reveal the File Mover buttons. When you click the Move or Copy button the page will automatically be saved and the selected items will be moved or copied accordingly. There is also a button to clear the current selection if needed. If you hover on any of the buttons a tooltip shows the filenames of the currently selected items, in case you need a reminder. Configuration There is a field in the module config that defines which roles are allowed to use the File Mover module. If the field is left empty then all roles are allowed. https://github.com/Toutouwai/FileMover https://processwire.com/modules/file-mover/
  11. @netcarver, this information about unlisted videos may be relevant: https://help.vimeo.com/hc/en-us/articles/12426199699985-Overview-of-video-privacy-settings So for a video with a URL like https://vimeo.com/553329597/04c306a466 the src for the iframe embed will need to include h=04c306a466 in the query string.
  12. @netcarver, your version works great for the two examples I gave in the GitHub issue. Thanks!
  13. Ahh, the config inputfield was inheriting those settings from the field, which is unwanted. Should be fixed now in v0.1.1. Thanks for bringing it to my attention.
  14. I don't understand. It's not mandatory to set an initial value setting for a field, and if you have chosen to set an initial value it's not mandatory to keep it for any given page in Page Edit - you can clear the initial value.
  15. @MarkE, not sure I understand the issue but I've removed the InputfieldPage::isValidPage() check in v0.3.7 because it seems unnecessary seeing as FieldtypePage will itself do this validation before it saves a value.
  16. @MarkE, I reported the issue here: https://github.com/processwire/processwire-issues/issues/1904
  17. Hmmm, I'm not keen to add that. A NullPage has an ID of 0, and it shouldn't be possible to have a Page object that lacks an ID. Therefore when a PageArray is cast to a string it should never be possible to get something that looks like "|20896|20897" where there is clearly a missing ID for the first item. If your code is somehow producing a Page object that lacks an ID then I think that's a core issue that should be reported, because in general it ought to be safe to use a PageArray in a selector without needing to check for missing IDs. But for Ryan to fix I expect you'll need to create a reproducible test case.
  18. Thanks @MarkE, have applied the fix in v0.3.6.
  19. Just to add to this: the Move action is only removed if there is a "Children are sorted by" setting on the parent template or the parent page. Because even if there are no other allowed parents, the Move action is present to allow sorting within the existing parent so long as no fixed sorting is set.
  20. OMG, yes. That's one of the things I override in my custom mods as the default is crazy big. Off topic, but I really think AdminThemeUikit could be improved if some of the Uikit defaults were overridden in the module. Because the default sizing and white space is just too much for an admin panel where the focus should be on functionality and efficiency. And if a few basic things like that were done then users might not feel the need to make custom themes which from past experience I think are the wrong way to go (maintenance nightmare). I did turn them off, mainly because of the screen efficiency thing again. Ideally there would be some way to have them appear without increasing the overall size of the field (maybe on hover or some other way of activating them on demand), but I can see how that would be tricky. Maybe the core should provide for a flyout menu per inputfield that other modules could add links/icons to? Just thinking out loud.
  21. Fantastic, thanks! I think I'll use standalone mode because its more efficient in screen real estate and I always open Adminer in a new tab, but it's really nifty how you solved the query string issue for the iframe option.
  22. It looks like there is a clash with the Wappalyzer Chrome extension. When I log event.data it fires many times with results like this: Hopefully there's a way to allow it to coexist with Wappalyzer because I find it a useful extension. I forgot to mention before that I also see this notice: Thanks.
×
×
  • Create New...