From 7432c2c7dcc14a84779d4508299e9857c235edc4 Mon Sep 17 00:00:00 2001 From: "S.Listl" <S.Listl@SLISTL.aditosoftware.local> Date: Tue, 7 Apr 2020 13:58:49 +0200 Subject: [PATCH] JditoFilter_lib and Date_lib improvements --- process/Date_lib/process.js | 166 ++++++++++++++++++++++++++++- process/JditoFilter_lib/process.js | 58 ++++++---- 2 files changed, 203 insertions(+), 21 deletions(-) diff --git a/process/Date_lib/process.js b/process/Date_lib/process.js index 18a7b2b188..9b6a804039 100644 --- a/process/Date_lib/process.js +++ b/process/Date_lib/process.js @@ -163,4 +163,168 @@ DateUtils.validateNotInFuture = function (pDate) DateUtils.getCurrentYear = function () { return parseInt(datetime.toDate(vars.get("$sys.date"), "yyyy")); -} \ No newline at end of file +} + + +/** + * Object for handling durations. It consists of years, months, days and milliseconds. Because hours, minutes and seconds have fixed lengths, these + * are all added to the milliseconds part, but years and months can have different amounts of days, so they are stored separately. + * + * @param {Number} [pYears=0] years + * @param {Number} [pMonths=0] months + * @param {Number} [pDays=0] days + * @param {Number} [pMillis=0] milliseconds + */ +function Duration (pYears, pMonths, pDays, pMillis) +{ + this.years = pYears !== undefined ? Number(pYears) : 0; + this.months = pMonths !== undefined ? Number(pMonths) : 0; + //because of daylight saving time, a day is not always 24h + this.days = pDays !== undefined ? Number(pDays) : 0; + this.milliseconds = pMillis !== undefined ? Number(pMillis) : 0; +} + +/** + * creates a new Duration object, this function can also take hours, minutes and seconds (they are automatically converted to milliseconds) + * + * @param {Number} [pYears=0] years + * @param {Number} [pMonths=0] months + * @param {Number} [pDays=0] days + * @param {Number} [pHours=0] hours + * @param {Number} [pMinutes=0] minutes + * @param {Number} [pSeconds=0] seconds + * @return {Duration} a new Duration object + */ +Duration.of = function (pYears, pMonths, pDays, pHours, pMinutes, pSeconds) +{ + if (pHours == undefined) + pHours = 0; + if (pMinutes == undefined) + pMinutes = 0; + if (pSeconds == undefined) + pSeconds = 0; + + pMinutes += pHours * 60; + pSeconds += pMinutes * 60; + + return new Duration(pYears, pMonths, pDays, pSeconds * 1000); +} + +/** + * creates a new Duration object only with hours, minutes and seconds + * + * @param {Number} [pHours=0] hours + * @param {Number} [pMinutes=0] minutes + * @param {Number} [pSeconds=0] seconds + * @return {Duration} a new Duration object + */ +Duration.ofTime = function (pHours, pMinutes, pSeconds) +{ + return Duration.of(undefined, undefined, undefined, pHours, pMinutes, pSeconds); +} + +/** + * parses a ISO-8601 duration string into a Duration object + * + * @param {String} pIso8601Duration string representation of the duration + * @return {Duration} new duration object + */ +Duration.parse = function (pIso8601Duration) +{ + var iso8601DurationRegex = /([-+]?)P(?:([-+]?[0-9]+)Y)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)W)?(?:([-+]?[0-9]+)D)?(?:T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+(?:[.,][0-9]{0,9})?)S)?)?/; + var matches = pIso8601Duration.match(iso8601DurationRegex); + + var sign = matches[1] === "-" ? -1 : 1; + + var years = matches[2] === undefined ? 0 : _toNumberCommaSafe(matches[2]) * sign; + var months = matches[3] === undefined ? 0 : _toNumberCommaSafe(matches[3]) * sign; + var weeks = matches[4] === undefined ? 0 : _toNumberCommaSafe(matches[4]) * sign; + var days = matches[5] === undefined ? 0 : _toNumberCommaSafe(matches[5]) * sign; + if (weeks > 0) + days += weeks * 7; + + var hours = matches[6] === undefined ? 0 : _toNumberCommaSafe(matches[6]) * sign; + var minutes = matches[7] === undefined ? 0 : _toNumberCommaSafe(matches[7]) * sign; + var seconds = matches[8] === undefined ? 0 : _toNumberCommaSafe(matches[8]) * sign; + + return Duration.of(years, months, days, hours, minutes, seconds); + + //converts a string to a number, accepting a comma as decimal separator (for example, Number("2,3") would normally return NaN) + function _toNumberCommaSafe (pNumberString) + { + return Number(pNumberString.replace(",", ".")); + } +} + +/** + * makes a ISO-8601 string representing the duration + * + * @return {String} the duration as string + */ +Duration.prototype.getIso8601Representation = function () +{ + var iso8601Duration = "P" + + (this.years ? this.years + "Y" : "") + + (this.months ? this.months + "M" : "") + + (this.days ? this.days + "D" : ""); + + if (this.milliseconds) + { + var millis = this.milliseconds; + var seconds = Math.floor(millis / 1000); + millis = millis % 1000; + var minutes = Math.floor(seconds / 60); + seconds = seconds % 60; + var hours = Math.floor(minutes / 60); + minutes = minutes % 60; + + iso8601Duration += "T" + + (hours ? hours + "H" : "") + + (minutes ? minutes + "M" : "") + + (seconds ? seconds + (millis ? "." + millis : "") + "S" : ""); + } + + //there must always be at least one element + if (iso8601Duration === "P") + iso8601Duration += "0D"; + + return iso8601Duration; +} + +/** + * inverts the direction of the duration + * + * @return {Duration} current object + */ +Duration.prototype.invert = function () +{ + this.years = -this.years; + this.months = -this.months; + this.days = -this.days; + this.milliseconds = -this.milliseconds; + + return this; +} + +/** + * Adds the duration to the given Date object (note that the duration can also be negative). This will alter the given object. + * + * @param {Date} pDate date to change, any value that is not of type "Date" will be converted to a Date + * @return {Date} the Date object + */ +Duration.prototype.addToDate = function (pDate) +{ + if (!(pDate instanceof Date)) + pDate = new Date(pDate); + + if (this.years !== 0) + pDate.setFullYear(pDate.getFullYear() + this.years); + if (this.months !== 0) + pDate.setMonth(pDate.getMonth() + this.months); + if (this.days !== 0) + pDate.setDate(pDate.getDate() + this.days); + if (this.milliseconds !== 0) + pDate.setTime(pDate.getTime() + this.milliseconds); + + return pDate; +} diff --git a/process/JditoFilter_lib/process.js b/process/JditoFilter_lib/process.js index e00af4d021..9e6137b3eb 100644 --- a/process/JditoFilter_lib/process.js +++ b/process/JditoFilter_lib/process.js @@ -2,10 +2,6 @@ import("system.tools"); import("system.logging"); import("Sql_lib"); -//private scope to make only JditoFilterUtils public -var JditoFilterUtils = (function () -{ - /** * object for filtering records * @@ -16,7 +12,7 @@ var JditoFilterUtils = (function () * * @private */ -function JditoFilterHelper (pColumns, pFilter, pCustomCheckFns, pCheckFnThisArg) +function JditoFilter (pColumns, pFilter, pCustomCheckFns, pCheckFnThisArg) { var columnMap = {}; for (let i = 0, l = pColumns.length; i < l; i++) @@ -25,12 +21,30 @@ function JditoFilterHelper (pColumns, pFilter, pCustomCheckFns, pCheckFnThisArg) if (col) columnMap[col] = { index : i, - checkFn : pCustomCheckFns[col]//or nothing when there is no custom function + checkFn : (pCustomCheckFns ? pCustomCheckFns[col] : null) }; } this.columnMap = columnMap; + + if (pFilter && pFilter.childs.length !== 0) + _removeEmptyGroups(pFilter.childs); + this.filter = pFilter; this.checkFnThisArg = pCheckFnThisArg || null; + + function _removeEmptyGroups (pCurrentArray) + { + for (let i = 0; i < pCurrentArray.length; i++) + { + let row = pCurrentArray[i]; + if (row.type == "group") + { + _removeEmptyGroups(row.childs); + if (row.childs.length === 0) + pCurrentArray.splice(i--, 1); + } + } + } } /** @@ -40,9 +54,9 @@ function JditoFilterHelper (pColumns, pFilter, pCustomCheckFns, pCheckFnThisArg) * * @return {boolean} true, if it matches the condition */ -JditoFilterHelper.prototype.checkRecord = function (pRow) +JditoFilter.prototype.checkRecord = function (pRow) { - if (this.filter.length == 0) + if (!this.filter || this.filter.childs.length === 0) return true; var regexFlags = JditoFilterUtils.isUserIgnoreCase() ? "i" : undefined; @@ -100,11 +114,17 @@ JditoFilterHelper.prototype.checkRecord = function (pRow) return pRowValue == ""; case "ISNOTNULL": return pRowValue != ""; + case "TIMEFRAME_EQUAL": + case "TIMEFRAME_COMING": + case "TIMEFRAME_PAST": } } } - +JditoFilter.prototype.filterRecords = function (pRecords) +{ + return pRecords.filter(this.checkRecord, this); +} /** * Provides functions for using the filter with jdito recordcontainers @@ -154,12 +174,7 @@ JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter, pCustomC if (!pFilter) return pRecords; - var filter = new JditoFilterHelper(pColumns, pFilter, pCustomCheckFns || {}, pCheckFnThisArg); - - return pRecords.filter(function (row) - { - return this.checkRecord(row); - }, filter); + return new JditoFilter(pColumns, pFilter, pCustomCheckFns, pCheckFnThisArg).filterRecords(pRecords); } /** @@ -178,7 +193,8 @@ JditoFilterUtils.filterRecords = function (pColumns, pRecords, pFilter, pCustomC * var cond = new SqlBuilder(); * ... * return cond; - * } + * }, + * FIELD4 : null //if you set the value here to null of false, the field will be ignored and not added to the condition * } * * @example @@ -215,7 +231,13 @@ JditoFilterUtils.getSqlCondition = function (pFilter, pTable, pTableAlias, pColu if (pFilter.type == "row") { if (pFilter.name in pColumnOrFnMap) + { pFilter.name = pColumnOrFnMap[pFilter.name]; + + //possibility to explicitly set the value to null/false so that the field is ignored + if (pFilter.name === null || pFilter.name === false) + return; + } else if (pTable && pTableAlias) pFilter.name = [pTable, pFilter.name, pTableAlias]; else if (pTable) @@ -302,7 +324,3 @@ JditoFilterUtils.isUserIgnoreCase = function () var ignoreCase = user ? user[tools.PARAMS][tools.SELECTION_IGNORECASE] : ""; return ignoreCase == "" || /true/i.test(ignoreCase); } - - return JditoFilterUtils; //return only functions that should be public - -})(); -- GitLab