From f8c85edff6fbb94dc5fe7075b184c3c60120ec68 Mon Sep 17 00:00:00 2001
From: Mingsong Hu <mingsonghu@Mingsongs-MBP.gateway>
Date: Fri, 27 Sep 2019 15:28:48 +1000
Subject: [PATCH] New feature: Display profile configuration

---
 config/schema/hm_display_profile.schema.yml   |  3 ++
 hierarchy_manager.libraries.yml               | 33 +++++++++++++++-
 hierarchy_manager.module                      | 10 +++++
 js/Plugin/jsoneditor/hm.jsoneditor.js         | 39 +++++++++++++++++++
 js/Plugin/jstree/hm.jstree.js                 |  3 +-
 src/Entity/HmDisplayProfile.php               |  9 ++++-
 src/Form/HmDisplayProfileForm.php             | 35 +++++++++++++++++
 src/Form/HmOverviewTerms.php                  |  9 ++++-
 .../HmDisplayPlugin/HmDisplayJstree.php       | 20 +++++++++-
 9 files changed, 154 insertions(+), 7 deletions(-)
 create mode 100644 js/Plugin/jsoneditor/hm.jsoneditor.js

diff --git a/config/schema/hm_display_profile.schema.yml b/config/schema/hm_display_profile.schema.yml
index 3de599e..6f91e0f 100644
--- a/config/schema/hm_display_profile.schema.yml
+++ b/config/schema/hm_display_profile.schema.yml
@@ -13,3 +13,6 @@ hierarchy_manager.hm_display_profile.*:
     plugin:
       type: string
       label: 'Display plugin'
+    config:
+      type: text
+      label: 'Configuration'
diff --git a/hierarchy_manager.libraries.yml b/hierarchy_manager.libraries.yml
index fae9dc7..a160505 100644
--- a/hierarchy_manager.libraries.yml
+++ b/hierarchy_manager.libraries.yml
@@ -6,6 +6,12 @@ feature.hm.jstree:
   dependencies:
     - hierarchy_manager/libraries.jquery.jstree
     - core/drupalSettings
+    
+feature.hm.jsoneditor:
+  js:
+    js/Plugin/jsoneditor/hm.jsoneditor.js: {}
+  dependencies:
+    - hierarchy_manager/libraries.jsoneditor
 
 # External libraries.
 
@@ -47,4 +53,29 @@ libraries.jquery.jstree.default-dark:
     https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.8/themes/default-dark/
   css:
     component:
-      /libraries/jquery.jstree/3.3.8/themes/default-dark/style.min.css: {}
\ No newline at end of file
+      /libraries/jquery.jstree/3.3.8/themes/default-dark/style.min.css: {}
+      
+libraries.jsoneditor:
+  remote: https://github.com/josdejong/jsoneditor
+  version: '7.0.4'
+  license:
+    name: Apache License 2.0
+    url: https://github.com/josdejong/jsoneditor/blob/develop/LICENSE
+    gpl-compatible: true
+  cdn:
+    https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/7.0.4/
+  js:
+    /libraries/jsoneditor/7.0.4/jsoneditor.min.js: {minified: true}
+    
+libraries.jsoneditor.default-theme:
+  remote: https://github.com/josdejong/jsoneditor
+  version: '7.0.4'
+  license:
+    name: Apache License 2.0
+    url: https://github.com/josdejong/jsoneditor/blob/develop/LICENSE
+    gpl-compatible: true
+  cdn:
+    https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/7.0.4/
+  css:
+    component:
+      /libraries/jsoneditor/7.0.4/jsoneditor.min.css: {minified: true}
\ No newline at end of file
diff --git a/hierarchy_manager.module b/hierarchy_manager.module
index 574aece..f27abfb 100644
--- a/hierarchy_manager.module
+++ b/hierarchy_manager.module
@@ -26,6 +26,16 @@ function hierarchy_manager_library_info_alter(array &$libraries, $module) {
     if ($cdn_library) {
       $libraries['libraries.jquery.jstree.default-dark']['css']['component'] = $cdn_library;
     }
+    // jsoneditor min js.
+    $cdn_library = _hierarchy_manager_use_cdn($libraries, 'libraries.jsoneditor', 'js');
+    if ($cdn_library) {
+      $libraries['libraries.jsoneditor']['js'] = $cdn_library;
+    }
+    // jsoneditor default theme.
+    $cdn_library = _hierarchy_manager_use_cdn($libraries, 'libraries.jsoneditor.default-theme', 'css');
+    if ($cdn_library) {
+      $libraries['libraries.jsoneditor.default-theme']['css']['component'] = $cdn_library;
+    }
   }
 }
 
diff --git a/js/Plugin/jsoneditor/hm.jsoneditor.js b/js/Plugin/jsoneditor/hm.jsoneditor.js
new file mode 100644
index 0000000..cf87329
--- /dev/null
+++ b/js/Plugin/jsoneditor/hm.jsoneditor.js
@@ -0,0 +1,39 @@
+// Codes just run once the DOM has loaded.
+// @See https://www.drupal.org/docs/8/api/javascript-api/javascript-api-overview
+(function($) {
+  const editorID = "json-editor";
+  const valueID = "config-value";
+  var container = document.getElementById(editorID);
+  var data = {};
+  var options = {
+      mode: "tree",
+      modes: ['code', 'tree'], // allowed modes
+      name: "Configuration",
+  };
+  
+  // json hidden element
+  var jsonInput = document.getElementById(valueID);
+  //json data
+  if (jsonInput && jsonInput.value) {
+    data = JSON.parse(jsonInput.value);
+  }
+  
+  var editor = new JSONEditor(container, options, data);
+  
+  editor.setName('Configuration');
+  
+  //The input form.
+  var form = jsonInput.form;
+  
+  var submit = function(e) {
+    jsonInput.value = JSON.stringify(editor.get());
+  };
+  
+  // Form submit event.
+  if(form.addEventListener){
+    form.addEventListener("submit", submit);  //Modern browsers
+  }else if(ele.attachEvent){
+    form.attachEvent('onsubmit', submit);            //Old IE
+  }
+  
+})(jQuery);
\ No newline at end of file
diff --git a/js/Plugin/jstree/hm.jstree.js b/js/Plugin/jstree/hm.jstree.js
index 62eea15..169bbdd 100644
--- a/js/Plugin/jstree/hm.jstree.js
+++ b/js/Plugin/jstree/hm.jstree.js
@@ -37,8 +37,7 @@
                   }
                 },
                 themes: {
-                  // Todo: make configurable.
-                  dots: dots === "1",
+                  dots: dots,
                   name: theme
                 },
                 'check_callback' : true,
diff --git a/src/Entity/HmDisplayProfile.php b/src/Entity/HmDisplayProfile.php
index 29f41bd..6216273 100644
--- a/src/Entity/HmDisplayProfile.php
+++ b/src/Entity/HmDisplayProfile.php
@@ -33,6 +33,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
  *     "id",
  *     "label",
  *     "plugin",
+ *     "config",
  *   },
  *   links = {
  *     "canonical" = "/admin/structure/hm_display_profile/{hm_display_profile}",
@@ -65,5 +66,11 @@ class HmDisplayProfile extends ConfigEntityBase implements HmDisplayProfileInter
    * @var string
    */
   protected $plugin;
-
+  
+  /**
+   * The configurations
+   * 
+   * @var string
+   */
+  protected $config;
 }
diff --git a/src/Form/HmDisplayProfileForm.php b/src/Form/HmDisplayProfileForm.php
index 45a60f9..2aa3ddc 100644
--- a/src/Form/HmDisplayProfileForm.php
+++ b/src/Form/HmDisplayProfileForm.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\hierarchy_manager\Form;
 
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Form\FormStateInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -82,6 +83,29 @@ class HmDisplayProfileForm extends EntityForm {
         '#description' => $this->t('Display plugin that is in charge of rendering the hierarchy view.'),
         '#required' => TRUE,
       ];
+      
+      $form['config'] = array(
+        '#type' => 'hidden',
+        '#value' => $hm_display_profile->get('config'),
+        '#attributes' => [
+          'id' => 'config-value',
+        ],
+      );
+      $form['json_editor'] = [
+        '#type' => 'html_tag',
+        '#tag' => 'div',
+        '#attributes' => [
+          'id' => 'json-editor',
+          'style' => 'width:100%; height: 600px;',
+        ],
+        '#attached' => [
+          'library' => [
+            'hierarchy_manager/libraries.jsoneditor',
+            'hierarchy_manager/feature.hm.jsoneditor',
+            'hierarchy_manager/libraries.jsoneditor.default-theme',
+          ]
+        ],
+      ];
     }
     else {
       $form['no_setup_plugin'] = [
@@ -98,6 +122,17 @@ class HmDisplayProfileForm extends EntityForm {
    */
   public function save(array $form, FormStateInterface $form_state) {
     $hm_display_profile = $this->entity;
+    // User input.
+    $input = $form_state->getUserInput();
+    
+    if (isset($input['config'])) {
+      // Sanitize the user input.
+      $input['config'] = Xss::filter($input['config']);
+      // Update the json data from input.
+      $hm_display_profile->set('config', $input['config']);
+    }
+
+    
     $status = $hm_display_profile->save();
 
     switch ($status) {
diff --git a/src/Form/HmOverviewTerms.php b/src/Form/HmOverviewTerms.php
index b26ecdb..f24f0da 100644
--- a/src/Form/HmOverviewTerms.php
+++ b/src/Form/HmOverviewTerms.php
@@ -61,7 +61,14 @@ class HmOverviewTerms extends OverviewTerms {
                 // Urls.
                 $source_url = Url::fromRoute('hierarchy_manager.taxonomy.tree.json', ['vid' => $vid], ['query' => ['token' => $token, 'destination' => $destination]])->toString();
                 $update_url = Url::fromRoute('hierarchy_manager.taxonomy.tree.update', ['vid' => $vid], ['query' => ['token' => $token]])->toString();
-                return $instance->getForm($source_url, $update_url, $form, $form_state);
+                $config = $display_profile->get("config");
+                if (!empty($config)) {
+                  $options = json_decode($config);
+                }
+                else {
+                  $options = NULL;
+                }
+                return $instance->getForm($source_url, $update_url, $form, $form_state, $options);
               }
             }
           }
diff --git a/src/Plugin/HmDisplayPlugin/HmDisplayJstree.php b/src/Plugin/HmDisplayPlugin/HmDisplayJstree.php
index ea26592..6a5e1d6 100644
--- a/src/Plugin/HmDisplayPlugin/HmDisplayJstree.php
+++ b/src/Plugin/HmDisplayPlugin/HmDisplayJstree.php
@@ -21,7 +21,7 @@ class HmDisplayJstree extends HmDisplayPluginBase implements HmDisplayPluginInte
   /*
    * Build the tree form.
    */
-  public function getForm(string $url_source, string $url_update, array &$form = [], FormStateInterface &$form_state = NULL, array $options = []) {
+  public function getForm(string $url_source, string $url_update, array &$form = [], FormStateInterface &$form_state = NULL, $options = NULL) {
     if (!empty($url_source)) {
       if (!empty(($form_state))) {
         $parent_formObj = $form_state->getFormObject();
@@ -29,7 +29,22 @@ class HmDisplayJstree extends HmDisplayPluginBase implements HmDisplayPluginInte
       }
       
       // The jsTree theme.
-      $theme = isset($options['theme']) ? $options['theme'] : 'default';
+      if (isset($options->theme)) {
+        if (isset($options->theme->name)) {
+          $theme =  $options->theme->name;
+        }
+        else {
+          $theme = 'default';
+        }
+        
+        if (isset($options->theme->dot)) {
+          $dot = $options->theme->dot;
+        }
+        else {
+          $dot = TRUE;
+        }
+      }
+
      
       // Search input.
       $form['search'] = [
@@ -61,6 +76,7 @@ class HmDisplayJstree extends HmDisplayPluginBase implements HmDisplayPluginInte
           'id' => isset($parent_id) ? 'hm-jstree-' . $parent_id : 'hm-jstree',
           'parent-id' => isset($parent_id) ? $parent_id : '',
           'theme' => $theme,
+          'dots' => $dot,
           'data-source' => $url_source,
           'url-update' => $url_update,
         ],
-- 
GitLab