Jump to content

Admin modal in front end


MarkE
 Share

Recommended Posts

This post is related to 

but is a different way of tackling the problem.

The idea is to use the JqueryUI.module in the front end to present a restricted access admin page in a modal (class pw-modal). However the JqueryUI module doesn't seem to work properly in the front end (I have it working in the back end OK). I'm guessing that this is because the front end page has not loaded all the .js that is needed (that would normally be loaded in the back end). My _main.php loads the following from the core at the moment:

'wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/js/uikit.min.js'
'wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/js/uikit-icons.min.js'
'wire/modules/Jquery/JqueryCore/JqueryCore.js'
'wire/modules/Jquery/JqueryUI/JqueryUI.js'

Any ideas what else I need, or have I got hold of the wrong end of the stick?

Link to comment
Share on other sites

 

1 hour ago, bernhard said:

Am I the only one preferring panels a LOT over modals? 😐 

Maybe, maybe not. If I could do an admin panel in the front end then I might be able to have an opinion 😉

 

Link to comment
Share on other sites

9 hours ago, MarkE said:

But the iPad scrolling issue still persists

Actually this seems to be a problem with the admin theme generally - for example, the tree panel in the uikit theme does not scroll on an iPad either. So looks like a bug. 

Link to comment
Share on other sites

If you load an admin page in a modal or panel from the front-end then there's not really any special PW magic there - it's just an iframe. So you don't have to use a JqueryUI modal or panel just because the PW admin does - you can use any JS modal library that supports iframes. There are a bazillion out there so there's bound to be something that doesn't cause this scrolling issue you're describing.

BTW I can confirm the tree panel scrolling issue on iPad - please do report it.

  • Like 1
Link to comment
Share on other sites

@Robin S there are lots of modal libraries, but the only reliable that I've found for including admin pages (iframes, html content, videos etc) in a modal is http://fancyapps.com/fancybox/3/ (and maybe magnific popup).

What I've not found is a library that makes it easy to create panels just like the pw admin does. Where one can simply add class="pw-panel" and it loads in an iframe, sliding in from left or right, being resizable, hideable, reloadable etc...

  • Like 1
Link to comment
Share on other sites

26 minutes ago, Robin S said:

use any JS modal library that supports iframes

Parallel to the approach I described above, I have also tried uikit's modal with an embedded iframe. This works adequately (and fixes the iPad issue with uk-overflow-auto), but there are a couple of snags - no doubt due to my incompetence:

  1. I can't work out how to make the modal/iframe height match the height of the embedded admin page - I can set the iframe width to 100%, but have to set a "hard" pixel height of, say 800, which may then leave whitespace for a small page.
  2. Because the target page for the iframe can vary (a range of pages may be edited), multiple modals/iframes are created via a loop (with toggle ids keyed to page ids). These then take  about 15-20 seconds to load, which is not really acceptable. No doubt there is some clever way of avoiding this using jQuery, but I haven't worked it out yet.

I will try some of the other suggestions as well. I also tried using the FEEL module, but that has the iPad problem too - see 

As mentioned there, I am not able to debug an iPad because I don't have a Mac. Similarly, @bernhard, I have no idea how to do a screencast on an iPad, but I can report the bug with a text description.

 

Link to comment
Share on other sites

2 hours ago, webhoes said:

did you get this working without giving user page-edit rights?

Obviously the user needs page-edit rights for the page in question. My approach to this was to write a hook after User::hasPagePermission which only gives them page-edit / page-add permission for the specific pages to which they are allowed access (i.e. in my app, their own membership records). If they try and access any other pages (e.g. directly in a browser, assuming they know the page-id or name, as the page in fancybox has modal=1, so no menu), they get a "You don't have access to edit" message.

Link to comment
Share on other sites

The pageload is about 3 seconds, but the hook doesn't seem to affect it. Because fancybox loads almost instantly and displays a rotating wheel, I don't think the wait is a problem.

48 minutes ago, webhoes said:

Do you give the user temporarily page-edits upon granted request of that page?

The module checks page-editable before rendering. The hook then adds the permission.

Link to comment
Share on other sites

Interesting. Are you willing to share you module? I have not been able to get a secure setup myself.

The pageload in my case is my security setup. I check for referenced users from a parent page or parent parent page. This is really time consuming.

Link to comment
Share on other sites

The module can be found at https://github.com/MetaTunes/AdminInModal

Use at your own risk!

The hook is specific to my app, but I hope the following gives the general idea:

wire()->addHookAfter('User::hasPagePermission', function(HookEvent $event) {
    // Get the object the event occurred on, if needed
    $user = $event->object;

    // An 'after' hook can retrieve and/or modify the return value
    $return = $event->return;

    // Get values of arguments sent to hook (if needed)
    $permission = $event->arguments(0);
    $p = $event->arguments(1);

    /* Your code here, perhaps modifying the return value */
    // Is it a page we need to customise access for?
    $templates = ['Membership', 'Member', 'Profile', 'Subscription', 'Payment', 'MemberShop', 'Booking', 'NewsItem'];
    $permissions = ['page-edit', 'page-add'];
    if ($p and in_array($p->template, $templates) and $permission and in_array($permission, $permissions)) {
        // Get the member-user
        $currentUser = $this->users->getCurrentUser();
        if ($currentUser and $currentUser->isLoggedin()) {
            if ($currentUser->hasRole('member')) {
                $email = $currentUser->email;
                $memberPage = $this->pages->get("has_parent=/memberships/, template=Member, email=$email");
                if ($currentUser->memberOnly) $return = false; // Member-only users can only access pages as defined below
                if ($memberPage->id) {
                    $membershipPage = $memberPage->parent;
                    //... and a lot more like that ($profilePage etc.) ...
                    $editablePages = new PageArray();
                    $addablePages = new PageArray();
                    $editablePages = $editablePages->add($membershipPage)->add($profilePage)->add($siblings)->add($currentSub)->add($shops)->add($subsPaymentPages)->add($draftNewsPages)->add($bookingPages);
                    $addablePages = $addablePages->add($membershipPage)->add($memberPage);  // pages where creation of children is allowed
                    if ($editablePages->has($p) and $permission == 'page-edit') $return = true;
                    if ($addablePages->has($p) and $permission == 'page-add') $return = true;
                }
            }
        }
    }

    // Populate back return value, if you have modified it
    $event->return = $return;
});

 

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Similar Content

    • By Rezvitskyq
      Hello! There was a need to rewrite the code written with jquery into vanilla js. I have little js code on my site and I see no reason to include a library such as jquery 🙂
      $('.progress-wrap .dot').on('click', function () { let $this = $(this) let stepValue = $this.attr('data-step') $this.closest('.progress-wrap').find('.bar').css('width', stepValue + '%') $this.siblings('.dot').removeClass('is-current') $this.addClass('is-active is-current') $this.prevAll('.dot').addClass('is-active') $this.nextAll('.dot').removeClass('is-active') $('.process-panel-wrap').removeClass('is-active') $('.step-title').removeClass('is-active') if (stepValue === '0') { $('#signup-panel-1, #step-title-1').addClass('is-active') } else if (stepValue === '25') { $('#signup-panel-2, #step-title-2').addClass('is-active') } else if (stepValue === '50') { $('#signup-panel-3, #step-title-3').addClass('is-active') } else if (stepValue === '75') { $('#signup-panel-4, #step-title-4').addClass('is-active') } else if (stepValue === '100') { $('#signup-panel-5, #step-title-5').addClass('is-active') } })  
    • By Majesrse
      Hey i have a problem with the code:
      $('a').click(function(link) { link.preventDefault(); location = this.href; $('body').fadeOut('slow', open); }); function more() { window.location = location; } It's writen in Jquery but i will convert it to vanilla js. Can somone help me with it?
    • By eschoonen
      I'm working on the threaded comments on my website and for this I need to include the comments.js
      When I do this it keeps on giving me the "Uncaught ReferenceRrror: jQuery is not defined". Whatever I do it keeps giving me this error message.
      It's the last javascript file that I load in. So how do I fix it?
    • By awebcreature
      Hello there
      I need a field with realtime percent calculation (without page save)  with values from other fields in admin template. I think about jQuery with onChange methods on corresponding fields but this is not clear for me how to do this in module. Any help with some advice or example will be highly appreciated! 
      Thanks in advance! 
       
    • By Matze
      Hi there,
      I'm trying to get to work some AJAX call with vanilla Javascript, not jQuery.
      Anything seems to work so far, but the !$config->ajax seems to be ignored.
      To find out whats the problem by comparing both, jquery and plain javascipt, i built this template. commenting out //loadJquery(''); or loadVanilla(''); switches the two variants. (empty url variable means that the same pages will be loaded.)
      The problem: the pure Javascript function ("loadVanilla") is loading the full page content into the dc-container, which is wrong. The jQuery function  ("loadJquery") only loads the part outside of the if(!$config->ajax): - which is as it should be. 
      So - any help with this, what am i doing wrong?

      Thanks a lot - Matze
      <?php namespace ProcessWire; if(!$config->ajax): ?> (some static content)<br> <a id="loadlink" href="#">load</a><br> <?php endif; // end if not ajax ?> <span id="dc-container">(dynamic content)</span> <?php if(!$config->ajax): ?> <script src="http://code.jquery.com/jquery-3.3.1.min.js"></script> <script> var loadlink = document.getElementById('loadlink'); loadlink.addEventListener('click', function(event) {   //loadJquery('');   loadVanilla('');   event.preventDefault() }); function loadVanilla(url) {   var xhttp = new XMLHttpRequest();   xhttp.onreadystatechange = function() {     if (this.readyState == 4 && this.status == 200) {       document.getElementById("dc-container").innerHTML = 'loaded: ' + this.responseText + (' (by vanilla javascript)');     }   };   xhttp.open("POST", "", true);   xhttp.send(); }   function loadJquery(url){ // Load content   $.ajax({       type: "POST",       url: url,       data: { ajax: true },       success: function(data,status){         pageData = data;       }   }).done(function(){ // when finished and successful     document.getElementById("dc-container").innerHTML = 'loaded: ' + pageData + ' (by jquery ajax)';   }); } </script> <?php endif; // end if not ajax ?>  
×
×
  • Create New...