Jump to content


Popular Content

Showing content with the highest reputation since 05/17/2019 in Posts

  1. 28 points
    We recently rebuilt the Architekturführer Köln (architectural guide Cologne) as a mobile-first JavaScript web app, powered by VueJS in the frontend and ProcessWire in the backend. Concept, design and implementation by schwarzdesign! The Architekturführer Köln is a guidebook and now a web application about architectural highlights in Cologne, Germany. It contains detailled information about around 100 objects (architectural landmarks) in Cologne. The web app offers multiple ways to search through all available objects, including: An interactive live map A list of object near the user's location Filtering based on architect, district and category Favourites saved by the user The frontend is written entirely in JavaScript, with the data coming from a ProcessWire-powered API-first backend. Frontend The app is built with the Vue framework and compiled with Webpack 4. As a learning exercise and for greater customizability we opted to not use Vue CLI, and instead wrote our own Webpack config with individually defined dependencies. The site is a SPA (Single Page Application), which means all internal links are intercepted by the Vue app and the corresponding routes (pages) are generated by the framework directly in the browser, using data retrieved from the API. It's also a PWA (Progressive Web App), the main feature of which is that you can install it to your home screen on your phone and launch it from there like a regular app. It also includes a service worker which catches requests to the API and returns cached responses when the network is not available. The Architekturführer is supposed to be taken with you on a walk through the city, and will keep working even if you are completely offline. Notable mentions from the tech stack: Vue Vue Router for the SPA functionality VueX for state management and storage / caching of the data returned through the API Leaflet (with Mapbox tiles) for the interactive maps Webpack 4 for compilation of the app into a single distributable Babel for transpilation of ES6+ SASS & PostCSS with Autoprefixer as a convenience for SASS in SFCs Google Workbox to generate the service worker instead of writing lots of boilerplate code Bootstrap 4 is barely used here, but we still included it's reboot and grid system Backend The ProcessWire backend is API-only, there are no server-side rendered templates, which means the only PHP template is the one used for the API. For this API, we used a single content type (template) with a couple of pre-defined endpoints (url segments); most importantly we built entdpoints to get a list of all objects (either including the full data, or only the data necessary to show teaser tiles), as well as individual objects and taxonomies. The API template which acts as a controller contains all the necessary switches and selectors to serve the correct response in <100 lines of code. Since we wanted some flexibility regarding the format in which different fields were transmitted over the api, we wrote a function to extract arbitrary page fields from ProcessWire pages and return them as serializable standard objects. There's also a function that takes a Pageimage object, creates multiple variants in different sizes and returns an object containing their base path and an array of variants (identified by their basename and width). We use that one to generate responsive images in the frontend. Check out the code for both functions in this gist. We used native ProcessWire data wherever possible, so as to not duplicate that work in the frontend app. For example: Page names from the backend translate to URLs in the frontend in the form of route parameters for the Vue Router Page IDs from ProcessWire are included in the API responses, we use those to identify objects across the app, for example to store the user's favourites, and as render keys for object lists Taxonomies have their own API endpoints, and objects contain their taxonomies only as IDs (in the same way ProcessWire uses Page References) Finally, the raw JSON data is cached using the cache API and this handy trick by @LostKobrakai to store raw JSON strings over the cache API. Screenshots
  2. 24 points
    This week I’m happy to report we now have WEBP support in ProcessWire thanks to a GitHub pull request from Horst Nogajski. This enables you to have highly optimized image output in PW and I think you’ll really like the difference it makes. Read on for all the details… https://processwire.com/blog/posts/webp-images-in-pw/
  3. 17 points
    For the last couple months, I've been working on a module that does exactly this. It's not a site profile, it's not a theme. I don't know what term would accurately describe it, but its a ProcessWire module that's an opinionated, update-able starting point, oriented towards developers, and brings in a bunch of boilerplate like: an installer that will create fields, templates, pages, hannacodes; it runs through a thorough check before doing anything that may result in an error (module installation errors are aggravating; i'm testing it very thoroughly) the installer will rename your 'templates' dir to something temporary, and then copy a starting 'templates' folder that's prepped for the module (you should only do this on dev) if you try to add it to an existing site with a bunch of data, it will work as long as there are not collisions in some fields and templates; if there are, the module won't install and tell you what you need to change around to allow it to install establishes some new $config variables ('env', 'disableTemplateCache', a few others) built with UIkit 3 in mind, but not hardcoded to it a menu builder based on Repeaters with its own Process Module has its own seo+og+twitter+sitemap metadata fields and uses Profields FieldGroup since that is the best module for handling such a grouping has it's own templates inside the module which can be used, or overridden in /site/templates/; this includes blog sitemap.xml maintenance search in addition to template files being able to be overridden, partial files can be overridden too! some module configuration fields (site_name, maintenance, etc.) the module has documentation and other statistics built into it for easy reference takes full advantage of setting() and markup regions; applies attributes like UIkit 'uk-grid' and other data attributes without "touching" the html; keeps the module flexible and easily allows you to rip out UIkit and swap it for another CSS framework (Bootstrap 4); you'll never need to touch edit the _main.php file because of how regions has been set up has it's on RepeaterMatrix fields with boilerplate matrix-types (headline, text, slideshow, etc. etc.); if the user makes new custom matrix types and a later version of my module brings in a new matrix-type, it will update the RepeaterMatrix field and merge it correctly (tricky to do!); the matrix types use many of the same base fields, thereby allowing you to switch from one matrix type to another without data being destroyed (this was only possible as of 2 weeks ago with the new matrix update) to avoid creating a bunch of 1-off fields for the matrix field for block configuration, it uses the new and quite amazing Mystique fieldtype in a unique way (this was tricky to do); this module is critical to establishing a page-builder that is clean (this was only possible as of April 2019 since the module is brand new) brings in PW's debugger to the frontend (brings in jQuery UI); can be disabled all field and template names don't use any prefixes; this would allow you to dump the module one day in the future if you don't like it, without having a bunch of field and template names that sound too specific to the module Laravel Mix based asset compiler pre-configured with UIkit works with FormBuilder and other modules I often use; works and may require certain Pro modules; eliminates the need for any modules that do blogging, menu building, sitemap, maintenance or seo since this module does it using native ProcessWire login/logout/account/register templates it may include a 'collection' generator for common things like events, products, people, properties, along with some templates for those. don't like the templates my module provides? then just create your own template file in /site/templates/the-template-file.php which will override /site/modules/my-module-name/templates/the-template-file.php Right now I just started building a few sites with it (spent the last 2 months developing it) which will hammer it out further. I will release it late summer, early fall.
  4. 15 points
    ProcessWire 3.0.133 adds a useful new $page->meta() method for a new type of page-specific persistent data storage, adds the ability for users to create their own bookmarks in Lister, and has a handy and time saving update for the asmSelect input type. Read on for all the details, examples and screenshots— https://processwire.com/blog/posts/pw-3.0.133/
  5. 15 points
    Repeater Images Adds options to modify Repeater fields to make them convenient for "page-per-image" usage. Using a page-per-image approach allows for additional fields to be associated with each image, to record things such as photographer, date, license, links, etc. When Repeater Images is enabled for a Repeater field the module changes the appearance of the Repeater inputfield to be similar (but not identical) to an Images field. The collapsed view shows a thumbnail for each Repeater item, and items can be expanded for field editing. Screencast Installation Install the Repeater Images module. Setup Create an image field to use in the Repeater field. Recommended settings for the image field are "Maximum files allowed" set to 1 and "Formatted value" set to "Single item (null if empty)". Create a Repeater field. Add the image field to the Repeater. If you want additional fields in the Repeater create and add these also. Repeater Images configuration Tick the "Activate Repeater Images for this Repeater field" checkbox. In the "Image field within Repeater" dropdown select the single image field. You must save the Repeater field settings to see any newly added Image fields in the dropdown. Adjust the image thumbnail height if you want (unlike the core Images field there is no slider to change thumbnail height within Page Edit). Note: the depth option for Repeater fields is not compatible with the Repeater Images module. Image uploads feature There is a checkbox to activate image uploads. This feature allows users to quickly and easily add images to the Repeater Images field by uploading them to an adjacent "upload" field. To use this feature you must add the image field selected in the Repeater Images config to the template of the page containing the Repeater Images field - immediately above or below the Repeater Images field would be a good position. It's recommended to set the label for this field in template context to "Upload images" or similar, and set the visibility of the field to "Closed" so that it takes up less room when it's not being used. Note that when you drag images to a closed Images field it will automatically open. You don't need to worry about the "Maximum files allowed" setting because the Repeater Images module overrides this for the upload field. New Repeater items will be created from the images uploaded to the upload field when the page is saved. The user can add descriptions and tags to the images while they are still in the upload field and these will be retained in the Repeater items. Images are automatically deleted from the upload field when the page is saved. Tips The "Use accordion mode?" option in the Repeater field settings is useful for keeping the inputfield compact, with only one image item open for editing at a time. The "Repeater item labels" setting determines what is shown in the thumbnail overlay on hover. Example for an image field named "image": {image.basename} ({image.width}x{image.height}) https://github.com/Toutouwai/RepeaterImages https://modules.processwire.com/modules/repeater-images/
  6. 15 points
    This week we’ll take a look at 3 different WEBP image strategies that you can use in ProcessWire 3.0.132+. Then we’ll dive into a major update for the Google Client API module, and finish up by outlining some useful new updates in FormBuilder— https://processwire.com/blog/posts/webp-images-and-more/
  7. 14 points
    Just had a very interesting conversation with @wbmnfktr and wanted to share this little preview of a quite big upgrade coming soon called "RockGridActions". I'll share some more infos soon. The great thing about it is that it is built modularly so that we'll be able to use it almost plug&play for RockTabulator ( @Beluga)
  8. 13 points
    This is the topic for the new module, TextInputAwesomeplete. Github: https://github.com/outflux3/TextInputAwesomplete Modules Directory: https://modules.processwire.com/modules/text-input-awesomplete/ Text Input Awesomplete Key Points: Uses Awesomplete JS library for instantiating autocomplete suggestions on text input fields in Processwire CMS. Supports any text field, including Page Title (FieldtypePageTitle). Allows admins to configure a list of suggestions (textarea input), or pull suggestions from Processwire pages, by configuring which pages to pull from and which field's value to use. About Awesomplete https://leaverou.github.io/awesomplete/ https://github.com/LeaVerou/awesomplete Benefits & Uses Can be helpful for fields where users may need to enter the same text in the same field on multiple pages, and you can't or don't want to use a Page Reference field. One example could be a site where you send emails using various boilerplate subjects; Another place to use this would be if you had an existing site with a text field that has some inconsistency when same values are added. The autocomplete would help editors to always use the same format as the other pages with the same value. Installation Upload or install from Modules directory. Usage & Configuration Once installed, on any text input field (including Page Title), you will see an option to enable autocomplete. Once enabled you will have the option to type a list of items for autocomplete suggestions, or enable the module to search pages for suggestions. Note that if you enter any items in the Items List field, those will always be part of the autocomplete suggestions, in addition to pages if configured. If you elect to use pages for the suggestions, you have these options: Choose a template to limit by (adds a template=sometemplate to the pages find selector). Override which field to pull suggestions from (by default it will use the field you are configuring). Sets the $field!= in the selector. Setup a Selector for finding the pages for the autocomplete suggestions. This overrides the template selected. Note that the selector needs to return pages that use the field being configured, or the field selected for override. Screenshots: (1) Examples of in-use: Module Configuration Screen
  9. 13 points
    In this post we take a quick look at the new version of ProFields Repeater Matrix, yet another new version of FormBuilder, and a new version of the GoogleClientAPI module— https://processwire.com/blog/posts/lots-of-module-updates/
  10. 12 points
    Or you could just use a RuntimeMarkup field with WireHttp() and $cache. I'd never heard of SmugMug before . Here's a demo for how this could be done in RM. We are mimicking a ProcessWire image field by using similar markup and including Image field's JS and CSS. Please see the notes in the code. We are also caching the response for 1 hour so we don't hit SM limits. I created a free 14-day trial account for this. Here it is...I couldn't think of a better name for it . As you can see in the demo video, we are pulling the exact images. The code could be improved. You could get all fancy and even push changes to SM using Ajax, for instance. Please see the examples in RM docs. This code goes into the file you are rendering. <?php namespace ProcessWire; // set PW image assets $url = $config->urls->InputfieldImage; $config->styles->add($url . "InputfieldImage.css"); // @note: JS just in case you need it but in that case, you will also need Magnific, etc $config->scripts->add($url . "InputfieldImage.js"); // get cache only if it’s less than or equal to 1 hour old (3600 seconds) // @note: cache is unique for this page $cacheName = "smugmug_{$page->id}"; $images = $cache->get($cacheName, 3600); // no cache or expired, request data from smugmug if(is_null($images)) { // Get an instance of WireHttp $http = new WireHttp(); // we want JSON, so set headers accordingly $headers = array('Accept'=>'application/json'); $http->setHeaders($headers); // an example public album $url = 'https://www.smugmug.com/api/v2/album/xxxxxx!images'; $data = array('APIKey'=>'12345678900987654321');// API key $response = $http->getJSON($url, true, $data); $images = $response['Response']['AlbumImage']; // cache the response, and expire after 1 hour (3600 seconds) // @note: only caching the albmum! $cache->save($cacheName, $images, 3600); } // outer list markup for images (c & p from PW with slight modifications) $out = "<ul class='gridImages ui-helper-clearfix ui-sortable'>"; // iterate through response. // @todo: You might want to do some error checking first foreach($images as $image) { // file size to kB $fileSize = ceil($image['OriginalSize'] / 1000); $out .= " <li id='file_{$image['UploadKey']}' class='ImageOuter gridImage ui-widget'> <div class='gridImage__tooltip'> <table> <tbody> <tr> <th>Dimensions</th> <td>{$image['OriginalWidth']}x{$image['OriginalHeight']}</td> </tr> <tr> <th>Filesize</th> <td>{$fileSize} kB</td> </tr> <tr> <th>Description</th> <td><small>{$image['Title']}</small></td> </tr> </tbody> </table> </div> <div class='gridImage__overflow' style='width: 130px; height: 130px;'> <img src='{$image['ThumbnailUrl']}' alt='{$image['Caption']}' data-w='{{$image['OriginalWidth']}}}' data-h='{{$image['OriginalHeight']}}' data-original='' style='max-height: 100%; max-width: none; top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0px);'> </div> <div class='gridImage__hover'> <div class='gridImage__inner'> <label for='' class='gridImage__trash'> <input class='gridImage__deletebox' type='checkbox' name='delete_images_{$image['UploadKey']}' value='1' title='Delete'> <span class='fa fa-trash-o'></span> </label> <a class='gridImage__edit' style='line-height: 130px;'> <span>Edit</span> </a> </div> </div> </li> "; } $out .= '</ul>'; $out = "<div id='my_album'>{$out}</div>"; return $out; Screenshot Video Demo
  11. 12 points
    @ryan thank you very much for all the additions you implemented in such a short time on top of my github pullrequest. It seems that there currently nothing is left in regard of webp support in ProcessWire. But I already have one or two points for future updates to the image rendering engines, that should be implemented when all browsers will support webp and we don't need fallback jpegs or pngs anymore.
  12. 11 points
    UPDATE OK, after I've faced that for and against again, I've decided to make the module freely available. If you are interested, you can test the current state of development. I already put the module on GitHub. Please note that the software is not yet intended for use in a production system. (Alpha version). For example, the configuration and handling of the VAT rates are still missing. Also the dashboard is still incomplete. And many other things needs to be improved and implemented... If you like, you can also submit feature requests and suggestions for improvement. I also accept pull requests. https://github.com/gadgetto/SnipWire
  13. 9 points
    A year or so later, I have seen the future. Actually, I just stumbled upon it. Just when I was diving into Angular + TypeScript + NativeScript for mobile apps, I recently came across this thing, Flutter. I have been totally blown away! The last time I was this excited was when I discovered ProcessWire :-). Long story short, before I ended up here, I was looking at Kivy and BeeWare. I managed to pick up Python along the way. Kivy looks promising. I am interested in both mobile and desktop apps and it ticks those boxes. Then along comes Flutter and wow! Cross platform, write once deploy everywhere (iOS, Android, Embedded, Windows, Mac). It's still early days but I am totally convinced. I was a bit hesitant because it is a Google project (you know, their history of killing off projects...) but since it is open source and there are some big players already involved, I am sold. Flutter compiles to machine code! It comes with lots of widgets out of the box, both for iOS and Android. You can also ask it to compile to JavaScript (like TypeScript can and does). To program in Flutter you use Dart, a language developed by Google. I came across Dart a while back. Back then, it was considered a dead language. It has made a resurgence, thanks to Flutter. If you know your OOP and JavaScript, it is very easy to pick up, in an hour or so. If looking at Flutter, have a look at Hummingbird as well. What do you folks think? Anyone used Flutter before?
  14. 8 points
    Version 0.8.0 has been released: Adds facebook share preview for content editors when editing Opengraph meta data Adds support to extend the rendered meta title with additional information such as the domain or site name (#11) Renders structured data (JSON-LD) for breadcrumbs via new group "structuredData" (#10) Adds new meta group "structuredData" which will handle more types of structured data in the future Happy weekend everyone! Cheers
  15. 8 points
    www.kentvitrini.com - It is a City Portal of Corlu (Turkey) , our hometown. After using TYPO3 CMS for more than 10 years for our projects, this is our first PW project. With PW less effort, less stress but much more fun. I am impressed. For Mobile Chrome Users : The site is a PWA (Progressive Web App), so it can be downloaded to the homescreen of the phone for future visits. As it is in turkish let me describe it: It has 3 main data groups - "Haberler" are News - "Firma Rehberi" is a Company Directory - "Etkinlik" are Events As there will be more and more information on the site a Live Search will help the visitors to find everything they need. For trying type "corlu" as search word, after 3 letters the search will be loading results. The Top Menu is "Mega Menu" enabled. Looks pretty good on hover On top (under the main menu) there is mix of all content. It looks like a billboard. Below are "Featured Companies" in random order, so the order of the companies changes with every load of the page. Below (Left) News Below (Left) nearest Events. And below (Sidebar) A summery of all content, Weather, pharmacy on duty. We will add Classified ads and "Who is Who" sections in near future.
  16. 8 points
    It's possible, but not as simple as it should be because it seems that the option() method of Datepicker (and Timepicker) is not working for the stepMinute option. Instead it seems you have to destroy and re-init the datepicker if you change stepMinute. In some custom admin JS, for a field named "date"... // For a Datetime field named "date" with time enabled $('#Inputfield_date').on('focus', function() { // Get the existing options for the Datetimepicker var options = $(this).datetimepicker('option', 'all'); // If the picker has the default stepMinute setting... if(options.stepMinute === 1) { // Set custom stepMinute setting options.stepMinute = 15; // Destroy picker $(this).datetimepicker('destroy'); // Re-initialise picker $(this).datetimepicker(options); } });
  17. 8 points
    We recently finished the relaunch auf camac.de, a client from the software industry, focused on controlling and business integration solutions. Concept, design and implementation by schwarzdesign. The site is focussed on longer content pages with text and image combination, with technical information for potential customers. It also offers multiple options for Call-to-Action elements to maximize conversions. Finally, the site is heavily optimized with caching and minification at every stop to be instantly readable even on slow connections. Features No hard-coded sections in any template: Almost all content types use the same repeater matrix field with several section types. This way, the entire site and all parts of the layout can be moved around and combined in any way imaginable. Custom Call-to-Action options: Two different contact forms, custom external links or a general CTA text. Automatically generated page navigation and human-readable anchors (as seen here) Every page fully loaded and interactive in ~1 second, even on poor mobile connections Automatically generated SEO meta tags, with overwrite fields available on every page Modules used ProFields FormBuilder Tracy Debugger Sitemap Duplicator ALIF - Admin Links In Frontend WireMailSMTP Content and conversions Every visitor is a potential customer - this is why we made sure there are ample opportunities to generate leads. At the end of every page, there are multiple options for the CTA section: A contact form with a customizable message (built with FormBuilder) A download form that allows visitors to download PDFs (e.g. the full article) in exchange for their name and E-Mail address. Other text + image combinations with custom links or buttons. The download form was custom coded, as it allows the editor to upload a file specific to the current page and make it available behind a small form. After successfully submitting the form, an e-mail is sent to the site owner, and the file is directly streamed to the client as a download. Technical insights This is one of the first pages where I used Twig for templating, and it's been a great developing experience. With Twig, you get content escaping and much better seperation between logic and view / display. I also spent some time working out a solid structure for the twig templates, with useful defaults, reusable blocks for page and section template (you can read more about the approach in my recent tutorial on integrating Twig with ProcessWire, part 1 and part 2). I also started using Parcel as a lightweight alternative for Webpack, when all I need is to compile a couple of small scripts (for the navigation, the lightbox, a dismissable cookie notice et c). What's great about parcel is that you get bundling of your own code and external libraries out of the box, as well as ES6+ transpilation and minification for production usage. Still, it required no configuration but a couple of command line options. This way, you get one bundled, minified JavaScript file, the same way we produce a minified CSS file with SCSS, but without the additional overhead of configuring Webpack. Screenshots
  18. 7 points
    UPDATE 2019-06-15 The taxes repeater field in module config editor was updated: changed to a grid view for more flexibility added field validation prepared the taxes-repeater field code to become a standalone flexible Inputfield module for general use (Array/JSON repeater input field which stores its values in a single text field) The taxes handling is completed! SnipWire now acts as a full flexible taxes-provider for Snipcart (we use Webhooks for this). No configuration needed in Snipcart dashboard. SnipCart orders are now fully working (except shipping handling). The sample shop templates got an update: customer login/logout customer dashboard link/button to view orders history and subscriptions editing of customer profile Other updates and fixes: The SnipWire Dashboard was updated (Charts, Orders, Customers, ...) --> see screenshot below. The Dashboard fetches its data from Snipcart via CURL multi - the response time for a fresh load is now under 2 seconds The Webhooks handler now supports all Snipcart events via hookable methods. Snipwire now supports all major Admin themes (Uikit, Reno and Default) All module classes/files are more structured (e.g. separate helper and service classes) Under the hood many bugs are fixed and code is updated to prevent unexpected errors. Added a crispy SVG logo for all SnipCart back-end pages Screen-recording of updated taxes-repeater: Screenshot of SnipWire Dashboard:
  19. 7 points
    Hi all, I thought that you'd be interested to know we've now launched our third ProcessWire site, called Home of the Blizzard - The Australasian Antarctic Expedition. It's about Douglas Mawson's famous expedition of 1911-1914. As a part of the move to ProcessWire from our previous CMS it has undergone a redesign as well. It has been done completely in-house. https://mawsonshuts.antarctica.gov.au/ It uses Fancybox for the image galleries and modal menu, Plyr for video, and Modernizr (primarily to check for CSS Grid compatibility). It was actually the first PW site we started working on, but then the SCAR COMNAP and Antarctic Jobs sites became priorities so it got pushed back. It's great to have it live at last. The next PW site we launch should be our main site (http://www.antarctica.gov.au)! That's still a work in progress.
  20. 7 points
    Why I'm still using jQuery in 2019
  21. 7 points
  22. 7 points
  23. 7 points
    Imagine you have a nice conversation with someone and only a few hours afterwards you are knee-deep into a module and possibilities you never thought of. Thank you @bernhard for hijacking my plans for the weekend.
  24. 6 points
    @ryan, thanks for the new features! In the past I've worked on modules that needed to store data for some pages and I had to create a custom DB table for that - the new page meta feature will avoid this and make module development easier. Regarding the Lister bookmarks feature, it would be nice if bookmarks were able to store filter rows where the value is empty. This is so that a bookmark could include rows that don't affect the results until a user enters a value, but are sitting there ready to use when needed. At the moment any rows without a value are not stored in the bookmark. I know that achieving a setup like this is possible with a Lister Pro instance or with a hook for the core Lister but it would be nice to have the option in Lister bookmarks too.
  25. 6 points
    In regards to dev vs live htaccess, you can also use htaccess's "if" conditional for blocks of code you want to selectively enable/disable depending on the site being loaded. By doing so, you don't need two separate htaccess files to maintain. When using ProCache combined with it's htaccess recommendations at the top, I wrap it inside a conditional like this: ################################################################################################# # ProcessWire ProCache recommended .htaccess tweaks for expires and gzip performance settings. # PWPC-3.0 Keep this line here for ProCache identification purposes. ################################################################################################# <If "%{HTTP_HOST} == 'my-live-website.com'"> ...the code here... </If>
  26. 6 points
    ANOTHER UPDATE SnipWires Taxes (VAT) configurator is ready! I added a new custom Fieldtype FieldtypeSnipWireTaxSelector based on an idea of @BitPoet - thanks for that! Also I created a full featured repeater for module config editor including drag&drop handling. Have a look at the animated GIF below. The taxes you configure here will be available as select option list in product page editor. The first tax in the configured list will be used a s the default tax in the custom field.
  27. 6 points
    v0.2.1 released. This is a fairly major update in that there has been quite a bit of refactoring. Please be alert for and report any issues. ProcessWire >= v3.0.0 is now required. This release adds a new hookable HannaCodeDialog::buildForm() method that lets you build the dialog form in the hook rather than setting inputfield options as pseudo-attributes in the Hanna Code tag settings. From the readme... Build entire dialog form in a hook You can hook after HannaCodeDialog::buildForm to add inputfields to the dialog form. You can define options for the inputfields when you add them. Using a hook like this can be useful if you prefer to configure inputfield type/options/descriptions/notes in your IDE rather than as extra attributes in the Hanna tag settings. It's also useful if you want to use inputfield settings such as showIf. When you add the inputfields you must set both the name and the id of the inputfield to match the attribute name. You only need to set an inputfield value in the hook if you want to force the value - otherwise the current values from the tag are automatically applied. To use this hook you only have to define the essential attributes (the "fields" for the tag) in the Hanna Code settings and then all the other inputfield settings can be set in the hook. Example buildForm() hook The Hanna Code attributes defined for tag "meal" (a default value is defined for "vegetables"): vegetables=Carrot meat cooking_style comments The hook code in /site/ready.php: $wire->addHookAfter('HannaCodeDialog::buildForm', function(HookEvent $event) { // The Hanna tag that is being opened in the dialog $tag_name = $event->arguments(0); // Other arguments if you need them /* @var Page $edited_page */ $edited_page = $event->arguments(1); // The page open in Page Edit $current_attributes = $event->arguments(2); // The current attribute values $default_attributes = $event->arguments(3); // The default attribute values // The form rendered in the dialog /* @var InputfieldForm $form */ $form = $event->return; if($tag_name === 'meal') { $modules = $event->wire('modules'); /* @var InputfieldCheckboxes $f */ $f = $modules->InputfieldCheckboxes; $f->name = 'vegetables'; // Set name to match attribute $f->id = 'vegetables'; // Set id to match attribute $f->label = 'Vegetables'; $f->description = 'Please select some vegetables.'; $f->notes = "If you don't eat your vegetables you can't have any pudding."; $f->addOptions(['Carrot', 'Cabbage', 'Celery'], false); $form->add($f); /* @var InputfieldRadios $f */ $f = $modules->InputfieldRadios; $f->name = 'meat'; $f->id = 'meat'; $f->label = 'Meat'; $f->addOptions(['Pork', 'Beef', 'Chicken', 'Lamb'], false); $form->add($f); /* @var InputfieldSelect $f */ $f = $modules->InputfieldSelect; $f->name = 'cooking_style'; $f->id = 'cooking_style'; $f->label = 'How would you like it cooked?'; $f->addOptions(['Fried', 'Boiled', 'Baked'], false); $form->add($f); /* @var InputfieldText $f */ $f = $modules->InputfieldText; $f->name = 'comments'; $f->id = 'comments'; $f->label = 'Comments for the chef'; $f->showIf = 'cooking_style=Fried'; $form->add($f); } });
  28. 6 points
    I just submitted a pull request with fixes for the overflow positioning, offset when CKEditor is in inline mode, and overrides for the <ul> padding and margin coming from AdminThemeUikit. https://github.com/BitPoet/ProcessCKInlineComplete/pull/4
  29. 6 points
    The most simple approach I can think of right now is hook into after InputfieldText::render: Put this code in site/ready.php: $wire->addHookAfter("InputfieldText::render", function($event){ $field = $event->object; if($field->name == "text_field_name" && $field->value){ $markup = $event->return; $url = "https://somedomain.com"; $markup .= "<img width='100' src='". $url . $field->value ."'>"; $event->return = $markup; } }); I'm assuming $url is whatever you need to append to complete the url with the ID in place. This should render the image right below the text input. If you want to dig a bit more, check the code in the link I pasted and debug with a $log->save() the $markup variable which basically gets it's content from the $event->return property which matches the return value of the render function in the Inpufield code.
  30. 6 points
    Important security update! Hi RockGrid users, I'm very sorry for that, but I have to announce a security update. If you are using RockGrid on a public site please upgrade to v0.0.22 (Fieldtype) immediately. It is a simple but important update: https://github.com/BernhardBaumrock/FieldtypeRockGrid/commit/0be2086139c84f775937246ed2985ac4c4a3e9c3; The proplem exists on all RockGrid fields with AJAX turned ON. In this case it was theoretically possible to expose the field data to a user that should not be allowed to see this data (in the worst case even a guest user) if the user knew how to do it and he also knew the name of the rockgrid field. The update now restricts access for AJAX field data to superusers only. You can easily adjust that via simple hooks: // rockgrid access control $wire->addHookAfter("InputfieldRockGrid::access", function(HookEvent $event) { // all grid data is accessible for all logged in users $event->return = $this->user->isLoggedin(); }); Or more granular via the fieldname: // rockgrid access control $wire->addHookAfter("InputfieldRockGrid::access", function(HookEvent $event) { $field = $event->arguments(0); $user = $this->user; $access = $event->return; switch($field) { case 'field1': case 'field2': case 'field3': $access = $user->isLoggedin(); break; case 'field4': $access = ($user->name == 'foo'); break; } $event->return = $access; }); Field 1-3 is allowed for logged in users, field4 only for user foo and all other fields only for superusers (default rule). I'm not totally happy any more with several aspects of RockFinder and RockGrid, but it is the best option I have so far (until I can build something totally new, maybe with tabulator if tests work well). Special thx to @Zeka for bringing this issue to my attention by coincidence in the other topic!
  31. 6 points
    I found the issue! I'll file a report on github and link it here when I'm done. https://github.com/processwire/processwire-issues/issues/885
  32. 6 points
    my preferred way is to make a generic 'service' template, and have a 'services' index page, under which you can add as many services/ajax endpoints as you want; then you just have the template include the correct service php file by matching the name; in any given service file, you can do a return $this->halt() or exit() to stop the appending; you can also just turn off prepend/append for that service template and you'd be all set... that's risky and not so future proof; also on some templates it might prevent you from doing some processing before the head loads, for that template – maybe add a dns prefetch to the header, or a custom script or style for that template's pages. if you don't have a lot of templates, it is probably better to just include head and foot in each template file and skip the auto prepend/append. The benefit of using pages for your endpoints is that you have full native access to the api, and no bootstrapping necessary..
  33. 5 points
    I wanted to let you know that I am currently working on a new ProcessWire module that fully integrates the Snipcart Shopping Cart System into ProcessWire. (this is a customer project, so I had to postpone the development of my other module GroupMailer). The new module SnipWire offers full integration of the Snipcart Shopping Cart System into ProcessWire. Here are some highlights: simple setup with (optional) pre-installed templates, product fields, sample products (quasi a complete shop system to get started immediately) store dashboard with all data from the snipcart system (no change to the snipcart dashboard itself required) Integrated REST API for controlling and querying snipcart data webhooks to trigger events from Snipcart (new order, new customer, etc.) multi currency support self-defined/configurable tax rates etc. Development is already well advanced and I plan to release the module in the next 2-3 months. I'm not sure yet if this will be a "Pro" module or if it will be made available for free. I would be grateful for suggestions and hints! (please have a look at the screenshots to get an idea what I'm talking about)
  34. 5 points
    Not sure if you have in mind a site profile for generally sharing with the community, or something that is made available only to some specific users/clients. If it's the former I would think option 1 would be necessary if you want the profile to be usable by a wide audience. I expect there are many here who are not running Git or Composer. And as you say you would update the profile from time to time (not really different in that regard from a module you have authored). If it's the latter then another option could be @bernhard's Kickstart tool: You would provide users with Kickstart settings that point to a remote profile zip that does not include any third-party modules within it, and then add the third-party modules in the "recipe". That way a user who is installing the profile always gets the latest module versions. I suppose you could use the Kickstart approach for a generally shared site profile too but it comes back to the audience thing again. If PW beginners should also be able to use the profile then it's probably best if the profile can be installed as per the standard procedure without them needing to learn any additional tools.
  35. 5 points
    I wrote a script a while back to search for this kind of thing, though it doesn't spider Gitlab, PW gists or forum code yet. I've made a start at putting it online at pwgeeks.com. Currently only has about 60 items of over 1300 it has found to date - but as I massage it back to life, the directory will fill up.
  36. 5 points
    Here's some JS for that, for a Table field named "table_select_once". Add the JS any way that suits you - with AdminOnSteroids, a hook before Page Edit execute, etc. $(function() { // Disable options already selected in another table row function disableSelectedOptions() { var $selects = $('.Inputfield_table_select_once select'); $selects.find('option').prop('disabled', false); $selects.each(function() { var $selected = $(this).find('option[value!=""]:selected'); if($selected.length) { $selects.not(this).find('option[value="' + $selected.val() + '"]').prop('disabled', true); } }); } // Disable selected options on DOM ready disableSelectedOptions(); // Disable selected options when select changes $(document).on('change', '.Inputfield_table_select_once select', disableSelectedOptions); });
  37. 5 points
    @bernhard It's a little trick you can do with Google Chrome: In the responsive view mode, select one of the iPhone models in the responsive mode settings bar. In the flyout menu on the upper right, there's an option "show device frame". Only works with some of the devices, I've used "iPhone 6/7/8 Plus". If you take a screenshot (via the same flyout menu) while in responsive design mode with the show device frame option turned on, the device frame will be included in the screenshot.
  38. 5 points
    It will be free, open-source, like other starter tools out there.
  39. 5 points
    Regarding Site Profiles: what is really missing is a system which turns one into an updatable "theme". Especially when targeting beginners, it would be preferable to provide a way to keep those profiles updated via the admin, like Ryan's module updater. Also, using UIkit 3 as the bases of it would be appealing to beginners and also some experienced devs, for the usual reasons: a popular and documented css "framework" is easy to use, extend and update. The site profile could provide "hooks" so that it can be modified and extended without changing the "core theme". Sure, I did not provide any new ideas at all, it is just a quick summary of what have been sought after dozens and dozens of times here, in the forums. @bernhard might even be working on something like this maybe?
  40. 5 points
    I just released version 0.7.0 of the module: It fixes the ugly label being showed above the "inhterit" checkbox for newer Processwire versions. I think there is a bug in core, because ProcessWire ignores the fact that the label is marked as "hidden". I had to fix it via CSS for now. Added the possibility to resize the Opengraph image when referencing a page image by specifying a width and/or height. Opengraph image: If the referenced image field is empty and pulls the image from another page (default value), the module now substitutes the default image as well. Other than that the readme now contains a chapter for the various hooks provided by SeoMaestro. This might be interesting if you need to customize the behaviour of the module. Please let me know if you find any issues! Cheers
  41. 5 points
    A more complex approach would be a new fieldtype which allow to browse and select through the SmugMug API. Edit: just found this, which may help to go that way: http://phpsmug.com/
  42. 5 points
    RepeaterMatrix is going to be the best choice for any type of page builder in ProcessWire (at least at this time). The recent updates to the module improve its flexibility further, such as being able to change the matrix-type of an item that's already been added to a page (this is similar to Gutenberg functionality of being able to change block-types... nice). After using RepeaterMatrix and its equivalents in other CMSes over the years (such as WordPress ACF Flexible Content field), my suggestion is you're better off NOT providing fully customizable layout functionality within your builder (that is, avoid the capability of allowing users to add things like containers, rows, columns). I've personally found that even other CMSes that do this well and are built around that concept are just too clunky. It's the nature of the beast. The better approach in my opinion is to provide a good set (5-10) of matrix-types/blocks that can instead achieve this. Once again, the recent feature addition whereby matrix types can be changed is going to help here since switching a matrix-type retains its content as long as the matrix-type you are switching to uses the same fields.
  43. 5 points
    if($config->ajax) { header('Content-Type: application/json'); echo $json; $this->halt(); // like die(); } else throw new Wire404Exception();
  44. 5 points
    I had a similar need recently for a new Fieldtype & Inputfield called AdminComments (allows users to post comments on backend pages). The way i did it was to have a Process module which installs when you install the Fieldtype and Inputfield. The javascript gets the endpoint from a data attribute that the inputfield generates (i put all the data attributes for the post url and other info directly in the inputfield, though it could have been put in the JS config also). If it helps to see this method, i can share that beta module with you. I also researched extensively to see if i could get away without a process module, and use some other endpoint, but was unsuccessful, so i just went with a Process Module. I made the module permission page-edit so that it doesn't need any special permissions to access when doing the post requests.
  45. 4 points
    I forgot to write some update here. We made some minor and one major release since 1.0.0 with this changes: fix some log warnings from some Repeater fields Module can now be installed via composer Add support for $config->elasticsearchFeederConnectionOverride Better support of own hosted ElasticSearch Servers Use of PW 3.0.133's new $page->meta() feature instead of creating a fields for indexed pages CI Tests via circleci.com and peridot-php Current Version is 1.2.0 and since we use $page-meta() the module requires now PW 3.0.133 And a live production demo will follow the next 1-2 weeks.
  46. 4 points
    Just a small addition to this. I just added a new site profile to my Github page. It's a mix of the official blank and the multi-language site profile. The reason I made and published it is simple. This kind of setup/profile is almost always my starting point for a new project. So it saves me a lot of time for the inital setup. I kept (almost) all example files, removed demo content, added a few core modules and stripped almost everything in the output/template files. No UIKIT. No real output strategy. No hassle. Just BLANK in multilanguage flavour. It's not much, but it's honest work. PWB Multi Blank
  47. 4 points
    Very nice. For context, this is like custom fields for images by using repeaters. This request for custom fields for images natively is one that is open, and slated for core one day: https://github.com/processwire/processwire-requests/issues/21 https://processwire.com/about/roadmap/
  48. 4 points
    I ran into issues with a slow server using this method, where wireHttp would already resolve a result while RestApi was still running. So with help from my co-worker @harmvandeven we came up with a more stable version, with some more redundancy: <?php /* api.php, a simple PW template to fill the gap between the RestApi and ProCache modules v2 @author: @eelkenet, with help from @harmvandeven & @ryan 1. Create a template called 'api' and set it up using the following settings: - Allow URL segments - Allow guests to view the page - Set the Content-Type to application/json - Make sure to NOT Prepend or Append any files 2. Add a page using this template and allow ProCache to run its magic */ $timeout = 600; $maxAttempts = 10; // Pre-check for unwanted symbols if (strpos($input->urlSegmentStr(), '.') !== false) { throw new Wire404Exception(); } // Build request URL $endpoint = $modules->get("RestApi")->endpoint; $url = $input->scheme() . "://" . $config->httpHost . "/" . $endpoint ."/" . $input->urlSegmentStr(); $http = new WireHttp(); // Set a high timeout, to deal with a slow server $http->setTimeout($timeout); // Get the HTTP status of the page, to make sure it exists in the first place $status = $http->status($url); // If the page exists, or possibly redirects to valid content if ($status >= 200 && $status < 400) { $result = false; $attempt = 0; // If the result isn't a string, something went wrong while(gettype($result) !== "string" && $attempt++ < $maxAttempts) { $result = $http->get($url); if ($attempt > 1) wire()->log->message("Loading content at $url, attempt $attempt: " . gettype($result)); } // Double check if the data is a string.. if (gettype($result) === "string"){ // .. And check if it can be decoded, if so: return the data and thus cache it if (json_decode($result) !== NULL) return $result; // If it cannot be decoded: throw exception (don't cache it) throw new WireException("Found the data at $url, but it could not be decoded. Please check your API output!"); } // Throw exception if data could not be loaded in time (don't cache it) throw new WireException("Found the data at $url, but could not load it in time, after $attempt attempts. Result has type: " . gettype($result)); } // Throw generic exception if the requested page was not found or there was another error throw new WireException("Failed to load the content at: $url, with HTTP status: " . $status);
  49. 4 points
    Finally fixed @arjen's issue, culprit was a non-readable file within the pwpc directory which wasn't excluded since I forgot exclusion paths need to be site relative (/site/assets/pwpc/ for all ProCache users).
  50. 4 points
    Probably one of the $sweepstake_children doesn't have any images. Probably best not to rename the images within the page because that results in the loss of potentially useful filename data and would break any links to the images within CKEditor fields. Instead you could copy the files to a temporary directory, renaming them in the process, then create the zip and download from there. Here is some code you can adapt for your purpose: // Create temp directory $td = $files->tempDir('to-zip'); $td_path = (string) $td; $files_to_zip = array(); foreach($page->children() as $child) { $image = $child->images->first(); // Continue if no image exists if(!$image) continue; // Set path including new filename as needed $new_path = $td_path . "{$child->id}.{$image->ext}"; // Copy image to new path $success = $files->copy($image->filename, $new_path); // Add new path to array if($success) $files_to_zip[] = $new_path; } // Set destination path for zip file $zip_path = $td_path . time() . '.zip'; // Create zip file $success = $files->zip($zip_path, $files_to_zip); // Send download if($success) $files->send($zip_path); // Optionally remove temp directory now rather than waiting for it to automatically expire $td->remove();
  • Create New...