Skip to content
This repository has been archived by the owner on Mar 5, 2021. It is now read-only.

Commit

Permalink
first working version of rest client path autocomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
Leonardo Menezes committed Nov 29, 2015
1 parent 73001a3 commit 6cd5eb8
Show file tree
Hide file tree
Showing 21 changed files with 726 additions and 18 deletions.
4 changes: 3 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ module.exports = function(grunt) {
'src/lib/bootstrap/js/bootstrap.js',
'src/lib/csv/csv.js',
'src/lib/csv/jquery.csv.js',
'src/lib/angular-tree-dnd/ng-tree-dnd.js'
'src/lib/angular-tree-dnd/ng-tree-dnd.js',
'src/lib/angularjs/angular-animate.min.js',
'src/lib/typeahead/typeahead.js'
],
dest: '_site/dist/lib.js'
},
Expand Down
8 changes: 8 additions & 0 deletions _site/dist/angular-animate.min.js.map

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions _site/dist/kopf.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
.typeahead-demo .custom-popup-wrapper {
top: 100%;
left: 0;
z-index: 1000;
display: none;
}

.typeahead-demo .custom-popup-wrapper > .message {
border-bottom: 1px solid #ddd;
color: #868686;
}

.typeahead-demo .custom-popup-wrapper > .dropdown-menu {
position: static;
float: none;
display: block;
border: none;
border-radius: 0;
box-shadow: none;
margin-left: 0px;
}

.node-badges {
width: 20px;
display: inline-block;
Expand Down
204 changes: 201 additions & 3 deletions _site/dist/kopf.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var kopf = angular.module('kopf', ['ngRoute', 'ntt.TreeDnD']);
var kopf = angular.module('kopf', ['ngRoute', 'ntt.TreeDnD', 'ngAnimate',
'ui.bootstrap']);

// manages behavior of confirmation dialog
kopf.factory('ConfirmDialogService', function() {
Expand Down Expand Up @@ -1779,7 +1780,7 @@ kopf.controller('RestController', ['$scope', '$location', '$timeout',
'ClipboardService',
function($scope, $location, $timeout, ExplainService, AlertService,
AceEditorService, ElasticService, ClipboardService) {
$scope.request = new Request('/_search', 'GET', '{}');
$scope.request = new Request('', 'GET', '{}');

$scope.validation_error = null;

Expand All @@ -1789,6 +1790,16 @@ kopf.controller('RestController', ['$scope', '$location', '$timeout',
$scope.response = '';
$scope.explanationResults = [];

$scope.mapping = undefined;
$scope.options = [];

$scope.updateOptions = function(text) {
if ($scope.mapping) {
var autocomplete = new URLAutocomplete($scope.mapping);
$scope.options = autocomplete.getAlternatives(text);
}
};

$scope.copyAsCURLCommand = function() {
var method = $scope.request.method;
var host = ElasticService.getHost();
Expand Down Expand Up @@ -1855,7 +1866,7 @@ kopf.controller('RestController', ['$scope', '$location', '$timeout',

function doSendRequest(successCallback) {
if (notEmpty($scope.request.path)) {
var path = encodeURI($scope.request.path);
var path = encodeURI('/' + $scope.request.path);
$scope.request.body = $scope.editor.format();
$scope.response = '';
$scope.explanationResults = [];
Expand Down Expand Up @@ -1927,6 +1938,15 @@ kopf.controller('RestController', ['$scope', '$location', '$timeout',
$scope.initializeController = function() {
$scope.initEditor();
$scope.history = $scope.loadHistory();
ElasticService.getClusterMapping(
function(mapping) {
$scope.mapping = mapping;
$scope.updateOptions($scope.request.path);
},
function(error) {
AlertService.error('Error while loading cluster mappings', error);
}
);
};

$scope.explanationTreeConfig = {
Expand Down Expand Up @@ -2892,6 +2912,19 @@ function ClusterHealth(health) {
this.fetched_at = getTimeString(new Date());
}

function ClusterMapping(data) {

this.getIndices = function() {
return Object.keys(data);
};

this.getTypes = function(index) {
var indexMapping = getProperty(data, index + '.mappings', {});
return Object.keys(indexMapping);
};

}

function ClusterSettings(settings) {
// FIXME: 0.90/1.0 check
var valid = [
Expand Down Expand Up @@ -3459,6 +3492,24 @@ kopf.filter('bytes', function() {

});

kopf.filter('startsWith', function() {

function strStartsWith(str, prefix) {
return (str + '').indexOf(prefix) === 0;
}

return function(elements, prefix) {
var filtered = [];
angular.forEach(elements, function(element) {
if (strStartsWith(element, prefix)) {
filtered.push(element);
}
});

return filtered;
};
});

kopf.filter('timeInterval', function() {

var UNITS = ['yr', 'mo', 'd', 'h', 'min'];
Expand Down Expand Up @@ -4090,6 +4141,139 @@ function SnapshotFilter() {

}

function URLAutocomplete(mappings) {

var PATHS = [
// Suggest
'_suggest',
'{index}/_suggest',
// Multi Search
'_msearch',
'{index}/_msearch',
'{index}/{type}/_msearch',
'_msearch/template',
'{index}/_msearch/template',
'{index}/{type}/_msearch/template',
// Search
'_search',
'{index}/_search',
'{index}/{type}/_search',
'_search/template',
'{index}/_search/template',
'{index}/{type}/_search/template',
'_search/exists',
'{index}/_search/exists',
'{index}/{type}/_search/exists'
];

var format = function(previousTokens, suggestedToken) {
if (previousTokens.length > 1) {
var prefix = previousTokens.slice(0, -1).join('/');
if (prefix.length > 0) {
return prefix + '/' + suggestedToken;
} else {
return suggestedToken;
}
} else {
return suggestedToken;
}
};

this.getAlternatives = function(path) {
var pathTokens = path.split('/');
var suggestedTokenIndex = pathTokens.length - 1;

/**
* Replaces the variables on suggestedPathTokens({index}, {type}...) for
* actual values extracted from pathTokens
* @param {Array} pathTokens tokens for the path to be suggested
* @param {Array} suggestedPathTokens tokens for the suggested path
* @returns {Array} a new array with the variables from suggestedPathTokens
* replaced by the actual values from pathTokens
*/
var replaceVariables = function(pathTokens, suggestedPathTokens) {
var replaced = suggestedPathTokens.map(function(token, position) {
if (position < pathTokens.length - 1 && token.indexOf('{') === 0) {
return pathTokens[position];
} else {
return token;
}
});
return replaced;
};

/**
* Checks if a given path matches the definition and current state of
* the path to be autocompleted
*
* @param {Array} pathTokens tokens of path to be autocompleted
* @param {Array} suggestedPathTokens tokens of possible suggestion
* @returns {boolean} if suggestion is valid
*/
var isValidSuggestion = function(pathTokens, suggestedPathTokens) {
var valid = true;
suggestedPathTokens.forEach(function(token, index) {
if (valid && index < pathTokens.length - 1) {
switch (token) {
case '{index}':
valid = mappings.getIndices().indexOf(pathTokens[index]) >= 0;
break;
case '{type}':
valid = mappings.getTypes(pathTokens[index - 1]).
indexOf(pathTokens[index]) >= 0;
break;
default:
valid = pathTokens[index] === token;
}
}
});
return valid;
};

var alternatives = [];

var addIfNotPresent = function(collection, element) {
if (collection.indexOf(element) === -1) {
collection.push(element);
}
};

PATHS.forEach(function(suggestedPath) {
var suggestedPathTokens = suggestedPath.split('/');
if (suggestedPathTokens.length > suggestedTokenIndex &&
isValidSuggestion(pathTokens, suggestedPathTokens)) {
suggestedPathTokens = replaceVariables(
pathTokens,
suggestedPathTokens
);
var suggestedToken = suggestedPathTokens[suggestedTokenIndex];
switch (suggestedToken) {
case '{index}':
mappings.getIndices().forEach(function(index) {
addIfNotPresent(alternatives, format(pathTokens, index));
});
break;
case '{type}':
var pathIndex = pathTokens[suggestedTokenIndex - 1];
mappings.getTypes(pathIndex).forEach(function(type) {
addIfNotPresent(alternatives, format(pathTokens, type));
});
break;
default:
addIfNotPresent(alternatives, format(pathTokens, suggestedToken));
}
}
});

return alternatives.sort(function(a, b) {
return a.localeCompare(b);
});
};

return this;

}

function WarmerFilter(id) {

this.id = id;
Expand Down Expand Up @@ -4866,6 +5050,20 @@ kopf.factory('ElasticService', ['$http', '$q', '$timeout', '$location',
this.clusterRequest('GET', path, params, {}, parseHotThreads, error);
};

/**
* Retrieve comples cluster mapping
*
* @callback success
* @callback error
*/
this.getClusterMapping = function(success, error) {
var transformed = function(response) {
success(new ClusterMapping(response));
};
var path = '/_mapping';
this.clusterRequest('GET', path, {}, {}, transformed, error);
};

this.getIndexMetadata = function(name, success, error) {
var transformed = function(response) {
success(new IndexMetadata(name, response.metadata.indices[name]));
Expand Down
Loading

0 comments on commit 6cd5eb8

Please sign in to comment.