Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 06/30/2021 in all areas

  1. While the version remains at 3.0.181 this week, there have been several core updates committed to the dev branch containing a mixture of issue fixes, new features, core optimizations and upgrades. This is likely to continue for another minor version or two while we prepare for our next master branch release. The most visible improvements this week can be found in ProcessField and ProcessTemplate (aka Setup > Fields, Setup > Templates). The main list of fields (Setup > Fields) has been improved with some new supported icon indicators that now identify fields that have template overrides/context settings, among others. All of the existing icon indicators have also been updated with contextual links so that clicking them takes you to the relevant part in the template editor. My favorite update here though is that the "Type" column in the fields list now indicates the Inputfield type in cases where it matters. For instance, rather than saying "Textarea" for the "body" field, it now says "Textarea/CKEditor". Likewise, Page and Options fields indicate what kind of input is used (i.e. "Page/AsmSelect" or "Options/Checkboxes"), as do some other types. Clicking on the "Templates" quantity now takes you to the "Add/remove from templates" field, rather than just showing you a list of templates. Similar updates were made to the ProcessTemplate main list of templates (Setup > Templates) though there wasn't as much to do there. Once you are actually editing a template, the instructions on the "Basics" tab have been improved to clarify what you can do on this screen. For instance, many don't know that you can click a field name/label to edit it in context, or that you can click and drag the percent indicator to adjust the field's width in the editor, all from this tab in the template editor. Now the description outlines these features. When you select a new field to add to your template, it now reveals a note that clarifies you must save before the field becomes editable in the context of that template. These are minor updates, but combined I think they add significant clarity, especially for new users. Stepping outside of the core, I've been working quite a bit this week on the PagesSnapshots module I told you about a couple of weeks ago. It lets you save or restore snapshot versions of pages, and it doesn't have any notable limitations in terms of fields. At this stage it is working fully with repeaters, matrix repeaters, nested repeaters, Page Tables and even paginated Table fields with thousands of rows. It can restore to the original page, to a new page, or to another page of your choice. And it is very fast. Eventually ProDrafts will use its API to handle saving and publishing of draft versions. Initially I plan to release it in one or more of the existing module sets (like ProDevTools or ProDrafts or both), and longer term it may be added to the core. I've got another week or two of work to cover with it, but at this stage the API is fully functional and working well, so I'm now beginning to focus more on the Process module (user interface) side of it. Thanks for reading and have a great weekend!
    29 points
  2. This week has been a continuation of last week in terms of ProcessWire development. While a lot of work has been done, there's not much new to report relative to last week, but I like to check in and say hello either way. I enjoyed putting a lot of time into the PagesSnapshots module this week and it's coming along nicely, getting closer every day. Today I've focused primarily on resolving GitHub issue reports, and am going to keep doing that every week till our next master version, which I hope to be ready in 2-3 weeks (same for the new module). But we'll adjust as needed. The next master version is going to be really solid, so I'm getting excited about it. I will likely bump the dev branch version to 3.0.182 next week. There were a couple more minor issues I wanted to get resolved in 3.0.182 but needed to spend a little more time with before I commit to the dev branch. Thanks and have a great weekend.
    24 points
  3. ProcessWire 3.0.182 is now posted on the dev branch. For a review of what's in this version, see the "Latest core updates" section of ProcessWire Weekly #374 and #375 plus this week there have been 12 additional commits with new issue resolutions, improvements and additions which can be found in the dev branch commits log. It's possible that ProcessWire Weekly #376 will also cover some of these updates when it is released too. I'd planned on even more in this version, but ended up losing a day of work yesterday as we had no electricity all day (it happens). So I worked outside in the yard instead— 3 issues were resolved, 4 improvements were made and 1 garage was organized. Focus in the coming weeks is on our next main/master version (core, not yard). If you have a chance, please take a moment to add sites you've built with ProcessWire to our sites directory. And if it's one that's already in the directory, feel free to add it again when/if it goes through a major redesign or redo. I'm really motivated by seeing the great work that all of you do and always enjoy seeing more of it. Plus, I'm thinking @teppo also likely looks at the newly submitted sites when considering the site of the week for his ProcessWire Weekly issues. If you find the existing categories on the submission form don't quite match a site you want to add, please send me a PM to let me know and I may be able to add new categories. Thanks for reading and have a great weekend.
    20 points
  4. Inertia Adapter ProcessWire Module Hello! Long time no see. I created this module so you can use Inertia.js (https://inertiajs.com/) with ProcessWire. Description Inertia allows you to create fully client-side rendered, single-page apps, without much of the complexity that comes with modern SPAs. It does this by leveraging existing server-side frameworks. Inertia isn’t a framework, nor is it a replacement to your existing server-side or client-side frameworks. Rather, it’s designed to work with them. Think of Inertia as glue that connects the two. Inertia comes with three official client-side adapters (React, Vue, and Svelte). This is an adapter for ProcessWire. Inertia replaces PHP views altogether by returning JavaScript components from controller actions. Those components can be built with your frontend framework of choice. Links - https://github.com/joyofpw/inertia - https://github.com/joyofpw/inertia-svelte-mix-pw - https://inertiajs.com/ Screenshots
    18 points
  5. ProcessWire 3.0.181 has fixes and improvements as usual, but the biggest addition is a nice pull request from @LostKobrakai, plus major updates to our Helloworld and ProcessHello demonstration modules. This post covers it all— https://processwire.com/blog/posts/pw-3.0.181-hello/
    17 points
  6. I developed the new Geffen Playhouse website over the course of 2018/2019 and launched it in September 2019. It has been perhaps the largest project I have been involved in. The Geffen Playhouse went through an entire re-branding done by Base (including a custom font), and I worked with Teak on the new website. Website https://www.geffenplayhouse.org/ Wikipedia https://en.wikipedia.org/wiki/Geffen_Playhouse Base write-up https://www.basedesign.com/work/geffen-playhouse-always-geffen-playhouse-always-new Teak SF write-up https://teaksf.com/work/geffen-playhouse-ticketing-ecommerce-website-design/ Another write-up: https://www.laurentakayama.com/geffen Their previous website was severely antiquated and it wasn't a responsive website (as of 2019!). Instead, it forwarded mobile users to a "mobile-friendly" website on a different subdomain, which I think was hosted by a third party service. However the data containing all the actors, shows, seasons, news and press articles were all in there. So one major aspect of this website was de-duping and importing their data into ProcessWire, along with some post-import cleaning… that's ~25 years of data. The site is built with UIkit 3 for the most part, and also uses FullCalendar for the large and small calendars. There is a custom integration with AudienceView, their ticketing system, which is used to import all the performance showtimes of their shows into ProcessWire. It's not the easiest API to work with (XML), but I eventually got it working. Repeater Matrix is being heavily used for section-based page building. Building out all the necessary matrix types took a long time as there was quite a bit of thinking what types and layouts we needed as we went along. However the end result has given the editors a lot of flexibility. ProCache is being used as well, including a CDN for all assets. This is crucial because when opening season sales are announced, the site gets slammed, but with caching turned on, it's not a problem anymore. On a deeper level, the site uses my new (well 2 years old now), universal and very opinionated base module that provides a menu builder, a standard set of fields/templates/pages, and a bunch of other tweaks that I tend to use on every site. All the fields, templates and pages are set up in a streamlined and editor friendly way. I wasn't able to access their previous CMS backend for various reasons (I only got the MySQL dump), so when developing the site and data model in ProcessWire, I was able to completely re-envision the editor experience and the data model without bias. A quote from one of the marketing directors at Geffen Playhouse: "We absolutely love ProcessWire."
    16 points
  7. Hi all, we made a small module for sending SMS via Sms77.io. It supports sending to one and multiple users. You can download it from GitHub and follow the instructions on how to install it - it is quite easy. An API key is required for sending, get yours for free @ Sms77 and receive 0,50 €. Hope this helps somebody and we are open for improvement suggestions! Best regards André
    13 points
  8. Reputation count is now back next to post count 🙂
    13 points
  9. Pete and I have been using Postmark in some PW based projects at reasonable scale (>13k emails a month) and have found it to be an exceptionally good API-based transactional email provider with fast delivery times and great availability. It seems strange that there is no WireMail offering (as far as we know of anyway) that supports Postmark, so we thought we'd throw one together in case anyone else in the community wants to give Postmark a try. NB: This is not the code we use in our production systems, just a rainy-day project to fill a gap in the WireMail ecosystem. However, it should be sufficient to get you going with Postmark. We hope you find it useful and please let us know if you find any issues. WireMailPostmark module on Netcarver's github account. Screenshot from my test account:
    12 points
  10. Select Images An inputfield that allows the visual selection and sorting of images, intended for use with the FieldtypeDynamicOptions module. Together these modules can be used to create a kind of "image reference" field. Integration with FieldtypeDynamicOptions InputfieldSelectImages was developed to be used together with FieldtypeDynamicOptions (v0.1.3 or newer): Create a Dynamic Options field. Choose "Select Images" as the "Inputfield type". Select Images appears in the "Multiple item selection" category but you can set "Maximum number of items" to 1 if you want to use Select Images for single image selections. Define selectable options for the field via a FieldtypeDynamicOptions::getSelectableOptions hook. See some examples below. FieldtypeDynamicOptions is recommended but is not a strict requirement for installing InputfieldSelectImages in case you want to use an alternative way to store the field data. Selection of Pageimages In this example the field allows selection of Pageimages that are in the "images" field of the home page. The field will store URLs to the Pageimages so it works as a kind of "image reference" field. You can use the "Format as Pagefile/Pageimage object(s)" option for the Dynamic Options field to have the formatted value of the field be automatically converted from the stored Pageimage URLs to Pageimage objects. $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { // The page being edited $page = $event->arguments(0); // The Dynamic Options field $field = $event->arguments(1); // For a field named "select_images" if($field->name === 'select_images') { $options = []; // Get Pageimages within the "images" field on the home page foreach($event->wire()->pages(1)->images as $image) { // Add an option for each Pageimage // When the key is a Pageimage URL the inputfield will automatically create a thumbnail // In this example the label includes the basename and the filesize /** @var Pageimage $image */ $options[$image->url] = "{$image->basename}<br>{$image->filesizeStr}"; } $event->return = $options; } }); Selection of image files not associated with a Page When not working with Pageimages you must add a "data-thumb" attribute for each selectable option which contains a URL to a thumbnail/image. In this example the field allows selection of image files in a "/pics/" folder which is in the site root. $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { // The page being edited $page = $event->arguments(0); // The Dynamic Options field $field = $event->arguments(1); // For a field named "select_images" if($field->name === 'select_images') { $options = []; // Get files that are in the /pics/ folder $root = $event->wire()->config->paths->root; $path = $root . 'pics/'; $files = $event->wire()->files->find($path); // Add an option for each file foreach($files as $file) { $basename = str_replace($path, '', $file); $url = str_replace($root, '/', $file); // The value must be an array with the following structure... $options[$url] = [ // The label for the image 'label' => $basename, 'attributes' => [ // An image URL in the "data-thumb" attribute 'data-thumb' => $url, ], ]; } $event->return = $options; } }); The field values don't have to be image URLs The values stored by the Dynamic Options field don't have to be image URLs. For example, you could use the images to represent different layout options for a page, or to represent widgets that will be inserted on the page. Also, you can use external URLs for the thumbnails. In the example below the options "calm" and "crazy" are represented by thumbnails from placecage.com. $wire->addHookAfter('FieldtypeDynamicOptions::getSelectableOptions', function(HookEvent $event) { // The page being edited $page = $event->arguments(0); // The Dynamic Options field $field = $event->arguments(1); // For a field named "calm_or_crazy" if($field->name === 'calm_or_crazy') { $options = []; // Add options that are illustrated with thumbnails from placecage.com $options['calm'] = [ // The label for the option 'label' => 'Nicolas Cage is a calm man', 'attributes' => [ // An image URL in the "data-thumb" attribute 'data-thumb' => 'https://www.placecage.com/260/260', ] ]; $options['crazy'] = [ // The label for the option 'label' => 'Nicolas Cage is a crazy man', 'attributes' => [ // An image URL in the "data-thumb" attribute 'data-thumb' => 'https://www.placecage.com/c/260/260', ] ]; $event->return = $options; } }); Field configuration You can define labels for the button, notices, etc, that are used within the inputfield if the defaults don't suit. https://github.com/Toutouwai/InputfieldSelectImages https://processwire.com/modules/inputfield-select-images/
    9 points
  11. You can achieve this with hooks to Page::addable and Page::editable. 1. Define access controls for the news-region and news-article templates so that users with the news-editor role can add children under news-region pages and they can edit and create news-article pages. 2. Create a news_regions Page Reference field which allows pages with template news-region. Best to make it a "multiple" AsmSelect field so it covers the potential case that a user needs to add/edit within multiple regions. Add this field to the user template. 3. Edit the news-editor users and set the regions they are allowed to add/edit within. 4. In /site/ready.php: $wire->addHookAfter('Page::addable', function(HookEvent $event) { /** @var Page $page */ $page = $event->object; $user = $event->wire()->user; // Return early if PW has already determined that the user is not allowed to add if(!$event->return) return; if($user->hasRole('news-editor') && $page->template == 'news-region') { // Addability depends on if the news_regions Page Reference field has the page $event->return = $user->news_regions->has($page); } }); $wire->addHookAfter('Page::editable', function(HookEvent $event) { /** @var Page $page */ $page = $event->object; $user = $event->wire()->user; // Return early if PW has already determined that the user is not allowed to edit if(!$event->return) return; if($user->hasRole('news-editor') && $page->template == 'news-article') { // Editability depends on if the news_regions Page Reference field has the parent page $event->return = $user->news_regions->has($page->parent); } }); The result for user "ringo": You could add all the regions to that user's page, but personally I would create a different news-supereditor role and just not make them subject to the restrictions in the hooks.
    9 points
  12. A few days ago I stumbled upon this old module, which had been laying in the modules directory of one of my sites since 2017 in a half-finished state. I have no recollection why I left it like that, but figured it might be useful for someone, so here we go: https://github.com/teppokoivula/Snippets https://processwire.com/modules/snippets/ Snippets is a tool for injecting front-end code snippets (HTML/JS/CSS) into page content. The way it works is that you create a snippet — say, a Google Analytics tag — and then choose... which element it should be tied to (there are some pre-populated choices and custom regex option), whether it should be placed before/after said element or replace it entirely, and which pages the snippet should apply to. The "apply to" option also has some ready to use options (such as "all pages" and "all non-admin pages") or you can select specific pages... or use a selector. Snippets are regular markup, with the exception that you can use values from current page (behind the scenes the module makes use of wirePopulateStringTags()). Available hooks: Snippets::isApplicable, which receives the snippet object and current Page object as arguments and returns a boolean (true/false). Snippets::applySnippet, which receives the snippet object, page content (string), variables (an object derived from WireData), and an array of options for wirePopulateStringTags() as arguments and returns the modified page content string. That's just about it. It's a pretty simple module, but perhaps someone will find this useful 🙂
    8 points
  13. Hello wonderful people, I've recently started using devdocs.io as my go-to reference for various programming languages and libraries; it's a great resource. Would be nice to see PW's API documentation in there too, but I don't yet know what needs to be done for this to happen. In the meantime, enjoy the docs :)
    8 points
  14. I really must make more of an effort to add more sites to this forum - we've done some nice work really. Women / Theatre / Justice is a case in point. WTJ is the umbrella title for research and public engagement activities undertaken by academics from various universities in partnership with Clean Break theatre company. Clean Break was founded in the 1970s by two women in prison and focuses on using theatre to help create positive change in the lives of women with experience of the criminal justice system. We wanted to reflect the origins of the organisation so we created a home made 'zine' like design with typewriter fonts and adding noise to the photographs and images to get a photocopied feel: There's not too much bespoke coding going on functionally - we created the usual blog and events as well as a simple photogallery, but most of the technical effort went into working out the best way to apply textures and filters to the images so that the admins could upload new content without needing to phaff around in photoshop ( CSS 'backdrop-filter' for the win). One interesting thing got thrown up in accessibility testing; originally we'd created the design using a fixed with typewriter font and even though we'd set a pretty large font size with good contrast that passed our automated accessibility testing, we found that real world users still had difficulty reading it. So we changed that to a more modern and readable slab serif. Testing with real users is always a good move.
    7 points
  15. A while back we had to import a few hundred users into PW from a site we were porting over. I needed to generate new passwords for them that matched our PW password requirements and couldn't find anything super useful so I scraped together a word list and a quick bit of code to spit out a list of reasonable diceware type passwords. Since then it's been surprisingly useful so I've tidied things up a bit and put it on Github in case anyone else could make us of it. There's a demo and Github link at https://millipedia.com/millco-diceware/ It's pretty simple and very Anglo-centric ... and possibly not suitable if you're a secret government agency ... but hey, it might come in handy.
    7 points
  16. But this isn't a solution for touch devices which don't have a hover state, and we all know that touch devices are a big share of internet use. There's discussion in the Invision Community support forums about how to bring back reputation points into the author pane (some of which I can't see but maybe @Pete can)... https://invisioncommunity.com/forums/topic/462326-current-ranks-–-and-–-reputation/ https://invisioncommunity.com/forums/topic/462099-bring-back-reputation-in-userinfopane/ Could we implement that here? Also, it would be nice to bring back custom member titles for those who had them (e.g. Ryan's reiska title): https://invisioncommunity.com/forums/topic/462409-46-how-to-restore-custom-member-titles/
    7 points
  17. This was a site we put together for the department of Arts and Culture at Queen Mary University in London (QMUL). https://conversations.qmul.ac.uk/ QMUL invited artists to converse with academics from across the university: A dentist spoke to a sculptor. A performance artist to a historian. A mathematician to a choreographer... The site needed to showcase not only the work of the artists but also reflect the back and forwards of the conversations which toook place during lockdown and were recorded over Zoom. We ended up implementing templates which allowed the admins to upload various different types of media for each side of the conversion - mostly video clips of the Zoom sessions but also slideshows, mp3 audio files, images and documents. To do this we used a few ProFields fields, most notably Repeater Matrix. We also built a simple events management system for an online Conversation Week event. Other modules we used included ProCache and Page Field Edit Links and Login Persist. On the front end we used PhotoSwipe for the slideshows and Plyr for the embedded audio and video files (mostly to give a consistant look). Oh and the css animated menu icon is from https://jonsuh.com/hamburgers/ - which are really useful (honestly I think I've used them in our last 4 projects).
    6 points
  18. This module implements the website live chat service from tawk.to. Actually the module doesn't have to do much. It just need to inserted a few lines of JavaScript just before the closing body tag </body> on each side. However, the module offers additional options to display the widget only on certain pages. Create an account Visit https://www.tawk.to and create an account. It's free! At some point you will reach a page where you can copy the required JavaScript-code. Open the module settings and paste the JavaScript-code into the field as shown below. Click "Submit" and that's all. Open the module settings The settings for this module are located int the menu Modules=>Configure=>LiveChatTawkTo.
    6 points
  19. HTMX is quite good. $config->ajax won't detect HTMX requests though, so I recommend adding this to your /site/ready.php: // if htmx request, DO NOT use _main.php if(array_key_exists('HTTP_HX_REQUEST', $_SERVER)) { $config->appendTemplateFile = ''; $config->htmxRequest = true; } That assumes you are using the Markup Regions output strategy by the way. Use $config->htmxRequest as needed.
    6 points
  20. Update: Here's a little snippet how to use dynamic navigation items using the NavJSON feature: // in getModuleInfo() 'useNavJSON' => true, // enable JSON nav feature 'nav' => [ [ 'url' => 'contacts', 'label' => 'Contacts', 'icon' => 'users', ],[ 'url' => 'mailings', 'label' => 'Mailings', 'icon' => 'folder-open-o', 'navJSON' => 'mailings-nav', // this will call executeMailingsNav() to get items ],[ 'url' => 'groups', 'label' => 'Groups', 'icon' => 'users', ], ] // and in the module /** * JSON nav for mailings */ public function executeMailingsNav() { $options['add'] = null; // no link to add pages $options['edit'] = $this->mailer()->url."new/?channel={name}"; $options['itemLabel'] = 'label'; // use the label property as item label (default is name) $options['items'] = []; foreach($this->mailer()->channels as $channel) { $data = $this->wire(new WireData()); /** @var WireData $data */ $data->name = $channel->short; $data->label = "New ".$channel->name; $data->icon = "plus-circle"; $options['items'][] = $data; } return parent::___executeNavJSON($options); }
    5 points
  21. FieldtypeDecimal uses InputfieldFloat as its inputfield, and it's the renderValue() method that determines what is shown when a field is not editable. So you could do this: $wire->addHookAfter('InputfieldFloat::renderValue', function(HookEvent $event) { /** @var InputfieldFloat $inputfield */ $inputfield = $event->object; $field = $inputfield->hasField; if($field && $field->name === 'your_field_name') { $event->return = '$' . number_format((float) $inputfield->value, 2); } });
    4 points
  22. According to the specs it should work like this (not tested) $results = $pages->find("title~=word1|word2|word3, title~=word4"); title=x, title=y is AND AND selectors: matching more than one value in the same field There will be instances where you need to say that a specific field matches more than one selector. This is simple, just specify all the conditions you need to match as separate selectors in the same string. For example: height>500, height<=1000 This AND selector matches all pages that have a "height" field greater than 500, and less than or equal to 1000. title=a|b|c, title=y should be the right combination https://processwire.com/docs/selectors/#and-selectors
    4 points
  23. Are you using pagefileSecure? If you do, or otherwise use ProcessWire to send the file, you can change the config to force mp3s to always download using this incantation: $config->fileContentTypes = array_merge($config->fileContentTypes, ['mp3' => '+audio/mpeg']); The + sign in front of the mime type will tell PW to use the header “Content-Disposition: attachment” when sending the file type in question. Cf. https://github.com/processwire/processwire/blob/master/wire/config.php#L632
    4 points
  24. Maybe that's what you are looking for: https://processwire.com/blog/posts/pw-3.0.137/#on-demand-mirroring-of-remote-web-server-files-to-your-dev-environment
    4 points
  25. I've tweaked the default colours (using the handy tool at https://learnui.design/tools/accessible-color-generator.html ) to be as close to the current colours as possible but still hitting AA contrast requirements. Here's before and after screenshots for comparison. I don't think it's too drastic a change... The admin.less changes for that are: /************************************************************** * Primary variables * * Adjusted to hit AA accessibility. * */ @reno-text-color: #354b60; @reno-link-color: #df2b5b; // #e83561; @reno-link-hover-color: darken(@reno-link-color, 10%); @reno-dark-background: #1C2836; @reno-muted-background: #f0f3f7; @reno-muted-text-color: #6f7580; // #8d939e; @reno-muted-text-color-alternate: #577898; // #6c8dae; @reno-primary-background: #008668; // #3eb998; @reno-secondary-background: #e2e9ef; @reno-success-background: #8bccde; @reno-success-color: @reno-text-color; @reno-warning-background: #FFD15E; @reno-warning-color: @reno-text-color; @reno-danger-background: #bc283d; @reno-danger-color: #fff; @reno-alert-background: #ffd; @reno-alert-color: @reno-text-color; @reno-primary-headline-color: #1C2836; @reno-secondary-headline-color: lighten(@reno-primary-headline-color, 30%); @reno-notes-text-color: @reno-muted-text-color; @reno-notes-background: #ffd; @reno-masthead-background: @reno-dark-background; @reno-masthead-link-color: rgba(255, 255, 255, 0.7); @reno-masthead-link-hover-color: lightblue; @reno-masthead-link-current-color: #fff; @reno-masthead-icon-color: #6f7580; // #8d939e; @reno-masthead-search-text-color: #8d939e; // #008668 @reno-masthead-search-background: transparent; @reno-masthead-search-border-color: lighten(#253447, 10%); @reno-masthead-search-focus-background: lighten(#253447, 5%); @reno-masthead-search-focus-text-color: #fff; @reno-masthead-search-focus-border-color: @reno-masthead-search-focus-background; @reno-masthead-search-icon-color: @reno-masthead-icon-color; @reno-button-text-color: #fff; @reno-button-background: @reno-primary-background; @reno-button-hover-background: @global-link-color; @reno-button-secondary-background: @reno-muted-text-color-alternate; @reno-dropdown-background: #fff; @reno-dropdown-color: @reno-text-color; @reno-dropdown-hover-background: #e2e9ef; @reno-dropdown-border-color: #d9e1ea; @reno-dropdown-border: 1px solid @reno-dropdown-border-color; @reno-dropdown-nav-icon-color: #667982; //#97aab4; @reno-page-list-link-color: #7a002b; @reno-page-list-link-open-color: #bb153e; @reno-page-list-icon-color: @reno-link-color; @reno-page-list-link-active-color: @reno-link-hover-color; @reno-page-list-link-hover-color: @reno-link-hover-color; @reno-page-list-action-link-color: #fff; @reno-page-list-action-link-background-color: @reno-link-color; @reno-page-list-action-link-hover-color: #fff; @reno-page-list-action-link-hover-background-color: @reno-link-hover-color; @reno-inputfield-border: 1px solid #d9e1ea; @reno-inputfield-input-background: #f0f3f7; @reno-inputfield-input-border-color: #b1c3d4 #cbd7e3 #cbd7e3 #cbd7e3; @reno-inputfield-select-background: #f0f3f7; @reno-inputfield-select-border-color: #cbd7e3; @reno-form-radio-checked-background: @reno-muted-text-color-alternate; @reno-offcanvas-text-color: @reno-text-color; @reno-offcanvas-link-color: @reno-text-color; @reno-offcanvas-link-hover-color: @reno-link-color; @reno-offcanvas-link-open-color: @reno-link-color; @reno-offcanvas-background: @reno-secondary-background; @reno-offcanvas-search-background: #fff; @reno-language-tab-background: transparent; @reno-language-tab-color: @reno-text-color; @reno-language-tab-current-background: #d2dce6; @reno-language-tab-current-color: @reno-primary-headline-color; @reno-language-tab-hover-background: @reno-muted-background; @reno-language-tab-hover-color: @reno-text-color; @reno-language-tab-empty-color: @reno-muted-text-color; @reno-table-header-color: @reno-muted-text-color-alternate; @reno-table-header-current-color: @reno-primary-background; I think it'd be worth updating to the defaults to something like this - seems an easy step in the right direction.
    4 points
  26. Symprowire is a PHP MVC Framework based and built on Symfony using ProcessWire 3.x as DBAL and Service-Provider It acts as a Drop-In Replacement Module to handle the Request/Response outside the ProcessWire Admin. Even tough Symfony or any other mature MVC Framework could be intimidating at first, Symprowire tries to abstract Configuration and Symfony Internals away as much as possible to give you a quick start and lift the heavy work for you. The main Goal is to give an easy path to follow an MVC Approach during development with ProcessWire and open up the available eco-system. You can find the GitHub Repo and more Information here: https://github.com/Luis85/symprowire Documentation The Symprowire Wiki https://github.com/Luis85/symprowire/wiki How to create a simple Blog with Symprowire https://github.com/Luis85/symprowire/wiki/Symprowire-Blog-Tutorial Last Update 16.07.2021 // RC 1 v0.6.0 centralized ProcessWire access trough out the Application by wrapping to a Service https://github.com/Luis85/symprowire/releases/tag/v0.6.0-rc-1 Requirements PHP ^7.4 Fresh ProcessWire ^3.0.181 with a Blank Profile Composer 2 (v1 should work, not recommended) The usual Symfony Requirements Features Twig Dependency Injection Monolog for Symprowire Support for .env YAML Configuration Symfony Console and Console Commands Symfony Webprofiler Full ProcessWire access inside your Controller and Services Webpack Encore support Caveats Symfony is no small Framework and will come with a price in terms of Memory Usage and added Overhead. To give you a taste I installed Tracy Debugger alongside to compare ProcessWire profiling with the included Symfony Webprofiler So in a fresh install Symprowire would atleast add another 2MB of Memory usage and around 40ms in response time, should be less in production due to the added overhead of the Webprofiler in dev env
    4 points
  27. I can't say that I have a strong opinion here either. Also not sure if I grasp the whole context — when you say "routing" and mention URL segments, does that mean that you create routes automatically based on page structure (I assume so but...) or that there's a separate routing setup for front-end and page structure is only reflected in the data? Or do you mean something different with this? 🙂 This may or may not be related, but one thing to consider is whether you want Symprowire to be "all in", or rather something that can be used only for some parts of the site. Couple of examples from other MVC(ish) solutions: Template Engine Factory hooks before Page::render and replaces the response, but also provides hookable method (TemplateEngineFactory::shouldRenderPage) for preventing it from rendering the page, in which case the site will fall back to the regular rendering flow (whatever that happens to be). Wireframe takes an entirely different approach: instead of a hook ("enabled by default") you need to point templates that you want to render via it to the front controller file via Alternate Template Filename setting (more details in the docs). Essentially it's disabled by default. Wireframe is my pet project and something we've used for our production sites for a while now, so that's what I'm mostly familiar with. I intentionally decided not to use hooks, since I felt it was best to let the developer decide if they want to use Wireframe for everything, just a small part of the site, or something in between. In fact it's possible to skip the MVC structure entirely, and just use Wireframe for its partials and/or components 🤷‍♂️ Template Engine Factory may be a bit closer to Symprowire feature wise, although Symprowire clearly has a much larger scope (and is more opinionated). So not sure if any of what I've said here applies as-is 🙂
    4 points
  28. @Cybermano, I don't understand what you are doing with this line inside the foreach: $boat->barca_results->sort('id', $race); This doesn't seem to correspond to the correct use of either $wirearray->sort() or $pages->sort() so maybe you are getting mixed up with the methods? To go back to brass tacks (you may already know a lot of this but it might be useful for others)... The first meaning of "sort" as it relates to pages is the sort value. This is a column in the "pages" database table. Every page (including Repeater pages) has a sort value and this determines its sort position relative to its sibling pages (assuming no automatic sort has been set on the parent page or template). The sort value starts at zero, and the lower the number is the closer to the top of the sort order the page will be relative to its siblings. So in this page structure... The sort value of "Red" will be 0, the sort value of "Green" will be 1, and so on. In some circumstances you can end up with gaps in the sort values as pages are deleted or moved and that is where the $pages->sort() method can be used to "rebuild" those sort values under a parent. But in 99% of cases you don't need to worry about sort values because PW just takes care of it and you don't have to use $pages->sort() to sort your Repeater items so we can ignore that. You can set the sort value of a page the same as you would an integer field in the page's template: $page->of(false); $page->sort = 123; $page->save(); The second meaning of "sort" is the WireArray::sort() method. When it comes to pages, a PageArray is a kind of WireArray, and a RepeaterPageArray is a kind of PageArray, so this means we can use WireArray::sort() to sort a RepeaterPageArray. The method works by sorting the WireArray by one or more properties of its items. In the case of a RepeaterPageArray this could be something like the "modified" timestamp of the items or it could be a field such as "title". So you could do something like this to sort a field named "test_repeater" alphabetically by title (assuming that the Title field was used in the Repeater): $page->test_repeater->sort('title'); And you can get more advanced by adding a temporary custom property to the items in a WireArray/PageArray/RepeaterPageArray and then using WireArray::sort() on that temporary property. I'll show an example of that in a moment. If you have a page $p that contains a Repeater field "test_repeater" then you can sort the RepeaterPageArray as shown above in your template file and when you output the items in $p->test_repeater they'll be in the sort order you want. But if you wanted to save $p after you sorted test_repeater then it's not enough to just have the items in test_repeater in the right order and then save $p. And that's because PW uses the sort value of each Repeater page to determine the sorting of the Repeater field when it loads it from the database. So to make the sort order stick we need to save the sort value of each Repeater page in the RepeaterPageArray, and to do that we can use an incrementing counter that starts at zero. A couple of code examples... Sort test_repeater by title and save: // Get the page containing the Repeater items $p = $pages(1066); // Turn off output formatting for the page because we are going to save it later $p->of(false); // Sort the Repeater items alphabetically by title $p->test_repeater->sort('title'); // $i is a counter we will use to set the sort value of each Repeater item/page $i = 0; foreach($p->test_repeater as $repeater_item) { $repeater_item->of(false); $repeater_item->sort = $i; $repeater_item->save(); $i++; // Increment the counter } // Save the test_repeater field for $p $p->save('test_repeater'); More advanced sorting using a temporary property: // Get the page containing the Repeater items $p = $pages(1066); // Turn off output formatting for the page because we are going to save it later $p->of(false); // More advanced sorting: sorting by title length // We add a temporary "custom_sort" property to each Repeater item // And then sort the RepeaterPageArray by that custom_sort property foreach($p->test_repeater as $repeater_item) { $repeater_item->custom_sort = strlen($repeater_item->title); } $p->test_repeater->sort('custom_sort'); // $i is a counter we will use to set the sort value of each Repeater item/page $i = 0; foreach($p->test_repeater as $repeater_item) { $repeater_item->of(false); $repeater_item->sort = $i; $repeater_item->save(); $i++; // Increment the counter } // Save the test_repeater field for $p $p->save('test_repeater'); Hope this helps.
    4 points
  29. 10 templates is definitely not going to be a problem. There's no particular number of templates that you should never go above, but I've asked Ryan about this topic in a Pro module forum and he said: ...and in reply to my proposal of a strategy to reduce the number of templates needed in a project... On that particular project I currently have 51 templates and there are no noticeable performance issues.
    4 points
  30. I'll see what I can do about the rep count - in the meantime I've done something someone else asked for (and my older eyes needed) - increased font size on mobile. I haven't gone too far with it but it's a lot better than 13px 😄
    4 points
  31. Thank you all for the insight! This has been super helpful. This community continues to impress me with how helpful and kind everyone is. The more I learn about ProcessWire the more I like what I see! This gives me the direction I need to continue development. I appreciate it!
    4 points
  32. @gornycreative, me and @fliwire are not teaching you how to do your modals. Both Unpoly and htmx are js libraries that help you (amoung other things) to extract a portion of markup that they receive from a ajax requests and paste it where you want it (in a modal). That way you do not need to alter the rendering, but can define which part of a rendered markup you need.
    4 points
  33. I've got some core updates in progress but nothing major committed yet, so we'll save that for next week. But I wanted to briefly tell you about a module I'm working on here, which I plan to eventually put in core. I built it for some needs I've had here, but it will first be released in ProDrafts (so ProDrafts may start using its API), and in ProDevTools too, since it is also a developer tool. It's a snapshot versioning system for pages, but more of an API tool at this stage, kind of like the $pages API var, but for snapshots/versions of pages. It lets you create a snapshot of any page, including its fields and files (including core fields, ProFields, 3rd party fields, repeaters, nested repeaters, table fields with a million rows, etc.). The snapshots can be restored at any later time. Snapshots may also be restored to a different page, such as a new or existing page. In this manner, a module like ProDrafts may be able to use it to manage draft versions even better than it currently can, or at least that's the plan. Though since it's an API tool, my hope is that when/if it winds up in the core, others may be able to use it for stuff we've not thought of yet too. The module is a little different than my previous attempts (like what's in ProDrafts now) in that it does most of its work directly at the database level (and file system level, where applicable), which enables it work without needing to know much about the Fieldtype. Currently it is fully functional, but I have a few less common cases to work out before it's ready for release. Once installed, every page includes a Snapshots fieldset, which can be located in the settings tab of the page editor, or a separate tab in the page editor (configurable). When installed, every page has one, so long as the user has the appropriate permissions. There's a screenshot of what it looks like in the page editor below, but it is very simple at this stage, basically just enough for testing purposes. Every snapshot has a name that is unique on the page. You can overwrite a snapshot just by saving a snapshot with the same name on the same page. So you could for instance have a hook that creates a snapshot named "undo" right before a page is saved (in a Pages::saveReady hook), and in that way a module could add a basic undo capability to the page editor. This is just a simple example though. Thanks for reading, have a great weekend!
    4 points
  34. Ok got it. There needs to be a 5th parameter passed of 1 so that the day selected is the first of the month otherwise it's getting a day that doesn't exist and skips over onto the next month. strftime($monthFormat, mktime(0, 0, 0, $n, 1))
    4 points
  35. Process Images A basic, proof-of-concept Textformatter module for ProcessWire. When the Textformatter is applied to a rich text field it uses Simple HTML DOM to find <img> tags in the field value and passes each img node through a hookable TextformatterProcessImages::processImg() method. This is a very simple module that doesn't have any configurable settings and doesn't do anything to the field value unless you hook the TextformatterProcessImages::processImg() method. Hook example When added to /site/ready.php the hook below will replace any Pageimages in a rich text field with a 250px square variation and wrap the <img> tag in a link to the original full-size image. For help with Simple HTML DOM refer to its documentation. $wire->addHookAfter('TextformatterProcessImages::processImg', function(HookEvent $event) { // The Simple HTML DOM node for the <img> tag /** @var \simple_html_dom_node $img */ $img = $event->arguments(0); // The Pageimage in the <img> src, if any (will be null for external images) /** @var Pageimage $pageimage */ $pageimage = $event->arguments(1); // The Page object in case you need it /** @var Page $page */ $page = $event->arguments(2); // The Field object in case you need it /** @var Field $field */ $field = $event->arguments(3); // Only for images that have a src corresponding to a PW Pageimage if($pageimage) { // Set the src to a 250x250 variation $img->src = $pageimage->size(250,250)->url; // Wrap the img in a lightbox link to the original $img->outertext = "<a class='lightboxclass' href='{$pageimage->url}'>{$img->outertext}</a>"; } }); GitHub: https://github.com/Toutouwai/TextformatterProcessImages Modules directory: https://processwire.com/modules/textformatter-process-images/
    4 points
  36. Great job and write-up @Jonathan Lahijani! Could you expand a bit on the RM based content builder? Maybe even post some screenshots or even videos, if that is allowed by the customer. We had a great conversation about content builders in the beginning of the year. And you are a named expert in the field, so would love to read/see/watch anything more detailed from you.
    3 points
  37. @rsi you can use $pages->sort() to set the sort value of the new page to zero after it is added, and that will make it appear at the top of its siblings but still be manually sortable. In /site/ready.php: $pages->addHookAfter('added', function(HookEvent $event) { $pages = $event->object; // The page that is being added $page = $event->arguments(0); // If the page passes some kind of test if($page->template == 'news_item') { // Set the sort value for the new page to zero (sibling sort will be automatically adjusted) $pages->sort($page, 0); } });
    3 points
  38. If you just want to do this from time-to-time you can add a filter row like this: Or if you want the default limit to always be 50 (or whatever limit you want) then you can add a hook in /site/ready.php: $wire->addHookBefore('ProcessPageLister::execute', function(HookEvent $event) { /** @var ProcessPageLister $lister */ $lister = $event->object; // Only for the "Find" lister if($event->wire()->page->name === 'lister') { $lister->defaultLimit = 50; } });
    3 points
  39. Hi there, My company, Fixate, has been building and supporting ProcessWire sites for a number of years now. I've recently accepted an offer for a position at another company, and as the last dev on the team (the team is now primarily UI/UX), we need to find someone who can assist with client requests. We have clients in Canada, Zambia, and South Africa, so we're comfortable with any timezone you may be in. The projects predominantly have this setup: Dockerised services for quick setup Gulp to automate: builds and file revisioning SSH deployments backups / restorations Some of our client's sites: blu-line.co.za biocarbonpartners.com knowledgehub.southernafricatrust.org We're looking for someone to work directly with our clients when they need assistance. Feel free to contact me at larry U+0040 fixate.it Thanks! Larry
    3 points
  40. @kaz If You put default then $options = array('markerIcon' => 'flag-checkered', 'markerColour' => 'orange', 'popupFormatter' => function($page) { $out[] = "<center><strong>Sub Header</strong></center>"; $out[] = "<center><img src=\"/images/logo.png\" width=\"100\" height=\"100\" /></center>"; // ** NB: Use escaped double quotes if HTML attributes needed ** return implode('<br/>', $out); } ); And yours Main Header will be as link But if you add the parameter 'markerTitleField' then the field with the link will disappear. $options = array('markerIcon' => 'flag-checkered', 'markerColour' => 'orange', 'markerTitleField' => '', 'popupFormatter' => function($page) { $out[] = "<center><strong>Sub Header</strong></center>"; $out[] = "<center><img src=\"/images/logo.png\" width=\"100\" height=\"100\" /></center>"; // ** NB: Use escaped double quotes if HTML attributes needed ** return implode('<br/>', $out); } ); You can see the result. It seems to me that this is exactly what you wanted to get. Without fixing the module codes.
    3 points
  41. I worked on this too. Attached is my modified admin theme I posted somewhere on the forum, but this version is bit modified, I tried to fix some focus issues... admin.less
    3 points
  42. Here is my Caddy 2 config for a PW site: mysite.fi, www.mysite.fi { encode gzip tls my@email.com root * /var/www/mysite/pw file_server php_fastcgi unix//var/run/php-fpm/php-fpm.sock { health_timeout 10000s } @deny_hidden path_regexp /\. @deny_root path_regexp /(CONTRIBUTING|COPYRIGHT|LICENSE|README|htaccess)\.txt @deny_assets path_regexp ^/site(-[^/]+)?/assets/(.*\.php|backups|cache|config|install|logs|sessions) @deny_install path_regexp ^/site(-[^/]+)?/install @deny_config path_regexp ^/(site(-[^/]+)?|wire)/(config(-dev)?|index\.config)\.php @deny_modules path_regexp ^/((site(-[^/]+)?|wire)/modules|wire/core)/.*\.(inc|module|php|tpl) @deny_templates path_regexp ^/(site(-[^/]+)?|wire)/templates(-admin)?/.*\.(inc|html?|php|tpl) rewrite @deny_hidden /denyaccess rewrite @deny_root /denyaccess rewrite @deny_assets /denyaccess rewrite @deny_install /denyaccess rewrite @deny_config /denyaccess rewrite @deny_modules /denyaccess rewrite @deny_templates /denyaccess # global rule try_files {path} {path}/ /index.php?it={path}&{query} log { format single_field common_log output file /var/log/www/access.log { roll_size 50MiB roll_keep 5 roll_keep_for 168h } } }
    3 points
  43. Maybe we should ask @Pete and @ryan if we can somehow add an attention-banner within the forum and maybe even the website for all to see in order to star the project. 700 is so... weird and so low... that sound so wrong!
    3 points
  44. Wow... thanks again @teppo! https://weekly.pw/issue/374/
    3 points
  45. This is brilliant! Thanks for making it available. I made a Manifest module for PW awhile ago and I thought that it would be related to this Inertia module since you are using Laravel Mix for your example. Here is the repo link: https://github.com/lesaff/processwire-manifest
    3 points
  46. I loved Svelte too. For the routing part I mostly use Laravel and now ProcessWire (With the Inertia Module) with the https://inertiajs.com/ Inertia adapters. That simplify greatly the flow and you got the best of backend and frontend 🙂
    3 points
  47. 3 points
  48. u can use unpoly. Layers - Unpoly <a href="/post-page" up-layer="new" up-target='.content'>Open Content</a>
    3 points
  49. Hey @Pete... do you have an idea when we will have the reputation count back? The more I use the forum now, the more I somehow want it back as fast as possible. It's probably weird but... it was such a great indicator for a lot of things here. And no... it's not about my silly amount of reputation points.
    3 points
×
×
  • Create New...