781 lines
23 KiB
JavaScript
Raw Normal View History

(function (global, $) {
const searchForm = document.querySelector('#nav-keyword-search-form');
const searchInput = searchForm.querySelector('#searchInput');
// Prevent `enter` key on single input from triggering default form action resulting in page reload
searchForm && searchForm.addEventListener('submit', e => e.preventDefault());
/**
* Implements handler for search functionality on Navigation Bar search form.
* Updates location hash which will trigger Ember Search route model refresh
* *Unfortunately current application model does not abide by Ember recommended approach, hence manual plumbing
* *will be refactored in eventual `purge`
*/
const handleSearchInput = function () {
if (searchInput) {
const {value: keyword} = searchInput;
const searchRouteHash = `#/search?keywords=${btoa(keyword)}&category=${global.g_currentCategory}&source=default&page=1`;
keyword && (document.location.hash = searchRouteHash);
// Piwik track search keyword
_paq.push(['trackSiteSearch', keyword, global.g_currentCategory, false]);
}
};
$('#advsearchtabs').find('a:first').tab('show');
$('#datasetAdvSearchLink').addClass('active');
String.prototype.replaceAll = function (target, replacement) {
return this.split(target).join(replacement);
};
global.g_currentCategory = 'Datasets';
function renderAdvSearchDatasetSources(parent, sources) {
let content = '';
if ((!parent) || (!sources) || sources.length == 0) {
return;
}
for (var i = 0; i < sources.length; i++) {
content += '<label class="checkbox"><input type="checkbox" name="sourceCheckbox" value="';
content += sources[i] + '"/>' + sources[i] + '</label>';
}
parent.append(content);
}
$.ui.autocomplete.prototype._renderItem = function (ul, item) {
var term = this.term.split(' ').join('|');
var re = new RegExp('(' + term + ')', 'gi');
var t = item.label.replace(re, "<b><font color='blue'>$1</font></b>");
return $('<li></li>')
.data('item.autocomplete', item)
.append('<a>' + t + '</a>')
.appendTo(ul);
};
var maxReturnedResults = 20;
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
function sortAutocompleteResult(data, term) {
var source = $.ui.autocomplete.filter(data, term);
var keyword = $.ui.autocomplete.escapeRegex(term);
if (keyword && keyword.length < 4) {
return source.slice(0, maxReturnedResults);
}
var startsWithMatcher = new RegExp('^' + keyword, 'i');
var startsWith = $.grep(source, function (value) {
return startsWithMatcher.test(value.label || value.value || value);
});
var containsMatcher = new RegExp(keyword, 'i');
var contains = $.grep(source, function (value) {
return containsMatcher.test(value.label || value.value || value);
});
var result = startsWith.concat(contains);
var sorted = result.filter(function (elem, pos) {
return result.indexOf(elem) == pos;
});
return sorted.slice(0, maxReturnedResults);
}
$('.searchCategory').click(function (e) {
var objs = $('.searchCategory');
if (objs) {
$.each(objs, function (index, value) {
$(objs[index]).parent().removeClass('active');
});
}
global.g_currentCategory = e.target.text;
updateSearchCategories(e.target.text);
//$(e.target).parent().addClass( 'active' );
e.preventDefault();
});
var datasetSourcesUrl = '/api/v1/advsearch/sources';
$.get(datasetSourcesUrl, function (data) {
if (data && data.status == 'ok') {
var advSearchSourceObj = $('#advSearchSource');
if (advSearchSourceObj) {
if (data.sources) {
renderAdvSearchDatasetSources(advSearchSourceObj, data.sources);
}
}
}
});
$.get('/api/v1/autocomplete/search', function (data) {
const possibleMatches = data.source;
$('#searchInput').autocomplete({
source: function ({term}, res) {
const matchResults = $.ui.autocomplete.filter(possibleMatches, extractLast(term));
/**
* Sort the matches by giving precedence to matches that are closer in length to searchTerm and have
* the searchTerm occurring closer to the start of the matching string.
* e.g. `merlin_frontend_trunk` should occur before `trunk_MERLIN`
* @param {Array} arrayOfMatches
* @param {String} searchTerm
* @returns {Array}
*/
function sortMatches(arrayOfMatches, searchTerm) {
// Significantly! improve sort performance using the `Schwartzian transform` technique.
// Create a temp array so String#toLowerCase and Array#indexOf are performed once per unique match,
// same for match String#length.
// This is more efficient since the comparisonFunction can be invoked many times per element within an array.
const schwartzianMap = {
indexOfOnLowerCase: (match, idx) => ({
idx,
value: match.toLowerCase().indexOf(searchTerm)
}),
length: (match, idx) => ({idx, value: match.length})
};
// Performs the sort using the previously derived values in ascending order
const comparator = ({value: aValue}, {value: bValue}) => aValue - bValue;
// Deconstructs Schwartzian map to get back the actual matches in preferred order
// currying the `originalArray` for lazy evaluation allowing re-use
const deconstructMapUsing = originalArray => match => originalArray[match.idx];
const orderByMatchPosition = (arrayOfMatches) => arrayOfMatches
.map(schwartzianMap.indexOfOnLowerCase)
.sort(comparator)
.map(deconstructMapUsing(arrayOfMatches));
const orderByMatchLength = (arrayOfMatches) => arrayOfMatches
.map(schwartzianMap.length)
.sort(comparator)
.map(deconstructMapUsing(arrayOfMatches));
return orderByMatchLength(orderByMatchPosition(arrayOfMatches));
}
res(sortMatches(matchResults, term).slice(0, maxReturnedResults));
},
minLength: 3,
focus: () => false,
select: function (e, {item: {value}}) {
// On select update search input by replacing search trigger with selected auto-complete string
const terms = split(this.value);
terms.pop();
terms.push(value);
terms.push('');
this.value = terms.join(',');
return false;
}
}).on('autocompleteselect', handleSearchInput);
});
$.get('/api/v1/advsearch/scopes', function (data) {
$('.scopeInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.scopes, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$.get('/api/v1/advsearch/tables', function (data) {
$('.tableInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.tables, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$.get('/api/v1/advsearch/fields', function (data) {
$('.fieldInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.fields, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$.get('/api/v1/advsearch/appcodes', function (data) {
$('.appcodeInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.appcodes, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$.get('/api/v1/advsearch/flowNames', function (data) {
$('.flowInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.flowNames, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$.get('/api/v1/advsearch/jobNames', function (data) {
$('.jobInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.jobNames, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
$('#scopeInInput').blur(function () {
$.get('/api/v1/advsearch/tables', {scopes: $('#scopeInInput').val()}, function (data) {
$('.tableInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.tables, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
});
$('#tableInInput').blur(function () {
$.get('/api/v1/advsearch/fields', {tables: $('#tableInInput').val()}, function (data) {
$('.fieldInput').autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.fields, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push('');
this.value = terms.join(', ');
return false;
}
});
});
});
$.get('/api/v1/advsearch/dashboards', function (data) {
$(".dashInput").autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.dashboardNames, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
$.get('/api/v1/advsearch/metricGroups', function (data) {
$(".groupInput").autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.metricGroups, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
$.get('/api/v1/advsearch/metricCategories', function (data) {
$(".categoryInput").autocomplete({
minLength: 0,
source: function (req, res) {
var results = $.ui.autocomplete.filter(data.metricCategories, extractLast(req.term));
res(results.slice(0, maxReturnedResults));
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
$.get('/api/v1/advsearch/metricNames', function (data) {
$(".metricnameInput").autocomplete({
minLength: 0,
source: function (req, res) {
var result = [];
if (data && data.metricNames && req.term) {
result = sortAutocompleteResult(data.metricNames, req.term);
}
return res(result);
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});
});
function advSearchForMetric() {
var empty = true;
var dashInInputObj = $('#dashInInput');
var dashIn = '';
if (dashInInputObj) {
dashIn = dashInInputObj.val();
if (dashIn) {
empty = false;
}
}
var dashNotInInputObj = $('#dashNotInInput');
var dashNotIn = '';
if (dashNotInInputObj) {
dashNotIn = dashNotInInputObj.val();
if (dashNotIn) {
empty = false;
}
}
var groupInInputObj = $('#groupInInput');
var groupIn = '';
if (groupInInputObj) {
groupIn = groupInInputObj.val();
if (groupIn) {
empty = false;
}
}
var groupNotInInputObj = $('#groupNotInInput');
var groupNotIn = '';
if (groupNotInInputObj) {
groupNotIn = groupNotInInputObj.val();
if (groupNotIn) {
empty = false;
}
}
var categoryInInputObj = $('#categoryInInput');
var categoryIn = '';
if (categoryInInputObj) {
categoryIn = categoryInInputObj.val();
if (categoryIn) {
empty = false;
}
}
var categoryNotInInputObj = $('#categoryNotInInput');
var categoryNotIn = '';
if (categoryNotInInputObj) {
categoryNotIn = categoryNotInInputObj.val();
if (categoryNotIn) {
empty = false;
}
}
var metricnameInInputObj = $('#metricnameInInput');
var metricnameIn = '';
if (metricnameInInputObj) {
metricnameIn = metricnameInInputObj.val();
if (metricnameIn) {
empty = false;
}
}
var metricnameNotInInputObj = $('#metricnameNotInInput');
var metricnameNotIn = '';
if (metricnameNotInInputObj) {
metricnameNotIn = metricnameNotInInputObj.val();
if (metricnameNotIn) {
empty = false;
}
}
if (empty) {
return;
}
var advSearchOpts = {};
advSearchOpts.category = 'Metric';
advSearchOpts.dashboard = {'in': dashIn, 'not': dashNotIn};
advSearchOpts.group = {'in': groupIn, 'not': groupNotIn};
advSearchOpts.cat = {'in': categoryIn, 'not': categoryNotIn};
advSearchOpts.metric = {'in': metricnameIn, 'not': metricnameNotIn};
window.location = "/#/advsearch/?query=" + btoa(JSON.stringify(advSearchOpts)) + '&page=1';
}
document.querySelector('#searchBtn').addEventListener('click', handleSearchInput);
// This is a stop gap implementation to solve the issue with handling the enter key on user search
document.querySelector('#searchInput').addEventListener('keypress', e => e.keyCode === 13 && handleSearchInput(e));
function advSearchForDataset() {
var empty = true;
var scopeInInputObj = $('#scopeInInput');
var scopeIn = '';
if (scopeInInputObj) {
scopeIn = scopeInInputObj.val();
if (scopeIn) {
empty = false;
}
}
var scopeNotInInputObj = $('#scopeNotInInput');
var scopeNotIn = '';
if (scopeNotInInputObj) {
scopeNotIn = scopeNotInInputObj.val();
if (scopeNotIn) {
empty = false;
}
}
var tableInInputObj = $('#tableInInput');
var tableIn = '';
if (tableInInputObj) {
tableIn = tableInInputObj.val();
if (tableIn) {
empty = false;
}
}
var tableNotInInputObj = $('#tableNotInInput');
var tableNotIn = '';
if (tableNotInInputObj) {
tableNotIn = tableNotInInputObj.val();
if (tableNotIn) {
empty = false;
}
}
var fieldAnyInputObj = $('#fieldAnyInput');
var fieldAny = '';
if (fieldAnyInputObj) {
fieldAny = fieldAnyInputObj.val();
if (fieldAny) {
empty = false;
}
}
var fieldAllInputObj = $('#fieldAllInput');
var fieldAll = '';
if (fieldAllInputObj) {
fieldAll = fieldAllInputObj.val();
if (fieldAll) {
empty = false;
}
}
var fieldNotInInputObj = $('#fieldNotInInput');
var fieldNotIn = '';
if (fieldNotInInputObj) {
fieldNotIn = fieldNotInInputObj.val();
if (fieldNotIn) {
empty = false;
}
}
var commentsInputObj = $('#commentsInput');
var comments = '';
if (commentsInputObj) {
comments = commentsInputObj.val();
if (comments) {
empty = false;
}
}
var sources = '';
$('input[name=sourceCheckbox]:checked').each(function () {
sources += this.value + ','
});
sources = sources.substring(0, sources.length - 1);
if (sources) {
empty = false;
}
if (empty) {
return;
}
var advSearchOpts = {};
advSearchOpts.category = 'Dataset';
advSearchOpts.scope = {'in': scopeIn, 'not': scopeNotIn};
advSearchOpts.table = {'in': tableIn, 'not': tableNotIn};
advSearchOpts.fields = {'any': fieldAny, 'all': fieldAll, 'not': fieldNotIn};
advSearchOpts.comments = comments;
advSearchOpts.sources = sources;
global.location = '/#/advsearch/?query=' + btoa(JSON.stringify(advSearchOpts)) + '&page=1';
}
function advSearchForFlow() {
var empty = true;
var appcodeInInputObj = $('#appcodeInInput');
var appcodeIn = '';
if (appcodeInInputObj) {
appcodeIn = appcodeInInputObj.val();
if (appcodeIn) {
empty = false;
}
}
var appcodeNotInInputObj = $('#appcodeNotInInput');
var appcodeNotIn = '';
if (appcodeNotInInputObj) {
appcodeNotIn = appcodeNotInInputObj.val();
if (appcodeNotIn) {
empty = false;
}
}
var flowInInputObj = $('#flowInInput');
var flowIn = '';
if (flowInInputObj) {
flowIn = flowInInputObj.val();
if (flowIn) {
empty = false;
}
}
var flowNotInInputObj = $('#flowNotInInput');
var flowNotIn = '';
if (flowNotInInputObj) {
flowNotIn = flowNotInInputObj.val();
if (flowNotIn) {
empty = false;
}
}
var jobInInputObj = $('#jobInInput');
var jobIn = '';
if (jobInInputObj) {
jobIn = jobInInputObj.val();
if (jobIn) {
empty = false;
}
}
var jobNotInInputObj = $('#jobNotInInput');
var jobNotIn = '';
if (jobNotInInputObj) {
jobNotIn = jobNotInInputObj.val();
if (jobNotIn) {
empty = false;
}
}
if (empty) {
return;
}
var advSearchOpts = {};
advSearchOpts.category = 'Flow';
advSearchOpts.appcode = {'in': appcodeIn, 'not': appcodeNotIn};
advSearchOpts.flow = {'in': flowIn, 'not': flowNotIn};
advSearchOpts.job = {'in': jobIn, 'not': jobNotIn};
global.location = '/#/advsearch/?query=' + btoa(JSON.stringify(advSearchOpts)) + '&page=1';
}
$('#advSearchBtn').click(function () {
var obj = $('#advsearchtabs').find('.active');
if (obj) {
var text = obj.text();
if (text == 'Datasets') {
advSearchForDataset();
}
else if (text == 'Metrics') {
advSearchForMetric();
}
else {
advSearchForFlow();
}
}
});
$('#advSearchResetBtn').click(function () {
var scopeInInputObj = $('#scopeInInput');
if (scopeInInputObj) {
scopeInInputObj.val('');
}
var scopeNotInInputObj = $('#scopeNotInInput');
if (scopeNotInInputObj) {
scopeNotInInputObj.val('');
}
var tableInInputObj = $('#tableInInput');
if (tableInInputObj) {
tableInInputObj.val('');
}
var tableNotInInputObj = $('#tableNotInInput');
if (tableNotInInputObj) {
tableNotInInputObj.val('');
}
var fieldAnyInputObj = $('#fieldAnyInput');
if (fieldAnyInputObj) {
fieldAnyInputObj.val('');
}
var fieldAllInputObj = $('#fieldAllInput');
if (fieldAllInputObj) {
fieldAllInputObj.val('');
}
var fieldNotInInputObj = $('#fieldNotInInput');
if (fieldNotInInputObj) {
fieldNotInInputObj.val('');
}
var commentsInputObj = $('#commentsInput');
if (commentsInputObj) {
commentsInputObj.val('');
}
$('input[name=sourceCheckbox]:checked').each(function () {
this.checked = false;
});
var appcodeInInputObj = $('#appcodeInInput');
if (appcodeInInputObj) {
appcodeInInputObj.val('');
}
var appcodeNotInInputObj = $('#appcodeNotInInput');
if (appcodeNotInInputObj) {
appcodeNotInInputObj.val('');
}
var flowInInputObj = $('#flowInInput');
if (flowInInputObj) {
flowInInputObj.val('');
}
var flowNotInInputObj = $('#flowNotInInput');
if (flowNotInInputObj) {
flowNotInInputObj.val('');
}
var jobInInputObj = $('#jobInInput');
if (jobInInputObj) {
jobInInputObj.val('');
}
var jobNotInInputObj = $('#jobNotInInput');
if (jobNotInInputObj) {
jobNotInInputObj.val('');
}
var dashboardInInputObj = $('#dashInInput');
if (dashboardInInputObj) {
dashboardInInputObj.val('');
}
var dashboardNotInInputObj = $('#dashNotInInput');
if (dashboardNotInInputObj) {
dashboardNotInInputObj.val('');
}
var groupInInputObj = $('#groupInInput');
if (groupInInputObj) {
groupInInputObj.val('');
}
var groupNotInInputObj = $('#groupNotInInput');
if (groupNotInInputObj) {
groupNotInInputObj.val('');
}
var categoryInInputObj = $('#categoryInInput');
if (categoryInInputObj) {
categoryInInputObj.val('');
}
var categoryNotInInputObj = $('#categoryNotInInput');
if (categoryNotInInputObj) {
categoryNotInInputObj.val('');
}
var metricInInputObj = $('#metricnameInInput');
if (metricInInputObj) {
metricInInputObj.val('');
}
var metricNotInInputObj = $('#metricnameNotInInput');
if (metricNotInInputObj) {
metricNotInInputObj.val('');
}
});
})(window, jQuery);