Leaderboard
Popular Content
Showing content with the highest reputation on 09/21/2018 in all areas
-
ProcessWire 3.0.114 is a relatively minor core version update. Most of the ProcessWire stuff I've been working on this week isn't quite ready to commit/release, so will save for later. This version adds a $database->supportsTransaction() method that returns a true or false as to whether or not the current DB engine supports transactions. Or if you give it (as an argument) the name of a table in the database, it'll return a true/false specific to that table. This version also adds importFiles() and replaceFiles() methods to $page->filesManager, which is what manages all the files for a page. These methods aren't likely to be useful in site development, but are useful for a module I'm working on, and maybe useful to other modules, so I went ahead and added them. Finally, probably the most interesting update in this version is that modules can now specify autoload order. This is something that Adrian requested, as TracyDebugger needs to load before other modules, so this update simplifies that. If you develop a module that has a similar need, be sure to see the notes for the autoload getModuleInfo() property in the Module class. That's all there is this week, so I'm not going to do a blog post this week, but stay tuned for more next week! Have a great weekend.14 points
-
An action that I made for my own convenience but that others might find useful too: Unordered List to Pages An action for the Admin Actions module for ProcessWire CMS/CMF. Creates a structure of new pages from an unordered list entered into a CKEditor field. The nesting of further unordered lists within the list will determine the nesting of the created pages. This can be useful to quickly create a page structure; especially so if you are rebuilding an existing non-ProcessWire site that has a Sitemap page that you can copy and paste from. All the created pages get the same template - for any pages that should use a different template you can easily change this as you edit the page to add content, or use the Page Manipulator action for bulk template changes. Usage Install the action by copying the "UnorderedListToPages" folder to /site/templates/AdminActions/, and then visiting the Admin Actions config screen and enabling the "Unordered List to Pages" action for the roles who are allowed to use it. Navigate to Admin Actions > Unordered List to Pages and fill out the config fields: Enter/paste an unordered list in the Source field. Select a parent page that the new pages will be created under. Select the template to use for the new pages. Execute the action. Screenshots Action config: Result: https://github.com/Toutouwai/UnorderedListToPages Update: https://github.com/Toutouwai/AdminActionsUnorderedListToPages This action module now has its own support topic:6 points
-
Another round ? 1) I have revamped the fullscreen / halfscreen buttons that are on many of the panels. They have been replaced by a single Maximize / Restore button which I think it much more useful. Hope you guys agree! 2) I have removed the "open in window" link from all panels - I never used this feature and it was painful to get the layout of some of the more complex panels to work in this mode. If others are finding they miss it, let me know and I'll see about reinstating it.4 points
-
I freaking love this! It is like the Add mode from BatchChildEditor, but on steroids! I'd be keen to include this as a core action if you're ok with that and you'd like to submit a PR. I can see using this for kickstarting many new sites. If you do want to include, maybe move simple_html_dom.php into the libraries folder under actions, unless you feel like removing this need and coming up with a DOMDocument solution?4 points
-
"There are some bright spots indicating that improving over state-of-the-art is not impossible." The author is probably not aware of another excellent piece of high quality software which should also be listed: ProcessWire ?4 points
-
You need to enable php short tag in the php.ini file or add php to any tag < ? then clear the cache.3 points
-
Reminds me of MorphOS: http://www.morphos.de/ which is still a 250MG disk image full of all sorts of GUI apps we are used to today and runs quite fast on a G4 PPC processor (more info: http://www.morphos.de/hardware). Last year I installed the demo of MorphOS on my G4 PPC and I really liked what I saw. I want to buy a silent power supply for he G4 so that its noise drops to a level where using it becomes enjoyable. I plan doing it next year, together with my son, just for fun. After all, he wants to become a programmer, so he needs be aware of efficient pieces of software out there. BTW, the author mentioned how shoddy browser based apps can be. Talented and dedicated programmers can do a lot better than that, of course, a very good example is: https://editor.construct.net/3 points
-
Another round of tweaks, bug fixes and new features. 1) File Editor revamp to improve layout and adds a new fullscreen editing mode (like the one added to the Console panel), also with the same CTRL + SHFT + Enter shortcut for toggling in and out of that fullscreen. 2) More tweaks and code cleanup for the Console panel. 3) Some nice enhancements and cleanup for the SnippetRunner panel. 4) New "Open" option for the "Goto Page ID" feature in the PW Info panel - this opens the page's branch in the page tree. I find this entire feature very useful when working on sites where the templates make heavy use of IDs instead of paths for querying pages. If you haven't tried, give it a go. ? 5) Various bug fixes in the module and also in the Tracy core. There are quite a lot of changes in this version, so please let me know if you find any issues.3 points
-
DEPRECATED If you are interested in the new version (commercial module launching in 2023) write me a PM --- Some of you might have followed the development of this module here: https://processwire.com/talk/topic/15524-previewdiscussion-rockdatatables/ . It is the successor of "RockDataTables" and requires RockFinder to get the data for the grid easily and efficiently. It uses the open source part of agGrid for grid rendering. WHY? ProcessWire is awesome for creating all kinds of custom backend applications, but where it is not so awesome in my opinion is when it comes to listing this data. Of course we have the built in page lister and we have ListerPro, but none of that solutions is capable of properly displaying large amounts of data, for example lists of revenues, aggregations, quick and easy sorts by the user, instant filter and those kind of features. RockGrid to the rescue ? Features/Highlights: 100k+ rows Instant (client side) filter, search, sort (different sort based on data type, eg "lower/greater than" for numbers, "contains" for strings) extendable via plugins (available plugins at the moment: fullscreen, csv export, reload, batch-processing of data, column sum/statistics, row selection) all the agGrid features (cell renderers, cell styling, pagination, column grouping etc) vanilla javascript, backend and frontend support (though not all plugins are working on the frontend yet and I don't plan to support it as long as I don't need it myself) Limitations: While there is an option to retrieve data via AJAX the actual processing of the grid (displaying, filtering, sorting) is done on the client side, meaning that you can get into troubles when handling really large datasets of several thousands of rows. agGrid should be one of the most performant grid options in the world (see the official example page with a 100k row example) and does a lot to prevent problems (such as virtual row rendering), but you should always have this limitation in mind as this is a major difference to the available lister options that do not have this limitation. Currently it only supports AdminThemeUikit and I don't plan to support any other admin theme. Download: https://gitlab.com/baumrock/FieldtypeRockGrid Installation: https://gitlab.com/baumrock/RockGrid/wikis/Installation Quikckstart: https://gitlab.com/baumrock/RockGrid/wikis/quickstart Further instructions: https://gitlab.com/baumrock/RockGrid/wikis/quickstart#further-instructions German Translation File: site--modules--fieldtyperockgrid--fieldtyperockgrid-module-php.json Changelog: https://gitlab.com/baumrock/FieldtypeRockGrid/raw/master/changelog.md Module status: alpha, License: MIT Note that every installation and uninstallation sends an anonymous google analytics event to my google analytics account. If you don't want that feel free to remove the appropriate lines of code before installation/uninstallation. Contribute: You can contribute to the development of this and other modules or just say thank you by testing, reporting issues and making PRs at gitlab liking this post buying me a drink: paypal.me/baumrock/5 liking my facebook page: facebook.com/baumrock hiring me for pw work: baumrock.com Support: Please note that this module might not be as easy and plug&play as many other modules. It needs a good understanding of agGrid (and JavaScript in general) and it likely needs some looks into the code to get all the options. Please understand that I can not provide free support for every request here in the forum. I try to answer all questions that might also help others or that might improve the module but for individual requests I offer paid support (please contact me via PM). Use Cases / Examples: Colored grid cells, Icons, Links etc. The Grid also has a "batcher" feature built in that helps communicating with the server via AJAX and managing resource intensive tasks in batches: Filters, PW panel links and instant reload on panel close: You can combine the grid with a chart library like I did with the (outdated) RockDataTables module:2 points
-
This is called "Set Filter" in aggrid and it is an enterprise feature: https://www.ag-grid.com/javascript-grid-filter-set/ I've already created two custom filters: https://gitlab.com/baumrock/FieldtypeRockGrid/tree/master/plugins/filters I want to create a filter similar to the set filter of aggrid one day, but it has low priority at the moment. You can try my smart filter (that is already default in the new versions) or you can try to build your own. If you (or anybody else) are/is interested in sponsoring this type of filter for the community please let me know.2 points
-
I'd like to add that JWT is to be taken with a grain of salt. Once a token is issued there's not way to revoke it's validity unless one is storing something in the db to validate the jwt against. Having something stored on the server makes it essentially a more complex, more manual session handling, so there's at least in my opinion no longer a point to use JWTs. They're mostly useful for shortlived tokens or you can use them if you implement something like oauth or similar stuff. I personally wouldn't suggest using them like they're implemented currently in the module.2 points
-
As https://www.ag-grid.com/javascript-grid-row-styles/#row-class says, you need to modify the gridOptions.rowClassRules for this. Now I found out how to do this. In your javascript file do this: document.addEventListener('RockGridItemAfterInit', function (e) { if (e.target.id != 'RockGridItem_stats') return var grid = RockGrid.getGrid(e.target.id) // set style of all rows to color #cecece remember styles are bad, better use classes grid.gridOptions.rowStyle = {background: '#cecece'}; // this is untested. First is the class to be assigned and second is the condition grid.gridOptions.rowClassRules: { 'rag-green': 'data.age < 20', 'rag-amber': 'data.age >= 20 && data.age < 25', 'rag-red': 'data.age >= 25' } // you can use the grid api like this: // grid.api().sizeColumnsToFit(); //grid.api().setHeaderHeight(48); })2 points
-
A friend wrote his own OS from scratch back 15 years ago. He was way ahead of competition and was telling the same things about how bloated and inefficient softwar3 and specially os's are. He's dad run a software company he also worked in but only got doubted and ignored somehow. He kept at it for almost 7 years until he proved everybody wrong. He could do things even seniored software guys got blown away. He's system was so small and efficient and only was about a couple Mb in size that would extract to some gb of data (ofc the apps) . He could install a whole computer network with 50 laptops in about 1m and boot them up all at the same time im 5s from his laptop. He was into clustering and had big things in mind. He's system they used for a central payment system that did run for +3 years without one single restart or outtage or problem. They were so impressed that they ordered more. Sadly he got fired by his own dad because of he work philosophie and had his problems. Unfortunately he died of cancer 11 years ago. His work kinda lost. Makes me sad and not a single day pass by without thinking of him. Yet 10 years later sadly nothing has changed in the industry. I'm so happy there's still people around who care.2 points
-
Hello All, I've been working on a new Fieldtype + Inputfield combination that handles street addresses. I've been using it now for about 3 months on my latest administration system for a charity and, so far, it seems to be working really well for them. It's based on the meta-data from Google's LibAddressInput project and uses the data feeds from that to build a cache of address formats used by various countries. My initial testing was aided by @Macrura and @adrian - and they were later joined by @mel47 and @BFD Calendar - so a big thank-you to them all. You can access the repository on GitHub and the Module Repository. Here's a few images from the project. First up: config screen. Here's an early version... ...and a more recent update... Here's a UK-based address. The module can integrate with my tag parser, if installed. Note that the output is formatted according to the output meta-data from the feed - which should match the preferred postal preferences of the destination country. Which subfields are required, and their regex expressions (if any) are also pulled from the feed and used as validation rules on the input side. Here's an address in the Netherlands - inputfield layout is currently adjusted on save - if you've configured it to adjust based on the destination country. Hopefully this will eventually be ajax driven. Use of the address preview is configurable and the HTML output can include micro-format data. Address sub-fields can also be used in selectors... Back with inputs, if you prefer a table-based input - you can have it... Format hints (unfortunately, I've found that many users need these)... Let me know if you find any issues or if you have any feature requests. So far, I have this from the previous testers... Allow multi-lingual address input for countries that support a multi-lingual postal system (like Canada.)1 point
-
1 point
-
1 point
-
Hi @adrian thanks for the latest update to add autoload support (and to Ryan for putting it into the core this week) as I can now use Tracy in the preview tab in FormBuilder to do a little StreetAddress work. Much appreciated!1 point
-
I think authors maintaining actions in their own repos is the way to go. I know from past experience that when tinkering around I often do several commits after I think I've done my "final commit" for a version as I spot little errors or think of new ideas. I wouldn't want to have to bother you or me with pull requests for these. Having a list of third-party actions in the readme sounds like a good idea, but I have another idea too. I think it would be cool if we could leverage the power of the modules directory and ProcessWireUpgrade for actions, so users can see when updates are available and easily pull those updates in. So the idea is that each third-party action that extends ProcessAdminActions would have its own "pseudo-module" - a module file containing just the required getModuleInfo() method. So for my action above the module folder would look like this: And ActionUnorderedListToPages.module would consist of this: <?php namespace ProcessWire; class ActionUnorderedListToPages extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Unordered List to Pages', 'description' => 'Creates a structure of new pages from an unordered list.', 'version' => '0.1.0', 'author' => 'Robin Sallis', 'href' => 'https://github.com/Toutouwai/ActionUnorderedListToPages', 'extends' => 'ProcessAdminActions' ); } } ProcessAdminActions would look for third-party actions like this... $third_party_actions = $this->wire('modules')->findByInfo('extends=ProcessAdminActions'); ...and then get the action by looking for an ".action.php" file in the module directory. ProcessAdminActions could hopefully grab the action title/description from getModuleInfo() rather than this needing to be duplicated inside the action file (but no big deal if that wont fly). So this would require coding some extra features in ProcessAdminActions but I think being able to use the modules directory would be really cool. And the exact details of how all this would work is up for discussion of course - this is just me brainstorming here. What do you think? I might be wrong but this sounds like it wouldn't work very reliably. Sitemaps generally just have the URL to the resource and that seems like it would problematic to parse into the desired page structure in many cases: There is no page title in an XML sitemap so pages would have to use the slug name as page title, which may not be that close to the desired title - so potentially requiring a lot of manual fixes later and not making the action much of a time-saver. Many sites don't have the tidy connection between URL and page structure that PW has - worst are ones like /index.php?id=1234&view=detail&foo=bar. I'm not sure what the action would be able to do with this. XML sitemaps often include entries for non-page resources such as PDF files. If you think the XML sitemap idea can work I'm happy to be proved wrong. ? Maybe you want to have a play around with it?1 point
-
Maybe also of interest: https://processwire.com/blog/posts/processwire-3.0.107-core-updates/#what-pages-point-to-this-one1 point
-
$faqs = $pages->find("template=template-of-faq-pages, page_ref_field_of_faqs=$page, limit=10"); we are limiting to 10 hits in this example.1 point
-
FYI. Well worth the read: https://www.i-programmer.info/news/81-web-general/12149-google-gives-amp-open-governance-still-not-good-enough.html "It doesn't matter if Google hands AMP over to an entirely benevolent foundation, as long as Google is adjusting its search and hosting the cache, it has too much control. The web served by Google isn't an open and free web, it is a walled garden in waiting."1 point
-
?. Yeah. What @adrian said. PHP is most likely running out of memory when ProcessWire tries to create thumbs for those images. Second time round, they should load fine (assuming the thumbs creation finished). Maybe also see if you need to rethink your approach? 300 images on one page, from a UX point of view can be 'not-so-friendly'?1 point
-
1 point
-
Hey @tpr - sorry I just realized it was a bit rude of me to not acknowledge that change as your idea when I posted about it above. Sorry about that!1 point
-
I know, it was your suggestion that prompted me to make the change ? Sometimes I am slow on coming around to a good idea ?1 point
-
1 point
-
Glad to hear that. I'm also still impressed how powerful and well crafted aggrid is ? If others read this just have a look here: https://gitlab.com/baumrock/FieldtypeRockGrid/blob/master/plugins/columns/rgColAddIcons.md https://gitlab.com/baumrock/FieldtypeRockGrid/blob/master/readme.md#transmit-data-to-the-client-side https://www.ag-grid.com/javascript-grid-row-styles/1 point
-
A very simply library that quickly allows localisation of country, language and currency names into various locales. It's based on the data from Umpirsky's country-list project. I started writing this back in 2014 but have finally got around to publishing it. I hope this is of use to some of you. Usage Examples... To create a localisation for a particular locale, first create a new instance and define the locale... $de_DE = wire('modules')->get('LibLocalisation')->setLocale('de_DE'); You can now use your locale to get information about countries, currencies and languages as they are used in that locale. For example, to output the names of various countries you use the country() method, passing in an ISO 3166-1 2alpha country code... echo $de_DE->country('CH'); // Outputs "Schweiz" - the German for Switzerland. echo $de_DE->country('AU'); // Outputs "Australien" - the German for Australia. echo $de_DE->country('US'); // Outputs "Vereinigte Staaten" - ditto for the United States of America. You can create as many instances of the module as you need and set them all up for the same, or different, locales. To access currency data, you call the currency() method, passing in the 3-letter currency code you are interested in. echo $de_DE->currency('GBP'); This returns an array of data about GBP - localised in German... [ digits => 2, number => "826", symbol => "£", name => "Britisches Pfund Sterling" ] Finally, you can output localised language names by calling the language() method and giving it a 2 letter language code. echo $de_DE->language('fr'); // Outputs "Französisch" - the German for French. Getting the Module... You can view the project on Github or in the module repository.1 point
-
I'm not sure how much you intend to further work on it, but https://github.com/unicode-cldr might also be a nice source for information.1 point
-
@kixe Awesome! I guess that explained in pretty much in detail! And guess what: after ignoring this problem for 24h now it solved itself... like always ? Thank you very much for this detailed explanation!1 point
-
Hey @teppo, the user 8-bit-guy is one of my sons favourites. My 12 years old son loves to work and hack retro hardware, like commodore 64 and a whole bunch of gaming handhelds or consoles, (besides others). Every third or second time, when he get something to work, and I ask him how he got it to work, he answers: "I found some useful information from the 8-bit-guy." ?1 point
-
Great read! A bit off topic (hey, this is the pub) but this is part of the reason why I love reading about old-school software development, and game development in particular. You know, when folks had to figure out how to run complex software while dealing with various limitations – such as being limited to something between 32 and 64 KB of memory in total. Good times. For the record, there are some awesome videos about old school development and hardware at YouTube by user The 8-Bit Guy. Not only does he clearly know his "old-school" computers inside out, he has also released amazingly polished new games for old hardware ?1 point
-
I see the same going on with imaging tools for backing up a whole partition on your computer. I tried Norton, Acronis, Paragon, etc. They are nothing but Corporate Bloat. And then there is this german programmer who made drive snapshot. I won't put any link here. I am not affiliated you can look it up your self with google. It's only 409 kbyte. Yes, thats right only 409 kbyte. You can install it, or use it portable or start it from a bootable iso. It blows away all the Corporate Bloat. So in addition to mr-fan's post, what I mean is it can be done, but somehow they won't.1 point
-
Thanks @bernhard! The API does not really care if it's served over http or https, it's just HTTP(s)-Requests after all. If your server is configured to redirect all http requests to https, it'll do so with these as well. However, it's always a bit of a hazzle to test locally, so I left the examples as is and put a note that it's a good idea to use https ? JWT Auth (in this case) works like the following: The client sends a login-request with username + password (this definitely should go over HTTPS) The server checks the login credentials and if correct, creates a unique token with an added encrypted signature The client uses this token to authentiate every following request Since the client does not know the secret, he cannot modify the contents of the token without making it invalid That's basically how I understood it ?1 point
-
LAPS, I am also using the LoginRegister module along with Kongondo Blog module, and wanted to add Favorite functionality for blog posts and users. This related thread gave me a good start: https://processwire.com/talk/topic/18618-best-way-to-handle-saving-an-item-as-a-favorite/ Guessing there will be more users than posts (and the pages may be sorted by favorite count in the future), I decided on using a page field "blog_favs" with input "templates : user" attached to my template "post". And I decided the Add/Remove functionality would be URL query based. Here is the code that I implemented in /site/Modules/MarkupBlog/MarkupBlog.module /** * Render favs * * Used by renderPostHead(). * * @access private * @param PageArray $blog_favs is field in blog_post template. * @return string $out Markup of favs * */ private function renderFavs($page, $small = false) { $options = $this->options; $out = ""; // if page field not available, break if ( !$page->blog_favs ) { return $out; } // if post display is summary snippet skip full UI // if user logged in, use full UI and functionality if ( $small != true && $this->wire('user')->isLoggedin() ) { $uid = $this->wire('user')->id; // uid is int $favExists = 0; // check query string for Add/Remove function $queryCheck = $this->wire('sanitizer')->entities($this->wire('input')->queryString); $queryAddFav = "add_fav={$page->id}"; $queryRemoveFav = "remove_fav={$page->id}"; $doSaveFav = 0; // on AddFav request, assume we are going to save fav $doRemoveFav = 0; // on RemoveFav request, assume we are going to remove fav if ( $queryCheck ) { if ( $queryCheck == $queryAddFav ) { $doSaveFav = 1; } if ( $queryCheck == $queryRemoveFav ) { $doRemoveFav = 1; } } // only loop through blog_favs if there are entries // only loop once if ( count($page->blog_favs) > 0 ) { foreach( $page->blog_favs as $fav ) { $fav_int = (int)(string)$fav; // convert saved object to string then to int (!) if ( $fav_int == $uid ) { if ( $doRemoveFav == 1 ) { $page->of(false); $page->blog_favs->remove($fav); $page->save('blog_favs'); $out .= "<div>" . $options['post_removed_fav_text'] . "</div>"; } else { $favExists = 1; } break; } } } // if AddFav, only if user not already faved this post if ( $doSaveFav == 1 && $favExists == 0 ) { $page->of(false); $page->blog_favs->add($uid); // $uid is int $page->save('blog_favs'); $favExists = 1; $out .= "<div>" . $options['post_added_fav_text'] . "</div>"; } // show Add or Remove links for user if ( $favExists == 0 ) { $out .= "<div><a href='{$page->url}?{$queryAddFav}'>" . $options['post_add_fav_text'] . "</a></div>"; } else { $out .= "<div><a href='{$page->url}?{$queryRemoveFav}'>" . $options['post_remove_fav_text'] . "</a></div>"; } } // always display basic UI Favorites Counter (this is at end to capture add/remove changes) $out .= "<span class='favs'>" . $options['post_favs_text'] . " " . count($page->blog_favs) . "</span>"; return $out; } I make no claims on performance or code elegance, but if any of this is helpful to you, enjoy!!!1 point
-
My module was also adding other attributes beforehand, eg classes, but that was too restricting, and IDEs were complaining about missing img attributes. That's why I decided to rewrite it to generate the srcset attribute only that you can use the way you need. It even works with lazysizes bgset attribute that I often use.1 point
-
Hi @zoeck, Thanks for your interest in Media Manager. I can't give a definite date but it will be in the autumn.1 point
-
Here is a new created version to track changes which works without any problems and you dont have to take care about the deletion of input values if the page was not saved successfully (like in the version before) Put this little piece of code inside your ready.php. //Compare before and after values and output a warning message $pages->addHookAfter('Pages::saveReady', function($event) { $page = $event->arguments('page'); $page->of(false); //configuration: change it to your needs $templates = ['event_businessvacations', 'event_dates', 'event_events', 'event_specialbusinesshours']; //array of templates where this hook should run $fields = ['summary', 'body']; //array of fields which should be checked //configuration end if(in_array($page->template->name, $templates)){ $changedfields = []; foreach($fields as $fieldname){ if ($page->isChanged($fieldname)) { // Page as it is in the DB $oldPage = wire('pages')->getById($page->id, array( 'cache' => false, // don't let it write to cache 'getFromCache' => false, // don't let it read from cache 'getOne' => true, // return a Page instead of a PageArray )); $changedfields[] = $oldPage->fields->$fieldname->label; } } $changedfields = implode(", ", $changedfields); if(!empty($changedfields)){ $this->warning(__("The following fields have been changed: {$changedfields}")); } } }); Change the configuration block to your needs (template names, field names). This little code snippet outputs only a warning message which fields have been changed - not more or less, but you can also run some other logics - its up to you. Note: Works also with repeaterfields, but you can only check the repeaterfields for changes in general. It is not possible to check for specific fields inside the repeater.1 point
-
Offtopic: no offense, but this is one reason why I stopped using bootstrap, uikit, foundation et al. Looks tempting at first but maintenance becomes a nightmare later.1 point