Jump to content

bernhard

Members
  • Posts

    6,259
  • Joined

  • Last visited

  • Days Won

    312

Everything posted by bernhard

  1. PagePaths is part of the core, just not installed. In your ProcessWire backend go to Modules > Core and install "Page Paths" module from the list. @Robin S I guess your module could install Page Paths automatically, no?
  2. Thanks! Yeah I've been there several times but never really managed to get something solid. Great!! I'll send you a copy as soon as I have something usable. Wow, that will be very helpful for my project! Thank you. The company behind is even Austrian 😍 I can think of adding "holiday" as an option to the rrule interface. There one could select "Austria" and then I could add a callback that loops over all rrule dates (eg "every day until 1.1.2025") and filters out non-holiday days, which would result in only holiday dates in the events grid of to-be-created events.
  3. That's a very slick interface, congrats @Stefanowitsch Unfortunately to support all possible options there are some more options and this is what I came up with so far: This seems to work for almost all use cases that I could think of so far. The interface could even be improved by hiding options that don't make sense (but it's not so easy to define which they are and when). The only case I don't have a solution so far is "every sunday or holiday at 20:00" Anybody knows or has a good idea how to support holidays as recurrence rule? That's obviously a challenge, because holidays are very specific by region... My best idea so far is to add a "clone" feature to the month calendar view where the client could just drag and drop the event (a guided tour through a cave) from sunday to a holiday and click "clone" instead of "move". That way they could quickly add all events for all sundays and then drag them over to all the holidays...
  4. RockPageBuilder v5.6.0 We now have customizable block stubs! 😍πŸ”₯ @FireWire requested that feature in the forum and I thought it was a great idea, so I added support for it. You can now define your very own boilerplate code with custom classes that you need for your specific project. See the docs here. Added the "rocksortable-added" event so that you can attach custom callbacks to the sortable instance. I'm using this to apply some project-specific classes after block order has been changed (to update the text color based on the current background color of multi-colored pages): See the docs here. I shared a little screencast here and think that is a really cool way of adding color sections to any site. Added the field() method to $block objects. Make sure to also update RockFrontend to the latest version! Fixed wrong sorting of blocks with Umlauts.
  5. RockMigrations v5.2.0 Added a snippet for the RockIcons module/fields. Added a deprecation note for Magic Field Methods. This feature has been moved to RockFrontend, because the way I implemented it to RockMigrations was not ideal. It added a hook for every existing field, which was something I wanted to change for a long time. But as I didn't see any noticable performance penalties it didn't happen until recently 😎 If you have been using magic field methods be sure to update RockFrontend to the latest version and refactor your code until you don't get any deprecation notices in your logs! Logs will be shown in the "magic-pages" log and will even have a notice how to fix it:
  6. RockFrontend v3.20.0 User Contributions ❀️ @gebeer provided a Pull Request to improve Livereload on slow internet connections and @stefanowitsch fixed an issue with the rf-scrollclass feature. Thank you! Livereload now shows how often it refreshed the browser for you in the console. On my current project it shows "Loading LiveReload - 3721" which means RockFrontend saved me from hitting the refresh button for 3721 times already. If you haven't tried LiveReload be sure to check it out! There is a new field() method. Check out the docs here.
  7. What do you think of something like this? // somewhere let HelloWorld = ProcessWire.hookable( { foo: "foo world!", ___hello: () => { return "hello world!"; }, }, "HelloWorld" ); console.log(HelloWorld.hello()); // output: hello universe! console.log(HelloWorld.foo); // output: foo universe! // somewhere else ProcessWire.addHookAfter("HelloWorld::hello", (e) => { e.return = "hello universe"; }); ProcessWire.addHookAfter("HelloWorld::foo", (e) => { e.return = "foo universe!"; }); I built a proof of concept module here, but it's already outdated and I'll work on a new version shortly. The reason why I'm building this is because I needed a way to modify some parts of my JS frontend setup on my RockCommerce project. So I added two methods RockCommerce.after(...) and RockCommerce.before(...) where we as a developer and user of RockCommerce customise every part of the Frontend (for example adding custom taxes or pricing calculations). Now while working on RockCalendar I wanted something similar. And while working on RockGrid I had the same need. For example adding custom locales or adding custom callbacks. What is easy as cake in PHP is not so easy to do in JS. So I thought, wouldn't it be nice to have hooks in JS as well? I asked Ryan and he seems to like the idea, so I'll work on that over the next few weeks. As you can see here I will most likely change the module soon to work with JS proxy objects. This is what provides the magic of AlpineJS behind the scenes. Now I'm wondering if some basic Alpine magic would make sense here as well, for example watching a property and firing a callback can be extremely helpful on its own! let demo = ProcessWire.magic({ foo: "foo", init() { this.$watch("foo", (newVal, oldVal) => { console.log(`foo property changed from ${oldVal} to ${newVal}`); }); }, }); demo.foo = "bar"; // will log "foo property changed from foo to bar" I've renamed ProcessWire.hookable() to .magic() in this example, as it does more than just adding hook support. Not sure about "magic", maybe you have better ideas? What do you think? Would that be helpful? What would be a good name? ProcessWire.rock(...) would be my favourite I guess πŸ˜„ ProcessWire.proxy(...) would also be an option. Not sure if adding basic apline magic to PW would be a good idea of if adding alpinejs itself would be better? Any JS experts here that want to help with that project?
  8. That's an interesting use case @Ellyot_Chase Would that be just a single checkbox or a daterange or an hourly schedule? Don't see a problem here as my calendar will be able to list any page as long as it contains a RockDaterangePicker field (which stores all the information about start timestamp, end timestamp, allDay yes/no etc. That would be regular PW pages and page reference fields. I'll keep your use case in mind! Thx
  9. I'd love to have something like this, where we can write code that doesn't break if something or someone changes an output formatting setting of a field and where we can request the value we need wherever we want: // force single value $p = $page->getPageOrFalse('my_page_ref_field'); if($p) ... // force page object $p = $page->getPageOrNullpage('my_page_ref_field'); if($p->id) ... // force array value $items = $page->getPageArray('my_page_ref_field'); foreach($items as $item) { ... } If you like that, give it a thumbs up: https://github.com/processwire/processwire-requests/issues/538
  10. Hi @notplants welcome to the forum and thx for your contribution! There is no standard way of adding requirements. ProcessWire does not use composer or such. It is just a platform to run modules. How you add your dependencies basically is up to you. One option is to include it into your module. So you'd do composer require ... on your dev environment and then you add require vendor autoload to your module and that's it. That means it is super easy to install for anybody else, but that also means that if you (or anybody else) had multiple modules that require guzzle in the best case it would just be some overhead (as every module might ship a separate version of guzzle) and in the worst case you'd get conflicts. Another option would be to create another module solely for adding guzzle to PW. That way several other modules could use the guzzle module and you'd have less overhead, but more to do during installation or maybe also more troubles as you need to keep versions compatible... The third and in this case IMHO best option is to use WireHttp instead of guzzle unless you really need guzzle for the http requests?! WireHttp is part of the core so you get the best of option 1 and option 2.
  11. Today while working on RockCalendar I had the need to change the database schema of my daterange fieldtime to add support for recurring events. I didn't know how to do it, so I had to do some research and that took quite some time. Here's the solution that I found in FieldtypeComments.module. When developing the fieldtype you can add a database schema like this and PW will take care of creating the table and columns for you: public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'timestamp NOT NULL'; // the from timestamp $schema['foo'] = 'timestamp NOT NULL'; return $schema; } This is quite easy, but I wanted to add another column and tried this: public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'timestamp NOT NULL'; // the from timestamp $schema['foo'] = 'timestamp NOT NULL'; $schema['bar'] = 'timestamp NOT NULL'; return $schema; } No luck. You will get an error that column "bar" does not exist. Ok, so we have to modify the table somehow... But we also have to make sure that this is only done once. How to we do that? The solution is to save the schema version to the field and use that to compare versions and conditionally update the schema: public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'timestamp NOT NULL'; // the from timestamp $schema['foo'] = 'timestamp NOT NULL'; $schema['bar'] = 'timestamp NOT NULL'; $schemaVersion = (int) $field->get('schemaVersion'); $updateSchema = true; $table = $field->getTable(); $database = wire()->database; if ($schemaVersion < 1 && $updateSchema) { try { if (!$database->columnExists($table, 'bar')) { $database->query("ALTER TABLE `$table` ADD bar " . $schema['bar']); } $field->set('schemaVersion', 1); $field->save(); } catch (\Throwable $th) { $this->error($th->getMessage()); $updateSchema = false; } } return $schema; } And maybe at a later point you want to add another column "baz": public function getDatabaseSchema(Field $field) { $schema = parent::getDatabaseSchema($field); $schema['data'] = 'timestamp NOT NULL'; // the from timestamp $schema['foo'] = 'timestamp NOT NULL'; $schema['bar'] = 'timestamp NOT NULL'; $schema['baz'] = 'timestamp NOT NULL'; $schemaVersion = (int) $field->get('schemaVersion'); $updateSchema = true; $table = $field->getTable(); $database = wire()->database; if ($schemaVersion < 1 && $updateSchema) { try { if (!$database->columnExists($table, 'bar')) { $database->query("ALTER TABLE `$table` ADD bar " . $schema['bar']); } $field->set('schemaVersion', 1); $field->save(); } catch (\Throwable $th) { $this->error($th->getMessage()); $updateSchema = false; } } if ($schemaVersion < 2 && $updateSchema) { try { if (!$database->columnExists($table, 'baz')) { $database->query("ALTER TABLE `$table` ADD baz " . $schema['baz']); } $field->set('schemaVersion', 2); $field->save(); } catch (\Throwable $th) { $this->error($th->getMessage()); $updateSchema = false; } } return $schema; } 😎
  12. I think this should be doable with a custom sort callback in fullcalendar in v6: https://fullcalendar.io/docs/eventOrder
  13. Thx @BrendonKoz and @Jonathan Lahijani that's very valuable input. I have read your article briefly and it's an interesting idea to build the frontend calendar on your own. On my quick and dirty tests i added the fullcalendar to the frontend to see if everything works. Then I added the mentioned drag and drop functionality to see if editing events also works. It did. But it needed quite a lot of not so easy code and to get something modular I had to refactor everything. Now I built the fullcalendar as a fieldtype for the backend, so anybody can easily add a calendar to the PW backend. This already works very well for managing events, resizing them, moving them, etc.; But the display part is currently also handled by FullCalendar which works, but also has downsides. For example the mobile view of the month is not ideal. I have to experiment more with it to finally decide, but there is room for improvement at the current state. On the other hand the folks at FullCalendar have built a very good product and for example styling the calendar is a breeze with just setting css variables to your needs. @Jonathan Lahijani how do you deal with multi-day events and how to you decide how they stack and what do you do if you have more events than what fits in one cell?
  14. For a current project I have the need to show and manage events. First, I thought I'd just show events as a list. The benefits of this approach are that it is very easy to do and it works well on desktop and mobile. Then I had a chat with @gebeer and we concluded that a real calendar interface is far more intuitive for the average user. I've built such a calendar once on an ancient site (https://www.mistelbach-mustangs.at/events/), but it was a lot of work and so I didn't do it again for any other project. Then I thought let's use google calendars for managing events. That would have the benefit that we get a lot for free (the whole gui for managing events, the data storage, recurring events, etc). But it also comes with downsides: First, clients need to create an account for their calendar on a third party. We will hopefully have many clients on that project, so instructing them to create an account somewhere else and then connecting both apps together is a lot of overhead. Second, events handled by google have a totally different data structure than PW pages. What if I wanted to display those events? What if I wanted to add image galleries to those events? What if I wanted to have event descriptions powered by RockPageBuilder? What if I wanted the best performance one can get using the awesome ProCache? These things are very easy to do when we are dealing with PW pages, but they are hard if we talk to a third party api like the one from google. So I decided to build RockCalendar. A module where a FullCalendar shows PW pages and all the tedious things are already built in (like managing events, creating events, resizing events, managing locales, etc). I've made good progress over the last few days and I think I'll have something to share next month, so I thought I'd ask for feedback what the community thinks would make sense for such a module? Have you ever had the need for such a module? If yes, what would be the key features that you'd want to see in such a module? What would be nice to have? What would be questions that come up in your head? I can't promise, but I'll try my best to incorporate the community's feedback and suggestions into the RockCalendar module to make it as useful and versatile as possible.
  15. I'm working on RockCalendar which will be released soon if everything goes smoothly 😎 I think it should be stable enough next month. If you want to get notified you can subscribe to the Rock Monthly Newsletter. The module uses https://fullcalendar.io/ for the calendar interface and when clicking an event it will open the page editor in a pw modal: Opening the modal was a bit of a challenge, because PW unfortunately does not offer a good JS API to open modals. It only offers markup-based options to control the behaviour of the modal - at least as far as I could find out. This is a problem, because all events in the calendar get loaded by fullcalendar and I only have the eventClick() callback where I need to fire my action. My solution is to create a fake element in the dom and trigger a click on that element: calendar.on("eventClick", (info) => { // create a fake link element in body let link = document.createElement("a"); let $link = $(link); $link.attr( "href", ProcessWire.config.urls.admin + "page/edit/?id=" + info.event.id ); $link.addClass("pw-modal"); $link.attr("data-autoclose", ""); $link.attr("data-buttons", "button.ui-button[type=submit]"); $link.on("click", pwModalOpenEvent); $(document).on("pw-modal-closed", this.refresh.bind(this)); $link.click(); $link.remove(); }); Maybe that helps anyone else looking for a solution to a similar problem. If anybody knows a better way how to do it, please let me know! PS: If you have input (feature requests) for the development of RockCalendar please let me know: https://processwire.com/talk/topic/30355-request-for-input-what-features-should-a-pw-calendar-module-have/
  16. I've done a video about DDEV, but it doesn't go through setting up ddev. Just follow the instructions on the ddev website. For this you need to tell tracy debugger where the files live on your local file system. This is because PW + Tracy run inside the container and inside the container your files live in /var/www/html. So if you click on a debugging link in tracy then your OS tries to find the file /var/www/html/foo.php and obviously can't find it. // tracy config for ddev development $config->tracy = [ 'outputMode' => 'development', 'guestForceDevelopmentLocal' => true, 'forceIsLocal' => true, 'localRootPath' => '/path/to/your/project/', 'numLogEntries' => 100, // for RockMigrations 'editor' => 'cursor://file/%file:%line', ]; The important part for you is the "localRootPath" setting.
  17. Jep, since 12.1.2024 πŸ™‚ https://processwire.com/talk/topic/29439-cursor-might-be-my-vscode-replacement/#comment-238405 For me it's absolutely worth the 20€ per month. It helps me a lot with JS and CSS and sometimes also PHP, but the better you are with a language the less often you'll need help from the AI. I think so, yes.
  18. What exactly? Maybe it also loads other .less files (in addDefaultFolders()) that reference a variable from uikit. What you are trying to do should definitely be possible so I'm sure we'll get it to work πŸ˜‰
  19. As you don't provide any details we can only guess. Maybe you want to use markup regions but they are disabled in config.php?
  20. Hi @Atlasfreeman I'm sorry but I don't understand what you are trying to say. What is file.php? What is index_filter.php? These things might be obvious for you but they are not for me/us. Every PW project is different, so you have to explain your setup in more detail. I don't understand what you mean by "catches all the page references". The RockPageBuilder field is a PW field like any other field. You output it like any other field in PW, see https://www.baumrock.com/en/processwire/modules/rockpagebuilder/docs/blocks/#rendering-blocks If you don't want to output any blocks on any page, don't add the field to the template and don't add the render call in the template file. ---- Maybe anybody else understands your questions better.
  21. Got it working again! v0.12.6 works and 0.12.7 has an issue, see https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1039
  22. Oh, i see I'm on 40.1 as well but the extension doesn't work 😞
  23. I'm on 0.39.x and I tried but didn't find a way to get the 0.40 update. Have you been lucky or do you know how I can force the upgrade somehow to the rolling release of 40.1? Yeah I was hesitant as well.
  24. Real programmers write tailwindcss classes right from their brain. For the rest of us there are extensions like https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss Today this extension stopped working for me and that was quite a bummer 🀯 I really can't work without suggestions like this: It seems that newer version of VSCode / Cursor don't work with this extension any more if you are using SCSS/SASS/LESS... I found this and got it back working: https://marketplace.visualstudio.com/items?itemName=TailwindCSSIntelliSenseplus.vscode-tailwindcss-plus Not sure if that is a trustworthy extension, see comment of @gebeer below It's very new and unpopular, so I'm wondering if there are better solutions of anybody of you has experienced something similar and has better solutions?
  25. @Stefanowitsch if you hook into Pages::saveReady then you modify the $page object right before the save happens. For example you can just set $page->title = 'foo' there without saving, because PW saves the page object right after you modified it. If you hook into Pages::saved the save has already happened. In that case you need another $page->save() after you modified anything. Sometimes it's better (or necessary) to use Pages::saved, sometimes you can just use Pages::saveReady to be a little more efficient.
Γ—
Γ—
  • Create New...