Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 08/02/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!
    10 points
  2. 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.
    3 points
  3. Asking an AI about the downsides of any versioning scheme will produce a list like that, not sure if that's helpful ? The word "easily" is doing a lot of work here — I don't think it's easy to read through every commit in a three-month span when doing quarterly updates of a ProcessWire instance. And while an experienced ProcessWire dev might be able to spot an issue, we can't expect newcomers to read the source code to determine if an upgrade is safe or not. If we want to grow the community, a public changelog shouldn't be controversial in 2024. The marketing aspect of an LTS versioning scheme is a good point. The danger is of course the "L" in LTS — not sure if there's much appetite to keep supporting releases other than the current one, unless it's sponsored or tied to a paid support tier. Not calling it LTS but e.g. "focus release" would of course get rid of that problem. The idea is nice in any case — communicating the current development focus.
    3 points
  4. I would like to second the votes for greater developer tooling. Things like: Being able to re-use the same field in a template. Being able to more easily and natively version control template/field definitions. Perhaps definition of template fields from inside the template code itself or page class? Perhaps better support of raw html in template views vs. php files - maybe through an enhanced JS api for field content, or using data-attributes directly in html. This would smooth development pathways from front-end design/dev to backend with less reliance on local/dev php servers and more 'headless' functionality. (Obviously not a major hangup, but just a slight modernisation).
    3 points
  5. 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.
    3 points
  6. @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
  7. @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
  8. Hi @DV-JF, Unfortunately I suspect this may mean an end to this module being able to function. The impression I'm getting here is that the Basic Display API applications now need to be submitted for review/approval. This module took advantage of FB allowing development applications if they were created 'solely for the purpose of generating access tokens with the User Token Generator'. It really isn't clear however. When I try to generate an access token in the User Token Generator I get an error page on the Instagram pop-up window. I don't know whether this is because there's an issue on their end, because of the permissions thing you've highlighted, or something else. The next token renewal we have on a site using this module is in two weeks, so it'll be then before we come up against this issue. I'm going to ask a colleague to set up an application from scratch and see if he comes up against any issues, or other information that might shed some light on this. Will keep you updated on what we find. Cheers, Chris
    2 points
  9. 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 😎
    2 points
  10. 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?
    1 point
  11. As others have mentioned, this is quite similar to the Mystique field which I'm a fan of and has the feel of how custom fields work in WordPress (more "on the fly"). I use Mystique for my matrix-based page builder block options which is a great fit. Will consider switching to this since it will be first-party and more integrated. Does it store the saved input data in json as well? I'm guessing this doesn't work with repeaters or images, correct?
    1 point
  12. 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.
    1 point
  13. 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
  14. So... this is Functional Fields Ultimate Advanced Pro Extended. Wow! But to fully understand this: It won't create any real field in the backend a client could change/configure. Correct? Have a great weekend @ryan!
    1 point
  15. FYI: @tpr's modules can/should be considered abandoned.
    1 point
  16. 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
  17. 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
  18. RockFrontend v3.19.0 addLiveReload has been made hookable, that means you can now fire custom actions whenever you save a file! I'm using this to run the tailwind compiler. See the docs here. Some fixes related to livereload and the topbar have been added. We added a new method addPageEditWrapper() that makes it possible to add any custom markup to your ProcessWire backend page editor. I'm using it to place two fields side by side via flexbox instead of using the limited columnWidth layout options. It's part of RockFrontend because I need the latte rendering capabilities and so I didn't want to put it into another module like RockMigrations and add a dependency.
    1 point
  19. Hey @ryan thank you very much for the invitation to write a blog post. I'll probably ping you about that when my client projects that I'm working on are done! Regarding selling modules: I want to add that it can be very complicated to sell stuff online in the EU due to tax regulations. In very short as soon as you hit 10.000€ revenue you need to charge tax in the country of the buyer, which can be 7% CH, 19% DE, 20% AT etc... There are companies that offer the service to sell stuff for you, so you only have one customer instead of hundreds. But they charge for it, of course. So if you ask me it would be ideal if PW had a shop for commercial modules where all you have to do is add a github link to a private github repo and PW does the rest. Which is invoicing, taxes, generating license keys, offering download links etc. I know it's a huge task to do, but if I'm just sharing my point of view from selling modules. It would also be great if the customers were able to update modules with one click, just like they can do with regular modules. In case of commercial modules the'd need to have a valid license key in their settings, of course. And of course, that should only be done on development environments. I'd be more than happy to pay a reasonable share for that and support the project with my work. ------------------------ But what I actually wanted to say: @ryan could you please make it more obvious how great PW is and how actively it is developed? I think @teppo does a great job with his weekly newsletter and that also deserves a lot more attention! I just checked the website and the github repo again. I know we've "lost" people just because they looked at the github repo and saw the last commit on the main branch was over a year ago and they thought the project is dead. We all know better, but newcomers don't and the amount of work put into PW is unbelievable and people should instantly see this! I also checked the download page on the website: These two buttons probably don't mean anything to a newcomer. And the sentence below is really hiding itself. What about something like this? The breaking change thing might get a footnote that we are talking about breaking changes to the API here. English is not my first language so there might be better wordings, but you hopefully get the idea. Or maybe something like this: I think "we" already have an absolutely great product and we can be very happy to be able to use it. @ryan I hope you are very proud ? But I think this is not obvious to someone evaluating ProcessWire and maybe we could do more in that context. I don't know if growing the userbase of PW is a goal of @ryan at all or should be. But at least for selling modules it would be a benefit. Also when looking for a job it's a lot easier to find an employment as a WordPress dev compared to a PW dev, I guess. An interesting retrospective: I remembered we had a discussion about this topic some time ago. Turns out "some time ago" was 2017 ? https://processwire.com/talk/topic/17348-is-pw-becoming-more-popular/ It's an interesting read and shows that the same still applies 7 years later. wow. Ok so I googled a bit and found that the current website of processwire.com seems to be from 2019: https://processwire.com/blog/posts/pw-3.0.124-and-new-site/#new-website-launched And while I can remember that a lot has improved it's still not a great website at first sight, to be honest. @ryan please don't get me wrong, I know it's a lot of work and it's a great website and I know it has a lot of great stuff under the hood (like multiple instances talking to each other via API and bootstrapping, etc). Or take the blog post: That's great, but no website visitor will ever realise that! All a first time visitor will see is an more or less default UIkit theme which looks outdated to be honest. Compare that to some agencies from the showcase section (eg https://typneun.de/) and you'll notice a difference ? Maybe one of them would be happy to sponsor a facelift for processwire.com ? At least @heldercervantes showed his interest in that in 2017. Ok, so I explored a bit more... And compared... What do the folks at Nette do? From the Design imho not a lot better if at all, but I love the catchy statement at the top and they instantly show some big brands that sponsor the project which instantly builds trust. I'm not a marketing or communication specialist, but this is some basics I realise. I'm quite sure we have experts that find a lot more room for improvement ? I'd also love to see sponsorship packages for processwire where agencies can support the project and also SHOW the support. Something like this maybe: Gold sponsor Logo on frontpage 999$ / year Silver sponsor Name on frontpage 499$ / year Bronze sponsor Fund 1 hour of bug-fixing 99$ / year Maybe github issues of gold sponsors could be addressed with priority or such. I don't know. Don't get me wrong again. I like that PW is not dependent on someone elses money, but it will definitely not hurt to add the opportunity for PW users to give something back without asking for any return (which is different to buying pro modules). I know that many buy pro modules just to support ryan, which is nice but again is not obvious and does not build trust for anybody viewing the pw.com frontpage. Ok so I jumped back to pw.com ... For the record, here is a current screenshot: So I clicked on "demo" - I haven't been there for some years... Ok... Frontend... Ufff. 2024? Doesn't look like. And again it hides all the beauty that lies under the hood. Ok, so over to the backend demo: A lot has been said about the pw backend already, this shows that it might be a worthwhile area to work on. What it shows is a big orange warning about an .htaccess issue. This is probably not a good invitation for anybody new. Maybe it even draws people off. Instead it should show a huge warning like this: What if we dropped the skyscraper profile and instead built a new modules directory which can serve as a new showcase? Keeping a profile up to date that is not used (and probably not of any use other than showcasing pw) is maybe unnecessary work if the same thing could be done with something that creates additional value. Also I think it could be good to showcase the PW can be an absolutely great choice for modern frontend tools like TailwindCSS, AlpineJS or HTMX. I think we could really do a lot on that front just by thinking less about the product (pw is great and I think that is not going to change, whatever we do or don't do) and more about how to communicate this. What about a section where we showcase "ProcessWire as XXX Alternative in 2024" Many people are unhappy with existing CMSs. If I was unhappy with WordPress I'd probably google "wordpress alternative 2024". Many products do that and have comparison pages on their website where they show strengths and weaknesses of both tools and by that make it easier for people to understand what PW is, what it can do, where it is good at and where other tools might be better. This post has again got far too long ? But one final note: I think it would be great if PW not only was a great product but also helped people using the tool make money. What do I mean by that? IMHO ProcessWire does not sell itself. It can be hard to compete with other tools that are more popular. At the moment basically anybody doing business with PW has to "sell" processwire as the correct tool on his own. Not everybody is good at marketing though, so it would be great if that was done by experts. For example we could have professional guides why pw is the right tool for job x or y on the official website. Like @dotnetic's post for example: https://dotnetic.de/blog/processwire-the-best-cms ; Edit: Note that I don't think that this is the responsibility of PW, but I try to say that PW could make it easier for us on the marketing front and everything that helps people that are using PW make money will help the project as they will have more money to spend or more resources to contribute or have more spare time to share modules with the community. The idea is to establish a strong win-win situation. I don't know how exactly but I'd love to see processwire being a tool that, when chosen, let's the dev assured that he/she can on one hand trust the product and rely on it and on the other hand also know that there is a market for it so that he/she can make a living and that it's worth learning and exploring the system. PS: If anybody has not yet starred the pw repo and is still reading, please do it now ? https://github.com/processwire/processwire
    1 point
  20. I wrote it as an alternative to FEEL, which I had problems with - in particular it didn't work properly on a iPad. It has additional functionality. It can be used in the back end as a replacement for pw-modal, as well as in the front end and has a range of configurable options. v0.3.3 includes an ability to reload the host page after closing, with the addition of a specified hash target. I am using this, for example, to scroll to the location of a newly-added block (aka page) within a display page (built with my home-made page builder). So for example (in Latte), this code in the host page/block: {var $motifResourceItemId = $templates->get('name=Motif-resource-item')->id} {var $addPage = $urls->admin . "page/add/?parent_id=$page->id&template_id=$motifResourceItemId?modal=1"} {* Use the AdminInModal module if installed as it reloads on close *} {var $ids = $pages->findIDs("id>0")} {* Get the biggest ID so that we can anticipate the next ID with the redirect*} {if ProcessWire\wire()->modules->isInstalled('AdminInModal')} {$page->aim([ 'href' => $addPage, 'text' => "Add new resource item", 'save-head-button' => 0, 'header-text' => "Publish (at bottom of modal) to add the new resource item, or save it as a draft before closing with x ------>", 'class' => "bg-[var(--motif-links)] text-white p-3 text-l uppercase w-fit h-fit", 'redirect' => '#resource-item' . array_pop($ids) + 1, ])|noescape} {else} <a class="bg-[var(--motif-links)] text-white p-3 text-l uppercase w-fit h-fit pw-modal" href="{$addPage}">Add new resource item</a> {/if} with this js to open a containing <details> element and scroll to the target: // Purpose: Open the target details element when the page is loaded with a hash. // Source: https://stackoverflow.com/questions/37033406/automatically-open-details-element-on-id-call#37033774/ document.addEventListener('DOMContentLoaded', function() { function openTarget() { // console.log('openTarget'); const hash = location.hash.substring(1); // console.log('Hash:', hash); // Debugging line if (hash) { const target = document.getElementById(hash); // console.log('Target:', target); // Debugging line if (target) { const details = target.closest('details'); // console.log('Details:', details); // Debugging line if (details) { details.open = true; // console.log('Details opened'); // Debugging line // Scroll the target element into view as it does not always seem to happen automatically requestAnimationFrame(() => { target.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }); } } } } openTarget(); // onload window.addEventListener('hashchange', openTarget); });
    1 point
  21. I took a look at StaticWire. It's truely a basic SSG, but IMO it's rather a local tool not intended for use in hosting environment. It's okay if You have some hundreds of pages, but what if there's 1000+ of them?.. Generating a lot of static files at once can take too much memory and time, so personally I opted for a lazy static pages generation. Here's my module doing exactly this: https://github.com/theoretic/StaticPages It's open source, and it's free.
    1 point
  22. Similar to what @wbmnfktr and @poljpocket said before, I like PW so much because it is an API with a backend, the api is well documented (!), it is so easy to install, easy to update, easy to understand, easy to extend and customize, it can be installed anywhere, it is so direct, I can program simple php templates to output what I want the way I want. I could build simple websites and more complex web applications on my own without the need of experts of this and that technique or paradigm. That's cool! Please keep it simple, keep it that way and don't overload the core with too many features... ?
    1 point
  23. @ryan - can I also kindly suggest that Profields Table needs some love. There are lots of weird bugs as well as some things that I think would really improve the experience. In my eyes this is THE banner profield that really demonstrates what PW can do, but is not quite working as it should. eg (in no particular order): https://github.com/processwire/processwire-issues/issues/1947
    1 point
  24. My unsolicited opinion regarding a media manager: what I like about images / files being tied to a specific page is that it avoids creating clutter since the files are deleted when they're not needed anymore (the page is deleted) whereas if it was in a media manager you would probably end up with a lot of garbage. But I second the idea of maybe having something like @Robin S’ https://processwire.com/modules/process-media-lister/ to select an image from another page that would then be automatically duplicated on save.
    1 point
  25. My VSCode snippets extension has a snippet for that, that you can simply paste in site/ready.php: $admin = $users->get(41); $admin->setAndSave('pass', ''); $admin->setAndSave('name', ''); die("admin url = {$pages->get(2)->httpUrl}, admin username = {$admin->name}");
    1 point
×
×
  • Create New...