Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/07/2019 in all areas

  1. Regarding compression and quality | webpQuality | lossy | lossless and how different the two rendering engines work, I want to show a little example, comparing two image motives with equal dimensions. I have created two master source images in the dimensions 3000 x 2000 px. The first one is a 24bit color jpeg, filled with noise in Photoshop. The second one is a checkerboard with 100x100 squares, only black and white, but also saved as 24bit color jpeg. I don't want to scare or confuse anybody. Look at the following tables with the file sizes for the different qualities, rendering engines and output formats. (Just let it sink, ...) Really interesting are the results of the IM files in 100% quality, compared to their jpegs and compared between both motives. ? EDIT: And here two more real world motives, but also with interesting IM 100 quality results:
    5 points
  2. Then if $wire works for the hook $wire inside the funtion doesn't work, need to use wire(). And yes the lock file is most likely the problem cause of using $wire inside your function.
    3 points
  3. Here a short tutorial of how to use file fields in ProcessModules because I needed that today. File fields are somewhat special as they are usually connected to an existing page with an existing ID and folder in /site/assets/files. But it is also possible to use the Inputfield alone to provide a GUI for uploading files (just like it is done in ProcessDatabaseBackups or the Modules GUI): /** * Import CSV file * * @return string */ public function executeImportcsv() { $form = $this->modules->get('InputfieldForm'); /** @var InputfieldForm $form */ $tmpDir = $this->files->tempDir('upload_csv'); // get path of temp directory $f = $this->modules->get('InputfieldFile'); $f->extensions = 'csv'; $f->maxFiles = 1; $f->descriptionRows = 0; $f->attr('id+name', 'upload_csv'); $f->label = 'Upload CSV'; $f->icon = 'download'; $f->destinationPath = $tmpDir; // here we set a custom destination path $form->add($f); $form->add([ 'type' => 'submit', 'name' => 'submit', 'icon' => 'download', 'value' => 'Import', ]); if($this->input->post->submit) { $form->processInput($this->input->post); // if there where any errors we exit early and render the form // we also exit here if no files where uploaded if($form->getErrors() OR !count($f->value)) return $form->render(); // loop all uploaded files // here we have only one file maximum, but still it is an array foreach($f->value as $pagefile) { // the regular pagefile's filename is incorrect because it links to // /site/assets/files and not the tempDir, so we get the correct path $file = $tmpDir . $pagefile->basename; // ####################################### // now do whatever you want with that file // ####################################### } // redirect to somewhere $this->session->redirect("/admin/somewhere/"); } // form was not submitted, so render it return $form->render(); } The result: When you upload an invalid file it will show a warning:
    2 points
  4. There is an example in the _main.php of the Multilanguage Site Profile. You can see it here: https://github.com/processwire/processwire/blob/master/site-languages/templates/_main.php#L65
    2 points
  5. Maybe your lazyCron is locked. Look into your /site/assets/lazycron/ or in /site/assets/ folder. Don't know the exact path and name right now. There should be a lazycron file and maybe even a lazycron.locked file. The last one prevents LazyCron from working due to an error that occured before.
    2 points
  6. Just want to thank @horst for all his work on the WebP integration and the effort for explaining many things (of which I am aware, because I also have a background in image retouching and stuff, but most people do not).
    2 points
  7. Thanks everyone, but especially @LostKobrakai. This "owner" selector is wonderful! So for the sake of people searching on forum, it give this so simple selector: $CategUsed = $pages->find('categ.owner.template=activity'); Mel
    2 points
  8. Hie @tiefenbacher_bluetomato You should be able to do it in this way $first_image = $page->images->first(); $first_image->description('de'); As pageimage class extends pagefile.
    2 points
  9. @interrobang - can you try this regex? '~ \b([a-z]{3,}://[a-z0-9%\$\-_.+!*;/?:@=&\'\#,]+[a-z0-9\$\-_+!*;/?:@=&\'\#,])\b\/? | # Fully URLs \b(www\.(?:[a-z0-9\-]+\.)+[a-z]{2,}(?:/[a-z0-9%\$\-_.+!*;/?:@=&\'\#,]+[a-z0-9\$\-_+!*;/?:@=&\'\#,])?)\b\/? | # www. domains \b([a-z0-9\\.+\'_\\-]+@(?:[a-z0-9\\-]+\.)+[a-z]{2,})\b # email addresses ~ix' It looks like it works. All I did was add the "\/?" to the end of the first two lines. If it works, I'll make a pull request.
    2 points
  10. There are a few solutions and the core in the end even added an selector for the usecase.
    2 points
  11. This can now be done with owner selectors (http://processwire.com/blog/posts/processwire-3.0.95-core-updates/) $tagsThatHaveBeenUsedOnPosts = $pages->find('template=tag, tags.owner.template=post'); Where tags is the name of the field on the post template that holds the tag pages. Also, for any given tag page you can check how many post pages reference it with $page->references('template=post')->count(); https://processwire.com/blog/posts/processwire-3.0.107-core-updates/#what-pages-point-to-this-one
    2 points
  12. A module helping you to manage SEO related tasks like a boss! Automatically generates and maintains a XML sitemap from your pages. Includes a Fieldtype and Inputfield to manage sitemap settings and meta data for pages (Title, Description, Canonical URL, Opengraph, Twitter, Structured Data etc.) Multi language support for the sitemap and meta data. Configure default values for meta data on template level and let pages inherit or overwrite them individually. Map existing fields to meta data, reducing the need to duplicate content. Live preview for content editors how the entered meta data appears on Google. Live preview for content editors how the entered Opengraph data looks like when sharing a page with Facebook. Check out the README on GitHub for more details, including usage instructions. The module is currently released as beta and needs testing! Please report any issues on GitHub or in this forum thread, if you find time to give it a try ? Examples Here is an example of rendered meta data you will get from a single SeoMaestro field: <title>Sed dictum eros quis massa semper rutrum. | acme.com</title> <meta name="description" content="Si lobortis singularis genitus ibidem saluto. Dolore ad nunc, mos accumsan paratus duis suscipit luptatum facilisis macto uxor iaceo quadrum. Demoveo, appellatio elit neque ad commodo ea. Wisi, iaceo, tincidunt at commoveo rusticus et, ludus."> <meta name="keywords" content="Foo,Bar"> <link rel="canonical" href="https://acme.com/en/about/"> <meta property="og:title" content="Sed dictum eros quis massa semper rutrum."> <meta property="og:description" content="Si lobortis singularis genitus ibidem saluto. Dolore ad nunc, mos accumsan paratus duis suscipit luptatum facilisis macto uxor iaceo quadrum. Demoveo, appellatio elit neque ad commodo ea. Wisi, iaceo, tincidunt at commoveo rusticus et, ludus."> <meta property="og:image" content="https://acme.com/site/assets/files/1001/og-image.jpg"> <meta property="og:image:type" content="image/jpg"> <meta property="og:image:width" content="1600"> <meta property="og:image:height" content="1200"> <meta property="og:image:alt" content="Lorem Ipsum"> <meta property="og:type" content="website"> <meta property="og:url" content="https://acme.com/en/about/"> <meta property="og:locale" content="en_EN"> <meta name="twitter:card" content="summary"> <meta name="twitter:creator" content="@schtifu"> <meta name="twitter:site" content="@schtifu"> <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "BreadcrumbList", "itemListElement": [ { "@type": "ListItem", "position": 1, "name": "About", "item": "https://acme.com/en/about/" } ] } </script> <meta name="generator" content="ProcessWire"> <link rel="alternate" href="https://acme.com/en/about/" hreflang="en"> <link rel="alternate" href="https://acme.com/en/about/" hreflang="x-default"> <link rel="alternate" href="https://acme.com/de/ueber/" hreflang="de"> <link rel="alternate" href="https://acme.com/fi/tietoja/" hreflang="fi"> And some screenshots of the UI:
    1 point
  13. Inspired by this thread with a little nugget based on AOS by @benbyf to visually distinguish development systems from production ones, I wrote a small module that does the same and lets you adapt colors and text. Link to the github repo: AdminDevModeColors Version 0.0.1 is still very alpha and only tested on PW 3.0.124. Description This module lets you change the color for the top toolbar and add a small piece of text for development systems, so you are immediately you aren't working on production (and vice versa). The adaptions are made through pure CSS and applied if either the "Enable DEV mode" checkbox in the module's configuration is checked or the property $config->devMode is set to true in site/config.php. Works with Default, Reno and Uikit admin themes (though probably needs a lot of testing with different versions still). Since a screenshot says more than thousand words... Production system (unchanged): Dev system (Default admin theme): Dev system (Reno admin theme): Dev system (Uikit admin theme): Feel free to leave any feedback here and report any problems either in this thread or the github issue tracker.
    1 point
  14. An Images field allows you to: Rename images by clicking the filename in the edit panel or in list view. Replace images, keeping metadata and filename (when possible) by dropping a new image on the thumbnail in the edit panel. Introduced here. But neither of these things is possible in File fields, which prompted this module. The way that files are renamed or replaced in this module is not as slick as in the Images field but it gets the job done. The most time-consuming part was dealing with the UI differences of the core admin themes. @tpr, gives me even more respect for the work that must go into AdminOnSteroids. Most of the code to support the rename/replace features is already present in InputfieldFile - there is just no UI for it currently. So hopefully that means these features will be offered in the core soon and this module can become obsolete. Files Rename Replace Allows files to be renamed or replaced in Page Edit. Usage Install the Files Rename Replace module. If you want to limit the module to certain roles only, select the roles in the module config. If no roles are selected then any role may rename/replace files. In Page Edit, click "Rename/Replace" for a file... Rename Use the text input to edit the existing name (excluding file extension). Replace Use the "Replace with" select to choose a replacement file from the same field. On page save the file will be replaced with the file you selected. Metadata (description, tags) will be retained, and the filename also if the file extensions are the same. Tip: newly uploaded files will appear in the "Replace with" select after the page has been saved. https://github.com/Toutouwai/FilesRenameReplace http://modules.processwire.com/modules/files-rename-replace/
    1 point
  15. Perfect! Thank you! I have merged your PR.
    1 point
  16. Here you go https://github.com/phlppschrr/TextformatterMakeLinks/pull/3
    1 point
  17. Yes the problem is most likely that both sites share the same names in it. abelt.test is in both setups and even in the root name. Just rename the root to something else more unique would do the trick. It's not something you would see anyway. "abelt.test" => array( // domain name is used to map to root page "root" => "abelt", // page name for the root page "http404" => 1031 ), "alexander-abelt.test" => array( // funktioniert nicht mit /en/ auf Home "root" => "alexander", "http404" => 1029 ),
    1 point
  18. I think this can happen if your multisite root page name has also the domain name in it. You should avoid that. Just rename it to something else My guess is that this comes from the fact you have domain.com and www.domain.com. You want to avoid that, cause the script isn't clever enough to know which is which. In any case you want to avoid having two domains setup for the same site. You should redirect your www to non www or the other way around.
    1 point
  19. Hi @horst Following your guides complete and having set quality to 100 every step of the way. Imagick is set to no sharpening and 100 output. I'm getting really bad banding in dark areas when an image is being resized. I can't imagine anything more I can do my side for this? Everything is at 100 quality so it shouldn't degrade. This is the original image: https://www.dropbox.com/s/0qh0fvg8ldfqxn5/060618-peter_paul00667-luke-hayes-edit.jpg?dl=0 Here is the image resized to 3840 x 2160 (for retina 4k displays): https://www.dropbox.com/s/gjtcl9vxtzmekp9/060618-peter_paul00667-luke-hayes-edit.3840x2160.jpg?dl=0 And here are where things get bad, resized to 1920 x 1080: https://www.dropbox.com/s/ihgwmp20gn2yvze/060618-peter_paul00667-luke-hayes-edit.1920x1080.jpg?dl=0 You can really start to see banding in the darker areas. Do you have any suggestions for this? I've done the correct photoshop formatting as said in your previous post. EDIT: Example 2 Original image: https://www.dropbox.com/s/rokphzpd1s225as/No_Bounds_Image_Large.jpg?dl=0 ProcessWire resize at 100 quality: https://www.dropbox.com/s/8phrl60fzjfmvnq/no_bounds_image_large.1920x1080.jpg?dl=0
    1 point
  20. Nothing. Escaping single quotes as HTML entities is perfectly valid and just an optical thing, the behavior stays the same as if there were literal single quotes.
    1 point
  21. Hi @ti-no For that, you can use hooks. First, take a look at the documentation https://processwire.com/docs/modules/hooks/ There is a list of core modules and classes and their hookable methods http://somatonic.github.io/Captain-Hook/
    1 point
  22. No, as written two posts above, we have different purpose images. There could be, for example, uncompressed master images that serves as source and should not be displayed on screen! Following I show some more image file purposes, but want to start with a brief introduction to image processing procedures. Within a web environments very limited support, our master source images have to be uncompressed JPGs with 8 bit color depth per channel. Far from optimal. In other environments TIFF or PSD in 16 or 32 bit color depth is used for that purpose. The destructive compression method of JPGs is responsible for most of the user errors that occur during the processing steps. Once you saved a JPG compressed within a workflow, as source or intermediate, you damaged it unrecoverable! And one also cannot detect this programmatic within a common web environment! This is one reason why we keep the master source, the original image untouched, "as is" in PW! (besides other aspects) So, for our use cases, the JPG format can have different purposes: uncompressed master source images, uncompressed intermediate variations, final optimized and compressed variations for screen output. Also, if one has a use case for it, one can optimize and finalize JPGs only for the purpose of printing in PW. Or for embedding them into PDFs, or for serving them as single files or as zipped archives for different purposes per downloads. So, it's not: "all get displayed on screen". Some never should be displayed on screen. (I maintain sites for photographers who keeps 60k+ images as original (pw master source) images in the site. They only publicly show watermarked images within limited dimensions. The original images are protected against web access. And they are used for all the different above listed output purposes.) Luckily with the WebP format it behaves different. Due to its intended purpose, (that is, highly compressed and optimized for screen output), it is unusable for all other purposes! Sure, if you want to or don't care about anything, you can use everything wrong, but it is not that subtle like with JPGs. In German we have a saying: "gefährliches Halbwissen" ("dangerous half-knowledge"). No idea whether one can translate the sense connected with it by DeepL? But it means something like: If you already know a good part, you quickly run the risk of drawing (wrong) conclusions about the unknown parts. Personally, I am always happy when I get explanations, help or advice from people who have more specialist knowledge. After all, I can't know everything myself, right? ? One of my most important life experiences & wisdoms to fight against my "gefährliches Halbwissen": "If there are many people who study and learn for years to get a vocational qualification before they can "really" get into the subject, then I know that a huge part of it is invisible to me, even if I think I already understand a lot of it.".
    1 point
  23. Because it is not a "normal" image format by its intended purpose! As far as I understood, you upload already compressed images that you don't want to proceed further? Note: 1) Already (not lossless) compressed images should not be used for any transformation, because the images are lacking lots of information due to the compression. (like the webp format!) 2) If you do not want to use the resize functionality, you have to provide the final webp by yourself too. PW only provides webp support for PW created variations for final output. This is due to the file formats nature or its intended purpose. Maybe you don't want or need a webp variation for admin thumbs. Maybe other users don't care. Maybe some users really like it when opening a editor page with 300 images displayed as admin thumbs. I cannot answer this other then: It may depend on a lot of different things? I really would like to discuss the general webp support first, and the less common use cases like this later on, in a following fine tuning phase. ----------- AFAIK the most common case is to use the pageimage system with uploaded uncompressed images that serves as master images. Those master images are never get served to the outside "as is". They every time get transformed into a variation file that is optimized and finalized for a specific purpose! At least this is the only correct way for an error-free workflow with maximum possible quality combined with smallest possible file size! Whether people understand this or not, my almost 30 years of expertise in the photographic industry has never shown me anything else. And all my work within the PW images system is (and only can be) based on this. ----------- I know that there also is a minor usage of the pageimage fields for simply displaying the original files to the frontend, but my best bet is that this is much lower then 10%. In my opinion this is not the intended use case for pageimages. The use of a file field would suffice, if it also could display an admin thumbnail in the backend. But because this functionality is missing in a file field, pageimage fields are used as "compromise solution" for this purpose.
    1 point
  24. Actually, this is incorrect. It is top priority for me now not least because I struggle with CSS (as I've stated previously) ?. The less CSS headache I have to deal with later the better for me. I see what you mean. Should hopefully be a simple fix...just remove the uk-margin. Looks great! Thanks for the idea. I was contemplating this question since I thought about it myself. I'm not sure though. I'll have to think a bit more about this. Yes. I was going to mention this in my post but I forgot. You will then be able to access them at $product->your_repeater; $product->another_custom_field; etc. The code is already there. The only thing I haven't decided is how to add the custom fields and how to edit them. In Media Manager all you need to do is to add your field to the template and editing is done in a modal. Editing the page itself (where it lives in PW). For Padloper, it is not that straightforward. I am trying to avoid modals as best as I can. Even if you added your custom field to the products template and was to edit it in a modal or different page, some users will probably be confused since they will not be able to see variants. on that page! I purposefully left out Inputfields for the custom Fieldtypes I created for Padloper. We don't need them since nothing is edited on the page. Given, the current UI can be transferred to the Inputfields but I am not keen on that. I'll need to have a proper think about his, especially RE repeaters. Any and all ideas are welcome :-). No, that's not correct. The video doesn't show inventory management at all. The inventory dash will list all variants where available alongside products that do not have variants. I haven't decided how to best display the table. The current ideas are: a simple table showing all variants and 'single' products a table/list that groups variants of one product together (something like mini-panels) A table listing products with variants hidden in accordions Whichever UI we go with, filters will still be available. Thoughts? The only core Fieldtype Padloper 2 uses are Pagefields (2), Textarea(2, 1 of which is rich text), Title and Images. Everything else is either a custom Fieldtype or a custom table. Is below good enough for prices ?? For prices we use the type decimal(12,2).
    1 point
  25. I just remembered that Drupal has a URL filter built into core. Maybe we can somehow use it's code since it's been battle tested? ...with credit of course. https://api.drupal.org/api/drupal/modules!filter!filter.module/function/_filter_url/7.x - For Drupal 7 In the comments of the Drupal module, it interestingly states "Each type must be processed separately, as there is no one regular expression that could possibly match all of the cases in one pass." There is also https://github.com/thephpleague/uri-parser that looks like it may help, but that would require composer to install the library? Also, I've been testing different regex patterns with https://regex101.com. It's the best regex tester I've found so far.
    1 point
  26. Just a brief update today. I’m going to give it another week before bumping the core version, as I don’t think there’s enough changes yet to warrant a version bump. For whatever reason, several of my clients have needed integration with Stripe (payments) over the last few weeks. I’d not worked with it before the last month or so, but now all of the sudden am working with it a lot, because that's what my clients have asked for. I’ve found myself working on four different Stripe integrations on existing PW sites, both Stripe Elements and Stripe Checkout. None of these are for sites that have an actual “store” where they would need a cart, but rather just “pay for your reservation”, “buy this book”, “buy this song”, and “make a donation of $10”, “make a recurring donation”, type things. After doing a few of these, I thought it would make a lot of sense to have this built into FormBuilder, which would save us time on this stuff. So this week I built Stripe support into FormBuilder (using the Stripe Elements API). It’s already fully functional, so I will be releasing a new version of FormBuilder with this capability quite soon. To add a Stripe payment input to your form you just add a new field of type “Stripe payment for FormBuilder”, and then it asks you for some info about it (like amount to charge) and then your form works as a payment processor. Stripe has a clever way of making this all work, so that the user never leaves your site, but your site (and FormBuilder) never sees credit card numbers or anything like that, so it’s secure and you don’t have to consider things like PCI compliance. I've also got some other unrelated updates for FormBuilder that I'll be covering soon as well. Have a great weekend!
    1 point
  27. This module helps you dynamically create schemas for improved SEO & SERP listings from within your templates. Each schema can be configured to meet your requirements. You can even add your own ProcessWire schema classes to the module. Read about the module on github: https://github.com/clipmagic/MarkupJsonLDSchema Download from github: https://github.com/clipmagic/MarkupJsonLDSchema/zipball/master Download from ProcessWire modules: http://modules.processwire.com/modules/markup-json-ldschema/
    1 point
  28. I have not used Padloper yet, but I built a custom shop lately and it's a LOT of work ? The problem is not the payment integration, the problem is handling all the user interactions (shopping cart, taxes, product variations etc). So it depends a lot on your scenario. If you only want to collect donations without any other features, then you might not need padloper (but then you could also just use a payment button from one of the providers)
    1 point
  29. 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
  30. Here you go. Images need to go into /site/templates/ImageSelect/[path/] and must be named [optionValue].jpg. For usage with FieldtypePage you need to add the module in the settings of InputfieldPage. For the newer options fieldtype it's available right away. Edit: My version might be more suited to the usecase of presenting layout options to the admins, rather than having a full blown thumbnail display. Archiv.zip
    1 point
  31. @MrSnoozles and everyone! This project is certainly halted at the moment and we are discussing what to do with it. We have not publish because one of our original intentions was to make it a Pro module. We still need to clear our heads from work and decide what to do.
    0 points
×
×
  • Create New...