Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 05/15/2020 in all areas

  1. This week I was back to focusing on the core and got quite a lot done. A lot of GitHub issue reports were resolved, plus several minor tweaks and additions were made in 3.0.156 as well. But the biggest update was the addition of the $pages->parents() API, which is something that I think you’ll likely have zero use for (and why I’m not putting it into a blog post) but something that the core itself will use quite a bit, and is a really nice improvement for the system and its scalability. So if you don’t mind some technical reading, read on. Whenever you call a $page->find() method ($page, not $pages) or use a “has_parent=“ in a selector, ProcessWire joins in a special table for the purpose called pages_parents. It uses this table to keep track of family relationships that aren’t otherwise apparent. For instance, let’s say we have page “g” that lives at path /a/b/c/d/e/f/g/. Page “g” only knows that it has page “f” as its parent. It doesn’t know that page “e” is its grandparent unless or until page “f” is loaded. Once “f” is loaded, then “f” can reveal its parent “e”. It works the same for every relationship down to the root parent “a”. So the pages are like a linked list or blockchain of sorts, where only 1 relationship forward or backward is known per page. The “pages_parents” table fills in this gap, enabling PW to quickly identify these relationships without having to load all the pages in the family. This is particularly useful in performing find() operations that you want to limit to a branch started by a particular parent. It’s the reason why we have both $pages->find() that searches the entire site, and $page->find() that limits the search within the branch started by $page. I haven’t paid much attention to the code behind this pages_parents table because it generally just worked, needing little attention. But I came across a couple of cases where the data in the table wasn’t fully accurate with the page tree, without a clear reason why. Then I became aware of one large scale case from a PW user where it was a huge bottleneck. It involved a large site (250k+ pages) and a recursive clone operation that appeared to involve hundreds of pages. But that operation was taking an unreasonable 10 minutes, so something wasn’t right. It came down to something going on with the pages_parents table. Once I dove into trying to figure out what was going on, I realized that if I was to have any chance of keeping track of it, we needed a dedicated API for managing these relationships and the table that keeps track of them. So that’s what got a lot of attention this week. While still testing here, it does appear initially that the 10 minute clone time has gone down to a few seconds, and everything about this relationship management is now rewritten, optimized and significantly improved. It was a lot of work, but absolutely worth it for PW. Rebuilding the entire table from scratch now takes between 2-3 seconds on a site with 250k pages and 150k relationships. The new API can be accessed from $pages->parents(). This API is really useful to the work that I do here (maintaining the core) but I’ll be honest, it’s probably not useful to most others, so I won’t go into the details here, other than to say I’m happy with it. But if you are interested, there are methods finding all the parents in a site, or a particular branch, and methods for rebuilding the pages_parents table, among others. Maybe more will be added to it later that actually would be useful in the public API, but for now I’ll likely leave it out of our public API docs. The $sanitizer->selectorValue() method also got a full rewrite this week (actually, one the last few weeks). It’s now quite a bit more comprehensive and configurable (see the new method options). The previous version was just fine, and actually still remains — you can use it by specifying [ ‘version’ => 1 ] in the $options argument to the selectorValue() method. But the new version is coded better and covers more edge cases, plus provides a lot more configurability for the times when you need it.
    8 points
  2. I have added a new field type to the FieldtypeColor package. It is still in beta, but is already working quite well. The module is an extension of the Core FieldtypeOptions module and offers colors as predefined selectable options via 4 different input field types (Select, SelectMultiple, Checkboxes and Radios). Please try it out and if you like it, recommend it in the modules directory ? 2 Screenshots
    6 points
  3. You need to enclose the api vars with curly brackets if there is more than one arrow in it. echo "<img src='$front_img_800->url'>"; // good echo "<h2>$item->front_productpage->title</h2>"; // bad echo "<h2>{$item->front_productpage->title}</h2>"; // good Read more: https://processwire.com/talk/topic/4439-when-do-we-need-curly-brackets/ https://www.php.net/manual/de/language.types.string.php#language.types.string.parsing.complex
    4 points
  4. We recently relaunched the website of IBIS Backwaren, a brand for international pastries and bakery products. Concept, design and implementation by schwarzdesign, built with ProcessWire. As always, we aimed to deliver a clean website design with a focus on content and fast loading times. Here's a list of modules used on this site, followed by a couple of interesting features included. The site is bilingual, though currently only the German version is available. The English version will be released at a later date. ProFields FormBuilder WireMailSMTP Cache Control MarkupSitemap Hanna Code Automatically link page titles Unique image variations Product database and product collections The website features a product database with all the products IBIS distributes. The product template is rather extensive, including fields for product categories and attributes, nutrition facts, certifications etc. We make heavy use of page reference fields, e.g. for product categories and attributes such as vegan or gluten-free products. Nutrition facts are stored in a Textareas field. There are multiple ways for visitors to explore products. One is a classic product finder with filters for product category and attributes. But there are also individual product collections (Produktwelten) which can be regularly updated by the client. Product collections include a list of related products. This allows the marketing department to quickly set up targeted landing pages. Recipes and custom forms Another approach to marketing and activating fans is the recipe section. Each recipe uses at least one IBIS product to give visitors some ideas. Of course, recipes and products are cross-linked to allow for exploration and discovery. There's a recipe submission form which allows you visitors to send in their own recipes, as well as a couple of other forms. All forms on the site are built with the Form Builder module. We made use of the form submissions to pages feature, which automatically creates a new (unpublished) page for new recipe submissions. Those can be reviewed by the staff and published directly. We also use a hook to automatically transform the plaintext fields for ingredients and instructions into HTML lists. Multi-brand IBIS uses different brands for different sets of products. Some landing pages as well as the gluten-free selection are branded differently. To accomodate this, we create an additional "brand" template with an override for the default logo. Each page has a brand selection field to allow switching the logo / branding for that page. Since brands are represented by normal pages, then client can create additional brands on their own.
    3 points
  5. Yes, perfect use case for it! RockGrid still works, but I'll not develop it further. I switched to tabulator.info some time ago, because ag-grid (used by RockGrid) is not fully open source and quite expensive if you need excel-export for example. I have to note that I want to rebuild RockTabulator soon, but not sure when I can manage to do that. If anybody has a project that could benefit from such listings and would be willing to outsource the work and sponsor the development of a new (and well documented) RockTabulator write me a message ? PS: If you want to keep things simple, you could even use your own implementation of tabulator.info or ag-grid. RockFinder2 will do the "hard" work of getting the data and you can simply display that data in a nice way with those js libraries. If you don't need any editing stuff, this should be really quick and easy!
    2 points
  6. Maybe give RockGrid and RockFinder2 a try? I'll tag @bernhard, the author to chime in if you need more info.
    2 points
  7. You're using OR-groups, which means only one of the selectors in parentheses needs to match. This means if standort_reference or standort_alle match for a page, the other selectors don't matter. If you remove the parentheses around the selectors for standort_reference and standort_alle, the selector should work as intended. Alternatively, use named OR-groups if you want to use multiple groups of alternative selectors in your query: https://processwire.com/docs/selectors/#or-groups
    2 points
  8. "Markup Regions pw vs data-pw different behavior" I have not yet experienced such a behavior. Maybe you are mixing up "Boolean action attributes (inner HTML)" with "Action attributes with value (outer HTML)"? Regarding the differences between these two, see my explanation below. +1 Here is my simplified docs for markup regions, we can also call it "cheat sheet". I wrote it some time ago: Defining markup regions Basic region Wrapping tags do appear in the final markup. Children tags are preserved if not explicitly replaced. <div id="hello"> OR <div data-pw-id="hello"> data-pw-... They are removed from the final output and thus not visible to front-end markup, while id="..." is not removed! Placeholder region Only the inner HTML will be used and the wrapping tags won't appear in the final markup. <pw-region id="hello">...</pw-region> Good for groupping tags in the <head> eg.: <pw-region id="site_scripts"> Optional region It will be automatically removed from the document markup if nothing populates it, so it is a region which should be empty by default. <div id='hello' data-pw-optional></div> Examples: an <ul>, which [according to HTML5 specs] is required to have one or more <li> elements within it, otherwise it's invalid HTML. a sidebar which is only needed on pages populated with widgets /* -------------------------------------------------------------------------------------------------- */ Populating markup regions Available action attributes: data-pw-replace: replaces a region’s markup data-pw-append: appends markup to a region data-pw-prepend: prepends markup to a region data-pw-before: inserts markup before a region data-pw-after: inserts markup after a region Boolean action attributes (inner HTML) Only applies the inner HTML to the region. TARGET CODE: <div id='hello'> <h2> Hello World </h2> </div> <p data-pw-id="hello" data-pw-append> This text will APPEND to div#hello </p> <p data-pw-id="hello" data-pw-prepend> This text will PREPEND to div#hello </p> <p data-pw-id="hello" data-pw-before> This will insert this text BEFORE div#hello </p> <p data-pw-id="hello" data-pw-after> This will insert this text AFTER div#hello. </p> RESULTS: This will insert this text BEFORE div#hello <div id='hello'> This text will PREPEND to div#hello <h2> Hello World </h2> This text will APPEND to div#hello </div> This will insert this text AFTER div#hello Action attributes with value (outer HTML) All of the markup that you specify (the outer HTML) becomes part of the final document markup (except for the pw-* attributes): TARGET CODE: <div id='hello'> <h2> Hello World </h2> </div> <p data-pw-append="hello"> This paragraph will APPEND to div#hello </p> <p data-pw-prepend="hello"> This paragraph will PREPEND to div#hello </p> <p data-pw-before="hello"> This will insert this paragraph BEFORE div#hello </p> <p data-pw-after="hello" class="world"> This will insert this paragraph with class "world" AFTER div#hello. </p> RESULTS: <p> This will insert this paragraph BEFORE div#hello </p> <div id='hello'> <p> This paragraph will PREPEND to div#hello </p> <h2> Hello World </h2> <p> This paragraph will APPEND to div#hello </p> </div> <p class="world"> This will insert this paragraph with class "world" AFTER div#hello. </p> /* ------------------------------------------------ ------------------------------------------------ */ Adding HTML attributes Any HTML attribute you add to the action tag that does not begin with pw- or data-pw- will be added to the originally defined region tag. TARGET CODE: <ul id="foo" class="bar"> <li> First item </li> </ul> ACTION CODE: <ul data-pw-append="foo" title="Hello"> <li> Second item </li> </ul> RESULTS: <ul id="foo" class="bar" title="Hello"> <li> First item </li> <li> Second item </li> </ul> Adding and removing classes Classes from the action tag and the region tag are merged by default. To remove a class by the region action: prepend a minus sign to the class to be removed, eg: class="-foo bar" will result in class="bar"
    2 points
  9. Site looks nice, BUT: "Should I use a carousel?"
    2 points
  10. Done too. I also added: PRO – Easy to maintain, no need to update the system frequently. The only driving force to update a ProcessWire system is the end-of-life policy of PHP. Because of the lack of security issues, updates are not required but can be performed easily if one wants to add new features. And to be fair, I also added this (since the list we are dealing with has systems like that): CON – This CMS is not for those who just want to download a frontend theme. ProcessWire has no concept of frontend themes like other CMSes have. Instead, you can customize some free frontends if you have basic HTML/CSS/PHP knowledge or hire a developer to implement a complete custom frontend according to your own needs. Another option is to learn the basics of web development and you can implement your own frontend easily because that is one of the main strengths of the system: makes it easy to get into complex web development if you have the time to learn.
    2 points
  11. Hi @Jorge, welcome to the forums. As Kongondo already said, you can or need to use a hook to inject your desired functionality. You can use one in the site/ready.php like this: $wire->addHookAfter('Pages::saved', null, function(HookEvent $event) { $page = $event->arguments(0); // now, after you have the page related to the hook event, check if it belongs to the pages / templates you want to process if('my-desired-templatename' != $page->template->name) return; if(!$page->mycheckbox_use_github) return; // after you definetly know that you want to process this page, execute what you want to ... }); Maybe a little OT, but also maybe useful for inspiration:
    1 point
  12. @ttttim I have added new Fieldtype Select Color Options to FieldtypeColor package. Read more here: Furthermore, as @elabx already mentioned, if you use Spectrum Color Picker as Inputfield in FieldtypeColor it is also possible to configure it to a select with predefined options: https://bgrins.github.io/spectrum/#options-togglePaletteOnly
    1 point
  13. @kixe, Thank you for pointing me in the right direction. As a PW newbie the PHP resource is exactly I was looking for. PW's Page Reference is so beautiful implemented. Now I can easily select any internal page in a repeater item. Front images show up just fine with a headline and linked to the corresponding internal page. Perfect. Thanks! echo "<a href='{$item->front_productpage->url}'><img src='{$front_img_800->url}'></a>"; echo "<h2><a href='{$item->front_productpage->url}'>{$item->front_productpage->title}</a></h2>";
    1 point
  14. Yes, that looks good! In both of the named groups, at least one of the selectors has to match for the entire group to match, like you wanted.
    1 point
  15. I don't understand this part. Doesn't that mean you could replace the lister bookmarks by a process module showing a RockTabulator and this RockTabulator would show data based on the 2 get-parameters? eg /your-admin/financials/?income=2015&cash=2018 This would mean unlimited number of RockTabulators with just one process module instead of one lister per income/cash combination?
    1 point
  16. Thanks for the cheat sheet, @szabesz. And you're code is great inspiration @Pixrael. Here's my code, @elabx, or parts of it. This is the code that gives me correct output. _main.php <?php namespace ProcessWire; ?> <!doctype html> … template stuff <footer pw-id=footer> … more template stuff </footer> </body> </html> some-page-template.php, the relevant code at the bottom: <?php namespace ProcessWire; ?> … template stuff <?php echo "<script data-pw-append=footer src=\"" . $config->urls->templates . "theme/js/showmore.min.js\"></script>"; echo "<script data-pw-append=footer type=\"application/ld+json\">" . json_encode($schema_review) . "</script>"; ?> But if I edit the last part, to <script pw-append=footer… instead of data-pw-append, it will output the scripts before <!doctype html>. That is what I don't get. Reading about the two variations being similar in usage.
    1 point
  17. Much appreciated - I'll admit to not knowing too much about these options yet, so great to get some more knowledgeable input. Thanks!
    1 point
  18. Thank you. Yeah, that's what I did now, as I do understand the "named groups" now correctly... my code looks finally now: if ($standort == '') { $termine = $page->children("sort=date, limit=10, date=(date>=today, enddate=''), date=(enddate>=today)"); } else { $termine = $page->children("standort=(standort_reference~=$standort), standort=(standort_alle=1), date=(date>=today, enddate=''), date=(date!='', enddate>=today), sort=date, limit=10"); } So I grouped by 2x date() and 2x by standort(). Is that correct coded now? Just to know, that I did understand it right.
    1 point
  19. I think I got it... It works now by the following: $termine = $page->children("standort=(standort_reference~=$standort), standort=(standort_alle=1), date=(date>=today, enddate=''), date=(date!='', enddate>=today), sort=date, limit=10"); At least It looks like the output is correct!?
    1 point
  20. Great! This is where I make noise about Flutter. Would be nice to hear you talk about your experiences there ?
    1 point
  21. The main page has three carousels, which are autoplaying to make it worse and one of them you can even interact with. The big image section at the top of the page The quotes section below it (can't interact) The collections section Related quote as I was just researching a different topic (SVGs): I think the main source of confusion and why people do not interact with carousels much is the typical "meatball" navigation, which is not intuitive. I am planning to implement a non-autoplaying carousel for a site and I will probably replace the mystery meatballs simply with descriptive text elements so you know what will happen on click. @cb2004 I put some trust into professional UX research groups as I do not have the resources to conduct this science myself.
    1 point
  22. @LuisM wow great breakdown! thanks for all this info!
    1 point
  23. And the next piece of information... Have you ever asked yourself on mondays, what should I do now with my project? Could I start with $method1 or would I like to do $method2? The right answer is, none of them! PLAN YOUR TIME AND TASKS! So far we have learned about basic conceptional work, estimation matrix and components/sub-components. The next logical step would be to use this knowledge and start to manage ourself. Lets say we have 183 Tasks as a result from all our work we have done upfront. Great. We also know how long each and every task would possible take. Better. We can now use a method called TimeBoxing. If you are familiar with Scrum you probably know about sprints. Which is nothing else than a timebox. I dont want to dig deep into the Scrum Framework. So lets take this method and use it for ourself. The typical dev timebox in my teams runs for 2 Weeks. So on mondays we plan what we want to achieve in the next 2 weeks. How can I timebox myself? Lets assume you work 40h a week, for a 2-week timebox we have 80h pure worktime. Typically you dont work 8h straight on your tasks. Maybe your phone rings, you have to answer some emails or you help a colleague. We assume a "task efficency" of 80%. So 80% of our time could be put straight into tasks. Which means 80h * 0.8eff = 64h of effective Worktime for our project in a 2-week timebox. Lets have a look at our tasks now. There are 183 Tasks in our "Backlog". Wow thats a lot. Lets start to prioritize them. What is essential for our project and so on. Once done, great. But there are still 183 Tasks?! You remember our estimation we did? Create a new Backlog for the next 2 Weeks. This could be a Excel file or what ever. Take all your prioritized tasks which fit into your 64h. Congratulations you have now planned your very first timebox. Your timebox should now include so much work to keep you busy for the next 2 Weeks. The core concept of project management is to break complex systems into smaller much more easier and understandable fragments. Therefor, see yourself as a project which has to be managed ? An example Project Backlog and Timebox Backlog down below. Left is the timebox, right is the project
    1 point
  24. To elaborate a lil bit more on this topic ? yeah yeah yeah I know I know. Project Management sucks and we have a self-organized team yada yada... Could be but...who is the person communicating with clients and stakeholders? This should be the project lead. Therefor you should always have a good understanding about project progress. Lets asume you are not a freelancer and have to manage a dedicated developer team or ui team or whatever. Try to have a minimum viable project (MVP) defined and refined. What does this mean? You have carefully planned and refined a piece of software which is able to provide the basic feature set to satisfy the End-Users needs. In case of an eCommerce project this could be a piece of software with the following set of methods a cart a product page the possibility to create a product the possibility to put a product into the cart the possibility to order the items in your cart We try to cut out every single thing which is not needed to have a running eCommerce system. Things like newsletters, categories, payment methods via modules etc etc. Why should I do this you may ask, well we are humans and we have simple minds. The greater and more complex a problem is, the more problems we have to understand the system. Next comes an refinement. Tackle each component and identify sub-components. Something like this CART Order button -> createOrder() Remove Product -> removeItemFromCart() List my Products -> getCartItems() Every bits and pieces we need to develop a basic version of our Cart. Next should be an estimation meeting. What do we think each component of our MVP would take to be completed? Depending how granular you have been in your refinement you could come up with something like this (estimation in hours, you could use days, story points, apples, eggs what ever) CART Order button - 4h Remove Product -> 2h List my Products -> 2h Total: 8h Do this for every single component! You, your team and your client now know what it takes to create V1.0. But be carefull, v1.0 doenst necessary mean you have a shippable product. We just try to cut out complexity ? Once done with every component create an estimation matrix, example below. The power of project management starts to unfold ? You can start to create tasks based on your refinement and estimation and furthermore you can prioritize. You have to discipline yourself to do all this work, I know. It could be a bit tedious and boring, but once implemented you have the knowledge and the insights about project progress AND your project is well planned, well tought and manageable.
    1 point
  25. Hi huseyin, just to put things into the right perspective. I studied design with an emphasis on concepting digital media and I am a certified scrum product owner. My projects are in the range of 100 - 500 dev days with usually 5 - 10 project members and a variety of stakeholders on top. Usually I start with a blank piece of paper writing down my ideas, thoughts, possible workflows etc. call it a typical mindmap. This should give me a brief understanding of the problem we try to solve. From this first rough idea I iterate into several pieces our project may need, something trivial like a login or newsletter register. The output of the second phase usually are all needed views and workflows we try to tackle. This could but doesnt have to include wireframes. Lets call it the refined product/project concept. Depending on the team, client and project we involve UI/UX for information architecture and design or use an existing Frontend Framework. But, not involving UI/UX doesnt mean we dont need a rough Design Wireframe. It is in yours, your developers and your clients best interest to atleast provide rough wireframes of every single view. At this point we should have the following documents project mindmap Initial concept with workflows wireframes for every view What could help to understand your project/product better is to create a product canvas. I attached 2 examples below. I highly recommend to try this method out. It helps to communicate, share and maintain a general overview of your project troughout the whole team including your client. Next we start to refine the concept into a technical concept, which means my developers have to provide an architecture blueprint. What servers are needed? How do they communicate? etc... What we also need is a planned database, how do our models look like? How are they organized? What services do we need? You get the point. This looks like a lot of work and it is. Usually 30-40% of our billable time is from concepting. If your client says a conecpt isnt needed, he knows what he wants. Believe me, he dont and he needs. Do yourself a flavor and plan your projects èn detail before touching your IDE. It will save you a lot in the longrun. [edit] You asked about tools, we use the following JIRA Confluence Slack good ol Excel If you need any help I would be happy to anyswer your questions.
    1 point
  26. On PW 3.0.92 on my production server with Maria DB 10.2.12 I get the following error when trying to save a page with the fieldtype, even though all the fields have been filled out. Error saving field "businessHours" - SQLSTATE[HY000]: General error: 1364 Field 'data' doesn't have a default value On my WAMP setup with mySQL 5.7.14 it does work. I managed to create a workaround by manually editing the table design in phpMyAdmin and setting a default value for the data field to 0.
    1 point
  27. Depending on how complex your needs are, the core does offer some support. Use something like this for the selector value for a page field: parent=page.otherpagefield That allows for ajax population of one select based on the selected value of the otherpagefield
    1 point
  28. I'll make sure that nobody is working on the content for that time (for example disabling login for editors). And I exclude tables which contain dynamic content, for example incoming contact requests ( ignore_tables = ['field_scf_email', 'field_scf_fullname', ... ]; ). But I know this doesn't handle all cases...
    1 point
  29. I like the idea. I have been looking for proper way to version control PW sites recently, and have not ended with a clear decision for myself. Of course "it depends on a project". But we can come up with a tutorial helping make the choices. What to version in git I never tried initialising a git repo in templates folder, as Ryan suggested here. Custom modules and now site/ready.php should go to version control, as well as config.php. For me the choiсe is either to version the whole installation or only the /site folder. As I usually modify the .htaccess I am leaning to the former. The next thing is what to ignore. Some think you should ignore /wire, some think it is worth having it in the repo. If we could (I mean If I knew how to) install the needed version of PW core as a dependency via composer or include it in a similar way automatically after deployment / git checkout, it would be better to leave /wire off. But for simplicity it could be better not to exclude it as it is quite small. That definately should be excluded is some part of site/assets. If the site is a big one, excluding site/assets/files is a must. But for a small near to static it is probably worthless. You should probably ignore these almost every time not to mess with constantly changing data: site/assets/cache site/assets/sessions site/assets/logs I found no reason not to include all modules to the VCS. Deployment Speaking about deployment, I do not like the idea to deploy every time I commit (which seems to be the case if using git-hooks, if I am getting it right). There are other ways for deployment with git, but I an intrigued by doing it with something like this or this (both are capistrano-like deployment tools in php). Anyway, I do not seem to find a way to easily deploy database changes. Maybe in the case of semi-static sites it is possible to dump a database and restore in with git-hooks (or to include a sql dump from sites/assets/backup/database to the revision and manually restore it), but it probably will never work with subscription sites and rich-content sites managed by clients. The only way to keep track of changes made to the database via PW GUI (admin) I came up with is keeping a journal. I made a folder where I include subfolders related to git commits with JSON export files for fields, templates and forms, which should be imported. Pages are just described in .txt as I know of no way to export them to something like JSON. It would be awesome to have something like the things discussed here available not to do it manually. Hope it is somehow useful. I would be delighted to hear how others do it, as I am certainly only an amateur in all this stuff.
    1 point
×
×
  • Create New...