Leaderboard
Popular Content
Showing content with the highest reputation on 08/27/2022 in all areas
-
This week we’ve got a new core version on the dev branch (v3.0.204) and a new version of FormBuilder (v53) posted in the FormBuilder board. Relative to ProcessWire 3.0.203 version 3.0.204 has 23 commits containing a mixture of feature improvements and issue resolutions. While there aren't major feature additions here there are a lot of worthwhile improvements and fixes, and I'd recommend the upgrade if using the dev branch. See the dev branch commit log for more details. The new FormBuilder version includes various improvements but the biggest is a new version of the included InputfieldFormBuilderFile module that supports file/image uploads in forms. It has been improved with a preview option (for images), the ability to collect a description for each file, improved multi-file inputs, and more. The new options appear on the “Details” tab when editing a file field in FormBuilder. This new version (v53) is available for download now in the FormBuilder board. If you upgrade an existing installation with file fields, I’d suggest testing out those forms after upgrade, and also review the new options to see if they make sense for your form. Thanks for reading and have a great weekend!4 points
-
I'm working on a one-page, vanilla javascript and php (PW API) shopping checkout module that integrates PayPal server side. Here's version 1.0 https://github.com/dtjngl/kiosk Looking forward to your feedback! DISCLAIMER this is a BETA version at best, it's my first "real" module I'm writing for ProcessWire (and first module I'm writing at all) so please don't eat me alive. I'm aware that it needs a lot of work, but at this point, but it's functional. I'm also aware that it is not very customisable at this point (it's mostly customised for one specific use case), but I promise I will work on that. My main objective is to get more seasoned developers' mentoring, feedback, advice, warnings – and and of course, if you want to look into or help develop it further – pull requests. Please point out any potential dangers you see or anything that raises a red flag for you. I'm learning so much from that. Though the module is held in german, you can translate almost all strings that are in the php files via PW's translate functionality. I cannot help with the strings in the javascript yet, but will do so soon (using a json file that lives on the file system probably). I started working on this module because many checkout systems out there are either overkill and too complicated, didn't fulfil my needs or come with a premium fee that is not worth it. Also, austrian law (and other countries' jurisdiction) demand a different flow than what PayPal's Express checkout offers. So this version makes calls to PayPal on the server. WHAT IT CONTAINS - OnePage checkout system with 4 steps: cart, address(es) form, payment method (paypal and deferred), order overview - "minicart" (the cart-summary in the page's header) - buy button (to add items to the cart) - a dashboard (with admin template) for an overview of all placed orders uses server session storage and browser localstorage REQUIRED WireMail SMTP UIKIT (for best behaviour, will be optional soon) vanilla Javascript (no jQuery required) PHP (DUHDOY!) ProcessWire Version (not sure, but works with version 3.0.200) if you want it in english you need a multi-language installation PayPal Business Account (Live or Sandbox to test with) HOW TO INSTALL 1. Put the folder "Kiosk" in your ProcessWire site's modules folder 2. Install the module Kiosk, this will… - create fields for the order template - create a template for the orders placed - create a template for the orders' parent page - create a parent page "Custom Orders" for all orders under /admin/page/ (you can rename the page, not the template) - create a template "kiosk_checkout" for the checkout page - create a page "Checkout" for the checkout, child to "Home" (you can move the page, you can rename the page, not the template) - install module ProcessKiosk along with it - ProcessKiosk create a page under /admin/ (visible in the module upon creation). Here you will see a table with all the orders placed. 3. check the Kiosk module's settings page (navigate via the module's overview page) and enter details to your best knowledge. Some are not "required" but they actually are. 4. Put the below code (in essence) on "kiosk_checkout.php": if ($config->ajax) { $kiosk->handleAJAX($input); return $this->halt(); } else { $kiosk->handleStaticContent($input); echo $kiosk->renderCheckoutSteps(); } 5. put this line on a page that loads everywhere, preferably on init.php: $kiosk = $modules->get('Kiosk') 6. put this line where you want the "minicart" and toggling cart preview (provided the site runs UIKIT) to be, probably in a header that renders on each page: echo $kiosk->renderMiniCart(); 7. put this line just above you closing tag: echo $kiosk->addScripts(); HOW DOES THIS THE ORDERING WORK? 1. Add items to the cart or update quantity when viewing the cart, continue with "weiter". 2. Enter your address, if your billing address differs, uncheck the "gleiche Rechnungsadresse" and enter the billing address, checked or unchecked, both forms will be sent to the server but handled accordingly, continue with "weiter" 3. Select a payment method, continue with "weiter" 4. formdata object (containing cart items, address(es), payment method) will be sent via AJAX to the server and stored in the server session variable 5.1. if payment method is deferred - AJAX response contains the order summary markup that will render in step4 - don't forget to check " ich habe die Datenschutzerklärung sowie die AGB zur Kenntnis genommen und akzeptiere diese." (privacy policy and terms and conditions) - click on "Zahlungspflichtig bestellen" will send another AJAX request to the server thus submitting the order (continue to WHAT HAPPENS WHEN AN ORDER IS PLACED?) 5.2. if it's paypal, a bit more is happening - server sends a cURL request to paypal containing client ID and secret - response will send a token - server sends that token along with the purchase unit (created from our placed order) in another cURL request to paypal - response will send an "approve"-URL - AJAX response contains that URL - user is redirected to paypal to approve the order - user is redirected to the "checkout" page along with a token and PayerID as GET parameters - token (not needed actually) and PayerID are stored in the server session - with the PayerID in the session variable and the "status" of the paypal approved order in the localstorage the checkout process will head on to step 4: order summary - don't forget to check " ich habe die Datenschutzerklärung sowie die AGB zur Kenntnis genommen und akzeptiere diese." (privacy policy and terms and conditions) - clicking on "Zahlungspflichtig bestellen" will send another AJAX request to the server - second AJAX request will send PayPalAccessToken, PayPalPayerId and PayPalRequestId in another cURL to PayPal which will trigger the payment - response will… continue to WHAT HAPPENS WHEN AN ORDER IS PLACED? WHAT HAPPENS WHEN AN ORDER IS PLACED? an order-page with all the order's details (plus order number from the kiosk's number circle) is created under /admin/page/custom_orders/ (you can find it in the Kiosk Dashboard) number circle is iterated email markup is created using the module's default email template, you can add a path to a custom template in the module's settings email is sent to the site master and the user (check the module's settings for email addresses etc.) order in server session is reset to an empty array paypal session in server session is reset to an empty array localstorage of the browser is deleted user is redirected to a custom url (defined in the module's settings) HOW ARE PRICES HANDLED? prices allow for a stack price functionality. This means that prices and shipping depend on the quantity of items purchased. You can enter different prices and shipping costs for different quantities. If a user's amount of a selected item reaches the specified stack price, the item price and the shipping costs change. HOW ARE PRODUCTS ADDED TO THE CART? a product should be a page object to keep things simple. That page needs an "images" array field (that very name). Below you can see what a product would need. These values are added to the button's data attributes. // This is how you make a product… $product = new WireArray(); $product->id = $page->id; $product->title = $page->title; $product->source = $page->parent->name; $product->url = $page->url; $product->images = $page->images; $product->product_width = 150 // for proportional item image calculation in the cart $product->taxrate = 10 // or what ever the tax rate $product->stack_prices = array( array( "qu" => 1, "sp" => 19.99, "sh" => 5 ), array( "qu" => 10, "sp" => 14.99, "sh" => 0 ), ); $product->stack_prices = htmlspecialchars(json_encode($product->stack_prices)); // then render the "add to cart" button $kiosk->renderBuyButton($product); UPDATE version 1.1: installing kiosk.module will also create a repeater field "kiosk_product_stack_prices" (including 3 subfields as described above) that handles the stack_prices array of arrays (as described above) so you can use the GUI. create a field "kiosk_product_tax_rate" create a field "kiosk_product_width " create a field "images" if there is none in your system. create a template "kiosk_product" with all these mentioned fields use this template for your products (or the fields thereon at least and add to your template of choice) and you should be good to go. CAUTION! If you uninstall kiosk.module it will delete all pages with template "kiosk_product", that's because I'm still figuring out how to detach the fields and fieldgroups without deleting the template. Also, if you're coming from version 1.0 and want to upgrade, please uninstall it in 1.0 first and only then get the new repo (v1.1) to install again. Class kiosk now provides the following hookable methods: ___renderBuyButton(Page $product, (string) 'add to cart') pass a product (preferably with template kiosk_product) and it returns a buybutton with the price for 1 item. This method now accepts the button's label (string) as a second argument. Method is hookable. ___getSpecificStackPrice(Page $product, (int) 5) // 5 is just an example pass a product (preferably with template kiosk_product) and an amount, it returns the price for that amount of items. Method is hookable. ___getSinglePrice(Page $product) pass a product (preferably with template kiosk_product) and it returns the price for 1 item. Method is hookable. So, use template "kiosk_product" for your products, edit the product page to add details, and then do echo $kiosk->renderBuyButton($product, (string) 'add to cart'); to render an "add to cart" button.3 points
-
Yeah, that's one of very rare examples where PW might add a little too much magic ? The different return values of an image field can definitely lead to confusion or even worse to problems. Until April this year I thought I would be save just using $page->getUnformatted('images') as this always returns the array version. https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222914 But thankfully @Robin S has pointed out that this array might include temporary items and therefore might lead to unexpected results again... See https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222917 There are several not so obvious solutions to the problem: https://processwire.com/talk/topic/26952-get-image-in-the-context-of-a-hook/?do=findComment&comment=222942 --- For my taste this shows that the different output formatting return types introduce more complexity and risk than necessary, but that decision was made a long time ago so we'll have to deal with it. Instead of using ->getUnformatted() I have switched to using ->getFormatted() instead and making sure to set the correct value via RockMigrations. <?php class Example extends Page { public function myImage() { // return image as single pageimage return $this->getFormatted('myimage'); } public function migrate() { [...] $rm->createField('myimage', 'FieldtypeImage', [ 'label' => 'My demo image field', // make sure that the image field returns a single image 'outputFormat' => FieldtypeFile::outputFormatSingle, [...] ]); } } I just realized though, that this can be a problem, because I'm defining an important piece of the method "myImage()" in another method! So on a more complex pageclass I might change the outputFormat of the field to outputFormatArray and I'll introduce a bug in myImage() ! That's not good... I think we should have something like this: $page->getImage('myimagefield'); // returns PageImage (or null) $page->getImages('myimagefield'); // returns PageImages Array That would make a bulletproof code look like this (which would then be a simple answer to your simple question): $image = $page->getImage('myimagefield'); if($image) echo "<img src='{$image->maxSize(400,300)->url}' alt='...'>"; // or $images = $page->getImages('myimagefield'); if($images->count()) echo "<img src='{$images->first()->maxSize(400,300)->url}' alt='...'>"; That would look a lot more like PW imho ? I've created a request for that, so if you like the idea give it a thumbs up: https://github.com/processwire/processwire-requests/issues/4532 points
-
I'll share my youtube videos in this thread and if you have questions this is the place to ask. You can also subscribe to this thread to get notified when I post new videos ? Here is the link to my channel: baumrock.com/youtube --- Hey! I've just published my very first ProcessWire video. It's about RockFrontend: https://processwire.com/talk/topic/27417-rockfrontend-??-take-your-processwire-frontend-development-to-the-next-level/#comment-225666 Here is the video: What do you think? Do you understand what I'm trying to explain (despite the many ääähms und öööhms...)? ? What about the length?? I really didn't plan do get to 40mins... Did anybody even watch it till the end? ? Would it be easier to follow when having a small thumbnail in the bottom corner when working on the code? Or better without? Is it worth the effort of creating a video or would a readme be just as good? ? Any tips for better sound/lighting? I'm not really knowing what I do, so any ideas for improvements are very welcome ? Better with or without background music? So many questions... So much to learn... ? But it's fun and I'm a bit proud ?1 point
-
Out of the box (without third party modules) your best option is the Page Table ("ProFields: Page Table") fieldtype. It's included with the core package, but might be uninstalled by default. The user interface for Page Table is a bit different in that you'll edit content in modal windows instead of "in context", but I'd suggest that you give it a try. You can save your content items under current page, or a different location in your page tree. If third party modules are an option, the Repeater Matrix module is worth checking out. It's commercial (paid) module, but if that's not an issue, it's really quite amazing. Other (non-commercial) module options include PageTableNext and PageTableExtended.1 point
-
@BrendonKozThanks for the interesting write-up. Generally speaking, with maps or chart graphics, there are two main ways to ensure accessibility: One is described neatly in this article: https://css-tricks.com/accessible-svgs/#aa-interactive-images e.g. the use of role=group vs. role=img, using role=list role=listitem, tabindex etc. In your map, you could turn your three floor groups into three lists. The other strategy is to output an unstyled + visually hidden table or ul/ol somewhere that represents the floors and rooms/areas. You would then simply put aria-hidden=true on the entire SVG. This strategy is certainly the most efficient. However, if you want to enable focusing areas with the keyboard (for people who can't use the mouse), you'd have to alter your SVG further, like the above example.1 point
-
Checkout for what? Checkout with which providers? Checkout with which framework? What is your module doing? Don't get me wrong but... a bit more details would be nice. Maybe adding your README here would be a great start. Is this based on Shopify, Snipcart, Foxy or plain ProcessWire? I'd like to play with your module. Easy one-click-solutions are always nice, but... details and some kind of introduction would be really nice. Update: Details were added.1 point
-
Apparently ready.php is too late for direct page views, so I would recommend init.php.1 point
-
I just remember endless toil trying to get standard appearances across browsers - still an issue, but nothing like the nightmare of trying to get Opera, Netscape, IE and Safari to be friends. And so much flash animation. So much. And then XHTML was going to be a thing, and UML was going to make everything play nice. And then those fun proprietary tools like coldfusion - I thought CFML was pretty cool. And the not fun tools. Pretty much every yahoo store RTML project was a shotgun to the face. Things have gotten so much more enjoyable, thanks to preprocessors and more uniform standards, etc. Really amazing how for we've come. I built my own CMS in ASP, then realized being part of a CMS community was important - Textpattern did everything I wanted out of my own system. Then clients asked for WordPress. Now its just got to be interoperable, fast, flexible and Processwire serves that purpose very well. At the same time, there's so much that can be done without developers now - it's really been interesting.1 point
-
The ProFields Combo field and Table fields create SQL tables behind the scenes, but they're still fieldtypes, so are expected to be added to a ProcessWire template and are linked to the page tree. Sometimes that's not necessary or desirable. With regards to creating custom tables, I'm quite happy writing SQL statements for this, or using the generated CREATE TABLE statements with a database export from mySQL, or for that matter even other dialects of SQL, with a bit of editing if necessary. It's not hard to write a CREATE TABLE statement initially, then an ALTER TABLE statement if subsequent changes are needed. I think this would play nice with your RockMigrations module to generate SQL schema changes in code, and I don't want to turn ProcessWire into mySQLAdmin or Adminer which is installed with Tracy Debugger, but it would be nice to have an end user friendly UI to view and edit custom SQL tables in the ProcessWire admin. You have made me thing of something I hadn't considered, about how to migrate SQL listers and editing forms, if the InputField settings or fields to display in a lister change, but if they're accessible via the API, it should be possible to manage migrations in a similar way to ProcessWire native fields and templates.1 point
-
@ryanFieldtypeCombo comes pretty close, but like you say, you define the table structure with the fieldtype. Also as a fieldtype it needs to be associated with a template, that links into the ProcessWire page tree, which isn't always desirable with SQL tables from an existing database. I'm thinking there would probably need to be two configurable Process modules. An ProcessSQLLister and ProcessSQLForm module. Names are just suggestions ProcessSQLTemplate could be another option however as it's not an output template, it's an admin UI for editing arbitrary SQL data. ProcessSQLLister would be similar to Lister Pro, except for selecting a source, you'd select an SQL table, then choose what fields from the table to display in the lister. Dealing with lookup fields which are similar to page reference fields, but can refer to an arbitrary database table would probably be the biggest challenge, but the basic lister should be pretty straightforward. Edit functionality would depend on a related ProcessSQLForm being defined for the specified table. ProcessSQLForm would involve picking an SQL table, then selecting fields from the table to include on the form in the order desired, and mapping and configuring a sane InputField type depending on the SQL field type. @kixe has already made FieldtypeSelectExtOption which can handle lookups from arbitrary SQL tables, so that InputField should be able to handle relational reference fields, and core InputFields should be able to map to other SQL fields types. For both, access control at the table level would be desirable. While access control at the field level would be technically possible, I don't think it's necessary at least initially, especially if it adds complication since the fields are SQL fields rather than ProcessWire fields. I can try to mock something up, but if someone else beats me to it, then feel free to go ahead. I think ProcessWire has all the nuts and bolts to do this, it's just a case of putting them together.1 point
-
Good plan. I was also thinking that you could use config inputfields to define the mapping (as types allow) and to specify a custom form layout. Not sure if I will get around to trying it*, but maybe @Kiwi Chris might like to. My attempt at documenting these types of modules might help. *I am pondering rewriting ProcessDbMigrate to operate with its own database (a bit like TextformatterHannaCode) but, even if I do, it is unlikely to happen in the near future.1 point
-
The backend is basically just a uikit navbar + content: https://getuikit.com/ You can simply include the backend theme files and use them for your frontend. You can even use the Less module and you get all the power of Less and variables etc. See https://github.com/baumrock/AdminStyleRock#how-adminthemeuikit-styles-work for details1 point
-
Hola Hanna, actually I dont't know _x() probably this function but __("string to translate") (two underscores) translates strings in template files, or better to say let's you translate via /processwire/setup/languages/ So in your case you would either change the line from <html lang="<?php echo _x('en', 'HTML language code'); ?>"> to <html lang="<?php echo _x('de', 'HTML language code'); ?>"> or you in admin you go to /setup/languages/ select your default (german) language and click on_main.php to translate, somehwere there should be written "HTML language code" and there you enter "de" I used a different approach in _init.php I defined the following // define var $lang for use in tpl files if($user->language->name == 'default') $lang = 'de'; else $lang = $user->language->name; then you can just put this in _main.php <html lang="<?= $lang; ?>"> and of course re-use wherever you like. Or, you could use the languages title field or add another custom field to language template and name it for example "language_short_code" or maybe you got an already created textfiel which you could re-use here. then you don't need to override the default languages name but just output your shortcode field like <html lang="<?= $user->language->language_short_code; ?>"> Hope it helps, enjoy Processwire1 point