You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ep...@apache.org on 2022/07/08 19:06:56 UTC

[solr] branch branch_9x updated: SOLR-16005: Support add/update/delete field types in Admin UI Schema page (#753)

This is an automated email from the ASF dual-hosted git repository.

epugh pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new faaeceaa822 SOLR-16005: Support add/update/delete field types in Admin UI Schema page (#753)
faaeceaa822 is described below

commit faaeceaa8225a26a821708175481435a269dabb1
Author: Ahmet Can KEPENEK <ah...@gmail.com>
AuthorDate: Fri Jul 8 22:06:09 2022 +0300

    SOLR-16005: Support add/update/delete field types in Admin UI Schema page (#753)
    
    Co-authored-by: Ahmet Can Kepenek <ah...@localhost.localdomain>
---
 solr/CHANGES.txt                                 |   3 +
 solr/webapp/web/css/angular/schema.css           |  31 ++++++-
 solr/webapp/web/js/angular/controllers/schema.js | 102 +++++++++++++++++++++++
 solr/webapp/web/partials/schema.html             |  45 ++++++++--
 4 files changed, 175 insertions(+), 6 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 4a7b2631e18..61bf0edfab9 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -13,8 +13,11 @@ New Features
 
 * SOLR-15921: Load jars in <solr-install-dir>/lib/ by default (janhoy)
 
+* SOLR-16005: Support add/update/delete field types in Admin UI Schema page.  (Ahmet Can Kepenek, Eric Pugh)
+
 * SOLR-15853: Admin UI support for managing Paramsets and using in Queries. (Betul Ince, Eric Pugh)
 
+
 Improvements
 ---------------------
 * SOLR-15986: CommitUpdateCommand and SplitIndexCommand can write user commit metadata. (Bruno Roustant)
diff --git a/solr/webapp/web/css/angular/schema.css b/solr/webapp/web/css/angular/schema.css
index 7fec7f2fb0d..cd5942ce55a 100644
--- a/solr/webapp/web/css/angular/schema.css
+++ b/solr/webapp/web/css/angular/schema.css
@@ -574,9 +574,11 @@ limitations under the License.
 #content #schema .actions #addField span { background-image: url( ../../img/ico/document-list.png ); }
 #content #schema .actions #addDynamicField span { background-image: url( ../../img/ico/documents-stack.png ); }
 #content #schema .actions #addCopyField span { background-image: url( ../../img/ico/document-import.png ); }
+#content #schema .actions #manipulateFieldType span { background-image: url( ../../img/ico/property.png ); }
 
 #content #schema .actions div.action
 {
+  display: inline-table;
   width: 320px;
   background-color: #fff;
   border: 1px solid #f0f0f0;
@@ -590,6 +592,10 @@ limitations under the License.
   z-index: 2;
 }
 
+#content #schema .actions div.action.field-type {
+  width: 450px;
+}
+
 #content #schema .actions p
 {
   padding-bottom: 8px;
@@ -603,7 +609,15 @@ limitations under the License.
   text-align: right;
   width: 25%;
 }
-
+#content #schema .actions .field-type label
+{
+  width: 30%;
+}
+#content #schema .actions .field-type textarea
+{
+  margin-left: 6px;
+  margin-top: 5px;
+}
 #content #schema .actions input,
 #content #schema .actions select,
 #content #schema .actions .buttons,
@@ -730,3 +744,18 @@ limitations under the License.
   opacity: 90;
   bottom: -20px;
 }
+#content #schema .actions .field-type .help {
+  position: absolute;
+  left: 15px;
+  padding: 6px;
+  width: 340px;
+  z-index: 200;
+  background-color: #FCF0AD;
+  border: 1px solid #f0f0f0;
+}
+
+#content #schema .actions .field-type .help p a {
+  color: #003eff;
+  text-decoration-line: underline;
+  text-decoration-color: #003eff;
+}
diff --git a/solr/webapp/web/js/angular/controllers/schema.js b/solr/webapp/web/js/angular/controllers/schema.js
index 8a80d42979c..3ff0b0e079f 100644
--- a/solr/webapp/web/js/angular/controllers/schema.js
+++ b/solr/webapp/web/js/angular/controllers/schema.js
@@ -92,6 +92,18 @@ solrAdminApp.controller('SchemaController',
         };
         $scope.refresh();
 
+        $scope.selectFieldTypeManipulationOption = function() {
+            $scope.fieldTypeObj = $scope.fieldTypeManipulationOption.template;
+        }
+
+        $scope.showHelp = function (id) {
+            if ($scope.helpId && ($scope.helpId === id || id === '')) {
+                delete $scope.helpId;
+            } else {
+                $scope.helpId = id;
+            }
+        };
+
         $scope.selectFieldOrType = function() {
             $location.search($scope.fieldOrType);
         }
@@ -138,6 +150,7 @@ solrAdminApp.controller('SchemaController',
             $scope.showAddField = false;
             $scope.showAddDynamicField = false;
             $scope.showAddCopyField = false;
+            $scope.showManipulateFieldType = false;
         }
 
         $scope.toggleAddField = function() {
@@ -289,6 +302,42 @@ solrAdminApp.controller('SchemaController',
                }
             });
         }
+        $scope.toggleManipulateFieldType = function() {
+            if ($scope.showManipulateFieldType) {
+                $scope.hideAll();
+            } else {
+                $scope.hideAll();
+                $scope.showManipulateFieldType = true;
+
+                $scope.adding = "fieldType";
+
+                $scope.fieldTypeObj = ""
+                delete $scope.addErrors;
+            }
+            $scope.fieldTypeManipulationOptions = getFieldTypeManipulationOptions();
+            $scope.fieldTypeManipulationOption = $scope.fieldTypeManipulationOptions[0];
+            $scope.selectFieldTypeManipulationOption();
+        }
+
+        $scope.manipulateFieldType = function() {
+            delete $scope.manipulateFieldTypeErrors;
+            var data = JSON.parse($scope.fieldTypeObj);
+            Schema.post({core: $routeParams.core}, data, function(data) {
+                if (data.errors) {
+                    $scope.manipulateFieldTypeErrors = data.errors[0].errorMessages;
+                    if (typeof $scope.manipulateFieldTypeErrors === "string") {
+                        $scope.manipulateFieldTypeErrors = [$scope.manipulateFieldTypeErrors];
+                    }
+                } else {
+                    $scope.added = true;
+                    $timeout(function() {
+                        $scope.showManipulateFieldType = false;
+                        $scope.added = false;
+                        $scope.refresh();
+                    }, 1500);
+                }
+            });
+        }
     }
 );
 
@@ -598,6 +647,59 @@ var getTermInfo = function(data) {
     return termInfo;
 };
 
+var getFieldTypeManipulationOptions = function() {
+    return [
+        {
+            value: "Add FieldType Template",
+            label: "Add FieldType",
+            template: "{\n" +
+                "  \"add-field-type\": {\n" +
+                "    \"name\": \"myNewTxtField\",\n" +
+                "    \"class\": \"solr.TextField\",\n" +
+                "    \"positionIncrementGap\": \"100\",\n" +
+                "    \"analyzer\": {\n" +
+                "      \"charFilters\": [\n" +
+                "        {\n" +
+                "          \"class\": \"solr.PatternReplaceCharFilterFactory\",\n" +
+                "          \"replacement\": \"$1$1\",\n" +
+                "          \"pattern\": \"([a-zA-Z])\\\\\\\\1+\"\n" +
+                "        }\n" +
+                "      ],\n" +
+                "      \"tokenizer\": {\n" +
+                "        \"class\": \"solr.WhitespaceTokenizerFactory\"\n" +
+                "      }\n" +
+                "    }\n" +
+                "  }\n" +
+                "}"
+        },
+        {
+            value: "Delete FieldType Template",
+            label: "Delete FieldType",
+            template: "{\n" +
+                "  \"delete-field-type\": {\n" +
+                "    \"name\": \"myNewTxtField\"\n" +
+                "  }\n" +
+                "}"
+        },
+        {
+            value: "Replace FieldType Template",
+            label: "Replace FieldType",
+            template: "{\n" +
+                "  \"replace-field-type\": {\n" +
+                "    \"name\": \"myNewTxtField\",\n" +
+                "    \"class\": \"solr.TextField\",\n" +
+                "    \"positionIncrementGap\": \"100\",\n" +
+                "    \"analyzer\": {\n" +
+                "      \"tokenizer\": {\n" +
+                "        \"class\": \"solr.StandardTokenizerFactory\"\n" +
+                "      }\n" +
+                "    }\n" +
+                "  }\n" +
+                "}"
+        }
+    ];
+};
+
 var sortedObjectArray = function(list) {
     var objarr = [];
     for (var i in list) {
diff --git a/solr/webapp/web/partials/schema.html b/solr/webapp/web/partials/schema.html
index e94b6dab47e..9913dbd2f2c 100644
--- a/solr/webapp/web/partials/schema.html
+++ b/solr/webapp/web/partials/schema.html
@@ -23,6 +23,7 @@ limitations under the License.
       <button id="addField" class="action" ng-click="toggleAddField()"><span>Add Field</span></button>
       <button id="addDynamicField" class="action" ng-click="toggleAddDynamicField()"><span>Add Dynamic Field</span></button>
       <button id="addCopyField" class="action" ng-click="toggleAddCopyField()"><span>Add Copy Field</span></button>
+      <button id="manipulateFieldType" class="action" ng-click="toggleManipulateFieldType()"><span>Manipulate Field Type</span></button>
 
       <div class="action add" data-rel="add" ng-show="showAddField" escape-pressed="hideAll()">
 
@@ -49,7 +50,7 @@ limitations under the License.
             indexed
             </label>
           </p>
-          
+
           <p class="clearfix">
             <label class="checkbox" for="add_uninvertible">
               <input type="checkbox" ng-model="newField.uninvertible" id="add_uninvertible" title="Field should be uninvertible, it is generally recomended to use docValues instead." ng-true-value="'true'" ng-false-value="'false'">
@@ -202,8 +203,41 @@ limitations under the License.
           </p>
 
         </form>
-
       </div>
+        <div class="action add field-type" data-rel="add" ng-show="showManipulateFieldType" escape-pressed="hideAll()">
+            <form>
+                <select id="field_type_manipulation_options"
+                        ng-model="fieldTypeManipulationOption"
+                        chosen
+                        disable-search="true"
+                        ng-change="selectFieldTypeManipulationOption()"
+                        ng-options="f.value for f in fieldTypeManipulationOptions"></select>
+                <a ng-click="showHelp('fieldTypeManipulationHelp')"><img class="help-ico" src="img/ico/question-white.png"/></a>
+                <div id="sampleDocsHelp" class="help" ng-show="helpId === 'fieldTypeManipulationHelp'">
+                    <p>
+                        <a target="_blank" href="https://solr.apache.org/guide/solr/latest/indexing-guide/schema-api.html#add-a-new-field-type">Add a New Field Type</a>: The <b>add-field-type</b> command adds a new field type to your schema.
+                    </p>
+                    <p>
+                        <a target="_blank" href="https://solr.apache.org/guide/solr/latest/indexing-guide/schema-api.html#delete-a-field-type">Delete a Field Type</a>: The <b>delete-field-type</b> command removes a field type from your schema.
+                    </p>
+                    <p>
+                        <a target="_blank" href="https://solr.apache.org/guide/solr/latest/indexing-guide/schema-api.html#replace-a-field-type">Replace a Field Type</a>: The <b>replace-field-type</b> command replaces a field type in your schema.
+                    </p>
+                </div>
+
+                <p class="clearfix">
+                    <textarea rows="20" cols="50" type="text" id="manipulate_field_type" ng-model="fieldTypeObj" focus-when="showManipulateFieldType" placeholder="specify field type operation(add, delete, replace) with field type patterns"></textarea>
+                </p>
+
+                <div ng-repeat="error in manipulateFieldTypeErrors" ng-show="addFieldTypeErrors" class="clearfix note error">
+                    <span>{{error}}</span></div>
+                <p class="clearfix buttons">
+                    <button type="submit" class="submit" ng-class="{success: added}" ng-click="manipulateFieldType()"><span>{{fieldTypeManipulationOption.label}}</span></button>
+                    <button type="reset" class="reset" ng-click="hideAll()"><span>Cancel</span></button>
+                </p>
+
+            </form>
+        </div>
     </div>
 
     <div id="data">
@@ -411,15 +445,16 @@ limitations under the License.
                 </form>
             </div>
         </dd>
-        <dt class="dynamic-field" ng-class="{active: selectedType=='Dynamic Field'}" ng-show="leftbar.dynamicFields">Dynamic Field {{dynamicFields}} / {{dynamicFields.length()}}</dt>
+        
+        <dt class="dynamic-field" ng-class="{active: selectedType=='Dynamic Field'}" ng-show="leftbar.dynamicFields">Dynamic Field</dt>
         <dd class="dynamic-field" ng-class="{active: selectedType=='Dynamic Field'}" ng-repeat="field in leftbar.dynamicFields"><a href="#/{{core}}/schema?dynamic-field={{field}}">{{field}}</a></dd>
 
         <dt class="type" ng-class="{active: selectedType=='Type'}" ng-show="leftbar.types">Type</dt>
         <dd class="type" ng-class="{active: selectedType=='Type'}" ng-repeat="type in leftbar.types"><a href="#/{{core}}/schema?type={{type}}">{{type}}</a></dd>
 
         <dt></dt>
-        <dd class="active delete-field" ng-show="isSchemaUpdatable &amp;&amp; leftbar.fields &amp;&amp;!showDelete"><button ng-click="toggleDelete()"><span>delete field</span></button></dd>
-        <dd class="active delete-field" ng-show="isSchemaUpdatable &amp;&amp; leftbar.dynamicFields &amp;&amp;!showDelete"><button ng-click="toggleDelete()"><span>delete dynamic field</span></button></dd>
+        <dd class="active delete-field" ng-show="isSchemaUpdatable && is.field && !showDelete"><button ng-click="toggleDelete()"><span>delete field</span></button></dd>
+        <dd class="active delete-field" ng-show="isSchemaUpdatable && is.dynamicField && !showDelete"><button ng-click="toggleDelete()"><span>delete dynamic field</span></button></dd>
 
         <div class="action delete" ng-show="showDelete">