SOLR-4316 add a collections dropdown alongside cores dropdown

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1698459 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Upayavira 2015-08-29 11:28:36 +00:00
parent e6e4f18fac
commit 3da81fb200
26 changed files with 491 additions and 107 deletions

View File

@ -137,6 +137,8 @@ New Features
* SOLR-7789: Introduce a ConfigSet management API (Gregory Chanan) * SOLR-7789: Introduce a ConfigSet management API (Gregory Chanan)
* SOLR-4316: Add a collections dropdown to angular admin UI (Upayavira, Shalin Shekhar Mangar)
Bug Fixes Bug Fixes
---------------------- ----------------------

View File

@ -0,0 +1,185 @@
/*
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 #dashboard .block
{
background-image: none;
width: 49%;
}
#content #dashboard .fieldlist
{
float: left;
}
#content #dashboard .fieldlist dt,
#content #dashboard .fieldlist dd
{
display: block;
float: left;
}
#content #dashboard .fieldlist dt
{
clear: left;
margin-right: 2%;
text-align: right;
width: 23%;
}
#content #dashboard .fieldlist dd
{
width: 74%;
}
#content #dashboard .fieldlist .index_optimized
{
margin-top: 10px;
}
#content #dashboard .fieldlist .ico
{
background-image: url( ../../img/ico/slash.png );
height: 20px;
}
#content #dashboard .fieldlist .ico.ico-1
{
background-image: url( ../../img/ico/tick.png );
}
#content #dashboard .fieldlist .ico span
{
display: none;
}
#content #dashboard #statistics .index_optimized.value a
{
display: none;
}
#content #dashboard #statistics .index_optimized.value.ico-0 a
{
background-color: #f0f0f0;
background-image: url( ../../img/ico/hammer-screwdriver.png );
background-position: 5px 50%;
border: 1px solid #c0c0c0;
display: block;
float: left;
margin-left: 50px;
padding: 1px 5px;
padding-left: 26px;
}
#content #dashboard #statistics .index_has-deletions
{
display: none;
}
#content #dashboard #statistics .index_has-deletions.value.ico-0
{
background-image: url( ../../img/ico/tick-red.png );
}
#content #dashboard #replication
{
float: left;
}
#content #dashboard #replication .is-replicating
{
background-position: 99% 50%;
display: block;
}
#content #dashboard #replication #details table thead td span
{
display: none;
}
#content #dashboard #instance
{
float: right;
}
#content #dashboard #instance .dir_impl
{
margin-top: 10px;
}
#content #dashboard #admin-extra
{
float: left;
}
#content #dashboard #healthcheck
{
float: right;
}
#content #dashboard #healthcheck .ico
{
background-image: url( ../../img/ico/slash.png );
height: 20px;
padding-left: 20px;
width: 60%;
}
#content #dashboard #healthcheck .ico.ico-1
{
background-image: url( ../../img/ico/tick.png );
}
#content #dashboard #system h2 { background-image: url( ../../img/ico/server.png ); }
#content #dashboard #statistics h2 { background-image: url( ../../img/ico/chart.png ); }
#content #dashboard #replication h2 { background-image: url( ../../img/ico/node.png ); }
#content #dashboard #replication.master h2 { background-image: url( ../../img/ico/node-master.png ); }
#content #dashboard #replication.slave h2 { background-image: url( ../../img/ico/node-slave.png ); }
#content #dashboard #instance h2 { background-image: url( ../../img/ico/server.png ); }
#content #dashboard #admin-extra h2 { background-image: url( ../../img/ico/plus-button.png ); }
#content #dashboard #collection h2 { background-image: url( ../../img/ico/book-open-text.png ); }
#content #dashboard #shards h2 { background-image: url( ../../img/ico/documents-stack.png ); }
#content #dashboard #shards { margin-left: 20px;}
#dashboard #shards .shard h3.shard-title {
display: block;
background-color: #c8c8c8;
font-weight: bold;
padding: 3px;
padding-left: 30px;
margin-left: 20px;
margin-top: 20px;
background-image: url( ../../img/ico/document-text.png );
background-position-x: 10px;
background-position-y: 3px;
}
#dashboard #shards .shard .shard-detail {
margin-bottom: 25px;
margin-top: 7px;
}
#dashboard #shards .shard .replica {
background-color: #e4e4e4;
}
#dashboard #shards .shard .replica.odd {
background-color: #fff;
}

View File

@ -43,29 +43,33 @@ limitations under the License.
text-overflow: ellipsis; text-overflow: ellipsis;
} }
#core-selector #core-selector,#collection-selector
{ {
margin-top: 20px; margin-top: 20px;
padding-right: 10px; padding-right: 10px;
} }
#core-selector a #core-selector a,
#collection-selector a
{ {
padding: 0; padding: 0;
padding-left: 8px; padding-left: 8px;
} }
#core-selector select #core-selector select,
#collection-selector select
{ {
width: 100%; width: 100%;
} }
#core-selector #has-no-cores a #core-selector #has-no-cores a,
#collection-selector #has-no-collections a
{ {
background-image: url( ../../img/ico/database--plus.png ); background-image: url( ../../img/ico/database--plus.png );
} }
#core-selector #has-no-cores span #core-selector #has-no-cores span,
#collection-selector #has-no-collections span
{ {
color: #c0c0c0; color: #c0c0c0;
display: block; display: block;
@ -172,34 +176,34 @@ limitations under the License.
{ {
} }
#core-menu p .sub-menu p
{ {
border-top: 1px solid #f0f0f0; border-top: 1px solid #f0f0f0;
} }
#core-menu li:first-child p .sub-menu li:first-child p
{ {
border-top: 0; border-top: 0;
} }
#core-menu p a .sub-menu p a
{ {
background-image: url( ../../img/ico/status-offline.png ); background-image: url( ../../img/ico/status-offline.png );
} }
#core-menu .active p a .sub-menu .active p a
{ {
background-image: url( ../../img/ico/box.png ); background-image: url( ../../img/ico/box.png );
} }
#core-menu ul, .sub-menu ul,
#menu ul #menu ul
{ {
padding-top: 5px; padding-top: 5px;
padding-bottom: 10px; padding-bottom: 10px;
} }
#core-menu .active ul, .sub-menu .active ul,
#menu .active ul #menu .active ul
{ {
display: block; display: block;
@ -211,6 +215,7 @@ limitations under the License.
} }
#core-menu ul li a, #core-menu ul li a,
#collection-menu ul li a,
#menu ul li a #menu ul li a
{ {
background-position: 7px 50%; background-position: 7px 50%;
@ -220,20 +225,20 @@ limitations under the License.
padding-left: 26px; padding-left: 26px;
} }
#core-menu ul li:last-child a, .sub-menu ul li:last-child a,
#menu ul li:last-child a #menu ul li:last-child a
{ {
border-bottom: 0; border-bottom: 0;
} }
#core-menu ul li a:hover, .sub-menu ul li a:hover,
#menu ul li a:hover #menu ul li a:hover
{ {
background-color: #f0f0f0; background-color: #f0f0f0;
color: #333; color: #333;
} }
#core-menu ul li.active a, .sub-menu ul li.active a,
#menu ul li.active a #menu ul li.active a
{ {
background-color: #d0d0d0; background-color: #d0d0d0;
@ -258,7 +263,7 @@ limitations under the License.
#menu #cloud.global .rgraph a { background-image: url( ../../img/ico/asterisk.png ); } #menu #cloud.global .rgraph a { background-image: url( ../../img/ico/asterisk.png ); }
#menu #cloud.global .dump a { background-image: url( ../../img/ico/download-cloud.png ); } #menu #cloud.global .dump a { background-image: url( ../../img/ico/download-cloud.png ); }
#core-menu .ping.error a .sub-menu .ping.error a
{ {
background-color: #ffcccc; background-color: #ffcccc;
@ -267,19 +272,19 @@ limitations under the License.
cursor: help; cursor: help;
} }
#core-menu .overview a { background-image: url( ../../img/ico/home.png ); } .sub-menu .overview a { background-image: url( ../../img/ico/home.png ); }
#core-menu .query a { background-image: url( ../../img/ico/magnifier.png ); } .sub-menu .query a { background-image: url( ../../img/ico/magnifier.png ); }
#core-menu .analysis a { background-image: url( ../../img/ico/funnel.png ); } .sub-menu .analysis a { background-image: url( ../../img/ico/funnel.png ); }
#core-menu .documents a { background-image: url( ../../img/ico/documents-stack.png ); } .sub-menu .documents a { background-image: url( ../../img/ico/documents-stack.png ); }
#core-menu .files a { background-image: url( ../../img/ico/folder.png ); } .sub-menu .files a { background-image: url( ../../img/ico/folder.png ); }
#core-menu .schema-browser a { background-image: url( ../../img/ico/book-open-text.png ); } .sub-menu .schema-browser a { background-image: url( ../../img/ico/book-open-text.png ); }
#core-menu .replication a { background-image: url( ../../img/ico/node.png ); } .sub-menu .replication a { background-image: url( ../../img/ico/node.png ); }
#core-menu .distribution a { background-image: url( ../../img/ico/node-select.png ); } .sub-menu .distribution a { background-image: url( ../../img/ico/node-select.png ); }
#core-menu .ping a { background-image: url( ../../img/ico/system-monitor.png ); } .sub-menu .ping a { background-image: url( ../../img/ico/system-monitor.png ); }
#core-menu .logging a { background-image: url( ../../img/ico/inbox-document-text.png ); } .sub-menu .logging a { background-image: url( ../../img/ico/inbox-document-text.png ); }
#core-menu .plugins a { background-image: url( ../../img/ico/block.png ); } .sub-menu .plugins a { background-image: url( ../../img/ico/block.png ); }
#core-menu .dataimport a { background-image: url( ../../img/ico/document-import.png ); } .sub-menu .dataimport a { background-image: url( ../../img/ico/document-import.png ); }
#core-menu .segments a { background-image: url( ../../img/ico/construction.png ); } .sub-menu .segments a { background-image: url( ../../img/ico/construction.png ); }
#content #navigation #content #navigation

View File

@ -27,7 +27,7 @@ limitations under the License.
<link rel="stylesheet" type="text/css" href="css/angular/analysis.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/analysis.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/cloud.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/cloud.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/cores.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/cores.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/styles/dashboard.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/dashboard.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/dataimport.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/dataimport.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/files.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/files.css?_=${version}">
<link rel="stylesheet" type="text/css" href="css/angular/index.css?_=${version}"> <link rel="stylesheet" type="text/css" href="css/angular/index.css?_=${version}">
@ -64,6 +64,7 @@ limitations under the License.
<script src="js/angular/controllers/threads.js"></script> <script src="js/angular/controllers/threads.js"></script>
<script src="js/angular/controllers/java-properties.js"></script> <script src="js/angular/controllers/java-properties.js"></script>
<script src="js/angular/controllers/core-overview.js"></script> <script src="js/angular/controllers/core-overview.js"></script>
<script src="js/angular/controllers/collection-overview.js"></script>
<script src="js/angular/controllers/analysis.js"></script> <script src="js/angular/controllers/analysis.js"></script>
<script src="js/angular/controllers/dataimport.js"></script> <script src="js/angular/controllers/dataimport.js"></script>
<script src="js/angular/controllers/documents.js"></script> <script src="js/angular/controllers/documents.js"></script>
@ -155,11 +156,36 @@ limitations under the License.
</ul> </ul>
<div id="collection-selector" ng-show="isCloudEnabled">
<div id="has-collections" ng-show="collections.length!=0">
<select data-placeholder="Collection Selector"
ng-model="currentCollection"
chosen
ng-change="showCollection(currentCollection)"
ng-options="collection.name for collection in collections"></select>
</div>
<p id="has-no-collections" ng-show="collections.length==0"><a href="#/~collections">
No collections available
<span>Go and create one</span>
</a></p>
</div>
<div id="collection-menu" class="sub-menu" ng-show="currentCollection">
<ul>
<li class="overview" ng-class="{active:page=='collection-overview'}"><a href="#/{{currentCore.name}}/collection-overview"><span>Overview</span></a></li>
<li class="analysis" ng-class="{active:page=='analysis'}"><a href="#/{{currentCollection.name}}/analysis"><span>Analysis</span></a></li>
<li class="dataimport" ng-class="{active:page=='dataimport'}"><a href="#/{{currentCollection.name}}/dataimport"><span>Dataimport</span></a></li>
<li class="documents" ng-class="{active:page=='documents'}"><a href="#/{{currentCollection.name}}/documents"><span>Documents</span></a></li>
<li class="files" ng-class="{active:page=='files'}"><a href="#/{{currentCollection.name}}/files"><span>Files</span></a></li>
<li class="query" ng-class="{active:page=='query'}"><a href="#/{{currentCollection.name}}/query"><span>Query</span></a></li>
<li class="schema-browser" ng-class="{active:page=='schema-browser'}"><a href="#/{{currentCollection.name}}/schema-browser"><span>Schema Browser</span></a></li>
</ul>
</div>
<div id="core-selector"> <div id="core-selector">
<div id="has-cores" ng-show="cores.length!=0"> <div id="has-cores" ng-show="cores.length!=0">
<select data-placeholder="Core Selector" <select data-placeholder="Core Selector"
ng-model="currentCore" ng-model="currentCore"
chosen chosen
ng-change="showCore(currentCore)"
ng-options="core.name for core in cores"></select> ng-options="core.name for core in cores"></select>
</div> </div>
<p id="has-no-cores" ng-show="cores.length==0"><a href="#/~cores"> <p id="has-no-cores" ng-show="cores.length==0"><a href="#/~cores">
@ -167,18 +193,18 @@ limitations under the License.
<span>Go and create one</span> <span>Go and create one</span>
</a></p> </a></p>
</div> </div>
<div id="core-menu" ng-show="currentCore"> <div id="core-menu" class="sub-menu" ng-show="currentCore">
<ul> <ul>
<li class="overview" ng-class="{active:page=='overview'}"><a href="#/{{currentCore.name}}"><span>Overview</span></a></li> <li class="overview" ng-class="{active:page=='overview'}"><a href="#/{{currentCore.name}}"><span>Overview</span></a></li>
<li class="analysis" ng-class="{active:page=='analysis'}"><a href="#/{{currentCore.name}}/analysis"><span>Analysis</span></a></li> <li ng-hide="isCloudEnabled" class="analysis" ng-class="{active:page=='analysis'}"><a href="#/{{currentCore.name}}/analysis"><span>Analysis</span></a></li>
<li class="dataimport" ng-class="{active:page=='dataimport'}"><a href="#/{{currentCore.name}}/dataimport"><span>Dataimport</span></a></li> <li ng-hide="isCloudEnabled" class="dataimport" ng-class="{active:page=='dataimport'}"><a href="#/{{currentCore.name}}/dataimport"><span>Dataimport</span></a></li>
<li class="documents" ng-class="{active:page=='documents'}"><a href="#/{{currentCore.name}}/documents"><span>Documents</span></a></li> <li ng-hide="isCloudEnabled" class="documents" ng-class="{active:page=='documents'}"><a href="#/{{currentCore.name}}/documents"><span>Documents</span></a></li>
<li class="files" ng-class="{active:page=='files'}"><a href="#/{{currentCore.name}}/files"><span>Files</span></a></li> <li ng-hide="isCloudEnabled" class="files" ng-class="{active:page=='files'}"><a href="#/{{currentCore.name}}/files"><span>Files</span></a></li>
<li class="ping" ng-class="{active:page=='ping'}"><a ng-click="ping()"><span>Ping</span><small class="qtime" ng-show="pingMS"> (<span>{{pingMS}}ms</span>)</small></a></li> <li class="ping" ng-class="{active:page=='ping'}"><a ng-click="ping()"><span>Ping</span><small class="qtime" ng-show="pingMS"> (<span>{{pingMS}}ms</span>)</small></a></li>
<li class="plugins" ng-class="{active:page=='plugins'}"><a href="#/{{currentCore.name}}/plugins"><span>Plugins / Stats</span></a></li> <li class="plugins" ng-class="{active:page=='plugins'}"><a href="#/{{currentCore.name}}/plugins"><span>Plugins / Stats</span></a></li>
<li class="query" ng-class="{active:page=='query'}"><a href="#/{{currentCore.name}}/query"><span>Query</span></a></li> <li ng-hide="isCloudEnabled" class="query" ng-class="{active:page=='query'}"><a href="#/{{currentCore.name}}/query"><span>Query</span></a></li>
<li class="replication" ng-class="{active:page=='replication'}"><a href="#/{{currentCore.name}}/replication"><span>Replication</span></a></li> <li class="replication" ng-class="{active:page=='replication'}"><a href="#/{{currentCore.name}}/replication"><span>Replication</span></a></li>
<li class="schema-browser" ng-class="{active:page=='schema-browser'}"><a href="#/{{currentCore.name}}/schema-browser"><span>Schema Browser</span></a></li> <li ng-hide="isCloudEnabled" class="schema-browser" ng-class="{active:page=='schema-browser'}"><a href="#/{{currentCore.name}}/schema-browser"><span>Schema Browser</span></a></li>
<li class="segments" ng-class="{active:page=='segments'}"><a href="#/{{currentCore.name}}/segments"><span>Segments info</span></a></li> <li class="segments" ng-class="{active:page=='segments'}"><a href="#/{{currentCore.name}}/segments"><span>Segments info</span></a></li>
</ul> </ul>
</div> </div>

View File

@ -63,6 +63,10 @@ solrAdminApp.config([
templateUrl: 'partials/core_overview.html', templateUrl: 'partials/core_overview.html',
controller: 'CoreOverviewController' controller: 'CoreOverviewController'
}). }).
when('/:core/collection-overview', {
templateUrl: 'partials/collection_overview.html',
controller: 'CollectionOverviewController'
}).
when('/:core/analysis', { when('/:core/analysis', {
templateUrl: 'partials/analysis.html', templateUrl: 'partials/analysis.html',
controller: 'AnalysisController' controller: 'AnalysisController'
@ -121,6 +125,11 @@ solrAdminApp.config([
redirectTo: '/' redirectTo: '/'
}); });
}]) }])
.constant('Constants', {
IS_ROOT_PAGE: 1,
IS_CORE_PAGE: 2,
IS_COLLECTION_PAGE: 3
})
.filter('highlight', function($sce) { .filter('highlight', function($sce) {
return function(input, lang) { return function(input, lang) {
if (lang && input && lang!="text") return hljs.highlight(lang, input).value; if (lang && input && lang!="text") return hljs.highlight(lang, input).value;
@ -319,9 +328,17 @@ solrAdminApp.config([
}; };
}); });
solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $location, Cores, System, Ping) { solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $location, Cores, Collections, System, Ping, Constants) {
$rootScope.hideException = function() {delete $rootScope.exception}; $rootScope.hideException = function() {delete $rootScope.exception};
$scope.refresh = function() { $scope.refresh = function() {
$scope.cores = [];
$scope.collections = [];
}
$scope.refresh();
$scope.resetMenu = function(page, pageType) {
Cores.list(function(data) { Cores.list(function(data) {
$scope.cores = []; $scope.cores = [];
var currentCoreName = $route.current.params.core; var currentCoreName = $route.current.params.core;
@ -329,22 +346,35 @@ solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $
for (key in data.status) { for (key in data.status) {
var core = data.status[key]; var core = data.status[key];
$scope.cores.push(core); $scope.cores.push(core);
if (core.name == currentCoreName) { if ((!$scope.isSolrCloud || pageType == Constants.IS_CORE_PAGE) && core.name == currentCoreName) {
$scope.currentCore = core; $scope.currentCore = core;
} }
} }
}); });
System.get(function(data) {
$scope.isCloudEnabled = data.mode.match( /solrcloud/i )
});
};
$scope.refresh();
$scope.resetMenu = function(page, isMainPage) { System.get(function(data) {
$scope.isCloudEnabled = data.mode.match( /solrcloud/i );
if ($scope.isCloudEnabled) {
Collections.list(function (data) {
$scope.collections = [];
var currentCollectionName = $route.current.params.core;
delete $scope.currentCollection;
for (key in data.collections) {
var collection = {name: data.collections[key]};
$scope.collections.push(collection);
if (pageType == Constants.IS_COLLECTION_PAGE && collection.name == currentCollectionName) {
$scope.currentCollection = collection;
}
}
})
}
});
$scope.showingLogging = page.lastIndexOf("logging", 0) === 0; $scope.showingLogging = page.lastIndexOf("logging", 0) === 0;
$scope.showingCloud = page.lastIndexOf("cloud", 0) === 0; $scope.showingCloud = page.lastIndexOf("cloud", 0) === 0;
$scope.page = page; $scope.page = page;
if (isMainPage) delete $scope.currentCore;
}; };
$scope.ping = function() { $scope.ping = function() {
@ -357,8 +387,16 @@ solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $
$scope.dumpCloud = function() { $scope.dumpCloud = function() {
$scope.$broadcast("cloud-dump"); $scope.$broadcast("cloud-dump");
} }
});
$scope.showCore = function(core) {
$location.url("/" + core.name);
}
$scope.showCollection = function(collection) {
$location.url("/" + collection.name + "/collection-overview")
}
});
(function(window, angular, undefined) { (function(window, angular, undefined) {

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('AnalysisController', solrAdminApp.controller('AnalysisController',
function($scope, $location, $routeParams, Luke, Analysis) { function($scope, $location, $routeParams, Luke, Analysis, Constants) {
$scope.resetMenu("analysis"); $scope.resetMenu("analysis", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function() { $scope.refresh = function() {
Luke.schema({core: $routeParams.core}, function(data) { Luke.schema({core: $routeParams.core}, function(data) {

View File

@ -16,7 +16,7 @@
*/ */
solrAdminApp.controller('CloudController', solrAdminApp.controller('CloudController',
function($scope, $location, Zookeeper) { function($scope, $location, Zookeeper, Constants) {
$scope.showDebug = false; $scope.showDebug = false;
@ -30,13 +30,13 @@ solrAdminApp.controller('CloudController',
var view = $location.search().view ? $location.search().view : "graph"; var view = $location.search().view ? $location.search().view : "graph";
if (view == "tree") { if (view == "tree") {
$scope.resetMenu("cloud-tree", true); $scope.resetMenu("cloud-tree", Constants.IS_ROOT_PAGE);
treeSubController($scope, Zookeeper); treeSubController($scope, Zookeeper);
} else if (view == "rgraph") { } else if (view == "rgraph") {
$scope.resetMenu("cloud-rgraph", true); $scope.resetMenu("cloud-rgraph", Constants.IS_ROOT_PAGE);
graphSubController($scope, Zookeeper, true); graphSubController($scope, Zookeeper, true);
} else if (view == "graph") { } else if (view == "graph") {
$scope.resetMenu("cloud-graph", true); $scope.resetMenu("cloud-graph", Constants.IS_ROOT_PAGE);
graphSubController($scope, Zookeeper, false); graphSubController($scope, Zookeeper, false);
} }
} }

View File

@ -0,0 +1,38 @@
/*
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.
*/
solrAdminApp.controller('CollectionOverviewController',
function($scope, $routeParams, Collections, Constants) {
$scope.resetMenu("collection-overview", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function() {
Collections.status({}, function(data) {
$scope.selectedCollection = data.cluster.collections[$routeParams.core];
$scope.selectedCollection.name = $routeParams.core;
});
};
$scope.showReplica = function(replica) {
replica.show = !replica.show;
}
$scope.hideShard = function(shard) {
shard.hide = !shard.hide;
}
$scope.refresh();
});

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('CoreOverviewController', solrAdminApp.controller('CoreOverviewController',
function($scope, $rootScope, $routeParams, Luke, CoreSystem, Update, Replication, Ping) { function($scope, $rootScope, $routeParams, Luke, CoreSystem, Update, Replication, Ping, Constants) {
$scope.resetMenu("overview"); $scope.resetMenu("overview", Constants.IS_CORE_PAGE);
$scope.refreshIndex = function() { $scope.refreshIndex = function() {
Luke.index({core: $routeParams.core}, Luke.index({core: $routeParams.core},
function(data) { function(data) {

View File

@ -17,30 +17,27 @@
// @todo test optimize (delete stuff, watch button appear, test button/form) // @todo test optimize (delete stuff, watch button appear, test button/form)
solrAdminApp.controller('CoreAdminController', solrAdminApp.controller('CoreAdminController',
['$scope', '$routeParams', '$location', '$timeout', 'Cores', 'Update', function($scope, $routeParams, $location, $timeout, Cores, Update, Constants){
function($scope, $routeParams, $location, $timeout, Cores, Update){ $scope.resetMenu("cores", Constants.IS_ROOT_PAGE);
$scope.resetMenu("cores", true); $scope.selectedCore = $routeParams.corename; // use 'corename' not 'core' to distinguish from /solr/:core/
$scope.currentCore = $routeParams.corename; // use 'corename' not 'core' to distinguish from /solr/:core/
$scope.refresh = function() { $scope.refresh = function() {
Cores.get(function(data) { Cores.get(function(data) {
var coreCount = 0; var coreCount = 0;
for (_obj in data.status) coreCount++; for (_obj in data.status) coreCount++;
$scope.hasCores = coreCount >0; $scope.hasCores = coreCount >0;
if (!$scope.currentCore && coreCount==0) { if (!$scope.selectedCore && coreCount==0) {
$scope.showAddCore(); $scope.showAddCore();
return; return;
} else if (!$scope.currentCore) { } else if (!$scope.selectedCore) {
for (firstCore in data.status) break; for (firstCore in data.status) break;
$scope.currentCore = firstCore; $scope.selectedCore = firstCore;
$location.path("/~cores/" + $scope.currentCore).replace(); $location.path("/~cores/" + $scope.selectedCore).replace();
} }
$scope.core = data.status[$scope.currentCore]; $scope.core = data.status[$scope.selectedCore];
var cores = []; $scope.corelist = [];
for (var core in data.status) { for (var core in data.status) {
cores.push(data.status[core]); $scope.corelist.push(data.status[core]);
} }
$scope.cores = cores;
$scope.$parent.refresh();
}); });
}; };
$scope.showAddCore = function() { $scope.showAddCore = function() {
@ -87,9 +84,9 @@ solrAdminApp.controller('CoreAdminController',
}; };
$scope.unloadCore = function() { $scope.unloadCore = function() {
var answer = confirm( 'Do you really want to unload Core "' + $scope.currentCore + '"?' ); var answer = confirm( 'Do you really want to unload Core "' + $scope.selectedCore + '"?' );
if( !answer ) return; if( !answer ) return;
Cores.unload({core: $scope.currentCore}, function(data) { Cores.unload({core: $scope.selectedCore}, function(data) {
$location.path("/~cores"); $location.path("/~cores");
}); });
}; };
@ -101,11 +98,11 @@ solrAdminApp.controller('CoreAdminController',
$scope.renameCore = function() { $scope.renameCore = function() {
if (!$scope.other) { if (!$scope.other) {
$scope.renameMessage = "Please provide a new name for the " + $scope.currentCore + " core"; $scope.renameMessage = "Please provide a new name for the " + $scope.selectedCore + " core";
} else if ($scope.other == $scope.currentCore) { } else if ($scope.other == $scope.selectedCore) {
$scope.renameMessage = "New name must be different from the current one"; $scope.renameMessage = "New name must be different from the current one";
} else { } else {
Cores.rename({core:$scope.currentCore, other: $scope.other}, function(data) { Cores.rename({core:$scope.selectedCore, other: $scope.other}, function(data) {
$location.path("/~cores/" + $scope.other); $location.path("/~cores/" + $scope.other);
$scope.cancelRename(); $scope.cancelRename();
}); });
@ -126,10 +123,10 @@ solrAdminApp.controller('CoreAdminController',
$scope.swapCores = function() { $scope.swapCores = function() {
if ($scope.swapOther) { if ($scope.swapOther) {
$swapMessage = "Please select a core to swap with"; $swapMessage = "Please select a core to swap with";
} else if ($scope.swapOther == $scope.currentCore) { } else if ($scope.swapOther == $scope.selectedCore) {
$swapMessage = "Cannot swap with the same core"; $swapMessage = "Cannot swap with the same core";
} else { } else {
Cores.swap({core: $scope.currentCore, other: $scope.swapOther}, function(data) { Cores.swap({core: $scope.selectedCore, other: $scope.swapOther}, function(data) {
$location.path("/~cores/" + $scope.swapOther); $location.path("/~cores/" + $scope.swapOther);
delete $scope.swapOther; delete $scope.swapOther;
$scope.cancelSwap(); $scope.cancelSwap();
@ -143,7 +140,7 @@ solrAdminApp.controller('CoreAdminController',
} }
$scope.reloadCore = function() { $scope.reloadCore = function() {
Cores.reload({core: $scope.currentCore}, Cores.reload({core: $scope.selectedCore},
function(successData) { function(successData) {
$scope.reloadSuccess = true; $scope.reloadSuccess = true;
$timeout(function() {$scope.reloadSuccess=false}, 1000); $timeout(function() {$scope.reloadSuccess=false}, 1000);
@ -151,7 +148,7 @@ solrAdminApp.controller('CoreAdminController',
function(failureData) { function(failureData) {
$scope.reloadFailure = true; $scope.reloadFailure = true;
$timeout(function() {$scope.reloadFailure=false}, 1000); $timeout(function() {$scope.reloadFailure=false}, 1000);
$scope.currentCore = null; $scope.selectedCore = null;
$scope.refresh(); $scope.refresh();
$location.path("/~cores"); $location.path("/~cores");
}); });
@ -164,7 +161,7 @@ solrAdminApp.controller('CoreAdminController',
}; };
$scope.optimizeCore = function() { $scope.optimizeCore = function() {
Update.optimize({core: $scope.currentCore}, Update.optimize({core: $scope.selectedCore},
function(successData) { function(successData) {
$scope.optimizeSuccess = true; $scope.optimizeSuccess = true;
$timeout(function() {$scope.optimizeSuccess=false}, 1000); $timeout(function() {$scope.optimizeSuccess=false}, 1000);
@ -179,7 +176,7 @@ solrAdminApp.controller('CoreAdminController',
$scope.refresh(); $scope.refresh();
} }
]); );
/************** /**************
'cores_load_data', 'cores_load_data',

View File

@ -18,8 +18,8 @@
var dataimport_timeout = 2000; var dataimport_timeout = 2000;
solrAdminApp.controller('DataImportController', solrAdminApp.controller('DataImportController',
function($scope, $rootScope, $routeParams, $location, $timeout, $interval, $cookies, Mbeans, DataImport) { function($scope, $rootScope, $routeParams, $location, $timeout, $interval, $cookies, Mbeans, DataImport, Constants) {
$scope.resetMenu("dataimport"); $scope.resetMenu("dataimport", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function () { $scope.refresh = function () {
Mbeans.info({core: $routeParams.core, cat: 'QUERYHANDLER'}, function (data) { Mbeans.info({core: $routeParams.core, cat: 'QUERYHANDLER'}, function (data) {

View File

@ -24,8 +24,8 @@ var DOC_PLACEHOLDER = '<doc>\n' +
var ADD_PLACEHOLDER = '<add>\n' + DOC_PLACEHOLDER + '</add>\n'; var ADD_PLACEHOLDER = '<add>\n' + DOC_PLACEHOLDER + '</add>\n';
solrAdminApp.controller('DocumentsController', solrAdminApp.controller('DocumentsController',
function($scope, $rootScope, $routeParams, $location, Luke, Update, FileUpload) { function($scope, $rootScope, $routeParams, $location, Luke, Update, FileUpload, Constants) {
$scope.resetMenu("documents"); $scope.resetMenu("documents", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function () { $scope.refresh = function () {
Luke.schema({core: $routeParams.core}, function(data) { Luke.schema({core: $routeParams.core}, function(data) {

View File

@ -19,8 +19,8 @@ var contentTypeMap = { xml : 'text/xml', html : 'text/html', js : 'text/javascri
var languages = {js: "javascript", xml:"xml", xsl:"xml", vm: "xml", html: "xml", json: "text", css: "css"}; var languages = {js: "javascript", xml:"xml", xsl:"xml", vm: "xml", html: "xml", json: "text", css: "css"};
solrAdminApp.controller('FilesController', solrAdminApp.controller('FilesController',
function($scope, $rootScope, $routeParams, $location, Files) { function($scope, $rootScope, $routeParams, $location, Files, Constants) {
$scope.resetMenu("files"); $scope.resetMenu("files", Constants.IS_COLLECTION_PAGE);
$scope.file = $location.search().file; $scope.file = $location.search().file;
$scope.content = null; $scope.content = null;

View File

@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
solrAdminApp.controller('IndexController', ['$scope', 'System', 'Cores', function($scope, System, Cores) { solrAdminApp.controller('IndexController', function($scope, System, Cores, Constants) {
$scope.resetMenu("index", true); $scope.resetMenu("index", Constants.IS_ROOT_PAGE);
$scope.reload = function() { $scope.reload = function() {
System.get(function(data) { System.get(function(data) {
$scope.system = data; $scope.system = data;
@ -67,7 +67,7 @@ solrAdminApp.controller('IndexController', ['$scope', 'System', 'Cores', functio
}); });
}; };
$scope.reload(); $scope.reload();
}]); });
var parse_memory_value = function( value ) { var parse_memory_value = function( value ) {
if( value !== Number( value ) ) if( value !== Number( value ) )

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('JavaPropertiesController', solrAdminApp.controller('JavaPropertiesController',
function($scope, Properties){ function($scope, Properties, Constants){
$scope.resetMenu("java-props", true); $scope.resetMenu("java-props", Constants.IS_ROOT_PAGE);
$scope.refresh = function() { $scope.refresh = function() {
Properties.get(function(data) { Properties.get(function(data) {
var sysprops = data["system.properties"]; var sysprops = data["system.properties"];

View File

@ -24,8 +24,8 @@ var format_time_content = function( time, timeZone ) {
} }
solrAdminApp.controller('LoggingController', solrAdminApp.controller('LoggingController',
function($scope, $timeout, $cookies, Logging){ function($scope, $timeout, $cookies, Logging, Constants){
$scope.resetMenu("logging", true); $scope.resetMenu("logging", Constants.IS_ROOT_PAGE);
$scope.timezone = $cookies.logging_timezone || "Local"; $scope.timezone = $cookies.logging_timezone || "Local";
$scope.refresh = function() { $scope.refresh = function() {
Logging.events(function(data) { Logging.events(function(data) {

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('PluginsController', solrAdminApp.controller('PluginsController',
function($scope, $rootScope, $routeParams, $location, Mbeans) { function($scope, $rootScope, $routeParams, $location, Mbeans, Constants) {
$scope.resetMenu("plugins"); $scope.resetMenu("plugins", Constants.IS_CORE_PAGE);
if ($routeParams.legacytype) { if ($routeParams.legacytype) {
// support legacy URLs. Angular cannot change #path without reloading controller // support legacy URLs. Angular cannot change #path without reloading controller

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('QueryController', solrAdminApp.controller('QueryController',
function($scope, $routeParams, $location, Query){ function($scope, $routeParams, $location, Query, Constants){
$scope.resetMenu("query"); $scope.resetMenu("query", Constants.IS_COLLECTION_PAGE);
// @todo read URL parameters into scope // @todo read URL parameters into scope
$scope.query = {wt: 'json', q:'*:*', indent:'on'}; $scope.query = {wt: 'json', q:'*:*', indent:'on'};

View File

@ -16,8 +16,8 @@
*/ */
solrAdminApp.controller('ReplicationController', solrAdminApp.controller('ReplicationController',
function($scope, $rootScope, $routeParams, $interval, $timeout, Replication) { function($scope, $rootScope, $routeParams, $interval, $timeout, Replication, Constants) {
$scope.resetMenu("replication"); $scope.resetMenu("replication", Constants.IS_CORE_PAGE);
$scope.iterationCount = 1; $scope.iterationCount = 1;

View File

@ -18,8 +18,8 @@
var cookie_schema_browser_autoload = 'schema-browser_autoload'; var cookie_schema_browser_autoload = 'schema-browser_autoload';
solrAdminApp.controller('SchemaBrowserController', solrAdminApp.controller('SchemaBrowserController',
function($scope, $routeParams, $location, $cookies, Luke) { function($scope, $routeParams, $location, $cookies, Luke, Constants) {
$scope.resetMenu("schema-browser"); $scope.resetMenu("schema-browser", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function () { $scope.refresh = function () {
Luke.schema({core: $routeParams.core}, function (schema) { Luke.schema({core: $routeParams.core}, function (schema) {

View File

@ -17,8 +17,8 @@
var MB_FACTOR = 1024*1024; var MB_FACTOR = 1024*1024;
solrAdminApp.controller('SegmentsController', function($scope, $routeParams, $interval, Segments) { solrAdminApp.controller('SegmentsController', function($scope, $routeParams, $interval, Segments, Constants) {
$scope.resetMenu("segments"); $scope.resetMenu("segments", Constants.IS_CORE_PAGE);
$scope.refresh = function() { $scope.refresh = function() {

View File

@ -16,9 +16,8 @@
*/ */
solrAdminApp.controller('ThreadsController', solrAdminApp.controller('ThreadsController',
["$scope", "Threads", function($scope, Threads, Constants){
function($scope, Threads){ $scope.resetMenu("threads", Constants.IS_ROOT_PAGE);
$scope.resetMenu("threads", true);
$scope.refresh = function() { $scope.refresh = function() {
Threads.get(function(data) { Threads.get(function(data) {
var threadDump = data.system.threadDump; var threadDump = data.system.threadDump;
@ -48,4 +47,4 @@ solrAdminApp.controller('ThreadsController',
} }
}; };
$scope.refresh(); $scope.refresh();
}]); });

View File

@ -35,6 +35,15 @@ solrAdminServices.factory('System',
"optimize": {params:{}} "optimize": {params:{}}
}); });
}]) }])
.factory('Collections',
['$resource', function($resource) {
return $resource('/solr/admin/collections',
{wt: 'json', _:Date.now()}, {
"list": {params:{action: "LIST"}},
"status": {params:{action: "CLUSTERSTATUS"}}
}
)
}])
.factory('Logging', .factory('Logging',
['$resource', function($resource) { ['$resource', function($resource) {
return $resource('/solr/admin/info/logging', {'wt':'json', '_':Date.now()}, { return $resource('/solr/admin/info/logging', {'wt':'json', '_':Date.now()}, {

View File

@ -0,0 +1,83 @@
<!--
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="dashboard">
<div class="clearfix">
<div id="collection" class="block fieldlist">
<h2><span>Collection: {{selectedCollection.name}}</span></h2>
<div class="content">
<dl>
<dt>Config name:</dt>
<dd class="value">{{selectedCollection.configName}}</dd>
<dt>Max shards per node:</dt>
<dd class="value">{{selectedCollection.maxShardsPerNode}}</dd>
<dt>Replication factor:</dt>
<dd class="value">{{selectedCollection.replicationFactor}}</dd>
<dt>Auto-add replicas:</dt>
<dd class="ico value" ng-class="selectedCollection.autoAddReplicas ? 'ico-1' : 'ico-0'"><span>yes</span></dd>
<dt>Router name:</dt>
<dd class="value">{{selectedCollection.router.name}}</dd>
</dl>
</div>
</div>
<div id="shards" class="block fieldlist">
<h2><span>Shards</span></h2>
<div>
<div class="shard" ng-repeat="(name, shard) in selectedCollection.shards">
<a ng-click="hideShard(shard)"><h3 class="shard-title">{{name}}</h3></a>
<dl class="shard-detail clearfix" ng-hide="shard.hide">
<dt>Range:</dt>
<dd class="value">{{ shard.range }}</dd>
<dt>Active:</dt>
<dd class="ico value" ng-class="shard.state='active' ? 'ico-1' : 'ico-0'"><span>yes</span></dd>
<dt>Replicas:</dt>
<dd>
<div class="replica clearfix {{$odd?'odd':''}}" ng-repeat="(name, replica) in shard.replicas">
<a ng-click="showReplica(replica)"><h3>{{replica.core}}</h3></a>
<dl ng-show="replica.show">
<dt>Base URL: </dt><dd>{{replica.base_url}}</dd>
<dt>Core: </dt><dd><a href="{{replica.base_url}}/{{replica.core}}">{{replica.core}}</a></dd>
<dt>Leader: </dt>
<dd class="ico value" ng-class="selectedCollection.autoAddReplicas ? 'ico-1' : 'ico-0'"><span>yes</span></dd>
</dl>
</div>
</dd>
</dl>
</div>
</div>
</div>
</div>

View File

@ -106,10 +106,10 @@ limitations under the License.
<form> <form>
<p class="clearfix"><label for="swap_core">this:</label> <p class="clearfix"><label for="swap_core">this:</label>
<input type="text" id="swap_core" name="core" ng-model="currentCore" readonly="readonly"></p> <input type="text" id="swap_core" name="core" ng-model="selectedCore" readonly="readonly"></p>
<p class="clearfix"><label for="swap_other">and:</label> <p class="clearfix"><label for="swap_other">and:</label>
<select name="other" ng-model="swapOther" ng-options="core.name as core.name for core in cores" class="other"> <select name="other" ng-model="swapOther" ng-options="core.name as core.name for core in corelist" class="other">
</select></p> </select></p>
<p class="clearfix note error" ng-show="swapMessage"> <p class="clearfix note error" ng-show="swapMessage">

View File

@ -112,6 +112,8 @@ limitations under the License.
<div class="trigger"> <div class="trigger">
<button class="submit" ng-click="toggleTerms()"><span ng-class="{loader:isLoadingTerms}">Load Term Info</span></button> <button class="submit" ng-click="toggleTerms()"><span ng-class="{loader:isLoadingTerms}">Load Term Info</span></button>
<br/>
<span ng-show="isCloudEnabled">N.B. Loaded from a single core - not from the whole collection.</span>
<a ng-show="showTerms" ng-click="toggleAutoload()" ng-class="{on:isAutoload}" class="autoload" title="Automatically load Term Info?"><span>Autoload</span></a> <a ng-show="showTerms" ng-click="toggleAutoload()" ng-class="{on:isAutoload}" class="autoload" title="Automatically load Term Info?"><span>Autoload</span></a>