2

I am using Kartik Tree Manager. I am able to add, remove, update nodes. There is more requirement, that is to show/hide nodes on the basis of user access. i.e. when a user is given a specific node(s) then only that particular node(s) with all the child (if any) should be shown.

What I have done so far?

I have created a table user-node in which I am assigning a node id to a user as shown below

enter image description here

What I want to do

Now I want to show only the specified node with its child node only and hide other nodes to that user

enter image description here

Controller

For now, there are two views in which I am rendering the tree structure but in the future, there shall be more

  1. My front page

    public function actionIndex()
    {
       if(Yii::$app->user->isGuest){
        $this->redirect(Yii::$app->urlManager->createUrl('site/login'));
        }
       return $this->render('index');
    }
    
  2. Itself tree-manager node controller

    /**
    * View, create, or update a tree node via ajax
    *
    * @return mixed json encoded response
    */
    public function actionManage()
    {
        static::checkValidRequest();
        $data = static::getPostData();
        $nodeTitles = TreeSecurity::getNodeTitles($data);
        $callback = function () use ($data, $nodeTitles) {
        $id = ArrayHelper::getValue($data, 'id', null);
        $parentKey = ArrayHelper::getValue($data, 'parentKey', '');
        $parsedData = TreeSecurity::parseManageData($data);
        $out = $parsedData['out'];
        $oldHash = $parsedData['oldHash'];
        $newHash = $parsedData['newHash'];
        /**
         * @var Module $module
         * @var Tree $treeClass
         * @var Tree $node
         */
        $treeClass = $out['treeClass'];
        if (!isset($id) || empty($id)) {
            $node = new $treeClass;
            $node->initDefaults();
        } else {
            $node = $treeClass::findOne($id);
        }
        $module = TreeView::module();
        $params = $module->treeStructure + $module->dataStructure + [
                'node' => $node,
                'parentKey' => $parentKey,
                'treeManageHash' => $newHash,
                'treeRemoveHash' => ArrayHelper::getValue($data, 'treeRemoveHash', ''),
                'treeMoveHash' => ArrayHelper::getValue($data, 'treeMoveHash', ''),
            ] + $out;
        if (!empty($data['nodeViewParams'])) {
            $params = ArrayHelper::merge($params, unserialize($data['nodeViewParams']));
        }
        if (!empty($module->unsetAjaxBundles)) {
            $cb = function ($e) use ($module) {
                foreach ($module->unsetAjaxBundles as $bundle) {
                    unset($e->sender->assetBundles[$bundle]);
                }
            };
            Event::on(View::class, View::EVENT_AFTER_RENDER, $cb);
        }
        TreeSecurity::checkSignature('manage', $oldHash, $newHash);
        return $this->renderAjax($out['nodeView'], ['params' => $params]);
    };
    return self::process(
        $callback,
        Yii::t('kvtree', 'Error while viewing the {node}. Please try again later.', $nodeTitles),
        null
    );
    }
    

How can I achieve it? Any help would be highly appreciated.

Moeez
  • 494
  • 9
  • 55
  • 147
  • 1
    You can override the `isVisible` method within the tree model to show the node selectively for the current user or anything based on your custom condition. For more information please read [Model Methods](https://demos.krajee.com/tree-manager#model-methods) – Moeez Jun 29 '20 at 17:35

1 Answers1

0

One way to achieve hide/show some nodes may be as follows:

  • In views you should have your db table names.

  • Look for the table name you are interested in.

  • Inside the folder of the table name there should be files names something like: _form.php, _script.php and index.php

  • The index.php file should have some use among of which there should be: ...

    use kartik\tree\TreeView;

    use kartik\tree\Module;

...

  • After these use statements, you can add this code:

    /** @var integer $uid */

      // get current logged in user id.
    
      // this is used to control showing tree content, and
    
      // to control form fields.
    
      if (isset(Yii::$app->user)) {
          $uid = Yii::$app->user->getId();
      }
    
  • So now the logged in user id is saved in variable $uid

  • In the same index.php file you should have code that renders the tree view. Something starts with: echo TreeView::widget

  • Inside this TreeView::widget([.. you can add a query that renders only current logged in user content, like this:

    'query' => YourTableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'),

... Other settings ...

If you want the admin(s) to see or change the content, you can add a Controller for example named AdminController, then in this index.php TreeView::widget you can add more options like this:

echo TreeView::widget([

    'query' => YourTableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'),

    'headingOptions' => ['label' => 'YourLableName'],

    //'rootOptions' => ['label' => '<span class="text-success">Root</span>'],

    'fontAwesome' => false,

    'isAdmin' => true,

    'showInactive' => AdminController::isAdmin(),

    'displayValue' => 0,

    'showIDAttribute' => true,

    'emptyNodeMsg' => ' type some msg here ... .',

    'showCheckbox' => false,

    'multiple' => false,

    'options' => ['id' => 'treeID'],

    'allowNewRoots' => false,

    'toolbar' => [
    'create' => ['alwaysDisabled' => true],
    //'remove' => ['alwaysDisabled' => !(AdminController::isAdmin())],
    // 'move-up' => ['alwaysDisabled' => !(AdminController::isAdmin())],
    // 'move-down' => ['alwaysDisabled' => !(AdminController::isAdmin())],
    // 'move-left' => ['alwaysDisabled' => !(AdminController::isAdmin())],
    // 'move-right' => ['alwaysDisabled' => !(AdminController::isAdmin())],
    //'remove' => false,
    ],

    'cascadeSelectChildren' => false,

    //'softDelete' => false,

    'iconEditSettings'=> [
    'show'      => 'list',
    'listData'  => [
    // 'folder' => 'Folder',
    'file' => 'File',
    'star' => 'Star',
    'bell' => 'Bell',
    // 'phone' => 'Phone',
    ]
],

'cacheSettings' => ['enableCache' => true],

'nodeAddlViews' => [
    Module::VIEW_PART_1 => '@app/views/mappings/_form',
    ],
]);
  • This is just a small start, but you can take it further. For example suppose the user is not logged in or suppose you want to show some nodes any way. In these cases you can use switch case statement and check for example if $uid is not defined (it is not set because the user is not logged in) in this case, you can ask the user to log in or render or show a different tree view:

    switch ($SomeVariable) { case "case_to_check": echo TreeView::widget([ ... 'query' => TableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'), ... break;
    case "another_case": echo TreeView::widget([ ... break; default: echo TreeView::widget([ ...

== You can also add html select at the top of index.php, something like this:

<select name="Give_any_name_you_like" size=1 class="btn btn-primary" style="margin-bottom: 0.5em; margin-left: 0.5em; ">
<option value="0">Select Node</option>
<option value="1">mynodes</option>
<option value="2">othernodes</option>
<option value="3">allnodes</option>
</select>

then use java script to filter and capture the selected value, then you can use this vale in switch case to show certain nodes. You can place the java script code inside <?php block and before switch case or echo TreeView::widget([ . java script code may look something like this:

$this->registerJs("
$('select[name=" . "The_name_you_give_in_select" . "]').change(function(){     
var value = $(this).val();                    
switch(value) {
case '1':
window.location.href = \"your-page-name?what=mynodes\" ; 
break;
case '2':
window.location.href = \"your-page-name?what=othernodes\" ;
break;        
default:
window.location.href = \"your-page-name?what=allnodes\" ;
}   

});", View::POS_READY); 

=== Then you check for the value of what in switch cases and use it to filter which tree node to show. Something like this code just below above java script code:

/** @var integer $The_name_you_give_in_select */
// get value from selection menu.
// this is used to filter and show desired tree.
if (isset($_GET['what'])) {
$The_name_you_give_in_select = $_GET['what'];
} else {
$The_name_you_give_in_select = "defaultcase";
}     
// Then in switch case:     
switch ($The_name_you_give_in_select) {
case "mynodes":
echo TreeView::widget([
...
break;
Case "othernodes":
echo TreeView::widget([
...
break;
default:
echo TreeView::widget([
...

============= === Also you may want to do some changes in views/your_table_name/_form.php

  • In _form.php you can also control what fields to show, what fields to make editable or read only, etc. something like this: == _form.php:

    ... /** @var integer $userid */

      // save current node user id in var $userid
    
      // to be used to control form fields
    
      $userid = $node->user_id;
    
      ...
    
      if(isset($userid)){
      $username = Yii::$app->user->identity;
      }
    
      ...
    
      <div class="your-form">
      ...
      <?= $form->field($node, 'annotation')->textarea(['rows' => 6, 'readonly' => !(Yii::$app->user->identity->id == $userid or AdminController::isAdmin())]) ?>
    
      <?= $form->field($node, 'comments')->textarea(['rows' => 6, 'readonly' => !(Yii::$app->user->identity->id == $userid or AdminController::isAdmin())]) ?>
    
      <!--   <?/*= $form->field($username, 'username')->textInput(['maxlength' => true, 'readonly'=>true])->label('Created by User') */?>-->
    
      <?= $form->field($node, 'user_id')->textInput(['readonly'=>true]) ?>
    
      <?= $form->field($node, 'date_added')->textInput(['placeholder' => 'Date Added', 'readonly'=>true]) ?>
    
      </div>
    

========= === The AdminContoler.php may look something like this:

<?php
namespace app\controllers;
use Yii;
...
class AdminController extends Controller
{

/**
*
* manage admins.
* add admins here
* this will allow admins more control on all tables, but not accessing and managing users
* controlling, accessing and managing users is configured through:
* - config/web.php and views/layouts/main.php
*  - (1) in config/web.php go to modules -> user -> admins and add username(s)that you want to be admin accessing and managing users
*  - (2) THEN in view views/layouts/main.php, follow the same logic in line 62 and add username(s).
*
* @return bool
*/
public static function isAdmin()
{
if (
Yii::$app->user->identity->username == 'type user name here'
or
Yii::$app->user->identity->username == 'type user name here'

// add more here for example by uncommenting the following lines and typing username that you want to be admin

// or
// Yii::$app->user->identity->username == 'type user name here'

// or
// Yii::$app->user->identity->username == 'type user name here'

// or
// Yii::$app->user->identity->username == 'type user name here'
) {
return true;
} else {
return false;
}
}
}
Miloud Eloumri
  • 779
  • 1
  • 8
  • 14
  • There will be more than one user who has access to view them the same node(s). For example, the admin can view all nodes. Also at each child node, there is a custome_id which Is unique for each customer – Moeez Jul 03 '20 at 10:29
  • You can use the mentioned AdminControl way to include admins or users that you want them to see or edit all nodes. Also you can use custome_id in _form.php fields to show to certian custome_id users or you can modify the 'query' => ... where clause and include your custome_id. You can check these links on query building: https://www.yiiframework.com/doc/guide/2.0/en/db-query-builder – Miloud Eloumri Jul 04 '20 at 14:26
  • Especially how to include multiple where clauses: https://forum.yiiframework.com/t/using-find-in-active-record-with-multiple-where-clause/77997 – Miloud Eloumri Jul 04 '20 at 14:40
  • Right now I don't have `user_id` in my `tree` table. Let's say I put it, then it means that one node will only be visible to only one user and cannot be set to another one. – Moeez Jul 13 '20 at 09:50
  • Also, I want to check the child nodes of the selected node. For example, a user is given access to `Floor-1` so all the child of the floor should also be visible – Moeez Jul 13 '20 at 09:56
  • I have tried your 1st way by doing `YourTableName::find()->where(['user_id' => $uid])->addOrderBy('root, lft'),`. I only shows me the node to which `user_id` is attached but not the child nodes. – Moeez Aug 05 '20 at 06:11
  • Please check the following link and see if you are aiming to accomplish same or similar functionality. I created it around 3 years ago. You can create your account, then add your nodes and see how adding nodes and child nodes work as well what you can see, control and edit. This is the link: https://www.btm-forum.org/bok-mapping/ I created the functionality using Kartik Tree Manager (https://demos.krajee.com/tree-manager) following among others the same steps or scenario on my previous posts on this thread. – Miloud Eloumri Aug 25 '20 at 18:37
  • @MiloudEloumri I have checked your provided link. You have done a good work. What widget you use for creating the flow diagram? After looking into the link provided by you. I am assuming that you have created new tree behind every square? And every tree has a separate view. My case is different. I have only single tree and want different view on every node click. – Faisal Qayyum Aug 27 '20 at 04:24
  • The flow diagram is just an image with boxes representing pages in the website. You can consider it as a navigation menu. The use of such image is just to show how to use the website, its functionality and purpose but it could be represented just like a vertical or horizontal navigation menu. You can use image map to create something similar. Check e.g.: https://www.w3schools.com/html/html_images_imagemap.asp and https://www.image-map.net/ – Miloud Eloumri Aug 29 '20 at 22:19
  • I used one Kartik Tree Manager setup and config, and then of course each box in the image (representing a page) has its own tree display or view depending on its purpose. – Miloud Eloumri Aug 29 '20 at 22:19