UNPKG

novo-elements

Version:

1,239 lines (1,224 loc) 46.9 kB
import * as i0 from '@angular/core'; import { Injector, Injectable, EventEmitter, LOCALE_ID, Optional, Inject } from '@angular/core'; import { Helpers, DateUtil, convertTokens } from 'novo-elements/utils'; import { parse, format } from 'date-fns'; import { MaskedEnum, MaskedRange } from 'imask'; // NG2 class ComponentUtils { append(ComponentClass, location, providers, onTop) { const parent = location.injector; const index = onTop ? 0 : location.length; const injector = Injector.create({ providers, parent }); return location.createComponent(ComponentClass, { index, injector, }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ComponentUtils, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ComponentUtils }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: ComponentUtils, decorators: [{ type: Injectable }] }); class CollectionEvent { static { this.REFRESH = 'Collection.REFRESH'; } static { this.ADD = 'Collection.ADD'; } static { this.REMOVE = 'Collection.REMOVE'; } static { this.REMOVE_ALL = 'Collection.REMOVE_ALL'; } static { this.REPLACE = 'Collection.REPLACE'; } static { this.INVALIDATE_ALL = 'Collection.INVALIDATE_ALL'; } static { this.SORT = 'Collection.SORT'; } static { this.FILTER = 'Collection.FILTER'; } static { this.CHANGE = 'Collection.CHANGE'; } static { this.CURRENTPAGE_CHANGE = 'Collection.CURRENTPAGE_CHANGE'; } static { this.PAGESIZE_CHANGE = 'Collection.PAGESIZE_CHANGE'; } static { this.NUMBEROFPAGES_CHANGE = 'Collection.NUMBEROFPAGES_CHANGE'; } constructor(type = 'Collection.REFRESH', data = []) { this.type = ''; this.data = []; this.type = type; this.data = data; } } // Ng /** * Base Class for all Collection based data providers * * @example * var dp:DataProvider = new DataProvider(); * dp.addItem({label:"Item 1"}); * dp.addItem({label:"Item 2"}); * dp.addItem({label:"Item 3"}); * dp.addItem({label:"Item 4"}); * var myList:List = new List(); * myList.dataProvider = dp; */ class ArrayCollection { constructor(source = []) { this.dataChange = new EventEmitter(); this.source = []; this.editData = []; this.isEditing = false; this.filterData = []; this._filter = {}; this._sort = []; this.source = source; this.editData = this.copy(this.source); this.filterData = this.source.slice(); } get length() { return this.filterData.length; } get total() { return this.filterData.length; } get list() { return this.filterData; } isEmpty() { return this.length <= 0 && !this.isLoading() && !this.hasErrors(); } hasErrors() { return false; } isLoading() { return false; } isFiltered() { return Object.keys(this._filter).length > 0; } /** * Method to switch the isEditingflag for the data source */ edit() { this.isEditing = true; this.editData = this.copy(this.source); } /** * Method to leave edit mode and reset source */ undo() { this.isEditing = false; this.source = this.copy(this.editData); this.refresh(); } /** * Method to leave edit mode and save editData */ commit() { this.isEditing = false; this.source = this.filterData.slice(); this.refresh(); } /** * Appends an item to the end of the data provider. * * * @memberOf ArrayCollection */ addItem(item) { this.isEditing ? this.editData.push(item) : this.source.push(item); this.onDataChange(new CollectionEvent(CollectionEvent.ADD, [item])); this.refresh(); } /** * Adds a new item to the data provider at the specified index. * * * @memberOf ArrayCollection */ addItemAt(item, index) { this.isEditing ? this.editData.splice(index, 0, item) : this.source.splice(index, 0, item); this.onDataChange(new CollectionEvent(CollectionEvent.ADD, [item])); this.refresh(); } /** * Appends multiple items to the end of the DataProvider and dispatches a CollectionEvent.ADD event. * * @memberOf ArrayCollection */ addItems(items) { this.isEditing ? this.editData.push(...items) : this.source.push(...items); this.onDataChange(new CollectionEvent(CollectionEvent.ADD, items)); this.refresh(); } /** * Adds several items to the data provider at the specified index and dispatches a CollectionEvent.ADD event. * * @memberOf ArrayCollection */ addItemsAt(items, index) { this.isEditing ? this.editData.splice(index, 0, ...items) : this.source.splice(index, 0, ...items); } /** * Creates a copy of the current ArrayCollection any. * * @memberOf ArrayCollection */ clone() { return new ArrayCollection(this.isEditing ? this.copy(this.editData) : this.copy(this.source)); } /** * Creates a copy of the current ArrayCollection any. * * @memberOf ArrayCollection */ copy(array) { return Helpers.deepClone(array); } /** * Concatenates the specified items to the end of the current data provider. * * @memberOf ArrayCollection */ concat(items) { this.addItems(items); } /** * Returns the item at the specified index. * * @memberOf ArrayCollection */ getItemAt(index) { return this.isEditing ? this.editData[index] : this.source[index]; } /** * Returns the index of the specified item. * * @memberOf ArrayCollection */ getItemIndex(item) { return this.isEditing ? this.editData.indexOf(item) : this.source.indexOf(item); } /** * Invalidates all the data items that the DataProvider contains and dispatches a CollectionEvent.INVALIDATE_ALL event. * * @memberOf ArrayCollection */ invalidate() { this.onDataChange(new CollectionEvent(CollectionEvent.INVALIDATE_ALL)); } /** * Appends the specified data into the data that the data provider contains and removes any duplicate items. * * @memberOf ArrayCollection */ merge(newData) { for (const obj of newData) { const existing = ~this.getItemIndex(obj); if (existing) { this.replaceItem(obj, existing); } else { this.addItem(obj); } } } /** * Removes all items from the data provider and dispatches a CollectionEvent.REMOVE_ALL event. * * @memberOf ArrayCollection */ removeAll() { this.source = []; this.editData = []; this.filterData = []; this.onDataChange(new CollectionEvent(CollectionEvent.REMOVE_ALL, [])); this.refresh(); } /** * Removes the specified item from the data provider and dispatches a CollectionEvent.REMOVE event. * * @memberOf ArrayCollection */ removeItem(item) { const index = this.getItemIndex(item); return this.removeItemAt(index); } /** * Removes the item at the specified index and dispatches a CollectionEvent.REMOVE event. * * @memberOf ArrayCollection */ removeItemAt(index) { const success = !!this.source.splice(index, 1); this.refresh(); return success; } /** * Replaces an existing item with a new item and dispatches a CollectionEvent.REPLACE event. * * @memberOf ArrayCollection */ replaceItem(newItem, oldItem) { const index = this.getItemIndex(oldItem); if (index >= 0) { this.replaceItemAt(newItem, index); } } /** * Replaces the item at the specified index and dispatches a CollectionEvent.REPLACE event. * * @memberOf ArrayCollection */ replaceItemAt(newItem, index) { this.filterData.splice(index, 1, newItem); } /** * Sorts the items that the data provider contains and dispatches a CollectionEvent.SORT event. * * @memberOf ArrayCollection */ get sort() { return this._sort; } set sort(value) { this._sort = value; this.refresh(); } /** * Sorts the items that the data provider contains by the specified field and dispatches a CollectionEvent.SORT event. * * @memberOf ArrayCollection */ sortOn(fieldName, reverse = false) { this.filterData = this.filterData.sort(Helpers.sortByField(fieldName, reverse)); this.onDataChange(new CollectionEvent(CollectionEvent.SORT)); return this.filterData; } get filter() { return this._filter; } set filter(value) { this._filter = value; this.refresh(); } filterOn(fieldName, value = null) { this.filterData = this.filterData.filter(Helpers.filterByField(fieldName, value)); return this.filterData; } onDataChange(event) { this.dataChange.emit(event); } refresh() { this.filterData = this.isEditing ? this.editData.slice() : this.source.slice(); for (const item of this._sort.reverse()) { this.sortOn(item.field, item.reverse); } for (const key in this._filter) { if (key) { this.filterOn(key, this._filter[key]); } } this.onDataChange(new CollectionEvent(CollectionEvent.CHANGE, this.filterData)); } /** * Creates an Array any representation of the data that the data provider contains. * * @memberOf ArrayCollection */ toArray() { return this.isEditing ? this.editData : this.source; } toJSON() { return this.isEditing ? this.editData : this.source; } } class PagedArrayCollection extends ArrayCollection { constructor(source = []) { super(source); this._page = 1; this._numberOfPages = 1; this._pageSize = 10; } get numberOfPages() { let result = this.source.length / this.pageSize; result = Math.ceil(result); return result; } get page() { return this._page; } set page(value) { this._page = value; this.refresh(); } get pageSize() { return this._pageSize; } set pageSize(value) { this._pageSize = value; this.refresh(); } next() { if (this.page === this.numberOfPages) { return this.page; } this.page++; return this.page; } prev() { if (this._page === 1) { return this.page; } this.page--; return this.page; } first() { if (this.page === 1) { return this.page; } this.page = 1; return this.page; } last() { if (this.page === this.numberOfPages) { return this.page; } this.page = this.numberOfPages; return this.page; } refresh() { this.filterData = this.isEditing ? this.editData.slice() : this.source.slice(); for (const item of this._sort.reverse()) { this.sortOn(item.field, item.reverse); } for (const key in this._filter) { if (key) { this.filterOn(key, this._filter[key]); } } if (this.page >= 0) { const start = (this.page - 1) * this.pageSize; const end = start + this.pageSize; const result = this.filterData.slice(start, end); this.onDataChange(new CollectionEvent(CollectionEvent.CHANGE, result)); } else { this.onDataChange(new CollectionEvent(CollectionEvent.CHANGE, this.filterData)); } } } // NG2 class NovoLabelService { constructor(userLocale = 'en-US') { this.userLocale = userLocale; this.and = 'and'; this.not = 'not'; this.filters = 'Filter'; this.filterss = 'Filters'; this.clear = 'Clear'; this.sort = 'Sort'; this.distributionListOwner = 'Owner'; this.dateAdded = 'Date Added'; this.emptyTableMessage = 'No Records to display...'; this.noMatchingRecordsMessage = 'No Matching Records'; this.noMoreRecordsMessage = 'No More Records'; this.erroredTableMessage = 'Oops! An error occurred.'; this.pickerError = 'Oops! An error occurred.'; this.pickerTextFieldEmpty = 'Begin typing to see results.'; this.pickerEmpty = 'No results to display...'; this.tabbedGroupPickerEmpty = 'No results found'; this.quickNoteError = 'Oops! An error occurred.'; this.quickNoteEmpty = 'No results to display...'; this.required = 'Required'; this.numberTooLarge = 'Number is too large'; this.apply = 'Apply'; this.save = 'Save'; this.cancel = 'Cancel'; this.next = 'Next'; this.itemsPerPage = 'Items per page:'; this.chooseAField = 'Choose a field...'; this.operator = 'Operator...'; this.select = 'Select...'; this.value = 'Value...'; this.selectDateRange = 'Select Date Range...'; this.typeToAddChips = 'Type and press Enter to add...'; this.selected = 'Selected'; this.selectAllOnPage = 'Select all on page'; this.deselectAll = 'Deselect all'; this.refresh = 'Refresh'; this.close = 'Close'; this.move = 'Move'; this.startDate = 'Start Date'; this.endDate = 'End Date'; this.rate = 'Rate'; this.more = 'more'; this.clearAll = 'CLEAR ALL'; this.clearAllNormalCase = 'Clear All'; this.clearSort = 'Clear Sort'; this.clearFilter = 'Clear Filter'; this.clearSearch = 'Clear Search'; this.clearSelected = 'Clear Selected'; this.today = 'Today'; this.now = 'Now'; this.isRequired = 'is required'; this.notValidYear = 'is not a valid year'; this.isTooLarge = 'is too large'; this.invalidAddress = 'requires at least one field filled out'; this.invalidEmail = 'requires a valid email (ex. abc@123.com)'; this.minLength = 'is required to be a minimum length of'; this.past1Day = 'Past 1 Day'; this.past7Days = 'Past 7 Days'; this.past14Days = 'Past 14 Days'; this.past21Days = 'Past 21 Days'; this.past30Days = 'Past 30 Days'; this.past60Days = 'Past 60 Days'; this.past90Days = 'Past 90 Days'; this.past180Days = 'Past 180 Days'; this.past270Days = 'Past 270 Days'; this.past1Year = 'Past 1 Year'; this.next1Day = 'Next 1 Day'; this.next7Days = 'Next 7 Days'; this.next14Days = 'Next 14 Days'; this.next21Days = 'Next 21 Days'; this.next30Days = 'Next 30 Days'; this.next60Days = 'Next 60 Days'; this.next90Days = 'Next 90 Days'; this.next180Days = 'Next 180 Days'; this.next270Days = 'Next 270 Days'; this.next1Year = 'Next 1 Year'; this.future = 'Future'; this.customDateRange = 'Custom Date Range'; this.backToPresetFilters = 'Back to Preset Filters'; this.okGotIt = 'Ok, Got it'; this.address = 'Address'; this.address1 = 'Address'; this.apt = 'Apt'; // TODO delete this.address2 = 'Apt'; this.city = 'City / Locality'; this.state = 'State / Region'; this.zip = 'Postal Code'; this.zipCode = 'Postal Code'; // TODO delete this.country = 'Country'; this.or = 'or'; this.clickToBrowse = 'click to browse'; this.chooseAFile = 'Choose a file'; this.no = 'No'; this.yes = 'Yes'; this.search = 'SEARCH'; this.noItems = 'There are no items'; this.dateFormat = 'MM/dd/yyyy'; this.dateFormatPlaceholder = 'MM/DD/YYYY'; this.localDatePlaceholder = 'mm/dd/yyyy'; this.timeFormatPlaceholderAM = 'hh:mm AM'; this.timeFormatPlaceholder24Hour = 'HH:mm'; this.timeFormatAM = 'AM'; this.timeFormatPM = 'PM'; this.confirmChangesModalMessage = 'Are you sure you want to change this field?'; this.promptModalMessage = 'Do you want to perform the following changes?'; this.asyncFailure = 'Async validation was not called within the 10s threshold, you might want to reload the page to try again'; this.previous = 'Previous'; this.actions = 'Actions'; this.all = 'All'; this.groupedMultiPickerEmpty = 'No items to display'; this.groupedMultiPickerSelectCategory = 'Select a category from the left to get started'; this.add = 'Add'; this.encryptedFieldTooltip = 'This data has been stored at the highest level of security'; this.noStatesForCountry = 'No states available for the selected country'; this.selectCountryFirst = 'Please select a country before selecting a state'; this.invalidIntegerInput = 'Special characters are not allowed for'; this.maxRecordsReached = 'Sorry, you have reached the maximum number of records allowed for this field'; this.selectFilterOptions = 'Please select one or more filter options below.'; this.addCondition = 'Add Condition'; this.includeAny = 'Include Any'; this.includeAll = 'Include All'; this.exclude = 'Exclude'; this.excludeAny = 'Exclude Any'; this.radius = 'Radius'; this.insideRadius = 'Radius (Inside)'; this.outsideRadius = 'Radius (Outside)'; this.equals = 'Equals'; this.equalTo = 'Equal To'; this.greaterThan = 'Greater Than'; this.lessThan = 'Less Than'; this.doesNotEqual = 'Does Not Equal'; this.beginsWith = 'Begins With'; this.true = 'True'; this.false = 'False'; this.before = 'Before'; this.after = 'After'; this.within = 'Within'; this.isNull = 'Is Empty'; this.isEmpty = 'Is Empty?'; this.between = 'Is Between'; this.refreshPagination = 'Refresh Pagination'; this.location = 'Location'; this.showLess = 'Show Less'; this.miles = 'Miles'; this.km = 'Km'; this.minimumPlaceholder = 'Minimum'; this.maximumPlaceholder = 'Maximum'; this.minGreaterThanMax = 'The minimum is greater than the maximum value'; } maxlengthMetWithField(field, maxlength) { return `Sorry, you have reached the maximum character count of ${maxlength} for ${field}.`; } maxlengthMet(maxlength) { return `Sorry, you have reached the maximum character count of ${maxlength} for this field.`; } invalidMaxlengthWithField(field, maxlength) { return `Sorry, you have exceeded the maximum character count of ${maxlength} for ${field}.`; } invalidMaxlength(maxlength) { return `Sorry, you have exceeded the maximum character count of ${maxlength} for this field.`; } getToManyPlusMore(toMany) { return `+${toMany.quantity} more`; } selectedRecords(selected) { return `${selected} records are selected.`; } showingXofXResults(shown, total) { return `Showing ${shown} of ${total} Results.`; } ofXAmount(amount) { return `of ${amount}`; } totalRecords(total, select = false) { return select ? `Select all ${total} records.` : `De-select remaining ${total} records.`; } dateFormatString() { return this.dateFormat; } localizedDatePlaceholder() { return this.localDatePlaceholder; } tabbedGroupClearSuggestion(tabLabelPlural) { return `Clear your search to see all ${tabLabelPlural}.`; } formatDateWithFormat(value, format) { const date = value instanceof Date ? value : new Date(value); if (date.getTime() !== date.getTime()) { return value; } return new Intl.DateTimeFormat(this.userLocale, format).format(date); } formatToTimeOnly(param) { } formatToDateOnly(param) { } formatTimeWithFormat(value, format) { const date = value instanceof Date ? value : new Date(value); if (date.getTime() !== date.getTime()) { return value; } const timeParts = Intl.DateTimeFormat(this.userLocale, format) .formatToParts(date) .reduce((obj, part) => { obj[part.type] = part.value; return obj; }, {}); const dayPeriod = timeParts.dayPeriod ? timeParts.dayPeriod : ''; const res = `${timeParts.hour}:${timeParts.minute} ${dayPeriod}`; return res; } getWeekdays(weekStartsOn = 0) { function getDay(dayOfWeek) { const dt = new Date(); return dt.setDate(dt.getDate() - dt.getDay() + dayOfWeek); } let weekdays = [getDay(0), getDay(1), getDay(2), getDay(3), getDay(4), getDay(5), getDay(6)].reduce((dayList, dt) => { dayList.push(new Intl.DateTimeFormat(this.userLocale, { weekday: 'long' }).format(dt)); return dayList; }, []); if (weekStartsOn > 0 && weekStartsOn <= 6) { const newStart = weekdays.splice(weekStartsOn); weekdays = [...newStart, ...weekdays]; } return weekdays; } getMonths() { function getMonth(month) { const dt = new Date(); return dt.setMonth(month, 1); } return [ getMonth(0), getMonth(1), getMonth(2), getMonth(3), getMonth(4), getMonth(5), getMonth(6), getMonth(7), getMonth(8), getMonth(9), getMonth(10), getMonth(11), ].reduce((months, dt) => { months.push(new Intl.DateTimeFormat(this.userLocale, { month: 'long' }).format(dt)); return months; }, []); } getProperty(value) { return this[value]; } getRangeText(page, pageSize, length, short) { if (length === 0 || pageSize === 0) { return `Displaying 0 of ${length}`; } length = Math.max(length, 0); const startIndex = page * pageSize; // If the start index exceeds the list length, do not try and fix the end index to the end. const endIndex = startIndex < length ? Math.min(startIndex + pageSize, length) : startIndex + pageSize; return short ? `${startIndex + 1} - ${endIndex}/${length}` : `Displaying ${startIndex + 1} - ${endIndex} of ${length}`; } formatCurrency(value) { const options = { style: 'currency', currency: 'USD' }; return new Intl.NumberFormat(this.userLocale, options).format(value); } /** * Extends the Intl.numberFormat capability with two extra features: * - Does NOT round values, but instead truncates to maximumFractionDigits * - By default uses accounting format for negative numbers: (3.14) instead of -3.14. * * @param value The number value to convert to string * @param overrideOptions Allows for overriding options used and passed to Intl.NumberFormat() */ formatBigDecimal(value, overrideOptions) { const defaultOptions = { style: 'decimal', minimumFractionDigits: 2, maximumFractionDigits: 2, useAccountingFormat: true, }; const options = Object.assign(defaultOptions, overrideOptions); const truncatedValue = this.truncateToPrecision(value, options.maximumFractionDigits); let _value = new Intl.NumberFormat(this.userLocale, options).format(truncatedValue); if (value < 0) { _value = options.useAccountingFormat ? `(${_value.slice(1)})` : `-${_value.slice(1)}`; } return _value; } /** * Performs a string-based truncating of a number with no rounding */ truncateToPrecision(value, precision) { let valueAsString = value ? value.toString() : '0'; const decimalIndex = valueAsString.indexOf('.'); if (decimalIndex > -1 && decimalIndex + precision + 1 < valueAsString.length) { valueAsString = valueAsString.substring(0, valueAsString.indexOf('.') + precision + 1); } return Number(valueAsString); } formatNumber(value, options) { return new Intl.NumberFormat(this.userLocale, options).format(value); } formatDateShort(value) { const options = { // DD/MM/YYYY, HH:MM A - 02/14/2017, 1:17 PM month: '2-digit', day: '2-digit', year: 'numeric', hour: 'numeric', minute: '2-digit', }; const _value = value === null || value === undefined || value === '' ? new Date() : new Date(value); return new Intl.DateTimeFormat(this.userLocale, options).format(_value); } formatTime(value) { const options = { // HH:MM A - 1:17 PM hour: 'numeric', minute: '2-digit', }; const _value = value === null || value === undefined || value === '' ? new Date() : new Date(value); return new Intl.DateTimeFormat(this.userLocale, options).format(_value); } formatDate(value) { const options = { // DD/MM/YYYY - 02/14/2017 month: '2-digit', day: '2-digit', year: 'numeric', }; const _value = value === null || value === undefined || value === '' ? new Date() : new Date(value); return new Intl.DateTimeFormat(this.userLocale, options).format(_value); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoLabelService, deps: [{ token: LOCALE_ID, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoLabelService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoLabelService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [LOCALE_ID] }] }] }); const NOVO_ELEMENTS_LABELS_PROVIDERS = [{ provide: NovoLabelService, useClass: NovoLabelService }]; // NG2 class DateFormatService { constructor(labels) { this.labels = labels; this.dateFormatAsImaskPattern = this.dateFormatToImaskPattern(this.labels.dateFormatString()); } getTimeMask(militaryTime) { const amFormat = this.labels.timeFormatAM.toUpperCase(); const pmFormat = this.labels.timeFormatPM.toUpperCase(); const mask = { mask: Date, pattern: militaryTime ? 'HH:mm' : 'hh:mm aa', overwrite: true, autofix: true, lazy: false, min: new Date(1970, 0, 1), max: new Date(2100, 0, 1), prepare(str) { return str.toUpperCase(); }, format(date) { return DateUtil.format(date, militaryTime ? 'HH:mm' : 'hh:mm A'); }, parse: (str) => { const time = militaryTime ? str : this.convertTime12to24(str); return DateUtil.parse(`${DateUtil.format(Date.now(), 'YYYY-MM-DD')}T${time}`); }, blocks: { HH: { mask: MaskedRange, placeholderChar: 'H', maxLength: 2, from: 0, to: 23, }, hh: { mask: MaskedRange, placeholderChar: 'h', maxLength: 2, from: 1, to: 12, }, mm: { mask: MaskedRange, placeholderChar: 'm', maxLength: 2, from: 0, to: 59, }, aa: { mask: MaskedEnum, placeholderChar: 'x', enum: ['AM', 'PM', 'am', 'pm', amFormat, pmFormat], }, }, }; return mask; } getDateMask() { return { mask: /^((\d)(\d|\/|\.|\-){0,7})?(\d){0,2}$/, }; } getDateTimeMask(militaryTime = false) { return [this.getDateMask(), /\,?/, /\s/, this.getTimeMask(militaryTime)]; } getTimePlaceHolder(militaryTime) { if (militaryTime) { return this.labels.timeFormatPlaceholder24Hour; } return this.labels.timeFormatPlaceholderAM; } parseCustomDateString(dateString, customFormat) { let isInvalidDate = true; let date = null; if (!customFormat) { customFormat = this.labels.dateFormatString(); } customFormat = convertTokens(customFormat); const [cleanDateString, cleanFormat] = this.removeNonstandardFormatCharacters(dateString, customFormat); try { date = parse(cleanDateString, cleanFormat, new Date(), { useAdditionalWeekYearTokens: false, }); if (isNaN(date.getTime())) { date = null; } else if (cleanDateString !== dateString) { // Verify that this parse matches the original dateString through this format. If not, then something may have mismatched - // in which case we consider the date to be invalid. // For instance, if we parsed "Fri Oct 18, 2023" as " Oct 18 2023" (removing the duplicative day-of-week) then it // would re-format as "Wed Oct 18 2023" and is an invalid date. const reformattedDate = format(date, customFormat); if (reformattedDate !== dateString) { date = null; } else { isInvalidDate = false; } } else { isInvalidDate = false; } } catch (err) { // ignore error - keep isInvalidDate true and date null } return [date, dateString, isInvalidDate]; } dateFormatToImaskPattern(formatString) { const partsReg = /(\w)\1+|([\.\\/-])/g; let output = ''; let match; while ((match = partsReg.exec(formatString)) != null) { if (match[1]) { const matchLow = match[1].toLowerCase(); if (matchLow === 'y') { output += 'Y'; } else { output += matchLow; } } else { output += `{${match[2]}}\``; } } return output; } /** * Certain date format characters are considered nonstandard. We can still use them, but remove them for date parsing to avoid errors * @param dateString * @param formatString * @returns date string and format in array, both having had their */ removeNonstandardFormatCharacters(dateString, formatString) { const bannedChars = /[iIRoPp]+/; // remove quotes formatString = formatString.replace(/['"]/g, ''); let match = null; while ((match = bannedChars.exec(formatString)) != null) { formatString = formatString.substring(0, match.index) + formatString.substring(match.index + match[0].length); dateString = dateString.substring(0, match.index) + dateString.substring(match.index + match[0].length); } return [dateString, formatString]; } parseDateString(dateString) { let dateFormat = this.labels.dateFormatString(); const dateFormatRegex = /(\w+)[\/|\.|\-](\w+)[\/|\.|\-](\w+)/gi; const dateValueRegex = /(\d+)[\/|\.|\-](\d+)[\/|\.|\-](\d+)/gi; let year; let month; let day; let date = null; let isInvalidDate = true; if (Helpers.isEmpty(dateFormat)) { // Default to MM/dd/yyyy dateFormat = 'mm/dd/yyyy'; } else { dateFormat = dateFormat.toLowerCase(); } const dateFormatTokens = dateFormatRegex.exec(dateFormat); const dateValueTokens = dateValueRegex.exec(dateString); if (dateFormatTokens && dateFormatTokens.length === 4 && dateValueTokens && dateValueTokens.length === 4) { for (let i = 1; i < 4; i++) { if (dateFormatTokens[i].includes('m')) { month = parseInt(dateValueTokens[i], 10) - 1; } else if (dateFormatTokens[i].includes('d')) { day = parseInt(dateValueTokens[i], 10); } else { year = parseInt(dateValueTokens[i], 10); } } if (month >= 0 && month <= 11 && year > 1900 && day > 0 && day <= 31) { date = new Date(year, month, day); isInvalidDate = false; } } else if (dateFormatTokens && dateFormatTokens.length === 4 && dateString.length >= 1) { const twoTokens = /\d{1,4}(\/|\.|\-)(\d{1,2})/.exec(dateString); const oneToken = /^(\d{1,4})$/.exec(dateString); const delimiter = /\w+(\/|\.|\-)\w+[\/|\.|\-]\w+/gi.exec(dateFormat); const dateStringWithDelimiter = dateString[dateString.length - 1].match(/\/|\.|\-/); if ((twoTokens && twoTokens.length === 3 && this.isValidDatePart(twoTokens[2], dateFormatTokens[2]) && !dateStringWithDelimiter) || (oneToken && oneToken.length === 2 && this.isValidDatePart(oneToken[1], dateFormatTokens[1]) && !dateStringWithDelimiter)) { dateString = `${dateString}${delimiter[1]}`; } } return [date, dateString, isInvalidDate]; } parseTimeString(timeString, militaryTime) { const value = new Date(); let timeStringParts; let amFormat = this.labels.timeFormatAM; let pmFormat = this.labels.timeFormatPM; if (!(timeString?.includes(':'))) { return [value, timeString]; } if (!militaryTime && amFormat && pmFormat) { let splits = []; let pm = false; amFormat = this.labels.timeFormatAM.toLowerCase(); pmFormat = this.labels.timeFormatPM.toLowerCase(); timeString = timeString.toLowerCase(); if (timeString.includes(amFormat)) { splits = timeString.split(amFormat); } else if (timeString.includes(pmFormat)) { splits = timeString.split(pmFormat); pm = true; } if (splits?.length) { for (const item of splits) { if (item?.trim().includes(':')) { timeStringParts = item.trim().split(':'); } } } if (timeStringParts?.length && timeStringParts.length === 2) { let hours = parseInt(timeStringParts[0], 10); if (hours === 12 && pm) { hours = 12; } else if (pm) { hours = hours + 12; } else if (hours === 12) { hours = 0; } value.setHours(hours); value.setMinutes(parseInt(timeStringParts[1], 10)); value.setSeconds(0); } } else { timeStringParts = /(\d{1,2}):(\d{2})/.exec(timeString); if (timeStringParts?.length && timeStringParts.length === 3) { value.setHours(parseInt(timeStringParts[1], 10)); value.setMinutes(parseInt(timeStringParts[2], 10)); value.setSeconds(0); } } return [value, timeString]; } parseString(dateTimeString, militaryTime, type) { if (!(dateTimeString?.length)) { return null; } switch (type) { case 'datetime': const str = dateTimeString.replace(/-/g, '/'); const parts = str.split(' '); const [dt, dts] = this.parseDateString(parts[0]); if (parts.length > 1) { const [tm, tms] = this.parseTimeString(parts[1], militaryTime); return [new Date(dt.setHours(tm.getHours(), tm.getMinutes())), `${dts} ${tms}`]; } return [dt, dts]; case 'date': return this.parseDateString(dateTimeString); case 'time': return this.parseTimeString(dateTimeString, militaryTime); default: return; } } convertTime12to24(time12h) { const pmFormat = this.labels.timeFormatPM.toUpperCase(); const [time, modifier] = time12h.split(' '); // eslint-disable-next-line prefer-const let [hours, minutes] = time.split(':'); if (hours === '12') { hours = '00'; } if (['PM', pmFormat].includes(modifier)) { hours = `${parseInt(hours, 10) + 12}`.padStart(2, '0'); } return `${hours}:${minutes}`; } isValidDatePart(value, formatString) { const datePart = parseInt(value, 10); return ((formatString.includes('m') && (datePart >= 2 || value.length === 2)) || (formatString.includes('d') && (datePart >= 4 || value.length === 2)) || (formatString.includes('y') && datePart >= 1000)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateFormatService, deps: [{ token: NovoLabelService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateFormatService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: DateFormatService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: NovoLabelService }] }); class GlobalRef { } class BrowserGlobalRef extends GlobalRef { get nativeGlobal() { return window; } get nativeWindow() { return window; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BrowserGlobalRef, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BrowserGlobalRef }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: BrowserGlobalRef, decorators: [{ type: Injectable }] }); class NodeGlobalRef extends GlobalRef { get nativeGlobal() { throw new Error('global doesn\'t compile for some reason'); } get nativeWindow() { throw new Error('Node does not have a window object'); } } // App class OptionsService { constructor() { } getOptionsConfig(http, field, config) { return { field: 'value', format: '$label', options: (query) => { return new Promise((resolve, reject) => { if (query && query.length) { const exp = new RegExp('^(?:[a-z]+:)?//', 'i'); let endpoint; if (exp.test(field.optionsUrl)) { const url = new URL(field.optionsUrl); url.searchParams.set('filter', query || ''); endpoint = url.toString(); } else { // Construct relative url (host will not be used but is required for construction) const url = new URL(`http://placeholder.com/${field.optionsUrl}`); url.searchParams.set('filter', query || ''); endpoint = `${url.pathname}${url.search}`; } http.get(endpoint).subscribe(resolve, reject); } else { resolve([]); } }); }, }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OptionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OptionsService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: OptionsService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); // NG2 class Security { constructor() { this.credentials = []; this.change = new EventEmitter(); } grant(data) { const parsed = []; if (data instanceof Array) { for (const permission of data) { parsed.push(permission.replace(/\s/gi, '')); } } else if (typeof data === 'object') { for (const key in data) { if (data[key] instanceof Array) { for (const permission of data[key]) { parsed.push(`${key}.${permission}`); } } } } this.credentials = [].concat(this.credentials, parsed); this.change.emit(this.credentials); } has(value) { return this.credentials.indexOf(value) > -1; } revoke(value) { const i = this.credentials.indexOf(value); this.credentials.splice(i, 1); this.change.emit(this.credentials); } clear() { this.credentials = []; this.change.emit(this.credentials); } subscribe(fn) { return this.change.subscribe(fn); } checkRoutes(routes, options) { const filtered = []; for (const route of routes) { if (route.entities && ~route.entities.indexOf(options.entityType)) { if (route.permissions instanceof Function) { if (route.permissions(options, this)) { filtered.push(route); } } else if (route.permissions && route.permissions.length) { if (route.permissions.every((perm) => this.has(perm))) { filtered.push(route); } } else { filtered.push(route); } } } return filtered; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: Security, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: Security, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: Security, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class LocalStorageService { setItem(key, value) { localStorage.setItem(key, value); } getItem(key) { return localStorage.getItem(key); } removeItem(key) { localStorage.removeItem(key); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocalStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocalStorageService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: LocalStorageService, decorators: [{ type: Injectable }] }); // NG2 class NovoTemplateService { constructor() { this.templates = { default: {}, custom: {}, }; } getAll() { const templates = {}; const customTemplateTypes = Object.keys(this.templates.custom); const defaultTemplateTypes = Object.keys(this.templates.default); defaultTemplateTypes.forEach((type) => { templates[type] = this.templates.default[type]; }); customTemplateTypes.forEach((type) => { templates[type] = this.templates.custom[type]; }); return templates; } addDefault(key, template) { this.templates.default[key] = template; } addCustom(key, template) { this.templates.custom[key] = template; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoTemplateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoTemplateService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.19", ngImport: i0, type: NovoTemplateService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); /** * Generated bundle index. Do not edit. */ export { ArrayCollection, BrowserGlobalRef, CollectionEvent, ComponentUtils, DateFormatService, GlobalRef, LocalStorageService, NOVO_ELEMENTS_LABELS_PROVIDERS, NodeGlobalRef, NovoLabelService, NovoTemplateService, OptionsService, PagedArrayCollection, Security }; //# sourceMappingURL=novo-elements-services.mjs.map