Leaderboard
Popular Content
Showing content with the highest reputation on 02/28/2024 in all areas
-
I'll chip in some thoughts here, and this is from a perspective of caring about you @titanium in this situation. Well... they're graphic designers, not web designers. I've lead a web team and trained graphic designers to become web designers because they are not remotely the same. I always take the route of asking questions- a lot of them- because I wouldn't be able to make an accurate recommendation without understanding their needs. So I'd ask about more specifics about their design, view a mockup if they have one, understand what they're asking for because it does sound to me like they're asking for the moon. It's a moment where people reveal their level of expertise, or lack thereof, in the first sentence of their request. Sounds like they want * { position: absolute; } This is why I always operate with this thought in mind: what a client asks for does not have intrinsic correlation with what they need, or even want to begin with. Maybe they actually could achieve what they want using sane tools like @bernhard's builder. I'm sure there are more specifics to your situation and I'm not sure of the relationship you have with this client, but I would be concerned that they're going to end up trying to do something that isn't possible, or is so remotely possible that it's not worth their time, or yours. It might be worthwhile to ask yourself: Is this client expecting something that can't be done that may get you stuck in a position where you can't deliver? You're the expert in this field. Wix, Squarespace, GoDaddy Website Builder (lol), etc. They all fundamentally build in blocks with all of the standard limitations of the web. If they want to be big kid web designers then the onus of finding a tool that lets them do what we do is their job, in my most humblest of opinions.2 points
-
For those who want to block the vendor folder using ProcessWire's main htaccess file, here's a snippet: https://github.com/processwire/processwire-requests/issues/191#issuecomment-19692149841 point
-
1 point
-
Hi @*Most Powerful Pony!* what you are describing is indeed more complex and in such a situation you'd have to be more careful. But it's not really a drawback of RockMigrations in my opinion - it's a general team management issue just like any other merge conflicts. If I understood you correctly you are talking about a situation like this: - website X, v1.0 --- feature branch A - adds field_a v1.1a --- feature branch B - adds field_b v1.1b --- feature branch C - adds field_c v1.1c Now if anyone checks out A, then B, then C he'd had all three fields, yes. That can be a problem, I agree. The question is what you do to prevent such problems. In a classic approach you'd move back and revert migrations from branch A, then checkout B, then revert, then checkout C. But you can do the same with RockMigrations. You could for example make a DB dump of v1.0, work on branch A, then checkout B, do "rockshell db:restore" so you'd be on v1.0 and then after that restore RockShell will have applied your migrations and you'd be on v1.1b with only field_b (and no field a+c). What I'm usually doing is to have one single source of truth, which is usually the production system. Then I can do whatever I want in whatever branch and just do a "rockshell db:pull" and it will pull the production DB and apply my local migrations of my current branch. That way I also make sure that I don't get any bad surprises on deployment. But you could also use RockMigrations in a more classical way. @elabx is using it in combination with the older Migrations module, which takes care of executing migrations one by one and also provides a UI for rollbacks. That might make sense in a scenario like you are describing, still RockMigrations can be of great help for writing the migrations code itself. But don't forget that when going the classical route you basically double the development effort. Every change needs to have the corresponding rollback code as well. If that is a requirement, you can do it (even with RockMigrations). I just don't do it because I don't need it, because "rockshell db:dump" and "rockshell db:restore" is usually a lot faster than writing code for rollbacks (and not to forget test everything) ? I'm using DDEV and I'm checking in the DB into my repo. So checking out any commit in the history is "git checkout ... && ddev import-db -f dump.sql". That's it. But if you want to support RockMigrations I'd be happy to add support for classical workflows to RockMigrations or we can discuss any other cooperation to push ProcessWire forward on this topic ?1 point
-
So... I am everything but a gamer (ok, maybe Sonic on the Raspberry or something like that) but still... I always thought about buying TVs or Presentation Displays (64" 8K+ while super low prices) yet... I always remember something that's telling me: DONT DO IT! But I can't remember THAT THING. Something of refresh rates from input to output and combined with colors. Just asked our new friends from the AI section and I got this: So... I actually guess, based on that, it was the refresh rate. Most TVs only run 30/60hz and back then only a few 120hz. I don't know if this helps but... who knows.1 point
-
Thanks. It was one of the first ones I watched ?. I've watched at least a dozen, maybe more. I have watched some that are like a series...now, 6 months later, 2 years, later, etc! Some people have gone back to PC monitors, others have stuck it out, others have gone for smaller TVs, etc. Like you said, there's quite a lot of factors to take into account as well as end use of the thing. Gamers, for instance, seem to like the LG C series a lot.1 point
-
Obviously you should try and educate your client into the advantages of building in PW (and in the difficulties of designing a pixel perfect site that works across all browser and devices) but if they really insist on being able to fiddle then WebFlow is probably the kind of thing they want. Not a PW solution, but it does work well once you get the hang of it. We lost a client of 20 years to it last year ?1 point
-
Thank you @Stefanowitsch for mentioning RockPageBuilder! However, it appears that what they need might differ from what RockPageBuilder offers. @FireWire eloquently highlighted this distinction recently: So, RockPageBuilder is more about helping developers to build content elements quickly and easily. These blocks enable clients to populate their websites with content seamlessly, without the need to think too much about the technical and visual aspects (because this is our job as web professionals). It's less about designing and more about managing content, which is something I love about ProcessWire and where it really shines. In RockPageBuilder the design is done in code - CSS, Less, Tailwind, UIkit, Bootstrap. You can choose whatever you like best. If you want a no-code page designer there are plenty of options out there, but RockPageBuilder is likely not your first choice ?1 point
-
1 point
-
On the dev branch this week we have a good collection of issue fixes and feature requests. The dev branch commit log has all the details. One feature added this week which I think could come in very handy is #520 (via @Jonathan Lahijani) which adds the ability to hide individual images in an images field. When an image is hidden, you can see and work with it in the admin, but it gets removed from the field value on the front-end of the site at runtime, effectively hiding it. I know I'll use this a lot, particularly on photo galleries where I may want to remove an image or two from appearing in the grid of photos, but don't necessarily want to delete them. Images can be hidden (or unhidden) from the Actions select of each image, where you'll see a "Hide" option (or an "Unhide" option if the image is already hidden). Hidden images are also dimmed out when viewing the images field in the admin. On the API side, you can hide or unhide images and files using $image->hidden(true) to hide, $image->hidden(false) to unhide, and $image->hidden() to get a true or false as to whether or not the image is hidden. Though this will only be useful on unformatted field values, since hidden images are automatically removed from formatted field values. The same can be used with regular file fields, but we don't currently have a UI/interface for hiding or unhiding items from regular (non-image) file fields. Likely we'll add one soon, but I figured it's likely to get more use with image fields than file fields, so figured we'd start there. More next week. Thanks for reading and have a great weekend!1 point
-
I was browsing the requests repo and saw a request from @adrian that reminded me of a PW feature I had forgotten existed: from Page List you can open a page for editing in a modal window by long-clicking on the Edit button. This is quite handy for when you want to make a quick edit to a page. But as the request notes, it would speed things up if there was a "Save + Close" button in the modal. Until the request is actioned in the core I thought I'd try implementing it in some custom code, and it's also an opportunity to show an easy way you can add custom JS and CSS to the ProcessWire admin. The first step is to create the following files at /site/templates/admin-assets/admin-custom.js and /site/templates/admin-assets/admin-custom.css. The CSS is optional. admin-custom.js $(document).ready(function() { const $body = $('body'); const is_modal = $body.hasClass('modal') || $body.hasClass('pw-iframe'); if($body.hasClass('ProcessPageEdit') && is_modal) { const params = new URLSearchParams(window.location.search); const $save_button = $('#submit_save'); if(params.has('quick_edit') && $save_button.length) { $save_button.parent().append('<button type="submit" name="submit_save" value="Save" class="ui-button uk-hidden" id="save-and-close">Save + Close</button>'); } } if($body.hasClass('ProcessPageList') && !is_modal) { $(document).on('ajaxComplete', function() { $('.PageListActionEdit a:not([data-autoclose])').each(function() { $(this).attr('data-autoclose', '#save-and-close').attr('href', $(this).attr('href') + '&quick_edit=1'); }); }); } }); admin-custom.css /* Avoid Tracy debugbar appearing on top of modal */ .ui-widget-overlay.ui-front { z-index:40000; } .ui-dialog { z-index:40001; } /* Place modal buttons on the left rather than the right */ .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float:none; } The second step is to add the following hook to /site/ready.php One good thing about using a hook to AdminTheme::getExtraMarkup to add custom CSS is that the file gets loaded after any CSS files that are loaded by modules or the PW core, so you can override any CSS rules without needing to add extra specificity. // Add custom JS and CSS to admin $wire->addHookAfter('AdminTheme::getExtraMarkup', function(HookEvent $event) { $parts = $event->return; $config = $event->wire()->config; // JS file should exist at /site/templates/admin-assets/admin-custom.js $js_url = $config->urls->templates . 'admin-assets/admin-custom.js'; $modified = filemtime(rtrim($config->paths->root, '/') . $js_url); $parts['head'] .= "<script type='text/javascript' src='$js_url?m=$modified'></script>"; // CSS file should exist at /site/templates/admin-assets/admin-custom.css $css_url = $config->urls->templates . 'admin-assets/admin-custom.css'; $modified = filemtime(rtrim($config->paths->root, '/') . $css_url); $parts['head'] .= "<link rel='stylesheet' href='$css_url?m=$modified'>"; $event->return = $parts; }); The end result:1 point
-
Thx Robin! While the Save + Close button is there (as expected), the js part makes the edit links all open home page, eg. they all have the link /processwire/page/edit/?id=1&quick_edit=1 I fixed that with: const $links = $('.PageListActionEdit a:not([data-autoclose])'); $links.each(function() { $link = $(this); $link.attr('data-autoclose', '#save-and-close').attr('href', $link.attr('href') + '&quick_edit=1'); }); Just to mention that using uk-hidden class (as a "belt and suspender" approach) would only work in AdminThemeUIkit, leaving out newer (and older) admin themes.1 point
-
It's working reliably on a few sites I've tested on but what you're saying makes sense. So you could add the button with PHP in a hook and not in the JS as demonstrated below. I also had a thought that Page Edit might be opened in a modal in some other circumstances (I think ListerPro has an option for this) where the "Save + Close" button wouldn't work or wouldn't be wanted. So I've updated the code in the first post and in the code below so that a "quick_edit" URL parameter is added for identification purposes. admin-custom.js $(document).ready(function() { const $body = $('body'); const is_modal = $body.hasClass('modal') || $body.hasClass('pw-iframe'); if($body.hasClass('ProcessPageList') && !is_modal) { $(document).on('ajaxComplete', function() { $('.PageListActionEdit a:not([data-autoclose])').each(function() { $(this).attr('data-autoclose', '#save-and-close').attr('href', $(this).attr('href') + '&quick_edit=1'); }); }); } }); Additional hook for /site/ready.php $wire->addHookAfter('ProcessPageEdit::buildForm', function(HookEvent $event) { /* @var InputfieldWrapper $form */ $form = $event->return; // Return if Page Edit is not in a modal window if(!$event->wire()->config->modal) return; // Return if quick_edit GET parameter is not present if(!$this->wire()->input->get('quick_edit')) return; $save_button = $form->getChildByName('submit_save'); if(!$save_button) return; /** @var InputfieldSubmit $f */ $f = $event->wire()->modules->get('InputfieldSubmit'); $f->id = 'save-and-close'; $f->name = 'submit_save'; $f->value = 'Save'; $f->text = 'Save + Close'; $f->addClass('uk-hidden', 'wrapClass'); $form->insertAfter($f, $save_button); });1 point
-
It's not exactly the same technique, but I have just got into this rabbit hole and after a bit of blood sweat and tears and help from a pal, this is working for me while using ProCache and using the nonce attribute on scripts. This configuration assumes you have mod_substitute and mod_cspnonce installed. <If "%{THE_REQUEST} !~ m# /processwire/?#"> Options +Includes AddOutputFilterByType SUBSTITUTE;INCLUDES text/html Substitute "s|--CSP-NONCE--|<!--#echo var=\"CSP_NONCE\" -->|i" # Customize to your needs Header add Content-Security-Policy "default-src 'self' 'nonce-%{CSP_NONCE}e'; </If> Place this at the end of the ProcessWire htaccess directives. This should swap on the fly the Apache response and replace any --CSP-NONCE-- script. Then on Apache you can also set the nonce headers like this: I do not use this because my server setup uses nginx as reverse proxy. For example: <script nonce="--CSP-NONCE--" src="https://totally-safe-website.com"></script> Will end up as: <!-- nonce swapped on every request! --> <script nonce="0O4I3O5nNFG/MVpqormzyIuH" src="https://totally-safe-website.com"></script> @ryan fyi In theory, this would be A LOT simpler in Apache 2.5, since you could put an expression within the Substitute directive instead of the server side includes to substitute the "--CSP-NONCE--" script, but right now I'm limited to Apache 2.4 in the setup where I need this since I don't have control of the stack versions. So this should work in Apache 2.4+1 point
-
1 point
-
A few days ago I stumbled upon this old module, which had been laying in the modules directory of one of my sites since 2017 in a half-finished state. I have no recollection why I left it like that, but figured it might be useful for someone, so here we go: https://github.com/teppokoivula/Snippets https://processwire.com/modules/snippets/ Snippets is a tool for injecting front-end code snippets (HTML/JS/CSS) into page content. The way it works is that you create a snippet — say, a Google Analytics tag — and then choose... which element it should be tied to (there are some pre-populated choices and custom regex option), whether it should be placed before/after said element or replace it entirely, and which pages the snippet should apply to. The "apply to" option also has some ready to use options (such as "all pages" and "all non-admin pages") or you can select specific pages... or use a selector. Snippets are regular markup, with the exception that you can use values from current page (behind the scenes the module makes use of wirePopulateStringTags()). Available hooks: Snippets::isApplicable, which receives the snippet object and current Page object as arguments and returns a boolean (true/false). Snippets::applySnippet, which receives the snippet object, page content (string), variables (an object derived from WireData), and an array of options for wirePopulateStringTags() as arguments and returns the modified page content string. That's just about it. It's a pretty simple module, but perhaps someone will find this useful ?1 point