Jump to content

bernhard

Members
  • Posts

    6,629
  • Joined

  • Last visited

  • Days Won

    358

Everything posted by bernhard

  1. i think most of us can handle this pressure of course it will not pay back the time invested but it's nice to have the possibility to say thank you. but of course if someone wants to invest more time on a module making it commercial is totally fine. i'm also thinking about that topic... regarding the docs i would love to see some kind of standardisation here. maybe someone knows a good solution already.
  2. i don't know how the guys from uikit are doing it but they have nice docs and it seems that everybody can post suggestions (there is an edit button on all pages): https://getuikit.com/docs/icon it's unbelievable how much you contributed to the community so far - a donation button would be the least imho. i've already asked you for that some time ago
  3. yeah, i was just starting to write a reply here, then dave was first and then i decided to start a new topic, because we got offtopic here and i'm sure it's valuable information for others as well. here is the tutorial:
  4. hi @mtwebit welcome to the forum and thanks for that module! i've created something similar for one of my projects but it's custom and not built into a module so i think there's potential for what you are doing some ideas/questions/feedback: use InputfieldMarkup to structure your custom code and make it look&feel more native. see my new tutorial here: do you know the wirequeue module? would be great to have an easy way to integrate this into other modules or custom pages. maybe it is already possible - i'll have a look when i have more time This is how my progressbar looks like using InputfieldMarkup:
  5. 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
  6. thx, didn't know that - a search led me to the plugin i mentioned above...
  7. if you want to register urls to open directly in vscode you can use this plugin and follow the instructions: https://github.com/shengyou/vscode-handler then fill in the 2 fields in tracy (url + local path) and you can directly click on links and they will open up in vscode
  8. Mpdf has a pagebreak method and you can also add CSS avoid-pagebreak to prevent two blocks from being split into multiple pages. I'm using [pagebreak] tags in ckeditor to give my clients the possibility of adding breaks
  9. Thank you Sam Give yourself 30 minutes and learn to create a process module. Use InputfieldMarkup and you'll be impressed what's possible
  10. I'm always using field names like password, email, name or the like. I guess most bots are more likely to fill fields with those names than any cryptic names.. would be interesting to try that in your case and see if that helps
  11. Do you have more information why it failed and how exactly you did the setup (field names, time checks..)?
  12. hi donald, the module is not intended to be used on the frontend. though it is not that hard to do it... example home.php <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <title><?php echo $page->title; ?></title> <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.34.5/handsontable.full.min.css" /> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/handsontable/0.34.5/handsontable.full.min.js" /> </head> <body> <h1><?php echo $page->title; ?></h1> <?php if($page->editable()) echo "<p><a href='$page->editURL'>Edit</a></p>"; ?> <?php bd($page->cars); ?> <div id="example"></div> <script type="text/javascript"> var container = document.getElementById('example'); var hot = new Handsontable(container, { data: <?= json_encode($page->cars->data) ?>, rowHeaders: false, colHeaders: <?= json_encode($page->cars->colHeaders) ?>, }); </script> </body> </html> the field config for the backend: $(document).on('afterInit.rht', '.handsontable', function(e, hot) { var colheaders = ['Volvo', 'Audi', 'BMW']; hot.updateSettings({ colHeaders: colheaders, minCols: colheaders.length, maxCols: colheaders.length, maxRows: 1, minRows: 1, rowHeaders: false, }); }); i don't know any technical details of the other module. i built this module to have a quick and easy way to INPUT some table data and be able to copy&paste from excel. for me the benefits of this module compared to the matrix field is the look&feel. it's more compact and more excel-like, so it's easier to grasp for my clients. but the field has some major limitations you have to keep in mind. for example changing inputfield config after some data already has been stored would lead in data destruction. its also not possible to use this data in selectors. and multilang values are not supported. thats no problem as long as you have only have numbers as data because you can translate column headers (see above example).
  13. Wishlist --> Posted Saturday at 03:12 AM New Module --> Posted Saturday at 06:08 AM crazy
  14. never used it but you could save another line with conditional hooks https://processwire.com/blog/posts/new-ajax-driven-inputs-conditional-hooks-template-family-settings-and-more/#new-conditional-hooks $wire->addHookAfter('Page(template=admin)::render', function($event) { ... });
  15. Sure, just hook page render and modify event->return like I showed above. I'm on mobile but this info is easy to find in the forum, it's nothing special
  16. You can also inject scripts and styles by hooking the page render and doing a str_replace("</head>", $yourscripts . "</head>", $event->return)
  17. hi avd and also welcome from my side, nice to hear that you get a pw site. maybe you can share your experience of pw after your first steps with us? would be interesting to hear! in processwire you can make almost everything editable. you CAN. but it's all up to the developer. and in my opinion thats a good thing. so the question is always WHY do you want to make this or that editable. if you have a valid reason one can just create a field for that and build that functionality into your site. but for other things that will not (or should not) change often it's better to change the code directly (and fonts seem to be a good example for that). hope you enjoy pw and your agency does a good job
  18. agree but of course you can combine markup regions and includes... agree
  19. you need to use pw's built in translation tools on the server side and send the array to your client (js): // some php file loaded in the backend $config->js('colheadersformyhandsonfield', [ 'col1' => __('First column'), 'col2' => __('Second column'), ]; then you can assign them in the js: $(document).on('afterInit.rht', '.handsontable', function(e, hot) { var colheaders = ProcessWire.config.colheadersformyhandsonfield; hot.updateSettings({ colHeaders: colheaders, minCols: colheaders.length, maxCols: colheaders.length, }); });
  20. @SamC what are you trying to do exactly? Like always in PW it's up to you. Just wanted to mention markup regions because I didn't see anybody mentioned them. If others are happier with using includes that's totally fine Ps: if performance is a factor for you the best you can do is to invest some euros and 3 minutes to download and install procache. No matter what technique you are using for generating the output, procache will make it lightning fast even on slow servers
  21. i haven't used markup regions on larger projects. ryan said its a little more overhead. but for smaller projects imho it is the cleanest and easiest solution. i think its much easier to understand for newcomers than the regular delayed output. it was also great to work together with my designer
  22. wow, did'nt read all the answers, but it seems nobody mentioned markup regions anywhere? soma's post is a must-read of course, but it's also from 2011 and we now have the same functionality a lot easier and cleaner imho: https://processwire.com/blog/posts/processwire-3.0.62-and-more-on-markup-regions/ a simple setup could be: _main.php <html> <head> <!-- scripts&co --> </head> <body> <section id="header">your header, menu or the like...</section> <region id="main"></region> <section id="footer">your footer</section> </body> </html> home.php (really no other markup than this in this file!) <section id="main"> <h1>Welcome to my website!</h1> <p>This is the awesome text of my awesome website</p> </section> blogitem.php (for example) <section id="main"> <h1>Blog Item <?= $page->title ?></h1> <?= $page->body ?> <ul> <?php $page->siblings("id!=$page")->each(function($p) { echo "<li><a href='{$p->url}'>{$p->title}</a></li>"; } ?> </ul> </section> This will render your website with header and footer, inject scripts on all sites and just change the content of the main section on your pages.
  23. sure: // save data or print errors if(!count($err)) { $answer = $feedback->answers->findOne("competence=$compid"); $feedback->of(false); // save data // if answer does not exist, create it if(!$answer OR !$answer->id) { // add a new repeater item $answer = $feedback->answers->getNew(); $feedback->answers->add($answer); $feedback->save(); } $answer->of(false); $answer->competence = $comp; $answer->rating = $rating; $answer->noanswer = $noanswer; $answer->textfeedback = $textfeedback; // save the changes $answer->save(); // update numanswers field, quickfix for this: // https://processwire.com/talk/topic/17549-is-this-a-wrong-selector-or-bug/ $feedback->save(); } else { // print errors echo implode("\n", $err); } edit: setAndSave was wrong in this regard - i'm using it only to set the repeater values when somebody provides a new rating
  24. thanks robin, i found the problem! by coincidence i had to modify one feedback and manually save it. now i wanted to investigate further and got a count of 1 for the answers.count>0 selector. then i saved another page and got a count of 2. so the repeater.count selector seems to work only after a page was saved. i set all the values via API so the selector didn't work. first i thought it's maybe because of setAndSave() but even after a foreach and page->save() the selector didn't work. it works only after a manual pagesave. my quickfix is an additional field + saveready hook that populates the number of answers. I'll file an issue on github.
  25. maybe this? https://processwire.com/blog/posts/inline-ajax-page-editing-comes-to-listerpro-processwire-2.6.6/
×
×
  • Create New...