You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by er...@apache.org on 2015/04/04 19:10:49 UTC

svn commit: r1671279 - in /lucene/dev/trunk: partials/ solr/ solr/webapp/web/ solr/webapp/web/css/angular/ solr/webapp/web/js/angular/ solr/webapp/web/js/angular/controllers/

Author: erick
Date: Sat Apr  4 17:10:48 2015
New Revision: 1671279

URL: http://svn.apache.org/r1671279
Log:
SOLR-7241: Add document tab support to AngularJS adminUI

Added:
    lucene/dev/trunk/partials/
    lucene/dev/trunk/partials/documents.html   (with props)
    lucene/dev/trunk/solr/webapp/web/css/angular/documents.css   (with props)
    lucene/dev/trunk/solr/webapp/web/js/angular/controllers/documents.js   (with props)
Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/webapp/web/index.html
    lucene/dev/trunk/solr/webapp/web/js/angular/app.js
    lucene/dev/trunk/solr/webapp/web/js/angular/services.js

Added: lucene/dev/trunk/partials/documents.html
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/partials/documents.html?rev=1671279&view=auto
==============================================================================
--- lucene/dev/trunk/partials/documents.html (added)
+++ lucene/dev/trunk/partials/documents.html Sat Apr  4 17:10:48 2015
@@ -0,0 +1,118 @@
+<!--
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<div id="documents" class="clearfix">
+  <div id="form">
+    <form>
+      <label for="qt">
+        <a rel="help">Request-Handler (qt)</a>
+      </label>
+      <input ng-model="handler" type="text" id="qt" value="/update" title="Request handler in solrconfig.xml.">
+      <label for="document-type">
+        <a rel="help">Document Type</a>
+      </label>
+
+      <div><select ng-model="type" id="document-type" ng-change="changeDocumentType()" placeholder="The type of the document field">
+        <!-- TODO: support the Builder -->
+        <option value="csv">CSV</option>
+        <option value="wizard">Document Builder</option>
+        <option value="upload">File Upload</option>
+        <option value="json">JSON</option>
+        <option value="solr">Solr Command (raw XML or JSON)</option>
+        <option value="xml">XML</option>
+      </select>
+      </div>
+      <div id="document-container">
+        <div id="wizard" ng-show="type=='wizard'">
+          <div id="wizard-fields">
+            <div><span class="description">Field</span>: <select ng-model="fieldName" id="wiz-field-select" name="wiz-field-select"
+                     ng-options="field for field in fields"></select>
+            </div>
+            <div><span id="wiz-field-data"><span class="description">Field Data</span>:</span>
+                <textarea ng-model="fieldData"
+                          id="wizard-doc"
+                          name="wizard-doc"
+                          rows="10"
+                          cols="40"
+                          placeholder="Enter your field text here and then click 'Add Field' to add the field to the document.">
+                </textarea>
+            </div>
+          </div>
+          <div id="wizard-add"><a ng-click="addWizardField()" id="add-field-href"><img border="0" src="./img/ico/plus-button.png"/>Add
+            Field</a></div>
+        </div>
+        <label for="document">
+          <a rel="help">Document(s)</a>
+        </label>
+        <textarea ng-show="type!='upload'" ng-model="document" name="document" id="document" title="The Document" rows="10"
+                  cols="70" placeholder="{{placeholder}}"></textarea>
+
+        <div id="file-upload" ng-show="type=='upload'">
+          <input type="file" id="the-file" name="the-file" file-model="fileUpload"/>
+        </div>
+      </div>
+
+      <div id="advanced">
+        <!-- TODO: only show for JSON/XML-->
+        <div id="attribs">
+          <div id="upload-only" ng-show="type=='upload'">
+            <label for="erh-params"><!-- TODO: cleaner way to do this? -->
+              <a rel="help">Extracting Req. Handler Params</a>
+            </label>
+            <input ng-model="literalParams" type="text" id="erh-params" value="&literal.id=change.me"
+                   title="Extracting Request Handler Parameters" size="50">
+          </div>
+          <div id="general-attribs">
+            <label for="commitWithin">
+              <a rel="help">Commit Within</a>
+            </label>
+            <input type="text" ng-model="commitWithin" id="commitWithin" value="1000" title="Commit Within (ms)">
+            <label for="overwrite">
+              <a rel="help">Overwrite</a>
+            </label>
+            <input ng-model="overwrite" type="text" id="overwrite" value="true" title="Overwrite">
+          </div>
+          <!-- Boost is json only, since the XML has it embedded -->
+          <div id="json-only" ng-show="type=='json'">
+            <label for="boost">
+              <a rel="help">Boost</a>
+            </label>
+            <input ng-model="boost" type="text" id="boost" value="1.0" title="Document Boost">
+          </div>
+        </div>
+      </div>
+
+      <button type="submit" ng-click="submit()" id="submit">Submit Document</button>
+    </form>
+  </div>
+  <div id="result">
+    <div id="response" ng-show="response">
+        <div>
+          <span class="description">Status: </span>{{ responseStatus }}
+        </div>
+        <div>
+          <span class="description">Response:</span>
+          <pre class="syntax language-json"><code ng-bind-html="response | highlight:'json' | unsafe"></code></pre>
+        </div>
+    </div>
+
+  </div>
+</div>
+
+

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1671279&r1=1671278&r2=1671279&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Sat Apr  4 17:10:48 2015
@@ -84,6 +84,9 @@ New Features
 * SOLR-6637: Solr should have a way to restore a core from a backed up index.
   (Varun Thacker, noble, shalin)
 
+* SOLR-7241, SOLR-7263, SOLR-7279: More functionality moving the Admin UI to Angular JS
+  (Upayavira via Erick)
+
 Bug Fixes
 ----------------------
 

Added: lucene/dev/trunk/solr/webapp/web/css/angular/documents.css
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/css/angular/documents.css?rev=1671279&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/css/angular/documents.css (added)
+++ lucene/dev/trunk/solr/webapp/web/css/angular/documents.css Sat Apr  4 17:10:48 2015
@@ -0,0 +1,179 @@
+/*
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*/
+
+#content #documents
+{
+  background-image: url( ../../img/div.gif );
+  background-position: 45% 0;
+  background-repeat: repeat-y;
+}
+
+#content #documents #form
+{
+  float: left;
+  /*width: 21%;*/
+}
+
+#content #documents #form label
+{
+  cursor: pointer;
+  display: block;
+  margin-top: 5px;
+}
+
+#content #documents #form input,
+#content #documents #form select,
+#content #documents #form textarea
+{
+  margin-bottom: 2px;
+  /*width: 100%;*/
+}
+
+#content #documents #form input,
+#content #documents #form textarea
+{
+  margin-bottom: 2px;
+  /*width: 98%;*/
+}
+
+#content #documents #form #start
+{
+  float: left;
+  /*width: 45%;*/
+}
+
+#content #documents #form #rows
+{
+  float: right;
+ /* width: 45%;*/
+}
+
+#content #documents #form .checkbox input
+{
+  margin-bottom: 0;
+  width: auto;
+}
+
+#content #documents #form fieldset,
+#content #documents #form .optional.expanded
+{
+  border: 1px solid #fff;
+  border-top: 1px solid #c0c0c0;
+  margin-bottom: 5px;
+}
+
+#content #documents #form fieldset.common
+{
+  margin-top: 10px;
+}
+
+#content #documents #form fieldset legend,
+#content #documents #form .optional.expanded legend
+{
+  display: block;
+  margin-left: 10px;
+  padding: 0px 5px;
+}
+
+#content #documents #form fieldset legend label
+{
+  margin-top: 0;
+}
+
+#content #documents #form fieldset .fieldset
+{
+  border-bottom: 1px solid #f0f0f0;
+  margin-bottom: 5px;
+  padding-bottom: 10px;
+}
+
+#content #documents #form .optional
+{
+  border: 0;
+}
+
+#content #documents #form .optional legend
+{
+  margin-left: 0;
+  padding-left: 0;
+}
+
+#content #documents #form .optional.expanded .fieldset
+{
+  display: block;
+}
+
+#content #documents #result
+{
+  float: right;
+  width: 54%;
+}
+
+#content #documents #result #url
+{
+  margin-bottom: 10px;
+  background-image: url( ../../img/ico/ui-address-bar.png );
+  background-position: 5px 50%;
+  border: 1px solid #f0f0f0;
+  box-shadow: 1px 1px 0 #f0f0f0;
+  -moz-box-shadow: 1px 1px 0 #f0f0f0;
+  -webkit-box-shadow: 1px 1px 0 #f0f0f0;
+  color: #c0c0c0;
+  display: block;
+  overflow: hidden;
+  padding: 5px;
+  padding-left: 26px;
+  white-space: nowrap;
+}
+
+#content #documents #result #url:focus,
+#content #documents #result #url:hover
+{
+  border-color: #c0c0c0;
+  box-shadow: 1px 1px 0 #d8d8d8;
+  -moz-box-shadow: 1px 1px 0 #d8d8d8;
+  -webkit-box-shadow: 1px 1px 0 #d8d8d8;
+  color: #333;
+}
+
+#content #documents #result #response
+{
+}
+
+#content #documents #result #response pre
+{
+  padding-left: 20px;
+}
+
+.description{
+  font-weight: bold;
+}
+
+#document-type{
+  padding-bottom: 5px;
+}
+
+#wizard-fields div{
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+#wiz-field-data, #wiz-field-data span{
+  vertical-align: top;
+}

Modified: lucene/dev/trunk/solr/webapp/web/index.html
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/index.html?rev=1671279&r1=1671278&r2=1671279&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/index.html (original)
+++ lucene/dev/trunk/solr/webapp/web/index.html Sat Apr  4 17:10:48 2015
@@ -35,7 +35,7 @@ limitations under the License.
   <link rel="stylesheet" type="text/css" href="css/angular/logging.css?_=${version}">
   <link rel="stylesheet" type="text/css" href="css/angular/menu.css?_=${version}">
   <link rel="stylesheet" type="text/css" href="css/styles/plugins.css?_=${version}">
-  <link rel="stylesheet" type="text/css" href="css/styles/documents.css?_=${version}">
+  <link rel="stylesheet" type="text/css" href="css/angular/documents.css?_=${version}">
   <link rel="stylesheet" type="text/css" href="css/angular/query.css?_=${version}">
   <link rel="stylesheet" type="text/css" href="css/styles/replication.css?_=${version}">
   <link rel="stylesheet" type="text/css" href="css/styles/schema-browser.css?_=${version}">
@@ -63,6 +63,7 @@ limitations under the License.
   <script src="js/angular/controllers/java-properties.js"></script>
   <script src="js/angular/controllers/core-overview.js"></script>
   <script src="js/angular/controllers/analysis.js"></script>
+  <script src="js/angular/controllers/documents.js"></script>
   <script src="js/angular/controllers/query.js"></script>
 
 </head>

Modified: lucene/dev/trunk/solr/webapp/web/js/angular/app.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/angular/app.js?rev=1671279&r1=1671278&r2=1671279&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/angular/app.js (original)
+++ lucene/dev/trunk/solr/webapp/web/js/angular/app.js Sat Apr  4 17:10:48 2015
@@ -67,6 +67,10 @@ solrAdminApp.config([
         templateUrl: 'partials/analysis.html',
         controller: 'AnalysisController'
       }).
+      when('/:core/documents', {
+        templateUrl: 'partials/documents.html',
+        controller: 'DocumentsController'
+      }).
       when('/:core/query', {
         templateUrl: 'partials/query.html',
         controller: 'QueryController'
@@ -197,9 +201,23 @@ solrAdminApp.config([
 
   return {request: started, response: ended, responseError: failed};
 })
-
 .config(function($httpProvider) {
   $httpProvider.interceptors.push("httpInterceptor");
+})
+.directive('fileModel', function ($parse) {
+    return {
+        restrict: 'A',
+        link: function(scope, element, attrs) {
+            var model = $parse(attrs.fileModel);
+            var modelSetter = model.assign;
+
+            element.bind('change', function(){
+                scope.$apply(function(){
+                    modelSetter(scope, element[0].files[0]);
+                });
+            });
+        }
+    };
 });
 
 var solrAdminControllers = angular.module('solrAdminControllers', []);

Added: lucene/dev/trunk/solr/webapp/web/js/angular/controllers/documents.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/angular/controllers/documents.js?rev=1671279&view=auto
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/angular/controllers/documents.js (added)
+++ lucene/dev/trunk/solr/webapp/web/js/angular/controllers/documents.js Sat Apr  4 17:10:48 2015
@@ -0,0 +1,131 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+//helper for formatting JSON and others
+
+var DOC_PLACEHOLDER = '<doc>\n' +
+                '<field name="id">change.me</field>' +
+                '<field name="title">change.me</field>' +
+                '</doc>';
+
+var ADD_PLACEHOLDER = '<add>\n' + DOC_PLACEHOLDER + '</add>\n';
+
+solrAdminApp.controller('DocumentsController',
+    function($scope, $rootScope, $routeParams, $location, Luke, Update, FileUpload) {
+        $scope.resetMenu("documents");
+
+        $scope.refresh = function () {
+            Luke.schema({core: $routeParams.core}, function(data) {
+                //TODO: handle dynamic fields
+                delete data.schema.fields._version_;
+                $scope.fields = Object.keys(data.schema.fields);
+            });
+            $scope.document = "";
+            $scope.handler = "/update";
+            $scope.type = "json";
+            $scope.commitWithin = 1000;
+            $scope.overwrite = true;
+            $scope.boost = "1.0";
+        };
+
+        $scope.refresh();
+
+        $scope.changeDocumentType = function () {
+            $scope.placeholder = "";
+            if ($scope.type == 'json') {
+                $scope.placeholder = '{"id":"change.me","title":"change.me"}';
+            } else if ($scope.type == 'csv') {
+                $scope.placeholder = "id,title\nchange.me,change.me";
+            } else if ($scope.type == 'solr') {
+                $scope.placeholder = ADD_PLACEHOLDER;
+            } else if ($scope.type == 'xml') {
+                $scope.placeholder = DOC_PLACEHOLDER;
+            }
+        };
+
+        $scope.addWizardField = function () {
+            if ($scope.document == "") $scope.document = "{}";
+            var doc = JSON.parse($scope.document);
+            doc[$scope.fieldName] = $scope.fieldData;
+            $scope.document = JSON.stringify(doc, null, '\t');
+            $scope.fieldData = "";
+        };
+
+        $scope.submit = function () {
+            var contentType = "";
+            var postData = "";
+            var params = {};
+            var doingFileUpload = false;
+
+            if ($scope.handler[0] == '/') {
+                params.handler = $scope.handler.substring(1);
+            } else {
+                params.handler = 'update';
+                params.qt = $scope.handler;
+            }
+
+            params.commitWithin = $scope.commitWithin;
+            params.boost = $scope.boost;
+            params.overwrite = $scope.overwrite;
+            params.core = $routeParams.core;
+            params.wt = "json";
+
+            if ($scope.type == "json" || $scope.type == "wizard") {
+                postData = "[" + $scope.document + "]";
+                contentType = "application/json";
+            } else if ($scope.type == "csv") {
+                postData = $scope.document;
+                contentType = "application/csv";
+            } else if ($scope.type == "xml") {
+                postData = "<add>" + $scope.document + "</add>";
+                contentType = "text/xml";
+            } else if ($scope.type == "upload") {
+                doingFileUpload = true;
+                params.raw = $scope.literalParams;
+            } else if ($scope.type == "solr") {
+                postData = $scope.document;
+                if (postData[0] == "<") {
+                    contentType = "text/xml";
+                } else if (postData[0] == "{") {
+                    contentType = "application/json";
+                } else {
+                    alert("Cannot identify content type")
+                }
+            }
+            if (!doingFileUpload) {
+                Update.post(params, postData).then(function (success) {
+                    $scope.responseStatus = "success";
+                    delete success.$promise;
+                    delete success.$resolved;
+                    $scope.response = JSON.stringify(success, null, '  ');
+                }).fail(function (failure) {
+                    $scope.responseStatus = failure;
+                });
+            } else {
+                var file = $scope.fileUpload;
+                console.log('file is ' + JSON.stringify(file));
+                var uploadUrl = "/fileUpload";
+                FileUpload.upload(params, $scope.fileUpload, function (success) {
+                    $scope.responseStatus = "success";
+                    $scope.response = JSON.stringify(success, null, '  ');
+                }, function (failure) {
+                    $scope.responseStatus = "failure";
+                    $scope.response = JSON.stringify(failure, null, '  ');
+                });
+            }
+        }
+    });
+

Modified: lucene/dev/trunk/solr/webapp/web/js/angular/services.js
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/webapp/web/js/angular/services.js?rev=1671279&r1=1671278&r2=1671279&view=diff
==============================================================================
--- lucene/dev/trunk/solr/webapp/web/js/angular/services.js (original)
+++ lucene/dev/trunk/solr/webapp/web/js/angular/services.js Sat Apr  4 17:10:48 2015
@@ -77,11 +77,32 @@ solrAdminServices.factory('System',
   }])
 .factory('Update',
   ['$resource', function($resource) {
-    return $resource('/solr/:core/update', {core: '@core', wt:'json', _:Date.now()}, {
+    return $resource('/solr/:core/:handler', {core: '@core', wt:'json', _:Date.now(), handler:'/update'}, {
       "optimize": {params: { optimize: "true"}},
-      "commit": {params: {commit: "true"}}
+      "commit": {params: {commit: "true"}},
+      "post": {method: "POST", params: {handler: '@handler'}}
     });
   }])
+.service('FileUpload', function ($http) {
+    this.upload = function(params, file, success, error){
+        var url = "/solr/" + params.core + "/" + params.handler + "?";
+        raw = params.raw;
+        delete params.core;
+        delete params.handler;
+        delete params.raw;
+        url += $.param(params);
+        if (raw && raw.length>0) {
+            if (raw[0] != "&") raw = "&" + raw;
+            url += raw;
+        }
+        var fd = new FormData();
+        fd.append('file', file);
+        $http.post(url, fd, {
+            transformRequest: angular.identity,
+            headers: {'Content-Type': undefined}
+        }).success(success).error(error);
+    }
+})
 .factory('Luke',
   ['$resource', function($resource) {
     return $resource('/solr/:core/admin/luke', {core: '@core', wt:'json', _:Date.now()}, {