Jump to content

Leaderboard

Popular Content

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

  1. This week there have been a few updates to the core on the dev branch, but nothing major. Next week I'll be bumping up the version to 3.0.227 and then likely merging back to the master/main branch again. While there aren't major updates relative to 3.0.226, that means there isn't a lot to test or break, so it makes sense to keep updating the main/master branch until we get into more significant updates on the dev branch. In addition to getting into more significant dev branch updates, I'm also planning to put out version updates on nearly all the Pro modules in the upcoming weeks. Thanks for reading and have a great weekend!
    4 points
  2. Most of the contents in site/assets are created on the fly like caches, compiled template files and log files, and therefore don't need to be transferred. The exception are page files (file and image fields), which live under site/assets/files, so you need to copy that directory too. The things that need to be copied to move a complete site to another server are site/templates site/modules site/assets/files [*] site/classes (if the site uses custom page classes) site/init.php (if used) site/ready.php (if used) site/finished.php (if used) Then any settings in site/config.php need to be adapted in the target site (including $config->userAuthSalt, which needs to match the database contents) sites/assets/cache should be emptied [*] If you've only done a visual overhaul to an existing site without changing any contents, you don't need to copy the files directory. If you don't have any content on the target site you need to preserve, you can of course also copy the whole site directory, empty the site/assets/cache directory and adapt the settings in site/config.php. In that case, you just need to pay attention that directory permissions under site/assets are correct so the webserver user has write permissions. That last point is often overlooked when uploading stuff using (s)ftp or zip files.
    3 points
  3. Hi, What's it all about I'd like to share some thoughts and approaches i took to meet the customers requirements when i built the website. Maybe someone has (or will have) similiar needs and can benefit from it, hopefully. I will focus mostly on technical stuff. And because of that i am not sure, if the showcase section is the place to post it (?). Its more like a testimonial. About the organisation/website https://vdp-ev.de (german language only) The Verband Deutscher Puppentheater e.V. (VDP) is the cultural policy respresentation for professional puppet stages in Germany. The VDP gives advice, shares knowledge and represents currently 140 member stages. They publish a magazine frequently, giving awards, workshops and organize events for their members. As the VDP was founded many years ago, they have lots and lots of contents, each with individual structural needs . So the first goal was to pack the vast of content in a good structure and make sure visitors has access to it as straight as possible. Therefor the grafical presentation is rather plain, not really stand out or comes with fancy stuff ?. Some random screens of the public website: Some random screens of the (secured) members marketplace (explanation s. below): Seeing no way to set skip links, here is a short plain TOC: 1. Building a marketplace for VDP members 1.1 Requirements and conceptual thoughts 1.2 Building the menu 1.3 Keep it maintainable 2. Publish selected members content on the public website 2.1 Clients request 2.2 Starting, first approach 2.3 Solution 1. Building a marketplace for VDP members 1.1 Requirements and conceptual thoughts Before the relaunch, members (they have a special user role) yet could login into the backend and edit their contents (data for their stage + add/edit productions). With help of @adrians AdminRestrictBranch they only see their own stage and productions. Those users have no access to other menu trees. With the relaunch the VDP wants to have something different/more elaborated: A secured member area (e.g. marketplace) where all members can share and swap ideas, informations, leading discussion related to their profession, offer or search for profession related material (like puppets, technical gear, services etc.) and some more. Just like some kind of a simple forum (with maintaining their own entries, s. below), but without the overhead of a standalone forum software. There was a (only grafical) approach how to do this by the former developer. His idea was to establish a secured member frontend where the loggedin user have (frontend) presentations to manage their own marketplace content, their stage and productions and even their profile a least. Well, some kind of reinventing the backend... Beside the fixed budged, i thought of a better way to do this. First, i wanted to seperate the marketplace output from the input strictly. Without real advantage member users shouldn't be forced to learn something they're already familiar with (Backend login and add/edit their stage and productions). Second, all marketplace content should live within the PW ecosystem, e.g. are template base pages that lives in the page tree. At least for administrators to see/edit... (s. below also). So, where to establish the CRUD actions for the members content of the marketplace section for each member user (with that special user role)? It all leads to adapt the PW Backend Menu. The Module CustomAdminMenus by @Robin S seems to give a good start for this. The setup for static pages is rather simple. But for my use case i had to deal with a much more dynamic approach. Luckily the module is hookable... I wanted to have two Menus: Mein Markplatz which displays all CRUD actions for the sections (Figuren, Bühne, Material, Tipps & Tricks a.s.o., s. image above) and Zum Markplatz Portal which links to the members marketplace overview page. 1.2 Building the menu First we get the current user content, populate the dynamic menu and build two menus at least. /** * Build Marketplace Admin Menu * * Backend interface for vdp members to add/edit pages marketplace * sections. * * Each member only will see entries that they created. */ $wire->addHookAfter('CustomAdminMenus::getMenuChildren', function(HookEvent $event) { // The menu number is the first argument $menu_number = $event->arguments(0); // Handle Menu 1 if($menu_number === 1) { // Get the current user $user = $event->wire()->user; // Hide admin menu except for vdp members if ($user->isSuperuser() || !$user->hasRole('theater')) { // Do not show the menu $event->return = false; } else { // init $hints_children = []; $offers_children = []; $blog_children = []; $discussions_children = []; // Get all hints for current user $hints = $event->wire()->pages->findRaw("template=members-marketplace-hint, created_users_id=$user.id", ['title', 'url', 'id']); // Allow to add a new hint // Adapt values to fit your environment $hints_children = [ [ 'icon' => 'plus-circle', 'label' => 'Neuen Eintrag anlegen', 'url' => $event->wire()->config->urls->root.'vdpadm/page/add/?parent_id=4232', 'newtab' => false, ] ]; // Build from results // Adapt values to fit your environment foreach($hints as $hint) { $hints_children[] = [ 'icon' => 'file-text-o', 'label' => $hint['title'], 'url' => $event->wire()->config->urls->root.'vdpadm/page/edit/?id='.$hint['id'], 'newtab' => false, ]; } // ... repeat for other marketplace sections ... // Build the menu $menu1 = [ [ 'icon' => 'thumbs-up', 'label' => 'Tipps und Tricks', 'url' => '', 'newtab' => false, 'children' => $hints_children, ] // ... repeat for other marketplace sections ..., don't forget the `,` ;-) ]; // Return the menu $event->return = $menu1; } } // Handle Menu 2 (Link to marketplace portal) if($menu_number === 2) { // Get the current user $user = $event->wire()->user; // Hide admin menu except for vdp members if ($user->isSuperuser() || !$user->hasRole('theater')) { // Do not show the menu $event->return = false; } else { $menu2 = []; // Return the menu $event->return = $menu2; } } }); FYI: Code is part of a ready.php file which lives in /site (s. also https://processwire.com/docs/modules/hooks/) After that the PW top header looks like this: If you click on Mein Markplatz, you get the verbose list*. *) The member user for the demo has no existing entries, so you see none (only the link to add a new entry). 1.3 Keep it maintainable As an administrator i must be able to identify which entry is related to which member. So i prepend the user name to pages names programmatically. This is done by a little helper hook. All relevant templates has a hidden field named `creator`, which gets populated with the user name on page save. To avoid overriding the value when a adminstrator edits an entry, its packed in a condition. Very important, because otherwise the assignment (entry <> member) gets lost! All entries edited by a administrator would have a new owner ?. Definitely not what we want... Btw. the user role `theater` in this example represents the special role for members mentioned above. /** * Utility hook for `Build Marketplace Admin Menu` * * Field `creator` is a hidden page field, that is populated * on page save with the username of the created user. Only related * to members marketplace pages. * * Prevent superuser to change `created user` while edit/save * the page for administration purposes. * * We need this hook on page save, because we want to show * the username within the admin page sidebar list ($page * only provide the ID of the created user). */ if (!$user->isSuperuser() && $user->hasRole('theater')) { $wire->addHookBefore('Pages::saved', function($event){ $page = $event->arguments(0); if($page->hasField("creator")) { // Get the current user $user = $event->wire()->user; // Populate template field for use in the admin sidebar list $page->creator = $user->name; // Save back to $page $page->save('creator'); } }); } FYI: Code is part of a ready.php file which lives in /site (s. also https://processwire.com/docs/modules/hooks/) The complete ready.php vdp-marketplace-demo-ready.php So this is it, mainly. As there are two ways to go after a successful login (Backend view to edit/add content or Frontend view of the members marketplace overview page) the members must decide where they want to go first. Btw, after the user is logged in, the navigation changes within the member frontend scope. So the user can switch between frontend and backend view each with one single click. 2. Publish selected members content on the public website 2.1 Clients request After the relaunch was online, the customer had another request: They wanted to let members decide if their entries (of particular sections of the member marketplace) should also be integrated/viewable on the public website. Visually identical to the views within the member marketplace. Those (public) pages should be available in the navigation and also be indexable by search engines. While this seems not quite a too difficult task at first glance, it turns out to be a bit more tricky. The reason are the restrictions of page paths when dealing with the (secured)members and public scope. Note: All sections in the members marketplace are applied as blog pages, e.g. each has a parent page and associated children. 2.2 Starting, first approach First, i add a conditional checkbox to all related marketplace templates, which was needed in any case. But than it gets a bit annoying. Having kind of a (public) placeholder template (and page based on it) and then iterating over the member blog entries was a dead end. The `children->url` path of course leads to the member section (at that time i wrote a post about this because i hoped this could be solved somehow) As i have to have a real template/page(s) for this (s. 2.1 why), it isn't possible to hook paths here. I realized, i had to find a complete other approach... 2.3 Solution Finally i set up clones for all relevant members section templates (e.g. parent + child template), built public available pages from it and mirror allowed* member entries to the appropriate public pages on a regular base. To avoid disruption, those public pages are readonly for editors. *) Entries with a particular option set (e.g. Beitrag auch auf der öffentlichen VDP Website anzeigen?, s. picture above) The synchronisation between the members area and the public clones is done by cronjobs for each section. Example sync file for one section (VDP Blog): <?php namespace ProcessWire; /** * Synchronize members < > public blog pages * * This file is meant to get executed by a cronjob * * 1. Synchronize (add, update, delete) * 2. Synchronize (delete) * 3. Log, Mail */ // bootstrap processwire, adapt to your path include("../index.php"); // init $d = array(); $o = array(); $totalcountUpdate = ''; $totalcountNew = ''; $totalcountDeleted = ''; // Get member blog items $members_marketplace_blog_items = $pages->find('template=members-marketplace-blog-item'); // Iterate over member blog items, save `name` foreach($members_marketplace_blog_items as $item) { $d[] = $item->name; } reset($d); /** * 1. Synchronize (add, update, delete) * * Perfom synchronisation based on existing member blog items */ // Iterate over members blog items for ($i=0; $i < count($d); $i++ ) { // Get member blog item by given name from the `d` array. $members_blog_item = $pages->findOne("template=members-marketplace-blog-item, name=$d[$i]"); // Get the related public clone (if exists) $public_blog_item = $pages->findOne("template=blog-vdp-item, name=$members_blog_item->name"); /** * Conditional actions * * 1. if * Update present page * * Verbose: Is yet present in public section && is * allowed to be displayed * * 2. elseif * Add new page * * Verbose: Is not present in public section && is * allowed to be displayed * * 3. elseif * Delete page * * Verbose: Is yet present in public section && is * not allowed to be displayed */ if ($public_blog_item->name == $members_blog_item->name && $members_blog_item->options_members_marketplace_entry_publish_to_public == 1) { $public_blog_item->title = $members_blog_item->title; $public_blog_item->name = $members_blog_item->name; $public_blog_item->headline = $members_blog_item->headline; $public_blog_item->blog_date = $members_blog_item->blog_date; $public_blog_item->page_blog_tags_vdp_blog = $members_blog_item->page_blog_tags_vdp_blog; $public_blog_item->body = $members_blog_item->body; // Save page to get an ID for adding images, s.below $public_blog_item->save(); // Make sure we process an array $public_blog_item->of(false); // Delete images first to avoid duplication $public_blog_item->images_members_marketplace_entry->deleteAll(); // Add images foreach ($members_blog_item->images_members_marketplace_entry as $img) { $public_blog_item->images_members_marketplace_entry->add($img); } // Save page again (just for the sake of it) $public_blog_item->save(); // Save iteration for mail, s. below $totalcountUpdate = $i; } elseif ($public_blog_item->name != $members_blog_item->name && $members_blog_item->options_members_marketplace_entry_publish_to_public == 1) { // Add new page $public_blog_item_add = new Page(); $public_blog_item_add->template = 'blog-vdp-item'; $public_blog_item_add->parent = '/wissenswertes-ueber-puppentheater/vdp-blog/'; $public_blog_item_add->title = $members_blog_item->title; $public_blog_item_add->name = $members_blog_item->name; $public_blog_item_add->headline = $members_blog_item->headline; $public_blog_item_add->blog_date = $members_blog_item->blog_date; $public_blog_item_add->page_blog_tags_vdp_blog = $members_blog_item->page_blog_tags_vdp_blog; $public_blog_item_add->body = $members_blog_item->body; // Save page to get an ID for adding images, s.below $public_blog_item_add->save(); // Make sure we process an array $public_blog_item_add->of(false); // Add images foreach ($members_blog_item->images_members_marketplace_entry as $img) { $public_blog_item_add->images_members_marketplace_entry->add($img); } // Save page again (just for the sake of it) $public_blog_item_add->save(); // Save itereation for mail, s. below $totalcountNew = $i; } elseif ($public_blog_item->name == $members_blog_item->name && $members_blog_item->options_members_marketplace_entry_publish_to_public == 0) { // Delete page $public_blog_item->delete(); } } /** * 2. Synchronize (delete) * * Delete outdated public blog item pages, e.g. do not * exists in the member section any longer. */ // Get all member blog items $_members_marketplace_blog_items = $pages->find('template=members-marketplace-blog-item'); // Iterate over member blog items, save `name` foreach($_members_marketplace_blog_items as $_member_item) { $o[] = $_member_item->name; } reset($o); // Get all public blog items $_public_blog_items = $pages->find("template=blog-vdp-item"); // Delete public blog item if not found in members array. foreach ($_public_blog_items as $_public_blog_item) { if(!in_array($_public_blog_item->name, $o)) { $_public_blog_item->delete(); $totalcountDeleted++; } } /** * 2. Log, Mail (delete) * * Log results in PW and send status mail */ // $log->save("cron", "Update public blog posts - New: $totalcountNew, Updated: $totalcountUpdate, Deleted: $totalcountDeleted"); // $emailTo = '<your-email-address>'; // $emailFrom = '<your-email-address>'; // $emailSubject = "VDP Blog | Cron | balance public to member sections "; // $header = ''; // $header .= "From: ".$emailFrom. "\r\n"; // $header .= "X-Mailer: PHP/" . phpversion(); // $message = ''; // $message .= "Am: ".date('d.m.Y H:i')."\n"; // $message .= "Aktualisierte Blog Beiträge: ".$totalcountUpdate."\n"; // $message .= "Hinzugefügte Blog Beiträge: ".$totalcountNew."\n"; // $message .= "Gelöschte Blog Beiträge: ".$totalcountDeleted."\n"; // mail($emailTo, $emailSubject, $message, $header); die(); ?> FYI: This example codefile can live anywhere, just adapt the path where your PW instance is located Example cronjob sync file: vdp-cronjob-sync-blog.php.zip Have fun ?
    2 points
  4. How many documents? How many users? If you only have a limited number then a simple page reference field would be all you need. Just add a field "readby" to your documents page and add users to that field via API. You just need to make sure that you don't have too many pages stored in the page reference field. So if you have many documents but just a few users add the page field to documents. If you have many users but just a few documents add the page field to the user template and add read documents to the field. If you have many documents and many users go with the custom table solution that I showed here:
    2 points
  5. Given that CSS has made huge strides in recent years combined with my desire to remove build processes (Sass, Tailwind), I'm thinking about going back to writing vanilla CSS, at least for some projects. My question is, what CSS organization methodology makes the most sense for vanilla CSS? I was never a fan of BEM personally and haven't had to think deeply about CSS methodologies for the past 10 years because I just followed the style of whatever CSS framework I was using.
    1 point
  6. Hello I created this issue https://github.com/processwire/processwire-requests/issues/502 please I would love to see your comments on this matter. This would enable using other servers besides Apache by implemeting .htaccess rewrite rules in PHP, maintaining the security of .htaccess in other webserver technologies. Thanks
    1 point
  7. An Images field allows you to: Rename images by clicking the filename in the edit panel or in list view. Replace images, keeping metadata and filename (when possible) by dropping a new image on the thumbnail in the edit panel. Introduced here. But neither of these things is possible in File fields, which prompted this module. The way that files are renamed or replaced in this module is not as slick as in the Images field but it gets the job done. The most time-consuming part was dealing with the UI differences of the core admin themes. @tpr, gives me even more respect for the work that must go into AdminOnSteroids. Most of the code to support the rename/replace features is already present in InputfieldFile - there is just no UI for it currently. So hopefully that means these features will be offered in the core soon and this module can become obsolete. Files Rename Replace Allows files to be renamed or replaced in Page Edit. Usage Install the Files Rename Replace module. If you want to limit the module to certain roles only, select the roles in the module config. If no roles are selected then any role may rename/replace files. In Page Edit, click "Rename/Replace" for a file... Rename Use the text input to edit the existing name (excluding file extension). Replace Use the "Replace with" select to choose a replacement file from the same field. On page save the file will be replaced with the file you selected. Metadata (description, tags) will be retained, and the filename also if the file extensions are the same. Tip: newly uploaded files will appear in the "Replace with" select after the page has been saved. https://github.com/Toutouwai/FilesRenameReplace http://modules.processwire.com/modules/files-rename-replace/
    1 point
  8. Really great work! Thanks for the technical lesson. I am still learning ProcessWire and this helps me a lot!
    1 point
  9. I write vanilla css. Well thats a lie ?. I write scss, but only because of lacking css nesting support. I guess in 1-2 years there should be a browser-support over 95%. Nesting is the only scss-feature i use. Everything else is vanilla css. Compiling scss to css is done by ProCache. I'm not a real programmer and have design/art background. Therefore i try to keep my workflow as simple as possible. In my projects I have to develop some „unusual“ layouts and many times the designs change a lot during the development. Therefore over the years the following distribution of files has worked for me pretty well. _reset.scss _fonts.scss (@font-face and sizes as classes) _globals.scss (color-variables, animation-classes and other global classes) _main.scss (for body and main element if needed) _header.scss _footer.scss m_component-name.scss … p_template-name.scss … I don't use components, but my section/article tags have always a unique classname, which correspond with the related php/css/js files. For Example for a image-slider i would have there three files: m_image-slider.php m_image-slider.scss m_image-slider.js .m_image_slider { width: 100%; } Should there be a need to overwrite some styles on a „project“ template, I can do that in a file like p_template_project.scss body.template_project { .m_image_slider { width: 50%; } } And if there is a need to have two different layouts for the image slider on two pages with the same template, I use the page ID. body.id_1234 { .m_image_slider { width: 80%; } } Therefore my body tag has always these two classes: <body class="id_<?= $page->id; ?> template_<?= $page->template; ?>"> That workflow helped me a lot to save time. Most of the the only my section tag has a classname. .m_image_slider { h2 { } figure { img { } } } What I want to say is that css methods have their justification and use. I do not work in teams and as single programmer it is much clearer and flexible to develop my own small method.
    1 point
  10. Hi @clsource I think this is a good idea. Gideon
    1 point
  11. I am long-time used to writing bem classes. They feel natural to me. But earlier this year I was also looking for more modern alternatives (that could be used without build step). Here is a nice article by Dave Rupert I've found on the topic. Didn't try any of it (yet?) though.
    1 point
  12. I played around and worked a lot with Astro in the last few months, and one thing I really liked was working with <Components />. Right now I try to move my experience from it towards my PW/Twig/Latte setup. Some parts work pretty well, while some things don't work out as expected. Splitting parts isn't that easy in PW, when using PW and Tailwind. Due to the missing build-step. But ok. I can live with it. When using plain CSS, this could be a totally different thing. Yet the CSS and JS isn't scoped. Boooh! I didn't use plain CSS for about 18 months now - which is wild, as I was a plain-CSS-advocate since always. But I am working on it again, which feels super awkward on its own right now, as PW is totally different compared to Astro or the tools I used in the last months. I could imagine using <Components /> in one way or another using Twig/Latte and some ProCache-magic... I could minimize CSS way more, yet I don't know if all that is really necessary. For what I can tell right now... each release with PW and JS/CSS is way bigger than in Astro, as PW has no real page-based build-step. That's fine for me, as most of my projects are super minimal right from the start and get 4x 100 in Google Pagespeed. To be really honest... I am at a point right now in which I really don't care about the last 100-500ms in a pagespeed tool anymore when I at leat get the 94 scores for each step. Addional note: Right now I work on a 11ty/Astro setup that loads all data, pages, and structure from PW in JSON-format. Loading all data (from https://www.restaurants-neumuenster.de/) takes about 1-2 seconds in total while building all pages, data entries, and everything else takes another 3-5 seconds. It works, yet I don't like the result somehow. There are things I really don't like and have to fix in JS/Nunjucks/Liquid or some other parts of the setup. Right now: I focus really on optimized PW Twig/Latte workflows and for minimals sites using JSON using 11ty/Astro as frontend layer.
    1 point
  13. Found this recently. Thought I would share. It provides a GUI in VSCode for DDEV. https://marketplace.visualstudio.com/items?itemName=biati.ddev-manager
    1 point
  14. I doubt this will happen. It appears that Ryan isn't inclined to work on it. I believe someone else will need to initiate this change, with Ryan providing final approval.
    1 point
  15. hi @nbcommunication You are absolutely right! but I don't have the skills and knowledge of processWire and php to do it that way. ? I'm not super happy with my solution, but it reduces the amount of data to be transferred to a good level. it is of course a quick and dirty implementation based on my skills. ? since I don't want to display the images on the page in full resolution but only link to instagram it makes sense not to have to load everything and just squeeze it small in the display. i read that in the "old" instagram api there was the possibility to request different image versions. this would actually be the perfect solution for the topic. this should potentially interest many users of the InstagramBasicDisplayAPI. Maybe there will be an update from Instagram? regardless, your module is a huge relief, 1000 thanks for that!
    1 point
  16. v0.2.0 is released, which adds support for multi-language, custom fields and upload name when a file is replaced.
    1 point
  17. Would be nice to update the Fontawesome icons in PW core, so they can be used for labels in the backend. The current version 4 is quite old and has a very limit set of icons. Version 6 also has a free version with more icons. The implementation seems to be very similar, so it should be easy to implement. The icons can be downloaded here.
    1 point
  18. I think you could try to edit the size setting of the modal via a hook, which should give you a similar experience than opening a full page.
    1 point
×
×
  • Create New...