Цей коміт міститься в:
2025-02-20 14:57:11 +08:00
коміт 687bda5ead
1924 змінених файлів з 4379193 додано та 0 видалено
+506
Переглянути файл
@@ -0,0 +1,506 @@
/*
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.
*/
var solrAdminApp = angular.module("solrAdminApp", [
"ngResource",
"ngRoute",
"ngCookies",
"ngtimeago",
"solrAdminServices",
"localytics.directives",
"ab-base64"
]);
solrAdminApp.config([
'$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/index.html',
controller: 'IndexController'
}).
when('/login', {
templateUrl: 'partials/login.html',
controller: 'LoginController'
}).
when('/~logging', {
templateUrl: 'partials/logging.html',
controller: 'LoggingController'
}).
when('/~logging/level', {
templateUrl: 'partials/logging-levels.html',
controller: 'LoggingLevelController'
}).
when('/~cloud', {
templateUrl: 'partials/cloud.html',
controller: 'CloudController'
}).
when('/~cores', {
templateUrl: 'partials/cores.html',
controller: 'CoreAdminController'
}).
when('/~cores/:corename', {
templateUrl: 'partials/cores.html',
controller: 'CoreAdminController'
}).
when('/~collections', {
templateUrl: 'partials/collections.html',
controller: 'CollectionsController'
}).
when('/~collections/:collection', {
templateUrl: 'partials/collections.html',
controller: 'CollectionsController'
}).
when('/~threads', {
templateUrl: 'partials/threads.html',
controller: 'ThreadsController'
}).
when('/~java-properties', {
templateUrl: 'partials/java-properties.html',
controller: 'JavaPropertiesController'
}).
when('/~cluster-suggestions', {
templateUrl: 'partials/cluster_suggestions.html',
controller: 'ClusterSuggestionsController'
}).
when('/:core/core-overview', {
templateUrl: 'partials/core_overview.html',
controller: 'CoreOverviewController'
}).
when('/:core/collection-overview', {
templateUrl: 'partials/collection_overview.html',
controller: 'CollectionOverviewController'
}).
when('/:core/analysis', {
templateUrl: 'partials/analysis.html',
controller: 'AnalysisController'
}).
when('/:core/dataimport', {
templateUrl: 'partials/dataimport.html',
controller: 'DataImportController'
}).
when('/:core/dataimport/:handler*', {
templateUrl: 'partials/dataimport.html',
controller: 'DataImportController'
}).
when('/:core/documents', {
templateUrl: 'partials/documents.html',
controller: 'DocumentsController'
}).
when('/:core/files', {
templateUrl: 'partials/files.html',
controller: 'FilesController'
}).
when('/:core/plugins', {
templateUrl: 'partials/plugins.html',
controller: 'PluginsController',
reloadOnSearch: false
}).
when('/:core/plugins/:legacytype', {
templateUrl: 'partials/plugins.html',
controller: 'PluginsController',
reloadOnSearch: false
}).
when('/:core/query', {
templateUrl: 'partials/query.html',
controller: 'QueryController'
}).
when('/:core/stream', {
templateUrl: 'partials/stream.html',
controller: 'StreamController'
}).
when('/:core/replication', {
templateUrl: 'partials/replication.html',
controller: 'ReplicationController'
}).
when('/:core/dataimport', {
templateUrl: 'partials/dataimport.html',
controller: 'DataImportController'
}).
when('/:core/dataimport/:handler*', {
templateUrl: 'partials/dataimport.html',
controller: 'DataImportController'
}).
when('/:core/schema', {
templateUrl: 'partials/schema.html',
controller: 'SchemaController'
}).
when('/:core/segments', {
templateUrl: 'partials/segments.html',
controller: 'SegmentsController'
}).
otherwise({
redirectTo: '/'
});
}])
.constant('Constants', {
IS_ROOT_PAGE: 1,
IS_CORE_PAGE: 2,
IS_COLLECTION_PAGE: 3,
ROOT_URL: "/"
})
.filter('uriencode', function() {
return window.encodeURIComponent;
})
.filter('highlight', function($sce) {
return function(input, lang) {
if (lang && input && lang!="txt" && lang!="csv") return hljs.highlight(lang, input).value;
return input;
}
})
.filter('unsafe', function($sce) { return $sce.trustAsHtml; })
.directive('loadingStatusMessage', function() {
return {
link: function($scope, $element, attrs) {
var show = function() {$element.css('display', 'block')};
var hide = function() {$element.css('display', 'none')};
$scope.$on('loadingStatusActive', show);
$scope.$on('loadingStatusInactive', hide);
}
};
})
.directive('escapePressed', function () {
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 27) {
scope.$apply(function (){
scope.$eval(attrs.escapePressed);
});
event.preventDefault();
}
});
};
})
.directive('focusWhen', function($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.focusWhen, function(value) {
if(value === true) {
$timeout(function() {
element[0].focus();
}, 100);
}
});
}
};
})
.directive('scrollableWhenSmall', function($window) {
return {
link: function(scope, element, attrs) {
var w = angular.element($window);
var checkFixedMenu = function() {
var shouldScroll = w.height() < (element.height() + $('#header').height() + 40);
element.toggleClass( 'scroll', shouldScroll);
};
w.bind('resize', checkFixedMenu);
w.bind('load', checkFixedMenu);
}
}
})
.filter('readableSeconds', function() {
return function(input) {
seconds = parseInt(input||0, 10);
var minutes = Math.floor( seconds / 60 );
var hours = Math.floor( minutes / 60 );
var text = [];
if( 0 !== hours ) {
text.push( hours + 'h' );
seconds -= hours * 60 * 60;
minutes -= hours * 60;
}
if( 0 !== minutes ) {
text.push( minutes + 'm' );
seconds -= minutes * 60;
}
if( 0 !== seconds ) {
text.push( ( '0' + seconds ).substr( -2 ) + 's' );
}
return text.join(' ');
};
})
.filter('number', function($locale) {
return function(input) {
var sep = {
'de_CH' : '\'',
'de' : '.',
'en' : ',',
'es' : '.',
'it' : '.',
'ja' : ',',
'sv' : ' ',
'tr' : '.',
'_' : '' // fallback
};
var browser = {};
var match = $locale.id.match( /^(\w{2})([-_](\w{2}))?$/ );
if (match[1]) {
browser.language = match[1].toLowerCase();
}
if (match[1] && match[3]) {
browser.locale = match[1] + '_' + match[3];
}
return ( input || 0 ).toString().replace(/\B(?=(\d{3})+(?!\d))/g,
sep[ browser.locale ] || sep[ browser.language ] || sep['_']);
};
})
.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
})
.directive('jstree', function($parse) {
return {
restrict: 'EA',
scope: {
data: '=',
onSelect: '&'
},
link: function(scope, element, attrs) {
scope.$watch("data", function(newValue, oldValue) {
if (newValue) {
var treeConfig = {
"plugins" : [ "themes", "json_data", "ui" ],
"json_data" : {
"data" : scope.data,
"progressive_render" : true
},
"core" : {
"animation" : 0
}
};
var tree = $(element).jstree(treeConfig);
tree.jstree('open_node','li:first');
if (tree) {
element.bind("select_node.jstree", function (event, data) {
scope.$apply(function() {
scope.onSelect({url: data.args[0].href, data: data});
});
});
}
}
}, true);
}
};
})
.directive('connectionMessage', function() {
return {
link: function($scope, $element, attrs) {
var show = function() {$element.css('display', 'block')};
var hide = function() {$element.css('display', 'none')};
$scope.$on('connectionStatusActive', show);
$scope.$on('connectionStatusInactive', hide);
}
};
})
.factory('httpInterceptor', function($q, $rootScope, $location, $timeout, $injector) {
var activeRequests = 0;
var started = function(config) {
if (activeRequests == 0) {
$rootScope.$broadcast('loadingStatusActive');
}
if ($rootScope.exceptions[config.url]) {
delete $rootScope.exceptions[config.url];
}
activeRequests++;
if (sessionStorage.getItem("auth.header")) {
config.headers['Authorization'] = sessionStorage.getItem("auth.header");
}
config.timeout = 10000;
return config || $q.when(config);
};
var ended = function(response) {
activeRequests--;
if (activeRequests == 0) {
$rootScope.$broadcast('loadingStatusInactive');
}
if ($rootScope.retryCount>0) {
$rootScope.connectionRecovered = true;
$rootScope.retryCount=0;
$timeout(function() {
$rootScope.connectionRecovered=false;
$rootScope.$broadcast('connectionStatusInactive');
},2000);
}
if (!$location.path().startsWith('/login')) {
sessionStorage.removeItem("http401");
sessionStorage.removeItem("auth.state");
sessionStorage.removeItem("auth.statusText");
}
return response || $q.when(response);
};
var failed = function(rejection) {
activeRequests--;
if (activeRequests == 0) {
$rootScope.$broadcast('loadingStatusInactive');
}
if (rejection.config.headers.doNotIntercept) {
return rejection;
}
if (rejection.status === 0) {
$rootScope.$broadcast('connectionStatusActive');
if (!$rootScope.retryCount) $rootScope.retryCount=0;
$rootScope.retryCount ++;
var $http = $injector.get('$http');
var result = $http(rejection.config);
return result;
} else if (rejection.status === 401) {
// Authentication redirect
var headers = rejection.headers();
var wwwAuthHeader = headers['www-authenticate'];
sessionStorage.setItem("auth.wwwAuthHeader", wwwAuthHeader);
sessionStorage.setItem("auth.statusText", rejection.statusText);
sessionStorage.setItem("http401", "true");
sessionStorage.removeItem("auth.scheme");
sessionStorage.removeItem("auth.realm");
sessionStorage.removeItem("auth.username");
sessionStorage.removeItem("auth.header");
sessionStorage.removeItem("auth.state");
if ($location.path().includes('/login')) {
if (!sessionStorage.getItem("auth.location")) {
sessionStorage.setItem("auth.location", "/");
}
} else {
sessionStorage.setItem("auth.location", $location.path());
$location.path('/login');
}
} else {
$rootScope.exceptions[rejection.config.url] = rejection.data.error;
}
return $q.reject(rejection);
};
return {request: started, response: ended, responseError: failed};
})
.config(function($httpProvider) {
$httpProvider.interceptors.push("httpInterceptor");
// Force BasicAuth plugin to serve us a 'Authorization: xBasic xxxx' header so browser will not pop up login dialogue
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
})
.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]);
});
});
}
};
});
solrAdminApp.controller('MainController', function($scope, $route, $rootScope, $location, Cores, Collections, System, Ping, Constants) {
$rootScope.exceptions={};
$rootScope.toggleException = function() {
$scope.showException=!$scope.showException;
};
$scope.refresh = function() {
$scope.cores = [];
$scope.collections = [];
}
$scope.refresh();
$scope.resetMenu = function(page, pageType) {
Cores.list(function(data) {
$scope.cores = [];
var currentCoreName = $route.current.params.core;
delete $scope.currentCore;
for (key in data.status) {
var core = data.status[key];
$scope.cores.push(core);
if ((!$scope.isSolrCloud || pageType == Constants.IS_CORE_PAGE) && core.name == currentCoreName) {
$scope.currentCore = core;
}
}
$scope.showInitFailures = Object.keys(data.initFailures).length>0;
$scope.initFailures = data.initFailures;
});
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.showingCloud = page.lastIndexOf("cloud", 0) === 0;
$scope.page = page;
$scope.currentUser = sessionStorage.getItem("auth.username");
$scope.http401 = sessionStorage.getItem("http401");
};
$scope.ping = function() {
Ping.ping({core: $scope.currentCore.name}, function(data) {
$scope.showPing = true;
$scope.pingMS = data.responseHeader.QTime;
});
// @todo .attr( 'title', '/admin/ping is not configured (' + xhr.status + ': ' + error_thrown + ')' );
};
$scope.dumpCloud = function() {
$scope.$broadcast("cloud-dump");
}
$scope.showCore = function(core) {
$location.url("/" + core.name + "/core-overview");
}
$scope.showCollection = function(collection) {
$location.url("/" + collection.name + "/collection-overview")
}
$scope.$on('$routeChangeStart', function() {
$rootScope.exceptions = {};
});
});
+201
Переглянути файл
@@ -0,0 +1,201 @@
/*
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('AnalysisController',
function($scope, $location, $routeParams, Luke, Analysis, Constants) {
$scope.resetMenu("analysis", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function() {
Luke.schema({core: $routeParams.core}, function(data) {
$scope.fieldsAndTypes = [];
for (var field in data.schema.fields) {
$scope.fieldsAndTypes.push({
group: "Fields",
value: "fieldname=" + field,
label: field});
}
for (var type in data.schema.types) {
$scope.fieldsAndTypes.push({
group: "Types",
value: "fieldtype=" + type,
label: type});
}
$scope.core = $routeParams.core;
});
$scope.parseQueryString();
// @todo - set defaultSearchField either to context["analysis.fieldname"] or context["analysis.fieldtype"]
};
$scope.verbose = true;
var getShortComponentName = function(longname) {
var short = -1 !== longname.indexOf( '$' )
? longname.split( '$' )[1]
: longname.split( '.' ).pop();
return short.match( /[A-Z]/g ).join( '' );
};
var getCaptionsForComponent = function(data) {
var captions = [];
for (var key in data[0]) {
key = key.replace(/.*#/,'');
if (key != "match" && key!="positionHistory") {
captions.push(key.replace(/.*#/,''));
}
}
return captions;
};
var getTokensForComponent = function(data) {
var tokens = [];
var previousPosition = 0;
var index=0;
for (var i in data) {
var tokenhash = data[i];
var positionDifference = tokenhash.position - previousPosition;
for (var j=positionDifference; j>1; j--) {
tokens.push({position: tokenhash.position - j+1, blank:true, index:index++});
}
var token = {position: tokenhash.position, keys:[], index:index++};
for (key in tokenhash) {
if (key == "match" || key=="positionHistory") {
//skip, to not display these keys in the UI
} else {
var tokenInfo = new Object();
tokenInfo.name = key;
tokenInfo.value = tokenhash[key];
if ('text' === key || 'raw_bytes' === key ) {
if (tokenhash.match) {
tokenInfo.extraclass = 'match'; //to highlight matching text strings
}
}
token.keys.push(tokenInfo);
}
}
tokens.push(token);
previousPosition = tokenhash.position;
}
return tokens;
};
var extractComponents = function(data, result, name) {
if (data) {
result[name] = [];
for (var i = 0; i < data.length; i += 2) {
var component = {
name: data[i],
short: getShortComponentName(data[i]),
captions: getCaptionsForComponent(data[i + 1]),
tokens: getTokensForComponent(data[i + 1])
};
result[name].push(component);
}
}
};
var processAnalysisData = function(analysis, fieldOrType) {
var fieldname;
for (fieldname in analysis[fieldOrType]) {console.log(fieldname);break;}
var response = {};
extractComponents(analysis[fieldOrType][fieldname].index, response, "index");
extractComponents(analysis[fieldOrType][fieldname].query, response, "query");
return response;
};
$scope.updateQueryString = function() {
var parts = $scope.fieldOrType.split("=");
var fieldOrType = parts[0];
var name = parts[1];
if ($scope.indexText) {
$location.search("analysis.fieldvalue", $scope.indexText);
} else if ($location.search()["analysis.fieldvalue"]) {
$location.search("analysis.fieldvalue", null);
}
if ($scope.queryText) {
$location.search("analysis.query", $scope.queryText);
} else if ($location.search()["analysis.query"]) {
$location.search("analysis.query", null);
}
if (fieldOrType == "fieldname") {
$location.search("analysis.fieldname", name);
$location.search("analysis.fieldtype", null);
} else {
$location.search("analysis.fieldtype", name);
$location.search("analysis.fieldname", null);
}
$location.search("verbose_output", $scope.verbose ? "1" : "0");
};
$scope.parseQueryString = function () {
var params = {};
var search = $location.search();
if (Object.keys(search).length == 0) {
return;
}
for (var key in search) {
params[key]=search[key];
}
$scope.indexText = search["analysis.fieldvalue"];
$scope.queryText = search["analysis.query"];
if (search["analysis.fieldname"]) {
$scope.fieldOrType = "fieldname=" + search["analysis.fieldname"];
$scope.schemaBrowserUrl = "field=" + search["analysis.fieldname"];
} else {
$scope.fieldOrType = "fieldtype=" + search["analysis.fieldtype"];
$scope.schemaBrowserUrl = "type=" + search["analysis.fieldtype"];
}
if (search["verbose_output"] == undefined) {
$scope.verbose = true;
} else {
$scope.verbose = search["verbose_output"] == "1";
}
if ($scope.fieldOrType || $scope.indexText || $scope.queryText) {
params.core = $routeParams.core;
var parts = $scope.fieldOrType.split("=");
var fieldOrType = parts[0] == "fieldname" ? "field_names" : "field_types";
Analysis.field(params, function(data) {
$scope.result = processAnalysisData(data.analysis, fieldOrType);
});
}
};
$scope.changeFieldOrType = function() {
var parts = $scope.fieldOrType.split("=");
if (parts[0]=='fieldname') {
$scope.schemaBrowserUrl = "field=" + parts[1];
} else {
$scope.schemaBrowserUrl = "type=" + parts[1];
}
};
$scope.toggleVerbose = function() {
$scope.verbose = !$scope.verbose;
$scope.updateQueryString();
};
$scope.refresh();
}
);
Різницю між файлами не показано, бо вона завелика Завантажити різницю
+62
Переглянути файл
@@ -0,0 +1,62 @@
/*
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('ClusterSuggestionsController',
function($scope, $http, Constants) {
$scope.resetMenu("cluster-suggestion", Constants.IS_COLLECTION_PAGE);
$scope.data={};
var dataArr =[];
var dataJson = {};
//function to display suggestion
$http({
method: 'GET',
url: '/api/cluster/autoscaling/suggestions'
}).then(function successCallback(response) {
$scope.data = response.data;
$scope.parsedData = $scope.data.suggestions;
}, function errorCallback(response) {
});
//function to perform operation
$scope.postdata = function (x) {
x.loading = true;
var path=x.operation.path;
var command=x.operation.command;
var fullPath='/api/'+path;
console.log(fullPath);
console.log(command);
$http.post(fullPath, JSON.stringify(command)).then(function (response) {
if (response.data)
console.log(response.data);
x.loading = false;
x.done = true;
x.run=true;
$scope.msg = "Command Submitted Successfully!";
}, function (response) {
x.failed=true;
$scope.msg = "Service does not exist";
$scope.statusval = response.status;
$scope.statustext = response.statusText;
$scope.headers = response.headers();
});
};
$scope.showPopover = function() {
$scope.popup = true;
};
$scope.hidePopover = function () {
$scope.popup = false;
};
});
+39
Переглянути файл
@@ -0,0 +1,39 @@
/*
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.rootUrl = Constants.ROOT_URL;
});
};
$scope.showReplica = function(replica) {
replica.show = !replica.show;
}
$scope.hideShard = function(shard) {
shard.hide = !shard.hide;
}
$scope.refresh();
});
+274
Переглянути файл
@@ -0,0 +1,274 @@
/*
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('CollectionsController',
function($scope, $routeParams, $location, $timeout, Collections, Zookeeper, Constants){
$scope.resetMenu("collections", Constants.IS_ROOT_PAGE);
$scope.refresh = function() {
$scope.rootUrl = Constants.ROOT_URL + "#/~collections/" + $routeParams.collection;
Collections.status(function (data) {
$scope.collections = [];
for (var name in data.cluster.collections) {
var collection = data.cluster.collections[name];
collection.name = name;
var shards = collection.shards;
collection.shards = [];
for (var shardName in shards) {
var shard = shards[shardName];
shard.name = shardName;
shard.collection = collection.name;
var replicas = shard.replicas;
shard.replicas = [];
for (var replicaName in replicas) {
var replica = replicas[replicaName];
replica.name = replicaName;
replica.collection = collection.name;
replica.shard = shard.name;
shard.replicas.push(replica);
}
collection.shards.push(shard);
}
$scope.collections.push(collection);
if ($routeParams.collection == name) {
$scope.collection = collection;
}
}
if ($routeParams.collection && !$scope.collection) {
alert("No collection called " + $routeParams.collection)
$location.path("/~collections");
}
$scope.liveNodes = data.cluster.liveNodes;
});
Zookeeper.configs(function(data) {
$scope.configs = [];
var items = data.tree[0].children;
for (var i in items) {
$scope.configs.push({name: items[i].data.title});
}
});
};
$scope.hideAll = function() {
$scope.showRename = false;
$scope.showAdd = false;
$scope.showDelete = false;
$scope.showSwap = false;
$scope.showCreateAlias = false;
$scope.showDeleteAlias = false;
};
$scope.showAddCollection = function() {
$scope.hideAll();
$scope.showAdd = true;
$scope.newCollection = {
name: "",
routerName: "compositeId",
numShards: 1,
configName: "",
replicationFactor: 1,
maxShardsPerNode: 1,
autoAddReplicas: 'false'
};
};
$scope.toggleCreateAlias = function() {
$scope.hideAll();
$scope.showCreateAlias = true;
}
$scope.toggleDeleteAlias = function() {
$scope.hideAll();
$scope.showDeleteAlias = true;
Zookeeper.aliases({}, function(data){
if (Object.keys(data.aliases).length == 0) {
delete $scope.aliases;
} else {
$scope.aliases = data.aliases;
}
});
}
$scope.cancelCreateAlias = $scope.cancelDeleteAlias = function() {
$scope.hideAll();
}
$scope.createAlias = function() {
var collections = [];
for (var i in $scope.aliasCollections) {
collections.push($scope.aliasCollections[i].name);
}
Collections.createAlias({name: $scope.aliasToCreate, collections: collections.join(",")}, function(data) {
$scope.hideAll();
});
}
$scope.deleteAlias = function() {
Collections.deleteAlias({name: $scope.aliasToDelete}, function(data) {
$scope.hideAll();
});
};
$scope.addCollection = function() {
if (!$scope.newCollection.name) {
$scope.addMessage = "Please provide a core name";
} else if (false) { //@todo detect whether core exists
$scope.AddMessage = "A core with that name already exists";
} else {
var coll = $scope.newCollection;
var params = {
name: coll.name,
"router.name": coll.routerName,
numShards: coll.numShards,
"collection.configName": coll.configName,
replicationFactor: coll.replicationFactor,
maxShardsPerNode: coll.maxShardsPerNode,
autoAddReplicas: coll.autoAddReplicas
};
if (coll.shards) params.shards = coll.shards;
if (coll.routerField) params["router.field"] = coll.routerField;
Collections.add(params, function(data) {
$scope.cancelAddCollection();
$scope.resetMenu("collections", Constants.IS_ROOT_PAGE);
$location.path("/~collections/" + $scope.newCollection.name);
});
}
};
$scope.cancelAddCollection = function() {
delete $scope.addMessage;
$scope.showAdd = false;
};
$scope.showDeleteCollection = function() {
$scope.hideAll();
if ($scope.collection) {
$scope.showDelete = true;
} else {
alert("No collection selected.");
}
};
$scope.deleteCollection = function() {
if ($scope.collection.name == $scope.collectionDeleteConfirm) {
Collections.delete({name: $scope.collection.name}, function (data) {
$location.path("/~collections");
});
} else {
$scope.deleteMessage = "Collection names do not match.";
}
};
$scope.reloadCollection = function() {
if (!$scope.collection) {
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");
});
};
$scope.toggleAddReplica = function(shard) {
$scope.hideAll();
shard.showAdd = !shard.showAdd;
delete $scope.addReplicaMessage;
Zookeeper.liveNodes({}, function(data) {
$scope.nodes = [];
var children = data.tree[0].children;
for (var child in children) {
$scope.nodes.push(children[child].data.title);
}
});
};
$scope.toggleRemoveReplica = function(replica) {
$scope.hideAll();
replica.showRemove = !replica.showRemove;
};
$scope.toggleRemoveShard = function(shard) {
$scope.hideAll();
shard.showRemove = !shard.showRemove;
};
$scope.deleteShard = function(shard) {
Collections.deleteShard({collection: shard.collection, shard:shard.name}, function(data) {
shard.deleted = true;
$timeout(function() {
$scope.refresh();
}, 2000);
});
}
$scope.deleteReplica = function(replica) {
Collections.deleteReplica({collection: replica.collection, shard:replica.shard, replica:replica.name}, function(data) {
replica.deleted = true;
$timeout(function() {
$scope.refresh();
}, 2000);
});
}
$scope.addReplica = function(shard) {
var params = {
collection: shard.collection,
shard: shard.name,
}
if (shard.replicaNodeName && shard.replicaNodeName != "") {
params.node = shard.replicaNodeName;
}
Collections.addReplica(params, function(data) {
shard.replicaAdded = true;
$timeout(function () {
shard.replicaAdded = false;
shard.showAdd = false;
$$scope.refresh();
}, 2000);
});
};
$scope.toggleShard = function(shard) {
shard.show = !shard.show;
}
$scope.toggleReplica = function(replica) {
replica.show = !replica.show;
}
$scope.refresh();
}
);
var flatten = function(data) {
var list = [];
for (var name in data) {
var entry = data[name];
entry.name = name;
list.push(entry);
}
return list;
}
+93
Переглянути файл
@@ -0,0 +1,93 @@
/*
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('CoreOverviewController',
function($scope, $rootScope, $routeParams, Luke, CoreSystem, Update, Replication, Ping, Constants) {
$scope.resetMenu("overview", Constants.IS_CORE_PAGE);
$scope.refreshIndex = function() {
Luke.index({core: $routeParams.core},
function(data) {
$scope.index = data.index;
delete $scope.statsMessage;
},
function(error) {
$scope.statsMessage = "Luke is not configured";
}
);
};
$scope.refreshReplication = function() {
Replication.details({core: $routeParams.core},
function(data) {
$scope.isSlave = data.details.isSlave == "true";
$scope.isMaster = data.details.isMaster == "true";
$scope.replication = data.details;
},
function(error) {
$scope.replicationMessage = "Replication is not configured";
});
};
$scope.refreshSystem = function() {
CoreSystem.get({core: $routeParams.core},
function(data) {
$scope.core = data.core;
delete $scope.systemMessage;
},
function(error) {
$scope.systemMessage = "/admin/system Handler is not configured";
}
);
};
$scope.refreshPing = function() {
Ping.status({core: $routeParams.core}, function(data) {
if (data.error) {
$scope.healthcheckStatus = false;
if (data.error.code == 503) {
$scope.healthcheckMessage = 'Ping request handler is not configured with a healthcheck file.';
}
} else {
$scope.healthcheckStatus = data.status == "enabled";
}
});
};
$scope.toggleHealthcheck = function() {
if ($scope.healthcheckStatus) {
Ping.disable(
function(data) {$scope.healthcheckStatus = false},
function(error) {$scope.healthcheckMessage = error}
);
} else {
Ping.enable(
function(data) {$scope.healthcheckStatus = true},
function(error) {$scope.healthcheckMessage = error}
);
}
};
$scope.refresh = function() {
$scope.refreshIndex();
$scope.refreshReplication();
$scope.refreshSystem();
$scope.refreshPing();
};
$scope.refresh();
});
+180
Переглянути файл
@@ -0,0 +1,180 @@
/*
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('CoreAdminController',
function($scope, $routeParams, $location, $timeout, $route, Cores, Update, Constants){
$scope.resetMenu("cores", Constants.IS_ROOT_PAGE);
$scope.selectedCore = $routeParams.corename; // use 'corename' not 'core' to distinguish from /solr/:core/
$scope.refresh = function() {
Cores.get(function(data) {
var coreCount = 0;
var cores = data.status;
for (_obj in cores) coreCount++;
$scope.hasCores = coreCount >0;
if (!$scope.selectedCore && coreCount==0) {
$scope.showAddCore();
return;
} else if (!$scope.selectedCore) {
for (firstCore in cores) break;
$scope.selectedCore = firstCore;
$location.path("/~cores/" + $scope.selectedCore).replace();
}
$scope.core = cores[$scope.selectedCore];
$scope.corelist = [];
$scope.swapCorelist = [];
for (var core in cores) {
$scope.corelist.push(cores[core]);
if (cores[core] != $scope.core) {
$scope.swapCorelist.push(cores[core]);
}
}
if ($scope.swapCorelist.length>0) {
$scope.swapOther = $scope.swapCorelist[0].name;
}
});
};
$scope.showAddCore = function() {
$scope.hideAll();
$scope.showAdd = true;
$scope.newCore = {
name: "new_core",
dataDir: "data",
instanceDir: "new_core",
config: "solrconfig.xml",
schema: "schema.xml",
collection: "",
shard: ""
};
};
$scope.addCore = function() {
if (!$scope.newCore.name) {
$scope.addMessage = "Please provide a core name";
} else if (false) { //@todo detect whether core exists
$scope.AddMessage = "A core with that name already exists";
} else {
var params = {
name: $scope.newCore.name,
instanceDir: $scope.newCore.instanceDir,
config: $scope.newCore.config,
schema: $scope.newCore.schema,
dataDir: $scope.newCore.dataDir
};
if ($scope.isCloud) {
params.collection = $scope.newCore.collection;
params.shard = $scope.newCore.shard;
}
Cores.add(params, function(data) {
$location.path("/~cores/" + $scope.newCore.name);
$scope.cancelAddCore();
});
}
};
$scope.cancelAddCore = function() {
delete $scope.addMessage;
$scope.showAdd = false
};
$scope.unloadCore = function() {
var answer = confirm( 'Do you really want to unload Core "' + $scope.selectedCore + '"?' );
if( !answer ) return;
Cores.unload({core: $scope.selectedCore}, function(data) {
$location.path("/~cores");
});
};
$scope.showRenameCore = function() {
$scope.hideAll();
$scope.showRename = true;
};
$scope.renameCore = function() {
if (!$scope.other) {
$scope.renameMessage = "Please provide a new name for the " + $scope.selectedCore + " core";
} else if ($scope.other == $scope.selectedCore) {
$scope.renameMessage = "New name must be different from the current one";
} else {
Cores.rename({core:$scope.selectedCore, other: $scope.other}, function(data) {
$location.path("/~cores/" + $scope.other);
$scope.cancelRename();
});
}
};
$scope.cancelRenameCore = function() {
$scope.showRename = false;
delete $scope.renameMessage;
$scope.other = "";
};
$scope.showSwapCores = function() {
$scope.hideAll();
$scope.showSwap = true;
};
$scope.swapCores = function() {
if (!$scope.swapOther) {
$scope.swapMessage = "Please select a core to swap with";
} else if ($scope.swapOther == $scope.selectedCore) {
$scope.swapMessage = "Cannot swap with the same core";
} else {
Cores.swap({core: $scope.selectedCore, other: $scope.swapOther}, function(data) {
$location.path("/~cores/" + $scope.swapOther);
delete $scope.swapOther;
$scope.cancelSwapCores();
});
}
};
$scope.cancelSwapCores = function() {
delete $scope.swapMessage;
$scope.showSwap = false;
}
$scope.reloadCore = function() {
if ($scope.initFailures[$scope.selectedCore]) {
delete $scope.initFailures[$scope.selectedCore];
$scope.showInitFailures = Object.keys(data.initFailures).length>0;
}
Cores.reload({core: $scope.selectedCore},
function(data) {
if (data.error) {
$scope.reloadFailure = true;
$timeout(function() {
$scope.reloadFailure = false;
$route.reload();
}, 1000);
} else {
$scope.reloadSuccess = true;
$timeout(function () {
$scope.reloadSuccess = false;
$route.reload();
}, 1000);
}
});
};
$scope.hideAll = function() {
$scope.showRename = false;
$scope.showAdd = false;
$scope.showSwap = false;
};
$scope.refresh();
}
);
+302
Переглянути файл
@@ -0,0 +1,302 @@
/*
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.
*/
var dataimport_timeout = 2000;
solrAdminApp.controller('DataImportController',
function($scope, $rootScope, $routeParams, $location, $timeout, $interval, $cookies, Mbeans, DataImport, Constants) {
$scope.resetMenu("dataimport", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function () {
Mbeans.info({core: $routeParams.core, cat: 'QUERY'}, function (data) {
var mbeans = data['solr-mbeans'][1];
$scope.handlers = [];
for (var key in mbeans) {
if (mbeans[key]['class'] !== key && mbeans[key]['class'] === 'org.apache.solr.handler.dataimport.DataImportHandler') {
$scope.handlers.push(key);
}
}
$scope.hasHandlers = $scope.handlers.length > 0;
if (!$routeParams.handler) {
$location.path("/" + $routeParams.core + "/dataimport/" + $scope.handlers[0]);
} else {
$scope.currentHandler = $routeParams.handler;
}
});
$scope.handler = $routeParams.handler;
if ($scope.handler && $scope.handler[0]=="/") {
$scope.handler = $scope.handler.substr(1);
}
if ($scope.handler) {
DataImport.config({core: $routeParams.core, name: $scope.handler}, function (data) {
try {
$scope.config = data.config;
var xml = $.parseXML(data.config);
$scope.entities = [];
$('document > entity', xml).each(function (i, element) {
$scope.entities.push($(element).attr('name'));
});
$scope.refreshStatus();
} catch (err) {
console.log(err);
}
});
}
$scope.lastUpdate = "unknown";
$scope.lastUpdateUTC = "";
};
$scope.toggleDebug = function () {
$scope.isDebugMode = !$scope.isDebugMode;
if ($scope.isDebugMode) {
// also enable Debug checkbox
$scope.form.showDebug = true;
}
$scope.showConfiguration = true;
}
$scope.toggleConfiguration = function () {
$scope.showConfiguration = !$scope.showConfiguration;
}
$scope.toggleRawStatus = function () {
$scope.showRawStatus = !$scope.showRawStatus;
}
$scope.toggleRawDebug = function () {
$scope.showRawDebug = !$scope.showRawDebug;
}
$scope.reload = function () {
DataImport.reload({core: $routeParams.core, name: $scope.handler}, function () {
$scope.reloaded = true;
$timeout(function () {
$scope.reloaded = false;
}, 5000);
$scope.refresh();
});
}
$scope.form = {
command: "full-import",
verbose: false,
clean: false,
commit: true,
showDebug: false,
custom: "",
core: $routeParams.core
};
$scope.submit = function () {
var params = {};
for (var key in $scope.form) {
if (key == "showDebug") {
if ($scope.form.showDebug) {
params["debug"] = true;
}
} else {
params[key] = $scope.form[key];
}
}
if (params.custom.length) {
var customParams = $scope.form.custom.split("&");
for (var i in customParams) {
var parts = customParams[i].split("=");
params[parts[0]] = parts[1];
}
}
delete params.custom;
if ($scope.isDebugMode) {
params.dataConfig = $scope.config;
}
params.core = $routeParams.core;
params.name = $scope.handler;
DataImport.post(params, function (data) {
$scope.rawResponse = JSON.stringify(data, null, 2);
$scope.refreshStatus();
});
};
$scope.abort = function () {
$scope.isAborting = true;
DataImport.abort({core: $routeParams.core, name: $scope.handler}, function () {
$timeout(function () {
$scope.isAborting = false;
$scope.refreshStatus();
}, 4000);
});
}
$scope.refreshStatus = function () {
console.log("Refresh Status");
$scope.isStatusLoading = true;
DataImport.status({core: $routeParams.core, name: $scope.handler}, function (data) {
if (data[0] == "<") {
$scope.hasHandlers = false;
return;
}
var now = new Date();
$scope.lastUpdate = now.toTimeString().split(' ').shift();
$scope.lastUpdateUTC = now.toUTCString();
var messages = data.statusMessages;
var messagesCount = 0;
for( var key in messages ) { messagesCount++; }
if (data.status == 'busy') {
$scope.status = "indexing";
$scope.timeElapsed = data.statusMessages['Time Elapsed'];
$scope.elapsedSeconds = parseSeconds($scope.timeElapsed);
var info = $scope.timeElapsed ? 'Indexing since ' + $scope.timeElapsed : 'Indexing ...';
$scope.info = showInfo(messages, true, info, $scope.elapsedSeconds);
} else if (messages.RolledBack) {
$scope.status = "failure";
$scope.info = showInfo(messages, true);
} else if (messages.Aborted) {
$scope.status = "aborted";
$scope.info = showInfo(messages, true, 'Aborting current Import ...');
} else if (data.status == "idle" && messagesCount != 0) {
$scope.status = "success";
$scope.info = showInfo(messages, true);
} else {
$scope.status = "idle";
$scope.info = showInfo(messages, false, 'No information available (idle)');
}
delete data.$promise;
delete data.$resolved;
$scope.rawStatus = JSON.stringify(data, null, 2);
$scope.isStatusLoading = false;
$scope.statusUpdated = true;
$timeout(function () {
$scope.statusUpdated = false;
}, dataimport_timeout / 2);
});
};
$scope.updateAutoRefresh = function () {
$scope.autorefresh = !$scope.autorefresh;
$cookies.dataimport_autorefresh = $scope.autorefresh ? true : null;
if ($scope.autorefresh) {
$scope.refreshTimeout = $interval($scope.refreshStatus, dataimport_timeout);
var onRouteChangeOff = $scope.$on('$routeChangeStart', function() {
$interval.cancel($scope.refreshTimeout);
onRouteChangeOff();
});
} else if ($scope.refreshTimeout) {
$interval.cancel($scope.refreshTimeout);
}
$scope.refreshStatus();
};
$scope.refresh();
});
var showInfo = function (messages, showFull, info_text, elapsed_seconds) {
var info = {};
if (info_text) {
info.text = info_text;
} else {
info.text = messages[''] || '';
// format numbers included in status nicely
/* @todo this pretty printing is hard to work out how to do in an Angularesque way:
info.text = info.text.replace(/\d{4,}/g,
function (match, position, string) {
return app.format_number(parseInt(match, 10));
}
);
*/
var time_taken_text = messages['Time taken'];
info.timeTaken = parseSeconds(time_taken_text);
}
info.showDetails = false;
if (showFull) {
if (!elapsed_seconds) {
var time_taken_text = messages['Time taken'];
elapsed_seconds = parseSeconds(time_taken_text);
}
info.showDetails = true;
var document_config = {
'Requests': 'Total Requests made to DataSource',
'Fetched': 'Total Rows Fetched',
'Skipped': 'Total Documents Skipped',
'Processed': 'Total Documents Processed'
};
info.docs = [];
for (var key in document_config) {
var value = parseInt(messages[document_config[key]], 10);
var doc = {desc: document_config[key], name: key, value: value};
if (elapsed_seconds && key != 'Skipped') {
doc.speed = Math.round(value / elapsed_seconds);
}
info.docs.push(doc);
}
var dates_config = {
'Started': 'Full Dump Started',
'Aborted': 'Aborted',
'Rolledback': 'Rolledback'
};
info.dates = [];
for (var key in dates_config) {
var value = messages[dates_config[key]];
if (value) {
value = value.replace(" ", "T")+".000Z";
console.log(value);
var date = {desc: dates_config[key], name: key, value: value};
info.dates.push(date);
}
}
}
return info;
}
var parseSeconds = function(time) {
var seconds = 0;
var arr = new String(time || '').split('.');
var parts = arr[0].split(':').reverse();
for (var i = 0; i < parts.length; i++) {
seconds += ( parseInt(parts[i], 10) || 0 ) * Math.pow(60, i);
}
if (arr[1] && 5 <= parseInt(arr[1][0], 10)) {
seconds++; // treat more or equal than .5 as additional second
}
return seconds;
}
+137
Переглянути файл
@@ -0,0 +1,137 @@
/*
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, Constants) {
$scope.resetMenu("documents", Constants.IS_COLLECTION_PAGE);
$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.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.overwrite = $scope.overwrite;
params.core = $routeParams.core;
params.wt = "json";
if ($scope.type == "json" || $scope.type == "wizard") {
postData = "[" + $scope.document + "]";
contentType = "json";
} else if ($scope.type == "csv") {
postData = $scope.document;
contentType = "csv";
} else if ($scope.type == "xml") {
postData = "<add>" + $scope.document + "</add>";
contentType = "xml";
} else if ($scope.type == "upload") {
doingFileUpload = true;
params.raw = $scope.literalParams;
} else if ($scope.type == "solr") {
postData = $scope.document;
if (postData[0] == "<") {
contentType = "xml";
} else if (postData[0] == "{" || postData[0] == '[') {
contentType = "json";
} else {
alert("Cannot identify content type")
}
}
if (!doingFileUpload) {
var callback = function (success) {
$scope.responseStatus = "success";
delete success.$promise;
delete success.$resolved;
$scope.response = JSON.stringify(success, null, ' ');
};
var failure = function (failure) {
$scope.responseStatus = failure;
};
if (contentType == "json") {
Update.postJson(params, postData, callback, failure);
} else if (contentType == "xml") {
Update.postXml(params, postData, callback, failure);
} else if (contentType == "csv") {
Update.postCsv(params, postData, callback, 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, ' ');
});
}
}
});
+100
Переглянути файл
@@ -0,0 +1,100 @@
/*
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.
*/
var contentTypeMap = { xml : 'text/xml', html : 'text/html', js : 'text/javascript', json : 'application/json', 'css' : 'text/css' };
var languages = {js: "javascript", xml:"xml", xsl:"xml", vm: "xml", html: "xml", json: "json", css: "css"};
solrAdminApp.controller('FilesController',
function($scope, $rootScope, $routeParams, $location, Files, Constants) {
$scope.resetMenu("files", Constants.IS_COLLECTION_PAGE);
$scope.file = $location.search().file;
$scope.content = null;
$scope.baseurl = $location.absUrl().substr(0,$location.absUrl().indexOf("#")); // Including /solr/ context
$scope.refresh = function () {
var process = function (path, tree) {
var params = {core: $routeParams.core};
if (path.slice(-1) == '/') {
params.file = path.slice(0, -1);
} else if (path!='') {
params.file = path;
}
Files.list(params, function (data) {
var filenames = Object.keys(data.files);
filenames.sort();
for (var i in filenames) {
var file = filenames[i];
var filedata = data.files[file];
var state = undefined;
var children = undefined;
if (filedata.directory) {
file = file + "/";
if ($scope.file && $scope.file.indexOf(path + file) == 0) {
state = "open";
} else {
state = "closed";
}
children = [];
process(path + file, children);
}
tree.push({
data: {
title: file,
attr: { id: path + file}
},
children: children,
state: state
});
}
});
}
$scope.tree = [];
process("", $scope.tree);
if ($scope.file && $scope.file != '' && $scope.file.split('').pop()!='/') {
var extension;
if ($scope.file == "managed-schema") {
extension = contentTypeMap['xml'];
} else {
extension = $scope.file.match( /\.(\w+)$/)[1] || '';
}
var contentType = (contentTypeMap[extension] || 'text/plain' ) + ';charset=utf-8';
Files.get({core: $routeParams.core, file: $scope.file, contentType: contentType}, function(data) {
$scope.content = data.data;
$scope.url = data.config.url + "?" + $.param(data.config.params); // relative URL
if (contentType.indexOf("text/plain") && (data.data.indexOf("<?xml")>=0) || data.data.indexOf("<!--")>=0) {
$scope.lang = "xml";
} else {
$scope.lang = languages[extension] || "txt";
}
});
}
};
$scope.showTreeLink = function(data) {
var file = data.args[0].id;
$location.search({file:file});
};
$scope.refresh();
});
+97
Переглянути файл
@@ -0,0 +1,97 @@
/*
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('IndexController', function($scope, System, Cores, Constants) {
$scope.resetMenu("index", Constants.IS_ROOT_PAGE);
$scope.reload = function() {
System.get(function(data) {
$scope.system = data;
// load average
var load_average = ( data.system.uptime || '' ).match( /load averages?: (\d+[.,]\d\d),? (\d+[.,]\d\d),? (\d+[.,]\d\d)/ );
if (load_average) {
for (var i=0;i<2;i++) {
load_average[i]=load_average[i].replace(",","."); // for European users
}
$scope.load_average = load_average.slice(1);
}
// physical memory
var memoryMax = parse_memory_value(data.system.totalPhysicalMemorySize);
$scope.memoryTotal = parse_memory_value(data.system.totalPhysicalMemorySize - data.system.freePhysicalMemorySize);
$scope.memoryPercentage = ($scope.memoryTotal / memoryMax * 100).toFixed(1)+ "%";
$scope.memoryMax = pretty_print_bytes(memoryMax);
$scope.memoryTotalDisplay = pretty_print_bytes($scope.memoryTotal);
// swap space
var swapMax = parse_memory_value(data.system.totalSwapSpaceSize);
$scope.swapTotal = parse_memory_value(data.system.totalSwapSpaceSize - data.system.freeSwapSpaceSize);
$scope.swapPercentage = ($scope.swapTotal / swapMax * 100).toFixed(1)+ "%";
$scope.swapMax = pretty_print_bytes(swapMax);
$scope.swapTotalDisplay = pretty_print_bytes($scope.swapTotal);
// file handles
$scope.fileDescriptorPercentage = (data.system.openFileDescriptorCount / data.system.maxFileDescriptorCount *100).toFixed(1) + "%";
// java memory
var javaMemoryMax = parse_memory_value(data.jvm.memory.raw.max || data.jvm.memory.max);
$scope.javaMemoryTotal = parse_memory_value(data.jvm.memory.raw.total || data.jvm.memory.total);
$scope.javaMemoryUsed = parse_memory_value(data.jvm.memory.raw.used || data.jvm.memory.used);
$scope.javaMemoryTotalPercentage = ($scope.javaMemoryTotal / javaMemoryMax *100).toFixed(1) + "%";
$scope.javaMemoryUsedPercentage = ($scope.javaMemoryUsed / $scope.javaMemoryTotal *100).toFixed(1) + "%";
$scope.javaMemoryPercentage = ($scope.javaMemoryUsed / javaMemoryMax * 100).toFixed(1) + "%";
$scope.javaMemoryTotalDisplay = pretty_print_bytes($scope.javaMemoryTotal);
$scope.javaMemoryUsedDisplay = pretty_print_bytes($scope.javaMemoryUsed); // @todo These should really be an AngularJS Filter: {{ javaMemoryUsed | bytes }}
$scope.javaMemoryMax = pretty_print_bytes(javaMemoryMax);
// no info bar:
$scope.noInfo = !(
data.system.totalPhysicalMemorySize && data.system.freePhysicalMemorySize &&
data.system.totalSwapSpaceSize && data.system.freeSwapSpaceSize &&
data.system.openFileDescriptorCount && data.system.maxFileDescriptorCount);
// command line args:
$scope.commandLineArgs = data.jvm.jmx.commandLineArgs.sort();
});
};
$scope.reload();
});
var parse_memory_value = function( value ) {
if( value !== Number( value ) )
{
var units = 'BKMGTPEZY';
var match = value.match( /^(\d+([,\.]\d+)?) (\w).*$/ );
var value = parseFloat( match[1] ) * Math.pow( 1024, units.indexOf( match[3].toUpperCase() ) );
}
return value;
};
var pretty_print_bytes = function(byte_value) {
var unit = null;
byte_value /= 1024;
byte_value /= 1024;
unit = 'MB';
if( 1024 <= byte_value ) {
byte_value /= 1024;
unit = 'GB';
}
return byte_value.toFixed( 2 ) + ' ' + unit;
};
+45
Переглянути файл
@@ -0,0 +1,45 @@
/*
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('JavaPropertiesController',
function($scope, Properties, Constants){
$scope.resetMenu("java-props", Constants.IS_ROOT_PAGE);
$scope.refresh = function() {
Properties.get(function(data) {
var sysprops = data["system.properties"];
var sep = sysprops["path.separator"]
var props = [];
for (var key in sysprops) {
var value = sysprops[key];
var key = key.replace(/\./g, '.&#8203;');
if (key.indexOf(".path")!=-1 || key.indexOf(".dirs")) {
var values = [];
var parts = value.split(sep);
for (var i in parts) {
values.push({pos:i, value:parts[i]})
}
props.push({name: key, values: values});
} else {
props.push({name: key, values: [value]});
}
}
$scope.props = props;
});
};
$scope.refresh();
});
+158
Переглянути файл
@@ -0,0 +1,158 @@
/*
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.
*/
var format_time_content = function( time, timeZone ) {
var format_time_options = {};
if (timeZone && timeZone!="Local") {
format_time_options.timeZone = timeZone;
}
return time.toLocaleString( undefined, format_time_options );
}
solrAdminApp.controller('LoggingController',
function($scope, $timeout, $cookies, Logging, Constants){
$scope.resetMenu("logging", Constants.IS_ROOT_PAGE);
$scope.timezone = $cookies.logging_timezone || "Local";
$scope.refresh = function() {
Logging.events(function(data) {
$scope.since = new Date();
$scope.sinceDisplay = format_time_content($scope.since, "Local");
var events = data.history.docs;
for (var i=0; i<events.length; i++) {
var event = events[i];
var time = new Date(event.time);
event.local_time = format_time_content(time, "Local");
event.utc_time = format_time_content(time, "UTC");
event.loggerBase = event.logger.split( '.' ).pop();
if( !event.trace ) {
var lines = event.message.split( "\n" );
if( lines.length > 1) {
event.trace = event.message;
event.message = lines[0];
}
}
event.message = event.message.replace(/,/g, ',&#8203;');
event.showTrace = false;
}
$scope.events = events;
$scope.watcher = data.watcher;
/* @todo sticky_mode
// state element is in viewport
sticky_mode = ( state.position().top <= $( window ).scrollTop() + $( window ).height() - ( $( 'body' ).height() - state.position().top ) );
// initial request
if( 0 === since ) {
sticky_mode = true;
}
$scope.loggingEvents = events;
if( sticky_mode )
{
$( 'body' )
.animate
(
{ scrollTop: state.position().top },
1000
);
}
*/
});
$scope.timeout = $timeout($scope.refresh, 10000);
var onRouteChangeOff = $scope.$on('$routeChangeStart', function() {
$timeout.cancel($scope.timeout);
onRouteChangeOff();
});
};
$scope.refresh();
$scope.toggleRefresh = function() {
if(!$scope.stopped) {
$scope.stopped = true;
$timeout.cancel($scope.timeout);
} else {
$scope.stopped = false;
$scope.timeout = $timeout($scope.refresh, 10000);
}
};
$scope.toggleTimezone = function() {
$scope.timezone = ($scope.timezone=="Local") ? "UTC":"Local";
$cookies.logging_timezone = $scope.timezone;
}
$scope.toggleRow = function(event) {
event.showTrace =! event.showTrace;
};
}
)
.controller('LoggingLevelController',
function($scope, Logging) {
$scope.resetMenu("logging-levels");
var packageOf = function(logger) {
var parts = logger.name.split(".");
return !parts.pop() ? "" : parts.join(".");
};
var shortNameOf = function(logger) {return logger.name.split(".").pop();}
var makeTree = function(loggers, packag) {
var tree = [];
for (var i=0; i<loggers.length; i++) {
var logger = loggers[i];
logger.packag = packageOf(logger);
logger.short = shortNameOf(logger);
if (logger.packag == packag) {
logger.children = makeTree(loggers, logger.name);
tree.push(logger);
}
}
return tree;
};
$scope.refresh = function() {
Logging.levels(function(data) {
$scope.logging = makeTree(data.loggers, "");
$scope.watcher = data.watcher;
$scope.levels = [];
for (level in data.levels) {
$scope.levels.push({name:data.levels[level], pos:level});
}
});
};
$scope.toggleOptions = function(logger) {
if (logger.showOptions) {
logger.showOptions = false;
delete $scope.currentLogger;
} else {
if ($scope.currentLogger) {
$scope.currentLogger.showOptions = false;
}
logger.showOptions = true;
$scope.currentLogger = logger;
}
};
$scope.setLevel = function(logger, newLevel) {
var setString = logger.name + ":" + newLevel;
logger.showOptions = false;
Logging.setLevel({set: setString}, function(data) {
$scope.refresh();
});
};
$scope.refresh();
});
+150
Переглянути файл
@@ -0,0 +1,150 @@
/*
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('LoginController',
['$scope', '$routeParams', '$rootScope', '$location', '$window', 'AuthenticationService', 'Constants',
function ($scope, $routeParams, $rootScope, $location, $window, AuthenticationService, Constants) {
$scope.resetMenu("login", Constants.IS_ROOT_PAGE);
$scope.subPath = $routeParams.route;
$rootScope.exceptions = {};
// Session variables set in app.js 401 interceptor
var wwwAuthHeader = sessionStorage.getItem("auth.wwwAuthHeader");
var authScheme = sessionStorage.getItem("auth.scheme");
if (wwwAuthHeader) {
// Parse www-authenticate header
var wwwHeader = wwwAuthHeader.match(/(\w+)(\s+)?(.*)/);
authScheme = "unknown";
var authParams = {};
if (wwwHeader && wwwHeader.length >= 1)
authScheme = wwwHeader[1];
if (wwwHeader && wwwHeader.length >= 3)
authParams = www_auth_parse_params(wwwHeader[3]);
if (typeof authParams === 'string' || authParams instanceof String) {
$scope.authParamsError = authParams;
} else {
$scope.authParamsError = undefined;
}
var realm = authParams['realm'];
sessionStorage.setItem("auth.realm", realm);
if (authScheme === 'Basic' || authScheme === 'xBasic') {
authScheme = 'Basic';
}
sessionStorage.setItem("auth.scheme", authScheme);
}
var supportedSchemes = ['Basic', 'Bearer', 'Negotiate'];
$scope.authSchemeSupported = supportedSchemes.includes(authScheme);
$scope.authScheme = sessionStorage.getItem("auth.scheme");
$scope.authRealm = sessionStorage.getItem("auth.realm");
$scope.wwwAuthHeader = sessionStorage.getItem("auth.wwwAuthHeader");
$scope.statusText = sessionStorage.getItem("auth.statusText");
$scope.authConfig = sessionStorage.getItem("auth.config");
$scope.authLocation = sessionStorage.getItem("auth.location");
$scope.authLoggedinUser = sessionStorage.getItem("auth.username");
$scope.authHeader = sessionStorage.getItem("auth.header");
$scope.login = function () {
AuthenticationService.SetCredentials($scope.username, $scope.password);
$location.path($scope.authLocation); // Redirect to the location that caused the login prompt
};
$scope.logout = function() {
// reset login status
AuthenticationService.ClearCredentials();
$location.path("/");
};
$scope.isLoggedIn = function() {
return (sessionStorage.getItem("auth.username") !== null);
};
}]);
// This function is copied and adapted from MIT-licensed https://github.com/randymized/www-authenticate/blob/master/lib/parsers.js
www_auth_parse_params= function (header) {
// This parser will definitely fail if there is more than one challenge
var params = {};
var tok, last_tok, _i, _len, key, value;
var state= 0; //0: token,
var m= header.split(/([",=])/);
for (_i = 0, _len = m.length; _i < _len; _i++) {
last_tok= tok;
tok = m[_i];
if (!tok.length) continue;
switch (state) {
case 0: // token
key= tok.trim();
state= 1; // expect equals
continue;
case 1: // expect equals
if ('=' != tok) return 'Equal sign was expected after '+key;
state= 2;
continue;
case 2: // expect value
if ('"' == tok) {
value= '';
state= 3; // expect quoted
continue;
}
else {
params[key]= value= tok.trim();
state= 9; // expect comma or end
continue;
}
case 3: // handling quoted string
if ('"' == tok) {
state= 8; // end quoted
continue;
}
else {
value+= tok;
state= 3; // continue accumulating quoted string
continue;
}
case 8: // end quote encountered
if ('"' == tok) {
// double quoted
value+= '"';
state= 3; // back to quoted string
continue;
}
if (',' == tok) {
params[key]= value;
state= 0;
continue;
}
else {
return 'Unexpected token ('+tok+') after '+value+'"';
}
continue;
case 9: // expect commma
if (',' != tok) return 'Comma expected after '+value;
state= 0;
continue;
}
}
switch (state) { // terminal state
case 0: // Empty or ignoring terminal comma
case 9: // Expecting comma or end of header
return params;
case 8: // Last token was end quote
params[key]= value;
return params;
default:
return 'Unexpected end of www-authenticate value.';
}
};
+167
Переглянути файл
@@ -0,0 +1,167 @@
/*
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('PluginsController',
function($scope, $rootScope, $routeParams, $location, Mbeans, Constants) {
$scope.resetMenu("plugins", Constants.IS_CORE_PAGE);
if ($routeParams.legacytype) {
// support legacy URLs. Angular cannot change #path without reloading controller
$location.path("/"+$routeParams.core+"/plugins");
$location.search("type", $routeParams.legacytype);
return;
}
$scope.refresh = function() {
Mbeans.stats({core: $routeParams.core}, function (data) {
var type = $location.search().type;
$scope.types = getPluginTypes(data, type);
$scope.type = getSelectedType($scope.types, type);
if ($scope.type && $routeParams.entry) {
$scope.plugins = $routeParams.entry.split(",");
openPlugins($scope.type, $scope.plugins);
} else {
$scope.plugins = [];
}
});
};
$scope.selectPluginType = function(type) {
$location.search({entry:null, type: type.lower});
$scope.type = type;
};
$scope.selectPlugin = function(plugin) {
plugin.open = !plugin.open;
if (plugin.open) {
$scope.plugins.push(plugin.name);
} else {
$scope.plugins.splice($scope.plugins.indexOf(plugin.name), 1);
}
if ($scope.plugins.length==0) {
$location.search("entry", null);
} else {
$location.search("entry", $scope.plugins.join(','));
}
}
$scope.startRecording = function() {
$scope.isRecording = true;
Mbeans.reference({core: $routeParams.core}, function(data) {
$scope.reference = data.reference;
console.log($scope.reference);
})
}
$scope.stopRecording = function() {
$scope.isRecording = false;
console.log($scope.reference);
Mbeans.delta({core: $routeParams.core}, $scope.reference, function(data) {
parseDelta($scope.types, data);
});
}
$scope.refresh();
});
var getPluginTypes = function(data, selected) {
var keys = [];
var mbeans = data["solr-mbeans"];
for (var i=0; i<mbeans.length; i+=2) {
var key = mbeans[i];
var lower = key.toLowerCase();
var plugins = getPlugins(mbeans[i+1]);
if (plugins.length == 0) continue;
keys.push({name: key,
selected: lower == selected,
changes: 0,
lower: lower,
plugins: plugins
});
}
keys.sort(function(a,b) {return a.name > b.name});
return keys;
};
var getPlugins = function(data) {
var plugins = [];
for (var key in data) {
var pluginProperties = data[key];
var stats = pluginProperties.stats;
delete pluginProperties.stats;
for (var stat in stats) {
// add breaking space after a bracket or @ to handle wrap long lines:
stats[stat] = new String(stats[stat]).replace( /([\(@])/g, '$1&#8203;');
}
plugin = {name: key, changed: false, stats: stats, open:false};
plugin.properties = pluginProperties;
plugins.push(plugin);
}
plugins.sort(function(a,b) {return a.name > b.name});
return plugins;
};
var getSelectedType = function(types, selected) {
if (selected) {
for (var i in types) {
if (types[i].lower == selected) {
return types[i];
}
}
}
};
var parseDelta = function(types, data) {
var getByName = function(list, name) {
for (var i in list) {
if (list[i].name == name) return list[i];
}
}
var mbeans = data["solr-mbeans"]
for (var i=0; i<mbeans.length; i+=2) {
var typeName = mbeans[i];
var type = getByName(types, typeName);
var plugins = mbeans[i+1];
for (var key in plugins) {
var changedPlugin = plugins[key];
if (changedPlugin._changed_) {
var plugin = getByName(type.plugins, key);
var stats = changedPlugin.stats;
delete changedPlugin.stats;
plugin.properties = changedPlugin;
for (var stat in stats) {
// add breaking space after a bracket or @ to handle wrap long lines:
plugin.stats[stat] = new String(stats[stat]).replace( /([\(@])/g, '$1&#8203;');
}
plugin.changed = true;
type.changes++;
}
}
}
};
var openPlugins = function(type, selected) {
for (var i in type.plugins) {
var plugin = type.plugins[i];
plugin.open = selected.indexOf(plugin.name)>=0;
}
}
+118
Переглянути файл
@@ -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.
*/
solrAdminApp.controller('QueryController',
function($scope, $routeParams, $location, Query, Constants){
$scope.resetMenu("query", Constants.IS_COLLECTION_PAGE);
// @todo read URL parameters into scope
$scope.query = {q:'*:*'};
$scope.filters = [{fq:""}];
$scope.dismax = {defType: "dismax"};
$scope.edismax = {defType: "edismax", stopwords: true, lowercaseOperators: false};
$scope.hl = {hl:"on"};
$scope.facet = {facet: "on"};
$scope.spatial = {};
$scope.spellcheck = {spellcheck:"on"};
$scope.qt = "/select";
$scope.doQuery = function() {
var params = {};
var set = function(key, value) {
if (params[key]) {
params[key].push(value);
} else {
params[key] = [value];
}
}
var copy = function(params, query) {
for (var key in query) {
terms = query[key];
// Booleans have no length property - only set them if true
if (((typeof(terms) == typeof(true) && terms) || terms.length > 0) && key[0]!="$") {
set(key, terms);
}
}
};
copy(params, $scope.query);
if ($scope.isDismax) copy(params, $scope.dismax);
if ($scope.isEdismax) copy(params, $scope.edismax);
if ($scope.isHighlight) copy(params, $scope.hl);
if ($scope.isFacet) copy(params, $scope.facet);
if ($scope.isSpatial) copy(params, $scope.spatial);
if ($scope.isSpellcheck) copy(params, $scope.spellcheck);
if ($scope.rawParams) {
var rawParams = $scope.rawParams.split(/[&\n]/);
for (var i in rawParams) {
var param = rawParams[i];
var equalPos = param.indexOf("=");
if (equalPos > -1) {
set(param.substring(0, equalPos), param.substring(equalPos+1));
} else {
set(param, ""); // Use empty value for params without "="
}
}
}
var qt = $scope.qt ? $scope.qt : "/select";
for (var filter in $scope.filters) {
copy(params, $scope.filters[filter]);
}
params.core = $routeParams.core;
if (qt[0] == '/') {
params.handler = qt.substring(1);
} else { // Support legacy style handleSelect=true configs
params.handler = "select";
set("qt", qt);
}
var url = Query.url(params);
Query.query(params, function(data) {
$scope.lang = $scope.query.wt;
if ($scope.lang == undefined || $scope.lang == '') {
$scope.lang = "json";
}
$scope.response = data;
// Use relative URL to make it also work through proxies that may have a different host/port/context
$scope.url = url;
$scope.hostPortContext = $location.absUrl().substr(0,$location.absUrl().indexOf("#")); // For display only
});
};
if ($location.search().q) {
$scope.query.q = $location.search()["q"];
$scope.doQuery();
}
$scope.removeFilter = function(index) {
if ($scope.filters.length === 1) {
$scope.filters = [{fq: ""}];
} else {
$scope.filters.splice(index, 1);
}
};
$scope.addFilter = function(index) {
$scope.filters.splice(index+1, 0, {fq:""});
};
}
);
+235
Переглянути файл
@@ -0,0 +1,235 @@
/*
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('ReplicationController',
function($scope, $rootScope, $routeParams, $interval, $timeout, Replication, Constants) {
$scope.resetMenu("replication", Constants.IS_CORE_PAGE);
$scope.iterationCount = 1;
$scope.refresh = function() {
Replication.details({core:$routeParams.core}, function(response) {
var timeout;
var interval;
if ($scope.interval) $interval.cancel($scope.interval);
$scope.isSlave = (response.details.isSlave === 'true');
if ($scope.isSlave) {
$scope.progress = getProgressDetails(response.details.slave);
$scope.iterations = getIterations(response.details.slave);
$scope.versions = getSlaveVersions(response.details);
$scope.settings = getSlaveSettings(response.details);
if ($scope.settings.isReplicating) {
timeout = $timeout($scope.refresh, 1000);
} else if(!$scope.settings.isPollingDisabled && $scope.settings.pollInterval) {
interval = $scope.interval = $interval(function() {
$scope.settings.tick--;
}, 1000, $scope.settings.tick);
timeout = $timeout($scope.refresh, 1000*(1+$scope.settings.tick));
}
} else {
$scope.versions = getMasterVersions(response.details);
}
$scope.master = getMasterSettings(response.details, $scope.isSlave);
var onRouteChangeOff = $scope.$on('$routeChangeStart', function() {
if (interval) $interval.cancel(interval);
if (timeout) $timeout.cancel(timeout);
onRouteChangeOff();
});
});
};
$scope.execute = function(command) {
Replication.command({core:$routeParams.core, command:command}, function(data){$scope.refresh()});
}
$scope.showIterations = function() { $scope.iterationCount = 100000}; // limitTo should accept undefined, but doesn't work.
$scope.hideIterations = function() { $scope.iterationCount = 1};
$scope.refresh();
});
var getProgressDetails = function(progress) {
progress.timeRemaining = parseSeconds(progress.timeRemaining);
progress.totalPercent = parseInt(progress.totalPercent);
if (progress.totalPercent === 0) {
progress.totalPercentWidth = "1px";
} else {
progress.totalPercentWidth = progress.totalPercent + "%";
}
progress.currentFileSizePercent = parseInt(progress.currentFileSizePercent);
if (!progress.indexReplicatedAtList) {
progress.indexReplicatedAtList = [];
}
if (!progress.replicationFailedAtList) {
progress.replicationFailedAtList = [];
}
return progress;
};
var getIterations = function(slave) {
var iterations = [];
var find = function(list, date) {
return list.filter(function(e) {return e.date == date});
};
for (var i in slave.indexReplicatedAtList) {
var date = slave.indexReplicatedAtList[i];
var iteration = {date:date, status:"replicated", latest: false};
if (date == slave.indexReplicatedAt) {
iteration.latest = true;
}
iterations.push(iteration);
}
for (var i in slave.replicationFailedAtList) {
var failedDate = slave.replicationFailedAtList[i];
var matchingIterations = find(iterations, failedDate);
if (matchingIterations[0]) {
iteration = matchingIterations[0];
iteration.status = "failed";
} else {
iteration = {date: failedDate, status:"failed", latest:false};
iterations.push(iteration);
}
if (failedDate == slave.replicationFailedAt) {
iteration.latest = true;
}
}
iterations.sort(function(a,b){ return a.date> b.date;}).reverse();
return iterations;
};
var getMasterVersions = function(data) {
versions = {masterSearch:{}, master:{}};
versions.masterSearch.version = data.indexVersion;
versions.masterSearch.generation = data.generation;
versions.masterSearch.size = data.indexSize;
versions.master.version = data.master.replicableVersion || '-';
versions.master.generation = data.master.replicableGeneration || '-';
versions.master.size = '-';
return versions;
};
var getSlaveVersions = function(data) {
versions = {masterSearch: {}, master: {}, slave: {}};
versions.slave.version = data.indexVersion;
versions.slave.generation = data.generation;
versions.slave.size = data.indexSize;
versions.master.version = data.slave.masterDetails.replicableVersion || '-';
versions.master.generation = data.slave.masterDetails.replicableGeneration || '-';
versions.master.size = '-';
versions.masterSearch.version = data.slave.masterDetails.indexVersion;
versions.masterSearch.generation = data.slave.masterDetails.generation;
versions.masterSearch.size = data.slave.masterDetails.indexSize;
versions.changedVersion = data.indexVersion !== data.slave.masterDetails.indexVersion;
versions.changedGeneration = data.generation !== data.slave.masterDetails.generation;
return versions;
};
var parseDateToEpoch = function(date) {
// ["Sat Mar 03 11:00:00 CET 2012", "Sat", "Mar", "03", "11:00:00", "CET", "2012"]
var parts = date.match( /^(\w+)\s+(\w+)\s+(\d+)\s+(\d+\:\d+\:\d+)\s+(\w+)\s+(\d+)$/ );
// "Sat Mar 03 2012 10:37:33"
var d = new Date( parts[1] + ' ' + parts[2] + ' ' + parts[3] + ' ' + parts[6] + ' ' + parts[4] );
return d.getTime();
}
var parseSeconds = function(time) {
var seconds = 0;
var arr = new String(time || '').split('.');
var parts = arr[0].split(':').reverse();
for (var i = 0; i < parts.length; i++) {
seconds += ( parseInt(parts[i], 10) || 0 ) * Math.pow(60, i);
}
if (arr[1] && 5 <= parseInt(arr[1][0], 10)) {
seconds++; // treat more or equal than .5 as additional second
}
return seconds;
}
var getSlaveSettings = function(data) {
var settings = {};
settings.masterUrl = data.slave.masterUrl;
settings.isPollingDisabled = data.slave.isPollingDisabled == 'true';
settings.pollInterval = data.slave.pollInterval;
settings.isReplicating = data.slave.isReplicating == 'true';
settings.nextExecutionAt = data.slave.nextExecutionAt;
if(settings.isReplicating) {
settings.isApprox = true;
settings.tick = parseSeconds(settings.pollInterval);
} else if (!settings.isPollingDisabled && settings.pollInterval) {
if( settings.nextExecutionAt ) {
settings.nextExecutionAtEpoch = parseDateToEpoch(settings.nextExecutionAt);
settings.currentTime = parseDateToEpoch(data.slave.currentDate);
if( settings.nextExecutionAtEpoch > settings.currentTime) {
settings.isApprox = false;
settings.tick = ( settings.nextExecutionAtEpoch - settings.currentTime) / 1000;
}
}
}
return settings;
};
var getMasterSettings = function(details, isSlave) {
var master = {};
var masterData = isSlave ? details.slave.masterDetails.master : details.master;
master.replicationEnabled = masterData.replicationEnabled == "true";
master.replicateAfter = masterData.replicateAfter.join(", ");
if (masterData.confFiles) {
master.files = [];
var confFiles = masterData.confFiles.split(',');
for (var i=0; i<confFiles.length; i++) {
var file = confFiles[i];
var short = file;
var title = file;
if (file.indexOf(":")>=0) {
title = file.replace(':', ' » ');
var parts = file.split(':');
if (isSlave) {
short = parts[1];
} else {
short = parts[0];
}
}
master.files.push({title:title, name:short});
}
}
return master;
}
+611
Переглянути файл
@@ -0,0 +1,611 @@
/*
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.
*/
var cookie_schema_browser_autoload = 'schema-browser_autoload';
solrAdminApp.controller('SchemaController',
function($scope, $routeParams, $location, $cookies, $timeout, Luke, Constants, Schema, Config) {
$scope.resetMenu("schema", Constants.IS_COLLECTION_PAGE);
$scope.refresh = function () {
Luke.schema({core: $routeParams.core}, function (schema) {
Luke.raw({core: $routeParams.core}, function (index) {
var data = mergeIndexAndSchemaData(index, schema.schema);
$scope.fieldsAndTypes = getFieldsAndTypes(data);
$scope.is = {};
var search = $location.search();
leftbar = {};
$scope.isField = $scope.isDynamicField = $scope.isType = false;
$scope.showing = true;
if (search.field) {
$scope.selectedType = "Field";
$scope.is.field = true;
$scope.name = search.field;
leftbar.fields = [$scope.name];
var field = data.fields[$scope.name];
leftbar.types = [field.type];
if (field.dynamicBase) leftbar.dynamicFields = [field.dynamicBase];
if (field.copySources && field.copySources.length>0) {
leftbar.copyFieldSources = sortedObjectArray(field.copySources.sort());
}
if (field.copyDests && field.copyDests.length>0) {
leftbar.copyFieldDests = sortedObjectArray(field.copyDests.sort());
}
$scope.fieldOrType = "field=" + $scope.name;
} else if (search["dynamic-field"]) {
$scope.selectedType = "Dynamic Field";
$scope.is.dynamicField = true;
$scope.name = search["dynamic-field"];
leftbar.dynamicFields = [$scope.name];
leftbar.types = [data.dynamic_fields[$scope.name].type];
$scope.fieldOrType = "dynamic-field=" + $scope.name;
} else if (search.type) {
$scope.selectedType = "Type";
$scope.is.type = true;
$scope.name = search.type;
leftbar.types = [$scope.name];
leftbar.fields = filterFields("fields", data, $scope.name);
leftbar.dynamicFields = filterFields("dynamic_fields", data, $scope.name);
$scope.fieldOrType = "type=" + $scope.name;
} else {
$scope.showing = false;
}
$scope.leftbar = leftbar;
$scope.core = $routeParams.core;
$scope.uniqueKeyField = data.unique_key_field;
$scope.similarity = data.similarity;
if ($scope.similarity && $scope.similarity.className) {
$scope.similarity.className = shortenPackages($scope.similarity.className);
}
$scope.isUniqueKeyField = ($scope.selectedType == "Field" && $scope.name == $scope.uniqueKeyField);
$scope.display = getFieldProperties(data, $routeParams.core, $scope.is, $scope.name);
$scope.analysis = getAnalysisInfo(data, $scope.is, $scope.name);
$scope.isAutoload = $cookies[cookie_schema_browser_autoload] == "true";
if ($scope.isAutoload) {
$scope.toggleTerms();
}
$scope.types = Object.keys(schema.schema.types);
});
});
Config.get({core: $routeParams.core}, function(data) {
$scope.isSchemaUpdatable = (data.config.hasOwnProperty('schemaFactory') == false || data.config.schemaFactory.class == "ManagedIndexSchemaFactory");
});
};
$scope.refresh();
$scope.selectFieldOrType = function() {
$location.search($scope.fieldOrType);
}
$scope.toggleAnalyzer = function(analyzer) {
analyzer.show = !analyzer.show;
}
$scope.loadTermInfo = function() {
var params = {fl: $scope.name, core: $routeParams.core};
if ($scope.topTermsCount) {
params.numTerms = $scope.topTermsCount;
}
$scope.isLoadingTerms = true;
Luke.field(params, function (data) {
$scope.isLoadingTerms = false;
$scope.termInfo = getTermInfo(data.fields[$scope.name]);
if (!$scope.topTermsCount) {
$scope.topTermsCount = $scope.termInfo.termCount;
}
});
}
$scope.toggleTerms = function() {
$scope.showTerms = !$scope.showTerms;
if ($scope.showTerms) {
$scope.loadTermInfo();
}
}
$scope.loadAllTerms = function() {
$scope.topTermsCount = $scope.termInfo.maxTerms;
$scope.loadTermInfo();
}
$scope.toggleAutoload = function() {
$scope.isAutoload = !$scope.isAutoload;
$cookies[cookie_schema_browser_autoload] = $scope.isAutoload;
console.log("cookie: " + $cookies[cookie_schema_browser_autoload]);
}
$scope.hideAll = function() {
$scope.showAddField = false;
$scope.showAddDynamicField = false;
$scope.showAddCopyField = false;
}
$scope.toggleAddField = function() {
if ($scope.showAddField && $scope.adding == "field") {
$scope.hideAll();
} else {
$scope.hideAll();
$scope.showAddField = true;
$scope.adding = "field";
$scope.newField = {
stored: "true",
indexed: "true",
uninvertible: "true"
}
delete $scope.addErrors;
}
}
$scope.addField = function() {
delete $scope.addErrors;
var data = {"add-field": $scope.newField};
Schema.post({core: $routeParams.core}, data, function(data) {
if (data.errors) {
$scope.addErrors = data.errors[0].errorMessages;
if (typeof $scope.addErrors === "string") {
$scope.addErrors = [$scope.addErrors];
}
} else {
$scope.added = true;
$timeout(function() {
$scope.showAddField = false;
$scope.added = false;
$scope.refresh();
}, 1500);
}
});
}
$scope.toggleAddDynamicField = function() {
if ($scope.showAddField && $scope.adding == "dynamicField") {
$scope.hideAll();
} else {
$scope.hideAll();
$scope.showAddField = true;
$scope.adding = "dynamicField";
$scope.newField = {
stored: "true",
indexed: "true"
}
delete $scope.addErrors;
}
}
$scope.addDynamicField = function() {
delete $scope.addErrors;
var data = {"add-dynamic-field": $scope.newField};
Schema.post({core: $routeParams.core}, data, function(data) {
if (data.errors) {
$scope.addErrors = data.errors[0].errorMessages;
if (typeof $scope.addErrors === "string") {
$scope.addErrors = [$scope.addErrors];
}
} else {
$scope.added = true;
$timeout(function() {
$scope.showAddField = false;
$scope.added = false;
$scope.refresh();
}, 1500);
}
});
}
$scope.toggleAddCopyField = function() {
if ($scope.showAddCopyField) {
$scope.hideAll();
} else {
$scope.hideAll();
$scope.showAddCopyField = true;
$scope.copyField = {};
delete $scope.addCopyFieldErrors;
}
}
$scope.addCopyField = function() {
delete $scope.addCopyFieldErrors;
var data = {"add-copy-field": $scope.copyField};
Schema.post({core: $routeParams.core}, data, function(data) {
if (data.errors) {
$scope.addCopyFieldErrors = data.errors[0].errorMessages;
if (typeof $scope.addCopyFieldErrors === "string") {
$scope.addCopyFieldErrors = [$scope.addCopyFieldErrors];
}
} else {
$scope.showAddCopyField = false;
$timeout($scope.refresh, 1500);
}
});
}
$scope.toggleDelete = function() {
if ($scope.showDelete) {
$scope.showDelete = false;
} else {
if ($scope.is.field) {
$scope.deleteData = {'delete-field': {name: $scope.name}};
} else if ($scope.is.dynamicField) {
$scope.deleteData = {'delete-dynamic-field': {name: $scope.name}};
} else {
alert("TYPE NOT KNOWN");
}
$scope.showDelete = true;
}
}
$scope.delete = function() {
Schema.post({core: $routeParams.core}, $scope.deleteData, function(data) {
if (data.errors) {
$scope.deleteErrors = data.errors[0].errorMessages;
if (typeof $scope.deleteErrors === "string") {
$scope.deleteErrors = [$scope.deleteErrors];
}
} else {
$scope.deleted = true;
$timeout(function() {
$location.search("");
}, 1500
);
}
});
}
$scope.toggleDeleteCopyField = function(field) {
field.show = !field.show;
delete field.errors;
}
$scope.deleteCopyField = function(field, source, dest) {
data = {'delete-copy-field': {source: source, dest: dest}};
Schema.post({core: $routeParams.core}, data, function(data) {
if (data.errors) {
field.errors = data.errors[0].errorMessages;
if (typeof $scope.deleteErrors === "string") {
field.errors = [field.errors];
}
} else {
field.deleted = true;
$timeout($scope.refresh, 1500);
}
});
}
}
);
var getFieldsAndTypes = function(data) {
var fieldsAndTypes = [];
var fields = Object.keys(data.fields).sort();
for (var i in fields) {
fieldsAndTypes.push({
group: "Fields",
value: "field=" + fields[i],
label: fields[i]
});
}
var dynamic_fields = Object.keys(data.dynamic_fields).sort();
for (var i in dynamic_fields) {
fieldsAndTypes.push({
group: "Dynamic Fields",
value: "dynamic-field=" + dynamic_fields[i],
label: dynamic_fields[i]
});
}
var types = Object.keys(data.types).sort();
for (var i in types) {
fieldsAndTypes.push({
group: "Types",
value: "type=" + types[i],
label: types[i]
});
}
return fieldsAndTypes;
};
var filterFields = function(type, data, name) {
var fields = [];
for (var i in data.types[name].fields) {
var field = data.types[name].fields[i];
if (data[type][field]) {
fields.push(field)
}
}
return fields.sort();
}
var mergeIndexAndSchemaData = function(index, schema) {
var data = {
unique_key_field: null,
similarity: null,
key: {},
fields: {},
dynamic_fields: {},
types: {},
relations: {
f_df: {},
f_t: {},
df_f: {},
df_t: {},
t_f: {},
t_df: {}
}
};
data.fields = index.fields;
data.key = index.info.key;
data.unique_key_field = schema.uniqueKeyField;
data.similarity = schema.similarity;
data.dynamic_fields = schema.dynamicFields;
data.types = schema.types;
for (var field in schema.fields) {
data.fields[field] =
$.extend({}, data.fields[field], schema.fields[field]);
}
for (var field in data.fields) {
var copy_dests = data.fields[field].copyDests;
for (var i in copy_dests) {
var copy_dest = copy_dests[i];
if (!data.fields[copy_dest]) {
data.fields[copy_dest] = {
partial: true,
copySources: []
};
}
if (data.fields[copy_dest].partial) {
data.fields[copy_dest].copySources.push(field);
}
}
var copy_sources = data.fields[field].copySources;
for (var i in copy_sources) {
var copy_source = copy_sources[i];
if (!data.fields[copy_source]) {
data.fields[copy_source] = {
partial: true,
copyDests: []
};
}
if (data.fields[copy_source].partial) {
data.fields[copy_source].copyDests.push(field);
}
}
data.relations.f_t[field] = data.fields[field].type;
if (!data.relations.t_f[data.fields[field].type]) {
data.relations.t_f[data.fields[field].type] = [];
}
data.relations.t_f[data.fields[field].type].push(field);
if (data.fields[field].dynamicBase) {
data.relations.f_df[field] = data.fields[field].dynamicBase;
if (!data.relations.df_f[data.fields[field].dynamicBase]) {
data.relations.df_f[data.fields[field].dynamicBase] = [];
}
data.relations.df_f[data.fields[field].dynamicBase].push(field);
}
}
for (var dynamic_field in data.dynamic_fields) {
data.relations.df_t[dynamic_field] = data.dynamic_fields[dynamic_field].type;
if (!data.relations.t_df[data.dynamic_fields[dynamic_field].type]) {
data.relations.t_df[data.dynamic_fields[dynamic_field].type] = [];
}
data.relations.t_df[data.dynamic_fields[dynamic_field].type].push(dynamic_field);
}
return data;
};
var getFieldProperties = function(data, core, is, name) {
var display = {};
display.partialState = is.field && !!data.fields[name].partial;
display.columns = [];
display.rows = [];
var allFlags = "";
var addRow = function(name, flags) {
if (flags[0]!='(') {
display.rows.push({name:name, flags:flags});
for (var i in flags) {
if (flags[i]!="-" && allFlags.indexOf(flags[i])<0) {
allFlags+=flags[i];
}
}
} else {
display.rows.push({name:name, comment:flags});
}
}
// Identify the rows for our field property table
if (is.field && data.fields[name]) {
if (data.fields[name].flags) {
addRow('Properties', data.fields[name].flags);
}
if (data.fields[name].schema) {
addRow('Schema', data.fields[name].schema);
}
if (data.fields[name].index) {
addRow('Index', data.fields[name].index);
}
display.docs = data.fields[name].docs;
display.docsUrl = "#/" + core + "/query?q=" + name + ":[* TO *]";
display.distinct = data.fields[name].distinct;
display.positionIncrementGap = data.fields[name].positionIncrementGap;
if (data.types[data.fields[name].type]) {
display.similarity = data.types[data.fields[name].type].similarity;
} else {
display.similarity = null;
}
} else if (is.dynamicField && data.dynamic_fields[name] && data.dynamic_fields[name].flags) {
addRow('Properties', data.dynamic_fields[name].flags);
display.similarity = data.types[data.dynamic_fields[name].type].similarity;
} else if (is.type && data.types[name]) {
display.similarity = data.types[name].similarity;
}
if (display.similarity && display.similarity.className) {
display.similarity.className = shortenPackages(display.similarity.className);
}
// identify columns in field property table:
for (var key in data.key) {
if (allFlags.indexOf(key)>=0) {
display.columns.push({key: key, name: data.key[key]});
}
}
// identify rows and cell values in field property table:
for (var i in display.rows) {
var row = display.rows[i];
row.cells = [];
if (!row.flags) {
continue; // Match the special case in the LukeRequestHandler
}
for (var j in display.columns) {
var flag = display.columns[j].key;
row.cells.push({key: flag, value: row.flags.indexOf(flag)>=0});
}
}
return display;
};
var getAnalysisInfo = function(data, is, name) {
var analysis = {};
if (is.field) {
var type = data.relations.f_t[name];
analysis.query = "analysis.fieldname=" + name;
}
else if (is.dynamicField) {
var type = data.relations.df_t[name];
analysis.query = "analysis.fieldtype=" + type;
}
else if (is.type) {
var type = name;
analysis.query = "analysis.fieldtype=" + name;
}
var processComponentType = function (label, key, componentTypeData) {
if (componentTypeData) {
var components = [];
for (var componentName in componentTypeData) {
var componentData = componentTypeData[componentName];
var component = {className: componentData.className, args:[]};
if (componentData.args) {
for (var argName in componentData.args) {
var argValue = componentData.args[argName];
if (argValue == "1" || argValue == "true") {
component.args.push({name: argName, booleanValue:true});
} else if (argValue == "0" || argValue == "false") {
component.args.push({name: argName, booleanValue:false});
} else {
component.args.push({name: argName, value:argValue});
}
}
}
components.push(component);
}
return {label: label, key: key, components: components};
} else {
return {label: label, key: key};
}
}
var buildAnalyzer = function (analyzerData) {
var analyzer = {};
analyzer.className = analyzerData.className;
analyzer.componentTypes = [];
if (analyzerData.tokenizer) {
analyzer.componentTypes.push(processComponentType("Char Filters", "charFilters", analyzerData.charFilters));
analyzer.componentTypes.push(processComponentType("Tokenizer", "tokenizer", {tokenizer: analyzerData.tokenizer}));
analyzer.componentTypes.push(processComponentType("Token Filters", "tokenFilters", analyzerData.filters));
}
return analyzer;
}
analysis.data = data.types[type];
if (analysis.data) {
analysis.analyzers = [
{key: "index", name: "Index", detail: buildAnalyzer(analysis.data.indexAnalyzer)},
{key: "query", name: "Query", detail: buildAnalyzer(analysis.data.queryAnalyzer)}
];
}
return analysis;
}
var getTermInfo = function(data) {
var termInfo = {};
if (data && data.topTerms) {
termInfo.topTerms = [];
var currentGroup = {count: 0}
for (var i = 0; i < data.topTerms.length; i += 2) {
var count = data.topTerms[i + 1];
if (currentGroup.count != count) {
currentGroup = {count: count, terms: []};
termInfo.topTerms.push(currentGroup);
}
currentGroup.terms.push(data.topTerms[i]);
}
termInfo.termCount = data.topTerms.length / 2;
termInfo.maxTerms = data.distinct;
}
if(data && data.histogram) {
termInfo.histogram = [];
termInfo.histogramMax = 0;
for (var i = 0; i < data.histogram.length; i += 2) {
termInfo.histogram.push({key: data.histogram[i], value: data.histogram[i + 1]});
termInfo.histogramMax = Math.max(termInfo.histogramMax, data.histogram[i + 1]);
}
}
return termInfo;
};
var sortedObjectArray = function(list) {
var objarr = [];
for (var i in list) {
objarr.push({"name": list[i]});
}
return objarr;
};
var shortenPackages = function(className) {
return className.replace("org.apache.solr", "o.a.s").replace("org.apache.lucene", "o.a.l");
};
+99
Переглянути файл
@@ -0,0 +1,99 @@
/*
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.
*/
var MB_FACTOR = 1024*1024;
solrAdminApp.controller('SegmentsController', function($scope, $routeParams, $interval, Segments, Constants) {
$scope.resetMenu("segments", Constants.IS_CORE_PAGE);
$scope.refresh = function() {
Segments.get({core: $routeParams.core}, function(data) {
var segments = data.segments;
var segmentSizeInBytesMax = getLargestSegmentSize(segments);
$scope.segmentMB = Math.floor(segmentSizeInBytesMax / MB_FACTOR);
$scope.xaxis = calculateXAxis(segmentSizeInBytesMax);
$scope.documentCount = 0;
$scope.deletionCount = 0;
$scope.segments = [];
for (var name in segments) {
var segment = segments[name];
var segmentSizeInBytesLog = Math.log(segment.sizeInBytes);
var segmentSizeInBytesMaxLog = Math.log(segmentSizeInBytesMax);
segment.totalSize = Math.floor((segmentSizeInBytesLog / segmentSizeInBytesMaxLog ) * 100);
segment.deletedDocSize = Math.floor((segment.delCount / segment.size) * segment.totalSize);
if (segment.delDocSize <= 0.001) delete segment.deletedDocSize;
segment.aliveDocSize = segment.totalSize - segment.deletedDocSize;
$scope.segments.push(segment);
$scope.documentCount += segment.size;
$scope.deletionCount += segment.delCount;
}
$scope.deletionsPercentage = calculateDeletionsPercentage($scope.documentCount, $scope.deletionCount);
});
};
$scope.toggleAutoRefresh = function() {
$scope.autorefresh = !$scope.autorefresh;
if ($scope.autorefresh) {
$scope.interval = $interval($scope.refresh, 1000);
var onRouteChangeOff = $scope.$on('$routeChangeStart', function() {
$interval.cancel($scope.interval);
onRouteChangeOff();
});
} else if ($scope.interval) {
$interval.cancel($scope.interval);
}
};
$scope.refresh();
});
var calculateXAxis = function(segmentInBytesMax) {
var steps = [];
var log = Math.log(segmentInBytesMax);
for (var j=0, step=log/4; j<3; j++, step+=log/4) {
steps.push({pos:j, value:Math.floor((Math.pow(Math.E, step))/MB_FACTOR)})
}
return steps;
};
var getLargestSegmentSize = function(segments) {
var max = 0;
for (var name in segments) {
max = Math.max(max, segments[name].sizeInBytes);
}
return max;
};
var calculateDeletionsPercentage = function(docCount, delCount) {
if (docCount == 0) {
return 0;
} else {
var percent = delCount / docCount * 100;
return Math.round(percent * 100) / 100;
}
};
+239
Переглянути файл
@@ -0,0 +1,239 @@
/*
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('StreamController',
function($scope, $routeParams, $location, Query, Constants) {
$scope.resetMenu("stream", Constants.IS_COLLECTION_PAGE);
$scope.stream = {
wt: 'json',
expr: $scope.expr,
indent: 'on'
};
$scope.qt = "stream";
$scope.doExplanation = false
$scope.doStream = function() {
var params = {};
params.core = $routeParams.core;
params.handler = $scope.qt;
params.expr = [$scope.expr]
if($scope.doExplanation){
params.explain = [$scope.doExplanation]
}
$scope.lang = "json";
$scope.response = null;
$scope.url = "";
var url = Query.url(params);
Query.query(params, function(data) {
var jsonData = JSON.parse(data.toJSON().data);
if (undefined != jsonData["explanation"]) {
$scope.showExplanation = true;
streamGraphSubController($scope, jsonData["explanation"])
delete jsonData["explanation"]
} else {
$scope.showExplanation = false;
}
data.data = JSON.stringify(jsonData,null,2);
$scope.lang = "json";
$scope.response = data;
$scope.url = url;
$scope.hostPortContext = $location.absUrl().substr(0,$location.absUrl().indexOf("#")); // For display only
});
};
if ($location.search().expr) {
$scope.expr = $location.search()["expr"];
$scope.doStream();
}
}
);
var streamGraphSubController = function($scope, explanation) {
$scope.showGraph = true;
$scope.pos = 0;
$scope.rows = 8;
$scope.resetGraph = function() {
$scope.pos = 0;
$scope.initGraph();
}
$scope.initGraph = function(explanation) {
data = explanation
var leafCount = 0;
var maxDepth = 0;
var rootNode = {};
leafCount = 0;
let recurse = function(dataNode, depth) {
if (depth > maxDepth) {
maxDepth = depth;
}
let graphNode = {
name: dataNode.expressionNodeId,
implementingClass: 'unknown',
data: {}
};
["expressionNodeId", "expressionType", "functionName", "implementingClass", "expression", "note", "helpers"].forEach(function(key) {
graphNode.data[key] = dataNode[key];
});
if (dataNode.children && dataNode.children.length > 0) {
graphNode.children = [];
dataNode.children.forEach(function(n) {
graphNode.children.push(recurse(n, depth + 1));
});
} else {
++leafCount;
}
return graphNode;
}
$scope.showPaging = false;
$scope.isRadial = false;
$scope.explanationData = recurse(data, 1);
$scope.depth = maxDepth + 1;
$scope.leafCount = leafCount;
};
$scope.initGraph(explanation);
};
solrAdminApp.directive('explanationGraph', function(Constants) {
return {
restrict: 'EA',
scope: {
data: "=",
leafCount: "=",
depth: "="
},
link: function(scope, element, attrs) {
var helper_path_class = function(p) {
var classes = ['link'];
return classes.join(' ');
};
var helper_node_class = function(d) {
var classes = ['node'];
if (d.data && d.data.expressionType) {
classes.push(d.data.expressionType);
}
return classes.join(' ');
};
var helper_node_text = function(d) {
if (d.data && d.data.functionName) {
return d.data.functionName;
}
return d.name
};
var helper_tooltip = function(d) {
return [
"Function: " + d.data.functionName,
"Type: " + d.data.expressionType,
"Class: " + d.data.implementingClass.replace("org.apache.solr.client.solrj.io", "o.a.s.c.s.i"),
"=============",
d.data.expression
].join("\n");
}
scope.$watch("data", function(newValue, oldValue) {
if (newValue) {
flatGraph(element, scope.data, scope.depth, scope.leafCount);
}
});
var flatGraph = function(element, graphData, depth, leafCount) {
var w = 100 + (depth * 100),
h = leafCount * 40;
var tree = d3.layout.tree().size([h, w]);
var diagonal = d3.svg.diagonal().projection(function(d) {
return [d.y * .7, d.x];
});
d3.select('#canvas', element).html('');
var vis = d3.select('#canvas', element).append('svg')
.attr('width', w)
.attr('height', h)
.append('g')
.attr('transform', 'translate(25, 0)');
var nodes = tree.nodes(graphData);
var link = vis.selectAll('path.link')
.data(tree.links(nodes))
.enter().append('path')
.attr('class', helper_path_class)
.attr('d', diagonal);
var node = vis.selectAll('g.node')
.data(nodes)
.enter().append('g')
.attr('class', helper_node_class)
.attr('transform', function(d) {
return 'translate(' + d.y * .7 + ',' + d.x + ')';
})
node.append('circle')
.attr('r', 4.5);
node.append('title')
.text(helper_tooltip);
node.append('text')
.attr('dx', function(d) {
return 8;
})
.attr('dy', function(d) {
return 5;
})
.attr('text-anchor', function(d) {
return 'start';
})
.text(helper_node_text)
};
}
};
})
+50
Переглянути файл
@@ -0,0 +1,50 @@
/*
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('ThreadsController',
function($scope, Threads, Constants){
$scope.resetMenu("threads", Constants.IS_ROOT_PAGE);
$scope.refresh = function() {
Threads.get(function(data) {
var threadDump = data.system.threadDump;
var threads = [];
for (var i=1; i<threadDump.length; i+=2) {
var thread = threadDump[i];
if (!!thread.stackTrace) {
var stackTrace = [];
for (var j=0; j<thread.stackTrace.length; j++) {
var trace = thread.stackTrace[j].replace("(", "\u200B("); // allow wrapping to happen, \u200B is a zero-width space
stackTrace.push({id:thread.id + ":" + j, trace: trace});
}
thread.stackTrace = stackTrace;
}
threads.push(thread);
}
$scope.threads = threads;
});
};
$scope.toggleStacktrace = function(thread) {
thread.showStackTrace = !thread.showStackTrace;
};
$scope.toggleStacktraces = function() {
$scope.showAllStacktraces = !$scope.showAllStacktraces;
for (var i=0; i<$scope.threads.length; i++) {
$scope.threads[i].showStackTrace = $scope.showAllStacktraces;
}
};
$scope.refresh();
});
+287
Переглянути файл
@@ -0,0 +1,287 @@
/*
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.
*/
var solrAdminServices = angular.module('solrAdminServices', ['ngResource']);
solrAdminServices.factory('System',
['$resource', function($resource) {
return $resource('admin/info/system', {"wt":"json", "nodes": "@nodes", "_":Date.now()});
}])
.factory('Metrics',
['$resource', function($resource) {
return $resource('admin/metrics', {"wt":"json", "nodes": "@nodes", "prefix":"@prefix", "_":Date.now()});
}])
.factory('Collections',
['$resource', function($resource) {
return $resource('admin/collections',
{'wt':'json', '_':Date.now()}, {
"list": {params:{action: "LIST"}},
"status": {params:{action: "CLUSTERSTATUS"}},
"add": {params:{action: "CREATE"}},
"delete": {params:{action: "DELETE"}},
"rename": {params:{action: "RENAME"}},
"createAlias": {params:{action: "CREATEALIAS"}},
"deleteAlias": {params:{action: "DELETEALIAS"}},
"deleteReplica": {params:{action: "DELETEREPLICA"}},
"addReplica": {params:{action: "ADDREPLICA"}},
"deleteShard": {params:{action: "DELETESHARD"}},
"reload": {method: "GET", params:{action:"RELOAD", core: "@core"}}
});
}])
.factory('Cores',
['$resource', function($resource) {
return $resource('admin/cores',
{'wt':'json', '_':Date.now()}, {
"query": {},
"list": {params:{indexInfo: false}},
"add": {params:{action: "CREATE"}},
"unload": {params:{action: "UNLOAD", core: "@core"}},
"rename": {params:{action: "RENAME"}},
"swap": {params:{action: "SWAP"}},
"reload": {method: "GET", params:{action:"RELOAD", core: "@core"}, headers:{doNotIntercept: "true"}}
});
}])
.factory('Logging',
['$resource', function($resource) {
return $resource('admin/info/logging', {'wt':'json', '_':Date.now()}, {
"events": {params: {since:'0'}},
"levels": {},
"setLevel": {}
});
}])
.factory('Zookeeper',
['$resource', function($resource) {
return $resource('admin/zookeeper', {wt:'json', _:Date.now()}, {
"simple": {},
"liveNodes": {params: {path: '/live_nodes'}},
"clusterState": {params: {detail: "true", path: "/clusterstate.json"}},
"detail": {params: {detail: "true", path: "@path"}},
"configs": {params: {detail:false, path: "/configs/"}},
"aliases": {params: {detail: "true", path: "/aliases.json"}, transformResponse:function(data) {
var znode = $.parseJSON(data).znode;
if (znode.data) {
return {aliases: $.parseJSON(znode.data).collection};
} else {
return {aliases: {}};
}
}}
});
}])
.factory('ZookeeperStatus',
['$resource', function($resource) {
return $resource('admin/zookeeper/status', {wt:'json', _:Date.now()}, {
"monitor": {}
});
}])
.factory('Properties',
['$resource', function($resource) {
return $resource('admin/info/properties', {'wt':'json', '_':Date.now()});
}])
.factory('Threads',
['$resource', function($resource) {
return $resource('admin/info/threads', {'wt':'json', '_':Date.now()});
}])
.factory('Properties',
['$resource', function($resource) {
return $resource('admin/info/properties', {'wt':'json', '_':Date.now()});
}])
.factory('Replication',
['$resource', function($resource) {
return $resource(':core/replication', {'wt':'json', core: "@core", '_':Date.now()}, {
"details": {params: {command: "details"}},
"command": {params: {}}
});
}])
.factory('CoreSystem',
['$resource', function($resource) {
return $resource(':core/admin/system', {wt:'json', core: "@core", _:Date.now()});
}])
.factory('Update',
['$resource', function($resource) {
return $resource(':core/:handler', {core: '@core', wt:'json', _:Date.now(), handler:'update'}, {
"commit": {params: {commit: "true"}},
"post": {headers: {'Content-type': 'application/json'}, method: "POST", params: {handler: '@handler'}},
"postJson": {headers: {'Content-type': 'application/json'}, method: "POST", params: {handler: '@handler'}},
"postXml": {headers: {'Content-type': 'text/xml'}, method: "POST", params: {handler: '@handler'}},
"postCsv": {headers: {'Content-type': 'application/csv'}, method: "POST", params: {handler: '@handler'}}
});
}])
.service('FileUpload', function ($http) {
this.upload = function(params, file, success, error){
var url = "" + 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(':core/admin/luke', {core: '@core', wt:'json', _:Date.now()}, {
"index": {params: {numTerms: 0, show: 'index'}},
"raw": {params: {numTerms: 0}},
"schema": {params: {show:'schema'}},
"field": {},
"fields": {params: {show:'schema'}, interceptor: {
response: function(response) {
var fieldsAndTypes = [];
for (var field in response.data.schema.fields) {
fieldsAndTypes.push({group: "Fields", label: field, value: "fieldname=" + field});
}
for (var type in response.data.schema.types) {
fieldsAndTypes.push({group: "Types", label: type, value: "fieldtype=" + type});
}
return fieldsAndTypes;
}
}}
});
}])
.factory('Analysis',
['$resource', function($resource) {
return $resource(':core/analysis/field', {core: '@core', wt:'json', _:Date.now()}, {
"field": {params: {"analysis.showmatch": true}}
});
}])
.factory('DataImport',
['$resource', function($resource) {
return $resource(':core/:name', {core: '@core', name: '@name', indent:'on', wt:'json', _:Date.now()}, {
"config": {params: {command: "show-config"}, headers: {doNotIntercept: "true"},
transformResponse: function(data) {
return {config: data};
}
},
"status": {params: {command: "status"}, headers: {doNotIntercept: "true"}},
"reload": {params: {command: "reload-config"}},
"post": {method: "POST",
headers: {'Content-type': 'application/x-www-form-urlencoded'},
transformRequest: function(data) { return $.param(data) }}
});
}])
.factory('Ping',
['$resource', function($resource) {
return $resource(':core/admin/ping', {wt:'json', core: '@core', ts:Date.now(), _:Date.now()}, {
"ping": {},
"status": {params:{action:"status"}, headers: {doNotIntercept: "true"}
}});
}])
.factory('Mbeans',
['$resource', function($resource) {
return $resource(':core/admin/mbeans', {'wt':'json', core: '@core', '_':Date.now()}, {
stats: {params: {stats: true}},
info: {},
reference: {
params: {wt: "xml", stats: true}, transformResponse: function (data) {
return {reference: data}
}
},
delta: {method: "POST",
params: {stats: true, diff:true},
headers: {'Content-type': 'application/x-www-form-urlencoded'},
transformRequest: function(data) {
return "stream.body=" + encodeURIComponent(data);
}
}
});
}])
.factory('Files',
['$resource', function($resource) {
return $resource(':core/admin/file', {'wt':'json', core: '@core', '_':Date.now()}, {
"list": {},
"get": {method: "GET", interceptor: {
response: function(config) {return config;}
}, transformResponse: function(data) {
return data;
}}
});
}])
.factory('Query',
['$resource', function($resource) {
var resource = $resource(':core/:handler', {core: '@core', handler: '@handler', '_':Date.now()}, {
"query": {
method: "GET",
transformResponse: function (data) {
return {data: data}
},
headers: {doNotIntercept: "true"}
}
});
resource.url = function(params) {
var qs = [];
for (key in params) {
if (key != "core" && key != "handler") {
for (var i in params[key]) {
qs.push(key + "=" + encodeURIComponent(params[key][i]));
}
}
}
return "" + params.core + "/" + params.handler + "?" + qs.sort().join("&");
}
return resource;
}])
.factory('Segments',
['$resource', function($resource) {
return $resource(':core/admin/segments', {'wt':'json', core: '@core', _:Date.now()}, {
get: {}
});
}])
.factory('Schema',
['$resource', function($resource) {
return $resource(':core/schema', {wt: 'json', core: '@core', _:Date.now()}, {
get: {method: "GET"},
check: {method: "GET", headers: {doNotIntercept: "true"}},
post: {method: "POST"}
});
}])
.factory('Config',
['$resource', function($resource) {
return $resource(':core/config', {wt: 'json', core: '@core', _:Date.now()}, {
get: {method: "GET"}
})
}])
.factory('AuthenticationService',
['base64', function (base64) {
var service = {};
service.SetCredentials = function (username, password) {
var authdata = base64.encode(username + ':' + password);
sessionStorage.setItem("auth.header", "Basic " + authdata);
sessionStorage.setItem("auth.username", username);
};
service.ClearCredentials = function () {
sessionStorage.removeItem("auth.header");
sessionStorage.removeItem("auth.scheme");
sessionStorage.removeItem("auth.realm");
sessionStorage.removeItem("auth.username");
sessionStorage.removeItem("auth.wwwAuthHeader");
sessionStorage.removeItem("auth.statusText");
};
return service;
}]);