Leaderboard
Popular Content
Showing content with the highest reputation on 12/11/2023 in all areas
-
This week I've continued work on the page versions support that I wrote about last week. While the main PagesVersions module needs more work before it's ready to commit to the dev branch and test externally, it is so far working quite well in internal testing. I mentioned last week how it will support an interface where Fieldtypes can declare that they will handle their own versions. That interface has been pushed to the dev branch as FieldtypeDoesVersions. I've also implemented it with the Repeater Fieldtype, which is visible starting here. Repeaters are so far working really well with versions! As far as core Fieldtypes go, Repeater, PageTable and FieldsetPage are likely the only ones that will need custom implementations. For ProFields, RepeaterMatrix already works with the implementation in the core Repeater (already tested). It's possible that other ProFields will not need custom implementations, though not yet positive. The module that provides version capability is called PagesVersions and the plan so far is to make it a core module that provides API version support for pages. A separate module provides interactive version support in the page editor. I've built this module initially so that I can test versions more easily, but it'll be expanded to provide a lot more. Below is a screenshot if what it looks like in the page editor Settings tab so far: As you can see, you can Edit or Restore any existing version. You can also create a new version from the Live version, or any other version. And of course you can view and delete any versions. When you Restore a version, it essentially replaces the live version with the one that you are restoring. All of this can be done from the module's API as well. Note that the API is provided by a $pagesVersions API variable that is present when PagesVersions module is installed. The API method names and such are a bit verbose right now but may be simplified before it's final. // Get page and add a new version of it $page = $pages->get(1234); $page->title = 'New title'; $version = $pagesVersions->addPageVersion($page); echo $version; // i.e. "2" // Get version 2 of a page $pageV2 = $pagesVersions->getPageVersion($page, 2); // Update a version of a page $pageV2->title = "Updated title"; $pagesVersions->savePageVersion($pageV2); // Restore version to live page $pagesVersions->restorePageVersion($pageV2); // Delete page version $pagesVersions->deletePageVersion($pageV2); Thanks for reading! More next week.3 points
-
@David Karich ProDrafts doesn't have versioning per se, it just maintains a draft version. So the version support will be something different, though the plan is that ProDrafts will be able to eventually use it for maintaining its draft versions. As for how the versioning works, it's very simple in that you have API methods to add, get, save, and delete versions of a page. That's the extent of it. While technically you could code a hook to make it save a new version on every page save, I don't think it would be practical, as a version is an entire copy of a page, including its files. Most likely one would use it to create a version intentionally, and perhaps work on it independently of the live version of the page. Or maybe they would use it to create a restorable snapshot or backup of a page's current state, before making some other changes. I think there are a lot of possibilities for how someone might use it, but for now I'm just focused on its API and making it all work reliably across different fieldtypes. @MrSnoozles A media manager is something I've not needed here, and I get off track and mess things up when I start developing stuff tools I don't have a use for in my own projects. Nearly everything that's in ProcessWire's core is stuff that I develop and maintain because I use it in my client work. When I need to share file or image assets across multiple pages I build a page or group of pages for the purpose, and that is ideal for my projects. A big part of the reason why PW as a framework is so modular and hookable is so that there is always the opportunity extend it in ways that are useful for your own projects. For example, @kongondo built what looks to be a really cool media manager for ProcessWire, though I don't have experience with it beyond reading about it and watching the videos. As for translations of the admin, PW's admin is already 100% translatable, so if you are seeing a mixture of English and another language, then that means that the language pack you have installed is missing translations. But that's something you'd need to ask the author of the language pack about. You can also always submit a pull request to the translation author's language pack, or create your own. PW makes this all very simple. Multisite is another example of a module that I just have not yet had a need surface for in my own work. Though I'm interested in it, so always looking for the opportunity. I'd have to come up with a case where I would use it and find it worthwhile. Otherwise I don't think I could do as a good job of a job as someone that is actively using it. I think the existing multi-site module(s) were built by someone (Soma, Apeisa?) that was using them in their projects. Worth mentioning too that PW will happily serve multi-site already, so long as you add all the hostnames to $config->httpHosts and use conditionals like if($config->httpHost === 'host.domain.com') to decide what content to serve. What I find useful in my work here is multi-instance, being able to boot other sites when and where needed, like we do on this site, where the modules directory actually comes from a separate ProcessWire installation, despite being delivered by the main site.2 points
-
@David KarichVery good points. I'm very excited for this feature too. IMO the things we and our clients have been missing the most in ProcessWire, apart from versioning, are (in that order): - global asset management / media manager with directories to reuse assets in various places. The lack of this is is often the sole reason we can not recommend ProcessWire for some projects - automatic backend translations using ProcessWire in any language other than English is suboptimal, because usually the backends will end up being half in <target language>, half in English - a proper multisite solution to handle multiple domains / channels in a single instance. The Multisite module is a good start, but having more isolated channels and sharing/isolation options for each channel would make this a much better fit2 points
-
what is the procedure now? should i write a bug report? i guess here https://github.com/processwire/processwire-issues/issues ? Thank you for your help ?1 point
-
but for a repeater field the page object is of class RepeaterPage. Using ->template returns 'repeater_....' which is not the name of the embedding page. The documentation of RepeaterPage describes a getForPage1 point
-
@ryan Good points. The slim core and the enormous flexibility is why so many love ProcessWire and trust you with your decisions. Still I want to comment on one point: I know it is simple, but the reality is that in client projects it often still ends up being a mix of <language> and English, because not all modules provide translations (the community seldom submits pull requests for languages) and there is no time to translate everything. I think that ProcessWire is lacking in this area has to do with you rarely needing it in another language but English. My idea how this could be improved would involve three relative simple steps: 1. Set up a community translation tool, like Weblate (https://weblate.org/), where people that want to contribute can easily see which translations are still missing. Weblate is really good feature-wise, but the interface for adding translations could be simpler, so another tool might fit better. 2. Write a crawler that goes through all the uploaded modules and core files, extract the translatable phrases and upload those packages to Weblate 3. Write a ProcessWire module that maps the languages defined in ProcessWire with country codes, then automatically downloads the matching translation files from Weblate whenever a module is added or updated In general: would that something you would consider useful? If so I could try implementing a POC when I find the time.1 point
-
Hey @ryan, I'm so excited about the feature. The two big things I think ProcessWire is missing are versioning and a lack of global asset management. ProDrafts was a good approach so far, but had limitations. Can you perhaps briefly explain how the versioning module works? ProDraft had the approach that everything I save is saved in a draft until I publish. Is this also the approach here, that every time I save a page a new version of the last state before saving is created or do I have to create a new version myself beforehand, in which I work, revise a draft and then "restore" it when I'm done as a form of "fake" publishing?1 point
-
You'll have to write some code for that @ShadowByte. This is my code for my blog tags (in Latte) which I'm sure you can adapt for your purposes (my blogs are in a repeater matix field here): {var $blogsPage = $page->motif_display_pageref} {var $blogs = $blogsPage->find("template=MotifDisplay, parent=$blogsPage")} {var $tags = []} {foreach $blogs as $blog} {foreach $blog->motif_layout_components as $component} {if $component->type == 'blog-post'} {var $blogTags = $component->motif_blog_tag->explode('title')} {* {bd($blogTags, 'blogtags')}*} {foreach $blogTags as $blogTag} {if !array_key_exists($blogTag, $tags)} {do $tags[$blogTag]['name'] = $blogTag} {do $tags[$blogTag]['count'] = 0} {/if} {do $tags[$blogTag]['count'] += 1} {/foreach} {/if} {/foreach} {/foreach} {* Sort the tags in descending order of frequency so that the most used are at the top *} {var $tagCount = []} {foreach $tags as $key => $tag } {do $tagCount[$key] = $tag['count']} {/foreach} {do array_multisort($tagCount, SORT_DESC, $tags)} {*<section>*} <ul n:foreach="$tags as $tagKey => $arr"> <li> <a href="{$blogsPage->url . 'tag/' . $tagKey}">{$tagKey}</a> </li> </ul> {*</section>*}1 point
-
Hi @Robin S, Thank you very much for your modules! With this I managed to create a simple conditional visual page selector. For anyone interested: $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { /** @var Page $page */ $page = $event->arguments(0); /** @var Field $field */ $field = $event->arguments(1); if($field->name === 'artworks') { $artists = $page->artists; // Page-reference field $inputfield = modules("InputfieldImage"); $options = []; foreach($artists as $artist) { foreach($artist->children() as $artwork) { if(!$artwork->gallery->count()) continue; $thumb = $inputfield->getAdminThumb($artwork->gallery->first()); $options[$artwork->id] = [ "label" => "$artwork->title, $artwork->year", "attributes" => [ "data-thumb" => $thumb["thumb"]->url ] ]; } } $event->return = $options; } }); + with the added bonus of being able to customize labels it works great. A question and a suggestion: Based on some condition (eg: if no artist is selected), it'd be nice to be able to display a specific message other than the "Unavailable" label using the hook (for the Dynamic Options module in general) A teeny-tiny css edit: put the clear button at top: 0 and left: 0, and add a padding: 6px to the label <div>1 point