Leaderboard
Popular Content
Showing content with the highest reputation on 03/04/2021 in all areas
-
RockCalculator Add a calculator to any Inputfield in the ProcessWire backend. Setup At the moment there is no UI for defining fields that should support the calculator. You have multiple options: Tracy Console // show rockcalculator and round result to .00 $field = $fields->get('yourfieldname'); $field->set('rockcalculator', 2); // 2 digit precision $field->save(); RockMigrations $rm->setFieldData('yourfield', ['rockcalculator' => 2]); Hook buildForm $wire->addHookAfter("ProcessPageEdit::buildForm", function($event) { $form = $event->return; $page = $event->process->getPage(); // edited page if($page->template !== 'yourpagetemplate') return; if($f = $form->get('yourfield1')) $f->rockcalculator = 2; if($f = $form->get('yourfield2')) $f->rockcalculator = 2; if($f = $form->get('yourfield3')) $f->rockcalculator = 2; }); Github: https://github.com/baumrock/RockCalculator Modules directory: https://processwire.com/modules/rock-calculator/9 points
-
Long time no module ? Github: https://github.com/baumrock/RockIframe Modules Directory: https://processwire.com/modules/rock-iframe/ Problem Sometimes the editor wants to see a preview of a file while editing a page. For example this can be helpful when digitizing invoices. Regular ProcessWire panels can be used for preview but overlap the page editor so the user has to open and close the panel repeatedly while working. RockIframe shows a preview of any content that can be rendered in an iframe and keeps the page editor 100% visible to the user. Usage Simply call $modules->get('RockIframe')->show('path/to/your/file.pdf') anywhere in the admin to show your data in a sidebar iframe on page load. You can also define a Pagefile(s) object as source of the iframe. Example This example shows the first file of the field myfilesfield on the page edit screen of pages having template mypagetemplate: $wire->addHookAfter("ProcessPageEdit::buildForm", function($event) { $page = $event->process->getPage(); if($page->template !== 'mypagetemplate') return; /** @var RockIframe $iframe */ $iframe = $this->wire->modules->get('RockIframe'); if($iframe) $iframe->show($page->get('myfilesfield')); }); Ideas & Notes PDF preview relies on the browser's capability to preview PDFs. Also at the moment there are no checks which content is thrown to the iframe as source. For images for example we could use https://leafletjs.com/examples/crs-simple/crs-simple.html to enable panning & zooming on the image. For better browsersupport of PDF we could use https://mozilla.github.io/pdf.js/web/viewer.html;4 points
-
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=2164122 points
-
Seeing that example it might make more sense to add different options to pw-panel: One showing the panel on top of the background and one pushing the main page to the side while keeping everything visible. That would also make it possible to support mobile devices... If anybody has time, feel free to improve the module ? ? Also if we have any JavaScript experts - I'd love to have the Iframe configurable in its width via mouse drag... no idea how that could be done. At the moment it is set to 40vw.2 points
-
NOTE: This thread originally started in the Pub section of the forum. Since we moved it into the Plugin/Modules section I edited this post to meet the guidelines but also left the original content so that the replies can make sense. ProcessGraphQL ProcessGraphQL seamlessly integrates to your ProcessWire web app and allows you to serve the GraphQL api of your existing content. You don't need to apply changes to your content or it's structure. Just choose what you want to serve via GraphQL and your API is ready. Warning: The module supports PHP version >= 5.5 and ProcessWire version >= 3. Links: Zip Download Github Repo ScreenCast PW modules Page Please refer to the Readme to learn more about how to use the module. Original post starts here... Hi Everyone! I became very interested in this GraphQL thing lately and decided to learn a bit about it. And what is the better way of learning a new thing than making a ProcessWire module out of it! For those who are wondering what GraphQL is, in short, it is an alternative to REST. I couldn't find the thread but I remember that Ryan was not very happy with the REST and did not see much value in it. He offered his own AJAX API instead, but it doesn't seem to be supported much by him, and was never published to official modules directory. While ProcessWire's API is already amazing and allows you to quickly serve your content in any format with less than ten lines of code, I think it might be convenient to install a module and have JSON access to all of your content instantly. Especially this could be useful for developers that use ProcessWire as a framework instead of CMS. GraphQL is much more flexible than REST. In fact you can build queries in GraphQL with the same patterns you do with ProcessWire API. Ok, Ok. Enough talk. Here is what the module does after just installing it into skyscrapers profile. It supports filtering via ProcessWire selectors and complex fields like FieldtypeImage or FieldtypePage. See more demo here The module is ready to be used, but there are lots of things could be added to it. Like supporting any type of fields via third party modules, authentication, permissions on field level, optimization and so on. I would love to continue to develop it further if I would only know that there is an interest in it. It would be great to hear some feedback from you. I did not open a thread in modules section of the forum because I wanted to be sure there is interest in it first. You can install and learn about it more from it's repository. It should work with PHP >=5.5 and ProcessWire 3.x.x. The support for 2.x.x version is not planned yet. Please open an issue if you find bugs or you want some features added in issue tracker. Or you can share your experience with the module here in this thread.1 point
-
Thanks for the tip on pre-selecting the new parent. I long ago gave up trying to use the Move button for anything but reordering among siblings; I find it simpler and more reliable to change the Parent in the page's Settings tab (once I'd found out that was where it was located!).1 point
-
1 point
-
Glad it helps! That's already possible - I've added an example to the readme: $wire->addHookAfter("ProcessPageEdit::buildForm", function($event) { $page = $event->process->getPage(); if($page->template !== 'mypagetemplate') return; /** @var RockIframe $iframe */ $iframe = $this->wire->modules->get('RockIframe'); if($iframe) $iframe->show("http://www.example.com"); });1 point
-
Hey @bernhard seems to be a very good timing to me, this release! ? One question: how would I tell the Iframe to load a page with urlsegments? I don't need to render a file- or imagefield but a sort of external or sibling page that need to be called with an id of the current edited page. Is this possible?1 point
-
1 point
-
Thx @snobjorn for creating the issue https://github.com/processwire/processwire-issues/issues/1339 Everybody having this problem please give it a thumbs up! I'm locked to v171 due to this issue ?1 point
-
Hi @titanium, I don't have had time to install PHP 8 and test out all my sites and modules under it. I will do so with priority for WireMailSmtp. But it may take 1 or 2 weeks, sorry.1 point
-
There might be a better approach, but this snippet in site/ready.php works for me: <?php namespace ProcessWire; $wire->addHookBefore('ProcessPageLister::execute', function(HookEvent $event) { if($event->page->process != "ProcessUser") return; # Put all fields that should be searchable by default here: $userSearchFields = ['email']; # We create a comma separated field selector string from the array above for use by ProcessPageLister $searchFieldsString = implode('', array_map(function($f) { return ", $f="; }, $userSearchFields)); $lister = $event->object; # ProcessUser appends the ", roles=" selector before our hook happens, so we inject our fields # before that part: $lister->defaultSelector = preg_replace( '/(?=, roles=)/', $searchFieldsString, $lister->defaultSelector ); }); ProcessPageLister builds its field list from the selector style string its $defaultSelector property. So you just need to put the names of your fields into the $userSearchFields array and ProcessPageLister will take care of the rest. If you want to completely replace the search field list, it's even simpler. <?php namespace ProcessWire; if($event->page->process != "ProcessUser") return; # Put all fields that should be searchable by default here: $userSearchFields = ['lastname', 'firstname']; # We create a comma separated field selector string from the array above for use by ProcessPageLister $searchFieldsString = implode(', ', array_map(function($f) { return "$f="; }, $userSearchFields)); $lister = $event->object; $lister->defaultSelector = $searchFieldsString; }1 point
-
What we need is really easy ways to contribute and build motivation towards contributions. - slack/discord for real-time Comms - merging PRs in the Processwire repo instead of the weird closing the PR and copy pasting it in. I raised a PR years ago, got no feedback and was told it may have fine in via copy and paste. I closed the PR myself to reduce noise and haven't entertained the idea of contributing since. Unless this has changed, start treating it like a modern open source project - roadmap on the GitHub board - indentified maintainers on the GitHub repo - a backlog / causal kanban style agile setup - monthly maintainer video calls to go over backlog etc. Maybe anyone can join. Maybe video recorded. - a patron or way to donate to the PW project. This pot can be used to pay maintainers to work on critical features etc. E.g. through donations with have enough money to fund 1 week of work, what should Ryan / another maintainer take time off their normal work to work on. - key goals established for the core maintainer team. We should as a whole be marching the same direction. (Though obviously people can work on what they want, but has to pass review) - a plan that @ryan is comfortable with to slowly distribute the reigns. We don't want to move too fast and over burden the core. - some sort of backlog voting system, instead of posts on the forum. - Id really like to modernise the process around Processwire. That scares anybody larger than a sole freelancer away from the project. Bigger users mean more support. More pro modules being sold etc. - on that note. Can we have the shop not just be Ryan's modules but extended to other pais for modules. I don't like that they are strewn across the web. (And Ryan charge a fee.)1 point
-
Long time no post. Here's my latest: https://maisliberdade.pt/ Mais Liberdade is a liberal think-tank in Portugal, promoting the values of liberal-democracy, individual freedom and free market economy. It's a non profit that gathers collaboration from people from multiple portuguese political parties, members of the european parliament, economists, professors, etc. During development, an announcement page was set up with a registration form for founding members. In that period of about a month, around 200 subscriptions were expected, but in the end we got over 6000 subscribers. This website features essays, events, videos and a free library that, at the time of this post is counting 400 books. The frontend was built using web components (Stencil js). Basic pages are built with a modular approach, I'm attaching a video of how they are created. The approach is a simple repeater with a custom block type selector interface. That selector is basically a modified version of FieldtypeSelectFile. I've hacked that module to expect a PNG to be available for each PHP file in the blocks folder, and modified the input field to generate a button grid after the select. This is lovely to use from the editor's perspective, but it's something to improve for the developer experience, because in the end this is a repeater, that has to contain all fields that each type of block needs, and for each of those fields I have to set it to show only if the blockType field equals X, Y or Z. With a lot of different block types this takes some planning and easily becomes hard to manage, but it's the best approach I found yet and the benefit for the editor's experience is well worth it. covered-compressed.mp41 point
-
When webmaster un-globals the Title field (for instance to have a person template with first and last name), there are some unintended consequences. For a site that uses Title on 90% of templates, un-global isn't really useful because it makes adding a new page harder for novice editors: Title field disappears from "Add New" dialog. When I "Add New" page using a template that DOES use the Title field, then the Title field is no longer shown in the Add New dialog window (in this window, an editor will enter Title and Name - and the page is then created and shown to the user in edit mode). No other "pseudo-title" fields can be added to the "Add New" dialog (and it's not possible to skip the two-step page creation process). (There is no simple way to pre-populate the Title field on templates.) Consider these flows: When Title field is global: Steps: From Page Tree, press New to create a new page, "Add New" page is shown with Title and Name fields, (User may need to select Template) Enter Title (Name is automatically set), The new page is shown - start editing fields Observation: Title and Name are shown on same page (good!). Page is created with little mental effort. When Title field is un-global and Page Template has a Title field: Steps: From Page Tree, press New to create a new page, "Add New" page is shown with Name field (but Title is no longer shown when template DOES have the Title field), (User may need to select Template) Enter Name, The new page is shown - start editing fields ("where am I?"). Enter Title (user no longer sees Title and Name at the same time) Observation: Redundant entries (Name and Title are often identical). Name and Title are separated across pages. Better: Show Title and Name on "Add New" page, use Title to set Name (as when Title field is global). When Title field is un-global and Page Template doesn't have a Title field: Setup: Webmaster goes to Template -> Advanced to set "List of fields to display in the admin Page List" (example: "{foo} - {bar}"). Thanks to Robins S for pointing this out. Webmaster cannot specify "Title" fields to be filled in on the "Add New" page. Steps: From Page Tree, press New to create a new page, "Add New" page is shown with Name field, (User may need to select Template) Enter Name, The new page is shown - start editing fields ("where am I?"). Better: Setup allows webmaster to specify "Title" fields to be filled in on the "Add New" page. Even better: Skip the "Add New" dialog page and go directly to the resulting Title page (when only one Template can be selected). Maybe by adding a GUID or other temporary page name that is later renamed? Also I don't think it's possible to pre-populate the Title field in the Administration? (for details, see Pavle's comment). See also: Creating a page without a title? (from 2012 - so I think it's OK to begin a new thread).1 point
-
+1 for a solid database migration mechanism. Deploying field/template updates to production involves a lot of manual copy/pasting. Having a built-in way of describing changes in database structure would make automated deployments and rollbacks possible.1 point
-
Thanks for all your suggestions. Here is what I use right now in my ready.php $wire->addHookAfter('AdminTheme::getExtraMarkup', function (HookEvent $event) { $parts = $event->return; $parts['head'] .= '<link rel="stylesheet" href="' . $this->config->urls->templates . 'admin/admin.css">'; $parts['head'] .= '<script src="' . $this->config->urls->templates . 'admin/admin.js"></script>'; $event->return = $parts; }); I don't want to rely on another module like AoS or AdminCustomFiles, because I think adding another module just to add styles and JavaScript is overkill and bloat. Instead I want to add the assets in my own modules, or in ready.php. I still think that it would be good in the core, and the core could still be lean. There are already methods there to prepend or append assets, but they don't work correctly because of the init order. Mainly the problem is that core modules should be loaded first with their assets like jQuery and CSS, etc, and then I should be able to add my assets after them to override them. I know it might be a specific case, where you want to alter default behavior and styles of the admin, but it is something I often need. In most cases the actual behaviour $config->styles->add($config->urls->templates . "admin/admin.css"); is just fine, if you are not trying to override some styles1 point
-
1 point
-
Just click on the "Change" button and hover over the currently selected page in the tree. The "unselect" button will pop out next to it. It's a bit hard to find, especially using the UIKit admin theme.1 point
-
I haven't had much (enough) time to work on my mailer module and haven't looked at how WireMailSMTP handles these particular things, but in general I'd have to agree with Pete. For things that are commonly used, it'd be best if there was a "standard" way to do that. One that doesn't depend on which module extending WireMail is installed at the time. I believe that we're talking about interfaces here, though that's not technically what it's going to be.. or what it is at the moment, at least. Then again, if @horst has implemented this feature already, I'll probably take a look at his implementation anyway and use similar public methods if possible to provide some consistency1 point