Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/04/2018 in all areas

  1. Beautiful, that did the trick. Thanks! Much better than modifying the core search module, and it won't spill over into generic find() calls in the front-end. No idea how I missed the findReady hook in the first place… Final working implementation: // Include unpublished participants in page fields for non-superusers wire()->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) { $selector = $event->arguments(0); if(strpos($selector, 'template=participant') !== false || strpos($selector, 'templates_id=76') !== false) { $selector .= ", check_access=0, include=all, status<" . Page::statusTrash; } $event->return = $selector; });
    5 points
  2. Hi all, I have posted this in the VIP support forum of Padloper as well. Some of you do not have access to that board so posting here as well. Hopefully it doesn't count as spamming?! In June 2018, Antti announced that he was looking for a new product owner for Padloper. Sometime after, I had a fruitful discussion with him about my vision for the project if I was to take over. We agreed that commitment, motivation and a concrete plan were all important ingredients for the continued success of Padloper. I would like to officially announce that I am now the product owner and lead developer of Padloper. For those who may not know, I am the author and maintainer of several ProcessWire modules, both free and commercial. I am also a moderator in the ProcessWire forums. I would like to share with you a number of things regarding what’s going to happen next. This will be a long read. First, I would like to thank Antti for developing a great product. A lot of man-hours, dedication, passion and love has gone into making Padloper what it is today. Secondly, I would like to thank all users of Padloper. A great product is nothing without active users utilising it, putting it to the test, reporting bugs (even offering possible solutions) and proposing new features. So, thank you for helping make Padloper great! Support Thousands of hours have gone into developing Padloper. Although the code is well-written and easy to follow, Padloper is a big application with many moving parts. As such, it will take some time before I can fully grasp its inner workings. To make this transition as smooth as possible, Antti will help me with support for Padloper for some time. Currently, Padloper has a dedicated support forum. This is an arrangement between Ryan and Antti. The support forum works great as it allows the opening of multiple support threads to cover different issues. I have yet to speak to Ryan whether this arrangement can continue. However, given that I have other pro modules that I support in the open forums, it is unlikely that I will be requesting Ryan to let Padloper’s dedicated forum carry forth. A dedicated forum for one of my pro modules and open forums for my other pro modules will lead to confusion and questions from users of those other modules. Hence, Padloper support in the forums will move to the open forums. The disadvantage here is obviously the fact that support will be offered in one single (and maybe massive) support thread. To get around a ‘single thread support forum’, I am thinking of developing a simple online support queue system for all my modules. Meanwhile, support will continue in a new single thread and via email. Roadmap This list is neither exhaustive nor cast in stone. Its aim is to give an overview of my plans for Padloper. · Padloper 2 – a new major release · New backend for Padloper · Optional pro frontend module for Padloper · Documentation · New payment modules Let’s talk a bit about this list. Padloper 2 Release Padloper 2 will be a major release that incorporates a new, central backend shop for Padloper. This will be a new process module that pulls from the existing parts of Padloper (data models, etc) into one interface (more on this below). This version will also be extensible in the frontend, allowing for the plugging in of a new, optional, commercial frontend shop (full featured shop profile). Padloper 2 will not support the current ‘any page can be a product’ paradigm. Technically, products will still be pages. However, all products will utilise the same Padloper template. These will be invisible to the shop users themselves (e.g., hidden in admin tree). Only superusers will have full control of the Padloper system stuff. Support The current Padloper will continue to be supported until the new Padloper 2 is released. New features will be included in Padloper 2 only. Once Padloper 2 is released, legacy Padloper will only receive security fixes. All other support will cease. Upgrade There will be no upgrade path from the current Padloper to Padloper 2. Although their underlying architecture is the same, making sure that everything works in different setups and environments will be time consuming. However, for those who really need to migrate, if time allows and for an agreed fee, I could develop a custom script for the migration. Backend A new backend interface will be the major visual difference between the existing Padloper and Padloper 2. It goes beyond visual differences though. The new backend will be the single gateway for managing all shop-related features, both current and new ones. The backend will unify and include: · Easily add shop products. · Ability to add as little or as many custom fields to products as required (title, SKU, price, discount field, image/photo, description, categories, tags, etc). · Discounts manager (including auto start/expire discount codes). · Customers manager. · Invoices manager. · Taxes management. · Payment gateways manager. · Improved digital products management. · Stock management. · Manual order creation. · Graphical sales report. · Customer support. · Access-controlled shop editors/staff. · Dashboard for shop metrics. · Shop settings. · Product variations. · Import/export products as CSV or JSON. · Products search/filter. · Etc. Users will be able to turn off backend features that they do not need. This will enable a more streamlined experience for users. I plan to release Padloper 2 within 4 - 6 months, hopefully sooner. This is a major undertaking, hence the timescale. Please note that the first release of Padloper 2 will not include all of the above planned features. The idea is to build incrementally, adding new features in minor updates, focusing on stability, usability and security. Frontend Past requests have included the development of a full featured frontend shop. This is planned for Padloper 2. However, this will be an optional pro module priced separately from Padloper itself. The ability to build own frontend shops using Padloper API will still continue. For those who want a plug-n-play solution, this frontend shop will come in handy. The frontend shop profile will feature an ajax-powered shopping cart and a customisable ready-to-go theme. Pricing Model There are no plans to change the current prices of the 3 Padloper licences (Single, Developer and Agency). However, in order to continue to provide Padloper as a stable product with great features, it is also important that it remains a competitive and financially sustainable project. In order for this to happen and to also bring Padloper in line with my existing pro modules, the pricing model itself has to change. Starting from Padloper 2, the pricing model will shift to an ‘annual subscription’ model rather than the current ‘lifetime licence model’. I am fully aware that there are different opinions for and against annual subscriptions. However, I believe that this model is the most equitable approach that suits both the developer and the clients. The annual subscription will allow users (licence holders) to get 12 months of free VIP support for Padloper as well as future updates available within that time period. After the 12 months, users will be able to renew (online) their subscription at a discounted cost (worked as a fraction of the full purchase price) for a further 12 months (perpetually). Users will be able to continue to use Padloper for life even if they don’t renew their subscriptions. Upgrading current licences to Padloper 2 will be a paid upgrade. Current users of Padloper will get an attractive discount. This will be a time-limited offer (maybe a couple of months) that will start with the release of Padloper 2. New customers will pay the full price for Padloper 2. I hope the planned features are reason enough for you to consider upgrading to Padloper 2. Payment Modules I will be taking over as the maintainer and lead developer of the existing payment gateways (Payment base class, PayPal and Stripe). New payment modules are also planned. Payment modules will continue to be free. However, only ProcessWire 3+ support will be provided going forward. Padloper Domain and Future Downloads I have also taken charge of the Padloper domain. Within the next 12 months, purchase and download of Padloper will shift to processwireshop.pw. Please note that this is not the official shop for ProcessWire! It just bears a name that reflects its product offerings ?. Eventually, traffic to padloper.pw will redirect to processwireshop.pw. Feedback I would love to hear your thoughts about the upcoming changes and any feature requests you might have for Padloper 2. Whilst I cannot guarantee that any request will be implemented, I can promise that I will thoughtfully consider all feedback. Thanks for reading and thank you for supporting Padloper! kongondo
    4 points
  3. Hooking ProcessPageSearch::findReady might be better because it's more specific to autocomplete and the method looks like it exists for just this sort of purpose. $wire->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) { $selector = $event->arguments(0); // Manipulate $selector as needed... }); /** * Hookable function to optionally modify selector before it is sent to $pages->find() * * Not applicable when Lister is handling the search/render. * * #pw-hooker * * @param string $selector Selector that will be used to find pages * @return string Must return the selector (optionally modified) * */ public function ___findReady($selector) { return $selector; }
    3 points
  4. Hey @Macrura - just wanted to let you know that I just started using this module and it's very handy. I don't have enough pages to bother with creating an import script, so copy paste is the way to go and this has made things much quicker. Thanks!
    3 points
  5. $pages->get gets only one page, try find() instead. Also, get() ignores published state which is perhaps not what you want.
    3 points
  6. My vote goes for the status quo - no need to change output formatting or have an indicator IMO. I think the best thing is to get into the habit of always turning output formatting off before setting any value to a page (I tend to do it individually for the page I'm changing rather than for all pages). I think it's simplest to follow that rule everywhere - frontend, backend, in a module, etc. It's just a single line of code, and if output formatting is already off for any reason then it doesn't do any harm to explicitly set it off to be sure. If Tracy was to get involved in output formatting I think it would add confusion, particularly for new users who are still getting to grips with output formatting.
    2 points
  7. I do want to hear from a few others, but I actually think that #3 (off in backend and on in frontend) makes most sense to me because that matches how PW itself works. I think perhaps a simple OF icon with either a red or green background somewhere on the console panel is probably a good idea as a reminder, but I don't think there should be a toggle - I think if you need to adjust the status, it should be added to the Console code.
    2 points
  8. Hey Bernhard - sorry for the hassles - hope you didn't do any long term damage to anything! As for whether this should be on or off, I am not really sure to be honest. Perhaps it should be "ON" if you're using the Console panel on the frontend and "OFF" if you're using it in the backend/admin. I don't explicitly set it on, but that is how it works by default. The problem with it being off is if you simply want to get the value of a field, it will return the raw, unformatted value: instead of: So, I guess we could take several different approaches: 1) Always ON 2) Always OFF 3) ON in frontend and OFF in backend/admin 4) Configurable as ON or OFF for both 5) Configurable separately for frontend and backend Any thoughts? What does everyone else think?
    2 points
  9. I put this in my ready.php file: // hack to overcome this: https://github.com/processwire/processwire-issues/issues/550 $this->addHookBefore('Pages::find', function(HookEvent $event) { $selector = $event->arguments(0); if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) { $selector .= ', check_access=0'; } $event->arguments(0, $selector); }); You'll need to adjust to suit the needs of your selector, but this is how I got around it and make it work for non-superusers. Sorry I forgot about this above. Definitely worth a read through that github issue as well: https://github.com/processwire/processwire-issues/issues/550
    2 points
  10. Is this an autocomplete inputfield? I just ran into the same problem (a page field not finding unpublished pages for non-superusers, even though Include unpublished is checked). I managed to isolate the issue to ProcessWire's internal admin search that is used behind the scenes of autocomplete fields. Not sure if anything from the last major search update in 3.0.108 might play a role here. This is what's worked for me: Copy the core search module folder from /wire/modules/Process/ProcessPageSearch to /site/modules/Process/ProcessPageSearch/ After lines 422–425 in ProcessPageSearch.module… if(!$status && !$hasInclude && $superuser) { // superuser only $selectors[] = "include=all, status<" . Page::statusTrash; } …insert this: // FIX: include unpublished pages for non-superusers else if(!$status && !$hasInclude && !$superuser) { $selectors[] = "include=all, status<" . Page::statusTrash; } Back in the admin, refresh the module cache (Navigation » Modules » Refresh). ProcessWire will then ask you which version to use for the search module. Pick the one you modified in the /site/ folder. This will basically make it work the same for superusers and non-superusers. I can't report any negative side effects at this point, but in my case it beats promoting all content editors to superusers.
    2 points
  11. This week flew by too fast. I did some work on the core, but mostly had to focus on some end-of-the-month client work deadlines, in ProcessWire-powered projects. As a result, I don't have enough core updates to warrant a version bump on the dev branch this week, so putting a quick update here rather than a blog post. ProcessWire 3.0.112 should be ready by this time next week. One of my clients recently requested a URL field that intermittently verifies itself—to make sure that the URL is still returning a 200 success, and not a 404 error, or some other error code. Their site has thousands of external URLs (more than they can check manually), and they want some way to avoid showing links for URLs that are no longer working. I thought a self-healing URL field sounded like a cool idea, so put a little work into that this week, and will likely finish it up next week. The module is called FieldtypeVerifiedURL and it extends the regular FieldtypeURL field, except that in its configuration you can specify how often you want it to verify that the URL is still valid. It also performs the verification whenever the value changes. It uses WireHttp to obtain and store the response code with the field, whether a 2xx (success), 3xx (redirect) or 4xx (error) code. So if you wanted to, you could filter the pages with this URL field by response code (like to find all those returning 404s for instance). It can optionally save the <title> tag found at the URL for you as well. In our case, we will be configuring it to check that URLs are valid once a week, and this is something that it will do in the background automatically. When a URL is found to be returning an error code (like a 404), the output of the field can be optionally configured to return an empty value rather than the URL (when output formatting is on). I'm not anywhere near finished with this one, but if this sounds useful to you, stay tuned for more on this soon. Have a great weekend!
    1 point
  12. There is no hookable method especially for images inserted in a CKEditor field. But two options: 1. Use/code a textformatter module to manipulate the image tags within a field. This approach has the advantage that you don't have to mess around with your field settings to make sure the classes and attributes you want to add are allowed by ACF and HTML Purifier. There is even an existing textformatter module you can use: https://modules.processwire.com/modules/textformatter-srcset/ 2. Hook the saving of pages (e.g. Pages::saveReady) and modify the markup in your CKEditor field before it is saved. The approach would be similar to the textformatter option - you parse the markup to identify the image tags (using regex or a DOM parser such as DOM) and use the src attribute to get the relevant Pageimage to create your different sizes from. The difference is that this parsing/modification is done whenever the page is saved rather whenever the field value is loaded. Option 2 is more efficient, but I would tend to go for option 1 because it's not destructive and gives greater flexibility to make changes down the line. And maybe that existing textformatter module is just what you need.
    1 point
  13. Never mind - ryan confirmed it's a bug and is fixed on latest dev.
    1 point
  14. @Beluga working on filters right now and just saw that your example could also be done with the quickfilter: https://www.ag-grid.com/javascript-grid-filter-quick/ maybe that's interesting for you?
    1 point
  15. There are several outlined in the second Issue that @Robin S linked to. It would actually be great if you could comment on that issue to get Ryan's attention once again if you wouldn't mind.
    1 point
  16. I can confirm that the latest version only supports either auto-accept mode or allow users to manage. But by now I use both options auto-accept mode and allow users to manage without any problems. I added one line to the cookie.monster.block function (jQuery version) to make it work. //set cookieMonster variables when user blocks cookieMonster.block = function() { // added to disable banner while blocking cookies in auto-accept mode cookieMonster.cfg.viewCount = -1; // cookieMonster.cfg.allowCookies = "n"; cookieMonster.cfg.selectionMade = "y"; cookieMonster.cfg.storedVersion = cookieMonster.cfg.version; cookieMonster.sendActionBeacon(); cookieMonster.updateStatus(); } I'm not sure anymore that auto-accept mode was the real deal-breaker here but that missing line. Maybe the (original) author had something in mind when he/she decided not to add that negative viewCount in the block function. In my use case I need it to get my expected behaviour while having all options (auto-accept and blocking) I want and need.
    1 point
  17. Good point. I've always used it conjunction with some light caching to store the results as JSON.
    1 point
  18. Best wishes for the new part @kongondo. It feels like a perfect fit, Padloper and you. ?
    1 point
  19. Oh... thats not good ? Is there a workaround? Is it possible that I only get the name and the Url/ID instead of the whole page`? /edit: It seems that the problem does not occur if you change the Page Reference field to "multiple pages"...
    1 point
  20. @MilenKo, If you're on OS/x I'd recommend using MAMP or MAMP Pro. I would just NOT recommend AMPPS at this stage, for any platform going on my personal experience. I'm not familiar with High Sierra, but not being able to run DevilBox with elevated privileges could be an issue. That certainly was the case in Ubuntu.
    1 point
  21. For most group-by-property situations, I use Fun with hooks: PageArray::groupBy.
    1 point
  22. Thanks @bernhard! I've noticed you've been building some awesome modules lately ?. Unfortunately I've not had the time to take them for a spin yet. I'll keep this suggestion in mind. Cheers.
    1 point
  23. Hi kongondo, also best wishes from my side! Have you ever tried RockGrid? I think you should! It's great for building all kinds of custom backend listings. Just drop me a line if you have any questions.
    1 point
  24. Probably safer with paths() so you get the full disk path paths()->templates
    1 point
  25. Adding to that, if you are using the Functions API, you could also use urls(). ? urls()->templates . "src/components/filename.php"; Or if you don't need to require you could try out wireIncludeFile. wireIncludeFile("./src/components/filename");
    1 point
  26. @ryan Another thought - I quite like using @wumbo's FieldtypeAssistedURL (https://processwire.com/talk/topic/10530-module-fieldtypeassistedurl/) - or more accurately, my fork of it: https://github.com/adrianbj/processwire-fieldtype-assisted-url/commits/master which adds support for storing local pages as ID, not URL. I would hate to have to choose between your new URL field as this one. I wonder if you'd consider adding the functionality of the assisted url field to your new one?
    1 point
  27. I would have multiple uses for this type of URL field for sure! At the moment I use @teppo's unreleased ProcessLinkChecker, which is awesome. I think the key thing would be that in addition to returning an empty value I think it also needs a way to log and also report (maybe via email or other options) broken links so that we don't need to monitor its findings.
    1 point
  28. It's easy using RockFinder. See the example in the docs: https://gitlab.com/baumrock/RockFinder#custom-sql-aggregations-groupings-distincts
    1 point
  29. hey @mel47 and @dragan please try the latest version (v1.0.8)
    1 point
  30. thanks @mel47 that is a bug! I'll fix it as soon as possible. then also your problem @dragan should be gone ?
    1 point
  31. This happens when you have a grid that tries to show more rows, then adds scrollbars and therefore does not have enough space to show those rows and removes one. Then it tries the same thing again. You can set your grid to a fixed amount of rows. The number of rows in your case do not change. It's only the number of pages that changes (and that's correct of course, if you add/remove one row you'll end up with different page numbers). This can happen if you have page fields or repeaters with multiple items. The RockFinder might return those values as joined results with each referenced value in a separate row. Analyze your SQL or your RockFinder and the result itself to see where this comes from. You can comment out some fields of the RockFinder then you see which field causes the number of results to increase to more than you'd expect. You can either create a different SQL (see the RockFinder docs, or - sorry - look into the code). Another way to prevent such situations is to create a new hidden field that gets populated via saveReady hook and holds the information you need. Eg you create a field "linked_pages" that holds an array of linked pages, eg [{id:123,title:"demo page1"},{id:456,title:"demo page2"}] You can then use a cellRenderer to show this information as you want (eg with icons, as comma separated list, as number of linked pages etc.). It might sound complex but it totally makes sense when you build more advanced grids. Having said that, that's how it works right now. It's not perfect for sure. If you have any suggestions for improvement let me know. In that case just setup a valueGetter and make sure you return a proper value for all cells. This is how you make sure it is a number (for calculating sums/avg etc): document.addEventListener('RockGridItemBeforeInit', function(e) { if(e.target.id != 'RockGridItem_rockgrid') return; var grid = RockGrid.getGrid(e.target.id); var col = grid.getColDef('yourcolumn'); col.valueGetter = function(params) { if(typeof params.data == 'undefined') return; var val = params.data[colDef.field]; return val*1; // make sure the value is a number and not a string } }); Of course you can hide it: https://www.ag-grid.com/javascript-grid-column-definitions/ document.addEventListener('RockGridItemBeforeInit', function(e) { if(e.target.id != 'RockGridItem_rockgrid') return; var grid = RockGrid.getGrid(e.target.id); var col = grid.getColDef('id'); col.hide = true; var col = grid.getColDef('title'); col.headerName = 'MyDemoTitle'; });
    1 point
  32. I should have just used my brain. Luckily I am not prone to alcoholism, so this public embarrassment will not lead to pathological results. Anyway, let's pretend nothing happened last week and move on to the next topic. I noticed the ag-Grid demo has a cool filter, which allows us to use multiple strings. However, when used with RockGrid/PW, it breaks, if the field values include null ones. Long story short, I figured the most inexpensive change perf-wise would be telling PDO to treat nulls as strings. I did the change in RockFinder. Perhaps it would be unwise to include in upstream as some users would expect nulls to stay nulls. The change in RockFinder.module.php: public function getObjects($array = null) { $timer = $this->timer('getObjects'); try { $this->database->setAttribute(\PDO::ATTR_ORACLE_NULLS, \PDO::NULL_TO_STRING); $results = $this->database->query($this->getSql()); $objects = $results->fetchAll($array ? \PDO::FETCH_ASSOC : \PDO::FETCH_OBJ); } In RockGrid code, there is also a possibility to use sql query as datasource, but I don't see it in the interface. Anyway, in case one would need to use it somehow: InputfieldRockGrid.module.php: // sql query as datasource $this->database->setAttribute(\PDO::ATTR_ORACLE_NULLS, \PDO::NULL_TO_STRING); $results = $this->database->query($sql); return $results->fetchAll(\PDO::FETCH_OBJ); Edit: later I noticed that dealing with the nulls in JS does not seem to affect perf even with a big data set, so I modified the filter example below to just do if (value === null) value = ''; Using the filter from ag-Grid demo in your .js: document.addEventListener('RockGridItemBeforeInit', function(e) { if(e.target.id != 'RockGridItem_rockgrid') return; var grid = RockGrid.getGrid(e.target.id); var col = grid.getColDef('myfield'); col.headerName = grid.js.myfield; col.filter = PersonFilter; col.floatingFilterComponent = PersonFloatingFilterComponent; }); document.addEventListener('RockGridItemAfterInit', function(e) { if(e.target.id != 'RockGridItem_rockgrid') return; var col; var colDef; var grid = RockGrid.getGrid(e.target.id); }); function PersonFilter() { } PersonFilter.prototype.init = function (params) { this.valueGetter = params.valueGetter; this.filterText = null; this.params = params; this.setupGui(); }; // not called by ag-Grid, just for us to help setup PersonFilter.prototype.setupGui = function () { this.gui = document.createElement('div'); this.gui.innerHTML = '<div style="padding: 4px;">' + '<div><input style="margin: 4px 0px 4px 0px;" type="text" id="filterText" placeholder="Multi-string search..."/></div>' + '</div>'; var that = this; this.onFilterChanged = function () { that.extractFilterText(); that.params.filterChangedCallback(); }; this.eFilterText = this.gui.querySelector('#filterText'); this.eFilterText.addEventListener("input", this.onFilterChanged); }; PersonFilter.prototype.extractFilterText = function () { this.filterText = this.eFilterText.value; }; PersonFilter.prototype.getGui = function () { return this.gui; }; PersonFilter.prototype.doesFilterPass = function (params) { // make sure each word passes separately, ie search for firstname, lastname var passed = true; var valueGetter = this.valueGetter; this.filterText.toLowerCase().split(" ").forEach(function (filterWord) { var value = valueGetter(params); if (value === null) value = ''; if (value.toString().toLowerCase().indexOf(filterWord) < 0) { passed = false; } }); return passed; }; PersonFilter.prototype.isFilterActive = function () { var isActive = this.filterText !== null && this.filterText !== undefined && this.filterText !== ''; return isActive; }; PersonFilter.prototype.getModelAsString = function (model) { return model ? model : ''; }; PersonFilter.prototype.getModel = function () { return this.eFilterText.value; }; // lazy, the example doesn't use setModel() PersonFilter.prototype.setModel = function (model) { this.eFilterText.value = model; this.extractFilterText(); }; PersonFilter.prototype.destroy = function () { this.eFilterText.removeEventListener("input", this.onFilterChanged); }; function PersonFloatingFilterComponent() { } PersonFloatingFilterComponent.prototype.init = function (params) { this.params = params; this.eGui = document.createElement('input'); var eGui = this.eGui; this.changeEventListener = function () { params.onFloatingFilterChanged(eGui.value); }; this.eGui.addEventListener('input', this.changeEventListener); }; PersonFloatingFilterComponent.prototype.getGui = function () { return this.eGui; }; PersonFloatingFilterComponent.prototype.onParentModelChanged = function (model) { // add in child, one for each flat if (model) { this.eGui.value = model; } else { this.eGui.value = ''; } }; PersonFloatingFilterComponent.prototype.destroy = function () { this.eGui.removeEventListener('input', this.changeEventListener); };
    1 point
  33. Don't you use Tracy Debugger? You could have easily done a bd($page->rockgrid) or d($page->rockgrid) and should have seen and been able to debug it quickly. PS: Even if you lost 15 hours - the module took many many more to develop so you are still saving loads of hours ?
    1 point
  34. Hi guys! What do you think about something like this? Because I use this option regularly in the Windows File Explorer breadcrumb and it's very useful. The drop-down menu can display only published/visible child pages. I've tried to find how to do it as a module, but I'm not a coder with enough skills for that ... or I don't know if I can use hooks to do that ...
    1 point
  35. Thanks @BitPoet! I think there might be some typos in the mutator example - maybe you meant: $blogposts = $pages->find("template=blog-post, sort=created"); $grouped = $blogposts->groupBy(function($pg) { return array(strftime('%Y', $pg->created), strftime('%m', $pg->created)); });
    1 point
  36. I think you need to set output formatting false before you start setting values to fields: $payment = $pages->get('template=payment,id='.$payment_id); $payment->of(false); if($payment->id) $payment->payment_status = P_PAID; $payment->save();
    1 point
  37. Hopefully their own content and not simply taken from others
    1 point
  38. I haven't really read all of this thread, but just wanted to chime in with a brief overview of a help desk system I built. I can only show you screen shots from the test server — since the real one has sensitive data — but I think you get the idea. Unfortunately it's all pretty specific to our environment here, and was never intended to be released. Ticket List This is pretty small in the test environment. The lighting bolt icons open a modal that shows some "quick look" information for admins. Last comment, ticket history, etc... It's just a way to quickly peek into a ticket without opening it. Ticket View Many of these test tickets are filled with a ton of content, but here's one that shows some of the features. It's conversation based. You can attach specific equipment (we have several equipment databases managed in other PW modules). You can add files/images to any reply. Typical help desk stuff really. Reply options This is at the bottom of the discussion, a lot like it is here in the discussion forum. Agents can reply or create an internal note.
    1 point
  39. As a workaround, it’s possible to set Minimum Value to 0.1, since the field is actually an InputfieldFloat. This will allow values of 0 but no negative ones. Edit: as a matter of fact, changing the modules used for Min and Max in InputfieldInteger.module to InputfieldInteger (seems sensible anyway?), makes it work as desired, as far as I can tell. 0 values don’t disappear when set and the validation within templates works fine as well. Maybe this change is all that’s necessary?
    1 point
×
×
  • Create New...