Jump to content
Kiwi Chris

How to handle multi-user multi-task scenario?

Recommended Posts

I have a site with the following structure:

User
-Orders
-Materials
User 2
-Orders
-Materials

...etc

I'm using AdminRestrictBranch module with custom PHP code, so that users when they log in, can only access their records.

return ($user->hasRole('client')) ? '/clients/'.strtolower($user->clientCode): '/';

So far so good...

Now I've been asked to add a new component in addition to the orders and materials, 'dispatch', however where this gets complicated, is I've been asked to separate this off and show it as a separate tab at the top (ie where Pages, Setup, Modules, Access etc go).

I know everything in Processwire is essentially a page, and Modules and Access have their own links as they are sub-pages of Admin, so I can create a new link up here OK.

The problem is with the default setup, you give access to one of these features or you don't.

What I need is to be able to do is assign all users with role 'client' access to certain functions, but ONLY let them edit, view and create their own records.

I can probably store the dispatch data under the user like I've done with Orders and Materials, but if so, I'll need to hide the page tree and create a separate dashboard so that I can have Orders and Materials under one heading, and Dispatch under another.

One option I've seen that I wonder whether might be helpful, is Lister Pro. I don't have the module yet, and I can't tell clearly enough from the module documentation whether it will help me achieve what I need. I definitely don't want people with 'client' role being able to change what pages to show in lists themselves, but I do need them to be able to see their own records, edit them, and add new ones.

Will Lister Pro help accomplish what I need, or are there other ways to achieve what I need, and importantly, what's likely to be the most efficient approach?

Share this post


Link to post
Share on other sites

@Kiwi Chris not sure I got all that but I had a scenario where what users could see depended on their roles, ie different data sets. I achieved this with RockFinder (now is RockFinder2). Maybe @bernhard can help?

  • Like 1

Share this post


Link to post
Share on other sites

Yes, perfect use case for RockFinder2 + RockTabulator - built exactly for situations like that.

Build a custom admin page, as simple as that (https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/ )

<?php
// ...
  public function execute() {
    $this->headline("Demo");
    $this->browserTitle("Demo");
    /** @var InputfieldForm $form */
    $form = $this->modules->get('InputfieldForm');

    $form->add([
      'type' => 'RockTabulator',
      'name' => 'yourlist',
      'label' => 'Yourlist Label',
    ]);

    return $form->render();
  }

Set the data:

<?php namespace ProcessWire;

// set role that is allowed to access this tabulator
$grid->access = 'your-role';

// set selector to find pages to show
$selector = ['template' => 'yourtemplate'];
if(!$this->user->isSuperuser()) {
  $selector['created_users_id'] = $this->user;
}

// setup finder
$rf = new RockFinder2();
$rf->find($selector);

// add columns to show
$rf->addColumns(['title', 'foo', 'bar']);

// setup grid and return it
$grid->setData($rf);
return $grid;

Then a hook to prevent page edit of pages that where not created by the user (I think there's even a module for that) and some custom JS + PHP and you have exactly what you need.

Just clone the repo at https://github.com/BernhardBaumrock/tabulator.test and see the examples 🙂 

  • Like 3

Share this post


Link to post
Share on other sites
11 hours ago, bernhard said:

Yes, perfect use case for RockFinder2 + RockTabulator - built exactly for situations like that.

Build a custom admin page, as simple as that (https://processwire.com/talk/topic/17709-how-to-create-custom-admin-pages-aka-processmodules-yes-its-that-simple/😞

 

Thanks. I've already used your tutorial on building custom admin pages and found it really helpful.

Rockfinder2 + RockTabulator are new to me, but it looks like they'll do what I want.

  • Like 1

Share this post


Link to post
Share on other sites
17 hours ago, Kiwi Chris said:

Rockfinder2 + RockTabulator are new to me, but it looks like they'll do what I want.

They CAN certainly do. But it's not plug&play, it will need some more or less simple coding 🙂 

Share this post


Link to post
Share on other sites
On 10/16/2019 at 3:09 AM, bernhard said:

They CAN certainly do. But it's not plug&play, it will need some more or less simple coding 🙂 

I'm getting there... The order of installation turns out to be fairly important: RockMarkup2 then RockTabulator then RockFinder2

I've got them all installed ok, but I'm getting the following error:

Call to undefined method stdClass::setData() in RockFinder2

on this line:

$grid->setData($rf);

Also I get a :

PHP Warning: Creating default object from empty value in 

when I save in the sandbox

I'm running PHP 7.2

Share this post


Link to post
Share on other sites
6 hours ago, Kiwi Chris said:

Call to undefined method stdClass::setData() in RockFinder2

$grid must be a RockTabulatorGrid object, not RockFinder2. It seems that your code is wrong.

7 hours ago, Kiwi Chris said:

I'm getting there... The order of installation turns out to be fairly important: RockMarkup2 then RockTabulator then RockFinder2

Thx, I've pushed a fix for this 🙂 

  • Like 1

Share this post


Link to post
Share on other sites
On 10/14/2019 at 3:01 AM, Kiwi Chris said:

What I need is to be able to do is assign all users with role 'client' access to certain functions, but ONLY let them edit, view and create their own records.

 

Under permissions is a setting where you can archive that users can only edit their own created pages. Like I answered here: 

 

To prevent page editing and listing pages in a normal lister or ListerPro I use hooks (this can be made in a custom module or in _init.php):

$this->addHookAfter('ProcessPageListActions::getActions', $this, 'restrictListerEditAccess');
$this->addHookAfter('ProcessPageEdit::buildForm', $this, 'removeTabs');
$this->addHookAfter('ProcessPageEdit::buildForm', $this, 'restrictEditAccess');
 
public function restrictEditAccess(HookEvent $event)
  {
    // don't do this for superusers
    if ($this->user->isSuperuser()) {
      return;
    }
    if ($this->config->ajax) {
      return;
    }
//    bd($event->return);
    $process = $event->object;
    $page = $process->getPage();
    $form = $event->return;
if ($condition !== true) {
        $this->error("Thou shall not pass");
        //$this->removeSaveButton($form);
        return;
      }
}

  /**
   * removes edit links from lister it the user has not the correct edit access
   * @param HookEvent $event
   * @throws WireException
   */
  public function restrictListerEditAccess(HookEvent $event)
  {
    if ($this->user->isSuperuser()) {
      return;
    }
    $page = $event->arguments[0];

    $editAccess = $this->hasEditAccess($page); // this is my own function for checking if the user has edit access, in the core there is $page->editable()
    if ($editAccess === false || $this->user->hasRole('someRole')) {
      $actions = $event->return;
      unset($actions['edit']);
      $event->return = $actions;
    }
  }

 /**
   * removes tabs in Edit form for specific roles
   * @param HookEvent $event
   */
  public function removeTabs(HookEvent $event)
  {
    if ($this->user->isSuperuser()) return;

    $p = $event->object->getPage();
    $form = $event->return;
//    bd($form);
    $fieldset = $form->find("id=ProcessPageEditChildren")->first();
    if (is_object($fieldset)) {
      $form->remove($fieldset);
      $event->object->removeTab('ProcessPageEditChildren');
    }

    $fieldset = $form->find("id=ProcessPageEditSettings")->first();
    if (is_object($fieldset)) {
      $form->remove($fieldset);
      $event->object->removeTab('ProcessPageEditSettings');
    }

   
      $fieldset = $form->find("id=ProcessPageEditDelete")->first();
      if (is_object($fieldset)) {
        $form->remove($fieldset);
        $event->object->removeTab('ProcessPageEditDelete');
      }
    

   
      // hide delete tab
      $fieldset = $form->find("id=ProcessPageEditDelete")->first();
      if (is_object($fieldset)) {
        $form->remove($fieldset);
        $event->object->removeTab('ProcessPageEditDelete');
      }
    
  }

 

  • Like 1

Share this post


Link to post
Share on other sites
13 hours ago, bernhard said:

$grid must be a RockTabulatorGrid object, not RockFinder2. It seems that your code is wrong.

Oops! I copied and pasted from the example you gave a few posts back. That will teach me for just copying without trying to understand the code. 😉

I realise RockFinder and RockGrid are still works in progress, and full documentation is coming. 🙂

Another issue I've struck is I get the following error in the RF2 sandbox: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'bottlingco_pw.field_stockCode' doesn't exist

(field is added via $rf->addColumns)

If I change the field name to all lower case (stockcode), I get no error, but RockTabulator just shows 'Field not found' in the sandbox RockTabulator.

It seems as though RockFinder is not translating a Processwire field name with an uppercase character in it into lowercase for the SQL query.

Share this post


Link to post
Share on other sites
6 hours ago, Kiwi Chris said:

I realise RockFinder and RockGrid are still works in progress, and full documentation is coming.

Not sure when/if full documentation will be coming... Best is to learn by examples: https://github.com/BernhardBaumrock/tabulator.test

6 hours ago, Kiwi Chris said:

If I change the field name to all lower case (stockcode), I get no error, but RockTabulator just shows 'Field not found' in the sandbox RockTabulator.

Yeah, it only supports lowercase fields. I can remember I had issues with uppercase letters from time to time, so I'm using 100% lowercase fieldnames since then. Maybe you want to file a detailed reproducable issue on github what is not working and how it should work? Maybe I find time some day to check it. Otherwise just use lowercase names for fields 🙂 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...