WIP
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
import { DropDownOption } from '../entity/dropDownOption';
|
||||
|
||||
export class ArrayUtils {
|
||||
|
||||
public static Equals(array1, array2) {
|
||||
// if the other array is a falsy value, return
|
||||
if (!array2)
|
||||
return false;
|
||||
|
||||
// compare lengths - can save a lot of time
|
||||
if (array1.length != array2.length)
|
||||
return false;
|
||||
|
||||
for (var i = 0, l = array1.length; i < l; i++) {
|
||||
// Check if we have nested arrays
|
||||
if (array1[i] instanceof Array && array2[i] instanceof Array) {
|
||||
// recurse into the nested arrays
|
||||
if (!ArrayUtils.Equals(array1[i], array2[i]))
|
||||
return false;
|
||||
}
|
||||
else if (array1[i] != array2[i]) {
|
||||
// Warning - two different object instances will never be equal: {x:20} != {x:20}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static ToDropDownOptions(array: any[], keyProperty: string | number, valueProperty: string | number): DropDownOption[] {
|
||||
var result = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const element = array[i];
|
||||
result.push(new DropDownOption(element[keyProperty], element[valueProperty]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static MoveItem(arr: any[], old_index, new_index) {
|
||||
if (new_index >= arr.length) {
|
||||
var k = new_index - arr.length + 1;
|
||||
while (k--) {
|
||||
arr.push(undefined);
|
||||
}
|
||||
}
|
||||
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
|
||||
};
|
||||
|
||||
public static GroupBy<T = any>(arr: Array<T>, groupKeyPrepareFunction: (obj: T) => any | any[]) {
|
||||
|
||||
let groups = arr.reduce(function (groupModel, obj) {
|
||||
|
||||
let keys = groupKeyPrepareFunction(obj);
|
||||
|
||||
const addToGroup = (key: any, obj: T) => {
|
||||
let group = groupModel.find(g => g.key == key);
|
||||
if (group == null) {
|
||||
group = new GroupModel(key);
|
||||
groupModel.push(group);
|
||||
}
|
||||
group.values.push(obj);
|
||||
}
|
||||
|
||||
if (Array.isArray(keys)) {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
addToGroup(key, obj);
|
||||
}
|
||||
} else {
|
||||
addToGroup(keys, obj);
|
||||
}
|
||||
return groupModel;
|
||||
}, [] as GroupModel<T>[]);
|
||||
return groups;
|
||||
}
|
||||
public static RemoveDuplicate<T>(objArray: T[], duplicateDetection: (a: T, b: T) => boolean) {
|
||||
return objArray.filter((value, index, self) =>
|
||||
index === self.findIndex((t) => duplicateDetection(t, value))
|
||||
);
|
||||
}
|
||||
|
||||
public static ConcatMultiArray<T>(arrays: T[][]): T[] {
|
||||
return <T[]>[].concat.apply(<T[]>[], arrays.map(arr => arr));
|
||||
}
|
||||
|
||||
public static insertAt = (arr: any[], index: number, newItems: any) => [
|
||||
// part of the array before the specified index
|
||||
...arr.slice(0, index),
|
||||
// inserted items
|
||||
newItems,
|
||||
// part of the array after the specified index
|
||||
...arr.slice(index)
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
export class GroupModel<T = any>{
|
||||
constructor(key: any) {
|
||||
this.key = key;
|
||||
this.values = [];
|
||||
}
|
||||
|
||||
key: any;
|
||||
values: T[];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export class UrlBase {
|
||||
|
||||
public static LoginPortalApiPrefixPath = "/TsPlusBridge/api";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
export class DateUtils {
|
||||
public static getIntervalDays(from: Date, to: Date, daysOfYear: DaysOfYear = DaysOfYear.ThirtyDaysPerMonth, countEndDate: boolean = false): number {
|
||||
let isNegative = false;
|
||||
if (from > to) {
|
||||
isNegative = true;
|
||||
let temp = new Date(to);
|
||||
to = from;
|
||||
from = temp;
|
||||
}
|
||||
|
||||
var days = 0;
|
||||
if (from && to) {
|
||||
//Get date without time
|
||||
from = new Date(from.getFullYear(), from.getMonth(), from.getDate());
|
||||
to = new Date(to.getFullYear(), to.getMonth(), to.getDate());
|
||||
var differenceTime = to.getTime() - from.getTime();
|
||||
if (differenceTime > 0) {
|
||||
if (daysOfYear == DaysOfYear.ThirtyDaysPerMonth) {
|
||||
var fromYear = from.getFullYear();
|
||||
var toYear = to.getFullYear();
|
||||
var fromMonth = from.getMonth() + 1;
|
||||
var toMonth = to.getMonth() + 1;
|
||||
|
||||
var fromDays = from.getDate() > 30 ? 30 : from.getDate();
|
||||
var toDays = to.getDate();
|
||||
|
||||
days += 30 - fromDays;
|
||||
days += toDays;
|
||||
//calculate full 12 months years
|
||||
if (toYear > (fromYear + 1)) {
|
||||
days += (toYear - fromYear - 1) * 12 * 30;
|
||||
}
|
||||
|
||||
//if it's two different years, calculate the interval months
|
||||
if (toYear > fromYear) {
|
||||
days += (12 - fromMonth) * 30;
|
||||
days += (toMonth - 1) * 30;
|
||||
}
|
||||
else {
|
||||
//same year
|
||||
days += (toMonth - fromMonth - 1) * 30
|
||||
}
|
||||
}
|
||||
else {
|
||||
// To calculate the no. of days between two dates
|
||||
days = Math.round(differenceTime / (1000 * 3600 * 24));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (days + (countEndDate ? 1 : 0)) * (isNegative ? -1 : 1);
|
||||
}
|
||||
|
||||
public static addDays(date: Date, days: number): Date {
|
||||
if (date) {
|
||||
var result = new Date(date);
|
||||
result.setDate(result.getDate() + days);
|
||||
return result;
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
public static format(date: Date, format: string, nullFormat: string = ''): string {
|
||||
if (date) {
|
||||
var z = {
|
||||
M: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
H: date.getHours(),
|
||||
h: (date.getHours() == 0 ? date.getHours() + 12 : date.getHours() > 12 ? date.getHours() - 12 : date.getHours()),
|
||||
m: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: (date.getHours() > 11 ? 'PM' : 'AM')
|
||||
};
|
||||
format = format.replace(/(M+|d+|H+|h+|m+|s+|a+)/g, function (v) {
|
||||
return ((v.length > 1 ? "0" : "") + z[v.slice(-1)]).slice(-2);
|
||||
});
|
||||
|
||||
return format.replace(/(y+)/g, function (v) {
|
||||
return date.getFullYear().toString().slice(-v.length)
|
||||
});
|
||||
}
|
||||
return nullFormat;
|
||||
}
|
||||
public static isValidDate(d): boolean {
|
||||
return d instanceof Date && d.getTime() == d.getTime();
|
||||
}
|
||||
public static parse(value): Date {
|
||||
if (value) {
|
||||
value = new Date(value);
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
public static getToday(endOfDay: boolean = false): Date {
|
||||
let value = new Date();
|
||||
if (!endOfDay) {
|
||||
value.setHours(0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
value.setHours(23, 59, 59, 999);
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
public static getBeginOfDate(value): Date {
|
||||
if (value) {
|
||||
value = new Date(value);
|
||||
value.setHours(0, 0, 0, 0);
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
public static getEndOfDate(value): Date {
|
||||
if (value) {
|
||||
value = new Date(value);
|
||||
value.setHours(23, 59, 59, 999);
|
||||
}
|
||||
return value
|
||||
}
|
||||
public static getEndOfMonth(value): Date {
|
||||
if (value) {
|
||||
return new Date(value.getFullYear(), value.getMonth() + 1, 0)
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static isSameDate(date: Date, comparison: Date): boolean {
|
||||
if (!date || !comparison) return (!date && !comparison);
|
||||
date = this.parse(date);
|
||||
comparison = this.parse(comparison);
|
||||
return date.getFullYear() == comparison.getFullYear() && date.getMonth() == comparison.getMonth() && date.getDate() == comparison.getDate();
|
||||
}
|
||||
|
||||
public static changeTimezone(date, ianatz) {
|
||||
// suppose the date is 12:00 UTC
|
||||
var invdate = new Date(date.toLocaleString('en-US', {
|
||||
timeZone: ianatz
|
||||
}));
|
||||
|
||||
// then invdate will be 07:00 in Toronto
|
||||
// and the diff is 5 hours
|
||||
var diff = date.getTime() - invdate.getTime();
|
||||
|
||||
// so 12:00 in Toronto is 17:00 UTC
|
||||
return new Date(date.getTime() + diff);
|
||||
}
|
||||
|
||||
public static changeTimezoneByOffset(date, tzOffset) {
|
||||
let time = date.getTime();
|
||||
return new Date(time - (tzOffset * 60000));
|
||||
}
|
||||
|
||||
public static getTimeStamp() {
|
||||
var now = new Date();
|
||||
return ((now.getMonth() + 1) + '/' + (now.getDate()) + '/' + now.getFullYear() + " " + now.getHours() + ':'
|
||||
+ ((now.getMinutes() < 10) ? ("0" + now.getMinutes()) : (now.getMinutes())) + ':' + ((now.getSeconds() < 10) ? ("0" + now
|
||||
.getSeconds()) : (now.getSeconds())));
|
||||
}
|
||||
|
||||
|
||||
public static getDatesBetween(startDate: Date, endDate: Date): Date[] {
|
||||
startDate = this.getBeginOfDate(startDate);
|
||||
endDate = this.getBeginOfDate(endDate);
|
||||
let result = [startDate];
|
||||
if (startDate < endDate) {
|
||||
let tempDate = new Date(startDate);
|
||||
while (tempDate < endDate) {
|
||||
tempDate = this.addDays(tempDate, 1);
|
||||
result.push(tempDate);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export enum DaysOfYear {
|
||||
ThirtyDaysPerMonth = 360,
|
||||
FullYearDays = 365
|
||||
}
|
||||
|
||||
|
||||
export enum DatePeriod {
|
||||
Daily,
|
||||
Weekly,
|
||||
Monthly,
|
||||
Quarterly,
|
||||
SemiAnnually,
|
||||
Annually,
|
||||
Period,
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
export class EnumUtils {
|
||||
|
||||
public static hasFlag(obj, enumValue): boolean {
|
||||
if (obj) {
|
||||
if (obj & enumValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export class FileUtils {
|
||||
public static formatFileSize(bytes: number): string {
|
||||
if (bytes < 1024) {
|
||||
return `${bytes} Bytes`;
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return `${(bytes / 1024).toFixed(2)} KB`;
|
||||
} else {
|
||||
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
|
||||
}
|
||||
}
|
||||
|
||||
public static getFileName(fileFullPath: string): string | null {
|
||||
const lastSlashIndex = fileFullPath.lastIndexOf('\\');
|
||||
if (lastSlashIndex === -1 || lastSlashIndex === 0 || lastSlashIndex === fileFullPath.length - 1) {
|
||||
return fileFullPath; // No folder found
|
||||
}
|
||||
return fileFullPath.slice(lastSlashIndex + 1);
|
||||
}
|
||||
public static getFileExt(filename: string): string | null {
|
||||
const lastDotIndex = filename.lastIndexOf('.');
|
||||
if (lastDotIndex === -1 || lastDotIndex === 0 || lastDotIndex === filename.length - 1) {
|
||||
return null; // No extension found
|
||||
}
|
||||
return filename.slice(lastDotIndex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
export class LinqUtils {
|
||||
public static GroupBy(xs: any[], key: any) {
|
||||
return xs.reduce(function (rv, x) {
|
||||
(rv[x[key]] = rv[x[key]] || []).push(x);
|
||||
return rv;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
@function add($a, $b) {
|
||||
@return $a + $b;
|
||||
}
|
||||
|
||||
@function mult($a, $b) {
|
||||
@return $a * $b;
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import { formatCurrency } from "@angular/common";
|
||||
|
||||
export class NumberUtils {
|
||||
|
||||
public static Ordinal(value: number): string {
|
||||
let suffix = '';
|
||||
const last = value % 10;
|
||||
const specialLast = value % 100;
|
||||
if (!value || value < 1) {
|
||||
return value.toString();
|
||||
}
|
||||
if (last === 1 && specialLast !== 11) {
|
||||
suffix = 'st';
|
||||
} else if (last === 2 && specialLast !== 12) {
|
||||
suffix = 'nd';
|
||||
} else if (last === 3 && specialLast !== 13) {
|
||||
suffix = 'rd';
|
||||
} else {
|
||||
suffix = 'th';
|
||||
}
|
||||
return value + suffix;
|
||||
}
|
||||
|
||||
public static Clamp(n: number, min: number, max: number): number {
|
||||
return Math.min(max, Math.max(min, n));
|
||||
}
|
||||
|
||||
public static SortFunction(a: number, b: number): number {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
public static Sum(array: number[], key: any = undefined): number {
|
||||
if (key) {
|
||||
return array.reduce((a, b) => (isNaN(a[key]) ? 0 : a[key]) + (isNaN(b[key]) ? 0 : b[key]), 0);
|
||||
}
|
||||
return array.reduce((a, b) => (isNaN(a) ? 0 : a) + (isNaN(b) ? 0 : b), 0);
|
||||
}
|
||||
|
||||
public static FormatCurrency(v: number, zeroExpression: string = '0'): string {
|
||||
|
||||
return ['', 0, null, undefined, NaN].includes(v) ? zeroExpression : formatCurrency(v, "en", "", "", `0.2`);
|
||||
}
|
||||
public static Round(num, precision) {
|
||||
const factor = 10 ** precision;
|
||||
return Math.round(num * factor) / factor;
|
||||
}
|
||||
|
||||
public static RoundCurrency(num) {
|
||||
return this.Round(num, 2);
|
||||
}
|
||||
|
||||
public static VersionDiff(v1: string, v2: string) {
|
||||
let versionDefine = [
|
||||
{ index: 0, name: 'major' },
|
||||
{ index: 1, name: 'minor' },
|
||||
{ index: 2, name: 'patch' },
|
||||
{ index: 3, name: 'build' }
|
||||
]
|
||||
if (v1 && v2) {
|
||||
let v1Versions = v1.split('.');
|
||||
let v2Versions = v2.split('.');
|
||||
|
||||
for (let i = 0; i < v1Versions.length; i++) {
|
||||
if (v2Versions.length == i) return versionDefine[i];
|
||||
if (v1Versions[i] != v2Versions[i]) return versionDefine[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
const dateAndTimeRegex = new RegExp(/^(?<Date>\d{4}-\d{2}-\d{2})T(?<HourMin>\d{2}:\d{2}):((?<SecondAndMillisecond>\d{2}\.\d{0,6})|(?<Second>\d{2}))$/);
|
||||
|
||||
export class ObjectUtils {
|
||||
|
||||
private static ReviveDateTime(key: any, value: any): any {
|
||||
if (typeof value === 'string') {
|
||||
if (dateAndTimeRegex.test(value)) {
|
||||
let newDate = new Date(value);
|
||||
return newDate;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static HasAnyData(obj: any, excludes: string[] = []) {
|
||||
var hasData = false;
|
||||
|
||||
for (const p in obj) {
|
||||
if (false == excludes.includes(p) && Object.prototype.hasOwnProperty.call(obj, p)) {
|
||||
const element = obj[p];
|
||||
if (element) {
|
||||
if (typeof element !== 'object' || this.HasAnyData(element, excludes)) {
|
||||
hasData = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasData;
|
||||
}
|
||||
public static Clone<T = any>(obj: T, avoidCirculateRef = false): T {
|
||||
if (avoidCirculateRef) {
|
||||
return JSON.parse(this.stringify(obj), ObjectUtils.ReviveDateTime);
|
||||
}
|
||||
return JSON.parse(JSON.stringify(obj), ObjectUtils.ReviveDateTime);
|
||||
}
|
||||
|
||||
public static CopyValue(source: any, destination: any, excludes: string[] = ["id"], overwriting: boolean = true) {
|
||||
|
||||
for (const p in source) {
|
||||
if (false == excludes.includes(p) && Object.prototype.hasOwnProperty.call(source, p)) {
|
||||
const element = source[p];
|
||||
|
||||
if (element && Array.isArray(element)) {
|
||||
if ([null, undefined].includes(destination[p])) {
|
||||
destination[p] = [];
|
||||
for (let i = 0; i < element.length; i++) {
|
||||
const cloneItem = {};
|
||||
this.CopyValue(element[i], cloneItem, excludes, true);
|
||||
destination[p].push(cloneItem);
|
||||
}
|
||||
} else if (Array.isArray(destination[p])) {
|
||||
|
||||
for (let i = 0; i < element.length; i++) {
|
||||
const item = element[i];
|
||||
let destLength = destination[p].length;
|
||||
if (i >= destLength) {
|
||||
destination[p].push(this.Clone(source[p][i]));
|
||||
}
|
||||
this.CopyValue(item, destination[p][i], excludes, overwriting);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element && typeof element.getMonth === 'function') {
|
||||
//For angular will treat Date as object
|
||||
try {
|
||||
destination[p] = element;
|
||||
} catch (error) {
|
||||
console.log(`can\'t copy ${p}`, error);
|
||||
}
|
||||
}
|
||||
else if (element && typeof element == 'object') {
|
||||
let objectOverwriting = overwriting;
|
||||
if ([null, undefined].includes(destination[p])) {
|
||||
destination[p] = {};
|
||||
objectOverwriting = true;
|
||||
}
|
||||
try {
|
||||
this.CopyValue(element, destination[p], excludes, objectOverwriting);
|
||||
} catch (error) {
|
||||
console.log(`can\'t copy ${p}`, error);
|
||||
}
|
||||
} else if (overwriting || [null, '', undefined].includes(destination[p])) {
|
||||
try {
|
||||
destination[p] = element;
|
||||
} catch (error) {
|
||||
console.log(`can\'t copy ${p}`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static ClearPkAndFk(source: any, excludes: string[] = [], clearExtra: string[] = []) {
|
||||
|
||||
for (const p in source) {
|
||||
const element = source[p];
|
||||
|
||||
if (element) {
|
||||
if (clearExtra.includes(p)) {
|
||||
source[p] = null;
|
||||
} else if (typeof element == 'object') {
|
||||
this.ClearPkAndFk(element, excludes, clearExtra);
|
||||
} else if (
|
||||
(typeof element == 'string' && (p == 'id' || p.indexOf('Id') > -1) &&
|
||||
false == excludes.includes(p))
|
||||
) {
|
||||
source[p] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public static ClearValue(source: any, excludes: string[] = ["id"]) {
|
||||
for (const p in source) {
|
||||
if (false == excludes.includes(p) && Object.prototype.hasOwnProperty.call(source, p)) {
|
||||
const element = source[p];
|
||||
|
||||
if (element) {
|
||||
if (typeof element == 'object') {
|
||||
this.ClearValue(element, excludes);
|
||||
} else if (typeof element == 'number') {
|
||||
source[p] = 0;
|
||||
} else {
|
||||
source[p] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* return `true` if the comparison has any different value with source.
|
||||
*/
|
||||
public static CompareDiffValue(source: any, comparison: any, excludes: string[] = ["id"]) {
|
||||
let isDifferent = false;
|
||||
for (const p in source) {
|
||||
if (false == excludes.includes(p) &&
|
||||
Object.prototype.hasOwnProperty.call(source, p)) {
|
||||
const element = source[p];
|
||||
if (element && Array.isArray(element)) {
|
||||
if (Array.isArray(comparison[p])) {
|
||||
for (let i = 0; i < element.length; i++) {
|
||||
const item = element[i];
|
||||
let destLength = comparison[p].length;
|
||||
if (i >= destLength) {
|
||||
return true;
|
||||
}
|
||||
isDifferent = this.CompareDiffValue(item, comparison[p][i], excludes);
|
||||
if (isDifferent) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (element && typeof element.getMonth === 'function') {
|
||||
//For angular will treat Date as object
|
||||
//TODO:Compare Date
|
||||
//comparison[p] = element;
|
||||
}
|
||||
else if (element && typeof element == 'object') {
|
||||
isDifferent = this.CompareDiffValue(element, comparison[p], excludes);
|
||||
|
||||
} else {
|
||||
isDifferent = comparison[p] != element;
|
||||
}
|
||||
|
||||
if (isDifferent) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* return `true` if the comparison has any different value with source.
|
||||
*/
|
||||
public static CompareDiffArrayContent(source: any[], comparison: any[], excludes: string[] = ["id"]) {
|
||||
let isDifferent = false;
|
||||
if (source && comparison) {
|
||||
if (source.length == comparison.length) {
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
const sourceItem = source[i];
|
||||
const comparisonItem = comparison[i];
|
||||
|
||||
isDifferent = this.CompareDiffValue(sourceItem, comparisonItem);
|
||||
if (isDifferent) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
public static nullCondition<T>(source: T) {
|
||||
if (source != null) return source;
|
||||
}
|
||||
|
||||
public static isNullOrUndefined(obj: any) {
|
||||
return [null, undefined].includes(obj);
|
||||
}
|
||||
|
||||
public static isObservable<T>(template: T | Observable<T>): template is Observable<T> {
|
||||
return (template as Observable<T>).subscribe !== undefined;
|
||||
}
|
||||
public static stringify(obj) {
|
||||
let cache = [];
|
||||
let str = JSON.stringify(obj, function (key, value) {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (cache.indexOf(value) !== -1) {
|
||||
// Circular reference found, discard key
|
||||
return;
|
||||
}
|
||||
// Store value in our collection
|
||||
cache.push(value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
cache = null; // reset the cache
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
export class LocalStorageKeys {
|
||||
//public static HOLIDAYS = "HOLIDAYS_FOR_DATE_PICKER";
|
||||
|
||||
public static NEW_TAB_PROFILE = "LoginPortal_newTabProfile";
|
||||
public static ESCROW_RECALL = "LoginPortal_escrowRecalls";
|
||||
public static SCREEN_HISTORY = "LoginPortal_screenHistory";
|
||||
public static LOGIN_ALL_ACCESS = "LoginPortal_allAccess";
|
||||
public static USER_PREFERENCE = "LoginPortal_userPreference";
|
||||
public static LAST_ESCROW_REFNDX = "LoginPortal_lastEscrowNo";
|
||||
public static COOKIE_ID = "LoginPortal_cookieId";
|
||||
public static USER_ACCESS = "LoginPortal_UserAccess";
|
||||
//public static DASHBOARD_WIDGETS_SETTING = "DASHBOARD_WIDGETS_SETTING";
|
||||
}
|
||||
export class SessionStorageKeys {
|
||||
public static SIDE_BAR_SEQ = "LoginPortal_SESSION_SCREEN_SEQ";
|
||||
public static ESCROW_TYPE = "LoginPortal_SESSION_ESCROW_TYPE";
|
||||
public static USER_PROFILE = "LoginPortal_USER_ACCESS"
|
||||
public static ESCROW_REFNDX = "LoginPortal_refndx"
|
||||
public static UI_DISPLAY_FOOTER_BAR = "LoginPortal_displayFooterBar"
|
||||
public static CURRENT_SCREEN = "LoginPortal_screen"
|
||||
}
|
||||
export class CookieKeys {
|
||||
public static SIDE_BAR_SEQ = "LoginPortal_SESSION_SCREEN_SEQ";
|
||||
public static ESCROW_TYPE = "LoginPortal_SESSION_ESCROW_TYPE";
|
||||
public static USER_PROFILE = "LoginPortal_USER_ACCESS"
|
||||
public static ESCROW_REFNDX = "LoginPortal_refndx"
|
||||
public static UI_DISPLAY_FOOTER_BAR = "LoginPortal_displayFooterBar"
|
||||
public static CURRENT_SCREEN = "LoginPortal_screen"
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
import { FtTagType } from "../components/fancy-table/fancy-row-column.model";
|
||||
|
||||
export class StringUtils {
|
||||
|
||||
static compare(aval: string, bval: string) {
|
||||
return aval ? aval.localeCompare(bval) : -1;
|
||||
}
|
||||
// Sorting function for SemVer
|
||||
// Returns 1 if a is greater, -1 if b is greater, 0 if equal
|
||||
public static compareSemVer(a: string, b: string): number {
|
||||
if (a === b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var a_components = a.split(".");
|
||||
var b_components = b.split(".");
|
||||
|
||||
var len = Math.min(a_components.length, b_components.length);
|
||||
|
||||
// loop while the components are equal
|
||||
for (var i = 0; i < len; i++) {
|
||||
// A bigger than B
|
||||
if (parseInt(a_components[i]) > parseInt(b_components[i])) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// B bigger than A
|
||||
if (parseInt(a_components[i]) < parseInt(b_components[i])) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// If one's a prefix of the other, the longer one is greater.
|
||||
if (a_components.length > b_components.length) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a_components.length < b_components.length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Otherwise they are the same.
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static isNullOrWhitespace(input: string): boolean {
|
||||
return !input || !input.trim() || 'null' == input;
|
||||
}
|
||||
|
||||
public static getTrimmedValue(input: string, emptyFormat: string = ''): string {
|
||||
if (input) {
|
||||
input = input.trim();
|
||||
}
|
||||
if (input) return input;
|
||||
return emptyFormat;
|
||||
}
|
||||
|
||||
|
||||
public static firstIsVowel(s: string): boolean {
|
||||
if (s) {
|
||||
return ['a', 'e', 'i', 'o', 'u'].indexOf(s[0].toLowerCase()) !== -1
|
||||
}
|
||||
}
|
||||
|
||||
public static makeCommaSeparatedString(arr: string[], useOxfordComma: boolean) {
|
||||
arr = arr.filter(s => s);
|
||||
const listStart = arr.slice(0, -1).join(', ');
|
||||
const listEnd = arr.slice(-1);
|
||||
const conjunction = arr.length <= 1 ? '' :
|
||||
useOxfordComma && arr.length > 2 ? ', and ' : ' and ';
|
||||
|
||||
return [listStart, listEnd].join(conjunction);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static getFormattedTerm(input: string, emptyFormatter: string = 'Empty'): string {
|
||||
if (false == this.isNullOrWhitespace(input)) {
|
||||
return input.trim();
|
||||
}
|
||||
return emptyFormatter;
|
||||
}
|
||||
public static camelToTitle(camelCase) {
|
||||
// no side-effects
|
||||
return camelCase
|
||||
// inject space before the upper case letters
|
||||
.replace(/([A-Z])/g, function (match) {
|
||||
return " " + match;
|
||||
})
|
||||
// replace first char with upper case
|
||||
.replace(/^./, function (match) {
|
||||
return match.toUpperCase();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* status could be `info` , `primary` , `danger` , `warning` , `success`
|
||||
*/
|
||||
public static getHtmlBadge(text: string, badgeStatus: FtTagType) {
|
||||
return `<label class="badge badge-${badgeStatus} mr-1 my-0 py-1">${text}</label>`;
|
||||
|
||||
}
|
||||
|
||||
public static getHtmlInnerText(htmlText: string) {
|
||||
return htmlText ? htmlText.replace(/<[^>]+>/g, '') : '';
|
||||
|
||||
let HTML_INNERTEXT_REGEX = />((.|\n*?))<\//g;
|
||||
|
||||
var match = HTML_INNERTEXT_REGEX.exec(htmlText);
|
||||
if (match) {
|
||||
return match[1];
|
||||
} else {
|
||||
return htmlText;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to parse city sate zip string like `Monrovia, CA 91016` to AddressInfo, if failed will return `null` instead.
|
||||
*/
|
||||
// public static tryParseCityStateZip(cityStateZip: string): AddressInfo {
|
||||
|
||||
// let addressInfo = new AddressInfo();
|
||||
// var regex = /([\w\s]*),\s*([A-Z]{2})\s*(\d*-?\d*)/g;
|
||||
// var match = regex.exec(cityStateZip);
|
||||
// if (match) {
|
||||
// addressInfo = new AddressInfo();
|
||||
// addressInfo.city = match[1];
|
||||
// addressInfo.state = match[2];
|
||||
// addressInfo.zip = match[3];
|
||||
// return addressInfo;
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// public static getCityStateZipString(addressInfo: AddressInfo): string {
|
||||
// let result = '';
|
||||
// if (false == this.isNullOrWhitespace(addressInfo.city)) {
|
||||
// result += `${addressInfo.city}, `;
|
||||
// }
|
||||
// if (false == this.isNullOrWhitespace(addressInfo.state)) {
|
||||
// result += `${addressInfo.state} `;
|
||||
// }
|
||||
// if (false == this.isNullOrWhitespace(addressInfo.zip)) {
|
||||
// result += addressInfo.zip;
|
||||
// }
|
||||
// return result;
|
||||
// }
|
||||
public static toUpperString(prop: any) {
|
||||
if (prop) {
|
||||
if (typeof prop === 'string') return prop.toUpperCase();
|
||||
prop.toString().toUpperCase();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
public static truncateString(str: string, maxLength: number) {
|
||||
if (str && str.length > maxLength) {
|
||||
return str.slice(0, maxLength);
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
public static insertAt(str: string, insertValue: string, index: number) {
|
||||
return [str.slice(0, index), insertValue, str.slice(index)].join('');
|
||||
}
|
||||
public static replaceAll(str: string, find: string, replace: string) {
|
||||
return str.replace(new RegExp(find, 'g'), replace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
export class TextareaUtils {
|
||||
|
||||
public static autoExpand(field: HTMLTextAreaElement) {
|
||||
//
|
||||
if (field) {
|
||||
// Reset field height
|
||||
field.style.height = '0px';
|
||||
const computed = window.getComputedStyle(field);
|
||||
// Calculate the height
|
||||
var height = 0
|
||||
+ parseInt(computed.getPropertyValue('border-top-width'), 10)
|
||||
+ field.scrollHeight
|
||||
+ parseInt(computed.getPropertyValue('border-bottom-width'), 10);
|
||||
|
||||
field.style.height = height + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
public static isEditingKeyPress(e: KeyboardEvent) {
|
||||
|
||||
if ([46, 8, 9, 27, 13, 190].indexOf(e.keyCode) !== -1 ||
|
||||
// Allow: Ctrl+A
|
||||
(e.keyCode === 65 && (e.ctrlKey || e.metaKey)) ||
|
||||
// Allow: Ctrl+C
|
||||
(e.keyCode === 67 && (e.ctrlKey || e.metaKey)) ||
|
||||
// Allow: Ctrl+V
|
||||
(e.keyCode === 86 && (e.ctrlKey || e.metaKey)) ||
|
||||
// Allow: Ctrl+X
|
||||
(e.keyCode === 88 && (e.ctrlKey || e.metaKey)) ||
|
||||
// Allow: page up, page down, home, end, left, right
|
||||
(e.keyCode >= 33 && e.keyCode <= 39)) {
|
||||
// let it happen, don't do anything
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof e.which == "undefined") {
|
||||
// This is IE, which only fires keypress events for printable keys
|
||||
return true;
|
||||
} else if (e.ctrlKey && e.key.toUpperCase() == 'V') {
|
||||
return true;
|
||||
}
|
||||
else if (!e.ctrlKey && !e.metaKey && !e.altKey && e.code != 'Tab' && e.key != 'Control') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
export class TimerUtils {
|
||||
|
||||
// private static debounceTimers: DebounceTimer[];
|
||||
|
||||
// private static addDebounceTimer(key: string, debounceTime: number, callback: Function) {
|
||||
// if (!this.debounceTimers) {
|
||||
// this.debounceTimers = [];
|
||||
// }
|
||||
// let timerProfile = this.debounceTimers.find(t => t.key == key);
|
||||
// if (timerProfile) {
|
||||
// clearTimeout(timerProfile.timer);
|
||||
// } else {
|
||||
// timerProfile = new DebounceTimer(){
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
export class DebounceTimer {
|
||||
|
||||
constructor(
|
||||
debounceTime: number,
|
||||
callback: Function
|
||||
) {
|
||||
//this.key = key
|
||||
this.debounceTime = debounceTime;
|
||||
this.callback = callback;
|
||||
//this.resetTimer();
|
||||
}
|
||||
|
||||
key: string;
|
||||
debounceTime: number;
|
||||
timer: any;
|
||||
callback: Function;
|
||||
resetTimer() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
this.timer = setTimeout(() => {
|
||||
this.callback();
|
||||
this.timer = null;
|
||||
}, this.debounceTime);
|
||||
}
|
||||
clearOut() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
export class UuidUtils {
|
||||
public static generate() {
|
||||
var d = new Date().getTime();//Timestamp
|
||||
var d2 = (performance && performance.now && (performance.now()*1000)) || 0;//Time in microseconds since page-load or 0 if unsupported
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random() * 16;//random number between 0 and 16
|
||||
if(d > 0){//Use timestamp until depleted
|
||||
r = (d + r)%16 | 0;
|
||||
d = Math.floor(d/16);
|
||||
} else {//Use microseconds since page-load if supported
|
||||
r = (d2 + r)%16 | 0;
|
||||
d2 = Math.floor(d2/16);
|
||||
}
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user