Leaderboard
Popular Content
Showing content with the highest reputation on 09/21/2017 in all areas
-
Based on this forum post, I wanted to find a more elegant solution for changing a field's settings per template. Hooking the page editor after it generates the form works and may still be needed for more complex modifications. But using field & template context, it's easier to modify the field settings and it greatly reduces the need for creating an almost identical field just to adjust a few things. In my blog post, I've written on how to extend contextual options to allow any fieldtype / inputfield settings to be changed depending on the template. Hope you find it useful, and if you have any questions or comments, feel free to post them here. https://abdus.co/blog/doing-more-with-fewer-fields-in-processwire/11 points
-
I am actually wondering if you might be better off not relying on ajax calls for each filter step. Have you considered storing all the details of all trees in a wireCache'd JSON object that you load up when the page originally loads and then filter through that in memory? I have done this before - I have 3MB of data in JSON which is cached, I make sure that data is transferred compressed (so it's only a couple of hundred KBs). The initially page load takes a couple of seconds, but after that, the filtering is instant. I think so long as you know that the data will not expand to an outrageous size, this might be a good approach. PS - Great looking site!5 points
-
i totally agree. i don't think it's necessary, but i think it would be nice to have a warning on the login site. a simple noscript tag could make things clear and save us from support-requests like "hey, my admin tree does not show up" where one's first thought could be a permission problem or the like...4 points
-
another example how versatile and extendable this module is: you can write your own plugins to show custom column statistics. here i'm showing max, average and minimum values of some collected feedbacks. X means no answer and is excluded from the stats: plugincode is quite simple once you know the basics of datatables api: $(document).on('update.rdt', 'div.colstats, div.colstatsselected', function(e, table, col) { var $div = $(e.target); var $table = $(table); var table = $table.DataTable(); // get table settings var id = $table.attr('id').replace('RockDatatable_',''); var dt = ProcessWire.config.RockDatatables[id]; var colname = dt.columnNames[col.index()]; var selector = {search: 'applied'}; if($div.hasClass('colstatsselected')) selector.selected = true; // get data var data = table .rows(selector) .data() .filter(function(row) { // return true if it is a number // don't count empty cells or "noanswer" cells that have an X return row[colname]*1; }) .pluck(colname); // get sum + rows var sum = data.sum(); var rows = data.length; // early exit? if(!sum || !rows) { $div.html(''); return; } // add stats for each column var avg = sum / rows; $div.html( ' ↑ ' + Math.max.apply(null, data) + ' ø ' + avg.toFixed(2) + ' ↓ ' + Math.min.apply(null, data) ); });4 points
-
hi adrian, data is stored just as normal pw pages. nothing fancy here. this makes it very easy to use! the current setup is that you need 3 files to define your field: // yourfield_data.php <?php // return all relations that belong to this project return $pages->find( "template=feedback". // find all relations ",has_parent=$page" // project must be the current project ); // yourfield_columns.php <?php namespace ProcessWire; // sample column showing the ID of the page $col = new dtCol(); $col->name = "id"; $col->title = 'Columns ID'; $col->data = function($page) { return $page->id; }; $this->cols->add($col); // yourfield_js.js (optional, but in most cases necessary to do advanced stuff) var settings = { select: true, pageLength: 100, }; I'm also very excited to take this further. I cannot release it at the current stage though because major changes are not only likely to come but almost planned i have to work more on performance. I'm thinking about some kind of caching technique and maybe also providing AJAX pagination. some things like column statistics would only work on the client side when all the data is loaded, though. but i know that datatables can handle several thousands of rows quite efficiently so i think i'll find a way to work with those amounts of data.3 points
-
I would say that it's been many years since developers had to worry about a site not working without JS. Back in the early 2000's it was considered evil and we did all sorts of things to avoid using it (and to make sure we used graceful degradation techniques), but these days there aren't many sites that you can use without it even on the frontend, so expecting it for the backend of a site shouldn't be an issue at all anymore. Facebook does this: but you guys should take a look at the old "m.facebook.com" site with javascript disabled - it looks ancient3 points
-
Definitely with @abdus on this one. PHP7 is noticeably faster than 5.6, and PW has no problems (that I'm aware of?) running under 7. If it is available, do it (taking the usual precautions, obvs). Also, there might be optimisations you could make to your selectors and there are probably mysterious optimisations you may be able to make to your mySQL setup, depending on how much control you have within your hosting. First of those you will probably get help with here, if you are able to share some code, second is down to black magic, voodoo and selling the soul of your firstborn. Or hiring an expert. All of that having been said, it's a very good looking website, and it works well - initial loading doesn't feel slow, just the filtering isn't instant. <edit>Man, 3 more replies while I write this one.</edit>3 points
-
I acheived a subscription service on this site http://betaville.co.uk/ using the PaymentStripe module as payment and my subscribers module with some tweaks. Although note that I'm in the process of creating a new members module set that will supersed the subscribers module.3 points
-
You can use localStorage to save and restore scroll position. Something to start with: (not tested) function saveScroll(href) { // save current scroll position for this page localStorage.setItem('scroll__' + href, window.scrollY); } function restoreScroll(href) { // restore previous scroll or scroll to top let scroll = localStorage.getItem('scroll__' + href); $('html, body').animate({ scrollTop: scroll ? scroll : 0 }, 10); } window.addEventListener('beforeunload', function (e) { // remove scroll position localStorage.removeItem('scroll__' + location.pathname); }); $(document).on('click', 'a:not(.external)', function (e) { saveScroll(this.href); history.pushState(null, null, this.href); replacePage(this.href); e.preventDefault(); }); $(window).bind('popstate', function () { replacePage(location.pathname); restoreScroll(location.pathname); }); https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage2 points
-
nothing fancy here. you see it's not polished and some hardcoded values... the javascript to handle the clicks: $(document).on('click', '.ckesnippet', function() { // find correct ckeditor instance $field = $(this).closest('li.Inputfield'); var id = $field.attr('id'); var ckename = id.replace('wrap_',''); var cke = CKEDITOR.instances[ckename]; var data = cke.getData(); cke.setData(data + $(this).data('snippet')); return false; }); and the hook to modify the field: $this->addHookBefore('InputfieldTextarea::render', $this, function($event) { $field = $event->object; if($field->name == 'rockinvoice_suffix') { $del = ''; foreach($this->wire->pages->get(38967)->texttemplates as $item) { $field->entityEncodeText = false; $field->description .= $del . '<a href="#" class="ckesnippet" data-snippet="' . str_replace(PHP_EOL, '', $item->body) . '">' . $item->title . '</a>'; $del = ' | '; } } elseif($field->name == 'rockinvoice_prefix') { $del = ''; foreach($this->wire->pages->get(38967)->texttemplates_greeting as $item) { $field->entityEncodeText = false; $field->description .= $del . '<a href="#" class="ckesnippet" data-snippet="' . str_replace(PHP_EOL, '', $item->body) . '">' . $item->title . '</a>'; $del = ' | '; } } $this->wire->modules->get('RockTools')->loadAsset('ckesnippets.js', 'HrDiamonds'); }); and a repeater to setup the snippets:2 points
-
it's one of many custom "hacks" all the items can be set by the client on a custom settings page. it's a regular repeater. then there is a hook that renders that items as field description and some javascript that adds the html to the ckeditor. thanks. no problem at all. but there's not really a lot of data... the table showing all the revenues for different years is a custom DB-view because there's no built in possibility for such listings in pw. the pw alternative would be many many foreach loops and thats a no-go.2 points
-
There's https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript2 points
-
pw needs javascript all over in the admin so there's no way to make it work without. i agree it would be nice to add a warning. the login screen would be a nice place. you could do a PR and add some warning here that would be hidden via javascript and therefore only visible to clients without javascript. https://github.com/processwire/processwire/blob/master/wire/modules/Process/ProcessLogin/ProcessLogin.module#L427-L4512 points
-
OK, so I had a stab at this using $cache and ready.php. It seems to work fine. Throw the following code in ready.php or similar...The code and in-line comments are purposefully verbose to make it easy to follow. // Hook into login/logout sessions wire()->addHookAfter('Session::loginSuccess', null, 'checkLoggedIn'); wire()->addHookBefore('Session::logout', null, 'removeLoggedIn');// Hook before to get $user->id /** * Check if a user is already logged in * * If user logged in, take an action (notify,logout,etc). * Else, cache user as logged in to check for duplicate logins. * * @param HookEvent $event The object (Session::loginSuccess) we are hooking into. * @return void * */ function checkLoggedIn(HookEvent $event) { $user = $event->arguments('user'); $session = wire('session'); $userDuplicateLogin = checkUserDuplicateLogin($user);// returns boolean // if user logged in, do something. Here, we log them out and redirect to home page // you could make an exception for Superusers, or exception by role, permission, etc if($userDuplicateLogin) { $session->logout(); $session->redirect('/'); } // set cache else setLoggedInUserCache($user); /* @note: testing only $log = wire('log'); $log->save("user-logs","Successful login for '$user->name'"); */ } /** * Check if a user is logged in more than once. * * @param User $user The user to whose logins to check. * @return Boolean $duplicateLogIn True if user already logged in, else false. * */ function checkUserDuplicateLogin(User $user) { $cache = wire('cache'); $duplicateLogIn = false; $userID = $user->id; $cachedUsersIDs = $cache->get('loggedInUserIDs');// array OR null if(is_array($cachedUsersIDs) && isset($cachedUsersIDs[$userID])) $duplicateLogIn = true; return $duplicateLogIn; } /** * Create or update cache for logged in user. * * @param User $user The user whose cache to set. * @return void * */ function setLoggedInUserCache(User $user) { $cache = wire('cache'); $userID = $user->id; $cachedUsersIDs = $cache->get('loggedInUserIDs'); // cache does not exist, create empty array ready to cache if(!count($cachedUsersIDs) || is_null($cachedUsersIDs)) $cachedUsersIDs = array(); // save/update cache // for value, can use whatever, even $user->name; doesn't matter, key is the important thing here // outer array: we use $user->id to group same user; // in inner array, we use session_id() to ensure uniqueness when removing cache $cachedUsersIDs[$userID][session_id()] = $userID; $cachedUsersIDsStr = json_encode($cachedUsersIDs);// JSON to save as cache $cache->save('loggedInUserIDs',$cachedUsersIDsStr);// @note: set expiration of cache if you wish to } /** * Remove a logged out user's cache. * * This to allow subsequent logins. * * @param HookEvent $event The object (Session::logout) we are hooking into. * @return void * */ function removeLoggedIn(HookEvent $event) { $user = wire('user'); removeLoggedInUserCache($user); /* @note: for testing only $log = wire('log'); $log->save("user-logs","Successful logout for '$user->name'"); */ } /** * Remove the cache for a user who has logged out. * * @param User $user The user whose logged-in cache we are removing. * @return void * */ function removeLoggedInUserCache(User $user) { $cache = wire('cache'); $userID = $user->id; $cachedUsersIDs = $cache->get('loggedInUserIDs'); // cache does not exist/empty, nothing to do if(!count($cachedUsersIDs) || is_null($cachedUsersIDs)) return; // save/update cache // @note: we check for current logged in user but we remove the whole user group (outer array) // this is because the user logged in 'validly' is logging out. if(isset($cachedUsersIDs[$userID][session_id()])) unset($cachedUsersIDs[$userID]); $cachedUsersIDsStr = json_encode($cachedUsersIDs); // save updated cached $cache->save('loggedInUserIDs',$cachedUsersIDsStr);// @note: set expiration of cache if you wish to }2 points
-
These might help you https://processwire-recipes.com/recipes/activate-all-languages/ https://processwire.com/talk/topic/4383-how-to-set-language-active-via-api/2 points
-
https://www.reddit.com/r/PHP/comments/71f8vs/cms_opinions_wanted/ I recommended PW, but maybe someone can give a more in depth answer.2 points
-
https://www.baumrock.com/portfolio/individuelles-crm-und-controlling-tool/ I'm happy to share my biggest and most interesting ProcessWire project so far with you It's a 100% custom office-management solution that helps my client to keep track of all their contacts, projects and finance/controlling stuff. Conception was done back in 2016 and the software is productive since begin of this year. My client is very happy with the result and so am I. Some technical insights: Everything is done inside the PW Admin. I'm using the Reno Theme with some custom colors. In the beginning I was not sure if I should stay with the pw admin or build my own admin-framework but now I'm VERY happy that I went with PW Almost all of my custom Process Pages use my RockDatatables module - there are still some limitations but without it, this project would not have been possible For the charts I used Google Charts and chartjs - both play well together with the datatables and make it possible to display filtered data instantly: also my handsontable module was created for this project to have a nice and quick option for matrix data inputs: Lister and ListerPro were no options as i needed much more flexibility regarding data presentation (like colorization, filtering and building sums of selected rows): invoices are highly customisable as well and easy to create. PDFs are created by php and mPDF by the way: all data is dummy data populated via my Module RockDummyData have a nice weekend everybody1 point
-
Hi Everyone, Since a couple of months, we have our new website live with processwire as CMS system. In this website there is a huge database (1900+ trees), wich can be found with different filters. Take a look at www.vdberk.com/trees. The website does not to be seen very fast when you select a couple of filters. Every time there is a delay between 3-5 seconds. Now we are migrate the website to another sever, with more preformance. So we hope this give us some timeprofits. Does anyone have any kind of suggest, to make this filter faster. Now the website is on PHP5.6, is php7 better? Can this make a different? We used ProCache already. Thanks in advance1 point
-
That error from the Repeater module looks like the same thing I raised a GitHub issue for recently, so there's a good chance it relates to PW's caching of module data rather than Recurme specifically. Ryan has pushed a fix for the issue to the dev branch.1 point
-
Here's a fairly easy question: With regard to the invoice GIF you shared, I hadn't ever seen auto-suggest/auto-fill links used before ... Is that a component built into core, an existing module, or something you customized? Everything else shown is enormously impressive. I'd like to think that PW is still running blazingly fast, but I'll ask anyway: is PW still running efficiently for the client (and during your mockdata testing)?1 point
-
1 point
-
..or if you want realtime search results, maybe you can try this: https://www.algolia.com/product ( I'm not an affiliate or promo agent )1 point
-
PW Admin doesn't really function without javascript, and my question would be, should we care? I think, however, either way it might be nice to add a "<span>Javascript doesn't seem to be available, therefore you may not be able to access the full functionality of the admin</span>" somewhere maybe?1 point
-
There's nothing invalid about the original page name in your gif. Adding the $beautify argument to $sanitizer->pageName() will give a result that is closer to the JS replacement that happens in the admin interface. But I take your point that it would be useful to have a sanitizer option that is an exact match for the JS replacement.1 point
-
1 point
-
very interesting article and very well put together. i'm wondering why for example the maxfiles setting for images fields is not activated by default for template context. any ideas on this?1 point
-
Superb website. It should be included in the featured sites if it isn't already. Perhaps your filter queries are not optimal. Feel free to post the filter code if you would like any feedback on this.1 point
-
Hi @sreeb Do you cache results of searches? I have a similar project with a lot of filtering options. I use WireCache for caching search results ( PageArrays) and MarkupCache for result cards. It works quite fast on shared hosting.1 point
-
It's usually plug and play, I dont remeber having any problems with the upgrade. Unless you're using deprecated features, you should be ok http://php.net/manual/en/migration70.php http://php.net/manual/en/migration70.deprecated.php Here are some guides on Tuts+ and DigitalOcean https://code.tutsplus.com/tutorials/upgrading-your-linux-server-to-php-7--cms-27583 https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-041 point
-
1 point
-
1 point
-
I have an issue that has been a mild annoyance for a while but has become more serious now due to a core change. The issue occurs at the end of the PW installation process using a custom site profile that I generated using ProcessExportProfile, and relates to a custom Fieldtype module not being "known" to PW immediately after installation. The error I used to get is this... ...and it was of no real consequence. I just ignore the message and on the next page load the message does not reappear (I used to do a Modules > Refresh but after more testing today it seems this isn't necessary - just reloading the page is enough to resolve the message). The issue relates to this section of code and seems to indicate that FieldtypeSelectImage is not included in $fieldtypes immediately after installation. But as soon as I login and check with Tracy I can see FieldtypeSelectImage is included as expected: Due to recent changes to FieldtypeRepeater.module I now get a more serious problem at the end of installation that prevents me from completing the installation, and install.php is left behind... Again due to the FieldtypeSelectImage fieldtype not being present in $fieldtypes. Now FieldtypeSelectImage is a custom module I created, and it was the first PW module I ever made so it wouldn't surprise me if there was some mistake in it. But there are other similar issues reported in the forums so I think it might be a more general issue that isn't specific to this particular module. https://processwire.com/talk/topic/574-site-copied-to-development-server-fieldtype-does-not-exist/ https://processwire.com/talk/topic/4067-site-doesnt-work-after-hosting-migration/ https://processwire.com/talk/topic/13781-problems-after-installing-remote-copy-to-local/ The agreement seems to be that the issue relates to the module cache, but what can I do to prevent the issue occurring during installation? The cache file that Ryan mentions in his reply to one of the threads above does not exist in my case. Is there some change I need to make to FieldtypeSelectImage so that PW can recognise it during the PW install process? The module code:1 point
-
For anyone not following the issues repo: Ryan has committed a fix for this issue to the dev branch.1 point
-
Ryan committed a change back in May in response to this issue but it hasn't been merged to the master branch yet.1 point
-
That was my initial experience as well. It served me well in the absence of xDebug (still use Tracy quite often, though), but now that I got it running again (by manually removing __debugInfo methods()) I don't use it as much. Console feature is immensely useful, you'll love it.1 point
-
New website for the Camel cigarette brand. When you enter you will see an legal smoking age alert in Spanish, please click on the lower right option "Soy mayor de edad, me registraré luego" (Legal age confirmation) https://camel.com.do Modules used: ProCache Croppable Image 3 Form Builder Login for Facebook ProDrafts Profiler Pro ProcessWire API Explorer Tracy Debugger ListerPro Redirects1 point
-
Let me introduce you: https://processwire.com/blog/posts/introducing-tracy-debugger/1 point
-
Protip: you can filter empty categories and specify sort in your selector, and simplify your code like this <?php namespace ProcessWire; // get categories that have been referenced by a blog post $categories = $pages('template=category, blogPost.count>0, sort=name'); // $categories = $pages('parent=/categories/, blogPosts.count>0'); ?> <?php if ($categories->count): ?> <ul class="list-unstyled"> <?php foreach ($categories as $category): ?> <li class="category"> <a href="<?= $category->url ?>"><?= $category->title ?> (<?= $category->blogPosts->count ?>)</a> </li> <?php endforeach; ?> </ul> <?php else: ?> <p>No categories yet.</p> <?php endif; ?> And using API methods, your post items can be simplified to: <article class="post"> <h1 class="post__title">...</h1> <p class="post__summary">...</p> <p>Posted in: <?= $post->categories->implode('/', function($c){return "<a href='{$c->url}'>{$c->title}</a>";}) ?></p> </article> https://processwire.com/api/ref/wire-array/#pwapi-methods-retrieval https://processwire.com/api/ref/wire-array/implode/1 point
-
1 point
-
Maybe he means in 2 different browsers? I know sometimes I have a dev site open in chrome and opera so I can be on two different pages in the admin.1 point
-
1 point
-
This module was suggested by @abdus to me in another post and after giving it a whirl, it's pretty awesome! If you link one way, it makes sense for pages to be linked the other way also.1 point
-
Hi all, I have just committed a major new version (2.0.0) on the dev branch (https://github.com/adrianbj/TableCsvImportExport/tree/dev). This version has breaking changes to the frontend export/import API methods!! Changes include: changed API methods - please see ReadMe for details: https://github.com/adrianbj/TableCsvImportExport/blob/dev/README.md module config settings to: set defaults for import and export parameters (delimiter, enclosure, etc) can users override the default parameters can users can select columns/order in exported CSV can users use an InputfieldSelector interface to filter table rows (this is an enhanced version of the built-in Table "Find" interface available when you have pagination enabled) I would like to make this the stable (master) version as soon as possible because the old API methods were not well constructed so I would really appreciate testing of this new version if you have any time. Thanks! PS - has anyone out there actually been using the API methods?1 point
-
1 point
-
Some more nice features copy&paste (eg from excel) that way the field could be used as an import-interface with live preview (much more userfriendly than CSV in my opinion) auto-add-rows (coulb be used as something like a repeater-replacement) hot.updateSettings({ colHeaders: ['Foods'], minCols: 1, maxCols: 1, rowHeaders: false, minRows: 1, minSpareRows: 1, }); auto-add-cols (like tagging) hot.updateSettings({ colHeaders: false, minCols: 1, minSpareCols: 1, rowHeaders: ['Foods'], minRows: 1, maxRows: 1, });1 point
-
I will take a look! I mainly listed price in case there were some kind of micro transaction service since some have a minimum per transaction fee. I would love to find there was a mostly put together way to do this! Instant digital download would be a must at such a low price! Too much labor to send links.1 point
-
a simple way of caching (nearly) everything using wirecache and 2 page render hooks in site/ready.php // the next ensures that the following code will only run on front end (otherwise back end would get cached, too which results in problems) // make sure to place anything you need in the backend before this line or change it to your needs.. if ((strpos($page->url, wire('config')->urls->admin) !== false) || ($page->id && $page->is('parent|has_parent=2'))) return; $cacheName = "prefix__$page->id-$page->template-{$user->language->name}"; if ($urlSegment1) $cacheName .= "-$urlSegment1"; if ($urlSegment2) $cacheName .= "-$urlSegment2"; if ($urlSegment3) $cacheName .= "-$urlSegment3"; if ($input->pageNum > 1) $cacheName .= "-page$input->pageNum"; // if already cached exit here printing cached content (only 1 db query) $wire->addHookBefore('Page::render', function() use($cache, $cacheName) { $cached = $cache->get($cacheName); if ($cached) { exit($cached); } }); // not cached so far, continue as usual but save generated content to cache $wire->addHookAfter('Page::render', function($event) use($cache, $cacheName) { $cached = $cache->get($cacheName); if (!$cached) { $cache->save($cacheName, $event->return); } unset($cached); }); of course not the same as a proper flat file cache like procache but at least saving many database queries make sure to adjust the $cacheName as needed, you can even cache query strings, almost everything you'd like and you could wrap everything in a condition to only run if no incoming post or query strings so form submits keep working example if (!count($input->get) && !count($input->post) && !$config->ajax) { // cache logic from above } have fun1 point
-
Haven't used it now, but already like it! (have had a look to the readme!) Below an example of a root parent and a first level child:1 point
-
1 point