Leaderboard
Popular Content
Showing content with the highest reputation on 08/18/2022 in all areas
-
I just had this problem as well, using a path hook like this: wire()->addHook('/my/path', function($event) { /*β¦*/ }); In conjunction with a form like this: <form method="POST" action="/my/path/"> ProcessWire redirects the version with the trailing slash to the path matching the hook. I presume the same thing happens with normal pages and url segments as well, depending on the template settings. So if your redirect goes from /action_page to /action_page/ or vice versa, just request the exact url directly.2 points
-
Modules Directory: https://processwire.com/modules/rock-frontend Github: https://github.com/baumrock/RockFrontend1 point
-
I came to this thread by coincidence: It was very popular back then. But I've never heard of anybody using dynamic roles over the last few years. Is anybody using it and want to share the "why" and "how"? ?1 point
-
Just a quick note, if you're on Linux & Code-OSS and have trouble opening your ALFRED / Tracy links to directly edit template code (around 34:00 in the video), you need to create a separate URL handler for vscode:// type links in ~/.local/share/applications create a file code-oss-vscode-url-handler.desktop #!/usr/bin/env xdg-open [Desktop Entry] Name=Code - OSS - VSCode URL Handler Comment=Handles opening of vscode:// URLs in Code-OSS GenericName=Text Editor Exec=/usr/bin/code-oss --open-url %U Icon=code-oss Type=Application NoDisplay=true StartupNotify=true StartupWMClass=Code - OSS Categories=Utility;TextEditor;Development;IDE; MimeType=x-scheme-handler/vscode Keywords=vscode; Terminal=false Borrowed from here: https://github.com/Microsoft/vscode/issues/48528#issuecomment-414056547 And Alfred is your new best pal ?1 point
-
No, sorry. Sometimes I have network problems as well (not related to livereload though) but restarting ddev/docker/my laptop has always helped ? Glad to hear that ?1 point
-
I think if all blog posts need the same fields, Berhard's solution is better. So you have to set the fields only once. But of course your solution works too ?1 point
-
@Jan Romero, You're super cool! That extra slash in form action value resolves the problem. Thanks a lot!1 point
-
I've improved the render method even further, so as from version 1.15.7 you don't need to add the |noescape filter any more when rendering a file via the render() method ? Also I've added support for a shorthand variable submission that is very handy for rendering lists (like blog post overview or such): <div class="uk-child-width-1-2@m" uk-grid> <div n:foreach="$page->children as $item"> {$rockfrontend->render("partials/card", $item)} </div> </div> That makes $item available as $page in card.latte ?1 point
-
In case you want a copy paste version to use RockFrontend with RepeaterMatrix from within a .latte file: {* templateExample.latte *} {foreach $page->repeaterMatrixField as $block} {$rockfrontend->render("fields/repeaterMatrixField/" . $block->type , ["block" => $block])|noescape} {/foreach} {* blockExample.latte *} <div> <h1>{$block->headline}</h1> {$block->body} <img src="{$block->image->url}" alt="{$block->image->description}"> </div>1 point
-
Hey @Boost it sounds like you have done a lot of research but never installed PW for testing? If so than just do it as this might help in understanding everything better ? ProcessWire has the concept of Pages, Templates and Fields. Note that the term "template" is very different to other systems like wordpress, where a template is an installable design. In PW the template defines the fields that the user can use for storing content. So when creating a new Page, you can select different Templates which means that on the next step the user can populate the fields that belong to the selected template. For example a boat template could have fields "title (name)", "year", "length", "cost" and the template blogpost could have fields "title", "body", "images" The visual representation of the template is done via template files that are stored in /site/templates. So the "boat" template would render the template file "/site/templates/boat.php". So far to the technical background. I guess that your question is not "can I choose different templates when writing a page" but rather "can I choose different layouts when writing a page"? So your client would create a new blog post having template "blogpost" for example. But then he/she can choose between layout1/2/3. You could do that by simply adding an options field holding all the possible options and then in your template file (/site/templates/blogpost.php) you do something like this: <?php include __DIR__."/layouts/" . $page->layout . ".php"; Which would make it render /site/templates/layouts/layout1.php for the selected option "layout1" of your blogpost...1 point
-
As usual, everything you touch transforms into gold.1 point
-
Thx to another request by @wbmnfktr and issues that I had on my own project I've improved asset handling, autoloading and debugging in v1.13.8 It also adds a new method to prepend() scripts and styles (like uikit.theme.less in the example below). Adding something like addAfter('mystyle.css', 'theme.css') is on my list... A default <head> can now look like this (note all the html comments that should be quite helpful): <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- RockFrontend SEO by baumrock.com --> <title>Home</title> <meta property="og:title" content="Home"> <meta name="description" content="Home"> <meta property="og:description" content="Home"> <meta property="og:image" content=""> <meta property="og:image:type" content=""> <meta property="og:image:width" content=""> <meta property="og:image:height" content=""> <meta property="og:image:alt" content="Home"> <script>let rf_livereload_secret = 'rDksCMGEMFs87mNq3WrTaVug1tfeldQ0r9L4kUkfqghS'</script> <!-- DEBUG enabled! You can disable it either via $config or use $rf->styles()->setOptions(['debug'=>false]) --> <!-- autoloading of default scripts/styles enabled - disable using ->setOptions(['autoload'=>false]) --> <!--rockfrontend-styles-head--> <!-- loading /var/www/html/site/templates/uikit-3.15.2/src/less/uikit.theme.less --> <!-- loading /var/www/html/site/templates/layouts/_global.less --> <!-- loading /var/www/html/site/templates/sections/footer.less --> <!-- loading /var/www/html/site/templates/sections/hero.less --> <!-- loading /var/www/html/site/templates/sections/job-footer.less --> <!-- loading /var/www/html/site/templates/sections/menu.less --> <!-- loading /var/www/html/site/templates/sections/rocket.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/FactsBar.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconBox.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/IconRow.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/PagesGrid.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/QuoteSlider.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Spacer.less --> <!-- loading /var/www/html/site/assets/RockMatrix/matrix/Team.less --> <link rel='stylesheet' href='/site/templates/bundle/head.css?m=1660204105'> <link href='/site/modules/RockFrontend/Alfred.css?m=1660124218' rel='stylesheet'> <link href='https://use.typekit.net/zeg8qpc.css' rel='stylesheet'> <link href='/site/templates/sections/foo.css?m=1660207177' rel='stylesheet'> <!--rockfrontend-scripts-head--> <script src='/site/modules/RockFrontend/Alfred.js?m=1660123300'></script> <script src='/site/modules/RockFrontend/livereload.js?m=1660123300'></script> <script src='/site/templates/uikit-3.15.2/dist/js/uikit.min.js?m=1659941286' defer></script> <script src='/site/templates/uikit-3.15.2/dist/js/uikit-icons.min.js?m=1659941286' defer></script> <script src='/site/modules/RockFrontend/lib/alpine.min.js?m=1660123300' defer></script> <script src='/site/modules/RockFrontend/RockFrontend.js?m=1660203134' defer></script> </head> ? v1.13.10 makes sure that LESS is forced to recompile on modules::refresh1 point
-
v1.13.5 adds notes about installed profiles thx to issue report from @wbmnfktr1 point
-
Wow! In general I think it's a huge benefit for the community to have a more opinionated way of doing frontend, so congrats on this is amazing module! I have no further comments until I try it fully but from what I see in the video it looks fantastic.1 point
-
Hey @MrSnoozles thx for the input!! ? Puh... I'm not sure ? I agree with you that it's nice to understand code without having to look anything up. On the other hand I'm not sure what would be a better naming? In code and in the docs it is a huge benefit to just refer to it as ALFRED because it's short and crystal clear what is meant. In code for someone not knowing alfred that's surely not the case, but it would be just as simple to look it up and quickly find and understand what it is doing. Don't you think? I could easily add an alias though. But I'm not sure if that is a good idea because it could cause name collisions with the core frontend editing?! What would be a good name in your opinion? What do others think about that? I was looking for that statement as I think it was really a good hint! Thought I have been dreaming ? I have played around with my code a little and think that that we could really simplify alfred syntax even further! // edit current page <div alfred> // edit given page+fields (latte) <div alfred="{$page}:title,gallery"> // php <div alfred="<?= $page ?>:title,gallery"> That could work using the page::render hook for replacing the tags, so one wouldn't even have to think of using the |noescape filter any more!! Thx! I have removed that part from the video as it already got so long... See this post that is using the old (alternative) syntax: https://processwire.com/talk/topic/27187-domid-labs-β microsite-for-a-museum-related-project/?do=findComment&comment=224750 This approach has major drawbacks IMHO: You need to add the scripts and styles tag manually to your markup, which is not what I call "zero-setup". I've had it working like this before I did the video, but then I realised that there's actually some steps to do to get everything working as it should. So I came up with the hook-based approach. And I really like that approach even if that means that it hides some parts away, which is a valid point... When injecting scripts or styles from your sections (or components, or modules) you need to make sure that those scripts are loaded BEFORE the scripts are rendered in the head. That's similar to the delayed output pattern of processwire. The markup would look like this: <?php // render layout first, so any of your sections can inject scripts or styles $body = $rockfrontend->renderLayout($page); ?> <html> <head> <?= $rockfrontend->styles()->add(...)->render() ?> <?= $rockfrontend->scripts()->add(...)->render() ?> </head> <body> <?= $body ?> </body> </html> The thing is that I really want ALFRED and livereloading work out of the box. Zero-Setup. If you want to use the alternate syntax you can do so. RockFrontend is smart enough to see that you are rendering scripts/styles manually and will not inject them twice ? What do you think?1 point
-
Find Merge Adds a Pages::findMerge() method that allows multiple PageFinder selectors to be merged into an efficient paginated set of results. This can be useful when you need more sophisticated sorting of results than what would be possible using only the sort value in a single $pages->find(). Details $results = $pages->findMerge($selectors, $options); $selectors is required and must be an array of selectors. Each selector can be in string format or array format. The findMerge() method will loop over the selectors in the order supplied, adding matching pages to the final results. $options is an optional associative array of options. limit (int) Limit for pagination. start (int) Manually override the start value rather than have it be automatically calculated from the current page number. excludeExisting (bool) Whether or not to exclude pages in each selector that have already been matched by a previous selector. Default is true. keepFirst (bool) When excludeExisting is false then a page might match more than one selector in the supplied array. But each page can only appear once in the results and if keepFirst is true then the page will appear in its earliest position in the results, whereas if keepFirst is false it will appear in its latest position in the results. Default is true. As a shortcut you can supply an integer as the second argument and it will be treated as the limit for pagination. Basic usage For most use cases only a limit will be needed for the $options argument. $selectors = [ 'title%=yellow', // title contains "yellow" 'title^=z', // title starts with "z" 'title=elephant', // title equals "elephant" 'template=colour, sort=-title, limit=3', // 3 colours in reverse alphabetical order 'template=country, sort=title, limit=40', // 40 countries in alphabetical order ]; $results = $pages->findMerge($selectors, 10); if($results->count) { echo "<p>Showing results {$results->getPaginationString()}</p>"; echo "<ul>"; foreach($results as $result) { echo "<li><a href='$result->url'>$result->title</a></li>"; } echo "</ul>"; echo $results->renderPager(); } Advanced usage The following notes are only relevant to rare cases and most users can safely skip this section. In the demo example the colour page Yellow will potentially match both the 1st selector and the 4th selector. Because of this the excludeExisting and keepFirst options will have an effect on the results. excludeExisting option false Note that the 4th selector asks for 3 colour pages (limit=3). By default excludeExisting is true, which means that when the 4th selector is processed it is interpreted as saying "find 3 colour pages in reverse alphabetical order that have not already been matched in an earlier selector". We can see that there are 3 pages in the results from that selector: Violet, Red, Orange. But if excludeExisting is set to false then the results are different. The matches of the 1st selector (Yellow, Yellow Warbler) are not excluded from consideration by the 4th selector (the 4th selector matches will be Yellow, Violet, Red), and because each page can only appear once in the results this means that the 4th selector ends up only adding 2 more pages to the results. $selectors = [ 'title%=yellow', // title contains "yellow" 'title^=z', // title starts with "z" 'title=elephant', // title equals "elephant" 'template=colour, sort=-title, limit=3', // 3 colours in reverse alphabetical order 'template=country, sort=title, limit=40', // 40 countries in alphabetical order ]; $options = [ 'limit' => 10, 'excludeExisting' => false, ]; $results = $pages->findMerge($selectors, $options); keepFirst option false As described above, the Yellow page potentially matches both the 1st and 4th selector. By default Yellow will appear in its earliest position within the results, i.e. the position resulting from it being matched by the 1st selector. But if keepFirst is set to false (and excludeExisting is false) then it will appear in its latest position within the results, i.e. the position resulting from it being matched by the 4th selector. $selectors = [ 'title%=yellow', // title contains "yellow" 'title^=z', // title starts with "z" 'title=elephant', // title equals "elephant" 'template=colour, sort=-title, limit=3', // 3 colours in reverse alphabetical order 'template=country, sort=title, limit=40', // 40 countries in alphabetical order ]; $options = [ 'limit' => 10, 'excludeExisting' => false, 'keepFirst' => false, ]; $results = $pages->findMerge($selectors, $options); keepFirst has no effect when excludeExisting is true. https://github.com/Toutouwai/FindMerge https://processwire.com/modules/find-merge/1 point
-
I think I don't understand your question.. I don't have any functions in init.php nowadays. I have everything in init() of a module or in init() of a pageclass. If there is something in init() of a pageclass I have to trigger that manually, which is the reason for the loadClasses method of RM which triggers init() automatically https://github.com/BernhardBaumrock/RockMigrations/blob/2d85e460ce5aa394480906ad5b41cd1a0e86d0fe/RockMigrations.module.php#L1991-L2003 This is a simple pageClass I'm using in my CRM for managing contacts: <?php namespace RockCRM; use ProcessWire\HookEvent; use ProcessWire\Page; class Contact extends Page { const tags = RockCRM::tags; const tpl = RockCRM::prefix."contact"; const prefix = RockCRM::prefix."contact_"; const field_skills = self::prefix."skills"; public function __construct() { parent::__construct(); $this->parent = $this->wire->rockcrm->contacts(); $this->template = $this->wire->templates->get(self::tpl); } public function init() { $tpl = "template=".self::tpl; $this->wire->addHookAfter("ProcessPageEdit::buildForm", $this, "buildForm"); $this->wire->addHookAfter("Pages::saveReady($tpl,id=0)", $this, "onCreate"); } /** * Page edit screen */ public function buildForm(HookEvent $event) { $form = $event->return; $page = $event->process->getPage(); if(!$page instanceof self) return; $crm = $this->wire->rockcrm; /** @var RockCRM $crm */ $rm = $crm->rm(); // modify page edit screen of a contact if($f = $form->get('title')) { $f->label = 'Name of the Contact'; $f->notes = 'Enter a great Name'; } // or load scripts with the new update $rm->addScript(__DIR__."/Contact.js"); } /** * Migrate this pageclass */ public function migrate() { $crm = $this->wire->rockcrm; /** @var RockCRM $crm */ $rm = $crm->rm(); $rm->migrate([ 'fields' => [ self::field_skills => [ 'type' => 'text', 'tags' => self::tags, ], ], 'templates' => [ self::tpl => [ 'tags' => self::tags, 'icon' => 'user-o', 'noSettings' => 1, 'pageClass' => '\RockCRM\Contact', 'fields' => [ 'title', self::field_skills, ], ], ], ]); } /** * Things to do when a contact is created * @return void */ public function onCreate(HookEvent $event) { $page = $event->arguments(0); $page->status = 1; // published, non-temp $event->pages->names()->uniqueRandomPageName(); // unique name } } This setup is extremely powerful, extremely clear and extremely nice to work with ? Was that what you were asking for? ?1 point