Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/03/2024 in all areas

  1. This week I received some client specifications for project that indicated it was going to need a lot of fields, and fields within fields. There are a lot of tools for this kind of stuff in ProFields, but none that I thought would make this particular project "easy" per se. The closest fit was the Combo field, but with 40-50 or so subfields/columns within each of the "groups", it was still going to be kind of a pain to put together. Not to mention, just a lot of fields and subfields to manage. To add more challenge to it, there was another group of 30 or so fields that needed to be repeatable over any number of times (in a repeater field). I wasn't looking forward to building out all these fields. That scale of fields/subfields is at the point where I don't really want to build and manage it interactively. Instead, I want to just edit it in a code editor or IDE, if such a thing is possible. With any large set of fields, there's often a lot of redundant fields where maybe only the name changes, so I wanted to be able to just copy and paste my way through these dozens of fields. That would save me a lot of time, relative to creating and configuring them interactively in the admin. Rather than spending a bunch of time trying to answer the specifications with existing field types, I ended up building a new Fieldtype and Inputfield to handle the task. Right now it's called the "Custom" field (for lack of a better term). But the term kind of fits because it's a field that has no structure on its own and instead is defined completely by a custom JSON file that you place on your file system. (It will also accept a PHP file that returns a PHP array or InputfieldWrapper). Below is an example of defining a custom field named "contact" with JSON. The array keys are the field names. The "type" can be the name of any Inputfield module (minus the "Inputfield" prefix). And the rest of the properties are whatever settings are supported by the chosen Inputfield module, or Inputfield properties in general. /site/templates/custom-fields/contact.json { "first_name": { "type": "text", "label": "First name", "required": true, "columnWidth": 50 }, "last_name": { "type": "text", "label": "Last name", "required": true, "columnWidth": 50 }, "email": { "type": "email", "label": "Email", "placeholder": "person@company.com", "required": true }, "colors": { "type": "checkboxes", "label": "What are your favorite colors?", "options": { "r": "Red", "g": "Green", "b": "Blue" } }, "address": { "type": "fieldset", "label": "Address", "children": { "address_street": { "type": "text", "label": "Street" }, "address_city": { "type": "text", "label": "City", "columnWidth": 50 }, "address_state": { "type": "text", "label": "State/province", "columnWidth": 25 }, "address_zip": { "type": "text", "label": "Zip/post code", "columnWidth": 25 } } } } The result in the page editor looks like this: The actual value from the API is a WireData object populated with the names mentioned in the JSON definition above. If my Custom field is named "contact", I can output the email name like this: echo $page->contact->email; Or if I want to output everything in a loop: foreach($page->contact as $key => $value) { echo "<li>$key: $value</li>"; } After defining a couple large fields with JSON, I decided that using PHP would sometimes be preferable because I could inject some logic into it, such as loading a list of 200+ selectable countries from another file, or putting reusable groups of fieldsets in a variable to reduce duplication. The other benefits of a PHP array were that I could make the field labels __('translatable'); and PHP isn't quite as strict as JSON about extra commas. So the module will accept either JSON or PHP array. Here's the equivalent PHP to the above JSON: /site/templates/custom-fields/contact.php return [ 'first_name' => [ 'type' => 'text', 'label' => 'First name', 'required' => true, 'columnWidth' => 50 ], 'last_name' => [ 'type' => 'text', 'label' => 'Last name', 'required' => true, 'columnWidth' => 50 ], 'email' => [ 'type' => 'email', 'label' => 'Email address', 'placeholder' => 'person@company.com' ], 'colors' => [ 'type' => 'checkboxes', 'label' => 'Colors', 'description' => 'Select your favorite colors', 'options' => [ 'r' => 'Red', 'g' => 'Green', 'b' => 'Blue' ], ], 'address' => [ 'type' => 'fieldset', 'label' => 'Mailing address', 'children' => [ 'address_street' => [ 'type' => 'text', 'label' => 'Street' ], 'address_city' => [ 'type' => 'text', 'label' => 'City', 'columnWidth' => 50 ], 'address_state' => [ 'type' => 'text', 'label' => 'State/province', 'columnWidth' => 25 ], 'address_zip' => [ 'type' => 'text', 'label' => 'Zip/post code', 'columnWidth' => 25 ] ] ] ]; The downside of configuring fields this way is that you kind of have to know the names of each Inputfield's configuration properties to take full advantage of all its features. Interactively, they are all shown to you, which makes things easier, and we don't have that here. There is yet another alternative though. If you define the fields like you would in a module configuration, your IDE (like PhpStorm) will be able to provide type hinting specific to each Inputfield type. I think I still prefer to use JSON or a PHP array, and consult the docs on the settings; but just to demonstrate, you can also have your custom field file return a PHP InputfieldWrapper like this: $form = new InputfieldWrapper(); $f = $form->InputfieldText; $f->name = 'first_name'; $f->label = 'First name'; $f->required = true; $f->columnWidth = 50; $form->add($f); $f = $form->InputfieldText; $f->name = 'last_name'; $f->label = 'Last name'; $f->required = true; $f->columnWidth = 50; $form->add($f); $f = $form->InputfieldEmail; $f->name = 'email'; $f->label = 'Email address'; $f->required = true; $f->placeholder = 'person@company.com'; $form->add($f); // ... and so on Now that this new Fieldtype/Inputfield is developed, I was able to answer the clients specs for lots of fields in a manner of minutes. Here's just some of it (thumbnails): There's more I'd like to do with this Fieldtype/Inputfield combination before releasing it, but since I've found it quite handy (and actually fun) to build fields this way, I wanted to let you know I was working on it and hope to have it ready to share soon, hopefully this month. Thanks for reading and have a great weekend!
    5 points
  2. I think ProcessWire has a well-estabilshed versioning plan: Ryan is increasing the version every few commits whenever some notable new feature was introduced. And the master version then just follows suit. I think a set release schedule with fixed time intervals is a very bad idea. I have been working with WordPress in the past and they have been notoriously bad at using their fixed minor release schedule. Sometimes a version introduced very important and big features and other times, there was barely anything new but both were minor releases just because the schedule said so. I have only been in the ProcessWire game for almost three years and thus have started out around where version 200 was released. At that time, I didn't look at GitHub too much though. I didn't notice the "slow releases" at all and was mostly influcenced by the forum and the website. For me, they did a good job. As many before me have mentioned, community activity is very important especially for new potential users (and even more to the target audience: fellow developers). This could also be reflected in more activity on the master branch. Finding a good solution might not be the easiest endeavour though. Has there ever been a situation where old versions needed to be patched for some bugs or security vulnerabilities? I haven't seen one yet. I think this mostly stems from the slow master releases which only ever get done when high stability has been reached. So for me, every master release is a "LTS" version, which is a big strength of ProcessWire: I have no reason to ever update a PW website I did years ago. As long as it doesn't get outdated because of external influences (PHP EOL comes to mind). I think using time-based releases like Ubuntu or Windows don't make much sense for ProcessWire. Years give a feeling of outdatedness. This directly contradicts ProcessWire's strengths: It does away with the stability and ease of upkeep arguments. How do you explain to a client that PW 2016.3 is still completely fine in 2024 and doesn't need any updates whatsoever? With operating systems, you want a sense of outdatedness simply because there is much more incentive to update to never versions, e.g. for hardware compatibility or platform support. Why not stick with semver with a few adjustments? One idea is to keep the patch part of the current versions as sort of like a build number which would primarily be used on the dev branch to indicate new features and fixes. And then every master version gets a minor version bump which corresponds to a dev version (indirectly that is). This would then allow for security fix updates down the road. Not that this would be needed much :).
    3 points
  3. I'd like to second this. It would be great if the new/improved admin theme was built with maximum customisability in mind. One use case is so that we can more easily offer a "mostly-frontend" user an admin experience that's radically different to what a superuser or site administrator gets in the uncustomised admin. Another admin customisation issue I've struck recently is when you want to customise markup for InputfieldWrapper. There's InputfieldWrapper::setMarkup() but this is marked as internal and isn't that practical to use because InputfieldWrapper::markup is static. That means any custom markup you set there persists for all InputfieldWrappers that are subsequently rendered, when what I want to do is customise markup for a specific instance of InputfieldWrapper. Edit: pull request When the admin theme is revisited it would be great to ask of each component that's rendered, "Is there an opportunity to make this rendering customisable?"
    3 points
  4. I'd love to see an "officially supported and recommended (and even documented) way" of initializing custom page class objects, discussed and requested by us over the years: https://github.com/processwire/processwire-requests/issues/456 https://processwire.com/talk/topic/30138-page-classes-diving-into-one-of-processwires-best-features/?do=findComment&comment=242737 https://processwire.com/talk/topic/25342-custom-classes-for-page-objects-the-discussion/
    3 points
  5. Obviously I haven’t used this myself I feel like there is some confusion in this thread regarding the storage model? My understanding is that the data in the database looks the same as any other field, ie. each field has its own table with subfields being individual columns. AFAIK that’s how Profields Combo works, which this has been compared to. That would alleviate @poljpocket’s concern about selectors. One would simply use the usual dot syntax. As with all dynamic db schemas the issue then becomes migrating data inbetween schema changes. „Stock“ ProcessWire helps you here by only allowing safe changes through the UI and/or showing warnings if data loss may occur. Such safeguards are presumably absent here, but I guess you’re supposed to know what you’re doing when dealing with code anyway.
    2 points
  6. Very interesting and reading through it, I was also instantly reminded of Mystique. And also, why I am almost never using fields like it. That is because of it's almost complete lack of support for selectors. Looking at your example, I am immediately thinking of problems like this one (people which have an email set, e.g. to filter contacts for a mail send operation): <?php $emailContacts = $pages->find('template=person,contact.email!='); Does your implementation support this? Mystique doesn't and you are stuck with loading everything and then filtering manually once the JSON is decoded.
    2 points
  7. Hello @Andy I have seen this CAPTCHA and it looks good. I have to test it first to see how it works and if and how it could be implemented into FrontendForms. But this is not on top of my priority list. At the moment I am working on an upgrade of the FrontendFormsManager to implement an UI for blocked IPs. Currently this will be handled inside the module config, but I want a better UI outside of the module config. This should help site owners to identifiy and block suspicious IP addresses, so I am working on to include this inside the FrontendFormsManager. But I will keep the new CAPTCHA on my list ?. Best regards
    2 points
  8. Another question: In Mystique, you are able to detect the page requesting the field, and as a result, modify the fields that actually get displayed. This is very useful because it allows you to have one Mystique field but have it "morph" depending on the context. On my sites, I typically only have 1 Mystique field called 'options'. I then assign that to various templates that need it (even specific matrix-types like for my page builder). Then when the field is loaded when editing a page or a matrix-type, I can "build" the field based on what template requested it because the $page variable is available. My 'gallery' matrix-type/page builder block will have fields that are gallery configuration related, my 'video' block will have video configuration fields, but they are all still technically the single Mystique 'options' field. @ryan So in your example of /site/templates/custom-fields/contact.php, is it able to determine what page requested it?
    2 points
  9. @BrendonKoz Looks like Mystique defines fields (subfields?) in a very similar way, in that it is also using the Inputfields settings/API (as an array) to define them. Though looks like the use of the "type" property might be something different, since it is mapping to a constant in the module rather than the name of an Inputfield. Maybe those constants still map to Inputfield names. Mystique looks good, perhaps I could have just used Mystique to solve the client's request! Though admittedly I have a lot of fun building Fieldtypes and Inputfields, and I'm guessing there will be just as many differences as similarities, but glad to see there are more options. @Kiwi Chris The syntax I'm using is just the Inputfields API. Looks like the Mystique field above also uses the same API as well. Nice that there is some consistency between these different use cases. That's good to know. Though in this case it was also that I needed a hierarchy of fieldsets which Combo doesn't support. Plus wanted something a little more lightweight, because there were so many fields and the client just needs the ability to store them and not so much to query them. I don't know if Combo is compatible with the migrations module or not, but always good to know about the options. I usually do prefer to manage stuff in the admin, but this is a case where it just seemed like it was not going to be fun.
    2 points
  10. @ryan What I was thinking looking at your syntax, is that it looks a lot like Rock Migrations syntax. If Combo pretty much does what you need but is too slow defining through the UI with a lot of subfields, if Rock Migrations fully supports Combo, then it would be very easy to define combo fields in code like you've done. Although Rock Migrations is primarily about migrations, it takes a definition in code of the state of fields and templates that looks a lot like what you've illustrated, that's easy to move between dev and live environments, so it's absolutely possible to use it to define fields, and you can be selective about it. If there are fields or templates you want to maintain the traditional way via the UI, then don't include them in the migration definition files. It's not all or nothing. On the other hand, because it works with fieldtypes, if you start out doing things via code, then decide you want to make some tweaks via the admin UI, that's possible, as it displays all the code for a field definition, that you can copy and paste back into the migration file, so it can work both ways. I'm not sure if it needs some tweaks for your use case scenario, but I think if Combo does what you need but is too cumbersome to define via the UI with a lot of subfields, then as long as it works with Rock Migrations, then it would probably be an existing way to achieve something very similar. As always with ProcessWire there is often more than one way to achieve the same outcome. ?
    2 points
  11. Ok, now I get it and that's what I was thinking about how it would work. @Kiwi Chris is right. There is some overlap here. At least it looks quite similar, yet RockMigration goes a different route and creates real fields, templates, and relationships between them aka adds to fields to templates. @BrendonKoz , I never thought about using Mystique that way and create such a big set of fields with it. Learned new things today. Again.
    2 points
  12. See my query here: My solution was to bulid my own module - HannaMigrate. Basically it exports or imports all Hanna codes in a database. It was built to use along with my migration module ProcessDbMigrate, but should operate without it (but not tested). It provides 2 methods exportAll() and importAll() Simple usage: Install the module. Use TracyDebugger console in the source database to: $hannaMig = $modules->get('HannaMigrate'); $hannaMig->exportAll('optional_migration_name'); where optional_migration_name is a name of a related migration, if you are using ProcessDbMigrate. Otherwise leave blank and the code will be in assets/migrations/hanna-codes/. Then use TracyDebugger console in the target database to: $hannaMig = $modules->get('HannaMigrate'); $hannaMig->importAll('optional_migration_name'); (Do this while on the Hanna Codes page, then refresh the page to see the results and any error messages). You could also use the methods in your own code. I may look to integrating it more fully in ProcessDbMigrate.
    2 points
  13. Thank you for all of the feedback! Definitely want to build more e-commerce, but just not in the core. I'm intrigued by what Jonathan mentioned and want to learn more. I suspect it influence the roadmap quite a bit. Would enjoy building an asset manager but since my clients don't need it, I could only build it by self funding it. I don't have the ability to self fund it yet. Agree PW should continue to grow on the framework side in the next major version. I don't know in what ways specifically just yet (feedback welcome), but am stating my agreement. I think we've been on a good path in this regard so far and should keep going / go further. Don't agree that Page objects need more initialization methods, but let's duke it out. ? Agree we could use a new site profile, preferably a professionally designed one. Agree we'll definitely continue improving the admin theme and maybe even add another. Prefer to avoid features that blur the line between content and style or front-end and admin, though there can always be exceptions. The requests for Inputfield/InputfieldWrapper sounded good. Supporting more DB platforms is also on my wishlist, but not sure it can be done in the next year as there are some challenges there. Note: replaced original/longer post with summary/bullet points.
    2 points
  14. Excited to see thoughts about starting work on ProcessWire 4. PHP 8+ bring so many improvements, would be nice to utilize them. My personal pain points and wishlist for ProcessWire: - a global media manager - more official integration of multi site / multi domain capabilities (in my case especially for the one database, multiple roots option) - admin theme improvements: - a permanently visible page tree to quickly jump between pages - more ways to customize it, depending on the applications needs. Like having a predefined place to add a "website select" for multi domain websites. - quick mockup, based on www.clickup.com. Clickup also has a "task bar" where you can put pages that you want to come back to. That's quite handy as well. - from a tech point, some things that could be nice to have, but most likely not feasible and against the philosophy of ProcessWire because it would most likely make the project more bloated: - better utilization of composer, e.g. having the ProcessWire core and admin package as separate composer packages, so a ProcessWire installation would just have a "site" and a "vendor" directory - PSR standards / framework ineropability where it makes sense - some automated tests, at least for the core api @Jonathan Lahijani+1. We're using it for application development and it works very well if there is not too much data involved (with 10,000,000+ pages you'll start to having to search for workarounds to keep things fast, in my experience). Would be nice to hear what would be your ideas for improvement. A more web-application like and customizable backend would be nice for us as well. In some projects we were able to hack and hide everything that was not needed. In other projects we build a custom admin panel. Then a way to render a form for a full template in the frontend would have come in handy several times already.
    2 points
  15. https://hamy.xyz/labs/2024-01_htmx-vs-alpine Quote: "Low-js tools like HTMX and AlpineJS are the future of the web. They allow us to build modern web apps without the bloat of popular SPA frameworks." What perplexity.ai says: https://www.perplexity.ai/search/explain-the-pros-and-cons-of-l-IrCeVWXSTAWsWJEv_GuNIA Let's think forward...
    2 points
  16. Thanks for this topic @ryan! Great to have a chance to look into the future and maybe even influence it a bit. I agree with @Jonathan Lahijani, but we surely need to expand on that. I can understand his point quite well. ProcessWire taught me be a (somewhat) ambitious developer, that is ready for bigger projects. And some of those grew big enough I started seeing the limitations of PW. And though I think that PW might be not the best choice for some projects (bigger web apps, as Ryan himself pointed out before), it can have its sweet spot in between regular CMS and web frameworks like Laravel. I will try to point some of the ways I see to improve PW to move further into that sweet spot. For now I can throw in this one: A better way to build custom user admin area. Reusing existing admin сomponents, but without the need to hide lots of stuff with permissions and hooks. So we could build something like /user-admin with limited functionality, but still using page edit module.
    2 points
  17. Making ProcessWire stronger for full-stack web application development, allowing it to become an unassuming alternative to Laravel and Rails but from the origins as a CMS. ProcessWire is the perfect CMS (there's no doubt in my mind about that), and it's actually already quite good for web application development (both natively and with 3rd party modules), but with some enhancements to make it more "batteries included", enhancing page classes and some tooling, ProcessWire can have its feet in both the CMS and full-stack framework buckets in a way that's perhaps unique. I can elaborate on this further as that sounds a little too generic, but I've been developing a web application with PW for over 9 months (it's a very complicated project and it's replacing an existing, in-production system which makes it even more tricky and high-stakes) and when it's done I can share some ideas. This one enhancement alone moved the needle quite a bit in making ProcessWire more web application friendly.
    2 points
  18. I think the most talked about feature is an asset manager. The drilling down of file and imagefields so that you can choose assets from a global library that have already been uploaded somewhere, instead of having to upload assets multiple times. Actually, the approach using references is the best I've come across so far. The data remains where it was originally uploaded, but is only referenced in a file/image field on another page.
    2 points
  19. I would love to see some kind of a bare bones of e-commerce features in the core, that could help to build a basic small shop directly in PW, without the need of integrating with third party e-commerce systems like Shopify etc. Just thinking out loud ? Have a great weekend!
    2 points
  20. Fridays are always the days when I'm full-time on ProcessWire. Other days I may be doing client work, or ProcessWire, just depending on the week. This week it's been mostly client work. And I just learned that I'll have to be out of the office tomorrow (Friday) for a family commitment. So I'm writing this weekly update today instead, and just sent out Teppo's great ProcessWire Weekly newsletter with ProMailer today (usually it gets sent Friday). Because of this change in schedule, I don't have much new to report just yet. Instead, I wanted to start talking a little about future plans, so here's a few ideas. I think we should get another main/master version out, perhaps by September. Following that, I thought we should focus on ProcessWire 3.1, or maybe it's time for version 4. What would be in this next major version of PW? For starters, we'll finally drop support for older PHP versions and start taking advantage of all that's been added new newer PHP versions (8+). This will involve lots of updates to the ProcessWire core code base, while remaining 100% API compatible with PW 3.x. I thought that would be a good starting point into our next major version at least. In addition, we'll likely be trimming some things out of the core and into separate non-core modules, such as FileCompiler, CKEditor, the two legacy admin themes, and a few rarely used Textformatter modules. Most likely we'll also have an overhaul of this website and some nice improvements to our primary (Uikit) admin theme to accompany the next major version as well. There will be plenty more too, but this is what I've been thinking about so far. Your feedback is welcome. Thanks for reading and have a great weekend!
    1 point
  21. From my perspective this is mostly spot-on @poljpocket. Yet there are a few things I'd like to add here: those of us that are active in the forum, read the weekly posts from Ryan, read weekly.pw from Teppo and follow every last bit... ProcessWire is evolving each day, each week, each month, all the time. YET... the last commit to master was 9-10 months ago, which is a century or two ago in the fast-living webdev-world - mostly due to the JS-sphere. I know a lot of people that look very close at this metric, but unfortunatelly on the wrong branch in this case. I'd love to see (and I personally keep it this way) the master branch as something like an LTS, while dev is more like a stable-rolling-release of some kind. I'd probably even use an unstable branch in some projects, even though there is no branch for it. BUT this isn't about naming, but MARKETING. And the last push on master is really bad marketing for ProcessWire right now. That's all I am saying. It doesn't look good. This needs to be changed. I don't care how, but it needs to be fixed. Fast! I don't care if we use SEMVER, ROMVER, WHATeVER, or any other way of versioning (besides the one from Ubuntu, which is really a bad look in the long run and introduces a lot of stress as there has to be a release no matter what at a specific date). All I need to know is if there are breaking changes or new requirements, like min. PHP 8.x and similar. I won't see (as in recognize) this in the version number and wouldn't even think about breaking changes the moment a ProcessWire 4.2 pops up in my upgrade module. Yeah, sorry... I just click UPGRADE as most of the users out there. Maybe the upgrading process/module needs a few upgrades, tricks, and markers to show and tell breaking changes, changed requirements, and what not. Sure more work for module developers but probably not really. Modules already have all these details like requirements. I'm not that deep into developing but as a user... that would be nice! One more thing... In this thread a lot of things were mentioned but mostly like "I'd like to have this feature and this, and that, and ..." which is fine. I'd support most of that. But I'd like to know and ask: Where do we want to see ProcessWire in 5-10 years? What can I do to support ProcessWire/Ryan more?
    1 point
  22. I think this is the wrong approach. Country is not relevant if we are only talking about language. Many countries have several languages, and each language is used in several countries. In some countries a part of the country uses one language and the other one another language (Belgium for example). From the visitor point of view this is confusing, a visitor thinks in term of language, not country. In terms of implementation you are choosing the more complex solution, if PW is straight forward for managing languages, you'll have to develop a solution over this language management for managing countries.
    1 point
  23. Remember that if you have all your country sites in one installation (without my inputs below), you are stuck with one set of Templates, one set of Fields and one set Languages (PW's term for localizations). From experience I can tell you that the more sites you have and the more different markets have to be reached, the more you will run into problems. Mostly, these will manifest in content only to be available in select regions and not others. I am from Switzerland and you could think, a site here should be in German and then offer a carbon-copy for French and Italian. Sometimes this is fine. For sites with multiple regional target audiences, I was immediately proven wrong though: The french want a banner for their super discount only the store in some location gets and the italians want a blog post which must only be available in their region. Remember, that a ProcessWire instance has one and exactly one default language/localization and all content must be available in this one language in order for the others to work. Now this is one country. You have multiple! Simply because of that, I would most likely use completely indepentent installations for every country. But PW has you covered! Here are some ideas: Building on @wbmnfktr's answer, there is also multi-site support in ProcessWire. This is where you have separate site folders with separate databases but all under one roof. More info here: Multiple site support in ProcessWire CMS. There is also multi-instance support which would allow you to e.g. fetch data from other installations (e.g. other countries for you). More info about this is here: How to use multi-instance in PW 3.x (processwire.com). You can use the multiple-site approach for your country pages. With this, every country has it's own set of Templates, Fields and Languages. They can mostly be the same but don't have to be the same at all. This allows for flexibility and sites to diverge from the "standard" as needed. On top of that, multi-instance would allow you to for example have a central newsroom section which gets displayed on all your sites somewhere.
    1 point
  24. Thanks @Juergen This site is on the list of this forum and it states what I use. your form. If you are interested, your form is here: https://surfdacha.com/en/booking/ Website published here
    1 point
  25. Thank you @Andy If you have a live site online with FrontendForms, you can give me a link to your site and I will add it to the "Live examples" section of the readme file. This is a brand new section so there are only 2 examples there at the moment, but I will add more examples over the time. In this case you get a backlink for free to your site, but I will point it to the page where the form is included.
    1 point
  26. Hi @Juergen There appears to be a useful captcha in modules. Do you think it could be attached to your forms?
    1 point
  27. Seemingly quite similar to @ukyo's solution via Mystique. I have a local SQLite database that is a mirror of an external vendor's data for our event calendar (I use an API to sync their external with our local so that I can more easily integrate items into our website rather than constantly referring to their API). By parsing available data in the SQLite database (and making it available via a local REST URL) to determine options in the field, I can then use the chosen values as a filter to then query/display matching records in the SQLite database. This particular field was explicitly allowed as a RepeaterMatrix Fieldtype, and then added, in my case. My Mystique template: /site/templates/configs/Mystique.calendar.php <?php namespace ProcessWire; /** * Resource: Dynamic Calendar settings field */ return function ($page = null, $field = null, $value = null) { // Get the data to feed possible selection values $audiences = json_decode(@file_get_contents(input()->httpHostUrl() . '/calendar/audiences.php?activeMerge=1'), true); $categories = json_decode(@file_get_contents(input()->httpHostUrl() . '/calendar/categories.php?activeMerge=1'), true); $fields = [ 'event_type' => [ 'label' => __('Event Type'), 'type' => 'InputfieldCheckboxes', 'options' => [ 'events' => 'Library Events', 'meetings' => 'Public Meetings' ], 'required' => true, 'columnWidth' => 33 ], 'limit_days' => [ 'label' => __('Upcoming Days to Check'), 'type' => Mystique::INTEGER, 'min' => 1, 'max' => 60, 'defaultValue' => 1, 'initValue' => 1, 'inputType' => 'number', 'required' => true, 'columnWidth' => 34 ], 'limit_events' => [ 'label' => __('Maximum Events to Display'), 'type' => Mystique::INTEGER, 'min' => 0, 'defaultValue' => 0, 'initValue' => 0, 'inputType' => 'number', 'required' => true, 'columnWidth' => 33, 'notes' => __('Per event type. Leave at 0 for no limit.') ], 'not_found_msg' => [ 'label' => __('Message if No Matches Found'), 'description' => __('This will be displayed if no events match the given criteria. Leave blank for no message.'), 'type' => Mystique::TEXT, 'columnWidth' => 100, 'notes' => __('HTML cannot be used here. Markdown is allowed.') ], 'private' => [ 'label' => __('Include Private (Calendar) Library Events'), 'type' => Mystique::CHECKBOX, 'value' => false, 'showIf' => [ 'event_type' => '=events' ], 'columnWidth' => 33, 'notes' => __('This is not recommended.') ], 'output_style' => [ 'label' => __('Output Styling'), 'description' => __('Choose the presentation style for any events that will be displayed.'), 'type' => 'InputfieldRadios', 'options' => [ 'list' => 'A Simple Bulleted List', 'grid' => 'A Grid-Like Display' ], 'showIf' => [ 'event_type' => '=events' ], 'columnWidth' => 33 ], 'show_images' => [ 'label' => __('Display associated event images?'), 'type' => Mystique::CHECKBOX, 'showIf' => [ 'output_style' => '=grid' ], 'columnWidth' => 34, 'notes' => __('Images are always taken directly from the calendar and cannot be properly optimized.') ], 'fieldset' => [ 'label' => __('Filters for Library Events'), 'type' => Mystique::FIELDSET, 'collapsed' => true, 'showIf' => [ 'event_type' => '=events' ], 'children' => [ 'audiences' => [ 'label' => __('Audiences'), 'description' => __('Only show:'), 'type' => 'InputfieldCheckboxes', 'options' => $audiences, 'defaultValue' => '', 'columnWidth' => 20, 'notes' => __('Leave blank to show all.') ], 'categories' => [ 'label' => __('Categories'), 'description' => __('Only show:'), 'type' => 'InputfieldCheckboxes', 'options' => $categories, 'defaultValue' => '', 'optionColumns' => 3, 'columnWidth' => 80, 'notes' => __('Leave blank to show all.') ] ] ] ]; return [ 'name' => 'calendar_events', 'title' => 'Calendar of Events', 'fields' => $fields ]; }; Which then renders: I could've looped the field generation instead of the values generation, similarly to what Ryan did above, but that wasn't my use case here. Regardless of solution, it's a very handy way to generate fields, options, and values.
    1 point
  28. This approach to defining fields looks not unlike what Bernhard has done with Rock Migrations, although admittedly, in his case they're not subfields. I haven't checked to see if the Combo fieldtype is compatible with Rock Migrations, but if it is then that might be another way of achieving this, with the bonus that Rock Migrations lets you have it both ways; you can define your fields in code or via the ProcessWire admin UI. If Combo isn't currently compatible with Rock Migrations, it would be worth ensuring that it is. I think there's this overlap because I'm not sure if @bernhard uses ProFields, and I'm not sure that @ryan uses Rock Migrations as you each have different workflows, but in this case it might be worth checking out each other's efforts. A couple of options I can think of: Talk to Bernhard about including Rock Migrations in the core. Pros - it's always there. Cons. It's always there, and for simpler sites where people are happy to use admin UI may be unnecessary. Build an empty site profile just with Rock Migrations installed. That way when someone needs to start a new project with this functionality they can get it straight away when they set up a new instance of ProcessWire. Pros - There when you need it, not when you don't. Cons - if you've already set up your site profile and realise you need it can't go back and reinstall profile (but still really easy to install the module from the directory).
    1 point
  29. @Sanyaissues Thanks a lot. That works like magic.
    1 point
  30. Try this @Edward Ver: <ul class="menu-main md:text-[16px] text-[18px]"> <!-- Loop through each child of the homepage --> <?php foreach($children as $child): ?> <!-- Check if the child has sub-children --> <?php if($child->hasChildren()): ?> <li class="menu-item-has-children"> <a href="<?= $child->url ?>" class="menu_link "> <?= $child->title ?> <i class="text-lg icon-chevron-down align-[-2px]"></i> </a> <div class="w-full border-t-2 rounded-md md:w-9/12 sub-menu mega-menu border-rose-600 max-w-[1280px] "> <div class="list-item"> <ul class="grid grid-cols-1 gap-1 lg:grid-cols-3 megamen--seclevel lg:grid-flow-col md:grid-rows-1 lg:grid-rows-11"> <!-- Loop through each sub-child --> <?php foreach($child->children() as $subchild): ?> <li class="w-full"> <a href="<?= $subchild->url ?>"><?= $subchild->title ?></a> </li> <?php endforeach; ?> </ul> </div> </div> </li> <!-- If the child has no sub-children --> <?php else: ?> <li><a href="<?= $child->url ?>"><?= $child->title ?></a></li> <?php endif; ?> <?php endforeach ?> </ul> Or this alternative where the <li> for subchildren and non-subchildren is the same, but we apply different classes based on $child->hasChildren() output. <?php // Get the homepage $home = pages()->get('/'); // Get the children of the homepage $children = $home->children(); ?> <ul class="menu-main md:text-[16px] text-[18px]"> <!-- Loop through each child of the homepage --> <?php foreach($children as $child): ?> <!-- Apply 'menu-item-has-children' class if the child has sub-children --> <li class="<?= $child->hasChildren() ? 'menu-item-has-children' : '' ?>"> <a href="<?= $child->url ?>" class="menu_link"> <?= $child->title ?> <!-- Show dropdown icon if the child has sub-children --> <?php if($child->hasChildren()): ?> <i class="text-lg icon-chevron-down align-[-2px]"></i> <?php endif; ?> </a> <!-- Display sub-menu if the child has sub-children --> <?php if($child->hasChildren()): ?> <div class="w-full border-t-2 rounded-md md:w-9/12 sub-menu mega-menu border-rose-600 max-w-[1280px]"> <div class="list-item"> <ul class="grid grid-cols-1 gap-1 lg:grid-cols-3 megamen--seclevel lg:grid-flow-col md:grid-rows-1 lg:grid-rows-11"> <!-- Loop through each sub-child --> <?php foreach($child->children() as $subchild): ?> <li class="w-full"> <a href="<?= $subchild->url ?>"><?= $subchild->title ?></a> </li> <?php endforeach; ?> </ul> </div> </div> <?php endif; ?> </li> <?php endforeach; ?> </ul>
    1 point
  31. Sadly, it did not work as expected. Sorry for the confusion, but i have added the classes. Your code html output: <ul class="menu-main md:text-[16px] text-[18px]"> <ul> <!-- Loop through each child of the homepage --> <li> <a href="/laser-treatments/" class="menu_link">Laser treatments</a> <!-- Check if the child has sub-children --> <ul class="sub-menu mega-menu"> <!-- Loop through each sub-child --> <li class="menu-item-has-children"> <a href="/laser-trstments/achilles/">Achilles</a> </li> </ul> </li> <li> <a href="/kontakt-oss/" class="menu_link">Kontakt oss</a> <!-- Check if the child has sub-children --> </li> </ul> </ul> The output html should be: <ul class="menu-main md:text-[16px] text-[18px]"> <!-- If the parent has HAS child, it should output this as well. But with the child menu --> <li class="menu-item-has-children"><a href="#" class="menu_link ">Laser treatment<i class="text-lg icon-chevron-down align-[-2px]"></i></a> <div class="w-full border-t-2 rounded-md md:w-9/12 sub-menu mega-menu border-rose-600 max-w-[1280px] "> <div class="list-item"> <ul class="grid grid-cols-1 gap-1 lg:grid-cols-3 megamen--seclevel lg:grid-flow-col md:grid-rows-1 lg:grid-rows-11"> <li class="w-full"> <a class="" href="/laser-treatment/acne">Acne</a> </li> </ul> </div> </div> </li> <!-- If the parent has no child, it should output this --> <li><a href="/Contact-us">Contact us</a></li> </ul> So close...thanks.
    1 point
  32. Wow, The community of PW is awesome. Thank you Sanyaissues. I will try it later and give a feedback. Thank you so much again.
    1 point
  33. Hi @Edward Ver don't worry, we are here to help you navigate PW! Here's an example for the menu you asked for: <?php // Get the homepage $home = pages()->get('/'); // Get the children of the homepage $children = $home->children(); ?> <nav class="menu"> <ul> <!-- Loop through each child of the homepage --> <?php foreach($children as $child): ?> <li> <a href="<?= $child->url ?>" class="menu_link"><?= $child->title ?></a> <!-- Check if the child has sub-children --> <?php if($child->hasChildren()): ?> <ul class="sub-menu mega-menu"> <!-- Loop through each sub-child --> <?php foreach($child->children() as $subchild): ?> <li class="menu-item-has-children"> <a href="<?= $subchild->url ?>"><?= $subchild->title ?></a> </li> <?php endforeach; ?> </ul> <?php endif; ?> </li> <?php endforeach; ?> </ul> </nav> The code wasn't tested but it should work.
    1 point
  34. Client quote: We just want a simple event calendar. Simple, right? We just add a DateTime field! Not really... One DateTime field is not enough, as we might have a date range, like summer holidays. Ok, so we add a second DateTime field? Ok, but what if we want a single full-day event, like one single holiday? And how would we easily query all events that are "active" in one month? The module is a commercial module and can be downloaded here: https://www.baumrock.com/releases/rockdaterangepicker/ Docs: https://www.baumrock.com/en/processwire/modules/rockdaterangepicker/docs/ Note: There's also a Pro Module by Ryan, which you find here: https://processwire.com/blog/posts/date-range-fields/ - For my use case this module was unfortunately not usable, because the daterange picker that Ryan chose does not support time inputs. As this was a no-go for me and I found the library www.daterangepicker.com which does exactly what I need, I went ahead and built that module. PS: When using AdminStyleRock it automatically applies the primary colour to match your admin style 😎
    1 point
  35. A module to work around a few shortcomings of Fieldset and FieldsetPage fields. Not submitted to the modules directory because I'm hopeful that most if not all of this will be handled in the core eventually. https://github.com/processwire/processwire-issues/issues/1953 https://github.com/processwire/processwire-requests/issues/533 https://github.com/processwire/processwire-requests/issues/534 Fieldset Helper Adds some visibility features to fields of type FieldtypeFieldsetOpen and FieldsetPage, and adds a helper method to get the child fields of a FieldtypeFieldsetOpen field. Visibility The module adds support for the following visibility settings to FieldtypeFieldsetOpen and FieldsetPage fields: Open when populated + Closed when blank Open when populated + Closed when blank + Load only when opened (AJAX) * Open when populated + Closed when blank + Locked (not editable) Open when blank + Closed when populated "Blank" in the context of a fieldset means that all the child fields within the fieldset are blank. * The AJAX part of this option doesn't currently work for FieldsetPage. Get the child fields of a fieldset If you've ever wanted to get the child fields that are within a fieldset you will have noticed that the ProcessWire API doesn't provide a direct way of doing this. Although they appear indented in Edit Template, the child fields are actually all on the same "level" as the other fields in the template. The module adds a FieldtypeFieldsetOpen::getFieldsetFields() method that you can use to get the child fields of a fieldset for a given page. Example: $field = $fields->get('my_fieldset'); $template = $templates->get('my_template'); $fieldset_fields = $field->type->getFieldsetFields($field, $template); First argument: the fieldset Field, i.e. a Field whose type is an instance of FieldtypeFieldsetOpen (this includes FieldtypeFieldsetTabOpen). Second argument: the Template that the fieldset field is part of. Return value: a FieldsArray of child fields. If there is a nested fieldset inside the fieldset then the child fields of the nested fieldset are not included in the return value, but of course you can use the method again to get the child fields of that fieldset. https://github.com/Toutouwai/FieldsetHelper
    1 point
  36. @ryan reading your reply makes me realise you are such a master of your craft, but you can't take all this on by yourself to grow the project. Rather than the community telling you what they want, tell us how we can help you.
    1 point
  37. So I had to do this one recently - develop a new theme on a busy site so the staff could test it out with their live data and the solution was to add this into site/init.php: if ($user->isLoggedIn() && $user->new_site_toggle == 1) { $config->urls->templates = "/site/tailwind/"; $config->paths->fieldTemplates = dirname(__DIR__) . "/site/tailwind/fields/"; $config->paths->templates = dirname(__DIR__) . $config->urls->tailwind; $modules->AdminThemeUikit->logoURL = 'site/tailwind/images/logo-white.svg'; $config->AdminThemeUikit = [ 'style' => '', 'recompile' => false, 'compress' => true, 'customCssFile' => '/site/assets/admin.css', 'customLessFiles' => ['/site/tailwind/styles/admin.less'], ]; } You might not need all that code but basically there was a checkbox field for certain users called "new_site_toggle" where they could login and toggle the new templates on and off and the template files just lived in /site/tailwind/ . "fieldTemplates" is for RepeaterMatrix template files in case anyone is wondering about that one. The Admin Theme config stuff at the end of my code above was just because I like to customise the colours etc in the admin theme, plus in this case it helped reinforce which version they were currently about to view on the frontend. I think I also added a toggle button and some jQuery to the frontend to make toggling whilst viewing the site a one-click process. Honestly the only problem with this approach was the new theme having different fields for some templates so old stuff had to live alongside new stuff, but as content was being updated all the time and I didn't really have time to do it any other way. In hindsight using some of Bernhard's modules would have helped as I ended up doing far too much dev on the live site instead of syncing changes ?
    1 point
  38. Something that I might find useful would be database abstraction so that it's possible to use more than one database engine. mySQL/MariaDB works fine in the majority of cases, but there are times where licensing or functionality means that an alternative database engine would be preferable. The two that I have an interest in are PostgreSQL and Microsoft SQL Server with each of these having scenarios where I find them a better fit than mySQL/MariaDB. Although not something that would result in a new version, improved documentation is another big one. Lots of great features have been added to ProcessWire over the years, but some of them lurk here in forum posts, or PW Weekly, rather than having everything in the main documentation site. Same applies for ProFields. It would be nice to have all documentation in one place.
    1 point
  39. No question, ProcessWire is fabulous for developers and the suggestions above would make it even better. Customers who are not developers are increasingly giving me feedback about how unintuitive the backend admin/editor is, especially now with the proliferation of DIY pagebuilders. Clients don't understand or care about the consequences. They care about not having to learn code to easily update their sites. They want the backend to look similar to the frontend, the convenience of doing it themselves without having to pay a developer. Too bad if the site doesn't work on all screen sizes, light/dark modes, isn't accessible, the home page looks like a ransom note, whatever. They genuinely don't like the default PW admin UI/UX. Pagegrid and RockPageBuilder modules are leading the way to solve this issue. Kudos to both developers BUT the modules are premium while a WP site gives customers basic WYSIWG page editing out of the box. My vote is to overhaul the admin UI/UX to make editing pages more WYSIWIG.
    1 point
  40. Would be great to see .env support. I think this base change would level up ProcessWire and make it an increasingly viable application framework that fits into modern workflows. I think this would be a great idea. It would greatly help module development where modifying or appending behavior to existing elements is needed. I could see that having been useful when developing my Fluency module. I'll throw a thought in about multi-site capability after considering multi-tenancy for a Laravel project using a module. May be a nice feature but if there's a tradeoff for future features and development speed due to maintenance overhead, both for ProcessWire core and modules, it may not pencil out. I know it's not apples to apples, but creating two sites and a private API between them has worked for me in the past.
    1 point
  41. This module provides Captcha functionality to ProcessWire. This specific captcha uses a puzzle that has to be solved by pulling the slider into the correct position. In contrast to other graphical captchas, this captcha also verifies the result on the server side. No jQuery is required. Only PHP and JavaScript. After module installation the source code in the page has to be modified as described in the following 3 examples. Example 1 This example shows, how to use the captcha with a form-submit and the captcha on the submit-button. Insert a onclick-listener in the button-tag: <button onclick="javascript:captcha('testform');return false;">Submit</button> Add the JavaScript: <script> function captcha(form) { slideCaptcha.onsuccess(function () { document.getElementById(form).submit(); slideCaptcha.hide(); slideCaptcha.refresh(); }); slideCaptcha.init(); slideCaptcha.show(); } </script> The form is not submitted by clicking on the button. Instead, the captcha is displayed. If the captcha has been solved correctly, the form is submitted. Check again on the server side, whether the captcha has really been solved: <?php session_start(); if ((isset($_POST['send'])) && ($_POST['send'] == '1')) { if ((isset($_SESSION['SlideCaptchaOk'])) && ($_SESSION['SlideCaptchaOk'] == 'ok')) { unset($_SESSION['SlideCaptchaOk']); echo '<p style="color:lime">Form submit received: Captcha solved</p>'; } else { echo '<p style="color:red">Form submit received: Captcha NOT solved.</p>'; } } ?> Example 2 This example shows, how to use the captcha with a form-submit and the captcha on a checkbox. Insert a onclick-listener in the checkbox-tag: <input id="id_checkbox" type="checkbox" required="required" onclick="javascript:captcha('id_checkbox');return false;" /> Add the JavaScript: <script> function captcha(checkbox) { slideCaptcha.init(); slideCaptcha.show(); slideCaptcha.onsuccess(function () { document.getElementById(checkbox).checked = true; slideCaptcha.hide(); slideCaptcha.refresh(); }); } </script> By using the required option inside the checkbox-tag, the form can only be submitted when the checkbox is checked. By clicking on the checkbox, the captcha is displayed. If the captcha has been solved correctly, the checkbox will be checked and the form can be submitted. Check again on the server side, as described in example 1, whether the captcha has really been solved. Example 3 This example shows, how to use the captcha with a hyperlink. Insert a onclick-listener in the hyperlink-tag. Also move the href link into the JavaScript-function: <a href="" onclick="javascript:captcha('Example3.php');return false;">DOWNLOAD</a> Add the JavaScript: <script> function captcha(file) { slideCaptcha.onsuccess(function () { window.location.href = file; slideCaptcha.hide(); slideCaptcha.refresh(); }); slideCaptcha.init(); slideCaptcha.show(); } </script> The captcha is displayed by clicking on the hyperlink. If the captcha has been solved correctly, the JavaScript will redirect to the specified location. Check again on the server side, whether the captcha has really been solved and deliver the content: <?php session_start(); if ((isset($_SESSION['SlideCaptchaOk'])) && ($_SESSION['SlideCaptchaOk'] == 'ok')) { unset($_SESSION['SlideCaptchaOk']); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="Example3.php"'); readfile('Example3.php'); die(); } ?> Module settings The settings for this module are located in the menu Modules=>Configure=>CaptchaSlide. Filename Filename which must not exist in the root directory and also not represents a page. The filename must be also changed in the captcha.js. The resolving URL receives the information from the client side JavaScript. Tolerance Specifies a tolerance in order to offer better user experience. A tolerance of 3 means +- 3 pixel tolerance (3 recommended). Logging Logs unsolved and solved Captcha attempts in the ProcessWire system logs. Pages The JavaScript and CSS for the Captcha will be included into the following pages. Photos All photos provided by unsplash.com. As described on their website, all photos, offered on their website, can be used for free for commercial and non-commercial purposes: Link to module directory: https://processwire.com/modules/captcha-slide/ Link to github.com: https://github.com/techcnet/CaptchaSlide
    1 point
  42. Hi everyone, We have a new module for you: the UpdMostViewed module. It's an addition to your ProcessWire site that enables you to track page views and deliver a list of your most visited pages within a given time range. This data is particularly useful for creating frontend features like a "Most Read Articles of the Week" widget. Installation You can choose to: Head into your ProcessWire backend, go to Modules > New and search for the Module UpdMostViewed. Get the module directly from the latest releases on our GitHub repository. If you're using Composer for your project, you can add the module by running the command composer require update-switzerland/updmostviewed in your project root directory. Once downloaded, you can install the module via the ProcessWire admin. Configuration The UpdMostViewed module provides you with a variety of configuration options. You can exclude certain branches, specific pages, certain IPs, restrict counting to specific templates, define which user roles to count, ignore views from search engine crawlers, and more. Moreover, you can also customize the time ranges for the "most viewed" data. Links For more detailed information on usage, updates, or to download the module, please visit our GitHub repository and check out the module in the Module Directory.
    1 point
  43. My suggestion would be to add a native global media manager and native multidomain support Media Manager: - Global management of images (also SVG) and Documents (e.g. PDFs) with a decent UI, Preview-Thumbnails, the possibility to organize the assets in folders, etc. - A field to reference those assets, with a usable UI and the possibility to define starting folders, e.g. having a field which only allows to select from a folder with employee portraits, etc. - References should be managed automatically, so one can't delete an image which is still referenced anywhere - If an image is not referenced anywhere anymore, there should be a dialog which asks, if one wants to delete the asset OR there could be a cleanup feature to find and delete unused media items - and so much more ideas, but the global management and the reference field with visual image preview in a clear UI would be great Multidomain Support: - Manage multiple Websites with different domains within one ProcessWire installation, with optional multilanguage support - Every website has a root parent page in the page tree, where everything is defined: domain name, language, etc. - Internal links will be managed by ProcessWire, so you can link between the domains. ProcessWire would determine if the links have to be prefixed with the domain name automatically - The root parent pages will be fully abstracted away, e.g. their page names won't be applied to urls I think that we really would need a native implementation of those features. Unfortunately, I don't have the time or expertise to develop them myself and make a PR, but I would like to add them to the wish list. And if they would be implemented, I would be happy to contribute ideas, feedback and provide beta testing.
    1 point
  44. Before I find time to add my very own wishlist let's not forget the PW requests repository
    1 point
  45. hi @Juergen! Thank you for you very fast answer, always! I was about to edit my comment as I got some progress, but yours feels a lot more coherent; I will add my previous solution below in case it helps someone to get to your answer ? $upload_path = $config->paths->assets.'files/'.$page->id."/"; foreach($form->getValue('fileupload') as $filename) { $pathname = $upload_path . $filename; $p->of(false); $p->images->add($pathname); $p->save(); unlink($pathname); } Thanks again!
    1 point
  46. It also took me a while to understand drupal. In a nutshell: A template is called content type and instead of pages there are nodes. These nodes can be transformed into a page structure via a navigation module. The templating is also somewhat difficult and the structures are predefined. The advantage is probabely that the editor can create many things in the backend himself (e.g. with the views module). However, it is anything but intuitive or easy to understand and learn.
    1 point
  47. Hi, I know this module have not changed since many years, but could I suggest to add a description for each Hanna code? I come back to my setup page and have some codes that I didn't update since years and I don't know why/where they used through my website. I would like to have written a small description. Yes, you could tell me I should have written comments in the code itself, and it's what I would do starting from now... ? But something on the setup page will be faster to read. Thanks!
    1 point
×
×
  • Create New...