Jump to content


  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by psy

  1. psy

    Get ready to party!

    @flydev ?? ? The home page has no caching. It's pure HTML & CSS including the gallery slider above the footer. CSS is such a powerful beast and HTML now has image lazy loading. The images in the slider, subsets of party packs, list of suburbs & featured customer love change on every page load which is a testament to the power & speed of PW
  2. psy

    Get ready to party!

    Thanks @flydev ?? and I'll check what's happening in Safari (the new IE ?) Edit: Scroll bar works on my MAC with Safari 14.0.1 so not sure why it's not working for you
  3. psy

    Get ready to party!

    Client happy with Happy Monkey ?
  4. psy

    Get ready to party!

    A little more to the back story... Client's biggest target audience is children's parties hence the look. The only time I said an absolute "NO" to client was when client said use "Comic Sans" font. There are some boundaries I will not overstep! Heading font is Google 'Happy Monkey'. ?
  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
  6. @PCuser Glad to help. Suggest editing your original post and inserting [solved] to the start of the title ?
  7. @PCuser there many ways to sanitise data using $sanitizer, eg pageName, digits, text, camelCase, etc, which is why you need to let $sanitizer know which method to use. They're all listed in the documentation. ?
  8. @PCuser you need to let Sanitizer know what kind of clean-up to do, eg: $sanitizer->pageName($sportspage->title) will convert the title text to lowercase and replace spaces with hyphens to make it suitable for use in a URL (or HTML id attribute). See what other $sanitizer methods are available at https://processwire.com/api/ref/sanitizer/ PS: Page titles can change and also not be unique. I prefer to use a letter first (HTML ids must start with a letter) then use the page ID, eg s1234. Alternatively, you could use the existing page name rather than the title.
  9. @joe_ma Maybe something like (untested): <?php $content .= '<main class="front">'; // Container for circles $content .= '<ul class="topCircles" role="navigation">'; // nav list // Output of 16 li elements with links at the chosen postions $items = $page->children("limit=16, sort=sort"); // PageArray limited to 16 items. Sorted according to template/page children settings foreach ($items as $item) { if ($item->front_position == $item->index() { $content .= '<a href="' . $item->url . '">' . $item->title . '</a>'; } $content .= '</li>'; } $content .= '</ul> </main>'; // Ende Liste und Container From the PW API Docs: https://processwire.com/api/ref/page/index/
  10. @joe_ma not sure if it's the issue but seems to me you're using a PHP array functions on a ProcessWire PageArray object - different beasts Is not a PHP array. It is a ProcessWire PageArray.
  11. Those subpages are now linked to your home page and you change your home page template to show what fields you want. For example, if your page reference field is called 'featured', in your home page template you can choose what fields you need to show from the subpage. <?php foreach ($page->featured as $apartment) : if ($page->featured->first->id == $apartment->id) : // it's the first one ?> <div class='featured first'> <h2><?=$apartment->title?></h2> <p>Bedrooms: <?=$apartment->bedrooms?></p> <p>Bathrooms: <?=$apartment->bathrooms?></p> <p>Price: <?=$apartment->price?></p> </div> <?php else: // it's not the first one ?> <div class='featured'> <h3><?=$apartment->title?></h3> <p>Bedrooms: <?=$apartment->bedrooms?></p> <p>Bathrooms: <?=$apartment->bathrooms?></p> <p>Price: <?=$apartment->price?></p> </div> <?php endif; endforeach; ?>
  12. Hi Brandy and welcome to ProcessWire There are many ways to achieve what you want. Hardest part is deciding which method works best for you and you client, eg: On your home page template you could have a Page reference field that allows your client to choose the featured projects and make the first the "main" project. For output, loop through the chosen page references and ensure the main project (page reference Project #1), gets different, more prominent styling. Use Tags on Project pages, eg "Home page featured" & "Home page other". Then in your home page template, use a selector to get the featured projects and loop through as above Based on info you supplied, I'd go with option 1 Hope this helps
  13. Just tested and it works a treat ? When a frontend user enters their event date, in _init.php: <?php if (!empty($input->post->availability)) { $availability = $sanitizer->date($input->post->availability, 'Y-m-d'); $sameDayBookings = $pages->find("template=booking, booking_date=$availability, booking_status!=pending|cancelled",['loadOptions'=>['autojoin' => true, 'joinFields' => ['booking_items']]]); $cache->save('sameDayBookings', $sameDayBookings); } This query takes no time at all. Next, in my custom module: <?php /** * @param Page $item - product page * @return int|void * @throws WireException */ public function itemAvailability(Page $item) { if ($item instanceof NullPage) return; $itemBookingCount = 0; $otherBookings = $this->wire('cache')->get('sameDayBookings'); if ($otherBookings->count > 0) { // there are other booking on the same event date foreach ($otherBookings as $otherBooking) { foreach ($otherBooking->booking_items as $otherBookingItem) { if ($otherBookingItem->booking_item->id == $item->id) { $itemBookingCount = (int)$itemBookingCount + (int)$otherBookingItem->booking_qty; } } } } $itemsAvailable = (int)$item->qty - (int)$itemBookingCount; return $itemsAvailable; } Query times for this function went from an average of 3.5sec to under 0.01 seconds per item and under 1sec to render the page listing multiple items with their availability. Happy dance time! Thank you all!
  14. Grateful for all your suggestions and you gave me an idea. Didn't get a chance to test today but will try tomorrow. It's a conglomeration of your suggestions. in _init.php prepended to all pages (or maybe refined to only the pages on which it's needed ?), collect all bookings for the day, regardless of individual item ids and cache it. Historical bookings won't change and without the repeater stuff, will be quick; instead of going back to the db for all calls, run the individual item queries on the cached page array - at most 20 items Will report back ?
  15. @dragan No question you ask is ever dumb! I should have made it clearer. Each item is a page, a product page. The qty is an integer field and refers to how many units of that product are owned by the client. The $limit is set to that number. The query searches through other bookings for that item on the nominated day, and on each match, subtracts the booking_qty from the item qty, to return how many are left for hire on that date. When all are booked out, the front-end customer cannot add it to their cart to prevent over-booking. A count wont do it as other bookings may have booked 2 or more units of the same item on that day.
  16. @BillH Thanks, I tried RockFinder3 a while ago. It's certainly a great module however I couldn't figure out how to get it working with Repeater fields. It's perfect with direct relation fields, eg PageReference but Repeaters are different beasts. Not sure if RF3 handles '.' separated fields in the selector, eg "booking_items.booking_item.id" either?
  17. I have a $pages selector that works great in giving me the requested info. However it's incredibly slow. Added to this, the request may be called up to 15 times on a particular page for 15 different listed items. <?php // in my custom module... // retrieves qty of items already hired on a particular day to determine availability for new bookings // booking_items is a repeater field and booking_item are repeater pages // I already have the $item and the $eventDate // Query is searching through 5K+ bookings and at least 3x that many booking_item repeater pages $limit = $item->qty; $selector = "template=booking, booking_items.booking_item.id=$item, booking_date=$eventDate, booking_status!=pending|cancelled, limit=$limit"; $pp = $this->wire()->pages; $otherBookings = $pp->find($selector); Each item query can take between 2 to 8 seconds ? What can I do to speed up this query? TIA psy
  18. Had an extreme example to deal with recently. Multiple field replacements for various fieldtypes. May not be the best approach but worked for me. Private function is in a custom module function. <?php /** * Takes a page field, eg 'body' as a template and replaces tags eg {age} with the same field value * from the supplied data page * @param $tplPage * @param $tplField * @param $dataPage * @param string $startTag * @param string $endTag * @param array $other * @return string|string[] * @throws WireException * @throws WirePermissionException */ private function _compileFieldTags ($tplPage, $tplField, $dataPage, $startTag = '{', $endTag = '}', $formatDate = false, $other = []) { $allowedFieldtypes = [ 'FieldtypeText', 'FieldtypeTextarea', 'FieldtypeInteger', 'FieldtypeFloat', 'FieldtypeDatetime', 'FieldtypeToggle', 'FieldtypeCheckbox', 'FieldtypePage' ]; $replacementNames = []; $replacementValues = []; // Sort out what to do with each inputfield type foreach ($dataPage->fieldgroup as $replacement) { if (!in_array($replacement->type, $allowedFieldtypes)) continue; switch ($replacement->type) { case 'FieldtypeDatetime': $fldData = $formatDate == false ? $dataPage->$replacement : $dataPage->getFormatted($replacement); break; case 'FieldtypePage': $fldData = $dataPage->$replacement->title; break; case 'FieldtypeCheckbox': $fldData = $dataPage->$replacement == true ? "Yes" : "No"; break; default: $fldData = $dataPage->$replacement; break; } $replacementNames[] = $replacement->name; $replacementValues[] = $fldData; } // Prepare replacement arrays foreach ($dataPage as $k => $v) { $replacementNames[] = $startTag . $k . $endTag; $replacementValues[] = $v; } $replacementNames['url'] = $startTag . 'url' . $endTag; $replacementValues[] = $dataPage->httpUrl; $result = str_ireplace($replacementNames, $replacementValues, $tplPage->$tplField); return $result; }
  19. Trying to upgrade TD to the latest version and I get this: Fatal Error: Uncaught WireException: No download URL specified in wire/modules/Process/ProcessModule/ProcessModule.module:1072 Happens both on the Modules->New and Settings->Upgrades with the upgrade module. I could upload the zip but that's not the issue. Reason for upgrade was another error message: Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0 which auto-magically began appearing. I'm not serializing any data and the error disappears when I turn off TD. Any ideas on what's happening here?
  20. @Knubbi that's a question for Ryan in the ProDrafts forum ?
  21. If it's only content, there's also https://modules.processwire.com/modules/version-control/
  22. @MoritzLost True, however (unless I missed something), ProDrafts doesn't work for Repeater Matrix whereas my suggestion will work for template development. As I understand it, ProDrafts is more for checking/comparing content before committing changes. I guess it's what @Knubbi is trying to do
  23. You could use site/config .php settings, eg: <?php if ($user->hasRole('dev') { // or whatever role you assign // development templates directory $config->urls->templates = $config->urls->site . 'templates-dev/'; $config->paths->templates = $config->paths->site . 'templates-dev/'; $config->urls->fieldTemplates = $config->urls->templates . 'fields/'; $config->paths->fieldTemplates = $config->paths->templates . 'fields/'; } // other users, including the public, will see the default $config->templates & $config->paths (same for fields)
  24. Some things to try as results can vary depending on the PHP version: Be more explicit in your if statement, and turning off outputting formatting: <?php if(!empty($page->myfield_text_a) && !empty($page->myfield_text_b) && !empty($page->myfield_options) && !empty($page->myfield_date)) { $page->of(false); //.... }
  25. Some things to check which tripped me up when taking over from a previous developer: In site/config.php ensure that the template url & path are pointing to YOUR templates url & path. The default is 'template' however is customisable In Set Up ->Templates -> [your template] -> Files tab, that your template file name is not being overridden in the Alternate File Name field by something the original dev entered HTH
  • Create New...