You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ge...@apache.org on 2023/11/13 19:14:03 UTC

(solr) branch main updated: SOLR-17062: Create JS client for Admin UI use (#2050)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 3ebbb37af8b SOLR-17062: Create JS client for Admin UI use (#2050)
3ebbb37af8b is described below

commit 3ebbb37af8be5c896c93e5cdb1740f5077dafe88
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Mon Nov 13 14:13:56 2023 -0500

    SOLR-17062: Create JS client for Admin UI use (#2050)
    
    This commit adds build code to generate a JS client (using the
    OpenAPI Generator's 'javascript' template) and adds the necessary
    plumbing to bundle the client into our Admin UI.  See 'CollectionsV2' in
    services.js as an example.
    
    Note that nothing in this commit adds this JS client as a release
    artifact, publishes it to npm, etc.
    
    ---------
    
    Co-authored-by: Houston Putman <ho...@apache.org>
---
 gradle/node.gradle                                 |  2 +-
 solr/api/build.gradle                              | 27 +++++++
 solr/webapp/build.gradle                           | 83 ++++++++++++++++++++++
 solr/webapp/web/index.html                         |  1 +
 .../web/js/angular/controllers/collections.js      | 22 +++---
 solr/webapp/web/js/angular/services.js             |  6 ++
 6 files changed, 129 insertions(+), 12 deletions(-)

diff --git a/gradle/node.gradle b/gradle/node.gradle
index ba895450573..bb0ea5b3f82 100644
--- a/gradle/node.gradle
+++ b/gradle/node.gradle
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-configure([project(":solr:packaging"), project(":solr:solr-ref-guide")]) {
+configure([project(":solr:packaging"), project(":solr:solr-ref-guide"), project(":solr:webapp")]) {
     apply plugin: "com.github.node-gradle.node"
 
     ext {
diff --git a/solr/api/build.gradle b/solr/api/build.gradle
index 8e50d634485..b83b61683d5 100644
--- a/solr/api/build.gradle
+++ b/solr/api/build.gradle
@@ -17,6 +17,7 @@
 
 plugins {
   id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.2'
+  id "org.openapi.generator" version "6.0.1"
 }
 
 apply plugin: 'java-library'
@@ -24,6 +25,7 @@ apply plugin: 'java-library'
 description = 'API - Interfaces and classes used to represent Solrs APIs'
 
 ext {
+    jsClientDir = "${buildDir}/generated/js"
     openApiSpecDir = "${buildDir}/generated/openapi"
     openApiSpecFile = "${project.openApiSpecDir}/openapi.json"
 }
@@ -33,6 +35,10 @@ configurations {
         canBeConsumed = true
         canBeResolved = false
     }
+    jsClient {
+        canBeConsumed = true
+        canBeResolved = false
+    }
 }
 
 resolve {
@@ -55,8 +61,29 @@ dependencies {
     testImplementation 'org.apache.lucene:lucene-test-framework'
 }
 
+// Non-Java client generation tasks below:
+
+task buildJSClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
+  generatorName.set("javascript")
+  inputSpec.set("$openApiSpecFile")
+  outputDir.set("$jsClientDir")
+  packageName.set("solr")
+  generateApiTests.set(false)
+  generateModelTests.set(false)
+}
+
+tasks.withType(org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
+  dependsOn(resolve)
+}
+
 artifacts {
+    // Ensure the OAS is available to other modules who want to generate code (i.e. solrj)
     openapiSpec resolve.outputDir, {
         builtBy resolve
     }
+
+    // Makes our Javascript client available to the Admin UI build
+    jsClient file(project.jsClientDir), {
+        builtBy buildJSClient
+    }
 }
diff --git a/solr/webapp/build.gradle b/solr/webapp/build.gradle
index d0074eed77d..6cd0189ac61 100644
--- a/solr/webapp/build.gradle
+++ b/solr/webapp/build.gradle
@@ -26,6 +26,14 @@ configurations {
   war {}
   serverLib
   solrCore
+  generatedJSClient
+  generatedJSClientBundle
+}
+
+ext {
+  jsClientWorkspace = layout.buildDirectory.dir("jsClientWorkspace").get()
+  jsClientBundleDir = layout.buildDirectory.dir("jsClientBundle").get()
+  browserifyVersion = "17.0.0"
 }
 
 dependencies {
@@ -34,6 +42,77 @@ dependencies {
   serverLib project(path: ":solr:server", configuration: "serverLib")
   solrCore project(":solr:core")
   implementation(configurations.solrCore - configurations.serverLib)
+
+  generatedJSClient project(path: ":solr:api", configuration: "jsClient")
+  generatedJSClientBundle files(jsClientBundleDir) {
+    builtBy "generateJsClientBundle"
+  }
+}
+
+task syncJSClientSourceCode(type: Sync) {
+  group = 'Solr JS Client'
+  from configurations.generatedJSClient
+
+  into project.jsClientWorkspace
+}
+
+task jsClientDownloadDeps(type: NpmTask) {
+  group = 'Solr JS Client'
+  dependsOn tasks.syncJSClientSourceCode
+
+  args = ["install"]
+  workingDir = file(project.jsClientWorkspace)
+
+  inputs.dir("${jsClientWorkspace}/src")
+  inputs.file("${jsClientWorkspace}/package.json")
+  outputs.dir("${jsClientWorkspace}/node_modules")
+}
+
+task jsClientBuild(type: NpmTask) {
+  group = 'Solr JS Client'
+  dependsOn tasks.jsClientDownloadDeps
+
+  args = ["run", "build"]
+  workingDir = file(project.jsClientWorkspace)
+
+  inputs.dir("${jsClientWorkspace}/src")
+  inputs.file("${jsClientWorkspace}/package.json")
+  inputs.dir("${jsClientWorkspace}/node_modules")
+  outputs.dir("${jsClientWorkspace}/dist")
+}
+
+task downloadBrowserify(type: NpmTask) {
+  group = 'Build Dependency Download'
+  args = ["install", "browserify@${project.browserifyVersion}"]
+
+  inputs.property("browserify version", project.browserifyVersion)
+  outputs.dir("${project.nodeProjectDir}/node_modules/browserify")
+}
+
+task setupJsBundleDir(type: Sync) {
+  group = 'Solr JS Client'
+  dependsOn tasks.syncJSClientSourceCode
+
+  from configurations.generatedJSClient
+
+  include "README.md"
+  include "docs/**"
+
+  into project.jsClientBundleDir
+}
+
+task generateJsClientBundle(type: NpxTask) {
+  group = 'Solr JS Client'
+  dependsOn tasks.downloadBrowserify
+  dependsOn tasks.jsClientBuild
+  dependsOn tasks.setupJsBundleDir
+
+  command = 'browserify'
+  args = ['dist/index.js', '-s', 'solrApi', '-o', "${jsClientBundleDir}/index.js"]
+  workingDir = file(project.jsClientWorkspace)
+
+
+  outputs.dir("${jsClientBundleDir}")
 }
 
 war {
@@ -44,6 +123,10 @@ war {
   exclude "libs/angular-utf8-base.js"
   exclude "libs/angular.js"
   exclude "libs/chosen.jquery.js"
+
+  from (configurations.generatedJSClientBundle, {
+    into "libs/solr"
+  })
 }
 
 // Expose 'war' archive as an artifact so that it can be packaged in the distribution.
diff --git a/solr/webapp/web/index.html b/solr/webapp/web/index.html
index 35b1d664860..dbe9a840c1a 100644
--- a/solr/webapp/web/index.html
+++ b/solr/webapp/web/index.html
@@ -68,6 +68,7 @@ limitations under the License.
   <script src="libs/highlight.js?_=${version}"></script>
   <script src="libs/d3.js?_=${version}"></script>
   <script src="libs/ui-grid.min.js?_=${version}"></script>
+  <script src="libs/solr/index.js"></script>
   <script src="libs/jquery-ui.min.js?_=${version}"></script>
   <script src="libs/angular-utf8-base64.min.js?_=${version}"></script>
   <script src="libs/jssha-3.3.1-sha256.min.js?_=${version}"></script>
diff --git a/solr/webapp/web/js/angular/controllers/collections.js b/solr/webapp/web/js/angular/controllers/collections.js
index be24620abf0..830290a1806 100644
--- a/solr/webapp/web/js/angular/controllers/collections.js
+++ b/solr/webapp/web/js/angular/controllers/collections.js
@@ -16,7 +16,7 @@
 */
 
 solrAdminApp.controller('CollectionsController',
-    function($scope, $routeParams, $location, $timeout, Collections, Zookeeper, Constants, ConfigSets){
+    function($scope, $routeParams, $location, $timeout, Collections, CollectionsV2, Zookeeper, Constants, ConfigSets){
       $scope.resetMenu("collections", Constants.IS_ROOT_PAGE);
 
       $scope.refresh = function() {
@@ -215,16 +215,16 @@ solrAdminApp.controller('CollectionsController',
             alert("No collection selected.");
             return;
         }
-        Collections.reload({name: $scope.collection.name},
-          function(successData) {
-            $scope.reloadSuccess = true;
-            $timeout(function() {$scope.reloadSuccess=false}, 1000);
-          },
-          function(failureData) {
-            $scope.reloadFailure = true;
-            $timeout(function() {$scope.reloadFailure=false}, 1000);
-            $location.path("/~collections");
-          });
+        CollectionsV2.reloadCollection($scope.collection.name, function(error, data,response) {
+           if (error) {
+               $scope.reloadFailure = true;
+               $timeout(function() {$scope.reloadFailure=false}, 1000);
+               $location.path("/~collections");
+           } else {
+               $scope.reloadSuccess = true;
+               $timeout(function() {$scope.reloadSuccess=false}, 1000);
+           }
+        });
       };
 
       $scope.toggleAddReplica = function(shard) {
diff --git a/solr/webapp/web/js/angular/services.js b/solr/webapp/web/js/angular/services.js
index 2b870ab53ff..0a2f5d95266 100644
--- a/solr/webapp/web/js/angular/services.js
+++ b/solr/webapp/web/js/angular/services.js
@@ -25,6 +25,12 @@ solrAdminServices.factory('System',
     ['$resource', function($resource) {
       return $resource('admin/metrics', {"wt":"json", "nodes": "@nodes", "prefix":"@prefix", "_":Date.now()});
     }])
+.factory('CollectionsV2',
+    function() {
+      solrApi.ApiClient.instance.basePath = '/api';
+      delete solrApi.ApiClient.instance.defaultHeaders["User-Agent"];
+      return new solrApi.CollectionsApi();
+    })
 .factory('Collections',
   ['$resource', function($resource) {
     return $resource('admin/collections',