Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 11/30/2020 in all areas

  1. Announcing the current status, planned release, roadmap and preview of Padloper 2. Status Feature freeze. Full multilingual support. Only PHP 7.2+ supported. Support for ProcessWire 3.0 only. Backend support for modern browsers only (that support JavaScript ES6 modules). Current Work Finish work on admin/backend. Work on installer and uninstaller (including configurable availability of some features). Work on UI/UX improvements. Start work on documentation with special focus on technical documentation. Continue work on Padloper API and data/model component. Roadmap Please note that these ARE NOT hard and fast targets. The roadmap may have to be adjusted to accommodate technical and non-technical constraints. Q1 2021 Inbuilt support for (latest) PayPal (full rewrite, no external modules required). Additional work on Padloper API. Invite a limited number of early alpha testers (fully-priced product). Soft and closed release of Padloper 2. Q2 2021 Start work on relaunch of Padloper website. Inbuilt support for Stripe (no external modules required). Future Plans Support for more Payment Gateways. Support for order, customers, etc imports and exports. Support for AdminThemeReno and AdminThemeDefault. Separate fully-featured frontend shop module. Consider support for multiple currencies. FAQ 1. Have you abandoned this project? No. 2. When will Padloper 2 be released? First early alpha release is scheduled for Q1 2021. This target may change depending on circumstances! Access will be by invite only for this first release. 3. What is the pricing model of Padloper 2? Three licences: Single Site, Developer and Agency licences (12 months’ updates and VIP support). 4. How much will Padloper 2 Cost? No price has been set yet. It will cost more than Padloper 1. 5. Can we upgrade from Padloper 1? No. 6. Will existing users of Padloper 1 get a discount for Padloper 2? No, this will not be possible. Apologies for the earlier announcement. It was unrealistic and unworkable. 7. Can we pay for Padloper 2 in advance? No. 8. Does Padloper 2 render markup/templates in the frontend? No. Access to all data you need to build your shop’s frontend is via the Padloper API. 9. Can we keep sending you ‘Are we there yet’ messages? No, please. Preview Here is a video preview of the current state of the backend/admin of Padloper 2. Please note the following: This is early alpha. There are bugs! It even includes WIP/notes!! FOUC, misaligned things, etc. The video shows the near-raw implementation of Vuetify UI. The UI/UX improvements work is yet to start. What you see here is the development version. Some of the incomplete features may not be available in the early releases. Most of the features you see will be optional to install.
    8 points
  2. Preloads should go in the <head> of your HTML, before most of your other assets, so they can be discovered and preloaded very early. The root of your FOUT issue lies somewhere else, however. The problem is that you're only preloading the CSS file from Google Fonts, but not the fonts themselves. Check out the CSS file you're preloading - it's only 9 lines! So preloading this will have a negligable effect (DNS preconnect or prefetch would be more useful in this case). That's because the CSS file only includes the @font-face definition which includes the URL to the actual font file. In modern browsers, this will be a woff2 file - this is what you want to preload. One caveat of this is that older browsers which don't support woff2 will receive a different font file in a different format, so those users will have preloaded the woff2 gratuitously. On the other hand, if you add preloads for all available font formats, everyone will receive multiple files they don't need. Personally, I would only preload the woff2 file. I would also recommend hosting the fonts locally - if you're in the EU, this is kind of necessary for GDPR compliance. And since Browsers nowadays have segmented caches anyways, loading the fonts from Google isn't that much faster. It also helps to have a predictable URL to preload the font from - if you preload the font file from Google, the preload will break any time a new version of the font is released (see the version number in the URL above ...).
    4 points
  3. For anyone who is interested in integrating tailwind inside a processwire project here is a little walktrough based on my workflow. This little guide is based on Tailwind 1.9.6 (latest before 2.0 release) because some PostCSS library I use are still not compatible with 2.0 version (not a big deal, really). You can find the necessary files here. - Place package.json, tailwind.config.js, postcss.config.js inside your template folder. - Create a "pcss" folder, and make a structure like this: pcss ├── inc │ ├── colors.pcss │ ├── fonts.pcss │ ├── media_queries │ │ ├── lg.pcss │ │ ├── md.pcss │ │ ├── sm.pcss │ │ └── xl.pcss │ └── sitewide.pcss └── kickstart.pcss Now you got everything to get started, let's have a look at the files: package.json Inside "package.json" you have different dependencies I've installed to mimick my "old" scss workflow (importing, nesting, etc..), the important part however is the script section: "start": "npx tailwindcss build pcss/kickstart.pcss -o css/dist.css", "watch": "npx postcss pcss/kickstart.pcss -o css/dist.css --watch", "build": "cross-env NODE_ENV=production npx postcss pcss/kickstart.pcss -o css/dist.css" "start" is the bootstrap script you have to run at first, to let node compile tailwind as a whole. Do it at the beginning of the project or everytime you make some changes to "tailwind.config.js" Change the name of your pcss files accordingly (I've used pcss as an extension, but css would work perfectly fine) "watch" is the next script you have to run in order to have live reload of your stylesheets. "build" is the script you have to invoke once you are ready to deploy to production (you need to specify your purge rules inside postcss.config.js, keep reading.) tailwind.config.js Here you can specify your tailwind configurations, read the docs here. One thing to notice inside mine is that I've set purge: false because I prefer to configure the purge part inside a dedicated file, which is: postcss.config.js This file is responsible to handle postcss options, and purge is one of them. The paths you declare inside the content array are the ones whom will be scanned and purged eventually. Mine could be different than yours, so pay attention. The whitelistPattern array is useful when you want to exclude some classes from the purge phase, below I'm excluding the ones whom starts with "fff-". ... content: [ './*.php', './inc/*.php', './fields/*/*.php' // etc. ], whitelistPatterns: [ // Pattern to exclude during extraction /^(fff-)/ ], ... The other settings are pretty explanatory (cssnano is used in production for minification). As a final note you'll notice that every pcss file I use starts (and ends) with: /* purgecss start ignore */ css... /* purgecss end ignore */ Those tell purgecss to ignore completely the file, since I know I want to retain every rule/class I write in there. If you got everything setup correctly you can start having fun ? Run: npm install then: npm run start and finally: npm run watch Hope this little "guide" could enlighten in using Tailwind ?
    3 points
  4. ? https://google-webfonts-helper.herokuapp.com/fonts
    2 points
  5. This site has been a long time in the making. Back story: Was first developed in PW 2.something many years ago. Around 5yrs ago, it underwent a major upgrade. The look was very 90's and the booking page had around 50 input fields on the one page. See screenshots. Original dev, who did a great job with web technology at the time, went AWOL Business was sold to a new owner New owner engaged me to revamp the site. I laugh & laugh & laugh. If only I knew then what I know now! It was crucial that the years of historical data be kept and accessible Busy period is November to February (Aussie summer). And then came COVID. Victoria was the state hardest hit with C19 in Australia and lockdowns were harsh. Definitely no parties. The possible product configurations, hire rates & rules (all with 'except for this one') had me melt into a puddle at times. Pricing is shown on product pages only when a valid venue postcode & event date entered and can change depending on the surface type (eg concrete attracts a $50 surcharge) One of the biggest things that tripped me up was the previous dev combined data/module logic with presentation HTML. I had to rewrite all the old code to adapt to the new layout. Would have been much easier to have logic & presentation separated. A while ago I chose to stop using CSS frameworks to dig deep into how CSS really works. Much of what I have learnt is in the site frontend code. The site is fully responsive and the only JS used is on the View Booking page when a customer alters the booking item qty. There is NO frontend presentation JS, including the dropdown & mobile menus. Where it stands today: There are still some things to do, including implementing a very sensible change recommended by @ryan. In addition to the frontend, there are a number of new backend/admin reports Victoria is coming out of C19 hell and getting back to normal The site is live and online bookings are rolling in New modules added: ProCache FormBuilder + StripePayment + Page Break CampaignMonitorAPI ProFields - Functional Fields ProFields - Repeater Matrix RockMarkup2 Database Backups Upgrades SeoMaestro TracyDebugger Page View Statistic Big shout out 'Thank you' to all the PW devs who responded when I reached out for help in the forum. Check out the new look www.aaronsamusements.com.au
    1 point
  6. ProcessWire 3.0.169 contains 19 commits relative to 3.0.168, and most are focused on improvements and minor fixes throughout the core. For more details see the dev branch commit log. This week I’ve also been working quite a bit on a new ProFields module that at the moment is called Combo. It contains both Fieldtype and Inputfield modules within it, and I’ll have more to tell you about it soon. But I can say that it fits right in with the purpose of ProFields, which is: greatly reduce the number of fields needed to accomplish a particular need. And it does so in a way that isn’t easily achieved with any other module at present, so I think it’ll be a nice addition. The Inputfield part of it can also be used independently of the Fieldtype, meaning you could use it in FormBuilder forms, etc. I’ve got to keep it short today because of the Thanksgiving holidays here in the US (my wife is off work and kids have no classes today). Thanks for reading and have a great weekend!
    1 point
  7. I'm reluctant to do that because the presence of the Hanna Code textformatter is how the module knows whether it should be interfering with the CKEditor field by loading plugins that will widgetise strings surrounded by the Hanna Code delimiters. Although it wouldn't be a common scenario, it ought to be possible for someone to use the Hanna Code delimiters for some other purpose within a field that isn't configured for Hanna Code without Hanna Code Dialog messing with it. You situation sounds like a fringe case. If the objective is to use unformatted field content in the repeater label could you use a hook instead? E.g. $wire->addHookAfter('InputfieldRepeater::renderRepeaterLabel', function (HookEvent $event) { $page = $event->arguments(2); $inputfield = $event->object; $field = $inputfield->hasField; if($field->name !== 'your_repeater') return; $label = strip_tags($event->wire()->sanitizer->truncate($page->getUnformatted('body'), ['maxLength' => 100, 'more' => ''])); $event->return = $label; });
    1 point
  8. I just made today a class for Processwire that automates the process quite a bit. It's really basic, I will improve it in the future. https://github.com/carlitoselmago/opengraphPW It's used like this: <head> <?php include_once("./opengraphPW/opengraphPW.php"); $OG=new openGraph( $page, // current PW page, required $pages, // PW pages wire object, required $config->urls->templates.'img/cover.jpg', // A general image (1200x628px recomended) for pages like a home page where there's no content image, optional "Title of your website"); // A generic title if the home element is called something like "home", optional ?> </head>
    1 point
  9. New field (created via GUI) without tags: Then apply: $field->useTags = 1; $field->save(); but nothing happens yet. But then reload the field settings page in the admin and now it looks correct: so it seems like the updating of the DB schema doesn't happen on save(), but rather when the field is loaded. My guess would be that this behavior was broken when Ryan added the new custom image fields a while back.
    1 point
  10. Try curly braces around the $item->images->first()->url. Actually I don't think this won't really solve the encoding issue haha. ?
    1 point
  11. @humanafterall If you are developing on localhost and need to override the https settings in your template files you can do this by using copying your site/config.php file to site/config-dev.php file, and adding this option to the new file: $config->noHTTPS = true; ...and it should work. There are several posts here in the forum that talk about how to setup your dev and live config files.
    1 point
  12. Thanks — this is now fixed as well ?
    1 point
  13. @teppo - that looks to have fixed that issue. Something else I have just noticed is this when viewing the Wirefame module settings, although this probably isn't PHP 8 related.
    1 point
  14. Congratulations... This looks fantastic. I've run a lot of stores and I feel like you really captured a lot of must-have features that are often neglected elsewhere.
    1 point
  15. 1) Works for me also and I haven't made any changes for over a month. 2) I agree that an explicit classname section would be a nice improvement. 3) Also no problem here - it redirects as expected.
    1 point
  16. @MSP01 Thanks for the feedback. 1. I couldn't duplicate that, when searching "admin action" it does find ProcessAdminActions for me at least. Though several days have passed so maybe Adrian recently updated something in the module info that makes it match. 2. The class name is the primary headline. But someone else mentioned this too, I will add something else that specifically indicates it. 3. I also can't seem to duplicate this. Those pages should be redirecting to the new modules directory URLs. Maybe it got stuck on that one for one reason or another. I have cleared the caches just in case.
    1 point
  17. Thanks for reporting this, @adrian! The issue is clear (return types for magic methods are now enforced by PHP) and the fix is simple, but I'll have to set up a test environment to make sure it really fixes the error... and doesn't introduce any new issues ? I'll get back to this ASAP. Edit: the dev branch at https://github.com/wireframe-framework/Wireframe/tree/dev now contains a fix for this, if you'd like to give it a try. I'll have to test this properly before merging to master.
    1 point
  18. $country = $session?->user?->getAddress()?->country; love it ?
    1 point
  19. Does this help? https://github.com/fusonic/opengraph#retrieve-open-graph-data-from-a-url You could try without a library, but something like: https://stackoverflow.com/questions/7454644/how-to-get-open-graph-protocol-of-a-webpage-by-php may not not be very reliable. There is also this: https://www.opengraph.io/examples/php-open-graph-example/ / https://github.com/primeobsession/opengraph-io-php but it hasn't been updated in years so not sure this is a great way to go but might be a useful resource nonetheless.
    1 point
  20. @jploch - this really does look very nice - much cleaner and more professional. I really appreciate the hard work that's gone into it and I would love to use it, but unfortunately for me it always comes back to the fact that themes in PW tend to end up out of date when Ryan applies fixes and new features so I find it's just not worth the risk. Am I the only one that feels this way?
    1 point
  21. The nifty code: $base = wire('config')->urls; $cssUrl = $base->InputfieldPassword."InputfieldPassword.css"; echo '<link rel="stylesheet" href="'.$cssUrl.'">'; $jsUrls = array(); $jsUrls[] = $base->InputfieldPassword."complexify/jquery.complexify.min.js"; $jsUrls[] = $base->InputfieldPassword."complexify/jquery.complexify.banlist.js"; $jsUrls[] = $base->JqueryCore."xregexp.min.js"; $jsUrls[] = $base->InputfieldPassword."InputfieldPassword.min.js"; foreach ($jsUrls as $jsUrl) { echo "<script src='$jsUrl'></script>"; }
    1 point
  22. For the topic how to import / batchimport content into PW you will find many posts with examples in the forums, - so I will focus on your special issue with your images that are linked to "./images/...." in your htmlContent. Assumed, you use an importer script, that reads the following from a source: title / name of an entry html content images basenames Assumed, that the importer script can access the imagefiles / knows where they are kept for the import. And assumed that you have created a template with fields for those pages you want to create during the import. Then you will come to a point, where you programatically create a new page: $p = new Page($myTemplateObject); $p->of(false); $p->title = $theEntryTitle; $p->parent = $theParentContainerPage; $p->save(); Now you can add / import your images to an imagefield: foreach($imagebasenameArray as $basename) { $p->imagefield->add($directorypathToImages . $basename); } Now all images of that entry resides in /site/assets/files/{PAGE_ID}/. And you have to modify your html-content to match this: $p->body = str_replace("./images/", $config->urls->files . $p->id . "/", $htmlContent); $p->save(); This way you will have the most possible flexibility with your pages, I think. Please note: written in the browser, - may have bugs, - is meant as pseudo code.
    1 point
  23. The problem with your approach is, that it only requests the data once and ProcessWire returns all pages instead of those who match the query string. This could be a problem on very dynamic sites, where the content changes often. Here is my solution which solves this: Modify the standard search.php and add if ($config->ajax) { header("Content-type: application/json"); // Set header to JSON echo $matches->toJSON(); // Output the results as JSON via the toJSON function } so the whole file reads <?php namespace ProcessWire; // look for a GET variable named 'q' and sanitize it $q = $sanitizer->text($input->get->q); // did $q have anything in it? if ($q) { // Send our sanitized query 'q' variable to the whitelist where it will be // picked up and echoed in the search box by _main.php file. Now we could just use // another variable initialized in _init.php for this, but it's a best practice // to use this whitelist since it can be read by other modules. That becomes // valuable when it comes to things like pagination. $input->whitelist('q', $q); // Sanitize for placement within a selector string. This is important for any // values that you plan to bundle in a selector string like we are doing here. $q = $sanitizer->selectorValue($q); // Search the title and body fields for our query text. // Limit the results to 50 pages. $selector = "title|body%=$q, limit=50"; // If user has access to admin pages, lets exclude them from the search results. // Note that 2 is the ID of the admin page, so this excludes all results that have // that page as one of the parents/ancestors. This isn't necessary if the user // doesn't have access to view admin pages. So it's not technically necessary to // have this here, but we thought it might be a good way to introduce has_parent. if ($user->isLoggedin()) $selector .= ", has_parent!=2"; // Find pages that match the selector $matches = $pages->find($selector); $cnt = $matches->count; // did we find any matches? if ($cnt) { // yes we did: output a headline indicating how many were found. // note how we handle singular vs. plural for multi-language, with the _n() function $content = "<h2>" . sprintf(_n('Found %d page', 'Found %d pages', $cnt), $cnt) . "</h2>"; // we'll use our renderNav function (in _func.php) to render the navigation $content .= renderNav($matches); } else { // we didn't find any $content = "<h2>" . __('Sorry, no results were found.') . "</h2>"; } if ($config->ajax) { header("Content-type: application/json"); // Set header to JSON echo $matches->toJSON(); // Output the results as JSON via the toJSON function } } else { // no search terms provided $content = "<h2>" . __('Please enter a search term in the search box (upper right corner)') . "</h2>"; } Then call typeahead with the following options: $.typeahead({ input: '#q', order: 'desc', hint: false, minLength: 3, //cache: false, accent: true, display: ['title'], // Search objects by the title-key backdropOnFocus: true, dynamic: true, backdrop: { "opacity": 1, "background-color": "#fff" }, href: "{{url}}", emptyTemplate: "No results for {{query}}", searchOnFocus: true, cancelButton: false, debug: true, source: { //url: actionURL // Ajax request to get JSON from the action url ajax: { method: "GET", url: actionURL, data: { q: '{{query}}' }, } }, callback: { onHideLayout: function (node, query) { $('#searchform').hide(); console.log('hide search'); } } }); The important parts are "dynamic:true" and the "source" configuration so the query string is beeing sent. Now you have a nice AJAX search. EDIT: If you also want to find the query string in other fields than the title make sure you add filter: false to the config of typeahead.
    1 point
×
×
  • Create New...