Leaderboard
Popular Content
Showing content with the highest reputation on 04/30/2016 in all areas
-
I got a client request to make Word template so she can create an image of the weekly menu of a restaurant to post on Facebook. I usually get sick when I have to deal with M$ Word - it's frustration and it's not meant to be used things like that. So I figured out a better system: PW + html2canvas.js. It took more time to finish but it was worth the trouble. The main issues were html2canvas versus some CSS issues, plus switching to different languages in PW on each line. Also, JavaScript cannot offer named downloads, only "download.png", so I had to use HTML5 attribute "download" on links to be able to add custom download filename. I used ProField modules Table and Matrix Repeater which allow very pleasant editing of menu items, even in multilanguage context. Front-end editing is created using the built-in front-end editor. I was about to achieve inline editing of menu items but it soon turned out that repeaters and tables can't be edited this way. Anyway, it's still better compared to my module FEEL because sections are reloaded using Ajax and the admin lightbox shows only the fields I choose. Here's a quick screencap - when the gray background turns to dark gray, then the menu is not HTML but canvas, that can be downloaded.8 points
-
Last week I mentioned we'd be continuing the documentation updates into this week and that's exactly what we did. All in all, these documentation updates involved 46 files and 5264 additions, so far. Read more about it in this weeks' blog post: https://processwire.com/blog/posts/processwire-3.0.16-continues-expanding-documentation-and-more/7 points
-
Hi everyone, A few commits today to improve a few things. You can now choose the branch of the Tracy core from the modules config settings. It defaults to the master (dev) version if you have PHP 5.4.4+, but now if you have having the slow rendering of the debugger bar (mentioned by @tpr above), you can easily choose to load the stable branch instead. Hopefully the Tracy folks will fix this and if they do, I'll likely remove this setting in the future. There is now better panel resizing and scrolling of internal content - this is especially handy with large panels when you have the dev console open on the bottom. Probably still not perfect, but should be much better. Actually I think the Tracy core needs some work to make this even better. Performance Panel now has internal scrolling - this was absent before. Enhancements to the Debug Mode panel, including linking of the API variables to the new PW 3.x API Reference docs.5 points
-
3 points
-
Depends a lot on the use case. I'm currently working on a site with roughly 10.000 pages, and because of some recent changes, most of those pages have a whole bunch of unused image variations. Per-page solution wouldn't do me much good here Generally speaking I'd say that a "clear all imagevariations" would be more useful than a per-page option.2 points
-
Hi! Just finished my first module This module adds a new "Google-Analytics" Page in your Admin-Panel and displays various Statistics from a Google Analytics Account. It uses the JQuery plugin "jqplot" to display the charts. Github: https://github.com/w...GoogleAnalytics Modules directory: http://modules.proce...ogle-analytics/ Features Visits by Date (Chart) General Statistics about Visits (Total visits, Visit duration, New visitors, Returning visitors etc.) Demographics: Countries, Cities, Languages System: Browsers, Operating Systems, Screen Resolutions Mobile: Operating Systems, Screen Resolutions Pageviews by Date (Chart) Top Content Traffic Sources: Keywords, Referral Traffic by Domain and URI Choose a default date range displaying statistics: last 24 hours, 2 days, 1 week, 1 month etc. Custom date range by setting a "start date" and "end date" Requirements Google Account and Analytics Account A Project in the Google APIs Console cURL Installation 1) Create a Project in the Google APIs Console: Create a new Project in the APIs Console: code.google.com/apis/console/ Under Services, enable the Analytics API Under API Access: create an Oauth 2.0 Client-ID Give a Product Name, choose "Web-Application", Domain doesn't matter Enter a Redirect URI to the GA-Page in your Processwire Installation: http://yourdomain.com/processwire/google-analytics/ Notes: The redirect URI must exactly match with the URL from the new "Google Analytics" page in Processwire. Open the Page and copy the URL from the address-bar (localhost does work too!) The project created in the APIs Console can be reused for every Processwire installation using this module. You just have to enter more redirect URIs 2) Install the module: Place the module's files in /site/modules/ProcessGoogleAnalytics Install the Module via the Admin-Panel Enter Client-ID and Client-Secret keys from the created project in the module config Load the newly created page "Google-Analytics" and click on the button "authenticate" Grant the module access to the Analytics Data Choose a Google Analytics account (Domain) from the dropdown Done: You should see the statistics. Check out the module config options for further customization In order to let other users see the Google Analytics page, you must give their role access to the "ga-view" permission. Ps. Processwire is awesome and so is this community!1 point
-
This module is deprecated in favor of RockMigrations. It'll continue to work and I might fix some smaller incompatibilities if they're reported, but no major development will happen on this anymore. There where various threads about a how to reasonably handle multiple dev/staging and live environments with ProcessWire and at best handle it as automatically as possible. A git based workflow makes it easy to handle files, but the pain point of migrating db changes has even lead to multiple requests of not handling template/field storage in the db at all. I've gone ahead and used for my own projects the concept of database migrations, which most frameworks are using to handle database changes – but the ProcessWire flavored way. ___ ___ ___ ___ ___ ___ ___ /\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /::L_L_ _\:\ \ /::\ \ /::\ \ /::\ \ \:\ \ /::\ \ /:/L:\__\ /\/::\__\ /:/\:\__\ /::\:\__\ /::\:\__\ /::\__\ /::\:\__\ \/_/:/ / \::/\/__/ \:\:\/__/ \;:::/ / \/\::/ / /:/\/__/ \:\:\/ / /:/ / \:\__\ \::/ / |:\/__/ /:/ / \/__/ \:\/ / \/__/ \/__/ \/__/ \|__| \/__/ \/__/ Beta This module does help you managing migration files, where any database changes can be stored in php files using just the simple ProcessWire api at your disposal. It's not as nice as using the admin UI, but certainly better than trying to migrate changes manually and possibly weeks after adding the changes. Also there's always the option to create helper modules, which can export changes made in the admin UI to something usable in those migration files. For example I'm using an internal process module, which does let me export changes to template access rules as json strings, which I then use in my migrations to actually apply the changes. Now on to the meat – How to use the module: Read the following guide on creating own migrations Maybe use the CLI tool to speed up your workflow (and possibly automate stuff) It is generally recommended, but not enforced, that migrations are run/rolled back in order. When doing migrations or rollbacks, without specifying a migration, this module will stick to the order. Creating Migrations Your migrations will probably hold lot's of code, which does delete data. By now this module does not have any security measurements to prevent that. Be sure to test your migrations locally and possibly keep a database backup before running them. There are currently four types of migrations: default (Migration) Default migrations are the most free form migrations. There's just a description and two functions – update() and downgrade(). What you're doing in those functions is totally up to you, but it's recommended to try the best to keep changes as reversible as possible. Meaning that running update() and downgrade() once should have as less effect on the installation as possible. The ProcessWire API is available exactly like in modules using the $this->pages, $this->config, … syntax. FieldMigration TemplateMigration ModuleMigration All of those are there to make your life easier. They all have different but similar functions – which you can find in migrations created by this module – which ease the creation and removal of fields, templates or modules. All the boilerplate is handled by the base classes these migrations do extend, so you don't even need to think about update() and downgrade(). You can rather just describe the item you want to handle and the creation / removal process is taken care of. These are by now not highly tested, so please again be sure to test migrations before running them on important content. Command-Line Interface The module does include a cli interface, which does allow the migrations to be run automatically by CI or deployment scripts or just by you if you like cli's. The cli script is located in the bin directory inside the module's folder. It does however require a composer package to work, which you can simply add by running composer require league/climate in your site directory (or the root directory for pw 3.0). Make sure to require composers autoload.php in your config.php for 2.x installations. The CLI does have a quite handy help page, which you get by running php migrate -h so I'm just adding the important bits of that here: > php migrate -h […] Usage: migrate [-h, --help] [-i info, --info info] [-m migrate, --migrate migrate] [-n new, --new new] [-nf newField, --newField newField] [-nm newModule, --newModule newModule] [-nt newTemplate, --newTemplate newTemplate] [-r rollback, --rollback rollback] Optional Arguments: -m migrate, --migrate migrate Run a specific migration or all new* ones if none given. * From latest migrated to newest. -r rollback, --rollback rollback Undo a specific migration or the latest one if none given. -n new, --new new Bootstrap a new migrations file. Optionally you can already supply a description. -nt newTemplate, --newTemplate newTemplate Bootstrap a new template migrations file. Optionally you can already supply a description. -nm newModule, --newModule newModule Bootstrap a new module migrations file. Optionally you can already supply a description. -nf newField, --newField newField Bootstrap a new field migrations file. Optionally you can already supply a description. -i info, --info info Get detailed info about a migration. -h, --help Show all commands of the cli tool. Link the migrations cli update save to ProcessWire's root: https://processwire.com/talk/topic/13045-migrations/?p=118329 Helper Functions There are already a handful of helper function included in the Migration base class, which tackle things I found to need way to much boilerplate for kinda simple changes, but you can also add own custom helper functions via hooks. /** * This does use @diogo's while loop technique to loop over all pages * without getting memory exhaustion. */ $this->eachPageUncache("template=toBeHidden", function($p){ $p->setAndSave('status', Page::statusHidden); }); /** * $template, $field, $reference = null, $after = true * The below function reads like this: * In the template … add the field … relative to the field … in the position after/before */ $this->insertIntoTemplate('basic-page', 'images', 'body', false); /** * Edit field settings in context of a template */ $this->editInTemplateContext('basic-page', 'title', function($f, $template){ $f->label = 'Headline'; }); And a simple example of adding a custom helper as a hook. // in ready.php $wire->addHook('Migration::renameHome', function(HookEvent $event){ $name = $event->arguments(0); wire('pages')->get('/')->setAndSave('title', $name); }); // in the migration $this->renameHome('Root'); Snippets Still not sure how all this works in practice? Or you want to share a maybe more complex migration? Just head over to the Snippets Repo at Github. https://github.com/LostKobrakai/MigrationSnippets There are also less specific examples in the modules repository: https://github.com/LostKobrakai/Migrations/tree/master/migrations Appendix As long as the module is in Beta the helper functions in the Migration.php might be object to change/removal, so be aware of that. Download http://mods.pw/Bm https://github.com/LostKobrakai/Migrations1 point
-
Found Spectre.css framework during I searched the web... could be interesting, so I post it here. Spectre.css is a lightweight, responsive and modern CSS framework for faster and extensible development. lightweight and clean starting point for your project and prototype flexbox, responsive and mobile-friendly layout carefully designed elements built in useful components and utilities patterns and html templates soon email templates soon URL: http://picturepan2.github.io/spectre/1 point
-
Hi there, i just want to share the code of what the subject line says. The pages to appear in the menu have a custom field "in_main_menu" of type checkbox checked. The item <li>s of the actually shown page and in the direttissima upwards - except home - get the class "current". The item <ul>s of submenus get the class "submenu". This is basically Ryans Code from here run through a meatgrinder. I hope useful for any beginners like me looking for a solution to a similar problem. Any improvement welcome! Now the code: /** * A recursive menu containing home. (It is added to the list of menu items while $level =1). * In order to be included, a page must have a custom field "in_main_menu" of type "checkbox", * and the latter has to be checked. * All submenu <ul>s get class "submenu". * All <li>s in the direttissima upwards of the page shown - except home - get the class "current". * Takes $root out of the recursion in order to not have all pages twice. * All menu items, that have children, do not have a link to their content, but act merely as switches. * You can switch this behaviour off by replacing * * $href = ( $item == $root || !$item->numChildren ? "$item->url" : "#" ); * * with * * $href = $item->url; * * Or you can make it conditional by querying a second custom field "has_own_page", e.g. * * $href = ( $item == $root || !$item->numChildren || $item->has_own_page ? "$item->url" : "#" ); * * Intended to be used without arguments, i.e. "selectiveMenu();" , i.e. always starting with site root. */ function selectiveMenu(Page $root = null) { $shownPage = wire('page'); if(is_null($root)) $root = wire('pages')->get('/'); $level = count($root->parents); $ul_class_string = (($level > 0) ? "class='submenu'" : ""); $out = "\n<ul {$ul_class_string}>"; $parents = $shownPage->parents; $items = $root->children; if ($level == 0) $items->prepend($root); foreach( $items as $item) { if ($item->in_main_menu) { $s = ''; $li_class_string = ( ( $parents->has($item) && $item !== $root ) || $item === $shownPage ? "class='current'" : "" ); if($item->numChildren && $item !== $root) { $s = str_replace("\n", "\n\t\t", selectiveMenu($item)); } $href = ( $item == $root || !$item->numChildren ? "$item->url" : "#" ); $out .= "\n\t<li {$li_class_string}>\n\t\t<a href='{$href}'>{$item->title}</a>$s\n\t</li>"; } } $out .= "\n</ul>"; return $out; }1 point
-
@laban, sorry didn't spot your question earlier. But here's the answer. // DOM is ready $(function () { // field with the name attribute title $("[name='title']").truncate({ characters: 55, prefix: '', suffix: ' character(s)' }); // field with the name attribute an-other-field $("[name='an-other-field']").truncate({ characters: 160, prefix: '', suffix: ' character(s)' }); });1 point
-
Hi, Horst and thank you for answer. For now i implement solution based on url segments. <?php if($input->urlSegment1 == 'download') { if($input->urlSegment2) { $names = array(); $urls = array(); foreach ($page->diagnostic_referral_repeater as $referral) { foreach ($referral->diagnostic_referral_files as $file) { array_push($names, $file->name); array_push($urls, $file->filename); } } $key = array_search($input->urlSegment2, $names); if($key !== false) { wireSendFile($urls[$key]); } else { throw new Wire404Exception(); } } } else if($input->urlSegment1) { // unknown URL segment, send a 404 throw new Wire404Exception(); } ?> <?php foreach ($page->diagnostic_referral_repeater as $referral) { ?> <div class="diagnostic-referral"> <div class="diagnostic-referral__box"> <div class="diagnostic-referral__title"> <?php echo $referral->diagnostic_referral_category->title; ?> </div> <?php echo $referral->render('diagnostic_referral_files', 'diagnostic-referral'); ?> <div class="diagnostic-referral__files"> <?php foreach ($referral->diagnostic_referral_files as $file) { ?> <div class="diagnostic-referral-file"> <a href="<?php echo $page->path.'download/'.$file->name; ?>" class="diagnostic-referral-file__link"> <div class="diagnostic-referral-file__icon"> <span class="icon-download"></span> </div> <div class="diagnostic-referral-file__title"> <?php echo $file->description; ?> </div> </a> </div> <?php } ?> </div> </div> </div> <?php } ?> Do you have any recommendation to improve it? Thanks.1 point
-
1 point
-
Have you tried setting your SMTP port to 587? Here is a link that explains the different SMTP ports http://blog.mailgun.com/25-465-587-what-port-should-i-use/1 point
-
Just grab the latest version from git (if you get a message that configurable module test failed, repeatedly refresh modules until the message goes away), then go into the module configuration and select "Radios". You can exclude certain media pages from showing up for the user through a hook in ready.php: wire()->addHookAfter("MediaLibrary::getPageMediaLibraries", null, "filterLibraries"); function filterLibraries($event) { $media = $event->return; if(! wire('user')->isSuperUser) { $event->return = array_filter($media, function($v) { return ($v->id != $ID_OF_PAGE_TO_EXCLUDE); }); } }1 point
-
In some WP plugins they solve such situations by allowing batch deletion of 50 or 100 images, and you can continue the process if there are images left.1 point
-
No, there is nothing built-in for this. You need to send apropriate HTTP-headers. About which one, you may read here: http://stackoverflow.com/questions/17968837/file-opens-instead-of-downloading-in-internet-explorer-in-a-href-link.1 point
-
I'm a little bit uncomfortable with allowing just any child under a media library, but I can understand the wish for nesting, so version 0.0.7 on github allows you to create libraries under existing MediaLibrary pages, and these child libraries (no limit for nesting) are also listed whenever their parent library is. For anybody planning to use MediaLibrary through the API, there's a new method that returns an array with all applicable media pages for a given page (following the under-parent-or-current-page rule): $ml = wire('modules')->get('MediaLibrary'); $mediapages = $ml->getPageMediaLibraries($page); foreach($mediapages as $mpage) { // ... } I've made getPageMediaLibraries hookable if anybody wants to apply further rules to which pages should be available.1 point
-
It's great to be able to switch to the Stable branch, now Tracy bar appears here without editing the module file, thanks!1 point
-
it's CentOS 6.6 I don't have direct access to it, only through Plesk. After the update the tags appear in the MailGun logs, thanks!1 point
-
Just keep in mind that $pages->find() can use those date strings, whereas further in memory filtering of pages can only handle raw timestamps.1 point
-
I think, PW is not just using strtotime() to convert the relative date to a timestring. You can take a look at wire/core/WireDateTime.php, to see how strings are converted to timestamps. It is also worth looking into the $datetime class and see how you could utilize that. But, this doesn't really answer your question why it is that you are getting different results. I would also expect to get the same results. Only thing I can think of is time zone conflict. Maybe your strtotime() operation is using a different time zone than the internal PW calculations? But this is just a wild guess. To see if this is the case, you could try and use date_default_timezone_set() before using strtotime() and getting the pages.1 point
-
Currently you're getting your top-level menu items with: $pa = $homepage->children; Try changing to a find selector. If there is some common attribute of the pages you want for the footer menu (template, value of a field, etc) you could use that to exclude the pages, otherwise you'll need to exclude them by name or id. $pa = $pages->find("parent=1, id!=1050|1051|1052"); Edit: just noticed that you have added a checkbox to select pages for the footer nav. So you can do: $footer_nav = $pages->find("parent=1, footer_checkbox=1"); $main_nav = $pages->find("parent=1, footer_checkbox!=1");1 point
-
My hosting provider says they've ran the chown command and that didn't fix it, so... McGyver time! I just duplicated the whole "site" folder with php. I took this script and slapped it in a php file, then temporarily changed public_html permissions to 777 and ran the script copying "site" to "siteB". Every file and folder in siteB got the correct owner/group. Turned permissions on the root folder back to 750 and renamed "siteB" to "site". Done.1 point
-
I am passing on this information to make you aware of some recent changes to the Google Chrome browser. Security Update for Chrome Version 50 http://googlechromereleases.blogspot.com/2016/04/stable-channel-update_28.html No More Updates To Chrome on Windows XP/Vista and MacOS 10.6/10.7/10.8 after Chrome Version 49 https://chrome.googleblog.com/2015/11/updates-to-chrome-platform-support.html Note: Many of you will have your computers setup to automatically update the Chrome browser, however you should be aware of these important changes to ensure your browsing experience is still secure. https://sites.google.com/a/chromium.org/dev/Home/chromium-security1 point
-
$childCount is a PageArray but you need a number. Add ->count() after children(...)1 point
-
added the module to the modules directory and changed version number to 1.0.0 please let me know if anyone experiences problems1 point
-
@tpr, what OS? I have the same intl version on my test box. It seems your build might be linking the wrong ICU (outdated) package. I just added a check in the module to test if the transliterator ID was valid on a given system. https://github.com/plauclair/WireMailMailgun/releases/tag/0.4.2 Note that I am not able to replicate your environment or the issue, so please let if know if this release corrects the issue on your end.1 point
-
Hi dlen, I don't know to which particular post you are referring too, but in general: this is why. See our PHP Coding Style Guide for more information.1 point
-
Thanks for your detailed answer! Very impressive stuff. The vangoghroute.nl site is very nice too.1 point
-
Thanks @Mats! The map tiles are designed in Mapbox, the map itself is built on Leaflet.js, using the great Ember Leaflet addon. Once you get the hang of Ember.js (quite a steep learning curve) and it all starts making sense, it becomes really logical and fast to build upon. Because it is so strict, you can predict how components and external addons will work, and how to separate your functions. All using the same philosophy. As a result, it's peanuts to toggle markers and other layers on the map that relate to other items in the application. Let me illustrate how easy it is. The polylines are added by adding a Polyline-layer, which is part of the Ember Leaflet addon. It requires 'locations': an array of lat/lng points. The stripped down version of it works like this: 1. From the API we get, for instance, this JSON for the Hoofdroute (main route) -> http://www.intonature.net/api/routes/hoofdroute 2. Through the default Ember Data Rest adapter this JSON gets loaded into the route* model: // models/route.js import DS from 'ember-data'; export default DS.Model.extend({ title: DS.attr("string"), points: DS.attr("array"), color: DS.attr("string"), }); 3. After the model promise is fulfilled, it renders the Template belonging to the Route*, often with help from an Controller to 'decorate' the data. If that made no sense, you can also read that previous sentence like this: Through the magic of Ember this ends up at the Map Component which is inserted into the Explore template. The stripped down version of the Explore template: {{!-- templates/explore.hbs --}} {{map-component locations=locations currentItem=currentItem currentPreviewItem=currentPreviewItem routes=routes }} 4.And then inside the map component we get the following: {{!-- components/map-component.hbs --}} {{#leaflet-map id='explore-map'}} {{tile-layer url=tileLayer}} {{#each routes as |route|}} {{#if route.points}} {{#polyline-layer locations=route.points color=route.color }} <span class="route-label">{{route.title}}</span> {{/polyline-layer}} {{/if}} {{/each}} {{/leaflet-map}} And that is essentially it. We load the /explore route*, which loads data from the server and puts it into a model, then renders its template. This template contains a component which draws polylines on top of a tile layer. My previous large map-oriented / PW- & RequireJS powered project took overall about 300 hours to develop. In large because I had to invent the wheel, discover fire, and then deal with burning wheels everywhere. In short: I was missing a strict, well defined idea of which part is responsible for which function, something that happens to a lot of developers I have noticed. That, combined with the incredible shitty documentation of the non-standard Google Maps stuff and some other setbacks made it quite a tedious project. (The resulting site is still quite nice though: http://www.vangoghroute.nl ) Developing Into Nature took me around 90 hours, of which maybe half map-related. I still had to figure out a lot, yet I don't think I'll quickly return to the old world of "Php-generated html with bits of Javascript here and there and oh let's throw some more Ajax at it shall we?" * Let me clarify: We are dealing with 2 kinds of routes here. First of all the "Into Nature art routes", and then there are the 'Ember Routes'. Ember Routes are the urls of the app, and responsible for getting data and injecting that data into models.1 point
-
I've just commited a few smaller updates (most on Jonathan's requests) Migration descriptions are now escaped, so that characters like double quotes or backslashes won't break any newly created migrations. Also the backend UI does now feature a textarea instead of a text input to allow for multiline description entry. In the cli one would have to add "\n" linebreaks manually. The module does now try to add the /site/migrations/ path automatically, when it's called for the first time (e.g. by accessing the admin UI page) I've added a basic onboarding page for the admin UI, when there are no migrations, which does now feature a "Create New" button to get started. Jonathan did also request the addition of importer migrations for modules like FormBuilder or HannaCode. I'm not really keen on adding those and especially maintaining them. I'd rather suggest creating a GitHub repo, where the community can add migration snippets via pull-request. For example using the FormBuilder importer is just a single line of code, whereas the HannaCode importer would need to be copied nearly completely, because it's so tightly coupled with it's backend form. This repo option would be an easy way to just share the bits of boilerplate which is sometimes needed to do things via the api. Additionally I'm going to add some example above on how to add own helper methods to the Migration class with hooks, so everybody can add his own helper functions. Edit: I've added the mentioned docs about helper functions.1 point