Leaderboard
Popular Content
Showing content with the highest reputation on 01/18/2025 in all areas
-
Just a quick note to say that the new version blog post is coming tomorrow rather than today. Here in Atlanta, tomorrow it is supposed to rain, while today the weather is perfect. So I spent the day outside and am moving my work day to tomorrow instead.17 points
-
ProcessWire 3.0.244 is our newest main/master/stable version. It’s been more than a year in the making and is packed with tons of new features, issue fixes, optimizations and more. This post covers all the details— https://processwire.com/blog/posts/pw-3.0.244/14 points
-
A nice weekend to everyone! It’s bin a while since I posted a decent showcase of one of my projects but I’ve been rather busy with other things (as ProcessWire development is not my main job). I’ve noticed that the showcases that are posted here are featuring sites that are really stunning. The ProcessWire community is producing better and better results as it seems. Really hard for me to catch up 🙂 Anyway I want to share a really interesting project: The Relaunch of the community portal for the district “Barmbek Nord” of the city of Hamburg, germany. This showcase is quite large because of all the technical concept description and markup details. If you want a quick look how the editing of the page looks like I included a video demonstration right here: Bildschirmaufnahme 2025-01-18 um 14.22.27.mp4 To keep it brief here is what this community portal is all about: The website Barmbek-Nord.info is a community portal for the Barmbek-Nord neighborhood in Hamburg, Germany. It features local events, cultural activities, initiatives, and resources, such as volunteer opportunities, social projects, and a calendar of events. It also highlights neighborhood news, collaboration opportunities, and community meetings to enhance the area's quality of life. This project was a collaboration of three parties: 1. the district council (providing the future page structure, contents and design ideas) 2. a web designer (https://www.andre-kraemer.de/) 3. me as the developer (https://www.thumann-media.de/) 1. Redesign Concepts Here is a picture of the old website (based on Word Press). This of course was a bit outdated (design wise) at the end of its lifecycle. The district Barmbek-Nord presents itself as a vibrant, exciting and diverse part of Hamburg and this version of the website was not representative at all. Luckily the district council hat a pretty clear vision of what the new version should look like. Basically it was all about “boxes and shapes”. So this was the final design concept hat I took as a blueprint for developing the page: 2. Layout anatomy If you are living in Germany you know the famous chocolate brand “Ritter Sport”. They have an even more famous slogan it’s called “Quadratisch. Praktisch. Gut.” which would translate to “Square. Practical. Good.” So you can describe the whole design concept with these three words 😉 There are two main page templates: Tile Page A Tile Page is divided into multiple grid boxes. There are 8 different grid box layouts available which can be placed in any order. Each grid box is horizontal and has the same dimensions but is divided into subboxes. Subox dimensions vary: There are squares, and rectangles in different alignments and in different amounts. Each of those “sub boxes” inside the grid can hold a specific design element. These design Elements include for example - Plain Images - Textfields - Speech Bubbles - Image and Text combined - and so on Everything is handled with the RockPageBuilder (more about that in the next points) Content Page As the name suggests, a Content Page is used for text-heavy pages. This page template does not feature any box grid layouts. Instead the page structure is predefined: 1. Header area with headline and image fields 2. Content area 3. Content area with specific content blocks that can be chosen using the RockPageBuilder. 3. Technical difficulties The four main challenges when developing the page were: 1. Creating Pages based on multiple stacked grid box layouts 2. Offer individual content elements for each of the grid boxes subboxes 3. The Boxes all have a fixed aspect ratio and should retain it on desktop and mobile devices 4. Make everything user friendly to edit (!) I made a small proof of concept using the RockPageBuilder and it worked out of the box! Let me explain: Here is what the 8 different grid box layouts look like: 4. Technical solutions How do you handle nested content blocks in the RockPageBuilder? Well this is no problem at all and actually quite straight forward. Step 1: Create a RPB Field for the main grid layout blocks and add it to your template Step 2: Create a new Block Type for each of the individual grid box layouts for this field: Now you can add multiple grid layouts to your page templates. But not without some markup of course. The markup of a grid box looks like this: <?php namespace ProcessWire; use RockPageBuilderBlock\LayoutA; /** @var Page $page */ /** @var LayoutA $block */ ?> <section class="rpb-layouta" <?= alfred($block,["trash" => false, "clone" => false, "widgetable" => false])?>> <div id="div1" class="col-2x1"><?= $block->rpb_cell_2_1_a->render(true); ?></div> <div id="div2" class="col-1x1"><?= $block->rpb_cell_1_1_a->render(true); ?></div> <div id="div3" class="col-1x1"><?= $block->rpb_cell_1_1_b->render(true); ?></div> <div id="div4" class="col-2x2"><?= $block->rpb_cell_2_2_a->render(true); ?></div> </section> As you can see you have to create individual RockPageBuilder fields for each sub box and and include them into the markup! Based on the design concept we have four different sub box aspect ratios (width/height) 1x1, 1x2, 2x1, 2x2 There can be two sub boxes with the same aspect ratio in one grid layout, so it was necessary to create two variants (named with the suffix “a” and “b”) of the same RPB field. The CSS for a layout box looks like this. I make massive use of the “grid layout” feature as this offers me an relative easy way to control the layout as well as keeping the aspect ratio. .rpb-layouta { min-height: 50px; display: grid; grid-template-rows: repeat(2, 1fr); grid-template-columns: repeat(4, 25%); gap: 0; #div1 { grid-area: ~"1 / 1 / 2 / 3"; } #div2 { grid-area: ~"2 / 1 / 3 / 2"; } #div3 { grid-area: ~"2 / 2 / 3 / 3"; } #div4 { grid-area: ~"1 / 3 / 3 / 5"; } @media @max-m { grid-template-rows: repeat(4, 1fr); grid-template-columns: repeat(2, 50%); #div1 { grid-area: ~"1 / 1 / 2 / 3"; } #div2 { grid-area: ~"2 / 1 / 3 / 2"; } #div3 { grid-area: ~"2 / 2 / 3 / 3"; } #div4 { grid-area: ~"3 / 1 / 5 / 3"; } } } Step 3: Creating sub box content blocks for the nested RPB fields Now this was the main part of the work. Based on the design concept I had to create individual content elements for the sub boxes (all RockPageBuilder Blocks). All together with markup, styles and configuration options (!) As I mentioned before these content elements consist of: - Plain Images - Textfields - Speech Bubbles - Image and Text combined - and so on Let’s take this sub box content element as an example. It is called “Image Bubble Horizontal”: The markup of this Blocks view file looks like this: <?php namespace ProcessWire; use RockPageBuilderBlock\ImgBubbleHorizontal; /** @var Page $page */ /** @var ImgBubbleHorizontal $block */ ?> <?php $bubbleForm = $block->settings('bubbleForm'); $bubblePosition = $block->settings('bubblePosition'); $bubbleColor = $block->settings('bubbleColor'); $customColorBubble = $block->settings('customColorBubble'); if ($bubbleColor === 'custom') { $bubbleColor = $customColorBubble; } $linkColor = $block->settings('linkColor'); $customColorLink = $block->settings('customColorLink'); if ($linkColor === 'custom') { $linkColor = $customColorLink; } ?> <section class="rpb-imgbubblehorizontal uk-height-1-1 uk-position-relative" data-id="<?=$block->id;?>" <?= alfred($block,["addTop" => false,"addBottom" => false,"clone" => false]) ?>> <?php $image = $block->img_single; if ($image) { ?> <img srcset="<?= $image->size('horizontal')->srcset() ?>" src="data:image/svg+xml;charset=utf-8,%3Csvg xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' viewBox%3D'0 0 <?=$config->imageSizes['horizontal']['width']?> <?=$config->imageSizes['horizontal']['height']?>'%2F%3E" sizes="auto" width="<?= $config->imageSizes['horizontal']['width']?>" height="<?= $config->imageSizes['horizontal']['height']?>" alt="<?= $image->description ?>" loading="lazy" /> <?php } ?> <div class="speech-bubble uk-flex uk-flex-center uk-flex-middle bubble-form-<?=$bubbleForm;?> <?=$bubblePosition;?>"> <div class="speech-bubble-content"> <?= $block->body(); ?> </div> <img style="color: <?=$bubbleColor?>;" src="/site/templates/images/bubbles/bubble-<?=$bubbleForm;?>.svg" uk-svg/> </div> <style> section[data-id="<?=$block->id?>"] a { color: <?=$linkColor?> !important; } </style> </section> I don’t want to go into details too much but one of the many great features of the RockPageBuilder module is that you can include and block specific setting fields directly into the Blocks PHP file without the hassle of creating those fields in the backend in the first place and adding them to the block manually. What a time saver this was! For example the content element “Image Bubble Horizontal” should have several config options. - the shape of the speech bubble - the position of the speech bubble - the color of the speech bubble - the color of the link text (if included) This is all done in the settingsTable method (https://www.baumrock.com/en/processwire/modules/rockpagebuilder/docs/settings/) public function settingsTable(\ProcessWire\RockFieldsField $field) { // You can set default settings for all blocks via hook. // See docs for details or leave this line unchanged. $settings = $this->getDefaultSettings($field); $settings->add([ 'name' => 'bubbleForm', 'label' => 'Sprechblase Form:', // the first parameter must match the name of the setting!! // in this case the setting's name is "demo", so we use "demo" here as well 'value' => $field->input( 'bubbleForm', // use either "radios" or "radios-inline" 'select', [ '*hexagon' => 'sechseckig', // the star marks the default option 'square' => 'viereckig', 'round' => 'rund', ] ), ]); $settings->add([ 'name' => 'bubblePosition', 'label' => 'Sprechblase Position:', 'value' => $field->input( 'bubblePosition', // use either "radios" or "radios-inline" 'select', [ 'uk-position-top-left' => 'Oben links', // the star marks the default option 'uk-position-top-center' => 'Oben mitte', 'uk-position-top-right' => 'Oben rechts', '*uk-position-center-left' => 'Mitte links', 'uk-position-center' => 'Mitte', 'uk-position-center-right' => 'Mitte rechts', 'uk-position-bottom-left' => 'Unten links', 'uk-position-bottom-center' => 'Unten mitte', 'uk-position-bottom-right' => 'Unten rechts', ] ), ]); $settings->add([ 'name' => 'bubbleColor', 'label' => 'Sprechblase Farbe:', 'value' => $field->input( 'bubbleColor', // use either "radios" or "radios-inline" 'select', [ '*#e61b7b' => 'Magenta', // the star marks the default option '#1cae8d' => 'Grün', '#dea500' => 'Gelb', '#646363' => 'Grau', 'custom' => 'Eigene Farbe', ] ), ]); $settings->add([ 'name' => 'customColorBubble', 'label' => 'Eigener Farbwert Sprechblase (HEX Code)', 'value' => $field->input('customColorBubble', 'text'), 'showIf' => 'bubbleColor=custom', ]); $settings->add([ 'name' => 'linkColor', 'label' => 'Linktext Farbe:', 'value' => $field->input( 'linkColor', // use either "radios" or "radios-inline" 'select', [ '*#e61b7b' => 'Magenta', // the star marks the default option '#1cae8d' => 'Grün', '#dea500' => 'Gelb', '#646363' => 'Grau', 'custom' => 'Eigene Farbe', ] ), ]); $settings->add([ 'name' => 'customColorLink', 'label' => 'Eigener Farbwert Linktext (HEX Code)', 'value' => $field->input('customColorLink', 'text'), 'showIf' => 'linkColor=custom', ]); return $settings; } The edit mask of the block then looks like this: 4. See it in action Heres a quick demonstration video of how the page editing with the layout bocks and nested blocks is working in real time: Bildschirmaufnahme 2025-01-18 um 14.22.27.mp4 5. Modules and other tech - UIkit 3 as frontend framework - RockFrontend (https://www.baumrock.com/processwire/module/rockfrontend/) - RockPageBuilder (and lots of thanks to @bernhard for helping me out on this project) (https://www.baumrock.com/processwire/module/rockpagebuilder/) - Cronjob Database Backup (https://processwire.com/modules/cronjob-database-backup/) - ProcessWire User Activity (https://processwire.com/store/pro-dev-tools/user-activity/6 points
-
@ryan So many great new and exciting features. A few are gamechangers. Thank you for all the hard work by both you and contributors. Repeater page classes are 🤌3 points
-
AFAIK, a PageFiles field shows all files, including file descriptions, tags, etc. The visibility option is for the entire field. It would be helpful to minimise the file list in admin to filename or custom fields, eg {basename} {modified}, only in the admin area similar to repeaters. A down arrow could expand individual file meta. When a page has lots of attached files, it's cumbersome to scroll through all the files with descriptions & tags when the field visibility is "Open".2 points
-
1 point
-
@zilli Some great questions! I spent many years writing vanilla PHP template markup. For Occam's Razor, have the leeway to apply as many or few features a tool offers. Your mentioning Markup Regions is a good example, I use many features of ProcessWire but have never used Markup Regions (I have no opinion, it just coincidentally never became part of my workflow). Both MR and templating engines aim to overcome challenges introduced when using PHP (like any language) alone for output. So it's up to the preference of the developer and needs of a project, a la "there are no wrong answers". My limited experience with MR make me a less than ideal candidate to draw comparisons or speak to compatibility. My first thought it to flip the question of complexity and see how it applies to tools you/me/we may already use. Page Classes are a layer of complexity to abstract logic out of presentation, ProcessWire itself is a layer of complexity to abstract database transactions/data management. Templating strategies are a layer of complexity that make your workflow less complex. Tools like MR and templating packages do that as well while sometimes affording some extra tools. My experience with templating solutions was born out of bumping my head on limitations and moments of thinking "there has to be a better way to do this". I ended up using creative tricks to make 'require' and 'require_once' carry the load but ended up making my code harder to manage, more files to make it work, and felt like I was breaking good practice rules. Consider this simple example: <!-- /site/templates/inc/header.inc.php --> <!DOCTYPE html> <html lang="en"> <head> <title><?=$page->title?></title> <?php if ($includeGoogleAnalytics ?? false): ?> <?php require_once '/path/to/google_analytics.inc.php' ?> <!-- GA code here --> <?php endif ?> </head> <body id="$pageId" class="<?=$pageClass?>"> <header> <img src="/path/to/logo.png"> <h1><?=$headline?></h1> </header> Then I have my home.php and to make this work, I have to start setting big scope variables to be made available to the 'require_once' code. This got worse as the site needed more features and the header and footer became more complex. Later I had to create a new headers for other parts of the site, so multiply the code above a few more times, and add some more 'require_once' lines to each of them. <?php namespace ProcessWire; // /site/templates/home.php $pageId = 'stuff-here'; $pageClass = 'stuff-there'; $includeGoogleAnalytics = true; require_once __DIR__ . 'partials/header.inc.php'; ?> <!-- We haven't even added one line of markup/code for the home page --> <?php $includeCallToAction = true; $includeTestimonials = false; $anotherOne = true; $iHearYouLikeOutOfScopeVariables = false; require_once __DIR__ . 'partials/footer.inc.php'; ?> Here's an actual snippet from a site I build years ago. If you look at a partial or component and it has a lot of if statements, sometimes but not always, it says "I'm a file that does too much" and it becomes increasingly difficult to manage. <!-- Real snippet of production code from /site/templates/partials/footer.inc.php --> <?php if ($mainNav): ?> <?php require_once __DIR__ . '/../inc/site_nav_overlay.inc.php' ?> <?php endif ?> <?php if ($salesCtaModal): ?> <?php require_once __DIR__ . '/../inc/cta_sales_quote_modal.inc.php' ?> <?php endif ?> <?php if ($solarCleaningCtaModal): ?> <?php require_once __DIR__ . '/../inc/cta_solar_cleaning_modal.inc.php' ?> <?php endif ?> <?php if ($solarRepairCtaModal): ?> <?php require_once __DIR__ . '/../inc/cta_solar_repair_modal.inc.php' ?> <?php endif ?> Is this how everyone does it? Maybe not, hopefully not, but every project runs the risk of becoming Frankenstein's monster. With a templating solution approach this would have been solved with 4 files. You can significantly reduce the number of if statements because each of these have a job to do, they know what it is, and when you're maintaining the site, or adding new features, there is zero confusion about where to go. Working on the blog parts? Go edit the blog templates and blog layout. The service/maintenance pages know they'll need the "cleaning" and "solar repair" modals so that whole if block doesn't exist anymore. Cake. <?php namespace ProcessWire; // This is the base layout. The layouts below declare this as *their* layout and pass data if needed $this->layout('layouts/base'); // For the majority of pages on the site $this->layout('layouts/main'); // For the pages dedicated to customer service and maintenance rather than sales $this->layout('layouts/service_mainenance'); // For all blog and blog related pages $this->layout('layouts/blog'); ?> Long story short, the complexity would have been immediately reduced by introducing a templating tool with a predictable set of features and functions to use. To contrast, as a longtime user of preprocessors myself, I can say that those have the potential to introduce a lot of things that fundamentally change how you work with the language itself. Sass/Less bring nesting, loops, variables (before custom properties were available), mixins, includes, file imports, modifier functions, if/else control flows, custom functions, (the list goes on) and an entire JavaScript toolset to handle it. You can solve a lot of problems you don't have! This isn't an argument against preprocessors, but there is a higher level of discipline you must have to keep this from going off the rails and being so clever you outsmart yourself. On the other hand, templating is so incredibly fundamental to producing apps and websites that the constrains start to tighten much sooner and it becomes more clear how many workarounds and "bending the rules" of good practice are present. The benefits of introducing templating tools bring a higher number of benefits that are more impactful faster. You're also adopting a common development practice, so it is leveling up your skillset. I have to mention that these benefits are not unique to Plates. Layouts, and enhanced insert/include features, are common to pretty much all templating tools. Pick the one that feels right be it Latte, Twig, Smarty, or Plates. My only argument in favor of Plates is that if templating is something that you're introducing into your projects for the first time you may be up to speed faster because: a) the core features set of Plates is very limited (intentionally), and b) it's the same PHP syntax you already use. The concepts and strategy you use with Plates will translate to other templating tools. In the case of this module, the potential amount of complexity is almost entirely due to the custom extensions I built which is why they are optional and disabled by default. You can safely ignore everything in my post above from "Plates for ProcessWIre Extensions" on down and still get simple yet powerful tools. If you have any Q's, post them here.1 point
-
We’ve been building web site with ProcessWire since 2013. ProcessWire serves to us as a secure, reliable platform, and honestly, I don’t remember any significant issue after 11 years of daily use (for us, PW is also a CRM). The magic of ProcessWire is that it is always growing with our needs and serves any unimaginable demand that our platform has had. All these years, our business has grown around ProcessWire, and as it usually happens, popularity brings the other side of the coin. In our case, it was online fraud and scammers. Our first approach was to use existing fraud prevention systems, but as our business is not pure e-commerce and fraud was indirect, there was no solution that matched our needs, so we started developing our system from scratch. This is where I exactly understood how ProcessWire and the community really hooked me. (-: First of all, taking ProcessWire as an example, we decided not to heavily rely on frameworks. It was a hard decision, because new school engineers like to bring as many dependencies as possible, but I continuously pointed to ProcessWire, and as a result, we created a fraud prevention/user behaviour analytics platform with ~4 PHP dependencies. The second decision that we took, looking at ProcessWire, was even harder than the first. The fraud prevention market, in contrast with CRM, is not widely targeted for open source software, but taking ProcessWire as an example, we decided to open source our system after ~8,000 engineer-hours under the AGPL license. For sure, after being open-sourced for one week, it's premature to give any feedback, and it is highly possible that open sourcing was a mistake. However, it brings me to the understanding that the real measure of software is not downloads or stars, but its influence over other developers, and from them onto other developers, like ripples on the water. From this perspective, I am infinitely grateful to @ryan, @Ivan Gretsky, @Soma, and every person behind the ProcessWire community for all the inspiration through these years. I'm so grateful that 11 years ago I met this community and had the chance to work with some of you. As I'm more reader than writer, I would like to use this rare opportunity to wish the ProcessWire community and your families a Merry Christmas and all the best in the New Year! Best Alex P.S. While this post is not intended to be an advertisement, if someone from community is facing challenges related to online fraud, user spam, or security, please feel free to contact me directly.1 point
-
We had a chat a bit with @Ivan Gretsky and understood that probably I need to complete our story with more details. Unlike common images of start-ups, this is not fun at all. As mentioned, we developed this system bootstrapped for 1,000 days with a remote team of 11 (4 female, 7 male) from Ukraine, Georgia, Netherlands, Germany, Switzerland, Poland, and Thailand. My second son was born during this period, and I was literally working on this with a baby in one hand and a laptop in the other. We lost connection with our lead developer, as he was in Kharkiv (Ukraine). We haven’t had a connection with him since July, but I sincerely hope he is safe… If someone had told me that it would take 1,000 days (I had planned for three times less) and several thousand engineer hours, I probably would have never started this development, as it looked so unreal. It took approximately half the time to develop the system itself and another half to debug it to the condition it has now. Of course, during this development, we had to rewrite everything from nearly scratch several times, and it still doesn’t look perfect, but at some point, we understood that it is impossible to develop the code on our own and we need to share it with the community. The code release itself was quite a journey. Especially the last weeks, days, and, most difficult of all, the last hours. Arina (our junior lead developer) and me spent all day in a smoke-filled bar in Belgrade polishing the last version prior to release. And, of course, at the very last moment, we found a very unusual error that was extremely difficult to debug at 1AM. And at 6AM, I had to rush to the airport. There was a 37.5cl bottle of champagne for the three of us: myself, Arina and our director (photo attached), and despite popular images of startups, there was no party at all, only a pretty intensive and really hard time prior to release. So my advise for everyone whom working on large code base are following: - multiply every realistic time estimation for three; - have always backup for lead developer; - be ready to release the code better soon than later, as it will never be accomplished. I write this here now because I wish to learn this before starting this journey. Of-course I expect that there another bunch of rakes around that only waiting for it’s time P.S. If someone could share simple user tracking event module for ProcessWire that we can adopt for use with tirreno, it would be highly appreciated. I was not aware how stars are important for GitHub ranking, so would like kindly ask to put one if you see this software helpful: https://github.com/TirrenoTechnologies/tirreno1 point
-
I've been continuing to work on the PageEditChildren module that I wrote about here last week. This week a "Clone" feature was added. You can click the Clone action and it'll create a copy of the page below the one you cloned, and then make it immediately editable before you even have to save. This Clone action is an example of an Inputfield header action, and it accompanies the Move, Pub/Unpub and Trash actions for each page in PageEditChildren. I thought this ability to add Inputfield actions seemed useful beyond just this module, so the ability has been added directly into ProcessWire's core Inputfields JS API. If you grab the current dev branch of ProcessWire, you can test it out if you'd like. You can paste these examples in your web browser's Javascript console. But in actual web development, you'd likely put these in a separate JS file that is added to your page editor with a hook. Open the page editor to any page, then open your Javascript console in your web browser, and then paste this in: Inputfields.addHeaderAction('title', { icon: 'fa-hand-stop-o', callback: function() { ProcessWire.alert('Hello World!'); } }); That should add a hand icon to your "Title" field header, and if you click it, it'll pop-up a dialog box that says "Hello World". Let's say you wanted it to show a different icon when you hover it, and also to show tooltip text via a title attribute. You can add the 'overIcon' to specify what icon to show on mouseover, and 'tooltip' to specify the tooltip text: Inputfields.addHeaderAction('title', { icon: 'fa-hand-stop-o', overIcon: 'fa-hand-peace-o', tooltip: 'Hello world', callback: function() { ProcessWire.alert('Hello World!'); } }); Above are examples of 'click' actions. We also support toggle or "on/off" actions: Inputfields.addHeaderAction('title', { onIcon: 'fa-toggle-on', onTooltip: 'Click to toggle off', onCallback: function() { ProcessWire.alert('You toggled on'); }, offIcon: 'fa-toggle-off', offTooltip: 'Click to toggle on', offCallback: function() { ProcessWire.alert('You toggled off'); } }); Toggle actions like this are primarily what is used by the PageEditChildren module to handle the Published vs Unpublished state, and Trash on/off state. Whereas "Clone" is an example of a Click action. Our callback functions in the examples above are very simple alerts, but of course you could make it do anything you want in those callbacks. Also added this week to the Inputfield JS API was an update to the Inputfields.label() function that now allows you to set the label for an Inputfield (previously it could only get the label). This is a bit of a contrived example, but since we were talking about header actions above, let's demonstrate the label() function within a header action. This example adds an action that lets you edit the Inputfield label: Inputfields.addHeaderAction('title', { icon: 'smile-o', callback: function($f) { ProcessWire.prompt('Enter new label', 'Label', function(val) { if(val) Inputfields.label($f, val); }); } }); By the way, there's a lot more to the Inputfields JS API, and it's all documented directly in ProcessWire's inputfields.js file. I'll be bumping the core dev version next week to hopefully accompany the first version of the PageEditChildren module. Thanks for reading and have a great weekend!1 point