This is an automated email from the ASF dual-hosted git repository. kbhatt pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/branch-2.0 by this push: new c27883c ATLAS-3900: UI: Allow user to select the date range for date attribute in basic search c27883c is described below commit c27883ccc38d07ddc6aa273f38d20920b8035a38 Author: kevalbhatt <kbh...@apache.org> AuthorDate: Fri Aug 7 18:16:33 2020 +0530 ATLAS-3900: UI: Allow user to select the date range for date attribute in basic search (cherry picked from commit 41eebcf4cf435d37c5e67aea916513eac36e3ee5) --- dashboardv2/package-lock.json | 6 +- dashboardv2/package.json | 2 +- dashboardv2/public/css/scss/override.scss | 24 ++- dashboardv2/public/js/utils/CommonViewFunction.js | 89 ++++---- dashboardv2/public/js/utils/Enums.js | 37 +++- .../public/js/views/search/QueryBuilderView.js | 236 +++++++++++++++------ dashboardv3/package-lock.json | 6 +- dashboardv3/package.json | 2 +- dashboardv3/public/css/scss/override.scss | 22 +- dashboardv3/public/js/main.js | 1 - .../search/SearchDefaultLayoutView_tmpl.html | 6 +- dashboardv3/public/js/utils/CommonViewFunction.js | 88 ++++---- dashboardv3/public/js/utils/Enums.js | 37 +++- .../public/js/views/search/QueryBuilderView.js | 236 +++++++++++++++------ .../js/views/search/tree/EntityTreeLayoutView.js | 3 +- 15 files changed, 536 insertions(+), 259 deletions(-) diff --git a/dashboardv2/package-lock.json b/dashboardv2/package-lock.json index afc9fb3..b0afc0b 100644 --- a/dashboardv2/package-lock.json +++ b/dashboardv2/package-lock.json @@ -357,9 +357,9 @@ "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=" }, "bootstrap-daterangepicker": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-2.1.25.tgz", - "integrity": "sha1-/Ni6C3VaBU0zDXo7fE3Yu4Vc/7c=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz", + "integrity": "sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==", "requires": { "jquery": ">=1.10", "moment": "^2.9.0" diff --git a/dashboardv2/package.json b/dashboardv2/package.json index e0809d3..1c17c67 100644 --- a/dashboardv2/package.json +++ b/dashboardv2/package.json @@ -29,7 +29,7 @@ "backgrid-select-all": "0.3.5", "backgrid-sizeable-columns": "0.1.1", "bootstrap": "3.3.7", - "bootstrap-daterangepicker": "2.1.25", + "bootstrap-daterangepicker": "3.1.0", "d3": "3.5.17", "d3-tip": "0.6.8", "dagre-d3": "0.6.4", diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss index 2bcfde9..de5462c 100644 --- a/dashboardv2/public/css/scss/override.scss +++ b/dashboardv2/public/css/scss/override.scss @@ -300,7 +300,7 @@ } .rule-operator-container { - width: 105px; + width: 150px; .form-control { width: 100% !important; @@ -507,4 +507,26 @@ div.columnmanager-dropdown-container { overflow: hidden; text-overflow: ellipsis; } +} + +.daterangepicker { + max-height: 400px; + overflow-y: scroll; + + .ranges { + max-height: 328px; + overflow: auto; + } + + .ranges li.active, + td.active { + background-color: $color_havelock_blue_approx; + } + + .drp-buttons { + .applyBtn { + background-color: $color_havelock_blue_approx; + border-color: $color_havelock_blue_approx; + } + } } \ No newline at end of file diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js index a1c5ad3..4d10fa6 100644 --- a/dashboardv2/public/js/utils/CommonViewFunction.js +++ b/dashboardv2/public/js/utils/CommonViewFunction.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enums', 'moment', 'utils/Globals'], function(require, Utils, Modal, Messages, Enums, moment, Globals) { +define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, Utils, Modal, Messages, Enums, moment, Globals) { 'use strict'; var CommonViewFunction = {}; @@ -387,9 +387,13 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum function objToString(filterObj) { var generatedQuery = _.map(filterObj.rules, function(obj, key) { + var obj = $.extend(true, {}, obj); // not to update the timezone abbr on original obj , copy of obj is used if (_.has(obj, 'condition')) { return ' <span class="operator">' + obj.condition + '</span> ' + '(' + objToString(obj) + ')'; } else { + if (obj.type === "date") { + obj.value = obj.value + " (" + moment.tz(moment.tz.guess()).zoneAbbr() + ")"; + } return '<span class="key">' + (Enums.systemAttributes[obj.id] ? Enums.systemAttributes[obj.id] : _.escape(obj.id)) + '</span> <span class="operator">' + _.escape(obj.operator) + '</span> <span class="value">' + (Enums[obj.id] ? Enums[obj.id][obj.value] : _.escape(obj.value)) + "</span>"; } }); @@ -487,6 +491,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum if (Globals[value[skey].typeName]) { attributeDefs = Globals[value[skey].typeName].attributeDefs; } + if (Globals._ALL_CLASSIFICATION_TYPES && Globals._ALL_CLASSIFICATION_TYPES.attributeDefs) { + attributeDefs = attributeDefs.concat(Globals._ALL_CLASSIFICATION_TYPES.attributeDefs); + } } val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); } else if (k == "entityFilters") { @@ -503,6 +510,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum if (Globals[value[skey].typeName]) { attributeDefs = Globals[value[skey].typeName].attributeDefs; } + if (Globals._ALL_ENTITY_TYPES && Globals._ALL_ENTITY_TYPES.attributeDefs) { + attributeDefs = attributeDefs.concat(Globals._ALL_ENTITY_TYPES.attributeDefs); + } } val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); } else if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) { @@ -544,7 +554,18 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum var type = (obj.type || obj.attributeType), //obj.value will come as an object when selected type is Date and operator is isNull or not_null; value = ((_.isString(obj.value) && _.contains(["is_null", "not_null"], obj.operator) && type === 'date') || _.isObject(obj.value) ? "" : _.trim(obj.value || obj.attributeValue)), - url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), (type === 'date' && formatedDateToLong && value.length ? Date.parse(value) : value)]; + url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), value]; + if (obj.operator === "TIME_RANGE") { + if (value.indexOf("-") > -1) { + url[2] = value.split('-').map(function(udKey) { + return Date.parse(udKey.trim()).toString() + }).join(",") + } else { + url[2] = Enums.queryBuilderDateRangeUIValueToAPI[_.trim(value)] || value; + } + } else if (value.length && type === 'date' && formatedDateToLong) { + url[2] = Date.parse(value); + } if (type) { url.push(type); } @@ -561,30 +582,8 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum } function mapApiOperatorToUI(oper) { - if (oper == "eq") { - return "="; - } else if (oper == "neq") { - return "!="; - } else if (oper == "lt") { - return "<"; - } else if (oper == "lte") { - return "<="; - } else if (oper == "gt") { - return ">"; - } else if (oper == "gte") { - return ">="; - } else if (oper == "startsWith") { - return "begins_with"; - } else if (oper == "endsWith") { - return "ends_with"; - } else if (oper == "contains") { - return "contains"; - } else if (oper == "notNull") { - return "not_null"; - } else if (oper == "isNull") { - return "is_null"; - } - return oper; + // Enum will be in effect once we click on save search. + return Enums.queryBuilderApiOperatorToUI[oper] || oper; } }, extractUrl: function(options) { @@ -594,30 +593,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum spliter = 1, apiObj = options.apiObj, mapUiOperatorToAPI = function(oper) { - if (oper == "=") { - return "eq"; - } else if (oper == "!=") { - return "neq"; - } else if (oper == "<") { - return "lt"; - } else if (oper == "<=") { - return "lte"; - } else if (oper == ">") { - return "gt"; - } else if (oper == ">=") { - return "gte"; - } else if (oper == "begins_with") { - return "startsWith"; - } else if (oper == "ends_with") { - return "endsWith"; - } else if (oper == "contains") { - return "contains"; - } else if (oper == "not_null") { - return "notNull"; - } else if (oper == "is_null") { - return "isNull"; - } - return oper; + return Enums.queryBuilderUIOperatorToAPI[oper] || oper; }, createObject = function(urlObj) { var finalObj = {}; @@ -636,13 +612,24 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum rule = {}; if (apiObj) { rule = { attributeName: temp[0], operator: mapUiOperatorToAPI(temp[1]), attributeValue: _.trim(temp[2]) } + rule.attributeValue = rule.type === 'date' && formatDate && rule.attributeValue.length ? moment(parseInt(rule.attributeValue)).format(Globals.dateTimeFormat) : rule.attributeValue; } else { rule = { id: temp[0], operator: temp[1], value: _.trim(temp[2]) } if (temp[3]) { rule['type'] = temp[3]; } - rule.value = rule.type === 'date' && formatDate && rule.value.length ? moment(parseInt(rule.value)).format(Globals.dateTimeFormat) : rule.value; + if (rule.operator === "TIME_RANGE") { + if (temp[2].indexOf(",") > -1) { + rule.value = temp[2].split(",").map(function(udKey) { + return moment(parseInt(udKey.trim())).format(Globals.dateTimeFormat) + }).join(" - ") + } else { + rule.value = Enums.queryBuilderDateRangeAPIValueToUI[_.trim(rule.value)] || rule.value; + } + } else if (rule.type === 'date' && formatDate && rule.value.length) { + rule.value = moment(parseInt(rule.value)).format(Globals.dateTimeFormat) + } } return rule; } diff --git a/dashboardv2/public/js/utils/Enums.js b/dashboardv2/public/js/utils/Enums.js index 24ec36b..131a08f 100644 --- a/dashboardv2/public/js/utils/Enums.js +++ b/dashboardv2/public/js/utils/Enums.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require'], function(require) { +define(["require", "backbone"], function(require) { 'use strict'; var Enums = {}; @@ -219,5 +219,40 @@ define(['require'], function(require) { 0: "false", 1: "true" }; + + Enums.queryBuilderUIOperatorToAPI = { + "=": "eq", + "!=": "neq", + "<": "lt", + "<=": "lte", + ">": "gt", + ">=": "gte", + "begins_with": "startsWith", + "ends_with": "endsWith", + "not_null": "notNull", + "is_null": "isNull", + "TIME_RANGE": "timerange" + }; + + Enums.queryBuilderApiOperatorToUI = _.invert(Enums.queryBuilderUIOperatorToAPI); + + Enums.queryBuilderDateRangeUIValueToAPI = { + "Today": "TODAY", + "Yesterday": "YESTERDAY", + "Last 7 Days": "LAST_7_DAYS", + "Last 30 Days": "LAST_30_DAYS", + "This Month": "THIS_MONTH", + "Last Month": "LAST_MONTH", + "This Quarter": "THIS_QUARTER", + "Last Quarter":"LAST_QUARTER", + "This Year": "THIS_YEAR", + "Last Year": "LAST_YEAR", + "Last 3 Months": "LAST_3_MONTHS", + "Last 6 Months": "LAST_6_MONTHS", + "Last 12 Months": "LAST_12_MONTHS" + }; + + Enums.queryBuilderDateRangeAPIValueToUI = _.invert(Enums.queryBuilderDateRangeUIValueToAPI); + return Enums; }); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/QueryBuilderView.js b/dashboardv2/public/js/views/search/QueryBuilderView.js index dc36ffe..ba6cf0d 100644 --- a/dashboardv2/public/js/views/search/QueryBuilderView.js +++ b/dashboardv2/public/js/views/search/QueryBuilderView.js @@ -24,9 +24,10 @@ define(['require', 'utils/CommonViewFunction', 'utils/Enums', 'utils/Globals', + 'moment', 'query-builder', 'daterangepicker' -], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums, Globals) { +], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums, Globals, moment) { var QueryBuilderView = Backbone.Marionette.LayoutView.extend( /** @lends QueryBuilderView */ @@ -58,6 +59,22 @@ define(['require', _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'businessMetadataDefCollection', 'tag', 'type', 'searchTableFilters', 'systemAttrArr', 'adminAttrFilters')); this.attrObj = _.sortBy(this.attrObj, 'name'); this.filterType = this.tag ? 'tagFilters' : 'entityFilters'; + this.defaultRange = "Last 7 Days"; + this.dateRangesMap = { + 'Today': [moment(), moment()], + 'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], + 'Last 7 Days': [moment().subtract(6, 'days'), moment()], + 'Last 30 Days': [moment().subtract(29, 'days'), moment()], + 'This Month': [moment().startOf('month'), moment().endOf('month')], + 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 3 Months': [moment().subtract(3, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 6 Months': [moment().subtract(6, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 12 Months': [moment().subtract(12, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'This Quarter': [moment().startOf('quarter'), moment().endOf('quarter')], + 'Last Quarter': [moment().subtract(1, 'quarter').startOf('quarter'), moment().subtract(1, 'quarter').endOf('quarter')], + 'This Year': [moment().startOf('year'), moment().endOf('year')], + 'Last Year': [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')] + } }, bindEvents: function() {}, getOperator: function(type, skipDefault) { @@ -71,7 +88,7 @@ define(['require', } } if (type === "date") { - obj.operators = ['>', '<']; + obj.operators = ['=', '!=', '>', '<', '>=', '<=', 'TIME_RANGE']; } if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double") { obj.operators = ['=', '!=', '>', '<', '>=', '<=']; @@ -266,20 +283,7 @@ define(['require', } if (obj.type === "date") { obj['plugin'] = 'daterangepicker'; - obj['plugin_config'] = { - "singleDatePicker": true, - "showDropdowns": true, - "timePicker": true, - locale: { - format: Globals.dateTimeFormat - } - }; - if (rules) { - var valueObj = _.find(rules, { id: obj.id }); - if (valueObj) { - obj.plugin_config["startDate"] = valueObj.value; - } - } + obj['plugin_config'] = this.getDateConfig(rules, obj.id); _.extend(obj, this.getOperator(obj.type)); return obj; } @@ -316,6 +320,86 @@ define(['require', return obj; } }, + getDateConfig: function(ruleObj, id, operator) { + var valueObj = ruleObj ? (_.find(ruleObj.rules, { id: id }) || {}) : {}, + isTimeRange = (valueObj.operator && valueObj.operator === "TIME_RANGE" && operator === "TIME_RANGE") || (operator === "TIME_RANGE"), + obj = { + opens: "center", + autoApply: true, + autoUpdateInput: false, + timePickerSeconds: true, + timePicker: true, + locale: { + format: Globals.dateTimeFormat + } + }; + + if (isTimeRange) { + var defaultRangeDate = this.dateRangesMap[this.defaultRange]; + obj.startDate = defaultRangeDate[0]; + obj.endDate = defaultRangeDate[1]; + obj.singleDatePicker = false; + obj.ranges = this.dateRangesMap; + } else { + obj.singleDatePicker = true; + obj.startDate = moment(); + obj.endDate = obj.startDate; + } + + if (!_.isEmpty(valueObj) && operator === valueObj.operator) { + if (isTimeRange) { + if (valueObj.value.indexOf("-") > -1) { + var dates = valueObj.value.split("-"); + obj.startDate = dates[0].trim(); + obj.endDate = dates[1].trim(); + } else { + var dates = this.dateRangesMap[valueObj.value] + obj.startDate = dates[0]; + obj.endDate = dates[1]; + } + obj.singleDatePicker = false; + } else { + obj.startDate = moment(valueObj.value); + obj.endDate = moment(valueObj.value); + obj.singleDatePicker = true; + } + } + + return obj; + }, + setDateValue: function(rule, rules_widgets) { + if (rule.filter.type === "date" && rule.operator.nb_inputs) { + var inputEl = rule.$el.find(".rule-value-container").find("input"), + datepickerEl = rule.$el.find(".rule-value-container").find("input").data("daterangepicker") + inputEl.attr('readonly', true); + if (datepickerEl) { + datepickerEl.remove(); + var configObj = this.getDateConfig(rules_widgets, rule.filter.id, rule.operator.type) + inputEl.daterangepicker(configObj); + if (rule.operator.type === "TIME_RANGE") { + rule.value = this.defaultRange; + } else { + rule.value = configObj.startDate.format(Globals.dateTimeFormat); + } + inputEl.on('apply.daterangepicker', function(ev, picker) { + picker.setStartDate(picker.startDate); + picker.setEndDate(picker.endDate); + var valueString = ""; + if (picker.chosenLabel) { + if (picker.chosenLabel === "Custom Range") { + valueString = picker.startDate.format(Globals.dateTimeFormat) + " - " + picker.endDate.format(Globals.dateTimeFormat); + } else { + valueString = picker.chosenLabel; + } + } else { + valueString = picker.startDate.format(Globals.dateTimeFormat); + } + picker.element.val(valueString); + rule.value = valueString; + }); + } + } + }, onRender: function() { var that = this, filters = [], @@ -339,7 +423,7 @@ define(['require', rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters ? this.searchTableFilters["adminAttrFilters"] : null, "formatDate": true });; } else { if (this.value) { - var rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true }); + rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true }); } _.each(this.attrObj, function(obj) { var type = that.tag ? that.value.tag : that.value.type; @@ -415,16 +499,20 @@ define(['require', } filters = _.uniq(filters, 'id'); if (filters && !_.isEmpty(filters)) { - this.ui.builder.queryBuilder({ - plugins: ['bt-tooltip-errors'], - filters: filters, - select_placeholder: placeHolder, - allow_empty: true, - conditions: ['AND', 'OR'], - allow_groups: true, - allow_empty: true, - templates: { - rule: '<div id="{{= it.rule_id }}" class="rule-container"> \ + this.ui.builder.off() + .on("afterUpdateRuleOperator.queryBuilder", function(e, rule) { + that.setDateValue(rule, rules_widgets); + }) + .queryBuilder({ + plugins: ['bt-tooltip-errors'], + filters: filters, + select_placeholder: placeHolder, + allow_empty: true, + conditions: ['AND', 'OR'], + allow_groups: true, + allow_empty: true, + templates: { + rule: '<div id="{{= it.rule_id }}" class="rule-container"> \ <div class="values-box"><div class="rule-filter-container"></div> \ <div class="rule-operator-container"></div> \ <div class="rule-value-container"></div></div> \ @@ -439,50 +527,58 @@ define(['require', <div class="error-container"><i class="{{= it.icons.error }}"></i> <span></span></div> \ {{?}} \ </div>' - }, - operators: [ - { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'like', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'in', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] } - ], - lang: { - add_rule: 'Add filter', - add_group: 'Add filter group', - operators: { - not_null: 'is not null' + }, + operators: [ + { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'like', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'in', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: 'TIME_RANGE', nb_inputs: 1, multiple: false, apply_to: ['date'] } + ], + lang: { + add_rule: 'Add filter', + add_group: 'Add filter group', + operators: { + not_null: 'is not null', + TIME_RANGE: "Time Range" + } + }, + icons: { + add_rule: 'fa fa-plus', + remove_rule: 'fa fa-times', + error: 'fa fa-exclamation-triangle' + }, + rules: rules_widgets + }) + .on("afterCreateRuleInput.queryBuilder", function(e, rule) { + rule.error = null; + if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") { + rule.$el.addClass("user-define"); + } else if (rule.$el.hasClass("user-define")) { + rule.$el.removeClass("user-define"); } - }, - icons: { - add_rule: 'fa fa-plus', - remove_rule: 'fa fa-times', - error: 'fa fa-exclamation-triangle' - }, - rules: rules_widgets - }).on("afterCreateRuleInput.queryBuilder", function(e, rule) { - rule.error = null; - if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") { - rule.$el.addClass("user-define"); - } else if (rule.$el.hasClass("user-define")) { - rule.$el.removeClass("user-define"); - } - }).on('validationError.queryBuilder', function(e, rule, error, value) { - // never display error for my custom filter - var errorMsg = error[0]; - if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) { - errorMsg = that.queryBuilderLang.errors[errorMsg]; - } - rule.$el.find(".error-container span").html(errorMsg); - }); + if (rule.filter.type === "date") { + rule.$el.find('.rule-value-container >input').attr('readonly', true) + } + that.setDateValue(rule, rules_widgets); + }) + .on('validationError.queryBuilder', function(e, rule, error, value) { + // never display error for my custom filter + var errorMsg = error[0]; + if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) { + errorMsg = that.queryBuilderLang.errors[errorMsg]; + } + rule.$el.find(".error-container span").html(errorMsg); + }); var queryBuilderEl = that.ui.builder.data("queryBuilder"); if (queryBuilderEl && queryBuilderEl.lang) { this.queryBuilderLang = queryBuilderEl.lang; diff --git a/dashboardv3/package-lock.json b/dashboardv3/package-lock.json index a9c0764..9721967 100644 --- a/dashboardv3/package-lock.json +++ b/dashboardv3/package-lock.json @@ -357,9 +357,9 @@ "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=" }, "bootstrap-daterangepicker": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-2.1.25.tgz", - "integrity": "sha1-/Ni6C3VaBU0zDXo7fE3Yu4Vc/7c=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz", + "integrity": "sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==", "requires": { "jquery": ">=1.10", "moment": "^2.9.0" diff --git a/dashboardv3/package.json b/dashboardv3/package.json index cab875d..43ae1bb 100644 --- a/dashboardv3/package.json +++ b/dashboardv3/package.json @@ -29,7 +29,7 @@ "backgrid-select-all": "0.3.5", "backgrid-sizeable-columns": "0.1.1", "bootstrap": "3.3.7", - "bootstrap-daterangepicker": "2.1.25", + "bootstrap-daterangepicker": "3.1.0", "d3": "3.5.17", "d3-tip": "0.6.8", "dagre-d3": "0.6.4", diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss index 7499894..1c8fcfc 100644 --- a/dashboardv3/public/css/scss/override.scss +++ b/dashboardv3/public/css/scss/override.scss @@ -304,7 +304,7 @@ } .rule-operator-container { - width: 105px; + width: 150px; .form-control { width: 100% !important; @@ -511,4 +511,24 @@ div.columnmanager-dropdown-container { overflow: hidden; text-overflow: ellipsis; } +} + +.daterangepicker { + + .ranges { + max-height: 328px; + overflow: auto; + } + + .ranges li.active, + td.active { + background-color: $color_havelock_blue_approx; + } + + .drp-buttons { + .applyBtn { + background-color: $color_havelock_blue_approx; + border-color: $color_havelock_blue_approx; + } + } } \ No newline at end of file diff --git a/dashboardv3/public/js/main.js b/dashboardv3/public/js/main.js index d5c6787..9f9747f 100644 --- a/dashboardv3/public/js/main.js +++ b/dashboardv3/public/js/main.js @@ -348,7 +348,6 @@ require(['App', startApp(); } }); - this.businessMetadataDefCollection.fetch({ complete: function() { that.businessMetadataDefCollection.fullCollection.comparator = function(model) { diff --git a/dashboardv3/public/js/templates/search/SearchDefaultLayoutView_tmpl.html b/dashboardv3/public/js/templates/search/SearchDefaultLayoutView_tmpl.html index 23ad9a8..1ce1218 100644 --- a/dashboardv3/public/js/templates/search/SearchDefaultLayoutView_tmpl.html +++ b/dashboardv3/public/js/templates/search/SearchDefaultLayoutView_tmpl.html @@ -30,7 +30,7 @@ <button class="btn-action btn-sm attribute-filter-text" data-id='attrFilter'> <i class="fa fa-angle-right"></i> Filters</button> <button class='btn-action btn-sm' data-id='clearQuerySearch'>Clear</button> <div class="attribute-filter-container hide"> - <div class="panel panel-default expand_collapse_panel-icon" data-id="includeExclude"> + <div class="panel panel-default expand_collapse_panel-icon" data-id="includeExclude" style="margin-bottom: 0px;"> <div class="panel-heading" data-toggle="collapse" href="#collapseIncludeExclude" aria-expanded="true"> <h4 class="panel-title"> <a>Include/Exclude</a> @@ -40,8 +40,8 @@ </div> </div> <div id="collapseIncludeExclude" class="panel-collapse collapse in"> - <div class="panel-body"> - <div class="form-group filter-box"> + <div class="panel-body" style="padding: 4px 15px;"> + <div class="form-group filter-box" style="margin: 0;"> <div class="entity-detail-table-toggle"> <div class="pretty p-switch p-fill"> <input type="checkbox" data-id="checkDeletedEntity" data-value="includeDE" id="historicalentities" /> diff --git a/dashboardv3/public/js/utils/CommonViewFunction.js b/dashboardv3/public/js/utils/CommonViewFunction.js index dd3818b..670e509 100644 --- a/dashboardv3/public/js/utils/CommonViewFunction.js +++ b/dashboardv3/public/js/utils/CommonViewFunction.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enums', 'moment', 'utils/Globals'], function(require, Utils, Modal, Messages, Enums, moment, Globals) { +define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, Utils, Modal, Messages, Enums, moment, Globals) { 'use strict'; var CommonViewFunction = {}; @@ -387,10 +387,14 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum function objToString(filterObj, type) { var generatedQuery = _.map(filterObj.rules, function(obj, key) { + var obj = $.extend(true, {}, obj); // not to update the timezone abbr on original obj , copy of obj is used if (_.has(obj, 'condition')) { return '<span class="operator">' + obj.condition + '</span>' + '(' + objToString(obj).join("") + ')'; } else { if (isCapsuleView) { + if (obj.type === "date") { + obj.value = obj.value + " (" + moment.tz(moment.tz.guess()).zoneAbbr() + ")"; + } return '<div class="capsuleView"><span class="key">' + (Enums.systemAttributes[obj.id] ? Enums.systemAttributes[obj.id] : _.escape(obj.id)) + '</span><span class="operator">' + _.escape(obj.operator) + '</span><span class="value">' + (Enums[obj.id] ? Enums[obj.id][obj.value] : _.escape(obj.value)) + "</span><div class='fa fa-close clear-attr' data-type=" + type + " data-id=" + _.escape(obj.id) + "></div></div>"; } return '<span class="key">' + (Enums.systemAttributes[obj.id] ? Enums.systemAttributes[obj.id] : _.escape(obj.id)) + '</span><span class="operator">' + _.escape(obj.operator) + '</span><span class="value">' + (Enums[obj.id] ? Enums[obj.id][obj.value] : _.escape(obj.value)) + "</span>"; @@ -507,6 +511,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum if (Globals[value[skey].typeName]) { attributeDefs = Globals[value[skey].typeName].attributeDefs; } + if (Globals._ALL_CLASSIFICATION_TYPES && Globals._ALL_CLASSIFICATION_TYPES.attributeDefs) { + attributeDefs = attributeDefs.concat(Globals._ALL_CLASSIFICATION_TYPES.attributeDefs); + } } val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); } else if (k == "entityFilters") { @@ -523,6 +530,9 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum if (Globals[value[skey].typeName]) { attributeDefs = Globals[value[skey].typeName].attributeDefs; } + if (Globals._ALL_ENTITY_TYPES && Globals._ALL_ENTITY_TYPES.attributeDefs) { + attributeDefs = attributeDefs.concat(Globals._ALL_ENTITY_TYPES.attributeDefs); + } } val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); } else if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) { @@ -564,7 +574,18 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum var type = (obj.type || obj.attributeType), //obj.value will come as an object when selected type is Date and operator is isNull or not_null; value = ((_.isString(obj.value) && _.contains(["is_null", "not_null"], obj.operator) && type === 'date') || _.isObject(obj.value) ? "" : _.trim(obj.value || obj.attributeValue)), - url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), (type === 'date' && formatedDateToLong && value.length ? Date.parse(value) : value)]; + url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), value]; + if (obj.operator === "TIME_RANGE") { + if (value.indexOf("-") > -1) { + url[2] = value.split('-').map(function(udKey) { + return Date.parse(udKey.trim()).toString() + }).join(",") + } else { + url[2] = Enums.queryBuilderDateRangeUIValueToAPI[_.trim(value)] || value; + } + } else if (value.length && type === 'date' && formatedDateToLong) { + url[2] = Date.parse(value); + } if (type) { url.push(type); } @@ -581,30 +602,8 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum } function mapApiOperatorToUI(oper) { - if (oper == "eq") { - return "="; - } else if (oper == "neq") { - return "!="; - } else if (oper == "lt") { - return "<"; - } else if (oper == "lte") { - return "<="; - } else if (oper == "gt") { - return ">"; - } else if (oper == "gte") { - return ">="; - } else if (oper == "startsWith") { - return "begins_with"; - } else if (oper == "endsWith") { - return "ends_with"; - } else if (oper == "contains") { - return "contains"; - } else if (oper == "notNull") { - return "not_null"; - } else if (oper == "isNull") { - return "is_null"; - } - return oper; + // Enum will be in effect once we click on save search. + return Enums.queryBuilderApiOperatorToUI[oper] || oper; } }, extractUrl: function(options) { @@ -614,30 +613,7 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum spliter = 1, apiObj = options.apiObj, mapUiOperatorToAPI = function(oper) { - if (oper == "=") { - return "eq"; - } else if (oper == "!=") { - return "neq"; - } else if (oper == "<") { - return "lt"; - } else if (oper == "<=") { - return "lte"; - } else if (oper == ">") { - return "gt"; - } else if (oper == ">=") { - return "gte"; - } else if (oper == "begins_with") { - return "startsWith"; - } else if (oper == "ends_with") { - return "endsWith"; - } else if (oper == "contains") { - return "contains"; - } else if (oper == "not_null") { - return "notNull"; - } else if (oper == "is_null") { - return "isNull"; - } - return oper; + return Enums.queryBuilderUIOperatorToAPI[oper] || oper; }, createObject = function(urlObj) { var finalObj = {}; @@ -662,7 +638,17 @@ define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enum if (temp[3]) { rule['type'] = temp[3]; } - rule.value = rule.type === 'date' && formatDate && rule.value.length ? moment(parseInt(rule.value)).format(Globals.dateTimeFormat) : rule.value; + if (rule.operator === "TIME_RANGE") { + if (temp[2].indexOf(",") > -1) { + rule.value = temp[2].split(",").map(function(udKey) { + return moment(parseInt(udKey.trim())).format(Globals.dateTimeFormat) + }).join(" - ") + } else { + rule.value = Enums.queryBuilderDateRangeAPIValueToUI[_.trim(rule.value)] || rule.value; + } + } else if (rule.type === 'date' && formatDate && rule.value.length) { + rule.value = moment(parseInt(rule.value)).format(Globals.dateTimeFormat) + } } return rule; } diff --git a/dashboardv3/public/js/utils/Enums.js b/dashboardv3/public/js/utils/Enums.js index 24ec36b..131a08f 100644 --- a/dashboardv3/public/js/utils/Enums.js +++ b/dashboardv3/public/js/utils/Enums.js @@ -16,7 +16,7 @@ * limitations under the License. */ -define(['require'], function(require) { +define(["require", "backbone"], function(require) { 'use strict'; var Enums = {}; @@ -219,5 +219,40 @@ define(['require'], function(require) { 0: "false", 1: "true" }; + + Enums.queryBuilderUIOperatorToAPI = { + "=": "eq", + "!=": "neq", + "<": "lt", + "<=": "lte", + ">": "gt", + ">=": "gte", + "begins_with": "startsWith", + "ends_with": "endsWith", + "not_null": "notNull", + "is_null": "isNull", + "TIME_RANGE": "timerange" + }; + + Enums.queryBuilderApiOperatorToUI = _.invert(Enums.queryBuilderUIOperatorToAPI); + + Enums.queryBuilderDateRangeUIValueToAPI = { + "Today": "TODAY", + "Yesterday": "YESTERDAY", + "Last 7 Days": "LAST_7_DAYS", + "Last 30 Days": "LAST_30_DAYS", + "This Month": "THIS_MONTH", + "Last Month": "LAST_MONTH", + "This Quarter": "THIS_QUARTER", + "Last Quarter":"LAST_QUARTER", + "This Year": "THIS_YEAR", + "Last Year": "LAST_YEAR", + "Last 3 Months": "LAST_3_MONTHS", + "Last 6 Months": "LAST_6_MONTHS", + "Last 12 Months": "LAST_12_MONTHS" + }; + + Enums.queryBuilderDateRangeAPIValueToUI = _.invert(Enums.queryBuilderDateRangeUIValueToAPI); + return Enums; }); \ No newline at end of file diff --git a/dashboardv3/public/js/views/search/QueryBuilderView.js b/dashboardv3/public/js/views/search/QueryBuilderView.js index dc36ffe..06ecd01 100644 --- a/dashboardv3/public/js/views/search/QueryBuilderView.js +++ b/dashboardv3/public/js/views/search/QueryBuilderView.js @@ -24,9 +24,10 @@ define(['require', 'utils/CommonViewFunction', 'utils/Enums', 'utils/Globals', + 'moment', 'query-builder', 'daterangepicker' -], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums, Globals) { +], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums, Globals, moment) { var QueryBuilderView = Backbone.Marionette.LayoutView.extend( /** @lends QueryBuilderView */ @@ -58,6 +59,22 @@ define(['require', _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'businessMetadataDefCollection', 'tag', 'type', 'searchTableFilters', 'systemAttrArr', 'adminAttrFilters')); this.attrObj = _.sortBy(this.attrObj, 'name'); this.filterType = this.tag ? 'tagFilters' : 'entityFilters'; + this.defaultRange = "Last 7 Days"; + this.dateRangesMap = { + 'Today': [moment(), moment()], + 'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], + 'Last 7 Days': [moment().subtract(6, 'days'), moment()], + 'Last 30 Days': [moment().subtract(29, 'days'), moment()], + 'This Month': [moment().startOf('month'), moment().endOf('month')], + 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 3 Months': [moment().subtract(3, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 6 Months': [moment().subtract(6, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'Last 12 Months': [moment().subtract(12, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], + 'This Quarter': [moment().startOf('quarter'), moment().endOf('quarter')], + 'Last Quarter': [moment().subtract(1, 'quarter').startOf('quarter'), moment().subtract(1, 'quarter').endOf('quarter')], + 'This Year': [moment().startOf('year'), moment().endOf('year')], + 'Last Year': [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')] + } }, bindEvents: function() {}, getOperator: function(type, skipDefault) { @@ -71,7 +88,7 @@ define(['require', } } if (type === "date") { - obj.operators = ['>', '<']; + obj.operators = ['=', '!=', '>', '<', '>=', '<=', 'TIME_RANGE']; } if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double") { obj.operators = ['=', '!=', '>', '<', '>=', '<=']; @@ -266,20 +283,7 @@ define(['require', } if (obj.type === "date") { obj['plugin'] = 'daterangepicker'; - obj['plugin_config'] = { - "singleDatePicker": true, - "showDropdowns": true, - "timePicker": true, - locale: { - format: Globals.dateTimeFormat - } - }; - if (rules) { - var valueObj = _.find(rules, { id: obj.id }); - if (valueObj) { - obj.plugin_config["startDate"] = valueObj.value; - } - } + obj['plugin_config'] = this.getDateConfig(rules, obj.id); _.extend(obj, this.getOperator(obj.type)); return obj; } @@ -316,6 +320,86 @@ define(['require', return obj; } }, + getDateConfig: function(ruleObj, id, operator) { + var valueObj = ruleObj ? (_.find(ruleObj.rules, { id: id }) || {}) : {}, + isTimeRange = (valueObj.operator && valueObj.operator === "TIME_RANGE" && operator === "TIME_RANGE") || (operator === "TIME_RANGE"), + obj = { + opens: "center", + autoApply: true, + autoUpdateInput: false, + timePickerSeconds: true, + timePicker: true, + locale: { + format: Globals.dateTimeFormat + } + }; + + if (isTimeRange) { + var defaultRangeDate = this.dateRangesMap[this.defaultRange]; + obj.startDate = defaultRangeDate[0]; + obj.endDate = defaultRangeDate[1]; + obj.singleDatePicker = false; + obj.ranges = this.dateRangesMap; + } else { + obj.singleDatePicker = true; + obj.startDate = moment(); + obj.endDate = obj.startDate; + } + + if (!_.isEmpty(valueObj) && operator === valueObj.operator) { + if (isTimeRange) { + if (valueObj.value.indexOf("-") > -1) { + var dates = valueObj.value.split("-"); + obj.startDate = dates[0].trim(); + obj.endDate = dates[1].trim(); + } else { + var dates = this.dateRangesMap[valueObj.value] + obj.startDate = dates[0]; + obj.endDate = dates[1]; + } + obj.singleDatePicker = false; + } else { + obj.startDate = moment(valueObj.value); + obj.endDate = moment(valueObj.value); + obj.singleDatePicker = true; + } + } + + return obj; + }, + setDateValue: function(rule, rules_widgets) { + if (rule.filter.type === "date" && rule.operator.nb_inputs) { + var inputEl = rule.$el.find(".rule-value-container").find("input"), + datepickerEl = rule.$el.find(".rule-value-container").find("input").data("daterangepicker") + inputEl.attr('readonly', true); + if (datepickerEl) { + datepickerEl.remove(); + var configObj = this.getDateConfig(rules_widgets, rule.filter.id, rule.operator.type) + inputEl.daterangepicker(configObj); + if (rule.operator.type === "TIME_RANGE") { + rule.value = this.defaultRange; + } else { + rule.value = configObj.startDate.format(Globals.dateTimeFormat); + } + inputEl.on('apply.daterangepicker', function(ev, picker) { + picker.setStartDate(picker.startDate); + picker.setEndDate(picker.endDate); + var valueString = ""; + if (picker.chosenLabel) { + if (picker.chosenLabel === "Custom Range") { + valueString = picker.startDate.format(Globals.dateTimeFormat) + " - " + picker.endDate.format(Globals.dateTimeFormat); + } else { + valueString = picker.chosenLabel; + } + } else { + valueString = picker.startDate.format(Globals.dateTimeFormat); + } + picker.element.val(valueString); + rule.value = valueString; + }); + } + } + }, onRender: function() { var that = this, filters = [], @@ -339,7 +423,7 @@ define(['require', rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters ? this.searchTableFilters["adminAttrFilters"] : null, "formatDate": true });; } else { if (this.value) { - var rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true }); + rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true }); } _.each(this.attrObj, function(obj) { var type = that.tag ? that.value.tag : that.value.type; @@ -415,16 +499,20 @@ define(['require', } filters = _.uniq(filters, 'id'); if (filters && !_.isEmpty(filters)) { - this.ui.builder.queryBuilder({ - plugins: ['bt-tooltip-errors'], - filters: filters, - select_placeholder: placeHolder, - allow_empty: true, - conditions: ['AND', 'OR'], - allow_groups: true, - allow_empty: true, - templates: { - rule: '<div id="{{= it.rule_id }}" class="rule-container"> \ + this.ui.builder.off() + .on("afterUpdateRuleOperator.queryBuilder", function(e, rule) { + that.setDateValue(rule, rules_widgets); + }) + .queryBuilder({ + plugins: ['bt-tooltip-errors'], + filters: filters, + select_placeholder: placeHolder, + allow_empty: true, + conditions: ['AND', 'OR'], + allow_groups: true, + allow_empty: true, + templates: { + rule: '<div id="{{= it.rule_id }}" class="rule-container"> \ <div class="values-box"><div class="rule-filter-container"></div> \ <div class="rule-operator-container"></div> \ <div class="rule-value-container"></div></div> \ @@ -439,50 +527,58 @@ define(['require', <div class="error-container"><i class="{{= it.icons.error }}"></i> <span></span></div> \ {{?}} \ </div>' - }, - operators: [ - { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'like', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'in', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] } - ], - lang: { - add_rule: 'Add filter', - add_group: 'Add filter group', - operators: { - not_null: 'is not null' + }, + operators: [ + { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, + { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'like', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'in', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, + { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, + { type: 'TIME_RANGE', nb_inputs: 1, multiple: false, apply_to: ['date'] } + ], + lang: { + add_rule: 'Add filter', + add_group: 'Add filter group', + operators: { + not_null: 'is not null', + TIME_RANGE: "Time Range" + } + }, + icons: { + add_rule: 'fa fa-plus', + remove_rule: 'fa fa-times', + error: 'fa fa-exclamation-triangle' + }, + rules: rules_widgets + }) + .on("afterCreateRuleInput.queryBuilder", function(e, rule) { + rule.error = null; + if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") { + rule.$el.addClass("user-define"); + } else if (rule.$el.hasClass("user-define")) { + rule.$el.removeClass("user-define"); } - }, - icons: { - add_rule: 'fa fa-plus', - remove_rule: 'fa fa-times', - error: 'fa fa-exclamation-triangle' - }, - rules: rules_widgets - }).on("afterCreateRuleInput.queryBuilder", function(e, rule) { - rule.error = null; - if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") { - rule.$el.addClass("user-define"); - } else if (rule.$el.hasClass("user-define")) { - rule.$el.removeClass("user-define"); - } - }).on('validationError.queryBuilder', function(e, rule, error, value) { - // never display error for my custom filter - var errorMsg = error[0]; - if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) { - errorMsg = that.queryBuilderLang.errors[errorMsg]; - } - rule.$el.find(".error-container span").html(errorMsg); - }); + if (rule.filter.type === "date") { + rule.$el.find('.rule-value-container >input').attr('readonly', true); + } + that.setDateValue(rule, rules_widgets); + }) + .on('validationError.queryBuilder', function(e, rule, error, value) { + // never display error for my custom filter + var errorMsg = error[0]; + if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) { + errorMsg = that.queryBuilderLang.errors[errorMsg]; + } + rule.$el.find(".error-container span").html(errorMsg); + }); var queryBuilderEl = that.ui.builder.data("queryBuilder"); if (queryBuilderEl && queryBuilderEl.lang) { this.queryBuilderLang = queryBuilderEl.lang; diff --git a/dashboardv3/public/js/views/search/tree/EntityTreeLayoutView.js b/dashboardv3/public/js/views/search/tree/EntityTreeLayoutView.js index f2111ca..a859ea0 100644 --- a/dashboardv3/public/js/views/search/tree/EntityTreeLayoutView.js +++ b/dashboardv3/public/js/views/search/tree/EntityTreeLayoutView.js @@ -242,7 +242,8 @@ define([ params["entityFilters"] = null; } } - + var getUrl = Utils.getUrlState.isSearchTab(); + if (!getUrl) { that.typeId = null; } if (that.typeId != selectedNodeId) { that.typeId = selectedNodeId; typeValue = name;