Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 02/08/2025 in all areas

  1. This week on the dev branch are 8 issue resolutions. The most significant one #2035 (found by @Jonathan Lahijani) is that when you trash a page with children, and then later restore it, the page gets restored correctly, but the children/descendants only partially get restored. By that I mean that the children would get moved out of the trash, but they'd continue to have trash status. So those pages could silently behave like they were in the trash, making them visible in the PageList but otherwise inaccessible. There wasn't really any way to fix it interactively, since you can't manually assign or un-assign trash status, at least not without using the API. While I suspect this bug has been around for a very long time, I couldn't find any installations where I had trashed and restored a nested structure of pages like this, but was able to reproduce it manually. Just in case any of your installations have pages like that, the PageList (as of this week's commits) now highlights them with both trash and warning icons. Fixing the issue is just a matter of editing the page and clicking Save. If you want to quickly check if you have any pages affected by the issue (in almost any PW version), you can paste in the following URL, assuming /processwire/ is the path to your admin: /processwire/page/search/for?status=trash&has_parent!=7&include=all While it might be rare to trash and restore a structure of pages, I want to make sure nobody is affected by it so I'll likely update the current main/master version within the next week, merging the current dev branch. Coming in ProcessWire 3.0.246 is support for another type of conditional hook which enables you to match the return value, or properties of the return value, for any hooked method. Currently conditional hooks let you match things from the object being hooked, or the arguments of the method being hooked, but it's not previously been possible to match the return value of of methods with conditional hooks. Next week it will be, which I think as a useful improvement to our hooks system. More on that next week. Thanks for reading and have a great weekend!
    2 points
  2. Hi, sorry to be so late to answer, hit week... 🙂 actually it's quite simple, i would use your folder but this way Blog -> template blog-index Post 1 -> template blog-post Post 2 Post 3 Categories -> template blog-cat-index Category 1 -> template blog-category Category 2 Category 3 ... Tags -> template blog-tag-index Tag 1 -> template blog-tag Tag 2 Tag 3 ... then in your blog post template i would add two page-reference fields, one for the categories (parent => categories) and on for the tags (parent = well, guess :)) this way each post can easlily belong to various categories and have as many tags as you need afterwards, for your main blog index template allowing page numbers and url segments it's easy to add a selection of the posts based on the categories and/or the tags with,, in both cases, the ability to have a pagination as well as for the main list of posts depending on the way you want to filter your posts you'll just have to check the url segemnts, if only one (pagination or not, you can check if it is a category or a tag, if two either you decide the order (category/tag) or just check what kind is each one (easy to do making arrays of the available categories and tags to check in which one is which segment) something more, this way, each post will just have only one url yoursite.com/blog/thepostname no matter from which selection you're coming avoiding many potential isszues with duplicate content, categories and tags being only a way to select which posts are displayed on your page hope it's a little more explicit 🙂 have a nice day
    2 points
  3. Ever felt like your ProcessWire emails look like they're stuck in 1999? You know the drill - sending emails is super easy with WireMail: $m = new WireMail(); $m->from('foo@bar.com'); $m->to('xxx@yyy.com'); $m->subject('Hello there!'); $m->bodyHTML('<h1>This is great!</h1><p>I am an ugly mail...</p>'); $m->send(); But let's be honest - they look about as pretty as a website built with Microsoft FrontPage! 😅 🪄 Enter the Mail Pimp Hook! Drop this magical hook into your /site/ready.php (or even better Site.module.php), and watch your emails transform from ugly ducklings into beautiful swans: <?php $wire->addHookBefore('WireMail::send', function(HookEvent $event) { // double check that we got a wiremail instance // this also tells the IDE what $mail is (to get IntelliSense) $mail = $event->object; if (!$mail instanceof WireMail) return; // get current mail body $html = $mail->get('bodyHTML'); if (!$html) return; // get email layout markup $layoutFile = wire()->config->paths->templates . 'mails/default.html'; if (!is_file($layoutFile)) return; // replace ##content## with actual mail content $html = str_replace( '##content##', $html, wire()->files->render($layoutFile) ); // write new body to mail $mail->bodyHTML($html); }); The HTML Just create a beautiful MJML template at /site/templates/mails/default.mjml, put ##content## where your email content should go, convert it to HTML and BOOM! 💥 Every email gets automatically wrapped in your gorgeous template. No more CSS wrestling matches, no more "Why does this look different in Outlook?" headaches. Just pure email beauty, automagically! ✨ Now your clients will think you spent days crafting those emails, when in reality, you're sipping coffee while your hook does all the heavy lifting. Work smarter, not harder! 🚀 #ProcessWire #EmailMagic #NoMoreUglyEmails PS: This is the MJML template that I used: <mjml> <mj-head> <mj-attributes> <mj-all font-family="Tahoma" /> <mj-text line-height="140%" /> </mj-attributes> </mj-head> <mj-body background-color="#efefef"> <mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="30px" padding-top="30px" text-align="center" > <mj-column> <mj-image align="center" padding="25px" src="xxx" target="_blank" width="200px" alt="Logo" ></mj-image> <mj-text>##content##</mj-text> </mj-column> </mj-section> <mj-section> <mj-column> <mj-text font-size="10px" color="#a0a0a0" align="center" > powered by <a href="https://www.baumrock.com/" style="color: #158f66" >baumrock.com</a > </mj-text> </mj-column> </mj-section> </mj-body> </mjml> VSCode has an extension to get a live preview and export MJML to HTML: And here are some other free templates: https://mjml.io/templates I use https://www.base64-image.de/ to add the logo to my mail template as src="data:image/jpeg;base64,/9j/4QAWRXhpZgAATU0AKgAAAA..." to avoid headaches with image paths, remote assets blocking etc.
    1 point
  4. Modernism Week is a nonprofit organization dedicated to celebrating and providing education about midcentury modern architecture in Palm Springs, California- the epicenter of the modernist architecture movement. The 10 day event takes place in every year in February and features over 200 unique activities that draw 125,000 people from around the world. At Modernism Week you can tour iconic homes and neighborhoods, attend a cocktail party at Frank Sinatra's house, see live music, watch films, and attend engaging lectures. The organization also engages in preservation efforts to keep historic buildings and landmarks protected for future generations, as well as providing scholarships for students pursuing degrees in architecture, preservation, engineering, and design. https://modernismweek.com Tech Alpine.js htmx Tailwind CSS For a full list of technology, software, members of the web team, and a list of thanks to module developers who made this site possible, view the humans.txt file here. I posted a deep dive into the behind the scenes features and application development that handles automation and extensive use of powerful ProcessWire features over on this forum post. It was a pleasure to work with ProcessWire on this project and its amazing API and features made it all possible.
    1 point
  5. Hi, you could set a hook to set dir attribute on html tag or only on input(s) on language based and using bidir plugin on ck-editor to get parts of or whole backend as rtl as explained in thread linked by Bernhard, still seem the way to go.
    1 point
  6. Nice. Just wanted to mention Cerberus as an alternative to MJML if you want to use email-friendly HTML templates directly.
    1 point
  7. I don't know for sure but I don't think that this is possible. All posts that I found do not mention any solutions either: https://processwire.com/talk/topic/17834-how-to-rtl-admintheme-core-files/ https://processwire.com/talk/topic/7262-ckeditor-rtl/ https://processwire.com/talk/topic/13540-ck-editor-rlt-for-arabic/ (@flydev seems to have tested it) But UIkit supports RTL, so it might be possible?
    1 point
  8. 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/
    1 point
×
×
  • Create New...