Jump to content

jploch

Members
  • Posts

    364
  • Joined

  • Last visited

  • Days Won

    8

Everything posted by jploch

  1. Hey folks. Iam working on a module that creates some templates and fields. The module creates these on install and deletes them on uninstall, works great. Now Iam looking for a way to run the create function when the module is updated, but It's not doing anything. I changed the version number and hit refreh on the module manager and a message indicated the update, but my function is not executed. Not sure if Iam hooking the right function here or if there is an __update() function I can use? Here is my code so far: <?php namespace ProcessWire; class BlockEditor extends WireData implements Module { public static function getModuleInfo() { return [ 'title' => 'Editor for PageGrid', 'summary' => 'Installs Template and Fields for a PageGrid Block', 'author' => 'Jan Ploch', 'icon' => 'font', 'autoload' => 'template=admin', 'version' => 1 ]; } public function getBlockName() { return array( 'name' => 'pg_editor', 'label' => 'Editor', ); } //function to create block public function createBlock() { $this->message("Create Block"); $this->log->save("PageGridBlock", "Create Block"); $fs = wire('fields'); $t = wire('templates'); $blockName = $this->getBlockName()['name']; $blockLabel = $this->getBlockName()['label']; if (!$fs->get($blockName)) { $f = new Field; $f->type = $this->modules->get("FieldtypeTextarea"); $f->name = $blockName; $f->label = $this->_($blockLabel); $f->tags = 'pgrid'; $f->save(); } if (!$t->get($blockName)) { $f = $fs->get($blockName); $titleF = $fs->get('title'); // fieldgroup for template $fg = new Fieldgroup(); $fg->name = $blockName; $fg->add($titleF); $fg->add($f); $fg->save(); $t = new Template(); $t->name = $blockName; $t->fieldgroup = $fg; $t->icon = $this->getModuleInfo()['icon']; $t->save(); } // Copy block files $copyFrom = $this->config->paths->BlockEditor . "blocks/"; $copyTo = $this->config->paths->templates . "blocks/"; $this->files->copy($copyFrom, $copyTo); } //function to remove block public function removeBlock() { $this->message("Remove Block"); $blockName = $this->getBlockName()['name']; $t = $this->templates->get($blockName); $fg = $this->fieldgroups->get($blockName); $f = $this->fields->get($blockName); if ($t && $f && $t->getNumPages() > 0 && $f->getNumPages() > 0) { throw new WireException("Can't uninstall because template or fields been used by some pages."); } else { if ($t) { wire('templates')->delete($t); } if ($fg) { wire('fieldgroups')->delete($fg); } if ($f) { wire('fields')->delete($f); } } } public function init() { // trigger on module update $this->addHookAfter('Process::upgrade', function (HookEvent $event) { bd('update'); $this->createBlock(); }); } public function ___install() { $this->createBlock(); } public function ___uninstall() { $this->removeBlock(); } }
  2. if you want to use this theme together with the Tracy debugger module. Tracy has an option now to change the position of the bar to the left side:
  3. Iam sorry to bump an old thread, but Iam currently working on a comercial module and looking for ways to make the update process as easy as possible. When I try fgb13 solution above I get this error after clicking on the "check for updates" link on my module settings page: ProcessModule: Error decoding JSON from web service My url is pointing to a zip file with my module files. Is there anything else, that needs to be done? EDIT: Ok I got it working. I had to link to a json file instead. Here is an example of how that file might look.
  4. @horst THX for the quick fix! Unfortunately my client already made the change to PHP 7.4. and I do not have a php 8 environment to test this at the moment. I will report back once I setup a local test environment.
  5. Hi! This is a really useful module. I use it to combine some graphics with the watermark option. However today a host of my client updated to PHP 8 und I got a fatal error: Exception: Cannot load the MemoryImage! After donwgrading to PHP 7.4. everything worked again. The host told the client they will switch to PHP 8 next year and only offer paid support for older versions, so it would be nice if I can continue to use this module. Are there any plans to support PHP 8 in the future?
  6. Hey! Today I discovered a strange behaviour with a fieldtype module Iam currently developing. I have a function that updates the config of the corresponding inputfield module, this functon is called via ajax to update one of the config options (a textarea) with some data. The strange thing is that sometimes it works and then sometimes it saves the new value but deletes all the other config options. Any Ideas why this could be happening? Here is the code that saves the inputfield config, this code is inside a process module and gets called via ajax: $settingsName = $this->sanitizer->text( $_POST['settingsName'] ); $settingsValue = $_POST['settingsValue']; if ( !empty( $settingsName ) && !empty( $settingsValue ) ) { $f = $this->fields->get( "pgrid" ); $f->set( $settingsName, $settingsValue ); $f->save(); return; } (testet on lates PW master Version 3.0.184)
  7. Thanks Adrian! I try to remove those checks and do some testing. Will report back soon.
  8. After some more tests with PageTable, I found out that migrator is not exporting/importing pages under admin. In my use case I have PageTable configured to save all item/pages in a container page under admin. For example admin–>pt-items. However with this setup migrator only exports the main page where the PageTable lives without the items. Placing the PageTable items under admin is a common thing, if you do not want editors to mess with them and keep your page tree clean. I think people also use this approach with PageTableExtended. So it would be nice if migrator would export PageTable items that live under admin or a diffrent parent than the containing page. Since PageTable has a field that saves the IDs of the item pages, that could be used to identify the items. I understand if this is out of scope for migrator. If so I might look into building my own solution.
  9. Thx for looking into this! Not sure if you saw my last edit. The zip export/import works for me with files that are directly in the templates directory, however Iam working on a pagebuilder based on page table that creates pages based on templates in the subfolder "templates/blocks" (See my EDIT above for more information). Would it be possible to support subfolders as well? I was trying to include those files with the "Helper Files" option, but the zip seems to fail if the module can not find the tempate files in the templates root folder.
  10. @adrian this module is really useful! But I can‘t get the zip export/import working. Importing via the other options works great. Iam able to export a zip file. But when I try to import and upload that file into another PW install it says: Fatal error: Uncaught PDOException: You cannot serialize or unserialize PDO instances in [no active file]:0 Stack trace: #0 [internal function]: PDO->__sleep() #1 {main} thrown in [no active file] on line 0 I tried this on my local machine (Laravel Valet on an old Apple iMac, latest Chrome Browser) with the latest PW version (3.0.184). Also when I try to unzip the achive manually, I get a file called files.zip.cpgz, not sure if this is expected. Any clue what's wrong here? EDIT: It seems to work fine with files inside the templates folder. I had templates under templates/blocks/ and it was not working. So I guess my question would be, if it is possible to allow templates from subfolders as well? Iam currently working an a pagebuilder module and looking into Migrator to update and import the pagebuilder template files. These files live under templates/blocks/ (my pagebuilder creates pages from these template files).
  11. jploch

    Alpine.js help

    I shortend the JSON manually and must have messed it up. I have now updated the post above with a code generated version, that validates ?
  12. jploch

    Alpine.js help

    ok I just made a quick test with inlining my data in the x-data attribute. With your simple data object above it works great. But with my nested data (see JSON code above), how would the x-text attribute look if I want to output block_editor-4980.tagname for example. Do I have to structure my object diffrently, to acess the values directly?
  13. jploch

    Alpine.js help

    @kongondo Wow! Thanks again for taking the time to explain this in detail. It helps me a lot! I have decided to release my module in it's current state first and do a refactor later. I already went down the rabbit hole with my module and refactoring it at this stage will take up too much time. But with your examples I will try to reafactor it at some point. That makes it clearer (I was reading the docs but it was not clear to me, how $store works). So using store is a nice way to acess the data globally across multiple js files: "Creating a store with Alpine.store allows you to access global state in your components using a $store property. That same Alpine.store method can be used to retrieve a store in your external scripts." I code most new projects in vanilla js, but since PW uses jquery internally already, I fall into old habbits. Also in my experience, the code with vanilla is often longer and browser compatibility can be an issue as well (Sorry this is a little bit off topic, we don't have to get into this). But I will definitely try going all vanilla js + alpine/vue for new projects, if it makes sense. It's just the way Iam used to work nowadays, installing external plugins/frameworks with node and importing them as js modules and than bundle them with webpack. Nice! will try that and get back at you if I hit another road block ? Also another question, this is more about JS objects/arrays in generall. With my current data structure is it possible to access an item by ID without looping over it (eg. $store.items[id].value)? I access the value like this now, which is more complicated: // looking for the values of this ID let itemId = 'block_editor-4980'; $.each(data['items'], function (idx, item) { // can access value in here like this if (itemId == item.id) { // access values of item } }); Thanks again!
  14. jploch

    Alpine.js help

    @kongondo This is a continued conversation from this thread I had with you about using Alpine.js in module development. Thanks again for your help! I want to refactor a module that is build using jquery with alpine. The main goal is to make the code simpler and more maintainable (It's working fine with jQuery, so not sure if it's worth the effort). Alpine is still very new to me. I feel more compftable working with jQuery, but I can see the benefit of using a reactive framework. Do you think it makes sense to refactor my module at this stage? Here is a simplified description of what my module does: The module is a pagebuilder module based on pagetable that uses the PW API to generate some inputfields. These inputfields are than used to set some css styling on the pagebuilder items/blocks. So when a block is clicked, the inputfields get populatet with data from a JSON object based on the block that was clicked (each block has a unique ID). With jQuery I use a on.change event to listen to changes to the inputs and than save the new value to the corresponding ID inside my JSON object. This code works fine, but is quite long now, and I think it maybe good to use the data binding ability of a reactive framework like alpine.js instead. With the help of you I was able to listen to the change event and call my save function to update the JSON. Now Iam looking for a way to set the values of the inputfields. The values have to be set when a block is clicked. Hope that makes sense ? here is my JS code for alpine so far (I added the attributes inside my php template vie PW API): import * as save from './save'; import Alpine from "alpinejs"; // this is my json object var jsonData = $('#Inputfield_pgrid_settings').val(); var objData = $.parseJSON(jsonData); // ALPINE (version 3+) document.addEventListener("alpine:init", () => { console.log('alpine!'); // this is just for testing, it works to set the value for one field // I want a way to get the value of a field based on its name Alpine.store("mystore", { settingsData: { testValue: 22 }, }) Alpine.data("settingsData", () => ({ cssChange(event) { let value = event.target.value; let name = event.target.name; console.log(name + ': ' + value); this.$store.mystore.settingsData.testValue = value; // caling a function to save the json setStyle(name, value); } })) }) Alpine.start(); JSON example: { "items": [{ "id": "block_editor-4976", "cssClass": "block_editor-4976", "cssClasses": "new-class", "tagName": "div", "state": "none", "breakpoints": { "base": { "css": { "grid-column-start": "auto", "grid-row-start": "auto", "grid-column-end": "span 6", "grid-row-end": "span 1" }, "size": "@media (min-width: 640px)", "name": "base" }, "m": { "css": { "grid-column-start": "auto", "grid-row-start": "auto", "grid-column-end": "span 6", "grid-row-end": "span 1" }, "size": "@media (max-width: 960px)", "name": "m" } } }, { "id": "block_editor-4980", "cssClass": "block_editor-4980", "cssClasses": "new-class", "tagName": "div", "state": "none", "breakpoints": { "base": { "css": { "grid-column-start": "auto", "grid-row-start": "auto" }, "size": "@media (min-width: 640px)", "name": "base" } } }], "breakpointActive": "s", "breakpointActiveSize": "@media (max-width: 960px)" }
  15. @kongondo I have experimented with Alpine.js and setting the attributes on the inpufields via PW api like you showed, and it works nicely! It's really a game changer compared to doing it in nativ js or jQuery! My code is now roghly 1/6 the size it was before and it's quite intuitive to use as well. Thanks for the hint! I highly recomend others to try this as well. Btw. it also works together with jQuery without a problem, if you want to keep that as part of your workflow. EDIT: Still having some trouble figuring things out with Alpine. For example I have JSON data saved inside a PW field. Now I want to use that data to pupulate my inputfields. Looking at your example, I guess I have to use alpine.store for that. How would that work?
  16. Nice! Thanks for the suggestion. Alpine looks great. I will definitely check out vue und alpine. There is a lot of new stuff to learn, working mainly with jquery in the past. This might also be a little to late for my pagebuilder module Iam currently working on (almost done, it's written in jQuery und uses the change event on the inputfields). However refactoring that, might be a nice way to learn about these reactive js frameworks ?
  17. I managed to get it working. However for my module it would be nice to use PW to render some inputfields und use them together with vue. But what I have learned so far is that vue would be used to render the markup, so I would need to write the markup for the inputfields myself und put them in my js file? That would not be ideal, because the markup might change with new admin themes. Is there a way to use PWs API to create the inputfields and use vue to react to the user input?
  18. @kongondo I would love to try vue for module development, but have trouble getting it to work. A tutorial would be highly appreciated! A vue module boilerplate would be nice ? I just started experimenting with vue, it looks very promising! Would it still be possible to run the module from within PW (when developing)? From what I understand vue uses it's own development server?
  19. Today I used this module for the first time to implement an RSS feed into an exiting website. On my local dev enviroment, everything worked well. But on the live website I get a error, when umlaute (ä,ö,ü) are present in the title field. The error looks like this: This page contains the following errors: error on line 4 at column 51: Entity 'uuml' not defined Below is a rendering of the page up to the first error. Here is the code to render the RSS feed (if I comment out the part $rss->title and $rss->description, it works) <?php namespace ProcessWire; // retrieve the RSS module $rss = $modules->get("MarkupRSS"); // configure the feed. see the actual module file for more optional config options. $rss->title = "ATLAS ist das Kundenmagazin von Gebrüder Weiss"; $rss->description = "ATLAS ist das Kundenmagazin von Gebrüder Weiss."; $rss->itemDescriptionField = 'textarea'; // find the pages you want to appear in the feed. // this can be any group of pages returned by $pages->find() or $page->children(), etc. $items = $pages->find("template=artikel, limit=10, sort=-parent, sort=sort"); // send the output of the RSS feed, and you are done $rss->render($items); ?> EDIT: My local PW version is 3.0.150 and my live PW version is 3.0.165. After replacing the module file (MarkupRSS.module) from the live site with the older version from my local site, everything is working fine. So there seems to be an issue with the newer version.
  20. still it would be nice to just use the title field as the block id without the need for an additional custom field. The title is not really needed in the context of the block, so I could just hide it in the editor. Since the block pages are hidden under the admin page in the tree (this can be changed in field settings, but maybe I will remove that setting and make that the default), there is no real danger to acidentally change the title of a block manually. That way I don't have to take care of installing/uninstalling the custom field. I guess the main question is if it should be possible to add existing pages to my grid, that do not use the block templates but are just regular pages in the tree. For those cases the title field would not be a good option. However it would still be possible to include those pages with a block that has a page reference field. This would also be a better option to include existing pages, since it's much more clear there is an actual connection to another page.
  21. I tried to keep it simple and was also concerned with performance. Updating the JSON field on the parent page is easy. Storing the data on the children/blocks would mean I have to update the JSON via ajax every time the blocks style is updated (not a big deal). Also there are some settings for the parent page I need to save as well, so it seemed like a good approach to have just one JSON field to keep all the data in one place. Maybe I will consider moving the JSON to each block instead, but that would mean a lot of refactoring needs to be done. Also what will happen if the same block page is added to two different grid fields/parent pages, then it could only have one style that is associated with the block. With my current approach, it would be possible to have different styles for the same block, since the JSON is stored on the parent. I have to think about this a little. Thanks for looking into this! I have a tunnel vision by now, and there are so many things to consider, it's very helpful to get a fresh perspective on it.
  22. Thx for your input! Just to be sure we are on the same page here. Iam talking about the parent page with my grid field, that holds all the childpages, lets call them blocks. So cloning this parent page from the page tree with the copy button, causes all the blocks on the clone to change their page id (need to be unique) and page name, the page title however will not change, so setting the title as the JSON ID will keep the styling information without any need for a comparison of IDs or additional fields. As I understand it, going with ids would need a hook on page add/clone to handle the switch of IDs or all the styling information is lost. Using the title field or a custom field to simply copy the same JSON id to the new page (page clone does this automatically) worked well so far. Iam worried when external pages that already exists in the page tree are added to the page grid field (eg. via api) it would not be a good idea to use the title field here, because it maybe be accidentally changed by the user and lose its connection with the JSON id. Also not sure I was clear, the JSON data lives on the parent page, I only need a way to connect the blocks with the JSON id. Hope that makes sense ?
  23. Hey folks! Just wanted to give you an update on this. Iam close to an alpha release now. I added a lot of features (containers/groups, more styling options, api functions, optional webfonts/google fonts integration, UI improvments etc.) and bug fixes and now it feels quite stable. I still have to do some testing and some UI stuff. Iam really exited to show you the new version soon! ? Before I can post a final release date I have to think a little bit about how the JSON for the styling is saved and make sure that it's solid. I have two approaches and can't decide which one is best. Maybe someone, who used page table (my module uses templates/fields just like page table), can help me figure this out. It works like this: When a new block/page is added to the page table, my module auto generates a title and a name. The title is generated based on the name of the template the page item is using plus the page id. I title could look like this: block_image_5143 This title (with sanitizer) is then used as an ID to save all the styling information for that item/page to my JSON field (it's also used to generate a css class name). The ID has to be unique in the context of the page containing the page table items. I figured I can't use the page id or the page name, because when a page containing a page table grid is cloned, all the items/pages added to the page table get duplicated and change their name and ids, so the clone loses all the styling information. So while it works great with the title field, it has the downside, that when the user changes the title, the connection to the ID/title in the JSON gets lost. So an alternative approach Iam considering now is to add an extra field to every page table item template automatically via api (pupulated on item/page creation), eg. pgrid_id. This field only has superuser access or is completly hidden. While this adds a little more overhead, it may be the better approach. What do you guys think is better?
  24. Gumroad looks very promising! Will take a closer look, that might just be what I need. From what I can see it's even possible to inform the customer of new versions of the module and adding subscriptions for support etc. Sweet!
×
×
  • Create New...