0
0
Fork 0

http/mapping subdir replaced by blevesearch/bleve-mapping-ui

The bleve mapping UI is now moved / replaced, and is available at...

   github.com/blevesearch/bleve-mapping-ui
This commit is contained in:
Steve Yen 2015-11-23 09:23:52 -08:00
parent fcf3980cea
commit ab3188becb
39 changed files with 0 additions and 3288 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,428 +0,0 @@
// Copyright (c) 2015 Couchbase, Inc.
// Licensed 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.
package mapping
//go:generate go-bindata-assetfs -pkg=mapping ./mapping_static/...
//go:generate go fmt .
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"sort"
"github.com/elazarl/go-bindata-assetfs"
"github.com/gorilla/mux"
"github.com/blevesearch/bleve"
"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/registry"
)
func AssetFS() *assetfs.AssetFS {
return assetFS()
}
// RegisterHandlers registers mapping handlers on a router at the
// given pathBase, such as at "/api".
func RegisterHandlers(router *mux.Router, pathBase string) {
router.HandleFunc(pathBase+"/_analyzerNames", ListAnalyzerNames).Methods("POST")
router.HandleFunc(pathBase+"/_datetimeParserNames", ListDateTimeParserNames).Methods("POST")
router.HandleFunc(pathBase+"/_charFilterNames", ListCharFilterNames).Methods("POST")
router.HandleFunc(pathBase+"/_charFilterTypes", ListCharFilterTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenizerNames", ListTokenizerNames).Methods("POST")
router.HandleFunc(pathBase+"/_tokenizerTypes", ListTokenizerTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenFilterNames", ListTokenFilterNames).Methods("POST")
router.HandleFunc(pathBase+"/_tokenFilterTypes", ListTokenFilterTypes).Methods("GET")
router.HandleFunc(pathBase+"/_tokenMapNames", ListTokenMapNames).Methods("POST")
router.HandleFunc(pathBase+"/_analyze", AnalyzerText).Methods("POST")
router.HandleFunc(pathBase+"/_validateMapping", ValidateMapping).Methods("POST")
}
func ListAnalyzerNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in analyzer names
_, analyzerNames := registry.AnalyzerTypesAndInstances()
// add custom analyzer names
for name := range indexMapping.CustomAnalysis.Analyzers {
analyzerNames = append(analyzerNames, name)
}
sort.Strings(analyzerNames)
rv := struct {
Status string `json:"status"`
Analyzers []string `json:"analyzers"`
}{
Status: "ok",
Analyzers: analyzerNames,
}
mustEncode(w, rv)
}
func AnalyzerText(w http.ResponseWriter, req *http.Request) {
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
mapping := bleve.NewIndexMapping()
var analyzeRequest = struct {
Analyzer string `json:"analyzer"`
Text string `json:"text"`
Mapping *bleve.IndexMapping `json:"mapping"`
}{}
err = json.Unmarshal(requestBody, &analyzeRequest)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
if analyzeRequest.Mapping != nil {
mapping = analyzeRequest.Mapping
}
ts, err := mapping.AnalyzeText(analyzeRequest.Analyzer, []byte(analyzeRequest.Text))
if err != nil {
showError(w, req, fmt.Sprintf("error analyzing text: %v", err), 400)
return
}
rv := struct {
Status string `json:"status"`
Text string `json:"text"`
TokenStream analysis.TokenStream `json:"token_stream"`
}{
Status: "ok",
Text: analyzeRequest.Text,
TokenStream: ts,
}
mustEncode(w, rv)
}
func ListDateTimeParserNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, dateTimeParserNames := registry.DateTimeParserTypesAndInstances()
// add custom date time parser names
for name := range indexMapping.CustomAnalysis.DateTimeParsers {
dateTimeParserNames = append(dateTimeParserNames, name)
}
sort.Strings(dateTimeParserNames)
rv := struct {
Status string `json:"status"`
DateTimeParsers []string `json:"datetime_parsers"`
}{
Status: "ok",
DateTimeParsers: dateTimeParserNames,
}
mustEncode(w, rv)
}
func ListCharFilterNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, charFilterNames := registry.CharFilterTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.CharFilters {
charFilterNames = append(charFilterNames, name)
}
sort.Strings(charFilterNames)
rv := struct {
Status string `json:"status"`
CharFilters []string `json:"char_filters"`
}{
Status: "ok",
CharFilters: charFilterNames,
}
mustEncode(w, rv)
}
func ListCharFilterTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
charFilterTypes, _ := registry.CharFilterTypesAndInstances()
sort.Strings(charFilterTypes)
rv := struct {
Status string `json:"status"`
CharFilterTypes []string `json:"char_filter_types"`
}{
Status: "ok",
CharFilterTypes: charFilterTypes,
}
mustEncode(w, rv)
}
func ListTokenizerNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenizerNames := registry.TokenizerTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.Tokenizers {
tokenizerNames = append(tokenizerNames, name)
}
sort.Strings(tokenizerNames)
rv := struct {
Status string `json:"status"`
Tokenizers []string `json:"tokenizers"`
}{
Status: "ok",
Tokenizers: tokenizerNames,
}
mustEncode(w, rv)
}
func ListTokenizerTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
tokenizerTypes, _ := registry.TokenizerTypesAndInstances()
sort.Strings(tokenizerTypes)
rv := struct {
Status string `json:"status"`
TokenizerTypes []string `json:"tokenizer_types"`
}{
Status: "ok",
TokenizerTypes: tokenizerTypes,
}
mustEncode(w, rv)
}
func ListTokenFilterNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenFilterNames := registry.TokenFilterTypesAndInstances()
// add custom char filter names
for name := range indexMapping.CustomAnalysis.TokenFilters {
tokenFilterNames = append(tokenFilterNames, name)
}
sort.Strings(tokenFilterNames)
rv := struct {
Status string `json:"status"`
TokenFilters []string `json:"token_filters"`
}{
Status: "ok",
TokenFilters: tokenFilterNames,
}
mustEncode(w, rv)
}
func ListTokenFilterTypes(w http.ResponseWriter, req *http.Request) {
// built in char filter names
tokenFilterTypes, _ := registry.TokenFilterTypesAndInstances()
sort.Strings(tokenFilterTypes)
rv := struct {
Status string `json:"status"`
TokenFilterTypes []string `json:"token_filter_types"`
}{
Status: "ok",
TokenFilterTypes: tokenFilterTypes,
}
mustEncode(w, rv)
}
func ListTokenMapNames(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
// built in char filter names
_, tokenMapNames := registry.TokenMapTypesAndInstances()
// add custom char map names
for name := range indexMapping.CustomAnalysis.TokenMaps {
tokenMapNames = append(tokenMapNames, name)
}
sort.Strings(tokenMapNames)
rv := struct {
Status string `json:"status"`
TokenMaps []string `json:"token_maps"`
}{
Status: "ok",
TokenMaps: tokenMapNames,
}
mustEncode(w, rv)
}
func ValidateMapping(w http.ResponseWriter, req *http.Request) {
indexMapping := bleve.NewIndexMapping()
// read the request body
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
showError(w, req, fmt.Sprintf("error reading request body: %v", err), 400)
return
}
// interpret request body as index mapping
if len(requestBody) > 0 {
err := json.Unmarshal(requestBody, &indexMapping)
if err != nil {
showError(w, req, fmt.Sprintf("error parsing index mapping: %v", err), 400)
return
}
}
rv := struct {
Status string `json:"status"`
}{
Status: "ok",
}
mustEncode(w, rv)
}
func showError(w http.ResponseWriter, r *http.Request,
msg string, code int) {
log.Printf("Reporting error %v/%v", code, msg)
http.Error(w, msg, code)
}
func mustEncode(w io.Writer, i interface{}) {
if headered, ok := w.(http.ResponseWriter); ok {
headered.Header().Set("Cache-Control", "no-cache")
headered.Header().Set("Content-type", "application/json")
}
e := json.NewEncoder(w)
if err := e.Encode(i); err != nil {
panic(err)
}
}

View File

@ -1,144 +0,0 @@
var AnalyzerModalCtrl = function ($scope, $modalInstance, $http, name, value, mapping) {
$scope.origName = name;
$scope.name = name;
$scope.errorMessage = "";
$scope.formpath = "";
$scope.mapping = mapping;
$scope.analyzer = {};
// copy in value for editing
for (var k in value) {
// need deeper copy of nested arrays
if (k == "char_filters") {
newcharfilters = [];
for (var cfi in value.char_filters) {
newcharfilters.push(value.char_filters[cfi]);
}
$scope.analyzer.char_filters = newcharfilters;
} else if (k == "token_filters") {
newtokenfilters = [];
for (var tfi in value.token_filters) {
newtokenfilters.push(value.token_filters[tfi]);
}
$scope.analyzer.token_filters = newtokenfilters;
} else {
$scope.analyzer[k] = value[k];
}
}
$scope.tokenizerNames = [];
$scope.loadTokenizerNames = function() {
$http.post('/api/_tokenizerNames',mapping).success(function(data) {
$scope.tokenizerNames = data.tokenizers;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadTokenizerNames();
$scope.charFilterNames = [];
$scope.loadCharFilterNames = function() {
$http.post('/api/_charFilterNames',mapping).success(function(data) {
$scope.charFilterNames = data.char_filters;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadCharFilterNames();
$scope.addCharFilter = function(scope) {
filter = scope.addCharacterFilterName;
if (filter !== undefined && filter !== "") {
$scope.selectedAnalyzer.char_filters.push(filter);
}
console.log($scope.selectedAnalyzer.char_filters);
};
$scope.removeCharFilter = function(index) {
$scope.selectedAnalyzer.char_filters.splice(index, 1);
};
$scope.tokenFilterNames = [];
$scope.loadTokenFilterNames = function() {
$http.post('/api/_tokenFilterNames',mapping).success(function(data) {
$scope.tokenFilterNames = data.token_filters;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadTokenFilterNames();
$scope.addCharFilter = function(scope) {
filter = scope.addCharacterFilterName;
if (filter !== undefined && filter !== "") {
$scope.analyzer.char_filters.push(filter);
}
console.log($scope.analyzer.char_filters);
};
$scope.removeCharFilter = function(index) {
$scope.analyzer.char_filters.splice(index, 1);
};
$scope.addTokenFilter = function(scope) {
filter = scope.addTokenFilterName;
if (filter !== undefined && filter !== "") {
$scope.analyzer.token_filters.push(filter);
}
console.log($scope.analyzer.token_filters);
};
$scope.removeTokenFilter = function(index) {
$scope.analyzer.token_filters.splice(index, 1);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.build = function() {
// must have a name
if (!$scope.name) {
$scope.errorMessage = "Name is required";
return;
}
// name must not already be used
if ($scope.name != $scope.origName && $scope.mapping.analysis.analyzers[$scope.name]) {
$scope.errorMessage = "Analyzer named '" + $scope.name + "' already exists";
return;
}
// ensure that this new mapping component is valid
analysis = {};
for (var ak in $scope.mapping.analysis) {
analysis[ak] = $scope.mapping.analysis[ak];
}
analyzers = {};
analyzers[$scope.name] = $scope.analyzer;
analysis["analyzers"] = analyzers;
testMapping = {
"analysis": analysis
};
$http.post('/api/_validateMapping',testMapping).success(function(data) {
// if its valid return it
result = {};
result[$scope.name] = $scope.analyzer;
$modalInstance.close(result);
}).
error(function(data, code) {
// otherwise display error
$scope.errorMessage = data;
});
};
};

View File

@ -1,105 +0,0 @@
var CharFilterModalCtrl = function ($scope, $modalInstance, $http, name, value, mapping) {
$scope.origName = name;
$scope.name = name;
$scope.errorMessage = "";
$scope.formpath = "";
$scope.mapping = mapping;
$scope.charfilter = {};
// copy in value for editing
for (var k in value) {
$scope.charfilter[k] = value[k];
}
$scope.unknownCharFilterTypeTemplate = "/static/partials/analysis/charfilters/generic.html";
$scope.charFilterTypeTemplates = {
"regexp": "/static/partials/analysis/charfilters/regexp.html",
};
$scope.charFilterTypeDefaults = {
"regexp": function() {
return {
"regexp": "",
"replace": ""
};
}
};
$scope.charFilterTypes = [];
updateCharFilterTypes = function() {
$http.get('/api/_charFilterTypes').success(function(data) {
$scope.charFilterTypes = data.char_filter_types;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
updateCharFilterTypes();
if (!$scope.charfilter.type) {
defaultType = "regexp";
if ($scope.charFilterTypeDefaults[defaultType]) {
$scope.charfilter = $scope.charFilterTypeDefaults[defaultType]();
}
else {
$scope.charfilter = {};
}
$scope.charfilter.type = defaultType;
}
$scope.formpath = $scope.charFilterTypeTemplates[$scope.charfilter.type];
$scope.charFilterTypeChange = function() {
newType = $scope.charfilter.type;
if ($scope.charFilterTypeDefaults[$scope.charfilter.type]) {
$scope.charfilter = $scope.charFilterTypeDefaults[$scope.charfilter.type]();
} else {
$scope.charfilter = {};
}
$scope.charfilter.type = newType;
if ($scope.charFilterTypeTemplates[$scope.charfilter.type]) {
$scope.formpath = $scope.charFilterTypeTemplates[$scope.charfilter.type];
} else {
$scope.formpath = unknownCharFilterTypeTemplate;
}
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.build = function() {
// must have a name
if (!$scope.name) {
$scope.errorMessage = "Name is required";
return;
}
// name must not already be used
if ($scope.name != $scope.origName && $scope.mapping.analysis.char_filters[$scope.name]) {
$scope.errorMessage = "Character filter named '" + $scope.name + "' already exists";
return;
}
// ensure that this new mapping component is valid
charFilters = {};
charFilters[$scope.name] = $scope.charfilter;
testMapping = {
"analysis": {
"char_filters": charFilters
}
};
$http.post('/api/_validateMapping',testMapping).success(function(data) {
// if its valid return it
result = {};
result[$scope.name] = $scope.charfilter;
$modalInstance.close(result);
}).
error(function(data, code) {
// otherwise display error
$scope.errorMessage = data;
});
};
};

View File

@ -1,179 +0,0 @@
var TokenFilterModalCtrl = function ($scope, $modalInstance, $http, name, value, mapping) {
$scope.origName = name;
$scope.name = name;
$scope.errorMessage = "";
$scope.formpath = "";
$scope.mapping = mapping;
$scope.tokenfilter = {};
// copy in value for editing
for (var k in value) {
$scope.tokenfilter[k] = value[k];
}
$scope.tokenMapNames = [];
$scope.loadTokenMapNames = function() {
$http.post('/api/_tokenMapNames',mapping).success(function(data) {
$scope.tokenMapNames = data.token_maps;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadTokenMapNames();
$scope.unknownTokenFilterTypeTemplate = "/static/partials/analysis/tokenfilters/generic.html";
$scope.tokenFilterTypeTemplates = {
"dict_compound": "/static/partials/analysis/tokenfilters/dict_compound.html",
"edge_ngram": "/static/partials/analysis/tokenfilters/edge_ngram.html",
"elision": "/static/partials/analysis/tokenfilters/elision.html",
"keyword_marker": "/static/partials/analysis/tokenfilters/keyword_marker.html",
"length": "/static/partials/analysis/tokenfilters/length.html",
"ngram": "/static/partials/analysis/tokenfilters/ngram.html",
"normalize_unicode": "/static/partials/analysis/tokenfilters/normalize_unicode.html",
"shingle": "/static/partials/analysis/tokenfilters/shingle.html",
"stop_tokens": "/static/partials/analysis/tokenfilters/stop_tokens.html",
"truncate_token": "/static/partials/analysis/tokenfilters/truncate_token.html",
};
$scope.tokenFilterTypeDefaults = {
"dict_compound": function() {
return {
"dict_token_map": $scope.tokenMapNames[0]
};
},
"edge_ngram": function() {
return {
"edge": "front",
"min": 3,
"max": 3,
};
},
"elision": function() {
return {
"articles_token_map": $scope.tokenMapNames[0]
};
},
"keyword_marker": function() {
return {
"keywords_token_map": $scope.tokenMapNames[0]
};
},
"length": function() {
return {
"min": 3,
"max": 255
};
},
"ngram": function() {
return {
"min": 3,
"max": 3
};
},
"normalize_unicode": function() {
return {
"form": "nfc"
};
},
"shingle": function() {
return {
"min": 2,
"max": 2,
"output_original": false,
"separator": "",
"filler": ""
};
},
"stop_tokens": function() {
return {
"stop_token_map": $scope.tokenMapNames[0]
};
},
"truncate_token": function() {
return {
"length": 25
};
},
};
$scope.tokenFilterTypes = [];
updateTokenFilterTypes = function() {
$http.get('/api/_tokenFilterTypes').success(function(data) {
$scope.tokenFilterTypes = data.token_filter_types;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
updateTokenFilterTypes();
if (!$scope.tokenfilter.type) {
defaultType = "length";
if ($scope.tokenFilterTypeDefaults[defaultType]) {
$scope.tokenfilter = $scope.tokenFilterTypeDefaults[defaultType]();
}
else {
$scope.tokenfilter = {};
}
$scope.tokenfilter.type = defaultType;
}
$scope.formpath = $scope.tokenFilterTypeTemplates[$scope.tokenfilter.type];
$scope.tokenFilterTypeChange = function() {
newType = $scope.tokenfilter.type;
if ($scope.tokenFilterTypeDefaults[$scope.tokenfilter.type]) {
$scope.tokenfilter = $scope.tokenFilterTypeDefaults[$scope.tokenfilter.type]();
} else {
$scope.tokenfilter = {};
}
$scope.tokenfilter.type = newType;
if ($scope.tokenFilterTypeTemplates[$scope.tokenfilter.type]) {
$scope.formpath = $scope.tokenFilterTypeTemplates[$scope.tokenfilter.type];
} else {
$scope.formpath = $scope.unknownTokenFilterTypeTemplate;
}
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.build = function() {
// must have a name
if (!$scope.name) {
$scope.errorMessage = "Name is required";
return;
}
// name must not already be used
if ($scope.name != $scope.origName && $scope.mapping.analysis.token_filters[$scope.name]) {
$scope.errorMessage = "Token filter named '" + $scope.name + "' already exists";
return;
}
// ensure that this new mapping component is valid
tokenfilters = {};
tokenfilters[$scope.name] = $scope.tokenfilter;
testMapping = {
"analysis": {
"token_filters": tokenfilters,
"token_maps": $scope.mapping.analysis.token_maps
}
};
$http.post('/api/_validateMapping',testMapping).success(function(data) {
// if its valid return it
result = {};
result[$scope.name] = $scope.tokenfilter;
$modalInstance.close(result);
}).
error(function(data, code) {
// otherwise display error
$scope.errorMessage = data;
});
};
};

View File

@ -1,138 +0,0 @@
var TokenizerModalCtrl = function ($scope, $modalInstance, $http, name, value, mapping) {
$scope.origName = name;
$scope.name = name;
$scope.errorMessage = "";
$scope.formpath = "";
$scope.mapping = mapping;
$scope.tokenizer = {};
// copy in value for editing
for (var k in value) {
$scope.tokenizer[k] = value[k];
}
$scope.tokenizerNames = [];
$scope.loadTokenizerNames = function() {
$http.post('/api/_tokenizerNames',mapping).success(function(data) {
$scope.tokenizerNames = data.tokenizers;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadTokenizerNames();
$scope.unknownTokenizerTypeTemplate = "/static/partials/analysis/tokenizers/generic.html";
$scope.tokenizerTypeTemplates = {
"regexp": "/static/partials/analysis/tokenizers/regexp.html",
"exception": "/static/partials/analysis/tokenizers/exception.html"
};
$scope.tokenizerTypeDefaults = {
"regexp": function() {
return {
"regexp": ""
};
},
"exception": function() {
return {
"exceptions": [],
"tokenizer": "unicode"
};
}
};
$scope.tokenizerTypes = [];
updateTokenizerTypes = function() {
$http.get('/api/_tokenizerTypes').success(function(data) {
$scope.tokenizerTypes = data.tokenizer_types;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
updateTokenizerTypes();
if (!$scope.tokenizer.type) {
defaultType = "regexp";
if ($scope.tokenizerTypeDefaults[defaultType]) {
$scope.tokenizer = $scope.tokenizerTypeDefaults[defaultType]();
}
else {
$scope.tokenizer = {};
}
$scope.tokenizer.type = defaultType;
}
$scope.formpath = $scope.tokenizerTypeTemplates[$scope.tokenizer.type];
$scope.tokenizerTypeChange = function() {
newType = $scope.tokenizer.type;
if ($scope.tokenizerTypeDefaults[$scope.tokenizer.type]) {
$scope.tokenizer = $scope.tokenizerTypeDefaults[$scope.tokenizer.type]();
} else {
$scope.tokenizer = {};
}
$scope.tokenizer.type = newType;
if ($scope.tokenizerTypeTemplates[$scope.tokenizer.type]) {
$scope.formpath = $scope.tokenizerTypeTemplates[$scope.tokenizer.type];
} else {
$scope.formpath = $scope.unknownTokenizerTypeTemplate;
}
};
$scope.addException = function(scope) {
if (scope.newregexp) {
$scope.tokenizer.exceptions.push(scope.newregexp);
scope.newregexp = "";
}
};
$scope.removeException = function(index) {
$scope.tokenizer.exceptions.splice(index, 1);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.build = function() {
// must have a name
if (!$scope.name) {
$scope.errorMessage = "Name is required";
return;
}
// name must not already be used
if ($scope.name != $scope.origName && $scope.mapping.analysis.tokenizers[$scope.name]) {
$scope.errorMessage = "Tokenizer named '" + $scope.name + "' already exists";
return;
}
// ensure that this new mapping component is valid
tokenizers = {};
tokenizers[$scope.name] = $scope.tokenizer;
// add in all the existing tokenizers, since we might be referencing them
for (var t in $scope.mapping.analysis.tokenizers) {
tokenizers[t] = $scope.mapping.analysis.tokenizers[t];
}
testMapping = {
"analysis": {
"tokenizers": tokenizers
}
};
$http.post('/api/_validateMapping',testMapping).success(function(data) {
// if its valid return it
result = {};
result[$scope.name] = $scope.tokenizer;
$modalInstance.close(result);
}).
error(function(data, code) {
// otherwise display error
$scope.errorMessage = data;
});
};
};

View File

@ -1,51 +0,0 @@
var WordListModalCtrl = function ($scope, $modalInstance, name, words, mapping) {
$scope.name = name;
$scope.origName = name;
$scope.errorMessage = "";
$scope.newWord = "";
$scope.words = words.slice(0); // create copy
$scope.selectedWords = [];
$scope.mapping = mapping;
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.addWord = function() {
if ($scope.newWord) {
$scope.words.push($scope.newWord);
$scope.newWord = "";
}
};
$scope.removeWord = function() {
// sort the selected word indexes into descending order
// so we can delete items without having to adjust indexes
$scope.selectedWords.sort(function(a,b){ return b - a; });
for (var index in $scope.selectedWords) {
$scope.words.splice($scope.selectedWords[index], 1);
}
$scope.selectedWords = [];
};
$scope.build = function() {
// must have a name
if (!$scope.name) {
$scope.errorMessage = "Name is required";
return;
}
// name must not already be used
if ($scope.name != $scope.origName && $scope.mapping.analysis.token_maps[$scope.name]) {
$scope.errorMessage = "Word list named '" + $scope.name + "' already exists";
return;
}
result = {};
result[$scope.name] = {
"type": "custom",
"tokens": $scope.words
};
$modalInstance.close(result);
};
};

View File

@ -1,379 +0,0 @@
// controller responsible for building a custom analysis components
function AnalysisCtrl($scope, $http, $routeParams, $log, $sce, $location, $modal) {
// analyzers
$scope.newAnalyzer = function () {
return $scope.editAnalyzer("", {
"type": "custom",
"char_filters": [],
"tokenizer": "unicode",
"token_filters": []
});
};
$scope.deleteAnalyzer = function (name) {
used = $scope.isAnalyzerUsed(name);
if (used) {
alert("This analyzer cannot be deleted because it is being used by the " + used + ".");
return;
}
if (confirm("Are you sure you want to delete '" + name + "'?")) {
delete $scope.$parent.mapping.analysis.analyzers[name];
}
};
$scope.isAnalyzerUsed = function(name) {
// analyzers are used in mappings (in various places)
// first check index level default analyzer
if ($scope.$parent.mapping.default_analyzer == name) {
return "index mapping default analyzer";
}
// then check the default documnt mapping
used = $scope.isAnalyzerUsedInDocMapping(name, $scope.$parent.mapping.default_mapping, "");
if (used) {
return "default document mapping " + used;
}
// then check the document mapping for each type
for (var docType in $scope.$parent.mapping.types) {
docMapping = $scope.$parent.mapping.types[docType];
used = $scope.isAnalyzerUsedInDocMapping(name, docMapping, "");
if (used) {
return "document mapping type '" + docType + "' ";
}
}
return null;
};
// a recursive helper
$scope.isAnalyzerUsedInDocMapping = function(name, docMapping, path) {
// first check the document level default analyzer
if (docMapping.default_analyzer == name) {
if (path) {
return "default analyzer at " + path;
} else {
return "default analyzer";
}
}
// now check fields at this level
for (var fieldIndex in docMapping.fields) {
field = docMapping.fields[fieldIndex];
if (field.analyzer == name) {
if (field.name) {
return "in the field named " + field.name;
}
return "in the field at path " + path;
}
}
// now check each nested property
for (var propertyName in docMapping.properties) {
subDoc = docMapping.properties[propertyName];
if (path) {
return $scope.isAnalyzerUsedInDocMapping(name, subDoc, path+"."+propertyName);
} else {
return $scope.isAnalyzerUsedInDocMapping(name, subDoc, propertyName);
}
}
return null;
};
$scope.editAnalyzer = function (name, value) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/static/partials/analysis/analyzer.html',
controller: 'AnalyzerModalCtrl',
resolve: {
name: function () {
return name;
},
value: function () {
return value;
},
mapping: function() {
return $scope.$parent.mapping;
}
}
});
modalInstance.result.then(function (result) {
// add this result to the mapping
for (var resultKey in result) {
if (name !== "" && resultKey != name) {
// remove the old name
delete $scope.$parent.mapping.analysis.analyzers[name];
}
$scope.$parent.mapping.analysis.analyzers[resultKey] = result[resultKey];
// reload parent available analyzers
$scope.$parent.loadAnalyzerNames();
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
// word lists
$scope.newWordList = function () {
return $scope.editWordList("", {tokens:[]});
};
$scope.deleteWordList = function (name) {
used = $scope.isWordListUsed(name);
if (used) {
alert("This word list cannot be deleted because it is being used by the " + used + ".");
return;
}
if (confirm("Are you sure you want to delete '" + name + "'?")) {
delete $scope.$parent.mapping.analysis.token_maps[name];
}
};
$scope.isWordListUsed = function(name) {
// word lists are only used by token filters
for (var tokenFilterName in $scope.$parent.mapping.analysis.token_filters) {
tokenFilter = $scope.$parent.mapping.analysis.token_filters[tokenFilterName];
// word lists are embeded in a variety of different field names
if (tokenFilter.dict_token_map == name ||
tokenFilter.articles_token_map == name ||
tokenFilter.keywords_token_map == name ||
tokenFilter.stop_token_map == name) {
return "token filter named '" + tokenFilterName + "'";
}
}
return null;
};
$scope.editWordList = function (name, value) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/static/partials/analysis/wordlist.html',
controller: 'WordListModalCtrl',
resolve: {
name: function () {
return name;
},
words: function () {
return value.tokens;
},
mapping: function() {
return $scope.$parent.mapping;
}
}
});
modalInstance.result.then(function (result) {
// add this result to the mapping
for (var resultKey in result) {
if (name !== "" && resultKey != name) {
// remove the old name
delete $scope.$parent.mapping.analysis.token_maps[name];
}
$scope.$parent.mapping.analysis.token_maps[resultKey] = result[resultKey];
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
// character filters
$scope.newCharFilter = function() {
return $scope.editCharFilter("", {});
};
$scope.deleteCharFilter = function(name) {
used = $scope.isCharFilterUsed(name);
if (used) {
alert("This character filter cannot be deleted because it is being used by the " + used + ".");
return;
}
if (confirm("Are you sure you want to delete '" + name + "'?")) {
delete $scope.$parent.mapping.analysis.char_filters[name];
}
};
$scope.isCharFilterUsed = function(name) {
// character filters can only be used by analyzers
for (var analyzerName in $scope.$parent.mapping.analysis.analyzers) {
analyzer = $scope.$parent.mapping.analysis.analyzers[analyzerName];
for (var charFilterIndex in analyzer.char_filters) {
charFilterName = analyzer.char_filters[charFilterIndex];
if (charFilterName == name) {
return "analyzer named '" + analyzerName + "'";
}
}
}
return null;
};
$scope.editCharFilter = function (name, value) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/static/partials/analysis/charfilter.html',
controller: 'CharFilterModalCtrl',
resolve: {
name: function () {
return name;
},
value: function () {
return value;
},
mapping: function() {
return $scope.$parent.mapping;
}
}
});
modalInstance.result.then(function (result) {
// add this result to the mapping
for (var resultKey in result) {
if (name !== "" && resultKey != name) {
// remove the old name
delete $scope.$parent.mapping.analysis.char_filters[name];
}
$scope.$parent.mapping.analysis.char_filters[resultKey] = result[resultKey];
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
// tokenizers
$scope.newTokenizer = function () {
return $scope.editTokenizer("", {});
};
$scope.deleteTokenizer = function (name) {
used = $scope.isTokenizerUsed(name);
if (used) {
alert("This tokenizer cannot be deleted because it is being used by the " + used + ".");
return;
}
if (confirm("Are you sure you want to delete '" + name + "'?")) {
delete $scope.$parent.mapping.analysis.tokenizers[name];
}
};
$scope.isTokenizerUsed = function(name) {
// tokenizers can be used by *other* tokenizers
for (var tokenizerName in $scope.$parent.mapping.analysis.tokenizers) {
tokenizer = $scope.$parent.mapping.analysis.tokenizers[tokenizerName];
if (tokenizer.tokenizer == name) {
return "tokenizer named '" + tokenizerName + "'";
}
}
// tokenizers can be used by analyzers
for (var analyzerName in $scope.$parent.mapping.analysis.analyzers) {
analyzer = $scope.$parent.mapping.analysis.analyzers[analyzerName];
if (analyzer.tokenizer == name) {
return "analyzer named '" + analyzerName + "'";
}
}
return null;
};
$scope.editTokenizer = function (name, value) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/static/partials/analysis/tokenizer.html',
controller: 'TokenizerModalCtrl',
resolve: {
name: function () {
return name;
},
value: function () {
return value;
},
mapping: function() {
return $scope.$parent.mapping;
}
}
});
modalInstance.result.then(function (result) {
// add this result to the mapping
for (var resultKey in result) {
if (name !== "" && resultKey != name) {
// remove the old name
delete $scope.$parent.mapping.analysis.tokenizers[name];
}
$scope.$parent.mapping.analysis.tokenizers[resultKey] = result[resultKey];
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
// token filters
$scope.newTokenFilter = function () {
return $scope.editTokenFilter("", {});
};
$scope.deleteTokenFilter = function (name) {
used = $scope.isTokenFilterUsed(name);
if (used) {
alert("This token filter cannot be deleted because it is being used by the " + used + ".");
return;
}
if (confirm("Are you sure you want to delete '" + name + "'?")) {
delete $scope.$parent.mapping.analysis.token_filters[name];
}
};
$scope.isTokenFilterUsed = function(name) {
// token filters can only be used by analyzers
for (var analyzerName in $scope.$parent.mapping.analysis.analyzers) {
analyzer = $scope.$parent.mapping.analysis.analyzers[analyzerName];
for (var tokenFilterIndex in analyzer.token_filters) {
tokenFilterName = analyzer.token_filters[tokenFilterIndex];
if (tokenFilterName == name) {
return "analyzer named '" + analyzerName + "'";
}
}
}
return null;
};
$scope.editTokenFilter = function (name, value) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: '/static/partials/analysis/tokenfilter.html',
controller: 'TokenFilterModalCtrl',
resolve: {
name: function () {
return name;
},
value: function () {
return value;
},
mapping: function() {
return $scope.$parent.mapping;
}
}
});
modalInstance.result.then(function (result) {
// add this result to the mapping
for (var resultKey in result) {
if (name !== "" && resultKey != name) {
// remove the old name
delete $scope.$parent.mapping.analysis.token_filters[name];
}
$scope.$parent.mapping.analysis.token_filters[resultKey] = result[resultKey];
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}

View File

@ -1,110 +0,0 @@
// controller responsible for building a mapping
function MappingCtrl($scope, $http, $routeParams, $log, $sce, $location) {
newFieldSection = function() {
return {
"enabled": true,
"dynamic": true,
"default_analyzer": "",
"properties": {},
"fields": [
{
"type": "",
"index": true,
"store": true,
"include_in_all": true,
"include_term_vectors": true
}
]
};
};
$scope.$parent.mapping = {
"default_mapping": newFieldSection(),
"type_field": "_type",
"default_type": "_default",
"default_analyzer": "standard",
"default_datetime_parser": "dateTimeOptional",
"default_field": "_all",
"byte_array_converter": "json",
"analysis": {
"analyzers": {},
"token_maps": {},
"char_filters": {},
"tokenizers": {},
"token_filters": {}
}
};
$scope.analyzerNames = [];
$scope.loadAnalyzerNames = function() {
$http.post('/api/_analyzerNames',$scope.$parent.mapping).success(function(data) {
$scope.analyzerNames = data.analyzers;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadAnalyzerNames();
$scope.datetimeParserNames = [];
$scope.loadDatetimeParserNames = function() {
$http.post('/api/_datetimeParserNames',$scope.$parent.mapping).success(function(data) {
$scope.datetimeParserNames = data.datetime_parsers;
}).
error(function(data, code) {
$scope.errorMessage = data;
});
};
$scope.loadDatetimeParserNames();
$scope.mappingType = "default";
$scope.selectedItem = null;
$scope.selectedLabel = "";
$scope.fieldTypes = [
{
"name": "text",
"label": "Text",
"description": "a text field"
},
{
"name": "number",
"label": "Number",
"description": "a numerical value, indexed to facilitate range queries"
},
{
"name": "datetime",
"label": "Date/Time",
"description": "a date/time value, indexed to facilitate range queries"
},
{
"name": "disabled",
"label": "Disabled",
"description": "a section of JSON to be completely ignored"
}
];
$scope.clickItem = function(x, y) {
$scope.selectedItem = x;
$scope.selectedLabel = y;
};
$scope.clickItem($scope.$parent.mapping.default_mapping);
$scope.addField = function(scope) {
if (scope.newFieldName) {
$scope.selectedItem.properties[scope.newFieldName] = newFieldSection();
scope.newFieldName = "";
console.log($scope.selectedItem);
}
};
$scope.changeType = function(scope) {
};
}

View File

@ -1,72 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">Custom Analyzer</h3>
</div>
<div class="modal-body">
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form" role="form">
<div class="form-group">
<label for="aname">Name</label>
<input ng-model="name" type="text" class="form-control" id="tname" placeholder="Name">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Character Filters</label>
<ul class="list-group" ng-show="analyzer.char_filters.length < 1">
<li class="list-group-item">None</li>
</ul>
<ul class="list-group" ng-show="analyzer.char_filters.length > 0" ui-sortable ng-model="analyzer.char_filters">
<li class="list-group-item" ng-repeat="analyzerCharFilter in analyzer.char_filters track by $index"><span class="glyphicon glyphicon-minus"></span> {{ analyzerCharFilter }}<span ng-click="removeCharFilter($index)" class="glyphicon glyphicon-remove pull-right"></span></li>
</ul>
</div>
<div class="form-group">
<label for="exampleInputPassword2"></label>
<div class="col-sm-10">
<select ng-change="addCharFilterChanged()" ng-model="addCharacterFilterName" class="form-control" id="addCharacterFilters">
<option ng-repeat="charFilter in charFilterNames">{{charFilter}}</option>
</select>
</div>
<div class="col-sm-2">
<button ng-click="addCharFilter(this)" type="button" class="btn btn-default pull-right">Add</button>
</div>
</div>
<div class="form-group">
<label for="analyzerTokenizer">Tokenizer</label>
<select ng-change="tokenizerChanged()" ng-model="analyzer.tokenizer" class="form-control" id="analyzerTokenizer">
<option ng-repeat="tokenizer in tokenizerNames">{{tokenizer}}</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputPassword2">Token Filters</label>
<ul class="list-group" ng-show="analyzer.token_filters.length < 1">
<li class="list-group-item">None</li>
</ul>
<ul class="list-group" ng-show="analyzer.token_filters.length > 0" ui-sortable ng-model="analyzer.token_filters">
<li class="list-group-item" ng-repeat="analyzerTokenFilter in analyzer.token_filters"><span class="glyphicon glyphicon-minus"></span> {{ analyzerTokenFilter }}<span ng-click="removeTokenFilter($index)" class="glyphicon glyphicon-remove pull-right"></li>
</ul>
</div>
<div class="form-group">
<label for="exampleInputPassword2"></label>
<div class="col-sm-10">
<select ng-change="addTokenFilterChanged()" ng-model="addTokenFilterName" class="form-control" id="addTokenFilters">
<option ng-repeat="tokenFilter in tokenFilterNames">{{tokenFilter}}</option>
</select>
</div>
<div class="col-sm-2">
<button ng-click="addTokenFilter(this)" type="button" class="btn btn-default pull-right">Add</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button ng-click="build()" type="button" class="btn btn-primary pull-right">Save</button>
</div>

View File

@ -1,34 +0,0 @@
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(aname,aval) in mapping.analysis.analyzers">
<td>{{aname}}</td>
<td>
<div class="btn-group btn-group-xs" role="group">
<button ng-click="editAnalyzer(aname, aval)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button ng-click="deleteAnalyzer(aname)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button>
</div>
</td>
</tr>
<tr ng-show="Utils.keys(mapping.analysis.analyzers).length < 1">
<td colspan="2">None</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button ng-click="newAnalyzer()" type="button" class="btn btn-sm btn-default pull-right">New Analyzer</button>
</td>
</tr>
</tfoot>
</table>

View File

@ -1,34 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">Custom Char Filter</h3>
</div>
<div class="modal-body">
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form" role="form">
<div class="form-group">
<label for="tname">Name</label>
<input ng-model="name" type="text" class="form-control" id="tname" placeholder="Name">
</div>
<div class="form-group">
<label for="charfiltertype">Type</label>
<div class="col-sm-12 input-group">
<select ng-change="charFilterTypeChange()" ng-model="charfilter.type" class="form-control" id="charfiltertype">
<option ng-repeat="charFilterTyp in charFilterTypes">{{charFilterTyp}}</option>
</select>
</div>
</div>
<div ng-show="charfilter.type" ng-include src="formpath"/>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button ng-click="build()" type="button" class="btn btn-primary pull-right">Save</button>
</div>

View File

@ -1,36 +0,0 @@
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(cfname,cfval) in mapping.analysis.char_filters">
<td>{{cfname}}</td>
<td>{{cfval.type}}</td>
<td>
<div class="btn-group btn-group-xs" role="group">
<button ng-click="editCharFilter(cfname, cfval)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button ng-click="deleteCharFilter(cfname)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button>
</div>
</td>
</tr>
<tr ng-show="Utils.keys(mapping.analysis.char_filters).length < 1">
<td colspan="3">None</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">
<button ng-click="newCharFilter()" type="button" class="btn btn-sm btn-default pull-right">New Character Filter</button>
</td>
</tr>
</tfoot>
</table>

View File

@ -1,9 +0,0 @@
<div class="form-group">
<label for="charfilterRegexp">Regular Expression</label>
<input ng-model="charfilter.regexp" type="text" class="form-control" id="charfilterRegexp" placeholder="">
</div>
<div class="form-group">
<label for="charfilterReplace">Replacement</label>
<input ng-model="charfilter.replace" type="text" class="form-control" id="charfilterReplace" placeholder="">
</div>

View File

@ -1,34 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">Custom Token Filter</h3>
</div>
<div class="modal-body">
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form" role="form">
<div class="form-group">
<label for="tname">Name</label>
<input ng-model="name" type="text" class="form-control" id="tname" placeholder="Name">
</div>
<div class="form-group">
<label for="tokenfiltertype">Type</label>
<div class="col-sm-12 input-group">
<select ng-change="tokenFilterTypeChange()" ng-model="tokenfilter.type" class="form-control" id="tokenfiltertype">
<option ng-repeat="tokenFilterTyp in tokenFilterTypes">{{tokenFilterTyp}}</option>
</select>
</div>
</div>
<div ng-show="tokenfilter.type" ng-include src="formpath"/>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button ng-click="build()" type="button" class="btn btn-primary pull-right">Save</button>
</div>

View File

@ -1,36 +0,0 @@
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(tfname,tfval) in mapping.analysis.token_filters">
<td>{{tfname}}</td>
<td>{{tfval.type}}</td>
<td>
<div class="btn-group btn-group-xs" role="group">
<button ng-click="editTokenFilter(tfname, tfval)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button ng-click="deleteTokenFilter(tfname)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button>
</div>
</td>
</tr>
<tr ng-show="Utils.keys(mapping.analysis.token_filters).length < 1">
<td colspan="3">None</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">
<button ng-click="newTokenFilter()" type="button" class="btn btn-sm btn-default pull-right">New Token Filter</button>
</td>
</tr>
</tfoot>
</table>

View File

@ -1,6 +0,0 @@
<div class="form-group">
<label for="tokenfilterTokenMaps">Sub Words</label>
<select ng-model="tokenfilter.dict_token_map" class="form-control" id="tokenfilterTokenMaps">
<option ng-repeat="tokenMap in tokenMapNames">{{tokenMap}}</option>
</select>
</div>

View File

@ -1,17 +0,0 @@
<div class="form-group">
<label for="tokenfilterEdge">Edge</label>
<select class="form-control" id="tokenfilterEdge" ng-model="tokenfilter.edge">
<option>front</option>
<option>back</option>
</select>
</div>
<div class="form-group">
<label for="tokenfilterMin">Min</label>
<input ng-model="tokenfilter.min" type="number" class="form-control" id="tokenfilterMin" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterMax">Max</label>
<input ng-model="tokenfilter.max" type="number" class="form-control" id="tokenfilterMax" placeholder="">
</div>

View File

@ -1,6 +0,0 @@
<div class="form-group">
<label for="tokenfilterTokenMaps">Articles</label>
<select ng-model="tokenfilter.articles_token_map" class="form-control" id="tokenfilterTokenMaps">
<option ng-repeat="tokenMap in tokenMapNames">{{tokenMap}}</option>
</select>
</div>

View File

@ -1,6 +0,0 @@
<div class="form-group">
<label for="tokenfilterTokenMaps">Keywords</label>
<select ng-model="tokenfilter.keywords_token_map" class="form-control" id="tokenfilterTokenMaps">
<option ng-repeat="tokenMap in tokenMapNames">{{tokenMap}}</option>
</select>
</div>

View File

@ -1,9 +0,0 @@
<div class="form-group">
<label for="tokenfilterMin">Min</label>
<input ng-model="tokenfilter.min" type="number" class="form-control" id="tokenfilterMin" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterMax">Max</label>
<input ng-model="tokenfilter.max" type="number" class="form-control" id="tokenfilterMax" placeholder="">
</div>

View File

@ -1,9 +0,0 @@
<div class="form-group">
<label for="tokenfilterMin">Min</label>
<input ng-model="tokenfilter.min" type="number" class="form-control" id="tokenfilterMin" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterMax">Max</label>
<input ng-model="tokenfilter.max" type="number" class="form-control" id="tokenfilterMax" placeholder="">
</div>

View File

@ -1,9 +0,0 @@
<div class="form-group">
<label for="tokenfilterNormalizeUnicode">Form</label>
<select class="form-control" id="tokenfilterNormalizeUnicode" ng-model="tokenfilter.form">
<option>nfc</option>
<option>nfd</option>
<option>nfkc</option>
<option>nfkd</option>
</select>
</div>

View File

@ -1,24 +0,0 @@
<div class="form-group">
<label for="tokenfilterMin">Min</label>
<input ng-model="tokenfilter.min" type="number" class="form-control" id="tokenfilterMin" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterMax">Max</label>
<input ng-model="tokenfilter.max" type="number" class="form-control" id="tokenfilterMax" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterInclude">Include Original Token</label>
<input ng-model="tokenfilter.output_original" type="checkbox" class="form-control" id="tokenfilterInclude">
</div>
<div class="form-group">
<label for="tokenfilterSep">Separator</label>
<input ng-model="tokenfilter.separator" type="text" class="form-control" id="tokenfilterSep" placeholder="">
</div>
<div class="form-group">
<label for="tokenfilterFiller">Filler</label>
<input ng-model="tokenfilter.filler" type="text" class="form-control" id="tokenfilterFiller" placeholder="">
</div>

View File

@ -1,6 +0,0 @@
<div class="form-group">
<label for="tokenfilterTokenMaps">Stop Words</label>
<select ng-model="tokenfilter.stop_token_map" class="form-control" id="tokenfilterTokenMaps">
<option ng-repeat="tokenMap in tokenMapNames">{{tokenMap}}</option>
</select>
</div>

View File

@ -1,4 +0,0 @@
<div class="form-group">
<label for="tokenfilterLen">Length</label>
<input ng-model="tokenfilter.length" type="number" class="form-control" id="tokenfilterLen" placeholder="">
</div>

View File

@ -1,3 +0,0 @@
<select ng-model="tokenfilter.word_map" class="form-control" id="tokenfilterTokenMaps">
<option ng-repeat="tokenMap in tokenMapNames">{{tokenMap}}</option>
</select>

View File

@ -1,34 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">Custom Tokenizer</h3>
</div>
<div class="modal-body">
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form" role="form">
<div class="form-group">
<label for="tname">Name</label>
<input ng-model="name" type="text" class="form-control" id="tname" placeholder="Name">
</div>
<div class="form-group">
<label for="tokenizertype">Type</label>
<div class="col-sm-12 input-group">
<select ng-change="tokenizerTypeChange()" ng-model="tokenizer.type" class="form-control" id="tokenizertype">
<option ng-repeat="tokenizerTyp in tokenizerTypes">{{tokenizerTyp}}</option>
</select>
</div>
</div>
<div ng-show="tokenizer.type" ng-include src="formpath"/>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button ng-click="build()" type="button" class="btn btn-primary pull-right">Save</button>
</div>

View File

@ -1,36 +0,0 @@
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(tname,tval) in mapping.analysis.tokenizers">
<td>{{tname}}</td>
<td>{{tval.type}}</td>
<td>
<div class="btn-group btn-group-xs" role="group">
<button ng-click="editTokenizer(tname, tval)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button ng-click="deleteTokenizer(tname)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button>
</div>
</td>
</tr>
<tr ng-show="Utils.keys(mapping.analysis.tokenizers).length < 1">
<td colspan="3">None</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">
<button ng-click="newTokenizer()" type="button" class="btn btn-sm btn-default pull-right">New Tokenizer</button>
</td>
</tr>
</tfoot>
</table>

View File

@ -1,24 +0,0 @@
<div class="form-group">
<label for="exampleInputPassword1">Exception Patterns</label>
<ul class="list-group" ng-show="tokenizer.exceptions.length < 1">
<li class="list-group-item">None</li>
</ul>
<ul class="list-group" ng-show="tokenizer.exceptions.length > 0" ui-sortable ng-model="tokenizer.exceptions">
<li class="list-group-item" ng-repeat="e in tokenizer.exceptions track by $index"><span class="glyphicon glyphicon-minus"></span> {{ e }}<span ng-click="removeException($index)" class="glyphicon glyphicon-remove pull-right"></span></li>
</ul>
</div>
<div class="form-group">
<label for="what"></label>
<div class="col-sm-10">
<input ng-model="newregexp" type="text" class="form-control" id="exceptionRegexp" placeholder="">
</div>
<div class="col-sm-2">
<button ng-click="addException(this)" type="button" class="btn btn-default pull-right">Add</button>
</div>
</div>
<div class="form-group">
<label for="analyzerTokenizer">Tokenizer for Remaining Input</label>
<select ng-change="tokenizerChanged()" ng-model="tokenizer.tokenizer" class="form-control" id="tokenizer">
<option ng-repeat="tokenizer in tokenizerNames">{{tokenizer}}</option>
</select>
</div>

View File

@ -1,4 +0,0 @@
<div class="form-group">
<label for="tokenizerRegexp">Regular Expression</label>
<input ng-model="tokenizer.regexp" type="text" class="form-control" id="tokenizerRegexp" placeholder="">
</div>

View File

@ -1,39 +0,0 @@
<div class="modal-header">
<h3 class="modal-title">Custom Word List</h3>
</div>
<div class="modal-body">
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form" role="form">
<div class="form-group">
<label for="tname">Name</label>
<input ng-model="name" type="text" class="form-control" id="tname" placeholder="Name">
</div>
<div class="form-group">
<label for="words">Words</label>
<select ng-model="selectedWords" multiple ng-multiple="true" id="words" size="5" class="form-control" ng-options="idx as word for (idx, word) in words">
</select>
</div>
<div class="form-group">
<label for="what"></label>
<div class="col-sm-8">
<input ng-model="newWord" type="text" class="form-control" id="newWord" placeholder="word">
</div>
<div class="col-sm-4">
<button ng-click="addWord()" type="button" class="btn btn-sm btn-default">Add</button>
<button ng-click="removeWord()" ng-disabled="selectedWords.length < 1" type="button" class="btn btn-sm btn-default pull-right">Remove</button>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" ng-click="cancel()">Cancel</button>
<button ng-click="build()" type="button" class="btn btn-primary pull-right">Save</button>
</div>

View File

@ -1,34 +0,0 @@
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(tmname,tmval) in mapping.analysis.token_maps">
<td>{{tmname}}</td>
<td>
<div class="btn-group btn-group-xs" role="group">
<button ng-click="editWordList(tmname, tmval)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button ng-click="deleteWordList(tmname)" type="button" class="btn btn-default btn-xs">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span> Delete
</button>
</div>
</td>
</tr>
<tr ng-show="Utils.keys(mapping.analysis.token_maps).length < 1">
<td colspan="2">None</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<button ng-click="newWordList()" type="button" class="btn btn-sm btn-default pull-right">New Word List</button>
</td>
</tr>
</tfoot>
</table>

View File

@ -1,119 +0,0 @@
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-file" aria-hidden="true"></span> Document Structure</h3>
</div>
<div class="panel-body">
<ul class="list-custom">
<span class="list-item" ng-click="clickItem(mapping.default_mapping, '<document root>')" ng-class="{selected: mapping.default_mapping==selectedItem}">
&bull; &lt;document root&gt;
</span>
<ul class="list-custom">
<li ng-repeat="(pname,pval) in mapping.default_mapping.properties" ng-include="'/static/partials/mapping/mapping-node.html'" ng-init="parent = pname"></li>
</ul>
</ul>
<div class="form-group form-group-sm">
<div class="col-sm-10">
<input ng-model="newFieldName" type="text" class="form-control" id="fieldName" placeholder="field name">
</div>
<button ng-click="addField(this)" type="button" class="btn btn-sm btn-default">Add</button>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-list" aria-hidden="true"></span> Indexing Behavior <small>{{selectedLabel}}</small></h3>
</div>
<div class="panel-body">
<div ng-show="selectedItem == null">Select an item in the document structure.</div>
<div ng-hide="selectedItem == null">
<div class="form-group form-group-sm">
<div class="col-sm-10">
<label>Type
<select ng-change="changeType(this)" ng-model="selectedItem.fields[0].type" ng-options="t.name as t.label for t in fieldTypes">
<option value="">Object</option>
</select>
</label>
</div>
</div>
<div ng-switch="selectedItem.fields[0].type">
<div ng-switch-when="text">
<div class="form-group form-group-sm">
<div class="col-sm-10">
<label>Analyzer
<select ng-change="changeType(this)" ng-model="selectedItem.fields[0].analyzer" ng-options="t as t for t in analyzerNames">
<option value="">Inherit</option>
</select>
</label>
</div>
</div>
</div>
<div ng-switch-when="datetime">
<div class="form-group form-group-sm">
<div class="col-sm-10">
<label>Date/TimeParser
<select ng-change="changeType(this)" ng-model="selectedItem.fields[0].date_format" ng-options="t as t for t in datetimeParserNames">
<option value="">Inherit</option>
</select>
</label>
</div>
</div>
</div>
</div>
</div>
<div ng-if="selectedItem.fields[0].type != '' && selectedItem.fields[0].type != 'disabled'">
<div class="checkbox">
<label>
<input ng-model="selectedItem.fields[0].index" type="checkbox"> Index
</label>
</div>
<div class="checkbox">
<label>
<input ng-model="selectedItem.fields[0].store" type="checkbox"> Store
</label>
</div>
<div class="checkbox">
<label>
<input ng-model="selectedItem.fields[0].include_in_all" type="checkbox"> Include in 'All' Field
</label>
</div>
<div ng-if="selectedItem.fields[0].type == 'text'">
<div class="checkbox">
<label>
<input ng-model="selectedItem.fields[0].include_term_vectors" type="checkbox"> Include Term Vectors
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,6 +0,0 @@
<span class="list-item"ng-click="clickItem(pval,pname)" ng-class="{selected: pval==selectedItem}">&bull; {{pname}}</span>
<ul class="list-custom">
<li ng-repeat="(pname,pval) in pval.properties" ng-init="parent = parent + '.' + pname">
<span class="list-item" ng-click="clickItem(pval,parent)" ng-class="{selected: pval==selectedItem}">&bull; {{pname}}</span>
</li>
</ul>

View File

@ -1,59 +0,0 @@
<div ng-show="errorMessage" class="alert alert-danger ng-cloak" role="alert"> {{errorMessage}}
</div>
<form class="form-horizontal" role="form">
<div class="form-group">
<label for="inputDoc" class="col-sm-2 control-label">Index Mapping</label>
<div class="col-sm-10">
<div class="radio">
<label>
<input ng-model="mappingType" type="radio" name="mappingType" value="default" checked>
Default
</label>
</div>
<div class="radio">
<label>
<input ng-model="mappingType" type="radio" name="mappingType" value="custom">
Custom
</label>
</div>
</div>
</div>
<div class="form-group" ng-show="mappingType == 'custom'">
<label for="inputDoc" class="col-sm-2 control-label">&nbsp;</label>
<div class="col-sm-10">
<div ng-include src="'/static/partials/mapping/mapping-custom.html'"/>
</div>
</div>
<div class="form-group" ng-controller="AnalysisCtrl" ng-show="mappingType == 'custom'">
<label for="inputDoc" class="col-sm-2 control-label">Custom Analysis</label>
<div class="col-sm-10">
<tabset>
<tab heading="Analyzers">
<div ng-include src="'/static/partials/analysis/analyzers.html'"/>
</tab>
<tab heading="Character Filters">
<div ng-include src="'/static/partials/analysis/charfilters.html'"/>
</tab>
<tab heading="Tokenizers">
<div ng-include src="'/static/partials/analysis/tokenizers.html'"/>
</tab>
<tab heading="Token Filters">
<div ng-include src="'/static/partials/analysis/tokenfilters.html'"/>
</tab>
<tab heading="Word Lists">
<div ng-include src="'/static/partials/analysis/wordlists.html'"/>
</tab>
</tabset>
</div>
</div>
</form>