Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 10/11/2017 in all areas

  1. @monchu, thanks for the reply. It's not quite what I'm asking about - it's the default sort order I'm interested in and why a new page would be inserted in the middle of existing pages. I did manage to figure some stuff out... Firstly, it seems the 404 page, Admin and Trash are always sorted last. There's no changing that, which is fine. Also, looking at the "sort" column of the "pages" table in the DB it looks like there were gaps in the sequence of sort values of pages under Home. Because of those gaps and also the fact that some of the pages that are part of my site profile happened to have high sort values, new pages were being inserted above them in the tree. So I fixed the gaps with... $home = $pages->get('/'); $pages->sort($home, true); // re-build sort values for children of $home, removing duplicates and gaps ...and then I manually gave high sort values to any pages that I want to keep at the bottom of the tree (but still above 404, Admin, etc, as per the above)... $p = $pages(1016); // the Form Builder page $pages->sort($p, 99); // set the sort value to a high number Now new pages are going just where I want them.
    5 points
  2. @bernhard Here's a preview of some features I use frequently: Variable hinting for API variables for intellisense (when not using API functions, such as page() instead of $page) Ctrl + Q for instant documentation Ctrl + Left Click for instant jump to source. Error hinting Refactoring and reformatting Proper step by step debugging using XDebug Stack trace, scope and global variables, console Variable watchers
    3 points
  3. I've just made a few more tweaks so that now you can have mixed html and php in your snippet file. For example this: <p>Welcome to the <?=$page->name?> page!</p> will return: This might come in handy for testing snippets of template code if you use a direct output approach, or markup regions, or anything else where you are embedding php into HTML tags. The only downside is that now pure PHP snippet files must start with a php open tag. I think this is a quite acceptable compromise as I couldn't imagine writing code in my editor without it. You can also do this with the Console Panel, but you have to start the snippet with ?> to close the automatically added PHP tag, eg: ?> <p>Welcome to the <?=$page->name?> page!</p> This is because the Console Panel always adds an opening PHP tag if it doesn't find one - I think this is best here because it's nice to not have to manually add when doing a quick code test. Anyone have any thoughts on these new abilities - does anything seem illogical?
    3 points
  4. I think that processwire is easier because I did exactly this comparison. Not with zero knowledge of programming, but zero knowledge of both CMSs. Tried with wordpress, got so fed up, switched to PW, made a site with everything I required in a month or so. I find the word 'easy' a bit misleading here. I found PW fitted in with my mindset a lot more than wordpress. The hierarchy, the realtionships between objects, everything makes more sense to me, therefore makes it easier understanding the API. I have no regrets at all about spending the last 15 or so months with PW I use it about once every two days. Since about 2010, I used Umbraco CMS (liked this), Drupal 7 (did the job), Craft CMS (liked this), Wordpress (tore hair out), then Processwire (love it!). Two things that stand out to me: 1) I can't give this forum and it's members enough credit for the help they have given. They are patient, very friendly, don't insult you when you ask beginner questions and you get replies so quickly. You can't even put a price on that IMHO. 2) My excitement and enthusiasm to web design has gone through the roof since starting PW because, at last, I have the confidence in being able to create whatever I want, with any design I want, using any framework (or no framework) I want. This is mainly because of (1) above. ...and @bernhard prefers making websites with processwire to flying a helicopter! Now that says how awesome it is
    3 points
  5. A client of mine was asking for a solution to send newsletter mails to a list of subscribers. I looked around for a module, but couldn't find any. Then I saw a screenshot on this blog post about UIKit update, and decided to recreate it. Huge thanks to @ryan for the inspiration. The module uses regular pages for building HTML content. These pages can be used to create a fallback link in emails (i.e. "Use this link if you can't view email properly"). During render it injects $page->mailerMode, which can be used to change page output between text and HTML, or to show a simplified, email only HTML output. Screenshots: Main screen is just a list of items. Create page: Module configuration page: During installation, module creates a page under admin for storing items similar to FieldtypeRepeater. It also creates some fields for storing mail info Todo: More testing Sending in batches (with a script that runs in background and real-time progress log) Plans: Integration with Mailchimp (for subscriber lists) Automation (as a separate module for creating email content pages) I'm hoping to complete and release the module in the following days. I think these features should be enough for the beginning, but I'm open to suggestions.
    2 points
  6. FYI: for regular CKEditor fields, there's @Robin S's plugin that lets you add hanna codes quickly https://modules.processwire.com/modules/hanna-code-dialog/
    2 points
  7. You named the hanna code as `test`, it should have been `include` instead. (or use [[test file=test]])
    2 points
  8. Hi @heldercervantes You can use getForPage method.
    2 points
  9. https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/#processwire-3.0.5-introduces-field-rendering-with-template-files
    2 points
  10. The thing with processwire, if you are a none coder and coming from systems like modx, wordpress, drupal, etc. your familiar way of approaching things won't work anymore. You have to invest time to get rid of old habits. Nothing comes out of the box with processwire. But that is the great thing about it. No longer searching for "the" cms that has it all, but a way that let's you do it all - processwire. But one thing is true also, experienced coders have great advantage with processwire compared with none coders.
    2 points
  11. great to hear that you are working on that, indeed very needed! how do you plan to send the emails? imho it would be nice to be able to easily integrate services like https://www.sparkpost.com or https://sendy.co/ . i'm not sure but i think for large amounts of emails it is better to use some kind of substitution based sending method (https://developers.sparkpost.com/api/substitutions-reference.html ). good luck for this module and have fun
    2 points
  12. Working perfectly, thanks.
    2 points
  13. So many goodies hidden in the core. Find a proper IDE that lets you navigate around classes easily (PhpStorm, free for students, yay!), and you're pretty much set.
    2 points
  14. https://www.baumrock.com/portfolio/individuelles-crm-und-controlling-tool/ I'm happy to share my biggest and most interesting ProcessWire project so far with you It's a 100% custom office-management solution that helps my client to keep track of all their contacts, projects and finance/controlling stuff. Conception was done back in 2016 and the software is productive since begin of this year. My client is very happy with the result and so am I. Some technical insights: Everything is done inside the PW Admin. I'm using the Reno Theme with some custom colors. In the beginning I was not sure if I should stay with the pw admin or build my own admin-framework but now I'm VERY happy that I went with PW Almost all of my custom Process Pages use my RockDatatables module - there are still some limitations but without it, this project would not have been possible For the charts I used Google Charts and chartjs - both play well together with the datatables and make it possible to display filtered data instantly: also my handsontable module was created for this project to have a nice and quick option for matrix data inputs: Lister and ListerPro were no options as i needed much more flexibility regarding data presentation (like colorization, filtering and building sums of selected rows): invoices are highly customisable as well and easy to create. PDFs are created by php and mPDF by the way: all data is dummy data populated via my Module RockDummyData have a nice weekend everybody
    1 point
  15. If anyone's interested, I've forked Ryan's ProcessWireUpgrade module and added the ability for it to detect if github has a tagged release for the latest version of each listed module (except for the PW core repos which will require special handling). If a tagged release entry is found, it then adds an extra link to the table. This is strictly an alpha "proof-of-concept" experiment, but if you are interested my fork of the repo is here - just replace the current version of the module code with my fork and you should be OK. Providing module authors start tagging their releases on github, it will allow you to navigate to the release notes for review before you hit the upgrade link. As you can see, Mike Rockett has already started tagging his releases - and hence his module gets the extra "Release Notes" link. Worthwhile idea?
    1 point
  16. Sorry to resurrect an older post, but I just had to provide an update. This is Margaret (also known as Margie, the one who started this thread - that's my personal account), as we got the go ahead to replace our current CMS with ProcessWire! This is our new AAD web team account. The web team is comprised of Warwick (web manager), myself (web developer) and Narelle (web developer). AAD = Australian Antarctic Division. We're just getting started at the moment, testing out some modules and so forth, but I expect you'll be seeing some more of us around the forums as we get further into moving all our sites across to ProcessWire!
    1 point
  17. I've encountered the same problem with many people specifying that any bids for a web site must be Wordpress. I come from a database development background, mostly doing Microsoft Access desktop apps, but also some web development, and even made my own CMS way back when Wordpress was only a dream waiting to happen. I'd describe Processwire as being data driven, whereas Wordpress is content driven. By that I mean that Wordpress revolves around posts and pages, whereas although Processwire calls them Pages, Processwire pages are really totally different beasts to Wordpress pages, and are really a less nerdy name for what are really objects, which can have any properties you like, and may not even be 'pages' in the publishing sense at all. If you want a blog using an existing theme, Wordpress is the way to go. If you want a web site that has to deal with pretty much any data structures you want to throw at it, Processwire is the way to go. Wordpress needs a plugin to do custom field types, and plugins to do lots of other things, and those plugins don't necessarily peacefully coexist or have consistent UIs. With Processwire, you start off bare-bones but can build anything you like quickly and efficiently. The development process for me is far more like building something with Microsoft Access, in that you design you data structures (fields, and I believe with Profields, you can actually do tables, but I haven't had enough work to justify that yet) and then add them to templates which are like forms or reports in Access. Site profiles are a bit like predefined Access templates for specific tasks. Perhaps it would be good to work towards a wider range of free and premium site templates available, but rather than modelling them on Wordpress themes, model them on Access templates, then people will see that Processwire is more of an app platform than just a web site CMS. Processwire can't really have 'themes' in the Wordpress sense, because those rely on assumptions about what data structures you have, whereas with Processwire, a site profile has to define data structures as well as presentation, as Processwire doesn't have any inherent data structures like posts or pages in a Wordpress sense. The reason Access was, and still is so wildly popular amongst a small group of developers is that it is the quickest way to develop a desktop front end for pretty much any kind of database app you might want to build, even if it has some inherent issues that IT departments don't always like. There are a few things I wish Processwire did differently, eg I'd like referential integrity at the database level, and I'd like to be able to use other database systems other than mySQL/MariaDB, (eg PostgreSQL, SQL Server) , but the reality is it's the most efficient tool I've found for quickly defining and presenting any kind of data on the web. With Wordpress, structured data is an afterthought, with Processwire it's core.
    1 point
  18. I recently switched to VSCode from Sublime Text and I haven't looked back since. Was hoping to make a demo of how I'm using it in my development...but haven't got the time...yet. I'm getting intellisense, step-by-step debugging (including CSS debugging!), terminal, grep, diff checker, push to Github, JS/HTML/CSS/PHP documentation, phpDocs, etc...the works!
    1 point
  19. I just wanna give @abdus here some big praise...he really helped me out here! Thanks again dude!
    1 point
  20. Ok, this was a very weird problem. It turns out that when submitting a form with JS, value of the submit button isn't posted with the form, that's why if ($input->post->submitForm) wasn't working as it would normally. We've solved the problem by checking for another field, `stripeToken`, to ensure that the form has been posted properly before processing the credit card. https://stackoverflow.com/questions/1709301/javascript-submit-does-not-include-submit-button-value Another way to solve this problem would be listening to submit button click instead of form submit, then preventing default action, validating the form with Stripe, and actually triggering click on the button.
    1 point
  21. Add hanna code to field's textformatters. Setup > Fields > <fieldname> > Details > Textformatters
    1 point
  22. Just an FYI - in the Console panel you can now do mixed HTML/PHP without needing to add a php closing tag first. <p>Welcome to the <?=$page->name?> page!</p> File-based snippets (Snippet Runner) can be plain html, plain php, or mixed html/php, but they must have an opening php tag as per normal PHP requirements. The Console panel does not require an opening PHP tag (although having one will still work). You can use mixed html/php as per the example above, but for a pure HTML file you will need an initial ?> before the HTML to make it work, eg: ?> <p>Welcome to this page</p> Plain html in the Console seems like a pretty uncommon use case, so hopefully this gives us the most flexibility without too much weirdness.
    1 point
  23. You couldn't believe your eyes at first, could you?
    1 point
  24. Precisely! Thank you Zeka, you've just saved my life.
    1 point
  25. what is the built in debugging? again my recommendation: use tracy you'll get nice info like this: https://processwire.com/blog/posts/introducing-tracy-debugger/#bardump you could just do a bd(ukBlogPosts($posts)) and see what this function returns and why count(ukBlog...) returns 1. you could also see the docs to this function in the code that says that it returns a string: https://github.com/ryancramerdesign/regular/blob/master/site-regular/templates/_uikit.php#L720 ... so count() correctly returns 1 ---------- but back to your initial question: i think it would be much easier to just use the API and forget about the uikit functions that are shipped with the profile! in your case it would be as easy as this: <ul> <?php foreach($pages->get('/categories')->children as $cat) { echo '<li class...>' . $cat->title . ' (' . $cat->numChilrden(true) . ')</li>'; } ?> </ul>
    1 point
  26. Yeah, but it's a little bit trickier than what you have shown. $pagesList= $pages->get("/"); foreach($pagesList as $page){ } If you do this, $pagesList is just the Home page by itself - it isn't a PageArray you can loop over to get all the pages in your site. For a full listing of pages you actually need to use a recursive function like Ryan's example here: Just wanted to point this out in case a beginner actually tried to use your example.
    1 point
  27. Hi @cleanboy I think i'm right in saying that the payment modules are wrappers for the Stripe and Paypal libraries, therefore you can access the Stripe methods in Processwire. That said, I think you were asking how to use it, the example shows how you can pass amounts and basic customer information to Stripe, if a successful request is made Stripe pass you back a payment button which enables the customer to click and add their card details. The module does not store any information on the purchase, what was purchased, who by or anything infact, its just a way of interacting with Stripe or Paypal. If you need to track payments or are selling physical items you will need someway of keeping track of transactions and items like a store e.g. padloper or create your own tracking (which I've done several times mainly because I've been selling digital goods like subscriptions so have little need for item tracking or postage variables). Hope that helps.
    1 point
  28. Any chance of mod_security in action?
    1 point
  29. You can sort them from your home template, under Family tab
    1 point
  30. All good now, thanks.
    1 point
  31. Sorry about that - I am not seeing that, but I see where it's coming from. Please try 4.6.5 and let me know. PS Don't forget to enable the new Request Info panel which now contains most of the info from the old version of the PW Info panel
    1 point
  32. @adrian, I'm seeing an error in the back-end AJAX bar after I save a page. Tracy v4.6.4
    1 point
  33. @Robin S - please try the latest version which supports declared namespaces in both Snippet Runner and Console panels.
    1 point
  34. It seems that, when developing a Fieldtype that requires user input (Inputfield, in this case), both modules must be developed in tandem? In other words, it's not something that could easily be tested against during development to create just the Fieldtype, or just an Inputfield (again, for something like this)? I didn't see your Edit before, but that was very helpful, as well as the mention of extending FieldtypeMulti (instead of just Fieldtype) -- thank you!! ...just saw the Module.php file in core -- so THAT's where all of the documentation is!
    1 point
  35. Ok, they are now a list of icons with labels by default with an option to turn off the labels in the module settings. Hope that helps! Of course if you are upgrading you will need to check the option.
    1 point
  36. CKEditor fields are regular HTML strings, they're not evaluated as PHP. Even then, whatever you write in the field is encoded, so < and > for example will turn into &lt; and &gt; HTML escaped variants. Your problem can be solved easily with Hanna Code
    1 point
  37. Thank you guys for replies. I will take a look at them
    1 point
  38. maybe a nice showcase of what can be done with processwire with VERY little code
    1 point
  39. https://www.baumrock.com/portfolio/event-voting-tool-social-impact-award/ Another nice little Showcase of what can quickly be done with Processwire I sponsored this voting tool for the Austrian Social Impact Award ceremony (https://socialimpactaward.net/) helping them to pick the winner of the audience voting. The site is based on the default UIKIT theme (obviously) and i basically just placed the logo + changed the colors. The site structure is also very simple, having only one parent to store all teams, one parent to store all votes and one page to show the results (to the admins): The Projects-Template stores some informations of the project and the vote-count: All the votings are single pages as well having only one checkbox, ensuring that every code can only vote once (every visitor got one code at the entrance): Votes are created via Tracy Console as easy as that: The hook that creates the passwords is also simple: /** * create unique code for voting */ $wire->addHookAfter('Pages::saveReady', function($event) { $page = $event->arguments(0); if($page->template != 'vote') return; if(!$page->title) { $rand = ''; while(!$rand OR pages("title=$rand")->count() > 0) $rand = randomPassword(); $page->title = $page->name = $rand; } }); And finally the check if the vote for this code is already done (inside the vote-template). the whole vote-template is as simple as that (thanks to the awesomeness of markup regions and functionsapi): <?php namespace ProcessWire; // handle votes (url segments) if($id = $sanitizer->int($input->urlSegment1)) { // if voting is locked redirect to thankyou message if($page->votingdone) $session->redirect($page->url); // else set voting $team = pages($id); if($team->id) { // increase voting for this team $team->setAndSave('votes', $team->votes+1); // lock this votings page $page->setAndSave('votingdone', 1); } } ?> <?php // if voting is done show thank you and lock page if($page->votingdone): ?> <region id="main"> <div class="uk-card uk-card-primary uk-card-body uk-width-1-1 uk-margin-small-top uk-text-center uk-border-rounded"> <h3 class="uk-card-title">Danke für Ihre Teilnahme!</h3> </div> </region> <?php return; endif; ?> <region id="main"> <div class="uk-text-center uk-margin-top"><?= $page->parent->body ?></div> <?php foreach(pages('template=team, sort=random') as $team): ?> <div class="uk-card uk-card-default uk-card-body uk-width-1-1 uk-margin-small-top uk-border-rounded"> <h3 class="uk-card-title uk-text-center"><?= $team->title ?></h3> <ul uk-accordion="collapsible: true"> <li> <p class="uk-accordion-title uk-text-center"><span uk-icon="icon: chevron-down"></span> Beschreibung anzeigen</p> <div class="uk-accordion-content"> <?= $team->body ?> </div> </li> </ul> <a href="<?= $team->id ?>" class="uk-button uk-button-large uk-button-primary uk-width-1-1 uk-border-rounded">Für dieses Projekt abstimmen</a> </div> <?php endforeach; ?> </region> I'm still impressed by ProcessWire and how much can be achieved with how little effort
    1 point
  40. I am sure it will! The challenge will be if someone asks you to work on a project with something else
    1 point
  41. You need to either put the call to count() outside of the string or use curly braces. So both of these should work: // outside of string $out .= "<a href='$item->url'>$item->title</a> <span class=''>" . $item->children->count() . "</span>"; // or with curly braces $out .= "<a href='$item->url'>$item->title</a> <span class=''>{$item->children->count()}</span>";
    1 point
  42. if u wanna use ukNav() function, u would need to edit it to display count. I dont know how your categories and post are structured, but based on ur post, this can maybe help: $categories = $pages->get('/categories/'); echo "<ul class='uk-nav uk-nav-default'>"; foreach($categories->children() as $cat) { echo "<li><a href='$cat->url'>{$cat->title} {$pages->find('categories=$cat')->count}</a></li>"; } echo "</ul>";
    1 point
  43. Simply put: a field is an interface to DB, an inputfield is an interface to user. One does not necessitate the other, but for some complex data types, you may need to build a custom inputfield (like MapMarker). If you're going to store information about multiple books on a single page, then you need to extend FieldtypeMulti class (FieldtypeEvents, FieldtypeNotifications, FieldtypeComments for example), to store information about a single book per page, you need to extend regular Fieldtype class (FieldtypeText, FieldtypeDatetime etc). If you want to allow more than 1 property to be used in selectors, then you need to use multiple table column in DB. This means you need to override getDatabaseSchema() method and specify a more complex table structure. Edit: Based on your description, you expose only one input to the user for ISBN/title, filling the rest is up to you (by fetching from a web service). You have two options: either fetch the data using fieldtype or using inputfield. Using inputfield to do fetch the rest of the data sounds more appropriate, because the purpose of the fieldtype is validation, formatting, sanitization querying and saving data from/to database, i.e. it only deals with the given data. An inputfield, however, collects and prepares all data that needs to be written to the database and presents it to a fieldtype.
    1 point
  44. After this tutorial you'll have learned how to: Build a Process module Make an AJAX request to backend Serve JSON as response Let's say you want to display the latest orders in a dashboard that you can access from admin panel. And you want it to refresh its content with a button click. Most straightforward and proper way (that I know of) is to create a Process module, as they're built for this purpose. First, create a directory under /site/modules/, call it ProcessDashboard, and create a file named ProcessDashboard.module under that directory. Following is about the least amount of code you need to create a Process module. <?php namespace ProcessWire; class ProcessDashboard extends Process { public static function getModuleInfo() { return [ 'title' => 'Orders Dashboard', 'summary' => 'Shows latest orders', 'version' => '0.0.1', 'author' => 'abdus', 'autoload' => true, // to automatically create process page 'page' => [ 'name' => 'order-dashboard', 'title' => 'Orders', 'template' => 'admin' ] ]; } public function ___execute() { return 'hello'; } } Once you refresh module cache from Modules > Refresh, you'll see your module. Install it. It will create an admin page under admin (/processwire/) and will show up as a new item in top menu, and when you click on it, it will show the markup we've built in execute() function. All right, now let's make it do something useful. Let's add create a data list to display latest orders. We'll change execute() function to render a data table. public function ___execute() { /* @var $table MarkupAdminDataTable */ $table = $this->modules->MarkupAdminDataTable; $table->setID($this->className . 'Table'); // "#ProcessDashboardTable" $table->headerRow([ 'Product', 'Date', 'Total' ]); // fill the table foreach ($this->getLatest(10) as $order) { $table->row([ $order['title'], $order['date'], $order['total'] ]); } // to refresh items $refreshButton = $this->modules->InputfieldSubmit; $refreshButton->name = 'refresh'; $refreshButton->id = $this->className . 'Refresh'; // "#ProcessDashboardRefresh" $refreshButton->value = 'Refresh'; // label of the button return $table->render() . $refreshButton->render(); } where getLatest() function finds and returns the latest orders (with only title, date and total fields) protected function getLatest($limit = 5, $start = 0) { // find last $limit orders, starting from $start $orders = $this->pages->find("template=order, sort=-created, limit=$limit, start=$start"); // Only return what's necessary return $orders->explode(function ($order) { return [ 'title' => $order->title, 'date' => date('Y-m-d h:i:s', $order->created), 'total' => $order->total ]; }); } When you refresh the page, you should see a table like this Now we'll make that Refresh button work. When the button is clicked, it will make an AJAX request to ./latest endpoint, which will return a JSON of latest orders. We need some JS to make AJAX request and render new values. Create a JS file ./assets/dashboard.js inside the module directory. window.addEventListener('DOMContentLoaded', function () { let refresh = document.querySelector('#ProcessDashboardRefresh'); let table = document.querySelector('#ProcessDashboardTable'); refresh.addEventListener('click', function (e) { // https://developer.mozilla.org/en/docs/Web/API/Event/preventDefault e.preventDefault(); // Send a GET request to ./latest // http://api.jquery.com/jquery.getjson/ $.getJSON('./latest', { limit: 10 }, function (data) { // check if data is how we want it // if (data.length) {} etc // it's good to go, update the table updateTable(data); }); }); function renderRow(row) { return `<tr> <td>${row.title}</td> <td>${row.date}</td> <td>${row.total}</td> </tr>`; } function updateTable(rows) { table.tBodies[0].innerHTML = rows.map(renderRow).join(''); } }); And we'll add this to list of JS that runs on backend inside init() function public function init() { $scriptUrl = $this->urls->$this . 'assets/dashboard.js'; $this->config->scripts->add($scriptUrl); } Requests to ./latest will be handled by ___executeLatest() function inside the module, just creating the function is enough, PW will do the routing. Here you should notice how we're getting query parameters that are sent with the request. // handles ./latest endpoint public function ___executeLatest() { // get limit from request, if not provided, default to 10 $limit = $this->sanitizer->int($this->input->get->limit) ?? 10; return json_encode($this->getRandom($limit)); } Here getRandom() returns random orders to make it look like there's new orders coming in. protected function getRandom($limit = 5) { $orders = $this->pages->find("template=order, sort=random, limit=$limit"); return $orders->explode(function ($order) { return [ 'title' => $order->title, 'date' => date('Y-m-d h:i:s', $order->created), 'total' => $order->total ]; }); } And we're done. When refresh button is clicked, the table is refreshed with new data. Here it is in action: 2017-04-29_19-01-40.mp4 (227KB MP4, 0m4sec) Here's the source code: https://gist.github.com/abdusco/2bb649cd2fc181734a132b0e660f64a2 [Enhancement] Converting page titles to edit links If we checkout the source of MarkupAdminDataTable module, we can see we actually have several options on how columns are built. /** * Add a row to the table * * @param array $a Array of columns that will each be a `<td>`, where each element may be one of the following: * - `string`: converts to `<td>string</td>` * - `array('label' => 'url')`: converts to `<td><a href='url'>label</a></td>` * - `array('label', 'class')`: converts to `<td class='class'>label</td>` * @param array $options Optionally specify any one of the following: * - separator (bool): specify true to show a stronger visual separator above the column * - class (string): specify one or more class names to apply to the `<tr>` * - attrs (array): array of attr => value for attributes to add to the `<tr>` * @return $this * */ public function row(array $a, array $options = array()) {} This means, we can convert a column to link or add CSS classes to it. // (ProcessDashboard.module, inside ___execute() method) // fill the table foreach ($this->getLatest(10) as $order) { $table->row([ $order['title'] => $order['editUrl'], // associative -> becomes link $order['date'], // simple -> becomes text [$order['total'], 'some-class'] // array -> class is added ]); } Now, we need to get page edit urls. By changing getLatest() and getRandom() methods to return edit links in addition to previous fields protected function getLatest($limit = 5, $start = 0) { // find last $limit orders, starting from $offset $orders = $this->pages->find("template=order, sort=-created, limit=$limit, start=$start"); return $orders->explode(function ($order) { return [ 'title' => $order->title, 'date' => date('Y-m-d h:i:s', $order->created), 'total' => $order->total, 'editUrl' => $order->editUrl ]; }); } protected function getRandom($limit = 5) { $orders = $this->pages->find("template=order, sort=random, limit=$limit"); return $orders->explode(function ($order) { return [ 'title' => $order->title, 'date' => date('Y-m-d h:i:s', $order->created), 'total' => $order->total, 'editUrl' => $order->editUrl ]; }); } and tweaking JS file to render first column as links function renderRow(row) { return `<tr> <td><a href="${row.editUrl}">${row.title}</a></td> <td>${row.date}</td> <td>${row.total}</td> </tr>`; } we get a much more practical dashboard.
    1 point
  45. I've been working on a blog profile that we can have as an installation option for ProcessWire. The goal is to have a profile that someone could download and setup a pretty nice website/blog without having to touch any code (i.e. it's ready-to-run and populate). I'm hoping that this is something that may help us to grow our audience beyond the web development community. The requirement is that it must be as easy (or easier) than WordPress, both to install and use. This profile is also for web developers, as it's a blog profile ready to be styled and enhanced -- a good starting point. It uses the Zurb Foundation CSS framework, so it is fully responsive and mobile-ready. It's not much to look at now, but should be fully functional. I'm making progress and wanted to post a preview. The content you see here is from one of my client's blogs and the content is just here to test things out. http://processwire.com/blogtest/ I'm hoping to get this up on GitHub next week. I've never really done much blogging, so am seeking feedback on what others would suggest to make the blog profile as good, powerful and simple as it can be. Right now it's pretty much a generic Zurb Foundation "look and feel", so it probably needs at least some color tweaks and integration of some masthead photo(s) or something.
    1 point
  46. Sure--what I would suggest is adding a text or textarea field and calling it "tags". Then people can type whatever tags in there that they want. When you want to find all pages matching a given tag, you'd do this: $matches = $pages->find("tag*=something"); // where 'something' is a tag If you want predefined tags, then I would use a page reference fieldtype to associate a group of pages as tags. Populate the pages with their name or title field as your tag. Then use a multiple selection field like asmSelect to allow selection of the tags/categories. To find pages matching a given tag, you'd do this: $tag = $pages->get("/tags/something/"); $matches = $pages->find("title=$tag");
    1 point
×
×
  • Create New...