Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/07/2021 in all areas

  1. This module lets you add some custom menu items to the main admin menu, and you can set the dropdown links dynamically in a hook if needed. Sidenote: the module config uses some repeatable/sortable rows for the child link settings, similar to the ProFields Table interface. The data gets saved as JSON in a hidden textarea field. Might be interesting to other module developers? Custom Admin Menus Adds up to three custom menu items with optional dropdowns to the main admin menu. The menu items can link to admin pages, front-end pages, or pages on external websites. The links can be set to open in a new browser tab, and child links in the dropdown can be given an icon. Requires ProcessWire v3.0.178 or newer and AdminThemeUikit. Screenshots Example of menu items Module config for the menus Link list shown when parent menu item is not given a URL Advanced Setting child menu items dynamically If needed you can set the child menu items dynamically using a hook. Example: $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); if($menu_number === 1) { $colours = $event->wire()->pages->findRaw('template=colour', ['title', 'url', 'page_icon']); $children = []; foreach($colours as $colour) { // Each child item should be an array with the following keys $children[] = [ 'icon' => $colour['page_icon'], 'label' => $colour['title'], 'url' => $colour['url'], 'newtab' => false, ]; } $event->return = $children; } }); Create multiple levels of flyout menus It's also possible to create multiple levels of flyout submenus using a hook. For each level a submenu can be defined in a "children" item. Example: $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); if($menu_number === 1) { $children = [ [ 'icon' => 'adjust', 'label' => 'One', 'url' => '/one/', 'newtab' => false, ], [ 'icon' => 'anchor', 'label' => 'Two', 'url' => '/two/', 'newtab' => false, 'children' => [ [ 'icon' => 'child', 'label' => 'Red', 'url' => '/red/', 'newtab' => false, ], [ 'icon' => 'bullhorn', 'label' => 'Green', 'url' => '/green/', 'newtab' => false, 'children' => [ [ 'icon' => 'wifi', 'label' => 'Small', 'url' => '/small/', 'newtab' => true, ], [ 'icon' => 'codepen', 'label' => 'Medium', 'url' => '/medium/', 'newtab' => false, ], [ 'icon' => 'cogs', 'label' => 'Large', 'url' => '/large/', 'newtab' => false, ], ] ], [ 'icon' => 'futbol-o', 'label' => 'Blue', 'url' => '/blue/', 'newtab' => true, ], ] ], [ 'icon' => 'hand-o-left', 'label' => 'Three', 'url' => '/three/', 'newtab' => false, ], ]; $event->return = $children; } }); Showing/hiding menus according to user role You can determine which menu items can be seen by a role by checking the user's role in the hook. For example, if a user has or lacks a role you could include different child menu items in the hook return value. Or if you want to conditionally hide a custom menu altogether you can set the return value to false. Example: $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); $user = $event->wire()->user; // For custom menu number 1... if($menu_number === 1) { // ...if user does not have some particular role... if(!$user->hasRole('foo')) { // ...do not show the menu $event->return = false; } } }); https://github.com/Toutouwai/CustomAdminMenus https://processwire.com/modules/custom-admin-menus/
    9 points
  2. Output formatting is off when in ajax mode...
    2 points
  3. I've found something similar in a few cases. Doing a Modules > Refresh is supposed to both clear the module info cache and the admin menu cache (AdminThemeUikit hooks Modules::refresh) but sometimes it doesn't work and you have to either logout/login or (easier) use the Tracy Debugger "Clear Session & Cookies" link in the "ProcessWire Info" panel. The whole cached admin menu thing seems a bit pointless to me, so if you want to effectively disable that you can put the following in /site/ready.php // Prevent admin menu from being cached $wire->addHookBefore('ProcessController::execute', function(HookEvent $event) { $event->wire()->session->removeFor('AdminThemeUikit', 'prnav'); }); But you'll still need to do a Modules > Refresh if you make changes to the "nav" item in a Process module's getModuleInfo method. Have a look at ProcessModule and I think you'll be able to work it out. Within getModuleInfo see "useNavJSON" and the "navJSON" items within the "nav" array, and the executeNavJSON method. You probably can't. Probably best to make a corresponding executeSomething() method in your Process module that simply lists the child links. Yeah, unfortunately you can't because AdminThemeFramework forces the Process page URL before the link for items in the "nav" array. It seems this array is really only intended to be used for executeSomething() methods within the Process module and not for general purpose links. Recently I've been playing around with an alternative approach to custom admin menus which involves hooking AdminThemeFramework::getPrimaryNavArray (only possible in PW 3.0.178 or newer). If you use Tracy to dump the event return you can work out how the menus can be manipulated. And I've put together a module that lets you add custom admin menus without writing code - will release soon.
    2 points
  4. @MarkE That I think may be defeating the purpose of making it load on-demand. What I intended to suggest is to add that adminSite() function, and then replace any of your calls with setting('admin_site') with adminSite(). For example, rather than calling setting('admin_site')->pages->get('...'); you'd call adminSite()->pages->get('...'); and it should do the same thing. The main difference is that your admin site doesn't get booted until the first time the adminSite() function is called. That's desirable because it prevents you from booting it when you aren't going to access it, saving overhead. A function can only be defined once, so it doesn't matter where you call adminSite(); from whether site-admin or site-web. Great! Glad that it seems to be working now. As for why the *= wasn't working, I think we'd need to look at what is in $host in order to tell. It would also be good to know the full context of that bodyFoot*=$host, for instance is that selector being sent to a $pages API call, or to something else? The biggest difference between *= and %= is that *= matches from the beginning of a word boundary whereas %= matches anywhere in the string. So if you've got an instance where %= is matching and *= isn't, then most likely it's because of that difference. If its querying the database, then *= is also subject to stopwords and minimum indexable word length (typically 4) whereas %= is not. @AndZyk Interesting, I'll have to try that out. Are you using the latest German language pack released by @dotnetic or a different/earlier one? I think the capitalization issue might not be specifically with InputfieldTextTags but with its usage in ProcessField/ProcessTemplate. I don't think there's a reason to avoid using it elsewhere. @kongondo The InputfieldPage had to be added because often InputfieldTextTags is used in combination with InputfieldPage. The jQuery selector ".InputfieldTextTags, .InputfieldPage" seems to be valid. Does the error trigger on that line in particular, or does it occur sometime later? Do you find there is any difference if you set $config->debug = 'dev'; ? That will make it use a newer jQueryCore version. That was throwing up the JavaScript error I posted above. My remedy was to let ProcessWire Inputfields trigger the reload, like this: Glad that seems to have fixed it. If this works, and triggering 'reload' manually didn't work, it means that $myInputfieldTextTagsSelectItem is not an .Inputfield element. The 'reload' event is is specific to .Inputfield elements, so the Inputfields.reload() method will attempt to locate the and trigger the .Inputfield element if given something other than an .Inputfield. I think that must be why it is working when the manually triggered one wasn't?
    1 point
  5. That's correct, currently PrivacyWire loads itself in the module ready() method. I played around with some settings to load PrivacyWire later. You can find the feature in this branch: https://github.com/webworkerJoshua/privacywire/tree/feature-initiate-privacywire-laster In this version PrivacyWire initiates itself before Page::render: $this->addHookBefore('Page::render', $this, 'initiatePrivacyWire'); Could you try this version and confirm, that it's working the way you wanted / expected? After that I will do some more testing before merging into the main branch just to be sure that there are no side effects ? Thanks!
    1 point
  6. Hi @Stefanowitsch, Thanks. I'll leave the implementation as it is at the moment, if there are further reports of the issue I'll investigate further. Cheers, Chris
    1 point
  7. Hi @elabx, Apologies it has taken a while to get back to you. From what I've been able to determine, the browser selects the first <source> in the list in the absence of media queries. In this case the webP version would always be selected as it comes first. I've added a couple of things that can help with the issue. The first is the ability to disable the render() extensions, falling back to the default Pageimage:render() method. This is done by passing $options as false. Here's an example, where if the webP image url isn't actually webP due to it being larger it uses the default render(). <?php echo $pageimages->each(function($pageimage) { return strpos($pageimage->webp()->url, '.webp') === false ? // If the webP url is not webp $pageimage->render(false) : // Disables the PageimageSource::render() extensions $pageimage->render(); }) The second is a similar option to the $config->webpOptions option 'useSrcUrlOnSize'. If this is enabled, the module checks to see if the webP url is actually webP (as in the example above) and if it is not (e.g. if it is a .jpg), then it disables webP for that image, which in turn disables the picture option: <?php echo $pageimage->render([ 'useSrcUrlOnSize' => true, ]); This takes the module to v 1.0.2, still in beta. Cheers, Chris
    1 point
  8. @DrQuincy I think you're looking for this https://processwire.com/api/ref/wire-http/status-text/
    1 point
  9. Nice, thank you Robin. Seems to work well.
    1 point
  10. Agreed. Biggest benefits you get from using an external mail service are a) ease of use — which is largely a non-issue for ProcessWire users, since WireMail modules provide a consistent API — and b) confidence that someone else is making sure that your emails are sent, can be received correctly, and don't miss their target or end up in spam. With hosting your own SMTP server there are always potential gotchas, but again if you're on top of things they can be (mostly) avoided. When I say "mostly", I mean things like someone reporting your message as spam, which could become an issue for you. Not much you can do about that, really, except for making sure that your recipient list is full of folks who really want to receive your newsletter ? In addition to what Horst mentioned above, I would recommend using a service such as https://www.mail-tester.com/ to make sure that your messages are a-OK before sending them to actual recipients. Edit: one ProMailer-specific benefit for using external service is that this way you can easily handle bounces and spam complaints etc. ProMailer supports webhooks for this stuff. You can set up a webhook for these without external service as well (at least for bounces, not entirely sure about spam complaints), but it could get tricky ?
    1 point
  11. If anyone else is interested, I started researching different ways to try to solve this problem(not just with Processwire.) You can view the Google doc here. Feel free to copy/edit or whatever. I wonder if we can simplify things? Do we really want a layout editor in the Processwire backend where you can adjust the grid widths and so on, or do we just need some UI modifications to the tools we already have? Here's an example where I think the backend page editor is too complex. from:https://getkirby.com/ and https://modmore.com/contentblocks/ The page editor could slow down and be clunky from trying to render all the DOM elements? Too complex to work on mobile Content editing gets smushed into small columns Dragging and dropping across layout regions requires a lot of dexterity for the end users - think accessibility. requires taking up the whole page for editing A page/layout editor will have to somehow visually represent your frontend layout in the backend. That seems problematic to me. Instead of having a complex page/layout editor where the user has to drag and drop columns, how about we simplify the interface so that it works on mobile as well? While the YooTheme demo looks cool, I don't think it would work good on mobile? I think the YooTheme UI is still too complex. How about we just allow the user to choose from prebuilt sections or components? Those prebuilt sections/components could then be edited in the Processwire sidebar panel like the Processwire ProDrafts sidebar editing. It would be cool if the RepeaterMatrix, Page Reference, Page Table, Repeater fields got rid of all the cluttered "Add New" type links and instead had one "Add new" button/link that would give the option to choose a template visually in a Processwire Sidebar Panel. Maybe also add another option to RepeaterMatrix, Page Reference, Page Table, Repeater fields to edit pages in the Processwire Sidebar Panel instead of the inline expand/dropdown editing? Just like the Processwire ProDrafts module does with Live Preview? This is how Godaddy.com's website builder works. You can try it for free. When you click the plus icon to add a new section, it shows this selector in the sidebar. This is also how https://froont.com/ sidebar works. A user selects a prebuilt section or component/widget. Also http://cards2.webflow.io/ and https://froala.com/design-blocks and https://www.brizy.io/brizy-design-kit-2/ you can see how a page is built from these widgets/components that stack on top of each other. Imagine if I were to create a Processwire "Landing Page" template. It would probably only have 3 fields: Page Header - Single Select - to override the default site header Page Sections - Allow Multi Select - to add layout rows Page Footer - Single Select - to override the default site footer That would give a lot flexibility of the page design without allowing a user to screw up the design. When looking at the processwire page editor, it could show the three fields each containing a preview graphic of the element that was selected. Maybe @bernhard 's module would allow the visual selection of the templates somehow or maybe @ryan could add a representative/template preview image option to all the templates? The Sections field would allow multiple selections. Those selections would display in a single column like the Page Table field that allows you to move the preview graphic of the element that was selected up or down in the list. Maybe Page Table Extended could be used to show that preview graphic from the TemplatePreviewImages module? I haven't tried. If you click the preview graphic, it will open that element in the Processwire Sidebar Panel for editing. Here is a rough mockup of what it could look like: That way the page editing is nice and simple, no need to worry about messing with the indentation of nested elements like in this example: Indentation is too easy for editors to mess up IMHO. Now what happens if you click on the "Three Column" item above? It would open for editing in Processwire Sidebar Panel on the right. Now that "Three Column" page has other Page Reference fields to components/widgets: Column 1 - contains a RTE Editor widget using a limited/restricted CKeditor or a markdown editor? Column 2 - contains an Art Directed Responsive Image widget Column 3 - contains a Accordion widget with other types of referenced widgets like a Editorjs.io widget or a file downloads listing widget So that is where I'm not clear on. Do we need some mechanism to allow us to "Drill down" to edit other referenced pages in the sidebar? How do we go deeper? Could there be some kind of breadcrumbs or back button like on an iphone? The SilverStripe CMS has drill down editing as seen in this video at the https://youtu.be/IKGUd2dq8XI?t=1022 although it doesn't use sidebar editing. Technically, I'm not sure how they achieve that? Anyways, I don't have the solution, but I thought I would share those concepts as rough as they are. ? I also like Bernhard's concept of defining these widget/components in code so they can be shared across sites. Creating all these fields and templates by clicking in the admin would not be fun. No disrespect to Processwire. (I love Processwire and it's admin theme btw) I love hearing all the discussion on this. It's one huge problem that definitely needs solving. I need to able to give non technical users the ability to create customized landing pages without them knowing html. They like to be able to switch out a whole section just to see what it would look like. That's why I would prefer to give them the ability to select prebuilt responsive components instead of allowing them the ability to create grids with rows with margins and paddings and so much other htmly stuff.
    1 point
  12. My approach from today: $wire->addHookProperty("Page::myFooLabel", function($event) { $page = $event->object; if($page->template != 'foo-page') return; $event->return = $page->title . " (foo label)"; } Then just set the label field to "myFooLabel" and enjoy. This also has the benefit of having the dynamic label always available easily via $page->myFooLabel
    1 point
×
×
  • Create New...