Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/07/2018 in all areas

  1. I sent him a PM to be sure, new threads and mentions are probably easy to miss.
    3 points
  2. This week we look at two new versions on the dev branch and a lot of updates. These include new page traversal methods, page list customization options, improved empty trash process, two factor authentication improvements, improvements to the profile editor, and more– https://processwire.com/blog/posts/processwire-3.0.115-and-3.0.116-core-updates/
    2 points
  3. Edit: Because of the great response to this topic I wrote a guest blogpost: https://processwire.com/blog/posts/building-custom-admin-pages-with-process-modules/ One of the hidden treasures of processwire seems to be the creation of custom admin pages. Technically speaking those pages are ProcessModules - but i guess that's the reason why so many people out there seem to be afraid of building them... it sounds so hard! You've never created a module for ProcessWire? You have never created a plugin for any other CMS? You have no clue about OOP with all its classes, methods and properties? No problem! I'll show you how simple you can start: <?php class CustomAdminPage extends Process { public static function getModuleinfo() { return [ 'title' => 'Custom Admin Page Example', 'summary' => 'Minimalistic ProcessModule to show that nobody has to be afraid of building custom admin pages.', 'href' => 'https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/', 'author' => 'Bernhard Baumrock, baumrock.com', 'version' => 1, // page that you want created to execute this module 'page' => [ 'name' => 'customadmin', // your page will be online at /youradmin/setup/customadmin/ 'parent' => 'setup', 'title' => 'Custom Admin Page Example' ], ]; } public function ___execute() { return 'This is the most simple Admin-Page you have ever seen :)'; } } Now save this file as CustomAdminPage.module and place it in your /site/modules folder. After a refresh it will show your module in the modules manager of your site where you can install it: After installation you already have your first very own admin page! Congratulations! Was not too hard, was it? It's as simple as that! Now lets add some more custom HTML. And to show you another nice feature we will add this code to a separate method called executeDemo(). And because everything is so simple we will also add some javascript to this page public function ___executeDemo() { $out = ''; $out .= '<h1>H1 has some special css styling in the admin, thats why it seems to have no effect</h1>'; $out .= '<h2>H2 looks different ;)</h2>'; $out .= '<h3>...and so does H3</h3>'; $out .= '<button onclick="myFunction()">Click me</button>'; $out .= '<script>function myFunction() { alert("this is a demo javascript"); }</script>'; return $out; return ''; } Now thanks to ProcessWire-magic your page will already have its own URL: Just append /demo to your url and see what you get: And of course don't forget to click the button Ok, now that code looks a bit hacky, right? Inputfields and especially InputfieldMarkup for the win! We add another method with some advanced code. To use inputfields we need a form that holds all those inputfields and that makes it possible to handle user input lateron. See somas great tutorial about forms here for a quickstart and more details: public function ___executeAdvanced() { $out = '<h2>A more complex Example</h2>'; $form = wire()->modules->get('InputfieldForm'); $field = wire()->modules->get('InputfieldMarkup'); $field->label = 'Markup Test 1'; $field->value = '<h1>h1</h1><h2>h2</h2><h3>h3</h3><h4>h4</h4>'; $form->add($field); $out .= $form->render(); return $out; } Ok, it get's boring Let's do something more fun and add a chart in a second field and change the fields to 50% screen width (I'm sure you know that already from the GUI template editor)! public function ___executeAdvanced() { $out = '<h2>A more complex Example</h2>'; $form = wire()->modules->get('InputfieldForm'); $field = wire()->modules->get('InputfieldMarkup'); $field->label = 'Markup Test 1'; $field->value = '<h1>h1</h1><h2>h2</h2><h3>h3</h3><h4>h4</h4>'; $field->columnWidth = 50; $form->add($field); $field = wire()->modules->get('InputfieldMarkup'); $field->label = 'Chart Sample'; $field->value = '$chart'; //$field->notes = 'Example code taken from here: http://www.chartjs.org/docs/latest/getting-started/usage.html'; $field->columnWidth = 50; $form->add($field); $out .= $form->render(); return $out; } OK, we are almost there... we only need to add the chart library! To keep everything clean we will put the code for the chart in another method. We will make that method PRIVATE to add some security. Our new Method: private function renderChart() { // prepare chart code wire()->config->scripts->add('https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.min.js'); ob_start(); ?> <canvas id="myChart"></canvas> <script> var ctx = document.getElementById("myChart"); var myChart = new Chart(ctx, { type: 'bar', data: { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255,99,132,1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero:true } }] } } }); </script> <?php return ob_get_clean(); } Now we just need to call $this->renderChart() in the right place! Here is the complete Module: <?php class CustomAdminPage extends Process { public static function getModuleinfo() { return [ 'title' => 'Custom Admin Page Example', 'summary' => 'Minimalistic ProcessModule to show that nobody has to be afraid of building custom admin pages.', 'href' => 'https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/', 'author' => 'Bernhard Baumrock, baumrock.com', 'version' => 1, // page that you want created to execute this module 'page' => [ 'name' => 'customadmin', // your page will be online at /youradmin/setup/customadmin/ 'parent' => 'setup', 'title' => 'Custom Admin Page Example' ], ]; } public function ___execute() { return 'This is the most simple Admin-Page you have ever seen :)'; } public function ___executeDemo() { $out = ''; $out .= '<h1>H1 has some special css styling in the admin, thats why it seems to have no effect</h1>'; $out .= '<h2>H2 looks different ;)</h2>'; $out .= '<h3>...and so does H3</h3>'; $out .= '<button onclick="myFunction()">Click me</button>'; $out .= '<script>function myFunction() { alert("this is a demo javascript"); }</script>'; return $out; return ''; } public function ___executeAdvanced() { $out = '<h2>A more complex Example</h2>'; $form = wire()->modules->get('InputfieldForm'); $field = wire()->modules->get('InputfieldMarkup'); $field->label = 'Markup Test 1'; $field->value = '<h1>h1</h1><h2>h2</h2><h3>h3</h3><h4>h4</h4>'; $field->columnWidth = 50; $form->add($field); $field = wire()->modules->get('InputfieldMarkup'); $field->label = 'Chart Sample'; $field->value = $this->renderChart(); $field->notes = 'Example code taken from here: http://www.chartjs.org/docs/latest/getting-started/usage.html'; $field->columnWidth = 50; $form->add($field); $out .= $form->render(); return $out; } private function renderChart() { // prepare chart code wire()->config->scripts->add('https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.3/Chart.min.js'); ob_start(); ?> <canvas id="myChart"></canvas> <script> var ctx = document.getElementById("myChart"); var myChart = new Chart(ctx, { type: 'bar', data: { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], backgroundColor: [ 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ 'rgba(255,99,132,1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 }] }, options: { scales: { yAxes: [{ ticks: { beginAtZero:true } }] } } }); </script> <?php return ob_get_clean(); } } I hope you enjoyed reading this and it will open up many new possibilities for you! Updates: permissions: https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/?do=findComment&comment=174746 tutorial on file uploads: https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/?do=findComment&comment=185261 snippet how to use NavJSON: https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/?do=findComment&comment=216412
    1 point
  4. Building your very own custom Fieldtypes in ProcessWire seems to be hard, but it actually is not, once you get the concept. In this post I'll share a simple and as minimalistic module as it can get that everybody can use as a boilerplate for his own Fieldtypes. A Fieldtype that does not store any information in the database A Fieldtype that stores information in the database (to be done) Make your Fieldtype configurable 1. A Fieldtype that does not store any information in the database Some of you might know the excellent RuntimeMarkup module by @kongondo. I've used it a lot in the past, but I get more and more into developing custom fieldtypes rather than hacking the runtime module to my needs. That has several advantages, but it has also one major drawback: It is always a pain to setup a new Fieldtype, because there are lots of methods (see the base class /wire/core/Fieldtype.php) and you have to know which methods you need, which ones you have to remove and adopt etc.; Not any more! Ryan has developed a showcase module (the Events Fieldtype) to learn from, but when I first peaked into it, it felt quite complex and I thought it would be a lot of effort to learn Fieldtype development). There are also some easy and small Fieldtypes to learn from, like the FieldtypeCheckbox. But all of them require a good understanding of what is going on, you need to modify existing config inputfields that might have been added to that fieldtype and afterall it's not as easy as it could be. With my new approach I plan to use a boilerplate fieldtype to start from (in OOP terms to "extend" from) and only change the parts i need... More on that later. Here is the boilerplate module with some debugging info to illustrate the internal flow on the tracy console: See the module in action in the tracy console ( @adrian has done such an amazing job with that module!!!): The code should be self-explaining. What is interesting, though, is that after the ### getUnformatted ### dump there is only one call to "___formatValue". All the other calls (loadPageField, wakeupValue and sanitizeValue) are not executed because the value is already stored in memory. Only the formatting part was not done at that point. With that concept it is very easy to create your very own custom Fieldtypes: <?php namespace ProcessWire; /** * Demo Fieldtype Extending the Boilerplate Runtime Fieldtype * * @author Bernhard Baumrock, 03.10.2018 * @license Licensed under MIT * @link https://www.baumrock.com */ class FieldtypeDemo extends FieldtypeMarkup { public static function getModuleInfo() { return [ 'title' => 'Demo', 'version' => '0.0.1', 'summary' => 'Demo Fieldtype', 'icon' => 'code', ]; } /** * convert the wakeupValue to the given format * eg: convert a page object to a string */ public function ___formatValue(Page $page, Field $field, $value) { $value = parent::___formatValue($page, $field, $value) . " - but even better!"; d($value, '___formatValue --> convert to whatever format you need'); return $value; } } Notice the change "but even better" in the last two dumps. I think it can't get any easier, can it?! ? I'll continue testing and improving this module, so any comments are welcome! 2. A Fieldtype that stores information in the database See this module for an easy example of how to extend FieldtypeText:
    1 point
  5. If you hook after Page::render you can assign $event->return to a variable and use that.
    1 point
  6. Thanks for the tip! The big bold button is what I need. Site is Ascot Brass, which I converted from a gruesome heap of tables within tables to Clipper a couple of years ago when asked to become webmaster. I decided to try it out as my first Clipper to PW conversion when faced with creating the Members page. Use of templating in Clipper made it reasonably easy to do the original conversion; and I've found the TemplateLatteReplace module suits my way of working in PW. KP
    1 point
  7. Thank you @kongondo! My use case is to display a set of banners. Since the banners themselves are in fact small pages (containing a.html & css file, some images, and a couple of JavaScript files and sometimes web fonts), my approach was to upload a .zip file containing all these files. I made a template where I point to the uploaded folder to show the banner. I display it as an embedded iframe, for example "assets/843") and that works well, only if all the files are in the root folder of that .zip file. But sometimes there are subfolders in the .zip file where extra images, or other assets are stored and needed for the banner. You can imagine I don't want to manual adjust every banner by copying the files in the subfolder to the root and then adjust the .html and css file. So it would save a lot of time to have the ability to upload .zip files with the file structure intact, including subfolders. Any help is appreciated ?
    1 point
  8. Crud will not be that easy. It's easier to open pages in a panel via the regular PW page editor. Linking the page title is very easy using cell renderers. See the aggrid docs.
    1 point
  9. 1 point
  10. And here's another update: I worked on history support. Now each time a document is saved, the "old" version is saved away (under site/assets/cache/.loolversions/$pageid/ with a unique hash as a name) and an entry is added into the versioning table (lool_versions). These versions can already be listed in the UI (File -> Version history opens a sidebar at the right). Also, the UI language for the editor can now be set in PW's profile settings. If you feel daring, you can grab the latest dev branch and take it for a test drive.
    1 point
  11. Looks like there is an include:sendgrid.net missing in processwire.com's SPF record. Your mail admin might be able to add an exception for processwire.com, but since there is a hard fail policy in the record, @ryan needs to change that in his DNS (or perhaps he has already done so but the change hasn't propagated to the DNS servers yet).
    1 point
  12. Update: I finally found a little time to work on the module. The WOPI endpoint (the "server" script that LibreOffice Online talks to) is now created by the installer. Also, there was a bug when PW was installed in a subdirectory, which has been fixed. The next thing I'm going to work on is revision history. This is quite underdocumented territory, so hold your fingers crossed ?
    1 point
  13. Sure we do, not yet in the core though... ? One can give a thumbs-up over here to support the request of adding it to the core: https://github.com/processwire/processwire-requests/issues/126 EDIT: ot here, but Padloper 2 should utilize FiledtypeDecimal, for example prices should be of this type. There are lots of currencies where a price like 100,000,000.00 is quite possible....
    1 point
  14. This is now solved: emptying the trash now uses transactions, if available and I made a PR to BCE which makes it use transactions.
    1 point
  15. This seems to have been caused by a database issue. It's been resolved,
    1 point
  16. Thanks for the updates Ryan! For the children counts in Page List, would you please consider adding hookable methods that return $numChildren and $numTotal? That would allow the option for devs to add a hook to correct those counts in case some descendant pages are not listable by some roles. Thanks. Also, not sure if this is deliberate but I notice the new child count options don't take effect in the Pages > Tree flyout menu.
    1 point
  17. What's your use case? Why is this important? If we got a better picture, we can probably suggest an alternative. Welcome to the forums ?
    1 point
  18. Boolean logic says that, if you want to negate a compound term, you need to negate each individual term AND change the operator. This is commonly referred to as De Morgan's law. !(a and b) = !a or !b Thus, you only need to change the and to or in your if clause: <?php if($item->size->value != 'half' || $item->prev()->size->value != 'half'): ?>
    1 point
  19. 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.
    1 point
  20. I know this is ancient, but: $session->errors('clear');
    1 point
  21. http://tonsky.me/blog/disenchantment/ regards mr-fan
    1 point
  22. 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
  23. https://processwire.com/blog/posts/pw-3.0.86/
    1 point
×
×
  • Create New...