12921 lines
282 KiB
Plaintext
12921 lines
282 KiB
Plaintext
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\jalali-moment.d.ts
|
||
|
||
declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, strict?: boolean): moment.Moment;
|
||
declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, language?: string, strict?: boolean): moment.Moment;
|
||
|
||
declare namespace moment {
|
||
type RelativeTimeKey = 's' | 'm' | 'mm' | 'h' | 'hh' | 'd' | 'dd' | 'M' | 'MM' | 'y' | 'yy';
|
||
type CalendarKey = 'sameDay' | 'nextDay' | 'lastDay' | 'nextWeek' | 'lastWeek' | 'sameElse' | string;
|
||
type LongDateFormatKey = 'LTS' | 'LT' | 'L' | 'LL' | 'LLL' | 'LLLL' | 'lts' | 'lt' | 'l' | 'll' | 'lll' | 'llll';
|
||
|
||
interface Locale {
|
||
[key: string]: any;
|
||
calendar(key?: CalendarKey, m?: Moment, now?: Moment): string;
|
||
|
||
longDateFormat(key: LongDateFormatKey): string;
|
||
invalidDate(): string;
|
||
ordinal(n: number): string;
|
||
|
||
preparse(inp: string): string;
|
||
postformat(inp: string): string;
|
||
relativeTime(n: number, withoutSuffix: boolean,
|
||
key: RelativeTimeKey, isFuture: boolean): string;
|
||
pastFuture(diff: number, absRelTime: string): string;
|
||
set(config: Object): void;
|
||
|
||
months(): string[];
|
||
jMonths(): string[];
|
||
|
||
months(m: Moment, format?: string): string;
|
||
jMonths(m: Moment): string;
|
||
monthsShort(): string[];
|
||
jMonthsShort():string[];
|
||
monthsShort(m: Moment, format?: string): string;
|
||
jMonthsParse(monthName: string): number;
|
||
monthsParse(monthName: string, format: string, strict: boolean): number;
|
||
monthsRegex(strict: boolean): RegExp;
|
||
monthsShortRegex(strict: boolean): RegExp;
|
||
|
||
week(m: Moment): number;
|
||
firstDayOfYear(): number;
|
||
firstDayOfWeek(): number;
|
||
|
||
weekdays(): string[];
|
||
weekdays(m: Moment, format?: string): string;
|
||
weekdaysMin(): string[];
|
||
weekdaysMin(m: Moment): string;
|
||
weekdaysShort(): string[];
|
||
weekdaysShort(m: Moment): string;
|
||
weekdaysParse(weekdayName: string, format: string, strict: boolean): number;
|
||
weekdaysRegex(strict: boolean): RegExp;
|
||
weekdaysShortRegex(strict: boolean): RegExp;
|
||
weekdaysMinRegex(strict: boolean): RegExp;
|
||
|
||
isPM(input: string): boolean;
|
||
meridiem(hour: number, minute: number, isLower: boolean): string;
|
||
}
|
||
|
||
interface StandaloneFormatSpec {
|
||
format: string[];
|
||
standalone: string[];
|
||
isFormat?: RegExp;
|
||
}
|
||
|
||
interface WeekSpec {
|
||
dow: number;
|
||
doy: number;
|
||
}
|
||
|
||
type CalendarSpecVal = string | ((m?: MomentInput, now?: Moment) => string);
|
||
interface CalendarSpec {
|
||
sameDay?: CalendarSpecVal;
|
||
nextDay?: CalendarSpecVal;
|
||
lastDay?: CalendarSpecVal;
|
||
nextWeek?: CalendarSpecVal;
|
||
lastWeek?: CalendarSpecVal;
|
||
sameElse?: CalendarSpecVal;
|
||
|
||
// any additional properties might be used with moment.calendarFormat
|
||
[x: string]: CalendarSpecVal | void; // undefined
|
||
}
|
||
|
||
type RelativeTimeSpecVal = (
|
||
string |
|
||
((n: number, withoutSuffix: boolean,
|
||
key: RelativeTimeKey, isFuture: boolean) => string)
|
||
);
|
||
type RelativeTimeFuturePastVal = string | ((relTime: string) => string);
|
||
|
||
interface RelativeTimeSpec {
|
||
future: RelativeTimeFuturePastVal;
|
||
past: RelativeTimeFuturePastVal;
|
||
s: RelativeTimeSpecVal;
|
||
m: RelativeTimeSpecVal;
|
||
mm: RelativeTimeSpecVal;
|
||
h: RelativeTimeSpecVal;
|
||
hh: RelativeTimeSpecVal;
|
||
d: RelativeTimeSpecVal;
|
||
dd: RelativeTimeSpecVal;
|
||
M: RelativeTimeSpecVal;
|
||
MM: RelativeTimeSpecVal;
|
||
y: RelativeTimeSpecVal;
|
||
yy: RelativeTimeSpecVal;
|
||
}
|
||
|
||
interface LongDateFormatSpec {
|
||
LTS: string;
|
||
LT: string;
|
||
L: string;
|
||
LL: string;
|
||
LLL: string;
|
||
LLLL: string;
|
||
|
||
// lets forget for a sec that any upper/lower permutation will also work
|
||
lts?: string;
|
||
lt?: string;
|
||
l?: string;
|
||
ll?: string;
|
||
lll?: string;
|
||
llll?: string;
|
||
}
|
||
|
||
type MonthWeekdayFn = (momentToFormat: Moment, format?: string) => string;
|
||
type WeekdaySimpleFn = (momentToFormat: Moment) => string;
|
||
|
||
interface LocaleSpecification {
|
||
useGregorianParser?: boolean;
|
||
months?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||
monthsShort?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||
|
||
weekdays?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||
weekdaysShort?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;
|
||
weekdaysMin?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;
|
||
|
||
meridiemParse?: RegExp;
|
||
meridiem?: (hour: number, minute: number, isLower: boolean) => string;
|
||
|
||
isPM?: (input: string) => boolean;
|
||
|
||
longDateFormat?: LongDateFormatSpec;
|
||
calendar?: CalendarSpec;
|
||
relativeTime?: RelativeTimeSpec;
|
||
invalidDate?: string;
|
||
ordinal?: (n: number) => string;
|
||
ordinalParse?: RegExp;
|
||
|
||
week?: WeekSpec;
|
||
|
||
// Allow anything: in general any property that is passed as locale spec is
|
||
// put in the locale object so it can be used by locale functions
|
||
[x: string]: any;
|
||
}
|
||
|
||
interface MomentObjectOutput {
|
||
years: number;
|
||
/* One digit */
|
||
months: number;
|
||
/* Day of the month */
|
||
date: number;
|
||
hours: number;
|
||
minutes: number;
|
||
seconds: number;
|
||
milliseconds: number;
|
||
}
|
||
|
||
interface Duration {
|
||
humanize(withSuffix?: boolean): string;
|
||
|
||
abs(): Duration;
|
||
|
||
as(units: unitOfTime.Base): number;
|
||
get(units: unitOfTime.Base): number;
|
||
|
||
milliseconds(): number;
|
||
asMilliseconds(): number;
|
||
|
||
seconds(): number;
|
||
asSeconds(): number;
|
||
|
||
minutes(): number;
|
||
asMinutes(): number;
|
||
|
||
hours(): number;
|
||
asHours(): number;
|
||
|
||
days(): number;
|
||
asDays(): number;
|
||
|
||
weeks(): number;
|
||
asWeeks(): number;
|
||
|
||
months(): number;
|
||
asMonths(): number;
|
||
|
||
years(): number;
|
||
asYears(): number;
|
||
|
||
add(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||
subtract(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||
|
||
locale(): string;
|
||
locale(locale: LocaleSpecifier): Duration;
|
||
localeData(): Locale;
|
||
|
||
toISOString(): string;
|
||
toJSON(): string;
|
||
|
||
/**
|
||
* @deprecated since version 2.8.0
|
||
*/
|
||
lang(locale: LocaleSpecifier): Moment;
|
||
/**
|
||
* @deprecated since version 2.8.0
|
||
*/
|
||
lang(): Locale;
|
||
/**
|
||
* @deprecated
|
||
*/
|
||
toIsoString(): string;
|
||
}
|
||
|
||
interface MomentRelativeTime {
|
||
future: any;
|
||
past: any;
|
||
s: any;
|
||
m: any;
|
||
mm: any;
|
||
h: any;
|
||
hh: any;
|
||
d: any;
|
||
dd: any;
|
||
M: any;
|
||
MM: any;
|
||
y: any;
|
||
yy: any;
|
||
}
|
||
|
||
interface MomentLongDateFormat {
|
||
L: string;
|
||
LL: string;
|
||
LLL: string;
|
||
LLLL: string;
|
||
LT: string;
|
||
LTS: string;
|
||
|
||
l?: string;
|
||
ll?: string;
|
||
lll?: string;
|
||
llll?: string;
|
||
lt?: string;
|
||
lts?: string;
|
||
}
|
||
|
||
interface MomentParsingFlags {
|
||
empty: boolean;
|
||
unusedTokens: string[];
|
||
unusedInput: string[];
|
||
overflow: number;
|
||
charsLeftOver: number;
|
||
nullInput: boolean;
|
||
invalidMonth: string | void; // null
|
||
invalidFormat: boolean;
|
||
userInvalidated: boolean;
|
||
iso: boolean;
|
||
parsedDateParts: any[];
|
||
meridiem: string | void; // null
|
||
}
|
||
|
||
interface MomentParsingFlagsOpt {
|
||
empty?: boolean;
|
||
unusedTokens?: string[];
|
||
unusedInput?: string[];
|
||
overflow?: number;
|
||
charsLeftOver?: number;
|
||
nullInput?: boolean;
|
||
invalidMonth?: string;
|
||
invalidFormat?: boolean;
|
||
userInvalidated?: boolean;
|
||
iso?: boolean;
|
||
parsedDateParts?: any[];
|
||
meridiem?: string;
|
||
}
|
||
|
||
interface MomentBuiltinFormat {
|
||
__momentBuiltinFormatBrand: any;
|
||
}
|
||
|
||
type MomentFormatSpecification = string | MomentBuiltinFormat | (string | MomentBuiltinFormat)[];
|
||
|
||
namespace unitOfTime {
|
||
type Base = (
|
||
"year" | "years" | "y" | "jYear" |
|
||
"month" | "months" | "M" | "jMonth" | "jmonth" |
|
||
"week" | "weeks" | "w" | "jw" |
|
||
"day" | "days" | "d" | "jDay" | "jD" |
|
||
"hour" | "hours" | "h" |
|
||
"minute" | "minutes" | "m" |
|
||
"second" | "seconds" | "s" |
|
||
"millisecond" | "milliseconds" | "ms"
|
||
);
|
||
|
||
type _quarter = "quarter" | "quarters" | "Q";
|
||
type _isoWeek = "isoWeek" | "isoWeeks" | "W";
|
||
type _date = "date" | "dates" | "D";
|
||
type DurationConstructor = Base | _quarter;
|
||
|
||
type DurationAs = Base;
|
||
|
||
type StartOf = Base | _quarter | _isoWeek | _date;
|
||
|
||
type Diff = Base | _quarter;
|
||
|
||
type MomentConstructor = Base | _date;
|
||
|
||
type All = Base | _quarter | _isoWeek | _date |
|
||
"weekYear" | "weekYears" | "gg" |
|
||
"isoWeekYear" | "isoWeekYears" | "GG" |
|
||
"dayOfYear" | "dayOfYears" | "DDD" |
|
||
"weekday" | "weekdays" | "e" |
|
||
"isoWeekday" | "isoWeekdays" | "E";
|
||
}
|
||
|
||
interface MomentInputObject {
|
||
years?: number;
|
||
year?: number;
|
||
y?: number;
|
||
|
||
months?: number;
|
||
month?: number;
|
||
M?: number;
|
||
|
||
days?: number;
|
||
day?: number;
|
||
d?: number;
|
||
|
||
dates?: number;
|
||
date?: number;
|
||
D?: number;
|
||
|
||
hours?: number;
|
||
hour?: number;
|
||
h?: number;
|
||
|
||
minutes?: number;
|
||
minute?: number;
|
||
m?: number;
|
||
|
||
seconds?: number;
|
||
second?: number;
|
||
s?: number;
|
||
|
||
milliseconds?: number;
|
||
millisecond?: number;
|
||
ms?: number;
|
||
}
|
||
|
||
interface DurationInputObject extends MomentInputObject {
|
||
quarters?: number;
|
||
quarter?: number;
|
||
Q?: number;
|
||
|
||
weeks?: number;
|
||
week?: number;
|
||
w?: number;
|
||
}
|
||
|
||
interface MomentSetObject extends MomentInputObject {
|
||
weekYears?: number;
|
||
weekYear?: number;
|
||
gg?: number;
|
||
|
||
isoWeekYears?: number;
|
||
isoWeekYear?: number;
|
||
GG?: number;
|
||
|
||
quarters?: number;
|
||
quarter?: number;
|
||
Q?: number;
|
||
|
||
weeks?: number;
|
||
week?: number;
|
||
w?: number;
|
||
|
||
isoWeeks?: number;
|
||
isoWeek?: number;
|
||
W?: number;
|
||
|
||
dayOfYears?: number;
|
||
dayOfYear?: number;
|
||
DDD?: number;
|
||
|
||
weekdays?: number;
|
||
weekday?: number;
|
||
e?: number;
|
||
|
||
isoWeekdays?: number;
|
||
isoWeekday?: number;
|
||
E?: number;
|
||
}
|
||
|
||
interface FromTo {
|
||
from: MomentInput;
|
||
to: MomentInput;
|
||
}
|
||
|
||
type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
|
||
type DurationInputArg1 = Duration | number | string | FromTo | DurationInputObject | void; // null | undefined
|
||
type DurationInputArg2 = unitOfTime.DurationConstructor;
|
||
type LocaleSpecifier = string | Moment | Duration | string[] | boolean;
|
||
|
||
interface MomentCreationData {
|
||
input: MomentInput;
|
||
format?: MomentFormatSpecification;
|
||
locale: Locale;
|
||
isUTC: boolean;
|
||
strict?: boolean;
|
||
}
|
||
|
||
interface Moment extends Object{
|
||
format(format?: string): string;
|
||
|
||
startOf(unitOfTime: unitOfTime.StartOf): Moment;
|
||
endOf(unitOfTime: unitOfTime.StartOf): Moment;
|
||
|
||
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
|
||
/**
|
||
* @deprecated reverse syntax
|
||
*/
|
||
add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;
|
||
|
||
subtract(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
|
||
/**
|
||
* @deprecated reverse syntax
|
||
*/
|
||
subtract(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;
|
||
|
||
calendar(time?: MomentInput, formats?: CalendarSpec): string;
|
||
|
||
clone(): Moment;
|
||
|
||
/**
|
||
* @return Unix timestamp in milliseconds
|
||
*/
|
||
valueOf(): number;
|
||
|
||
// current date/time in local mode
|
||
local(keepLocalTime?: boolean): Moment;
|
||
isLocal(): boolean;
|
||
|
||
// current date/time in UTC mode
|
||
utc(keepLocalTime?: boolean): Moment;
|
||
isUTC(): boolean;
|
||
/**
|
||
* @deprecated use isUTC
|
||
*/
|
||
isUtc(): boolean;
|
||
|
||
parseZone(): Moment;
|
||
isValid(): boolean;
|
||
invalidAt(): number;
|
||
|
||
hasAlignedHourOffset(other?: MomentInput): boolean;
|
||
|
||
creationData(): MomentCreationData;
|
||
parsingFlags(): MomentParsingFlags;
|
||
|
||
year(y: number): Moment;
|
||
year(): number;
|
||
jYear(y: number): Moment;
|
||
jYear():number;
|
||
/**
|
||
* @deprecated use year(y)
|
||
*/
|
||
years(y: number): Moment;
|
||
/**
|
||
* @deprecated use year()
|
||
*/
|
||
years(): number;
|
||
quarter(): number;
|
||
quarter(q: number): Moment;
|
||
quarters(): number;
|
||
quarters(q: number): Moment;
|
||
month(M: number|string): Moment;
|
||
jMonth(M: number|string): Moment;
|
||
month(): number;
|
||
jMonth(): number;
|
||
/**
|
||
* @deprecated use month(M)
|
||
*/
|
||
months(M: number|string): Moment;
|
||
/**
|
||
* @deprecated use month()
|
||
*/
|
||
months(): number;
|
||
day(d: number|string): Moment;
|
||
day(): number;
|
||
jDay(d: number|string): Moment;
|
||
jDay(): number;
|
||
days(d: number|string): Moment;
|
||
days(): number;
|
||
date(d: number): Moment;
|
||
jDate(d: number): Moment;
|
||
date(): number;
|
||
jDate(): number;
|
||
/**
|
||
* @deprecated use date(d)
|
||
*/
|
||
dates(d: number): Moment;
|
||
/**
|
||
* @deprecated use jDate(d)
|
||
*/
|
||
jDates(d: number): Moment;
|
||
/**
|
||
* @deprecated use date()
|
||
*/
|
||
dates(): number;
|
||
/**
|
||
* @deprecated use jDate()
|
||
*/
|
||
jDates():number;
|
||
|
||
hour(h: number): Moment;
|
||
hour(): number;
|
||
hours(h: number): Moment;
|
||
hours(): number;
|
||
minute(m: number): Moment;
|
||
minute(): number;
|
||
minutes(m: number): Moment;
|
||
minutes(): number;
|
||
second(s: number): Moment;
|
||
second(): number;
|
||
seconds(s: number): Moment;
|
||
seconds(): number;
|
||
millisecond(ms: number): Moment;
|
||
millisecond(): number;
|
||
milliseconds(ms: number): Moment;
|
||
milliseconds(): number;
|
||
weekday(): number;
|
||
//TODO:jweekday
|
||
weekday(d: number): Moment;
|
||
isoWeekday(): number;
|
||
isoWeekday(d: number|string): Moment;
|
||
weekYear(): number;
|
||
jWeekYear(): number;
|
||
weekYear(d: number): Moment;
|
||
jWeekYear(d: number): Moment;
|
||
isoWeekYear(): number;
|
||
isoWeekYear(d: number): Moment;
|
||
week(): number;
|
||
jWeek(): number;
|
||
week(d: number): Moment;
|
||
jWeek(d: number): Moment;
|
||
weeks(): number;
|
||
jWeeks(): number;//TODO:check it
|
||
weeks(d: number): Moment;
|
||
isoWeek(): number;
|
||
isoWeek(d: number): Moment;
|
||
isoWeeks(): number;
|
||
isoWeeks(d: number): Moment;
|
||
weeksInYear(): number;
|
||
//TODO : jWeeksInYear
|
||
isoWeeksInYear(): number;
|
||
dayOfYear(): number;
|
||
jDayOfYear(): number;
|
||
dayOfYear(d: number): Moment;
|
||
jDayOfYear(d: number): Moment;
|
||
|
||
from(inp: MomentInput, suffix?: boolean): string;
|
||
to(inp: MomentInput, suffix?: boolean): string;
|
||
fromNow(withoutSuffix?: boolean): string;
|
||
toNow(withoutPrefix?: boolean): string;
|
||
|
||
diff(b: MomentInput, unitOfTime?: unitOfTime.Diff, precise?: boolean): number;
|
||
|
||
toArray(): number[];
|
||
toDate(): Date;
|
||
toISOString(): string;
|
||
inspect(): string;
|
||
toJSON(): string;
|
||
unix(): number;
|
||
|
||
isLeapYear(): boolean;
|
||
jIsLeapYear(): boolean;
|
||
/**
|
||
* @deprecated in favor of utcOffset
|
||
*/
|
||
zone(): number;
|
||
zone(b: number|string): Moment;
|
||
utcOffset(): number;
|
||
utcOffset(b: number|string, keepLocalTime?: boolean): Moment;
|
||
isUtcOffset(): boolean;
|
||
daysInMonth(): number;
|
||
jDaysInMonth(): number;
|
||
isDST(): boolean;
|
||
|
||
zoneAbbr(): string;
|
||
zoneName(): string;
|
||
|
||
isBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||
isAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||
isSame(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||
isSameOrAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||
isSameOrBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||
isBetween(a: MomentInput, b: MomentInput, granularity?: unitOfTime.StartOf, inclusivity?: "()" | "[)" | "(]" | "[]"): boolean;
|
||
|
||
doAsGregorian(): Moment;
|
||
|
||
/**
|
||
* @deprecated as of 2.8.0, use locale
|
||
*/
|
||
lang(language: LocaleSpecifier): Moment;
|
||
/**
|
||
* @deprecated as of 2.8.0, use locale
|
||
*/
|
||
lang(): Locale;
|
||
|
||
locale(): string;
|
||
locale(locale: LocaleSpecifier): Moment;
|
||
|
||
localeData(): Locale;
|
||
|
||
/**
|
||
* @deprecated no reliable implementation
|
||
*/
|
||
isDSTShifted(): boolean;
|
||
|
||
// NOTE(constructor): Same as moment constructor
|
||
/**
|
||
* @deprecated as of 2.7.0, use moment.min/max
|
||
*/
|
||
max(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||
/**
|
||
* @deprecated as of 2.7.0, use moment.min/max
|
||
*/
|
||
max(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||
|
||
// NOTE(constructor): Same as moment constructor
|
||
/**
|
||
* @deprecated as of 2.7.0, use moment.min/max
|
||
*/
|
||
min(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||
/**
|
||
* @deprecated as of 2.7.0, use moment.min/max
|
||
*/
|
||
min(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||
|
||
get(unit: unitOfTime.All): number;
|
||
set(unit: unitOfTime.All, value: number): Moment;
|
||
set(objectLiteral: MomentSetObject): Moment;
|
||
|
||
toObject(): MomentObjectOutput;
|
||
}
|
||
|
||
export var version: string;
|
||
export var fn: Moment;
|
||
|
||
// NOTE(constructor): Same as moment constructor
|
||
export function utc(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||
export function utc(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||
|
||
export function unix(timestamp: number): Moment;
|
||
|
||
export function invalid(flags?: MomentParsingFlagsOpt): Moment;
|
||
export function isMoment(m: any): m is Moment;
|
||
export function isDate(m: any): m is Date;
|
||
export function isDuration(d: any): d is Duration;
|
||
|
||
/**
|
||
* @deprecated in 2.8.0
|
||
*/
|
||
export function lang(language?: string): string;
|
||
/**
|
||
* @deprecated in 2.8.0
|
||
*/
|
||
export function lang(language?: string, definition?: Locale): string;
|
||
|
||
export function locale(language?: string): string;
|
||
export function locale(language?: string[]): string;
|
||
export function locale(language?: string, definition?: LocaleSpecification | void): string; // null | undefined
|
||
|
||
export function localeData(key?: string | string[]): Locale;
|
||
|
||
export function duration(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||
|
||
// NOTE(constructor): Same as moment constructor
|
||
export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||
export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||
|
||
export function months(): string[];
|
||
export function months(index: number): string;
|
||
export function months(format: string): string[];
|
||
export function months(format: string, index: number): string;
|
||
export function monthsShort(): string[];
|
||
export function monthsShort(index: number): string;
|
||
export function monthsShort(format: string): string[];
|
||
export function monthsShort(format: string, index: number): string;
|
||
|
||
export function jWeekOfYear(mom: Moment, firstDayOfWeek: number, firstDayOfWeekOfYear: number): MomentInput;
|
||
export function jDaysInMonth(jMear: number, jMonth: number): number;
|
||
export function jIsLeapYear(jYear: number): boolean;
|
||
export function useJalaliSystemPrimarily(): void;
|
||
export function useJalaliSystemSecondary(): void;
|
||
export var jConvert: any;
|
||
|
||
export function from (date: string, locale: string, format?: string): Moment;
|
||
|
||
export function weekdays(): string[];
|
||
export function weekdays(index: number): string;
|
||
export function weekdays(format: string): string[];
|
||
export function weekdays(format: string, index: number): string;
|
||
export function weekdays(localeSorted: boolean): string[];
|
||
export function weekdays(localeSorted: boolean, index: number): string;
|
||
export function weekdays(localeSorted: boolean, format: string): string[];
|
||
export function weekdays(localeSorted: boolean, format: string, index: number): string;
|
||
export function weekdaysShort(): string[];
|
||
export function weekdaysShort(index: number): string;
|
||
export function weekdaysShort(format: string): string[];
|
||
export function weekdaysShort(format: string, index: number): string;
|
||
export function weekdaysShort(localeSorted: boolean): string[];
|
||
export function weekdaysShort(localeSorted: boolean, index: number): string;
|
||
export function weekdaysShort(localeSorted: boolean, format: string): string[];
|
||
export function weekdaysShort(localeSorted: boolean, format: string, index: number): string;
|
||
export function weekdaysMin(): string[];
|
||
export function weekdaysMin(index: number): string;
|
||
export function weekdaysMin(format: string): string[];
|
||
export function weekdaysMin(format: string, index: number): string;
|
||
export function weekdaysMin(localeSorted: boolean): string[];
|
||
export function weekdaysMin(localeSorted: boolean, index: number): string;
|
||
export function weekdaysMin(localeSorted: boolean, format: string): string[];
|
||
export function weekdaysMin(localeSorted: boolean, format: string, index: number): string;
|
||
|
||
export function min(...moments: MomentInput[]): Moment;
|
||
export function max(...moments: MomentInput[]): Moment;
|
||
|
||
/**
|
||
* Returns unix time in milliseconds. Overwrite for profit.
|
||
*/
|
||
export function now(): number;
|
||
|
||
export function defineLocale(language: string, localeSpec: LocaleSpecification | void): Locale; // null
|
||
export function updateLocale(language: string, localeSpec: LocaleSpecification | void): Locale; // null
|
||
|
||
export function locales(): string[];
|
||
|
||
export function normalizeUnits(unit: unitOfTime.All): string;
|
||
export function relativeTimeThreshold(threshold: string): number | boolean;
|
||
export function relativeTimeThreshold(threshold: string, limit: number): boolean;
|
||
export function relativeTimeRounding(fn: (num: number) => number): boolean;
|
||
export function relativeTimeRounding(): (num: number) => number;
|
||
export function calendarFormat(m: Moment, now: Moment): string;
|
||
|
||
/**
|
||
* Constant used to enable explicit ISO_8601 format parsing.
|
||
*/
|
||
export var ISO_8601: MomentBuiltinFormat;
|
||
|
||
export var defaultFormat: string;
|
||
export var defaultFormatUtc: string;
|
||
}
|
||
|
||
export = moment;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\public-api.ts
|
||
|
||
/*
|
||
* Public API Surface of x-framework-core
|
||
*/
|
||
|
||
//#region Classes ...
|
||
export * from './lib/classes/x-loggable';
|
||
export * from './lib/classes/x-base.service';
|
||
export * from './lib/classes/x-renderer.class';
|
||
export * from './lib/classes/x-persian-date-adapter';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Constants ...
|
||
export * from './lib/constants/x-file.enum';
|
||
export * from './lib/constants/x.constants';
|
||
export * from './lib/constants/x-crud.enum';
|
||
export * from './lib/constants/x-param.enum';
|
||
export * from './lib/constants/x-header.enum';
|
||
export * from './lib/constants/x-border.enum';
|
||
export * from './lib/constants/x-setting.resources';
|
||
export * from './lib/constants/x-exception.resources';
|
||
export * from './lib/constants/x-translation.resources';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Guards ...
|
||
export * from './lib/guards/x-can-deactivate.guard';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Models ...
|
||
export * from './lib/models/x-base-dto';
|
||
export * from './lib/models/x-grouped-data.dto';
|
||
export * from './lib/models/x-base.indexed.dto';
|
||
export {
|
||
XBehaviourEvent,
|
||
XBehaviourEventType,
|
||
} from './lib/directives/x-scroll-behavior.directive';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Tools ...
|
||
export * from './lib/tools/x-task.tools';
|
||
export * from './lib/tools/x-page.tools';
|
||
export * from './lib/tools/x-uuid-tools';
|
||
export * from './lib/tools/x-file.tools';
|
||
export * from './lib/tools/x-array.tools';
|
||
export * from './lib/tools/x-color.tools';
|
||
export * from './lib/tools/x-number.tools';
|
||
export * from './lib/tools/x-object.tools';
|
||
export * from './lib/tools/x-string.tools';
|
||
export * from './lib/tools/x-to-form-data';
|
||
export * from './lib/tools/x-formatter.tools';
|
||
export * from './lib/tools/x-date-time.tools';
|
||
export * from './lib/tools/x-exception.tools';
|
||
export * from './lib/tools/x-observable.tools';
|
||
export * from './lib/tools/x-type-detect.tools';
|
||
export * from './lib/tools/x-type-convert.tools';
|
||
export * from './lib/tools/x-type-defaults.tools';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Common Typings ...
|
||
export * from './lib/typings/x.typings';
|
||
export * from './lib/typings/x-page.typings';
|
||
export * from './lib/typings/x-query.typings';
|
||
export * from './lib/typings/x-color.typings';
|
||
export * from './lib/typings/x-storage.typings';
|
||
export * from './lib/typings/x-setting.typings';
|
||
export * from './lib/typings/x-manager.typings';
|
||
export * from './lib/typings/x-date-time.typings';
|
||
export * from './lib/typings/x-exception.typings';
|
||
export * from './lib/typings/x-translation.typings';
|
||
export * from './lib/typings/x-task-manager.typings';
|
||
export * from './lib/typings/x-notification.typings';
|
||
export * from './lib/typings/x-theme-manager.typings';
|
||
export * from './lib/typings/x-base-component.typings';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Export Directives ...
|
||
export * from './lib/directives/x-var.directive';
|
||
export * from './lib/directives/x-color.directive';
|
||
export * from './lib/directives/x-focus.directive';
|
||
export * from './lib/directives/x-render.directive';
|
||
export * from './lib/directives/x-slider.directive';
|
||
export * from './lib/directives/x-on-enter.directive';
|
||
export * from './lib/directives/x-formatter.directive';
|
||
export * from './lib/directives/x-droppable.directive';
|
||
export * from './lib/directives/x-clipboard.directive';
|
||
export * from './lib/directives/x-on-escape.directive';
|
||
export * from './lib/directives/x-file-reader.directive';
|
||
export * from './lib/directives/x-mouse-handler.directive';
|
||
export * from './lib/directives/x-focus-handler.directive';
|
||
export * from './lib/directives/x-scroll-behavior.directive';
|
||
export * from './lib/directives/x-on-outside-click.directive';
|
||
export * from './lib/directives/x-stop-click-propagation.directive';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Export Validators ...
|
||
export * from './lib/validators/x-general-validators';
|
||
export * from './lib/validators/x-valid-url.directive';
|
||
export * from './lib/validators/x-valid-email.directive';
|
||
export * from './lib/validators/x-value-match.directive';
|
||
export * from './lib/validators/x-valid-phone-number.directive';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Export Pipse ...
|
||
export * from './lib/pipes/x-as.pipe';
|
||
export * from './lib/pipes/x-log.pipe';
|
||
export * from './lib/pipes/x-formatter.pipe';
|
||
export * from './lib/pipes/x-safe-html.pipe';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Tokens ...
|
||
export * from './lib/tokens/x-injectable-tokens';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Export Config ...
|
||
export * from './lib/config/x-framework-core.config';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Module ...
|
||
export * from './lib/modules/x-directives.module';
|
||
export * from './lib/x-framework-core.module';
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\test.ts
|
||
|
||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||
|
||
import 'zone.js';
|
||
import 'zone.js/testing';
|
||
import { getTestBed } from '@angular/core/testing';
|
||
import {
|
||
BrowserDynamicTestingModule,
|
||
platformBrowserDynamicTesting
|
||
} from '@angular/platform-browser-dynamic/testing';
|
||
|
||
declare const require: {
|
||
context(path: string, deep?: boolean, filter?: RegExp): {
|
||
keys(): string[];
|
||
<T>(id: string): T;
|
||
};
|
||
};
|
||
|
||
// First, initialize the Angular testing environment.
|
||
getTestBed().initTestEnvironment(
|
||
BrowserDynamicTestingModule,
|
||
platformBrowserDynamicTesting()
|
||
);
|
||
// Then we find all the tests.
|
||
const context = require.context('./', true, /\.spec\.ts$/);
|
||
// And load the modules.
|
||
context.keys().map(context);
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\x-framework-core.module.ts
|
||
|
||
import { NgModule } from '@angular/core';
|
||
import { IonicModule } from '@ionic/angular'
|
||
import { CommonModule } from '@angular/common';
|
||
import { XDirectivesModule } from './modules/x-directives.module';
|
||
import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
|
||
import { XHammerGestureConfig } from './classes/x-hammer-gesture-config';
|
||
|
||
@NgModule({
|
||
declarations: [],
|
||
providers: [
|
||
//
|
||
// Gesture Config ...
|
||
{
|
||
provide: HAMMER_GESTURE_CONFIG,
|
||
useClass: XHammerGestureConfig,
|
||
},
|
||
],
|
||
imports: [CommonModule, IonicModule, XDirectivesModule],
|
||
exports: [CommonModule, IonicModule, XDirectivesModule],
|
||
})
|
||
export class XFrameworkCoreModule {}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\classes\x-base.service.ts
|
||
|
||
import { XLoggable } from './x-loggable';
|
||
|
||
export abstract class XBaseService extends XLoggable {
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\classes\x-hammer-gesture-config.ts
|
||
|
||
import { Injectable } from '@angular/core';
|
||
import { HammerGestureConfig } from '@angular/platform-browser';
|
||
|
||
@Injectable()
|
||
export class XHammerGestureConfig extends HammerGestureConfig {
|
||
public overrides = <any> {
|
||
pinch: {
|
||
enable: false
|
||
},
|
||
rotate: {
|
||
enable: false
|
||
},
|
||
swipe: {
|
||
direction: 6
|
||
}
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\classes\x-loggable.ts
|
||
|
||
import {
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString
|
||
} from '../tools/x-type-detect.tools';
|
||
import { Inject } from '@angular/core';
|
||
import { X_FRAMEWORK_CORE_CONFIG } from '../tokens/x-injectable-tokens';
|
||
import { XFrameworkCoreConfig } from '../config/x-framework-core.config';
|
||
|
||
export enum XLogType {
|
||
Warn,
|
||
Error,
|
||
Debug,
|
||
Info
|
||
}
|
||
|
||
export interface GetLogTag {
|
||
getLogTag(): string;
|
||
}
|
||
|
||
export abstract class XLoggable implements GetLogTag {
|
||
//
|
||
// Constructor ...
|
||
constructor(
|
||
@Inject(X_FRAMEWORK_CORE_CONFIG) public config: XFrameworkCoreConfig
|
||
) {}
|
||
|
||
//
|
||
// GetLogTag Implementation ...
|
||
/**
|
||
* retrieve logging tag ...
|
||
*/
|
||
getLogTag(): string {
|
||
//
|
||
if (this.constructor) {
|
||
return `${this.config.baseLogTag}_[${this.constructor.name}]`;
|
||
}
|
||
|
||
//
|
||
return `${this.config.baseLogTag}_[NON-Constructor]`;
|
||
}
|
||
|
||
protected log(type: XLogType, message?: any, ...args: any[]) {
|
||
//
|
||
if (!this.config.enableLogging) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
let logMsg = !isNullOrEmptyString(message)
|
||
? this.getLogTag() + ' => ' + message
|
||
: this.getLogTag();
|
||
|
||
//
|
||
const logArgs = args;
|
||
args.push(new Date());
|
||
|
||
//
|
||
switch (type) {
|
||
case XLogType.Debug:
|
||
//
|
||
logMsg = 'D: ' + logMsg;
|
||
|
||
//
|
||
isNullOrUndefined(logArgs)
|
||
? // tslint:disable-next-line:no-console
|
||
console.debug(logMsg)
|
||
: // tslint:disable-next-line:no-console
|
||
console.debug(logMsg, logArgs);
|
||
break;
|
||
|
||
case XLogType.Error:
|
||
//
|
||
logMsg = 'E: ' + logMsg;
|
||
|
||
//
|
||
isNullOrUndefined(logArgs)
|
||
? console.error(logMsg)
|
||
: console.error(logMsg, logArgs);
|
||
break;
|
||
|
||
case XLogType.Warn:
|
||
//
|
||
logMsg = 'W: ' + logMsg;
|
||
|
||
//
|
||
isNullOrUndefined(logArgs)
|
||
? console.warn(logMsg)
|
||
: console.warn(logMsg, logArgs);
|
||
break;
|
||
|
||
case XLogType.Info:
|
||
//
|
||
logMsg = 'I: ' + logMsg;
|
||
|
||
//
|
||
isNullOrUndefined(logArgs)
|
||
? // tslint:disable-next-line:no-console
|
||
console.info(logMsg)
|
||
: // tslint:disable-next-line:no-console
|
||
console.info(logMsg, logArgs);
|
||
break;
|
||
}
|
||
}
|
||
|
||
protected logDebug(message?: any, ...args: any) {
|
||
this.log(XLogType.Debug, message, args);
|
||
}
|
||
|
||
protected logError(message?: any, ...args: any) {
|
||
this.log(XLogType.Error, message, args);
|
||
}
|
||
|
||
protected logWarn(message?: any, ...args: any) {
|
||
this.log(XLogType.Warn, message, args);
|
||
}
|
||
|
||
protected logInfo(message?: any, ...args: any) {
|
||
this.log(XLogType.Info, message, args);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\classes\x-persian-date-adapter.ts
|
||
|
||
import * as moment_ from 'jalali-moment';
|
||
const moment = moment_;
|
||
import {
|
||
MomentDateAdapter,
|
||
MAT_MOMENT_DATE_FORMATS,
|
||
} from '@angular/material-moment-adapter';
|
||
import { XParam } from '../constants/x-param.enum';
|
||
import { DateAdapter } from '@angular/material/core';
|
||
import { applyLocale, XLocale } from '../typings/x-translation.typings';
|
||
import { toPersianNumbers } from '../tools/x-string.tools';
|
||
import { localeData, Moment, isMoment, invalid } from 'jalali-moment';
|
||
import { isString } from '../tools/x-type-detect.tools';
|
||
|
||
export const PERSIAN_DATE_FORMATS = {
|
||
parse: {
|
||
dateInput: 'jYYYY/jMM/jDD',
|
||
},
|
||
display: {
|
||
dateInput: 'jYYYY/jMM/jDD',
|
||
monthYearLabel: 'jYYYY jMMMM',
|
||
dateA11yLabel: 'jYYYY/jMM/jDD',
|
||
monthYearA11yLabel: 'jYYYY jMMMM',
|
||
},
|
||
};
|
||
|
||
export class XPersianDateAdapter extends DateAdapter<Moment> {
|
||
//
|
||
private mLocale: XLocale = 'fa-IR';
|
||
|
||
constructor() {
|
||
super();
|
||
super.setLocale(this.mLocale);
|
||
}
|
||
|
||
getYear(date: Moment): number {
|
||
return this.clone(date).jYear();
|
||
}
|
||
|
||
getMonth(date: Moment): number {
|
||
return this.clone(date).jMonth();
|
||
}
|
||
|
||
getDate(date: Moment): number {
|
||
return this.clone(date).jDate();
|
||
}
|
||
|
||
getDayOfWeek(date: Moment): number {
|
||
return this.clone(date).day();
|
||
}
|
||
|
||
getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
|
||
//
|
||
const jLocalData = localeData(this.mLocale);
|
||
|
||
//
|
||
switch (style) {
|
||
case 'long':
|
||
case 'short':
|
||
return jLocalData._jMonths.slice(0);
|
||
case 'narrow':
|
||
return jLocalData._jMonthsShort.slice(0);
|
||
}
|
||
}
|
||
|
||
getDateNames(): string[] {
|
||
const valuesArray = Array(31);
|
||
for (let i = 0; i < 31; i++) {
|
||
valuesArray[i] = toPersianNumbers(String(i + 1));
|
||
}
|
||
return valuesArray;
|
||
}
|
||
|
||
getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
|
||
switch (style) {
|
||
case 'long':
|
||
return localeData(this.mLocale).weekdays().slice(0);
|
||
case 'short':
|
||
return localeData(this.mLocale).weekdaysShort().slice(0);
|
||
case 'narrow':
|
||
return ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'];
|
||
}
|
||
}
|
||
|
||
getYearName(date: Moment): string {
|
||
return toPersianNumbers(this.clone(date).jYear().toString());
|
||
}
|
||
|
||
getFirstDayOfWeek(): number {
|
||
return localeData(this.mLocale).firstDayOfWeek();
|
||
}
|
||
|
||
getNumDaysInMonth(date: Moment): number {
|
||
return this.clone(date).jDaysInMonth();
|
||
}
|
||
|
||
clone(date: Moment | Date | string | any): Moment {
|
||
//
|
||
const isDateMoment = moment.isMoment(date);
|
||
if (!isDateMoment) {
|
||
date = moment(new Date(date));
|
||
}
|
||
|
||
//
|
||
let result: Moment;
|
||
|
||
//
|
||
try {
|
||
result = date.clone().locale(this.mLocale);
|
||
} catch {
|
||
//
|
||
result = this.today().clone().locale(this.mLocale);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
createDate(year: number, month: number, date: number): Moment {
|
||
if (month < 0 || month > 11) {
|
||
throw Error(
|
||
`Invalid month index "${month}". Month index has to be between 0 and 11.`
|
||
);
|
||
}
|
||
if (date < 1) {
|
||
throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
|
||
}
|
||
const result = moment()
|
||
.jYear(year)
|
||
.jMonth(month)
|
||
.jDate(date)
|
||
.hours(0)
|
||
.minutes(0)
|
||
.seconds(0)
|
||
.milliseconds(0)
|
||
.locale(this.mLocale);
|
||
|
||
if (this.getMonth(result) !== month) {
|
||
throw Error(`Invalid date ${date} for month with index ${month}.`);
|
||
}
|
||
if (!result.isValid()) {
|
||
throw Error(`Invalid date "${date}" for month with index "${month}".`);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
today(): Moment {
|
||
return moment().locale(this.mLocale);
|
||
}
|
||
|
||
parse(value: any, parseFormat: string | string[]): Moment | null {
|
||
if (value && typeof value === 'string') {
|
||
return moment(value, parseFormat, this.mLocale);
|
||
}
|
||
return value ? moment(value).locale(this.mLocale) : null;
|
||
}
|
||
|
||
format(date: Moment | Date | string | any, displayFormat: string): string {
|
||
//
|
||
if (isString(date)) {
|
||
date = applyLocale(date.toString(), 'en-US');
|
||
}
|
||
|
||
//
|
||
date = this.clone(date);
|
||
|
||
//
|
||
if (!this.isValid(date)) {
|
||
throw Error('JalaliMomentDateAdapter: Cannot format invalid date.');
|
||
}
|
||
|
||
//
|
||
try {
|
||
return applyLocale(date.format(displayFormat), this.mLocale);
|
||
} catch {
|
||
return applyLocale(this.today().format(displayFormat), this.mLocale);
|
||
}
|
||
}
|
||
|
||
addCalendarYears(date: Moment, years: number): Moment {
|
||
return this.clone(date).add(years, 'jYear');
|
||
}
|
||
|
||
addCalendarMonths(date: Moment, months: number): Moment {
|
||
return this.clone(date).add(months, 'jmonth');
|
||
}
|
||
|
||
addCalendarDays(date: Moment, days: number): Moment {
|
||
return this.clone(date).add(days, 'jDay');
|
||
}
|
||
|
||
toIso8601(date: Moment): string {
|
||
return this.clone(date).format();
|
||
}
|
||
|
||
isDateInstance(obj: any): boolean {
|
||
return isMoment(obj);
|
||
}
|
||
|
||
isValid(date: Moment): boolean {
|
||
return this.clone(date).isValid();
|
||
}
|
||
|
||
invalid(): Moment {
|
||
return invalid();
|
||
}
|
||
|
||
deserialize(value: any): Moment | null {
|
||
let date;
|
||
if (value instanceof Date) {
|
||
date = moment(value);
|
||
}
|
||
if (typeof value === 'string') {
|
||
if (!value) {
|
||
return null;
|
||
}
|
||
date = moment(value).locale(this.mLocale);
|
||
}
|
||
if (date && this.isValid(date)) {
|
||
return date;
|
||
}
|
||
return super.deserialize(value);
|
||
}
|
||
}
|
||
|
||
export const DateAdapterFactory = (matDateLocale: XLocale) => {
|
||
//
|
||
if (matDateLocale === 'fa-IR') {
|
||
return new XPersianDateAdapter();
|
||
}
|
||
|
||
//
|
||
return new MomentDateAdapter(matDateLocale);
|
||
};
|
||
|
||
export const MatDateFormatFactory = (matDateLocale: XLocale) => {
|
||
//
|
||
if (matDateLocale === 'fa-IR') {
|
||
return PERSIAN_DATE_FORMATS;
|
||
}
|
||
|
||
//
|
||
return MAT_MOMENT_DATE_FORMATS;
|
||
};
|
||
|
||
export const LocaleFactory = () => {
|
||
return window[XParam.Language];
|
||
};
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\classes\x-renderer.class.ts
|
||
|
||
import {
|
||
NgZone,
|
||
Inject,
|
||
Renderer2,
|
||
ElementRef,
|
||
RendererStyleFlags2,
|
||
} from '@angular/core';
|
||
import { Observable } from 'rxjs';
|
||
import {
|
||
isFunction,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from '../tools/x-type-detect.tools';
|
||
import { XLoggable } from './x-loggable';
|
||
import { hasChild } from '../tools/x-array.tools';
|
||
import { ViewportRuler } from '@angular/cdk/overlay';
|
||
import { XRef, XStandardType } from '../typings/x.typings';
|
||
import { XCssProperties } from '../typings/x-setting.typings';
|
||
import { toObservable, toPromise } from '../tools/x-observable.tools';
|
||
import { X_FRAMEWORK_CORE_CONFIG } from '../tokens/x-injectable-tokens';
|
||
import { XFrameworkCoreConfig } from '../config/x-framework-core.config';
|
||
import { waitForXElement } from '../tools/x-object.tools';
|
||
|
||
export class XRenderer extends XLoggable {
|
||
//
|
||
//#endregion Props ...
|
||
private PREFIX = '--';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Constructor ...
|
||
constructor(
|
||
@Inject(X_FRAMEWORK_CORE_CONFIG) public config: XFrameworkCoreConfig,
|
||
public element: ElementRef,
|
||
public renderer: Renderer2,
|
||
public ruler: ViewportRuler,
|
||
public ngZone: NgZone
|
||
) {
|
||
super(config);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Document ...
|
||
getElementById(id: string) {
|
||
return document.getElementById(id);
|
||
}
|
||
|
||
getElementsByClassName(className: string) {
|
||
return document.getElementsByClassName(className);
|
||
}
|
||
|
||
getElementsByName(elementName: string) {
|
||
return document.getElementsByName(elementName);
|
||
}
|
||
|
||
getElementsByTagName<K extends keyof HTMLElementTagNameMap>(
|
||
tagName: K | string
|
||
) {
|
||
return document.getElementsByTagName(tagName);
|
||
}
|
||
|
||
getRootNode() {
|
||
return document.getRootNode();
|
||
}
|
||
|
||
waitForElement(selector: string) {
|
||
return waitForXElement(selector);
|
||
}
|
||
|
||
querySelector<K extends keyof HTMLElementTagNameMap>(selector: K | string) {
|
||
return document.querySelector(selector);
|
||
}
|
||
|
||
querySelectorAll<K extends keyof HTMLElementTagNameMap>(
|
||
selector: K | string
|
||
) {
|
||
return document.querySelectorAll(selector);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Renderer ...
|
||
/**
|
||
* convert an element to HTML Element
|
||
* for accessing props ...
|
||
*
|
||
* @param el elementRef of the selected element
|
||
*/
|
||
getElement(el?: ElementRef | HTMLElement) {
|
||
//
|
||
if (!el) {
|
||
el = this.element;
|
||
}
|
||
|
||
//
|
||
return el instanceof ElementRef
|
||
? ((el as ElementRef).nativeElement as HTMLElement)
|
||
: (el as HTMLElement);
|
||
}
|
||
|
||
/**
|
||
* adding classes to an element ...
|
||
*
|
||
* @param clz the classes names
|
||
* @param el the element
|
||
*/
|
||
addClass(clz: string, el?: ElementRef | HTMLElement) {
|
||
this.renderer.addClass(this.getElement(el), clz);
|
||
}
|
||
|
||
/**
|
||
* remove classes from an element ...
|
||
*
|
||
* @param clz the classes names
|
||
* @param el the element
|
||
*/
|
||
removeClass(clz: string, el?: ElementRef | HTMLElement) {
|
||
this.renderer.removeClass(this.getElement(el), clz);
|
||
}
|
||
|
||
/**
|
||
* create an element ...
|
||
*
|
||
* @param name create an element
|
||
* @param nameSpace adding a namespace
|
||
*/
|
||
createElement(name: string, nameSpace?: string) {
|
||
return this.renderer.createElement(name, nameSpace);
|
||
}
|
||
|
||
/**
|
||
* create a Text Element ...
|
||
*
|
||
* @param value a text value
|
||
*/
|
||
createText(value: string) {
|
||
return this.renderer.createText(value);
|
||
}
|
||
|
||
/**
|
||
* adding a child element to another element ...
|
||
*
|
||
* @param parent the parent element
|
||
* @param newChild the child element
|
||
*/
|
||
appendChild(parent: any, newChild: any) {
|
||
this.renderer.appendChild(parent, newChild);
|
||
}
|
||
|
||
/**
|
||
* adding a child element to another element ...
|
||
*
|
||
* @param child child element
|
||
* @param el parent element
|
||
*/
|
||
appendChildToElement(child: any, el?: ElementRef | HTMLElement) {
|
||
this.renderer.appendChild(this.getElement(el), child);
|
||
}
|
||
|
||
/**
|
||
* set an attribute of an element ...
|
||
*
|
||
* @param name attribute name
|
||
* @param value attribute value
|
||
* @param el destination element
|
||
* @param namespace name space name
|
||
*/
|
||
setAttribute(
|
||
name: string,
|
||
value: string,
|
||
el?: ElementRef | HTMLElement,
|
||
namespace?: string | null
|
||
) {
|
||
this.renderer.setAttribute(this.getElement(el), name, value, namespace);
|
||
}
|
||
|
||
/**
|
||
* remove an attribute from an element ...
|
||
*
|
||
* @param name attribute name
|
||
* @param el destination element
|
||
* @param namespace name space name
|
||
*/
|
||
removeAttribute(
|
||
name: string,
|
||
el?: ElementRef | HTMLElement,
|
||
namespace?: string | null
|
||
) {
|
||
this.renderer.removeAttribute(this.getElement(el), name, namespace);
|
||
}
|
||
|
||
/**
|
||
* set style of an element ...
|
||
*
|
||
* @param style the style name
|
||
* @param value style value
|
||
* @param el destination element
|
||
* @param flags flags
|
||
*/
|
||
setStyle(
|
||
style: string,
|
||
value: any,
|
||
el?: ElementRef | HTMLElement,
|
||
flags?: RendererStyleFlags2
|
||
) {
|
||
this.renderer.setStyle(this.getElement(el), style, value, flags);
|
||
}
|
||
|
||
/**
|
||
* remove an style from an element
|
||
*
|
||
* @param style style name
|
||
* @param el destination element
|
||
* @param flags flags
|
||
*/
|
||
removeStyle(
|
||
style: string,
|
||
el?: ElementRef | HTMLElement,
|
||
flags?: RendererStyleFlags2
|
||
) {
|
||
this.renderer.removeStyle(this.getElement(el), style, flags);
|
||
}
|
||
|
||
/**
|
||
* set property to an element ...
|
||
*
|
||
* @param name property name
|
||
* @param value property value
|
||
* @param el destination element
|
||
*/
|
||
setProperty(name: string, value: any, el?: ElementRef | HTMLElement) {
|
||
this.renderer.setProperty(this.getElement(el), name, value);
|
||
}
|
||
|
||
/**
|
||
* set value of specific node
|
||
*
|
||
* @param node specific element
|
||
* @param value value
|
||
*/
|
||
setValue(node: any, value: string) {
|
||
this.renderer.setValue(node, value);
|
||
}
|
||
|
||
/**
|
||
* recieve computed style of an element ...
|
||
*
|
||
* @param el destination element
|
||
*/
|
||
getComputedStyle(el?: ElementRef | HTMLElement) {
|
||
return getComputedStyle(this.getElement(el));
|
||
}
|
||
|
||
/**
|
||
* prepare a css var name
|
||
*
|
||
* @param key css variable name
|
||
*/
|
||
prepareCssKey(key: XCssProperties) {
|
||
return `${this.PREFIX}${key}`;
|
||
}
|
||
|
||
/**
|
||
* remove css key prefix ...
|
||
*
|
||
* @param key a prepared css var ...
|
||
*/
|
||
removeCssKeyPrefix(key: XCssProperties) {
|
||
return key.replace(this.PREFIX, '');
|
||
}
|
||
|
||
/**
|
||
* read specific css var value of an element
|
||
* @param name css variable name
|
||
* @param element destination element
|
||
*/
|
||
getCssVar(name: XCssProperties, el?: ElementRef | HTMLElement) {
|
||
//
|
||
return this.getComputedStyle(el).getPropertyValue(this.prepareCssKey(name));
|
||
}
|
||
|
||
/**
|
||
* set css var into element ...
|
||
*
|
||
* @param name css var name
|
||
* @param value css var value
|
||
* @param elements destination element of array of elements
|
||
*/
|
||
setCssVar(
|
||
name: XCssProperties,
|
||
value: string,
|
||
el?: ElementRef | HTMLElement
|
||
) {
|
||
//
|
||
if (isNullOrEmptyString(name)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.getElement(el).style.setProperty(this.prepareCssKey(name), value);
|
||
}
|
||
|
||
/**
|
||
* load script and add to component dynamically ...
|
||
*
|
||
* @param path path to js file
|
||
*/
|
||
addScript(path: string) {
|
||
//
|
||
const s = this.renderer.createElement('script');
|
||
s.type = 'text/javascript';
|
||
s.src = path;
|
||
s.text = ``;
|
||
this.renderer.appendChild(document.body, s);
|
||
}
|
||
|
||
/**
|
||
* add script content ...
|
||
*
|
||
* @param script the script block
|
||
*/
|
||
addScriptContent(script: string) {
|
||
//
|
||
const s = this.renderer.createElement('script');
|
||
s.type = 'text/javascript';
|
||
s.text = `${script}`;
|
||
this.renderer.appendChild(document.body, s);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Providers ...
|
||
public getElementBoundaryRect(el?: ElementRef | HTMLElement) {
|
||
return this.getElement(el).getBoundingClientRect();
|
||
}
|
||
|
||
public getElementBoundaryWidth(el?: ElementRef | HTMLElement) {
|
||
return this.getElementBoundaryRect().width;
|
||
}
|
||
|
||
public getElementBoundaryHeight(el?: ElementRef | HTMLElement) {
|
||
return this.getElementBoundaryRect().height;
|
||
}
|
||
|
||
public getElementClientWidth(el?: ElementRef | HTMLElement) {
|
||
return this.getElement(el).clientWidth;
|
||
}
|
||
|
||
public getElementClientHeight(el?: ElementRef | HTMLElement) {
|
||
return this.getElement(el).clientHeight;
|
||
}
|
||
|
||
public getElementOffsetWidth(el?: ElementRef | HTMLElement) {
|
||
return this.getElement(el).offsetWidth;
|
||
}
|
||
|
||
public getElementOffsetHeight(el?: ElementRef | HTMLElement) {
|
||
return this.getElement(el).offsetHeight;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Zone Actions ...
|
||
run<T>(fn: (...args: any[]) => T, applyThis?: any, applyArgs?: any[]): T {
|
||
return this.ngZone.run(fn, applyThis, applyArgs);
|
||
}
|
||
|
||
runTask<T>(
|
||
fn: (...args: any[]) => T,
|
||
applyThis?: any,
|
||
applyArgs?: any[],
|
||
name?: string
|
||
): T {
|
||
return this.ngZone.runTask(fn, applyThis, applyArgs, name);
|
||
}
|
||
|
||
runGuarded<T>(
|
||
fn: (...args: any[]) => T,
|
||
applyThis?: any,
|
||
applyArgs?: any[]
|
||
): T {
|
||
return this.ngZone.runGuarded(fn, applyThis, applyArgs);
|
||
}
|
||
|
||
runOutsideAngular<T>(fn: (...args: any[]) => T): T {
|
||
return this.ngZone.runOutsideAngular(fn);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Action Runnings ...
|
||
async runTimedOut<T>(
|
||
fn: (...args: any[]) => T,
|
||
delay?: XStandardType<number>
|
||
) {
|
||
//
|
||
let desiredDelay = 0;
|
||
if (!isNullOrUndefined(delay)) {
|
||
desiredDelay = await toPromise(toObservable(delay));
|
||
}
|
||
|
||
//
|
||
if (!fn) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
return await new Promise<T>((res, rej) => {
|
||
//
|
||
setTimeout(() => {
|
||
//
|
||
try {
|
||
//
|
||
const result = fn();
|
||
res(result);
|
||
} catch {
|
||
//
|
||
rej(null);
|
||
}
|
||
}, desiredDelay);
|
||
});
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Private ...
|
||
//#endregion
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\config\x-framework-core.config.ts
|
||
|
||
import { XCountryCode } from '../typings/x.typings';
|
||
import { XNotificationSound } from '../typings/x-notification.typings';
|
||
import { XLanguageDescriptor, XLocale } from '../typings/x-translation.typings';
|
||
|
||
/**
|
||
* Application Configuration Structure ...
|
||
*/
|
||
export interface XFrameworkCoreConfig {
|
||
//
|
||
// Environment Identifier ...
|
||
isProd: boolean;
|
||
|
||
//
|
||
// App Info ...
|
||
appInstanceName: string;
|
||
appNameResource: string;
|
||
appCompanyResource: string;
|
||
appVersion: string;
|
||
|
||
//
|
||
poweredValue: string;
|
||
|
||
//
|
||
// Logging Configuration ...
|
||
enableLogging: boolean;
|
||
baseLogTag: string;
|
||
|
||
//
|
||
// Language Configuration ...
|
||
availableLanguages: XLanguageDescriptor[];
|
||
defaultLanguage: XLocale;
|
||
|
||
//
|
||
// Audio Service Configurations ...
|
||
defaultNotificationDelay: number;
|
||
notificationAudioSources: XNotificationSound[];
|
||
|
||
//
|
||
// Security Service Configurations ...
|
||
secretKey: string;
|
||
|
||
//
|
||
// Image Related Configs ...
|
||
minAllowedImageSize: number;
|
||
maxAllowedImageSize: number;
|
||
allowedImageExtensions: string[];
|
||
|
||
//
|
||
// Profile Image Configs ...
|
||
maxProfileImageSize: number;
|
||
maxProfileImagesUploadFiles: number;
|
||
minAllowedImageCroppableSize: number;
|
||
|
||
//
|
||
// DCountry Code ...
|
||
defaultCountryCode: XCountryCode;
|
||
|
||
//
|
||
// Page Sizes ...
|
||
defaultPageSize: number;
|
||
pageSizes: number[];
|
||
|
||
//
|
||
// Action Delays ...
|
||
defaultActionDelay: number;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-border.enum.ts
|
||
|
||
export enum XBorderStyle {
|
||
Dotted = 'dotted',
|
||
Dashed = 'dashed',
|
||
Solid = 'solid',
|
||
Double = 'double',
|
||
Grove = 'groove',
|
||
Ridge = 'ridge',
|
||
Inset = 'inset',
|
||
Outset = 'outset',
|
||
None = 'none',
|
||
Hidden = 'hidden',
|
||
}
|
||
|
||
export type XBorderStyleIdentifier = XBorderStyle | string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-crud.enum.ts
|
||
|
||
export enum XCrudAction {
|
||
Add = 'add',
|
||
Update = 'update',
|
||
Delete = 'delete'
|
||
}
|
||
|
||
export type XCrudActionIdentifier = XCrudAction | string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-exception.resources.ts
|
||
|
||
import { XExceptionIndex } from '../typings/x-exception.typings';
|
||
|
||
export enum XExceptionIDs {
|
||
//
|
||
//#region Invalid Exceptions 1xx ...
|
||
InvalidData = 100,
|
||
InvalidDate = 101,
|
||
BadRequest = 102,
|
||
InvalidArgs = 103,
|
||
InvalidMessage = 104,
|
||
InvalidToken = 105,
|
||
InvalidVerificationCode = 106,
|
||
InvalidEmailAddress = 107,
|
||
InvalidMobileNumber = 108,
|
||
InvalidPassword = 109,
|
||
InavlidUrl = 110,
|
||
InvalidDevice = 111,
|
||
InvalidProfileImage = 112,
|
||
InavlidFile = 113,
|
||
InvalidUserName = 114,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Not (...) Exceptions 2xx ...
|
||
NotFound = 200,
|
||
NotAllowed = 201,
|
||
NotAuthorized = 202,
|
||
NotVisible = 203,
|
||
//#endregion
|
||
|
||
//
|
||
//#region User/Registration/Account/Bann Exceptions 3xx ...
|
||
AccountLockedOut = 300,
|
||
LoginFailed = 301,
|
||
UserRegisteredBefore = 302,
|
||
UserDisabled = 303,
|
||
DeviceBanned = 304,
|
||
VerificationCodeResendNotAllowed = 305,
|
||
PasswordsSame = 306,
|
||
MobilesSame = 307,
|
||
EmailsSame = 308,
|
||
MobileInUsed = 309,
|
||
EmailInUsed = 310,
|
||
MobileNotConfirmed = 311,
|
||
EmailNotConfirmed = 312,
|
||
PostBanned = 313,
|
||
UserBanned = 314,
|
||
//#endregion
|
||
|
||
//
|
||
//#region General Exceptions 4xx ...
|
||
Unknown = 400,
|
||
Duplicate = 401,
|
||
ActionFailed = 402,
|
||
ExpiredDate = 403,
|
||
Unavailable = 404,
|
||
MaxAllowedTagExceeded = 405,
|
||
Timeout = 406,
|
||
//#endregion
|
||
|
||
//
|
||
//#region File Exceptions 5xx ...
|
||
EmptyFile = 500,
|
||
MaxFileSizeExceeded = 501,
|
||
UnsupportedFileType = 502,
|
||
MaxAllowedMediaExceeded = 503,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Configuration Exceptions 6xx ...
|
||
InvalidConfiguration = 600,
|
||
StorageServiceInitialFailed = 601,
|
||
MessageServiceInitialFailed = 602,
|
||
//#endregion
|
||
|
||
//
|
||
//#region xFramework Exceptions 9xx ...
|
||
MaxAllowedFilesExceeded = 900,
|
||
MinFilesSizeExceeded = 901,
|
||
MaxFilesSizeExceeded = 902,
|
||
MustAcceptTerms = 903,
|
||
UnsupportedBrowser = 904,
|
||
PermissionDenied = 905,
|
||
PositionUnavailable = 906,
|
||
StorageNotSupported = 907,
|
||
MustLogout = 908,
|
||
InvalidLocale = 909,
|
||
InvalidUserSelector = 910,
|
||
//#endregion
|
||
}
|
||
|
||
/**
|
||
* a collection of Available Exceptions on System ...
|
||
*/
|
||
export const Exceptions: XExceptionIndex = {
|
||
//
|
||
//#region Invalid Exceptions 1xx ...
|
||
InvalidData: {
|
||
id: 100,
|
||
message: 'Invalid Data ...',
|
||
},
|
||
InvalidDate: {
|
||
id: 101,
|
||
message: 'Invalid Date ...',
|
||
},
|
||
BadRequest: {
|
||
id: 102,
|
||
message: 'Bad Request ...',
|
||
},
|
||
InvalidArgs: {
|
||
id: 103,
|
||
message: 'Invalid Args ...',
|
||
},
|
||
InvalidMessage: {
|
||
id: 104,
|
||
message: 'Invalid Message ...',
|
||
},
|
||
InvalidToken: {
|
||
id: 105,
|
||
message: 'Invalid Token ...',
|
||
},
|
||
InvalidVerificationCode: {
|
||
id: 106,
|
||
message: 'Invalid Verification Code ...',
|
||
},
|
||
InvalidEmailAddress: {
|
||
id: 107,
|
||
message: 'Invalid Email Address ...',
|
||
},
|
||
InvalidMobileNumber: {
|
||
id: 108,
|
||
message: 'Invalid Mobile Number ...',
|
||
},
|
||
InvalidPassword: {
|
||
id: 109,
|
||
message: 'Invalid Password ...',
|
||
},
|
||
InavlidUrl: {
|
||
id: 110,
|
||
message: 'Inavlid Url ...',
|
||
},
|
||
InvalidDevice: {
|
||
id: 111,
|
||
message: 'Invalid Device ...',
|
||
},
|
||
InvalidProfileImage: {
|
||
id: 112,
|
||
message: 'Invalid Profile Image ...',
|
||
},
|
||
InavlidFile: {
|
||
id: 113,
|
||
message: 'Invalid File ...',
|
||
},
|
||
InvalidUserName: {
|
||
id: 114,
|
||
message: 'Invalid Username ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region Not (...) Exceptions 2xx ...
|
||
NotFound: {
|
||
id: 200,
|
||
message: 'Not Found ...',
|
||
},
|
||
NotAllowed: {
|
||
id: 201,
|
||
message: 'Not Allowed ...',
|
||
},
|
||
NotAuthorized: {
|
||
id: 202,
|
||
message: 'Not Authorized ...',
|
||
},
|
||
NotVisible: {
|
||
id: 203,
|
||
message: 'Not Visible ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region User/Registration/Account/Bann Exceptions 3xx ...
|
||
AccountLockedOut: {
|
||
id: 300,
|
||
message: 'Account Locked out Until: (%$s)',
|
||
},
|
||
LoginFailed: {
|
||
id: 301,
|
||
message: 'Login Failed ...',
|
||
},
|
||
UserRegisteredBefore: {
|
||
id: 302,
|
||
message: 'User Registered Before ...',
|
||
},
|
||
UserDisabled: {
|
||
id: 303,
|
||
message: 'User Disabled ...',
|
||
},
|
||
DeviceBanned: {
|
||
id: 304,
|
||
message: 'Device Banned Until:(%$s)',
|
||
},
|
||
VerificationCodeResendNotAllowed: {
|
||
id: 305,
|
||
message: `You can't Request Verification code Until:(%$s)`,
|
||
},
|
||
PasswordsSame: {
|
||
id: 306,
|
||
message: 'Passwords Same ...',
|
||
},
|
||
MobilesSame: {
|
||
id: 307,
|
||
message: 'Mobiles Same ...',
|
||
},
|
||
EmailsSame: {
|
||
id: 308,
|
||
message: 'Emails Same ...',
|
||
},
|
||
MobileInUsed: {
|
||
id: 309,
|
||
message: 'Mobile In Used ...',
|
||
},
|
||
EmailInUsed: {
|
||
id: 310,
|
||
message: 'Email In Used ...',
|
||
},
|
||
MobileNotConfirmed: {
|
||
id: 311,
|
||
message: 'Mobile Not Confirmed ...',
|
||
},
|
||
EmailNotConfirmed: {
|
||
id: 312,
|
||
message: 'Email Not Confirmed ...',
|
||
},
|
||
PostBanned: {
|
||
id: 313,
|
||
message: 'Post Banned ...',
|
||
},
|
||
UserBanned: {
|
||
id: 314,
|
||
message: 'User Banned ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region General Exceptions 4xx ...
|
||
Unknown: {
|
||
id: 400,
|
||
message: 'Unknown Error ...',
|
||
},
|
||
Duplicate: {
|
||
id: 401,
|
||
message: 'Duplicate ...',
|
||
},
|
||
ActionFailed: {
|
||
id: 402,
|
||
message: 'Action Failed ...',
|
||
},
|
||
ExpiredDate: {
|
||
id: 403,
|
||
message: 'Expired Date ...',
|
||
},
|
||
Unavailable: {
|
||
id: 404,
|
||
message: 'Unavailable ...',
|
||
},
|
||
MaxAllowedTagExceeded: {
|
||
id: 405,
|
||
message: 'Max Allowed Tag Exceeded ...',
|
||
},
|
||
Timeout: {
|
||
id: 406,
|
||
message: 'Timed out ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region File Exceptions 5xx ...
|
||
EmptyFile: {
|
||
id: 500,
|
||
message: 'Empty File ...',
|
||
},
|
||
MaxFileSizeExceeded: {
|
||
id: 501,
|
||
message: 'max File size exceeded ...',
|
||
},
|
||
UnsupportedFileType: {
|
||
id: 502,
|
||
message: 'Unsupported File Type ...',
|
||
},
|
||
MaxAllowedMediaExceeded: {
|
||
id: 503,
|
||
message: 'Max Allowed Media Exceeded ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region Configuration Exceptions 6xx ...
|
||
InvalidConfiguration: {
|
||
id: 600,
|
||
message: 'Invalid Configuration ...',
|
||
},
|
||
StorageServiceInitialFailed: {
|
||
id: 601,
|
||
message: 'Storage Service Initiallization Failed ...',
|
||
},
|
||
MessageServiceInitialFailed: {
|
||
id: 602,
|
||
message: 'Message Service Initialization Failed ...',
|
||
},
|
||
//#endregion
|
||
|
||
//
|
||
//#region xFramework Exceptions 9xx ...
|
||
MaxAllowedFilesExceeded: {
|
||
id: 900,
|
||
message: 'Max Allowed Files Exceeded ...',
|
||
},
|
||
MinFilesSizeExceeded: {
|
||
id: 901,
|
||
message: 'Min Files Size not Exceeded ...',
|
||
},
|
||
MaxFilesSizeExceeded: {
|
||
id: 902,
|
||
message: 'Max Files Size Exceeded ...',
|
||
},
|
||
MustAcceptTerms: {
|
||
id: 903,
|
||
message: 'Must Accept Terms And Conditions ...',
|
||
},
|
||
UnsupportedBrowser: {
|
||
id: 904,
|
||
message: 'Browser does not support location services ...',
|
||
},
|
||
PermissionDenied: {
|
||
id: 905,
|
||
message: 'You have rejected access to your location ...',
|
||
},
|
||
PositionUnavailable: {
|
||
id: 906,
|
||
message: 'Unable to determine your location ...',
|
||
},
|
||
StorageNotSupported: {
|
||
id: 907,
|
||
message: 'Service timeout has been reached ...',
|
||
},
|
||
MustLogout: {
|
||
id: 908,
|
||
message: `logged in user's can't access to this content ...`,
|
||
},
|
||
InvalidLocale: {
|
||
id: 909,
|
||
message: 'Invalid Locale ...',
|
||
},
|
||
InvalidUserSelector: {
|
||
id: 910,
|
||
message: 'Invalid User Selector ...',
|
||
},
|
||
//#endregion
|
||
};
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-file.enum.ts
|
||
|
||
//
|
||
//#region XFile Types ...
|
||
export enum XFileType {
|
||
Image,
|
||
ProfileImage,
|
||
CoverImage,
|
||
Audio,
|
||
Video,
|
||
Document,
|
||
}
|
||
|
||
export enum XGeneralThumbnails {
|
||
UNKNOWN = 'unknown',
|
||
IMAGE = 'image',
|
||
AUDIO = 'audio',
|
||
VIDEO = 'video',
|
||
DOCUMENT = 'document',
|
||
}
|
||
|
||
export const TypesMatcher = {
|
||
IMAGE: 'image',
|
||
VIDEO: 'video',
|
||
AUDIO: 'audio',
|
||
};
|
||
//#endregion
|
||
|
||
//
|
||
//#region File Extensions ...
|
||
export enum XAudioFileExtensions {
|
||
Aif = '.aif',
|
||
Cda = '.cda',
|
||
Iff = '.iff',
|
||
Mid = '.mid',
|
||
Midi = '.midi',
|
||
Mp3 = '.mp3',
|
||
Mpa = '.mpa',
|
||
Wav = '.wav',
|
||
Wma = '.wma',
|
||
Wpl = '.wpl',
|
||
Aa = '.aa',
|
||
Aac = '.aac',
|
||
Aax = '.aax',
|
||
Act = '.act',
|
||
Aiff = '.aiff',
|
||
Alac = '.alac',
|
||
Amr = '.amr',
|
||
Ape = '.ape',
|
||
Au = '.au',
|
||
Awb = '.awb',
|
||
Dss = '.dss',
|
||
Dvf = '.dvf',
|
||
Flac = '.flac',
|
||
Gsm = '.gsm',
|
||
Iklax = '.iklax',
|
||
Ivs = '.ivs',
|
||
M4a = '.m4a',
|
||
M4b = '.m4b',
|
||
M4p = '.m4p',
|
||
Mmf = '.mmf',
|
||
Mpc = '.mpc',
|
||
Msv = '.msv',
|
||
Nmf = '.nmf',
|
||
Ogg = '.ogg',
|
||
Oga = '.oga',
|
||
Mogg = '.mogg',
|
||
Opus = '.opus',
|
||
Ra = '.ra',
|
||
Rm = '.rm',
|
||
Raw = '.raw',
|
||
Rf64 = '.rf64',
|
||
Sln = '.sln',
|
||
Tta = '.tta',
|
||
Voc = '.voc',
|
||
Vox = '.vox',
|
||
Wv = '.wv',
|
||
Eightsvx = '.8svx',
|
||
}
|
||
|
||
export enum XVideoFileExtensions {
|
||
Avi = '.avi',
|
||
Flv = '.flv',
|
||
H264 = '.h264',
|
||
M4v = '.m4v',
|
||
Mkv = '.mkv',
|
||
Mov = '.mov',
|
||
Mp4 = '.mp4',
|
||
Mpg = '.mpg',
|
||
Mpeg = '.mpeg',
|
||
Rm = '.rm',
|
||
Swf = '.swf',
|
||
Vob = '.vob',
|
||
Wmv = '.wmv',
|
||
ThreeG2 = '.3g2',
|
||
ThreeGp = '.3gp',
|
||
Webm = '.webm',
|
||
Viv = '.viv',
|
||
Gifv = '.gifv',
|
||
Svi = '.svi',
|
||
Roq = '.roq',
|
||
Rmvb = '.rmvb',
|
||
Yuv = '.yuv',
|
||
Qt = '.qt',
|
||
Ogv = '.ogv',
|
||
Ogg = '.ogg',
|
||
Nsv = '.nsv',
|
||
Mng = '.mng',
|
||
M4p = '.m4p',
|
||
M2v = '.m2v',
|
||
Mp2 = '.mp2',
|
||
Mpe = '.mpe',
|
||
Mpv = '.mpv',
|
||
Mts = '.mts',
|
||
M2ts = '.m2ts',
|
||
Mxf = '.mxf',
|
||
Gif = '.gif',
|
||
F4v = '.f4v',
|
||
F4p = '.f4p',
|
||
F4a = '.f4a',
|
||
F4b = '.f4b',
|
||
Drc = '.drc',
|
||
Amv = '.amv',
|
||
Asf = '.asf',
|
||
}
|
||
|
||
export enum XImageFileExtensions {
|
||
Ai = '.ai',
|
||
Bmp = '.bmp',
|
||
Gif = '.gif',
|
||
Jpeg = '.jpeg',
|
||
Jpg = '.jpg',
|
||
Max = '.max',
|
||
Obj = '.obj',
|
||
Png = '.png',
|
||
Ps = '.ps',
|
||
Psd = '.psd',
|
||
Svg = '.svg',
|
||
Tif = '.tif',
|
||
Tiff = '.tiff',
|
||
Threeds = '.3ds',
|
||
Threedm = '.3dm',
|
||
Ico = '.ico',
|
||
Icns = '.icns',
|
||
}
|
||
|
||
export enum XDocumentFileExtensions {
|
||
Asp = '.asp',
|
||
Aspx = '.aspx',
|
||
Cer = '.cer',
|
||
Cfm = '.cfm',
|
||
Cgi = '.cgi',
|
||
Pl = '.pl',
|
||
Cs = '.cs',
|
||
Css = '.css',
|
||
SCss = '.scss',
|
||
Htm = '.htm',
|
||
Html = '.html',
|
||
Js = '.js',
|
||
Jsp = '.jsp',
|
||
JSON = '.json',
|
||
MD = '.md',
|
||
VSCodeWorkspace = '.code-workspace',
|
||
Part = '.part',
|
||
Php = '.php',
|
||
Rss = '.rss',
|
||
Xhtml = '.xhtml',
|
||
Bak = '.bak',
|
||
Cfg = '.cfg',
|
||
Cpl = '.cpl',
|
||
Cur = '.cur',
|
||
Dll = '.dll',
|
||
Dmp = '.dmp',
|
||
Drv = '.drv',
|
||
Ini = '.ini',
|
||
Lnk = '.lnk',
|
||
Msi = '.msi',
|
||
Sys = '.sys',
|
||
Tmp = '.tmp',
|
||
Accdb = '.accdb',
|
||
Csv = '.csv',
|
||
Dat = '.dat',
|
||
Db = '.db',
|
||
Dbf = '.dbf',
|
||
Log = '.log',
|
||
Mdb = '.mdb',
|
||
Pdb = '.pdb',
|
||
Sav = '.sav',
|
||
Sql = '.sql',
|
||
Tar = '.tar',
|
||
TarGz = '.tar.gz',
|
||
Key = '.key',
|
||
Odp = '.odp',
|
||
Pps = '.pps',
|
||
Ppt = '.ppt',
|
||
Pptx = '.pptx',
|
||
Ods = '.ods',
|
||
Xlr = '.xlr',
|
||
Xls = '.xls',
|
||
Xlsx = '.xlsx',
|
||
Doc = '.doc',
|
||
Docx = '.docx',
|
||
Odt = '.odt',
|
||
Msg = '.msg',
|
||
Pdf = '.pdf',
|
||
Rtf = '.rtf',
|
||
Tex = '.tex',
|
||
Txt = '.txt',
|
||
Wks = '.wks',
|
||
Wps = '.wps',
|
||
Wpd = '.wpd',
|
||
Apk = '.apk',
|
||
Bat = '.bat',
|
||
Com = '.com',
|
||
Exe = '.exe',
|
||
Py = '.py',
|
||
Pyw = '.pyw',
|
||
Wsf = '.wsf',
|
||
Appx = '.appx',
|
||
SevenZ = '.7z',
|
||
A = '.a',
|
||
Aapkg = '.aapkg',
|
||
Ace = '.ace',
|
||
Alz = '.alz',
|
||
Bke = '.bke',
|
||
Arj = '.arj',
|
||
B = '.b',
|
||
Ba = '.ba',
|
||
Bin = '.bin',
|
||
Bz2 = '.bz2',
|
||
Xaml = '.xaml',
|
||
Deb = '.deb',
|
||
Dmg = '.dmg',
|
||
Dn = '.dn',
|
||
Egg = '.egg',
|
||
Egt = '.egt',
|
||
Ezip = '.ezip',
|
||
Ess = '.ess',
|
||
Gz = '.gz',
|
||
Ipg = '.ipg',
|
||
Jar = '.jar',
|
||
Lzh = '.lzh',
|
||
Lz = '.lz',
|
||
Lzo = '.lzo',
|
||
Lzma = '.lzma',
|
||
Mhtml = '.mhtml',
|
||
Nth = '.nth',
|
||
Oar = '.oar',
|
||
Pak = '.pak',
|
||
Par = '.par',
|
||
Par2 = '.par2',
|
||
Paf = '.paf',
|
||
Pea = '.pea',
|
||
Pyk = '.pyk',
|
||
Pk3 = '.pk3',
|
||
Pk4 = '.pk4',
|
||
Pxz = '.pxz',
|
||
Rar = '.rar',
|
||
Sis = '.sis',
|
||
Sisx = '.sisx',
|
||
Skb = '.skb',
|
||
Sq = '.sq',
|
||
Tib = '.tib',
|
||
Xap = '.xap',
|
||
Xz = '.xz',
|
||
Z = '.z',
|
||
Ts = '.ts',
|
||
Zoo = '.zoo',
|
||
Zip = '.zip',
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region File Extension Descriptions ...
|
||
export enum XAudioFileExtensionDescriptions {
|
||
Aif = 'AIF/Audio Interchange audio',
|
||
Cda = 'CD audio track',
|
||
Iff = 'Interchange File Format',
|
||
Mid = 'MIDI audio',
|
||
Midi = 'MIDI audio',
|
||
Mp3 = 'MPEG Layer III Audio',
|
||
Mpa = 'MPEG-2 audio',
|
||
Wav = 'Standard audio file container format',
|
||
Wma = 'Windows Media Audio format',
|
||
Wpl = 'Windows Media Player playlist',
|
||
Aa = 'A low-bitrate audiobook container format',
|
||
Aac = 'Advanced Audio Coding format',
|
||
Aax = 'An Audiobook format',
|
||
Act = 'lossy ADPCM 8 kbit/s compressed audio format',
|
||
Aiff = 'Apple, A standard uncompressed CD-quality, audio file format',
|
||
Alac = 'Apple, An audio coding format developed by Apple Inc',
|
||
Amr = 'AMR-NB audio, used primarily for speech',
|
||
Ape = "Monkey's Audio lossless audio compression format",
|
||
Au = 'Sun Microsystems standard audio file format',
|
||
Awb = 'AMR-WB audio, used primarily for speech',
|
||
Dss = 'Olympus proprietary format',
|
||
Dvf = 'A Sony proprietary format for compressed voice files',
|
||
Flac = 'Free Lossless Audio Codec',
|
||
Gsm = 'Designed for telephony use in Europe',
|
||
Iklax = 'iKlax Media proprietary format',
|
||
Ivs = 'Digital Rights Management developed by 3D Solar UK Ltd',
|
||
M4a = 'audio-only MPEG-4 file, used by Apple for unprotected music',
|
||
M4b = 'Audiobook / podcast extension with AAC or ALAC encoded audio in an MPEG-4 container',
|
||
M4p = 'A version of AAC with proprietary Digital Rights Management developed by Apple for use in music downloaded from their iTunes Music Store and their music streaming service known as Apple Music',
|
||
Mmf = 'Yamaha, Samsung A Samsung audio format',
|
||
Mpc = 'Musepack, an open source lossy audio codec',
|
||
Msv = 'Sony proprietary format for Memory Stick compressed voice',
|
||
Nmf = 'NICE Media Player audio',
|
||
Ogg = 'Xiph.Org Foundation A free, open source container format',
|
||
Oga = 'Xiph.Org Foundation A free, open source container format',
|
||
Mogg = 'Xiph.Org Foundation A free, open source container format',
|
||
Opus = 'lossy audio compression format developed by the Internet Engineering Task Force (IETF) and made especially suitable for interactive real-time applications over the Internet',
|
||
Ra = 'RealAudio format designed for streaming audio over the Internet',
|
||
Rm = 'RealAudio format designed for streaming audio over the Internet',
|
||
Raw = 'raw file can contain audio in any format',
|
||
Rf64 = 'One successor to the Wav format',
|
||
Sln = 'Signed Linear PCM format used by Asterisk',
|
||
Tta = 'The True Audio, real-time lossless audio codec',
|
||
Voc = 'Creative Technology The file format',
|
||
Vox = 'Adaptive Differential Pulse Code Modulation',
|
||
Wv = 'Format for wavpack',
|
||
Eightsvx = 'Electronic Arts The IFF-8SVX format for 8-bit sound samples',
|
||
}
|
||
|
||
export enum XVideoFileExtensionDescriptions {
|
||
Avi = 'Audio Video Interleave',
|
||
Flv = 'Adobe Flash Video',
|
||
H264 = 'H.264 Video',
|
||
M4v = 'Apple MP4 Video, MPEG-4 Part 12',
|
||
Mkv = 'Matroska Multimedia Container',
|
||
Mov = 'Apple QuickTime Movie',
|
||
Mp4 = 'MPEG-4 Video',
|
||
Mpg = 'MPEG Video',
|
||
Mpeg = 'MPEG Video',
|
||
Rm = 'Real Media',
|
||
Swf = 'Shockwave flash',
|
||
Vob = 'DVD Video Object',
|
||
Wmv = 'Windows Media Video',
|
||
ThreeG2 = '3GPP2 Multimedia',
|
||
ThreeGp = '3GPP multimedia',
|
||
Webm = 'Royalty-free format created for HTML5 video',
|
||
Viv = 'VivoActive based upon H.263 video',
|
||
Gifv = 'Video alternative to GIF',
|
||
Svi = 'Samsung video format for portable players',
|
||
Roq = 'used by Quake',
|
||
Rmvb = 'RealMedia Variable Bitrate',
|
||
Yuv = 'Raw video format',
|
||
Qt = 'QuickTime File Format',
|
||
Ogv = 'Ogg Video',
|
||
Ogg = 'Ogg Video',
|
||
Nsv = 'Nullsoft Streaming Video',
|
||
Mng = 'Multiple-image Network Graphics',
|
||
M4p = 'MPEG-4 Part 14',
|
||
M2v = 'MPEG-2 Part 3',
|
||
Mp2 = 'MPEG-1 Part 2',
|
||
Mpe = 'MPEG-1',
|
||
Mpv = 'MPEG-1',
|
||
Mts = 'MPEG Transport Stream',
|
||
M2ts = 'MPEG Transport Stream',
|
||
Mxf = 'Material Exchange Format',
|
||
Gif = 'Simple animation, inefficient compression',
|
||
F4v = 'Adobe Flash Video',
|
||
F4p = 'Adobe Flash Video',
|
||
F4a = 'Adobe Flash Video',
|
||
F4b = 'Adobe Flash Video',
|
||
Drc = 'Dirac',
|
||
Amv = 'Modified version of AVI',
|
||
Asf = 'Advanced Systems Format',
|
||
}
|
||
|
||
export enum XImageFileExtensionDescriptions {
|
||
Ai = 'Adobe Illustrator',
|
||
Bmp = 'Bitmap image',
|
||
Gif = 'Graphical Interchange Format',
|
||
Jpeg = 'Joints Photographic Experts Group',
|
||
Jpg = 'Joints Photographic Experts Group',
|
||
Max = '3ds Max Scene',
|
||
Obj = 'Wavefront 3D Object',
|
||
Png = 'Portable Network Graphic image',
|
||
Ps = 'PostScript',
|
||
Psd = 'Adobe Photoshop Document image',
|
||
Svg = 'Scalable Vector Graphics',
|
||
Tif = 'TIFF image',
|
||
Tiff = 'TIFF image',
|
||
Threeds = '3D Studio Scene',
|
||
Threedm = 'Rhino 3D Model',
|
||
Ico = 'Icon',
|
||
Icns = 'macOS X icon resource',
|
||
}
|
||
|
||
export enum XDocumentFileExtensionDescriptions {
|
||
Asp = 'Active Server Page',
|
||
Aspx = 'Active Server Page',
|
||
Cer = 'Internet security certificate',
|
||
Cfm = 'ColdFusion Markup',
|
||
Cgi = 'Common Gateway Interface Script',
|
||
Pl = 'Perl script',
|
||
Cs = 'C# document',
|
||
Css = 'Cascading Style Sheet',
|
||
SCss = 'Sass and Less Style Sheet',
|
||
Htm = 'Hypertext Markup Language',
|
||
Html = 'Hypertext Markup Language',
|
||
Js = 'JavaScript',
|
||
Jsp = 'Java Server Page',
|
||
JSON = 'Java Script Object Notation',
|
||
MD = 'Markdown',
|
||
VSCodeWorkspace = 'VSCode Workspace',
|
||
Part = 'Partially downloaded',
|
||
Php = 'PHP Source Code',
|
||
Rss = 'Rich Site Summary',
|
||
Xhtml = 'Extensible Hypertext Markup Language',
|
||
Bak = 'Backup',
|
||
Cfg = 'Configuration',
|
||
Cpl = 'Windows Control panel',
|
||
Cur = 'Windows cursor',
|
||
Dll = 'Dynamic Link Library',
|
||
Dmp = 'Dump',
|
||
Drv = 'Device driver',
|
||
Ini = 'Initialization',
|
||
Lnk = 'Windows shortcut',
|
||
Msi = 'Windows installer package',
|
||
Sys = 'Windows system',
|
||
Tmp = 'Temporary',
|
||
Accdb = 'Access 2007 Database',
|
||
Csv = 'Comma separated value',
|
||
Dat = 'Data',
|
||
Db = 'Database',
|
||
Dbf = 'Database',
|
||
Log = 'Log',
|
||
Mdb = 'Microsoft Access database',
|
||
Pdb = 'Program Database',
|
||
Sav = 'Save',
|
||
Sql = 'Structured Query Language database',
|
||
Tar = 'Linux / Unix tarball file archive',
|
||
TarGz = 'gzipped tar',
|
||
Key = 'Keynote presentation',
|
||
Odp = 'OpenOffice Impress presentation',
|
||
Pps = 'PowerPoint slide show',
|
||
Ppt = 'PowerPoint presentation',
|
||
Pptx = 'PowerPoint Open XML presentation',
|
||
Ods = 'OpenOffice Calc spreadsheet',
|
||
Xlr = 'Microsoft Works spreadsheet',
|
||
Xls = 'Microsoft Excel',
|
||
Xlsx = 'Microsoft Excel Open XML spreadsheet',
|
||
Doc = 'Microsoft Word',
|
||
Docx = 'Microsoft Word Open XML',
|
||
Odt = 'OpenOffice Writer document',
|
||
Msg = 'Outlook Mail Message',
|
||
Pdf = 'Portable Document Format',
|
||
Rtf = 'Rich Text Format',
|
||
Tex = 'LaTeX document',
|
||
Txt = 'Plain text',
|
||
Wks = 'Lotus 1-2-3 Spreadsheet',
|
||
Wps = 'Microsoft Works Word Processor Document',
|
||
Wpd = 'WordPerfect document',
|
||
Apk = 'Android package',
|
||
Bat = 'Batch',
|
||
Bin = 'Binary',
|
||
Com = 'MS-DOS command',
|
||
Exe = 'Executable',
|
||
Jar = 'Java Archive',
|
||
Py = 'Python',
|
||
Pyw = 'Python',
|
||
Wsf = 'Windows Script',
|
||
Appx = 'Microsoft Application Package',
|
||
SevenZ = '7-Zip compressed',
|
||
A = 'An external file extension for C/C++',
|
||
Aapkg = 'ArchestrA IDE',
|
||
Ace = 'ACE compressed',
|
||
Alz = 'ALZip compressed',
|
||
Bke = 'BackupEarth.com data compression',
|
||
Arj = 'ARJ compressed',
|
||
B = 'Similar to .a, but less compressed',
|
||
Ba = 'Scifer External Archive Type',
|
||
Bz2 = 'bzip2',
|
||
Xaml = 'Used in programs like Visual Studio to create exe files',
|
||
Deb = 'Debian install package',
|
||
Dmg = 'Apple compressed/encrypted format',
|
||
Dn = 'Adobe Dimension CC file format',
|
||
Egg = 'Alzip Egg Edition compressed',
|
||
Egt = 'EGT Universal Document',
|
||
Ezip = 'EGT Compressed Folder',
|
||
Ess = 'SmartSense',
|
||
Gz = 'Compressed',
|
||
Ipg = 'Format in which Apple Inc. packages their iPod games',
|
||
Lzh = 'Lempel, Ziv, Huffman',
|
||
Lz = 'Lempel, Ziv',
|
||
Lzo = 'Lempel, Ziv',
|
||
Lzma = 'Lempel Ziv Markov chain algorithm compressed',
|
||
Mhtml = 'Mime HTML (Hyper-Text Markup Language) code',
|
||
Nth = 'Nokia Theme Used by Nokia Series 40 Cellphones',
|
||
Oar = 'OAR archive',
|
||
Pak = 'Enhanced type of .ARC archive',
|
||
Par = 'Parchive',
|
||
Par2 = 'Parchive',
|
||
Paf = 'Portable Application File',
|
||
Pea = 'PeaZip archive',
|
||
Pyk = 'Compressed',
|
||
Pk3 = 'Quake 3 archive',
|
||
Pk4 = 'Opens similarly to a zip archive.',
|
||
Pxz = 'A compressed layered image',
|
||
Rar = 'Rar Archive',
|
||
Sis = 'Symbian Application Package',
|
||
Sisx = 'Symbian Application Package',
|
||
Skb = 'Google SketchUp backup',
|
||
Sq = 'Squish Compressed Archive',
|
||
Tib = 'Acronis True Image backup',
|
||
Xap = 'Windows Phone Application Package',
|
||
Xz = 'xz compressed files, based on LZMA/LZMA2 algorithm',
|
||
Z = 'Unix compress',
|
||
Ts = 'Typescript',
|
||
Zoo = 'based on LZW',
|
||
Zip = 'popular compression format',
|
||
}
|
||
//#endregion
|
||
|
||
export type XFileExtensions =
|
||
| XAudioFileExtensions
|
||
| XVideoFileExtensions
|
||
| XImageFileExtensions
|
||
| XDocumentFileExtensions;
|
||
|
||
export type XFileExtensionDescriptions =
|
||
| XAudioFileExtensionDescriptions
|
||
| XVideoFileExtensionDescriptions
|
||
| XImageFileExtensionDescriptions
|
||
| XDocumentFileExtensionDescriptions;
|
||
|
||
//
|
||
//#region Files Informations Constants ...
|
||
//
|
||
const XImageFileKeys = Object.keys(Object.assign({}, XImageFileExtensions));
|
||
const XImageFilesInfo = XImageFileKeys.map((ik) => {
|
||
return {
|
||
identifier: ik,
|
||
type: XFileType.Image,
|
||
typeIdentifier: XGeneralThumbnails.IMAGE,
|
||
extension: XImageFileExtensions[ik],
|
||
description: XImageFileExtensionDescriptions[ik],
|
||
};
|
||
});
|
||
|
||
//
|
||
const XAudioFileKeys = Object.keys(Object.assign({}, XAudioFileExtensions));
|
||
const XAudioFilesInfo = XAudioFileKeys.map((ik) => {
|
||
return {
|
||
identifier: ik,
|
||
type: XFileType.Audio,
|
||
typeIdentifier: XGeneralThumbnails.AUDIO,
|
||
extension: XAudioFileExtensions[ik],
|
||
description: XAudioFileExtensionDescriptions[ik],
|
||
};
|
||
});
|
||
|
||
//
|
||
const XVideoFileKeys = Object.keys(Object.assign({}, XVideoFileExtensions));
|
||
const XVideoFilesInfo = XVideoFileKeys.map((ik) => {
|
||
return {
|
||
identifier: ik,
|
||
type: XFileType.Video,
|
||
typeIdentifier: XGeneralThumbnails.VIDEO,
|
||
extension: XVideoFileExtensions[ik],
|
||
description: XVideoFileExtensionDescriptions[ik],
|
||
};
|
||
});
|
||
|
||
//
|
||
const XDocumentFileKeys = Object.keys(
|
||
Object.assign({}, XDocumentFileExtensions)
|
||
);
|
||
const XDocumentFilesInfo = XDocumentFileKeys.map((ik) => {
|
||
return {
|
||
identifier: ik,
|
||
type: XFileType.Document,
|
||
typeIdentifier: XGeneralThumbnails.DOCUMENT,
|
||
extension: XDocumentFileExtensions[ik],
|
||
description: XDocumentFileExtensionDescriptions[ik],
|
||
};
|
||
});
|
||
|
||
/**
|
||
* provides all informations about supported files ...
|
||
*/
|
||
export const XFileInfos = [
|
||
...XImageFilesInfo,
|
||
...XVideoFilesInfo,
|
||
...XAudioFilesInfo,
|
||
...XDocumentFilesInfo,
|
||
];
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-header.enum.ts
|
||
|
||
export enum XHeader {
|
||
File = 'file',
|
||
Files = 'files',
|
||
Scope = 'scope',
|
||
Accept = 'Accept',
|
||
ExpiresAt = 'expires_at',
|
||
XPoweredBy = 'X-PoweredBy',
|
||
ActionToken = 'actionToken',
|
||
ContentType = 'Content-Type',
|
||
RefreshToken = 'refresh_token',
|
||
Authorization = 'Authorization',
|
||
AuthorizationPrefix = 'Bearer ',
|
||
RevisionChecksum = 'revision_checksum',
|
||
RejectUnauthorized = 'rejectUnauthorized',
|
||
}
|
||
|
||
export enum XContentType {
|
||
AppJson = 'application/json',
|
||
AppOctetStream = 'application/octet-stream',
|
||
}
|
||
|
||
export function getAuthorizationHeaderValue(token: string) {
|
||
return `${XHeader.AuthorizationPrefix}${token}`;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-param.enum.ts
|
||
|
||
export enum XParam {
|
||
//
|
||
// QueryParams and Headers ...
|
||
Id = 'id',
|
||
ReturnUrl = 'ru',
|
||
Type = 'type',
|
||
//
|
||
Errors = 'errors',
|
||
//
|
||
Item = 'item',
|
||
Items = 'items',
|
||
//
|
||
Option = 'option',
|
||
Options = 'options',
|
||
//
|
||
HasBack = 'b',
|
||
//
|
||
// Header
|
||
Language = 'language',
|
||
//
|
||
// XQuery interface Params ...
|
||
Filter = 'Filter',
|
||
ContainsDetail = 'ContainsDetail',
|
||
EnableTracking = 'EnableTracking',
|
||
SortBy = 'SortBy',
|
||
IsAscending = 'IsAscending',
|
||
Page = 'Page',
|
||
PageSize = 'PageSize',
|
||
//
|
||
// XPageRequest interface Params ...
|
||
First = 'First',
|
||
Last = 'Last',
|
||
After = 'After',
|
||
Before = 'Before',
|
||
DescendingSort = 'DescendingSort',
|
||
//
|
||
// Exception ...
|
||
Exception = 'ex',
|
||
}
|
||
//#endregion
|
||
|
||
export type XParamIdentifier = XParam | string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-setting.resources.ts
|
||
|
||
export enum XSettingsStorageKey {
|
||
Locale = '[SETTINGS] Locale'
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x-translation.resources.ts
|
||
|
||
export enum XResourceIDs {
|
||
//
|
||
//#region App ...
|
||
app_name,
|
||
company,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Commons ...
|
||
id,
|
||
file_name,
|
||
//
|
||
error,
|
||
required,
|
||
|
||
//
|
||
loading,
|
||
|
||
//
|
||
username,
|
||
password,
|
||
|
||
//
|
||
first_name,
|
||
last_name,
|
||
|
||
//
|
||
verified,
|
||
unverified,
|
||
|
||
//
|
||
thumbnail,
|
||
language,
|
||
|
||
//
|
||
take_screenshot,
|
||
enable_capture_mode,
|
||
disable_capture_mode,
|
||
|
||
//
|
||
be,
|
||
not_to_be,
|
||
enabled,
|
||
disabled,
|
||
banned,
|
||
un_banned,
|
||
//#endregion
|
||
|
||
//
|
||
//#region File Types ...
|
||
audio,
|
||
video,
|
||
document,
|
||
cover_image,
|
||
image,
|
||
avatar,
|
||
unknown,
|
||
location,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Messages ...
|
||
are_you_sure,
|
||
success_msg,
|
||
locked_msg,
|
||
empty_content,
|
||
no_item,
|
||
drag_drop_here,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Components ...
|
||
map_dialog_title,
|
||
map_dialog_select_title,
|
||
color_picker_dialog_title,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Verbs ...
|
||
dismiss,
|
||
accept,
|
||
ok,
|
||
save,
|
||
cancel,
|
||
retry,
|
||
edit,
|
||
reset,
|
||
change,
|
||
start,
|
||
yes,
|
||
no,
|
||
verify,
|
||
confirm,
|
||
crop,
|
||
clear,
|
||
set,
|
||
select,
|
||
send,
|
||
show,
|
||
hide,
|
||
search,
|
||
delete,
|
||
clone,
|
||
select_all,
|
||
select_file,
|
||
select_all_group,
|
||
deselect_all,
|
||
deselect_all_group,
|
||
inverse_selection,
|
||
selected_location,
|
||
color,
|
||
colors,
|
||
preset_colors,
|
||
copy_to_clipboard,
|
||
//
|
||
upload,
|
||
import,
|
||
continue,
|
||
finish,
|
||
enable,
|
||
disable,
|
||
//
|
||
all,
|
||
new,
|
||
add,
|
||
update,
|
||
details,
|
||
translation,
|
||
|
||
//
|
||
download,
|
||
list,
|
||
options,
|
||
descriptions,
|
||
|
||
//
|
||
type,
|
||
|
||
//
|
||
media,
|
||
medias,
|
||
|
||
//
|
||
go,
|
||
input,
|
||
preview,
|
||
|
||
//
|
||
close,
|
||
undo,
|
||
redo,
|
||
|
||
//
|
||
refresh,
|
||
|
||
//
|
||
submit,
|
||
|
||
//
|
||
//#region Pagination ...
|
||
first,
|
||
last,
|
||
previous,
|
||
next,
|
||
back,
|
||
//#endregion
|
||
//#endregion
|
||
|
||
//
|
||
//#region Themes Related ...
|
||
//
|
||
theme,
|
||
theme_mode,
|
||
//
|
||
theme_dark,
|
||
theme_light,
|
||
//
|
||
theme_name,
|
||
theme_name_description,
|
||
//
|
||
theme_clone_title,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Color Picker Related ...
|
||
input_color_title,
|
||
input_color_description,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Markdown Component ...
|
||
x_markdown_preview,
|
||
x_markdown_image,
|
||
x_markdown_link,
|
||
x_markdown_ol,
|
||
x_markdown_ul,
|
||
x_markdown_quote,
|
||
x_markdown_code,
|
||
x_markdown_heading,
|
||
x_markdown_italic,
|
||
x_markdown_bold,
|
||
x_markdown_guide,
|
||
//#endregion
|
||
|
||
//
|
||
//#region XIDE Component ...
|
||
ide_mode,
|
||
ide_format,
|
||
//#endregion
|
||
|
||
//
|
||
//#region Password Validation Errors ...
|
||
required_length,
|
||
required_unique_chars,
|
||
require_digit,
|
||
require_lowercase,
|
||
require_uppercase,
|
||
require_non_alphanumeric,
|
||
//#endregion
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\constants\x.constants.ts
|
||
|
||
export const DEFAULT_JAVASCRIPT_VOID_HREF = 'javascript:void(0)';
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-clipboard.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Output,
|
||
Directive,
|
||
HostListener,
|
||
EventEmitter
|
||
} from '@angular/core';
|
||
import { isNullOrEmptyString } from '../tools/x-type-detect.tools';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xClipboard]'
|
||
})
|
||
export class XClipboardDirective {
|
||
//
|
||
@Input()
|
||
clipData: string;
|
||
|
||
@Output()
|
||
copied = new EventEmitter<string>();
|
||
|
||
@HostListener('click', ['$event'])
|
||
whenClicked(event: MouseEvent) {
|
||
event.preventDefault();
|
||
|
||
//
|
||
if (isNullOrEmptyString(this.clipData)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const listener = (e: ClipboardEvent) => {
|
||
//
|
||
// tslint:disable-next-line:no-string-literal
|
||
const clipboard = e.clipboardData || window['clipboardData'];
|
||
clipboard.setData('text', this.clipData);
|
||
e.preventDefault();
|
||
|
||
this.copied.emit(this.clipData);
|
||
};
|
||
|
||
//
|
||
document.addEventListener('copy', listener, false);
|
||
document.execCommand('copy');
|
||
document.removeEventListener('copy', listener, false);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-color.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Renderer2,
|
||
OnChanges,
|
||
Directive,
|
||
ElementRef,
|
||
SimpleChanges,
|
||
} from '@angular/core';
|
||
import {
|
||
getXColorClassName,
|
||
getXColorForegroundClassName,
|
||
} from '../tools/x-color.tools';
|
||
import { keys } from '../tools/x-object.tools';
|
||
import { XStandardType } from '../typings/x.typings';
|
||
import { concatMap, map, first } from 'rxjs/operators';
|
||
import { toObservable } from '../tools/x-observable.tools';
|
||
import { isNullOrEmptyString } from '../tools/x-type-detect.tools';
|
||
import { XColorIdentifier, XColor } from '../typings/x-color.typings';
|
||
|
||
/**
|
||
* this directive used to apply an specific color on an element ...
|
||
*/
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xColor]',
|
||
})
|
||
export class XColorDirective implements OnChanges {
|
||
//
|
||
private COLOR_CLASS: string;
|
||
|
||
//
|
||
/**
|
||
* a color identifier to apply on element ...
|
||
*/
|
||
// tslint:disable-next-line:no-input-rename
|
||
@Input('xColor')
|
||
xColor: XStandardType<XColorIdentifier>;
|
||
|
||
/**
|
||
* determines the selected color must apply on foreground or background of element
|
||
*/
|
||
@Input()
|
||
isForeground: XStandardType<boolean> = false;
|
||
|
||
//
|
||
constructor(private element: ElementRef, private renderer: Renderer2) {}
|
||
|
||
//
|
||
ngOnChanges(changes: SimpleChanges) {
|
||
//
|
||
const changeKeys = keys(changes);
|
||
if (changeKeys.includes('xColor') || changeKeys.includes('isForeground')) {
|
||
this.handleColorChanges();
|
||
}
|
||
}
|
||
|
||
//
|
||
private handleColorChanges() {
|
||
//
|
||
toObservable(this.xColor)
|
||
.pipe(
|
||
concatMap((color) => {
|
||
return toObservable(this.isForeground).pipe(
|
||
map((isForeground) => {
|
||
return {
|
||
color,
|
||
isForeground,
|
||
};
|
||
})
|
||
);
|
||
}),
|
||
first()
|
||
)
|
||
.subscribe((info) => {
|
||
//
|
||
if (!info.color) {
|
||
info.color = XColor.Dark;
|
||
}
|
||
|
||
//
|
||
const colorClassName = info.isForeground
|
||
? getXColorForegroundClassName(info.color)
|
||
: getXColorClassName(info.color);
|
||
|
||
//
|
||
if (!isNullOrEmptyString(this.COLOR_CLASS)) {
|
||
this.renderer.removeClass(
|
||
this.element.nativeElement,
|
||
this.COLOR_CLASS
|
||
);
|
||
}
|
||
|
||
//
|
||
this.COLOR_CLASS = colorClassName;
|
||
this.renderer.addClass(this.element.nativeElement, colorClassName);
|
||
});
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-droppable.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Output,
|
||
Renderer2,
|
||
Directive,
|
||
ElementRef,
|
||
EventEmitter,
|
||
HostListener,
|
||
} from '@angular/core';
|
||
import {
|
||
getXColorClassName,
|
||
getXColorForegroundClassName,
|
||
} from '../tools/x-color.tools';
|
||
import { hasChild } from '../tools/x-array.tools';
|
||
import { XOneOrManyType } from '../typings/x.typings';
|
||
import { isArray, isString } from '../tools/x-type-detect.tools';
|
||
import { XColorIdentifier, XColor } from '../typings/x-color.typings';
|
||
import { getExtension, isExistsExtension } from '../tools/x-file.tools';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xDroppable]',
|
||
})
|
||
export class XDroppableDirective {
|
||
//
|
||
private DISABLED: boolean;
|
||
private COLOR_CLASSES: string[] = [];
|
||
|
||
//
|
||
@Input()
|
||
disableFileCheck = false;
|
||
|
||
@Input()
|
||
public allowedExtensions: XOneOrManyType<string> = [];
|
||
|
||
@Input()
|
||
public successColor: XColorIdentifier = XColor.Success;
|
||
|
||
@Input()
|
||
public errorColor: XColorIdentifier = XColor.Danger;
|
||
|
||
@Input()
|
||
public accentColor: XColorIdentifier = XColor.Secondary;
|
||
|
||
@Input()
|
||
public supportsMultipleFiles = true;
|
||
|
||
@Input()
|
||
public isForegroundColor = false;
|
||
|
||
@Input()
|
||
set dragDisabled(value: boolean) {
|
||
//
|
||
if (value !== this.DISABLED) {
|
||
//
|
||
this.DISABLED = value;
|
||
if (!value) {
|
||
this.setBackgroundColor('transparent');
|
||
} else {
|
||
this.setBackgroundColor(this.successColor);
|
||
}
|
||
}
|
||
}
|
||
|
||
@Input()
|
||
set error(val: boolean) {
|
||
if (val) {
|
||
this.setBackgroundColor(this.errorColor);
|
||
return;
|
||
}
|
||
|
||
if (this.DISABLED) {
|
||
return;
|
||
}
|
||
|
||
this.setBackgroundColor('transparent');
|
||
}
|
||
|
||
@Output()
|
||
public filesChangeEmiter: EventEmitter<File | File[]> = new EventEmitter();
|
||
|
||
constructor(private elementRef: ElementRef, private renderer: Renderer2) {}
|
||
|
||
@HostListener('dragover', ['$event'])
|
||
public async onDragOver(event: any) {
|
||
//
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
|
||
//
|
||
if (this.DISABLED) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
await this.setBackgroundColor(this.accentColor);
|
||
}
|
||
|
||
@HostListener('dragleave', ['$event'])
|
||
public async onDragLeave(event: any) {
|
||
//
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
|
||
//
|
||
if (this.DISABLED) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
await this.setBackgroundColor('transparent');
|
||
}
|
||
|
||
@HostListener('drop', ['$event'])
|
||
public async onDrop(event: DragEvent) {
|
||
event.preventDefault();
|
||
event.stopPropagation();
|
||
|
||
//
|
||
if (this.DISABLED) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const files = Array.from(event.dataTransfer.files);
|
||
if (files.length === 0) {
|
||
await this.setBackgroundColor(this.errorColor);
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Retrieve Allowen Extensions ...
|
||
let allowedExtensions: string[] = [];
|
||
if (isArray(this.allowedExtensions)) {
|
||
allowedExtensions = this.allowedExtensions as string[];
|
||
} else if (isString(this.allowedExtensions)) {
|
||
allowedExtensions.push(this.allowedExtensions as string);
|
||
}
|
||
|
||
//
|
||
if (!this.disableFileCheck) {
|
||
if (files.length === 1) {
|
||
//
|
||
const file = files[0];
|
||
const ext = getExtension(file.name);
|
||
|
||
//
|
||
let isAllowed = true;
|
||
|
||
if (hasChild(allowedExtensions)) {
|
||
isAllowed = isExistsExtension(allowedExtensions, ext);
|
||
}
|
||
|
||
//
|
||
if (isAllowed) {
|
||
//
|
||
await this.setBackgroundColor(this.successColor);
|
||
} else {
|
||
await this.setBackgroundColor(this.errorColor);
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.filesChangeEmiter.emit(file);
|
||
await this.setBackgroundColor('transparent');
|
||
} else {
|
||
//
|
||
if (!this.supportsMultipleFiles) {
|
||
await this.setBackgroundColor(this.errorColor);
|
||
return;
|
||
}
|
||
|
||
//
|
||
const isAllowedAll = !hasChild(allowedExtensions)
|
||
? true
|
||
: files.every((file) => {
|
||
//
|
||
const ext = getExtension(file.name);
|
||
//
|
||
let isAllowed = true;
|
||
if (hasChild(allowedExtensions)) {
|
||
isAllowed = isExistsExtension(allowedExtensions, ext);
|
||
}
|
||
|
||
//
|
||
return isAllowed;
|
||
});
|
||
|
||
//
|
||
if (isAllowedAll) {
|
||
//
|
||
await this.setBackgroundColor(this.successColor);
|
||
} else {
|
||
await this.setBackgroundColor(this.errorColor);
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.filesChangeEmiter.emit(files);
|
||
await this.setBackgroundColor('transparent');
|
||
}
|
||
} else {
|
||
//
|
||
this.filesChangeEmiter.emit(files);
|
||
await this.setBackgroundColor('transparent');
|
||
}
|
||
}
|
||
|
||
private async setBackgroundColor(color: XColorIdentifier) {
|
||
//
|
||
if (!color) {
|
||
color = 'transparent';
|
||
}
|
||
|
||
//
|
||
const colorClassName = this.isForegroundColor
|
||
? getXColorForegroundClassName(color)
|
||
: getXColorClassName(color);
|
||
|
||
//
|
||
if (!this.COLOR_CLASSES.includes(colorClassName)) {
|
||
this.COLOR_CLASSES.push(colorClassName);
|
||
}
|
||
|
||
//
|
||
if (hasChild(this.COLOR_CLASSES)) {
|
||
this.COLOR_CLASSES.forEach((clz) => {
|
||
this.renderer.removeClass(this.elementRef.nativeElement, clz);
|
||
});
|
||
}
|
||
|
||
//
|
||
this.renderer.addClass(this.elementRef.nativeElement, colorClassName);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-file-reader.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Output,
|
||
OnInit,
|
||
OnChanges,
|
||
Directive,
|
||
OnDestroy,
|
||
EventEmitter,
|
||
SimpleChanges
|
||
} from '@angular/core';
|
||
import { Subject } from 'rxjs';
|
||
import { takeUntil } from 'rxjs/operators';
|
||
import { XFileType } from '../constants/x-file.enum';
|
||
import { getFileType } from '../tools/x-file.tools';
|
||
import { keys, nameof } from '../tools/x-object.tools';
|
||
import { XFileReaderInputType } from '../typings/x.typings';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xFileReader]'
|
||
})
|
||
export class XFileReaderDirective implements OnInit, OnChanges, OnDestroy {
|
||
//
|
||
private UNSUBSCRIBER = new Subject();
|
||
private FILE_READER: FileReader;
|
||
|
||
//
|
||
@Input('xFileReader')
|
||
file: XFileReaderInputType;
|
||
|
||
@Input()
|
||
refreshFileReader = new Subject();
|
||
|
||
//
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onFileReaderError = new EventEmitter<any>();
|
||
|
||
//
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onFileReaderLoad = new EventEmitter<boolean>();
|
||
|
||
//
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onFileReaderProgress = new EventEmitter<any>();
|
||
|
||
//
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onFileReaderFinish = new EventEmitter<any>();
|
||
|
||
//
|
||
ngOnInit() {
|
||
this.refreshFileReader
|
||
.asObservable()
|
||
.pipe(takeUntil(this.UNSUBSCRIBER))
|
||
.subscribe(() => {
|
||
this.handleStartReading();
|
||
});
|
||
}
|
||
|
||
//
|
||
ngOnDestroy() {
|
||
this.UNSUBSCRIBER.next();
|
||
this.UNSUBSCRIBER.complete();
|
||
this.UNSUBSCRIBER = null;
|
||
}
|
||
|
||
//
|
||
ngOnChanges(changes: SimpleChanges) {
|
||
//
|
||
const changeKeys = keys(changes);
|
||
const isFileChanged = changeKeys.includes(
|
||
nameof<XFileReaderDirective>('file')
|
||
);
|
||
if (isFileChanged) {
|
||
this.handleStartReading();
|
||
}
|
||
}
|
||
|
||
//
|
||
private async handleStartReading() {
|
||
//
|
||
await this.destroyReader();
|
||
|
||
//
|
||
const type = getFileType(this.file);
|
||
if (type !== XFileType.Image) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.FILE_READER = new FileReader();
|
||
|
||
//
|
||
this.FILE_READER.onerror = err => {
|
||
this.onFileReaderError.emit(err);
|
||
this.destroyReader();
|
||
};
|
||
|
||
//
|
||
this.FILE_READER.onabort = err => {
|
||
this.onFileReaderError.emit(err);
|
||
this.destroyReader();
|
||
};
|
||
|
||
//
|
||
this.FILE_READER.onloadstart = _ => this.onFileReaderLoad.emit(true);
|
||
this.FILE_READER.onprogress = ev => this.onFileReaderProgress.emit(ev);
|
||
this.FILE_READER.onloadend = _ => {
|
||
this.onFileReaderLoad.emit(false);
|
||
this.destroyReader();
|
||
};
|
||
|
||
//
|
||
this.FILE_READER.onload = _ =>
|
||
this.onFileReaderFinish.emit(this.FILE_READER.result);
|
||
|
||
//
|
||
this.FILE_READER.readAsDataURL(this.file as Blob);
|
||
}
|
||
|
||
private async destroyReader() {
|
||
//
|
||
if (!this.FILE_READER) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.FILE_READER.abort();
|
||
this.FILE_READER = null;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-focus-handler.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Directive,
|
||
ElementRef,
|
||
HostListener,
|
||
ChangeDetectorRef,
|
||
} from '@angular/core';
|
||
import { toArray } from '../tools/x-array.tools';
|
||
import { toPromise } from '../tools/x-observable.tools';
|
||
import { XOneOrManyType, XStandardType } from '../typings/x.typings';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xFocusHandler]',
|
||
})
|
||
export class XFocusedHandlerDirective {
|
||
//
|
||
//#region Props ...
|
||
@Input()
|
||
enableHandler: XStandardType<boolean> = false;
|
||
|
||
@Input()
|
||
appliedClassNames: XStandardType<XOneOrManyType<string>> = 'x-focused';
|
||
//#endregion
|
||
|
||
//
|
||
//#region Constructor ...
|
||
constructor(
|
||
public el: ElementRef,
|
||
public changeDetector: ChangeDetectorRef
|
||
) {}
|
||
//#endregion
|
||
|
||
//
|
||
//#region HostListener Handlers ...
|
||
@HostListener('focus', ['$event'])
|
||
async whenFocused(event: any) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const el = this.getElement();
|
||
if (!el) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const appliedClasses = await this.getClasses();
|
||
|
||
//
|
||
appliedClasses.forEach((clz) => {
|
||
el.classList.add(clz);
|
||
});
|
||
|
||
//
|
||
this.changeDetector.detectChanges();
|
||
}
|
||
|
||
@HostListener('blur', ['$event'])
|
||
async whenBlured(event: any) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const el = this.getElement();
|
||
if (!el) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const appliedClasses = await this.getClasses();
|
||
|
||
//
|
||
appliedClasses.forEach((clz) => {
|
||
el.classList.remove(clz);
|
||
});
|
||
|
||
//
|
||
this.changeDetector.detectChanges();
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Private ...
|
||
private async isEnable() {
|
||
return await toPromise(this.enableHandler);
|
||
}
|
||
|
||
private async getClasses() {
|
||
//
|
||
const classType = await toPromise(this.appliedClassNames);
|
||
return toArray(classType);
|
||
}
|
||
|
||
private getElement() {
|
||
return this.el && this.el.nativeElement
|
||
? (this.el.nativeElement as HTMLElement)
|
||
: null;
|
||
}
|
||
//#endregion
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-focus.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Directive,
|
||
OnDestroy,
|
||
OnChanges,
|
||
ElementRef,
|
||
AfterViewInit,
|
||
SimpleChanges,
|
||
AfterContentInit,
|
||
} from '@angular/core';
|
||
import { takeUntil } from 'rxjs/operators';
|
||
import { Subject, Subscription } from 'rxjs';
|
||
import { nameof } from '../tools/x-object.tools';
|
||
import { isNullOrUndefined } from '../tools/x-type-detect.tools';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xFocus]',
|
||
})
|
||
export class XFocusDirective
|
||
implements AfterViewInit, AfterContentInit, OnChanges, OnDestroy
|
||
{
|
||
//
|
||
private subscription: Subscription;
|
||
private ngUnsubscribe = new Subject();
|
||
|
||
//
|
||
@Input('xFocus')
|
||
reFocus = new Subject();
|
||
|
||
constructor(private element: ElementRef) {}
|
||
|
||
//
|
||
//#region LifeCycles ...
|
||
ngAfterViewInit() {
|
||
this.initFocusHandler();
|
||
}
|
||
|
||
ngAfterContentInit() {
|
||
this.doFocus();
|
||
}
|
||
|
||
ngOnChanges(changes: SimpleChanges): void {
|
||
//
|
||
if (isNullOrUndefined(changes)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const changeKeys = Object.keys(changes);
|
||
const isReFocusChanged = changeKeys.includes(
|
||
nameof<XFocusDirective>('reFocus')
|
||
);
|
||
if (isReFocusChanged) {
|
||
this.initFocusHandler();
|
||
}
|
||
}
|
||
|
||
ngOnDestroy() {
|
||
//
|
||
this.ngUnsubscribe.next();
|
||
this.ngUnsubscribe.complete();
|
||
}
|
||
//#endregion
|
||
|
||
private doFocus() {
|
||
setTimeout(() => this.element.nativeElement.focus(), 500);
|
||
}
|
||
|
||
private initFocusHandler() {
|
||
//
|
||
if (!isNullOrUndefined(this.subscription)) {
|
||
//
|
||
this.subscription.unsubscribe();
|
||
this.subscription = undefined;
|
||
}
|
||
|
||
//
|
||
if (isNullOrUndefined(this.reFocus)) {
|
||
this.reFocus = new Subject();
|
||
}
|
||
|
||
//
|
||
this.subscription = this.reFocus
|
||
.asObservable()
|
||
.pipe(takeUntil(this.ngUnsubscribe))
|
||
.subscribe(() => {
|
||
this.doFocus();
|
||
});
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-formatter.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
OnInit,
|
||
Directive,
|
||
ElementRef,
|
||
HostListener,
|
||
} from '@angular/core';
|
||
import { XFormatterOption } from '../typings/x.typings';
|
||
import { applyFormat, clearFormat } from '../tools/x-formatter.tools';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xFormatter]',
|
||
})
|
||
export class XFormatterDirective implements OnInit {
|
||
//
|
||
private el: HTMLInputElement;
|
||
|
||
//
|
||
@Input('xFormatter')
|
||
options: XFormatterOption;
|
||
|
||
@Input()
|
||
clearLocale = true;
|
||
|
||
//
|
||
constructor(private elementRef: ElementRef) {
|
||
this.el = this.elementRef.nativeElement;
|
||
}
|
||
|
||
//
|
||
ngOnInit() {
|
||
this.el.value = this.format(this.el.value);
|
||
}
|
||
|
||
//
|
||
@HostListener('focus', ['$event.target.value'])
|
||
onFocus(value: any) {
|
||
this.el.value = this.clear(value);
|
||
}
|
||
|
||
//
|
||
@HostListener('blur', ['$event.target.value'])
|
||
onBlur(value: any) {
|
||
this.el.value = this.format(value);
|
||
}
|
||
|
||
//
|
||
private format(value: any) {
|
||
return applyFormat(this.options, value ? value.toString() : '');
|
||
}
|
||
|
||
//
|
||
private clear(value: any) {
|
||
return clearFormat(
|
||
this.options,
|
||
this.clearLocale,
|
||
value ? value.toString() : ''
|
||
);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-mouse-handler.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
OnInit,
|
||
Output,
|
||
Directive,
|
||
OnDestroy,
|
||
OnChanges,
|
||
ElementRef,
|
||
HostListener,
|
||
EventEmitter,
|
||
AfterViewInit,
|
||
SimpleChanges,
|
||
AfterContentInit,
|
||
} from '@angular/core';
|
||
import { XStandardType } from '../typings/x.typings';
|
||
import { toPromise } from '../tools/x-observable.tools';
|
||
import { isNullOrUndefined } from '../tools/x-type-detect.tools';
|
||
|
||
/**
|
||
* this is a directive which bind to mouse/touch events and react based on them ...
|
||
*/
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xMouseHandler]',
|
||
})
|
||
export class XMouseHandlerDirective
|
||
implements OnInit, OnChanges, AfterViewInit, AfterContentInit, OnDestroy {
|
||
//
|
||
//#region Props ...
|
||
@Input()
|
||
enableHandler: XStandardType<boolean> = false;
|
||
|
||
@Output()
|
||
started = new EventEmitter<MouseEvent>();
|
||
|
||
@Output()
|
||
moved = new EventEmitter<MouseEvent>();
|
||
|
||
@Output()
|
||
finished = new EventEmitter<MouseEvent>();
|
||
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onWindowStarted = new EventEmitter<MouseEvent>();
|
||
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onWindowMoved = new EventEmitter<MouseEvent>();
|
||
|
||
// tslint:disable-next-line:no-output-on-prefix
|
||
@Output()
|
||
onWindowFinished = new EventEmitter<MouseEvent>();
|
||
//#endregion
|
||
|
||
//
|
||
//#region Constructor ...
|
||
constructor(private el: ElementRef) {}
|
||
//#endregion
|
||
|
||
//
|
||
//#region LifeCycles ...
|
||
ngOnInit() {}
|
||
|
||
ngOnChanges(changes: SimpleChanges) {}
|
||
|
||
ngAfterViewInit() {}
|
||
|
||
ngAfterContentInit() {}
|
||
|
||
ngOnDestroy() {}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Host Listeners ...
|
||
//
|
||
//#region Element Listeners ...
|
||
@HostListener('document:mousedown', ['$event'])
|
||
@HostListener('document:touchstart', ['$event'])
|
||
async whenMoveStart(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
if (!this.isTargetMatched(event)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.started.emit(event);
|
||
}
|
||
|
||
@HostListener('document:mousemove', ['$event'])
|
||
@HostListener('document:touchmove', ['$event'])
|
||
async whenMove(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
if (!this.isTargetMatched(event)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.moved.emit(event);
|
||
}
|
||
|
||
@HostListener('document:mouseup', ['$event'])
|
||
@HostListener('document:touchend', ['$event'])
|
||
async whenMoveFinished(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
if (!this.isTargetMatched(event)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.finished.emit(event);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Window Listeners ...
|
||
@HostListener('window:mousedown', ['$event'])
|
||
@HostListener('window:touchstart', ['$event'])
|
||
async whenWindowMoveStart(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.onWindowStarted.emit(event);
|
||
}
|
||
|
||
@HostListener('window:mousemove', ['$event'])
|
||
@HostListener('window:touchmove', ['$event'])
|
||
async whenWindowMove(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.onWindowMoved.emit(event);
|
||
}
|
||
|
||
@HostListener('window:mouseup', ['$event'])
|
||
@HostListener('window:touchend', ['$event'])
|
||
async whenWindowMoveFinished(event: MouseEvent) {
|
||
//
|
||
const isEnable = await this.isEnable();
|
||
if (!isEnable) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.onWindowFinished.emit(event);
|
||
}
|
||
//#endregion
|
||
//#endregion
|
||
|
||
//
|
||
//#region Private ...
|
||
private async isEnable() {
|
||
return await toPromise(this.enableHandler);
|
||
}
|
||
|
||
private isTargetMatched(event: MouseEvent) {
|
||
return !isNullOrUndefined(event)
|
||
? (this.el.nativeElement.contains(event.target) as boolean)
|
||
: false;
|
||
}
|
||
//#endregion
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-on-enter.directive.ts
|
||
|
||
import { Directive, Output, EventEmitter, HostListener } from '@angular/core';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xOnEnter]'
|
||
})
|
||
export class XOnEnterDirective {
|
||
//
|
||
@Output('xOnEnter')
|
||
listener: EventEmitter<any> = new EventEmitter<any>();
|
||
|
||
//
|
||
@HostListener('keyup.enter', ['$event'])
|
||
onEnterPressed(event: any) {
|
||
// tslint:disable-next-line: deprecation
|
||
this.listener.emit(event);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-on-escape.directive.ts
|
||
|
||
import { Directive, Output, EventEmitter, HostListener } from '@angular/core';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xOnEscape]'
|
||
})
|
||
export class XOnEscapeDirective {
|
||
//
|
||
@Output('xOnEscape')
|
||
listener: EventEmitter<any> = new EventEmitter<any>();
|
||
|
||
//
|
||
@HostListener('keyup.esc', ['$event'])
|
||
onEscapePressed(event: any) {
|
||
// tslint:disable-next-line: deprecation
|
||
this.listener.emit(event);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-on-outside-click.directive.ts
|
||
|
||
import {
|
||
Output,
|
||
Directive,
|
||
ElementRef,
|
||
EventEmitter,
|
||
HostListener,
|
||
} from '@angular/core';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xOnOutsideClicked]',
|
||
})
|
||
export class XOutsideClickDirective {
|
||
//
|
||
@Output('xOnOutsideClicked')
|
||
listener: EventEmitter<any> = new EventEmitter<any>();
|
||
|
||
//
|
||
constructor(private elementRef: ElementRef) {}
|
||
|
||
@HostListener('document:click', ['$event.target'])
|
||
public onClick(targetElement: any) {
|
||
//
|
||
const clickedInside = this.elementRef.nativeElement.contains(targetElement);
|
||
if (!clickedInside) {
|
||
this.listener.emit();
|
||
}
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-render.directive.ts
|
||
|
||
import {
|
||
Directive,
|
||
Renderer2,
|
||
ElementRef,
|
||
RendererStyleFlags2
|
||
} from '@angular/core';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xRender]'
|
||
})
|
||
export class XRenderDirective {
|
||
//
|
||
constructor(private renderer: Renderer2, private el: ElementRef) {}
|
||
|
||
addClass(clz: string) {
|
||
this.renderer.addClass(this.el.nativeElement, clz);
|
||
}
|
||
|
||
removeClass(clz: string) {
|
||
this.renderer.removeClass(this.el.nativeElement, clz);
|
||
}
|
||
|
||
createElement(name: string, nameSpace?: string) {
|
||
return this.renderer.createElement(name, nameSpace);
|
||
}
|
||
|
||
createText(value: string) {
|
||
return this.renderer.createText(value);
|
||
}
|
||
|
||
appendChild(parent: any, newChild: any) {
|
||
this.renderer.appendChild(parent, newChild);
|
||
}
|
||
|
||
appendChildToElement(child: any) {
|
||
this.renderer.appendChild(this.el.nativeElement, child);
|
||
}
|
||
|
||
setAttribute(name: string, value: string, namespace?: string | null) {
|
||
this.renderer.setAttribute(this.el.nativeElement, name, value, namespace);
|
||
}
|
||
|
||
removeAttribute(name: string, namespace?: string | null) {
|
||
this.renderer.removeAttribute(this.el.nativeElement, name, namespace);
|
||
}
|
||
|
||
setStyle(style: string, value: any, flags?: RendererStyleFlags2) {
|
||
this.renderer.setStyle(this.el.nativeElement, style, value, flags);
|
||
}
|
||
|
||
removeStyle(style: string, flags?: RendererStyleFlags2) {
|
||
this.renderer.removeStyle(this.el.nativeElement, style, flags);
|
||
}
|
||
|
||
setProperty(name: string, value: any) {
|
||
this.renderer.setProperty(this.el.nativeElement, name, value);
|
||
}
|
||
|
||
setValue(node: any, value: string) {
|
||
this.renderer.setValue(node, value);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-scroll-behavior.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
OnInit,
|
||
Output,
|
||
Directive,
|
||
Renderer2,
|
||
OnDestroy,
|
||
OnChanges,
|
||
EventEmitter,
|
||
HostListener,
|
||
AfterViewInit,
|
||
SimpleChanges,
|
||
} from '@angular/core';
|
||
import { Subject, Subscription } from 'rxjs';
|
||
import { hasChild } from '../tools/x-array.tools';
|
||
import { keys, nameof } from '../tools/x-object.tools';
|
||
import { isArray, isString } from '../tools/x-type-detect.tools';
|
||
|
||
//
|
||
//#region Definitions ...
|
||
export interface XBehaviourEvent {
|
||
type: XBehaviourEventType;
|
||
event: any;
|
||
elements: Element[];
|
||
}
|
||
|
||
export type XBehaviourEventType = 'scrollStart' | 'scrollEnd' | 'scrolling';
|
||
//#endregion
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xScrollBehaviour]',
|
||
})
|
||
export class XScrollBehaviourDirective
|
||
implements OnInit, OnChanges, OnDestroy, AfterViewInit
|
||
{
|
||
//
|
||
private elementsRef: Element[] = [];
|
||
private xUnSubscriber = new Subject();
|
||
|
||
//
|
||
@Output()
|
||
scrollStarted = new EventEmitter<XBehaviourEvent>();
|
||
|
||
@Output()
|
||
scrollEnded = new EventEmitter<XBehaviourEvent>();
|
||
|
||
@Output()
|
||
scrolling = new EventEmitter<XBehaviourEvent>();
|
||
|
||
//
|
||
@Input()
|
||
scrollStartClasses: string | string[];
|
||
|
||
@Input()
|
||
scrollEndClasses: string | string[];
|
||
|
||
@Input()
|
||
scrollingClasses: string | string[];
|
||
|
||
//
|
||
private ACTION_PROVIDER_SUBSCRIPTION: Subscription;
|
||
|
||
@Input()
|
||
scrollingActionProvider = new Subject<XBehaviourEventType>();
|
||
|
||
//
|
||
@Input('xScrollBehaviour')
|
||
elements: string | string[];
|
||
|
||
//
|
||
@HostListener('ionScrollStart', ['$event'])
|
||
async onScrollStart(event: any) {
|
||
//
|
||
await this.prepareScroller();
|
||
|
||
//
|
||
await this.removeClass(this.scrollEndClasses);
|
||
await this.addClass(this.scrollStartClasses);
|
||
|
||
//
|
||
const eventModel: XBehaviourEvent = {
|
||
type: 'scrollStart',
|
||
event,
|
||
elements: this.elementsRef,
|
||
};
|
||
|
||
//
|
||
this.scrollStarted.emit(eventModel);
|
||
}
|
||
|
||
@HostListener('ionScrollEnd', ['$event'])
|
||
async onScrollEnd(event: any) {
|
||
//
|
||
await this.prepareScroller();
|
||
|
||
//
|
||
await this.removeClass(this.scrollStartClasses);
|
||
await this.removeClass(this.scrollingClasses);
|
||
await this.addClass(this.scrollEndClasses);
|
||
|
||
//
|
||
const eventModel: XBehaviourEvent = {
|
||
type: 'scrollEnd',
|
||
event,
|
||
elements: this.elementsRef,
|
||
};
|
||
|
||
//
|
||
this.scrollEnded.emit(eventModel);
|
||
}
|
||
|
||
@HostListener('ionScroll', ['$event'])
|
||
async onScroll(event: any) {
|
||
//
|
||
await this.prepareScroller();
|
||
|
||
//
|
||
await this.addClass(this.scrollingClasses);
|
||
|
||
//
|
||
const eventModel: XBehaviourEvent = {
|
||
type: 'scrolling',
|
||
event,
|
||
elements: this.elementsRef,
|
||
};
|
||
|
||
//
|
||
this.scrolling.emit(eventModel);
|
||
}
|
||
|
||
//
|
||
constructor(public renderer: Renderer2) {}
|
||
|
||
//
|
||
async ngOnInit() {
|
||
//
|
||
await this.prepareScroller();
|
||
}
|
||
|
||
async ngAfterViewInit() {
|
||
//
|
||
await this.prepareScroller();
|
||
}
|
||
|
||
ngOnChanges(changes: SimpleChanges) {
|
||
//
|
||
const changeKeys = keys(changes);
|
||
|
||
//
|
||
//#region ActionProvider Changed ...
|
||
const isActionProviderChanged = changeKeys.includes(
|
||
nameof<XScrollBehaviourDirective>('scrollingActionProvider')
|
||
);
|
||
if (isActionProviderChanged) {
|
||
this.registerActionProvider();
|
||
}
|
||
//#endregion
|
||
}
|
||
|
||
ngOnDestroy() {
|
||
//
|
||
this.unregisterActionProvider();
|
||
|
||
//
|
||
this.xUnSubscriber.next();
|
||
this.xUnSubscriber.complete();
|
||
}
|
||
|
||
//
|
||
private getType() {
|
||
//
|
||
if (!this.elements) {
|
||
return 'unknown';
|
||
}
|
||
|
||
//
|
||
if (isArray(this.elements)) {
|
||
return 'array';
|
||
} else {
|
||
return 'single';
|
||
}
|
||
}
|
||
|
||
private registerActionProvider() {
|
||
//
|
||
this.unregisterActionProvider();
|
||
|
||
//
|
||
if (!this.scrollingActionProvider) {
|
||
this.scrollingActionProvider = new Subject<XBehaviourEventType>();
|
||
}
|
||
|
||
//
|
||
this.ACTION_PROVIDER_SUBSCRIPTION = this.scrollingActionProvider
|
||
.asObservable()
|
||
.subscribe(async (model) => {
|
||
//
|
||
if (!model) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
switch (model) {
|
||
//
|
||
case 'scrollStart':
|
||
await this.onScrollStart(null);
|
||
break;
|
||
|
||
//
|
||
case 'scrollEnd':
|
||
await this.onScrollEnd(null);
|
||
break;
|
||
|
||
//
|
||
case 'scrolling':
|
||
await this.onScroll(null);
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
|
||
private unregisterActionProvider() {
|
||
//
|
||
if (!this.ACTION_PROVIDER_SUBSCRIPTION) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.ACTION_PROVIDER_SUBSCRIPTION.unsubscribe();
|
||
this.ACTION_PROVIDER_SUBSCRIPTION = null;
|
||
}
|
||
|
||
private async prepareScroller() {
|
||
//
|
||
await this.generateElementsRef();
|
||
await this.addTransition();
|
||
|
||
//
|
||
this.registerActionProvider();
|
||
}
|
||
|
||
private async generateElementsRef() {
|
||
//
|
||
this.elementsRef = [];
|
||
|
||
//
|
||
const inputType = this.getType();
|
||
if (inputType === 'unknown') {
|
||
return [];
|
||
} else if (inputType === 'single') {
|
||
//
|
||
const elements = document.querySelectorAll(this.elements as string);
|
||
if (elements.length > 0) {
|
||
elements.forEach((e) => {
|
||
this.elementsRef.push(e);
|
||
});
|
||
}
|
||
} else if (inputType === 'array') {
|
||
//
|
||
(this.elements as string[]).forEach((eSelector) => {
|
||
//
|
||
const elements = document.querySelectorAll(eSelector);
|
||
if (elements.length > 0) {
|
||
elements.forEach((e) => {
|
||
this.elementsRef.push(e);
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
//
|
||
return this.elementsRef;
|
||
}
|
||
|
||
private async addClass(cls: string | string[]) {
|
||
//
|
||
if (!hasChild(this.elementsRef)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const clsList = isString(cls) ? [cls as string] : (cls as string[]);
|
||
if (!hasChild(clsList)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.elementsRef.forEach((e) => {
|
||
e.classList.add(...clsList);
|
||
});
|
||
}
|
||
|
||
private async removeClass(cls: string | string[]) {
|
||
//
|
||
if (!hasChild(this.elementsRef)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
const clsList = isString(cls) ? [cls as string] : (cls as string[]);
|
||
if (!hasChild(clsList)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.elementsRef.forEach((e) => {
|
||
e.classList.remove(...clsList);
|
||
});
|
||
}
|
||
|
||
private async addTransition(descriptor?: string) {
|
||
//
|
||
if (!descriptor) {
|
||
descriptor = 'transform 500ms, opacity 250ms';
|
||
}
|
||
|
||
//
|
||
if (!hasChild(this.elementsRef)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
this.elementsRef.forEach((e) => {
|
||
this.renderer.setStyle(e, '-webkit-transition', descriptor);
|
||
this.renderer.setStyle(e, 'transition', descriptor);
|
||
});
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-slider.directive.ts
|
||
|
||
import {
|
||
Input,
|
||
Output,
|
||
Directive,
|
||
ElementRef,
|
||
HostListener,
|
||
EventEmitter,
|
||
} from '@angular/core';
|
||
|
||
export interface XSliderValueEventModel {
|
||
s?: number;
|
||
v?: number;
|
||
rg?: number;
|
||
rgX?: number;
|
||
rgY?: number;
|
||
}
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xSlider]',
|
||
})
|
||
export class XSliderDirective {
|
||
//
|
||
@Input()
|
||
rgX: number;
|
||
|
||
@Input()
|
||
rgY: number;
|
||
|
||
//
|
||
@Output()
|
||
newValue = new EventEmitter<XSliderValueEventModel>();
|
||
|
||
//
|
||
private listenerMove: any = (event: any) => {
|
||
this.move(event);
|
||
// tslint:disable-next-line:semicolon
|
||
};
|
||
|
||
//
|
||
private listenerStop: any = () => {
|
||
this.stop();
|
||
// tslint:disable-next-line:semicolon
|
||
};
|
||
|
||
//
|
||
constructor(private el: ElementRef) {}
|
||
|
||
setCursor(event: any) {
|
||
//
|
||
const height = this.el.nativeElement.offsetHeight;
|
||
const width = this.el.nativeElement.offsetWidth;
|
||
const x = Math.max(0, Math.min(this.getX(event), width));
|
||
const y = Math.max(0, Math.min(this.getY(event), height));
|
||
|
||
//
|
||
if (this.rgX !== undefined && this.rgY !== undefined) {
|
||
//
|
||
this.newValue.emit({
|
||
s: x / width,
|
||
v: 1 - y / height,
|
||
rgX: this.rgX,
|
||
rgY: this.rgY,
|
||
});
|
||
} else if (this.rgX === undefined && this.rgY !== undefined) {
|
||
//
|
||
// ready to use vertical sliders
|
||
this.newValue.emit({ v: y / height, rg: this.rgY });
|
||
} else {
|
||
//
|
||
this.newValue.emit({ v: x / width, rg: this.rgX });
|
||
}
|
||
}
|
||
|
||
move(event: any) {
|
||
event.preventDefault();
|
||
this.setCursor(event);
|
||
}
|
||
|
||
@HostListener('mousedown', ['$event'])
|
||
@HostListener('touchstart', ['$event'])
|
||
start(event: any) {
|
||
//
|
||
this.setCursor(event);
|
||
|
||
//
|
||
document.addEventListener('mousemove', this.listenerMove);
|
||
document.addEventListener('touchmove', this.listenerMove);
|
||
document.addEventListener('mouseup', this.listenerStop);
|
||
document.addEventListener('touchend', this.listenerStop);
|
||
}
|
||
|
||
stop() {
|
||
//
|
||
document.removeEventListener('mousemove', this.listenerMove);
|
||
document.removeEventListener('touchmove', this.listenerMove);
|
||
document.removeEventListener('mouseup', this.listenerStop);
|
||
document.removeEventListener('touchend', this.listenerStop);
|
||
}
|
||
|
||
getX(event: any): number {
|
||
//
|
||
return (
|
||
(event.pageX !== undefined ? event.pageX : event.touches[0].pageX) -
|
||
this.el.nativeElement.getBoundingClientRect().left -
|
||
window.pageXOffset
|
||
);
|
||
}
|
||
|
||
getY(event: any): number {
|
||
//
|
||
return (
|
||
(event.pageY !== undefined ? event.pageY : event.touches[0].pageY) -
|
||
this.el.nativeElement.getBoundingClientRect().top -
|
||
window.pageYOffset
|
||
);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-stop-click-propagation.directive.ts
|
||
|
||
import { Directive, HostListener } from '@angular/core';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xStopClickPropagation]'
|
||
})
|
||
export class XStopClickPropagationDirective {
|
||
@HostListener('click', ['$event'])
|
||
public onClick(event: any): void {
|
||
event.stopPropagation();
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\directives\x-var.directive.ts
|
||
|
||
import {
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from '../tools/x-type-detect.tools';
|
||
import { keys } from '../tools/x-object.tools';
|
||
import { hasChild } from '../tools/x-array.tools';
|
||
import { Input, Directive, ChangeDetectorRef } from '@angular/core';
|
||
|
||
export interface XVarModel {
|
||
name: string;
|
||
value: any;
|
||
}
|
||
|
||
@Directive({
|
||
selector: '[xVar]',
|
||
exportAs: 'xVar',
|
||
})
|
||
export class XVarDirective {
|
||
//
|
||
private context: any = {};
|
||
|
||
//
|
||
@Input('xVar')
|
||
set xVar(value: XVarModel) {
|
||
//
|
||
this.context[this.prepareVarName(value.name)] = value;
|
||
this.changeDetector.detectChanges();
|
||
}
|
||
|
||
constructor(private changeDetector: ChangeDetectorRef) {}
|
||
|
||
hasVar(name: string) {
|
||
return (
|
||
!isNullOrEmptyString(name) &&
|
||
!isNullOrUndefined(this.context) &&
|
||
hasChild(keys(this.context)) &&
|
||
!isNullOrUndefined(this.context[name])
|
||
);
|
||
}
|
||
|
||
getVar(name: string) {
|
||
return this.hasVar(this.prepareVarName(name))
|
||
? this.context[this.prepareVarName(name)]
|
||
: undefined;
|
||
}
|
||
|
||
getVars() {
|
||
return this.context;
|
||
}
|
||
|
||
private prepareVarName(name: string) {
|
||
return `xVar_${name}`;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\guards\x-can-deactivate.guard.ts
|
||
|
||
import {
|
||
CanDeactivate,
|
||
RouterStateSnapshot,
|
||
ActivatedRouteSnapshot
|
||
} from '@angular/router';
|
||
import { Observable } from 'rxjs';
|
||
import { Injectable } from '@angular/core';
|
||
|
||
export interface XCanDeactivate {
|
||
canDeactivate: (
|
||
component: XCanDeactivate,
|
||
route: ActivatedRouteSnapshot,
|
||
state: RouterStateSnapshot
|
||
) => Observable<boolean> | Promise<boolean> | boolean;
|
||
}
|
||
|
||
@Injectable()
|
||
export class XCanDeactivateGuard implements CanDeactivate<XCanDeactivate> {
|
||
canDeactivate(
|
||
component: XCanDeactivate,
|
||
route: ActivatedRouteSnapshot,
|
||
state: RouterStateSnapshot
|
||
) {
|
||
const url: string = state.url;
|
||
|
||
return component.canDeactivate
|
||
? component.canDeactivate(component, route, state)
|
||
: true;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\models\x-base-dto.ts
|
||
|
||
import { isSameObject } from '../tools/x-object.tools';
|
||
|
||
// tslint:disable-next-line:no-empty-interface
|
||
export interface XBaseDto {}
|
||
|
||
export abstract class XBaseDtoHelper<T extends XBaseDto> {
|
||
//
|
||
//#region Abstracts ...
|
||
abstract defaultValues: T;
|
||
abstract get values(): T;
|
||
abstract prepareModelFields(dto?: T): T;
|
||
abstract fill(dto?: T): void;
|
||
//#endregion
|
||
|
||
//
|
||
//#region Constructor ...
|
||
constructor(dto?: T) {
|
||
//
|
||
this.fill(this.prepareModelFields(dto));
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Actions ...
|
||
public isDefaultModel(dto?: T): boolean {
|
||
//
|
||
if (!dto) {
|
||
dto = {
|
||
...this.values,
|
||
};
|
||
}
|
||
|
||
//
|
||
const result = isSameObject(
|
||
this.prepareModelFields(dto),
|
||
this.defaultValues
|
||
);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
}
|
||
|
||
export interface XBaseNumberIDDto {
|
||
id: number;
|
||
}
|
||
|
||
// tslint:disable-next-line: no-empty-interface
|
||
export interface XBaseRequestDto {}
|
||
|
||
export interface XBaseRangeRequestDto<T> extends XBaseRequestDto {
|
||
items: Array<T>;
|
||
}
|
||
|
||
// tslint:disable-next-line:no-empty-interface
|
||
export interface XBaseResponseDto {}
|
||
|
||
export interface XBaseStorableDto<T> extends XBaseDto {
|
||
id?: T
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\models\x-base.indexed.dto.ts
|
||
|
||
import { XBaseDto } from './x-base-dto';
|
||
|
||
export interface XBaseIndexedDto<T, TKey, Tindex> extends XBaseDto {
|
||
item: T;
|
||
key: TKey;
|
||
index: Tindex;
|
||
}
|
||
|
||
export interface XBaseIntIndexedDto<T>
|
||
extends XBaseIndexedDto<T, string, number> {}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\models\x-grouped-data.dto.ts
|
||
|
||
import { XBaseDto } from "./x-base-dto";
|
||
|
||
export interface XGroupedDataDto<T, TGroupedy> extends XBaseDto {
|
||
groupedBy: TGroupedy;
|
||
members: Array<T>;
|
||
timeStamp: Date;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\modules\x-directives.module.ts
|
||
|
||
import { NgModule } from '@angular/core';
|
||
import { IonicModule } from '@ionic/angular';
|
||
import { FormsModule } from '@angular/forms';
|
||
import { XAsPipe } from '../pipes/x-as.pipe';
|
||
import { XLogPipe } from '../pipes/x-log.pipe';
|
||
import { CommonModule } from '@angular/common';
|
||
import { XSafeHtmlPipe } from '../pipes/x-safe-html.pipe';
|
||
import { XFormatterPipe } from '../pipes/x-formatter.pipe';
|
||
import { XVarDirective } from '../directives/x-var.directive';
|
||
import { XFocusDirective } from '../directives/x-focus.directive';
|
||
import { XColorDirective } from '../directives/x-color.directive';
|
||
import { XRenderDirective } from '../directives/x-render.directive';
|
||
import { XSliderDirective } from '../directives/x-slider.directive';
|
||
import { XOnEnterDirective } from '../directives/x-on-enter.directive';
|
||
import { XValidUrlDirective } from '../validators/x-valid-url.directive';
|
||
import { XOnEscapeDirective } from '../directives/x-on-escape.directive';
|
||
import { XDroppableDirective } from '../directives/x-droppable.directive';
|
||
import { XClipboardDirective } from '../directives/x-clipboard.directive';
|
||
import { XFormatterDirective } from '../directives/x-formatter.directive';
|
||
import { XValueMatchDirective } from '../validators/x-value-match.directive';
|
||
import { XValidEmailDirective } from '../validators/x-valid-email.directive';
|
||
import { XFileReaderDirective } from '../directives/x-file-reader.directive';
|
||
import { XMouseHandlerDirective } from '../directives/x-mouse-handler.directive';
|
||
import { XFocusedHandlerDirective } from '../directives/x-focus-handler.directive';
|
||
import { XOutsideClickDirective } from '../directives/x-on-outside-click.directive';
|
||
import { XScrollBehaviourDirective } from '../directives/x-scroll-behavior.directive';
|
||
import { XValidPhoneNumberDirective } from '../validators/x-valid-phone-number.directive';
|
||
import { XStopClickPropagationDirective } from '../directives/x-stop-click-propagation.directive';
|
||
|
||
@NgModule({
|
||
declarations: [
|
||
//
|
||
// Directives
|
||
XVarDirective,
|
||
XFocusDirective,
|
||
XColorDirective,
|
||
XSliderDirective,
|
||
XRenderDirective,
|
||
XOnEnterDirective,
|
||
XOnEscapeDirective,
|
||
XFormatterDirective,
|
||
XClipboardDirective,
|
||
XDroppableDirective,
|
||
XFileReaderDirective,
|
||
XOutsideClickDirective,
|
||
XMouseHandlerDirective,
|
||
XFocusedHandlerDirective,
|
||
XScrollBehaviourDirective,
|
||
XStopClickPropagationDirective,
|
||
|
||
//
|
||
// Pipes ...
|
||
XAsPipe,
|
||
XLogPipe,
|
||
XSafeHtmlPipe,
|
||
XFormatterPipe,
|
||
|
||
//
|
||
// Validators ...
|
||
XValidUrlDirective,
|
||
XValueMatchDirective,
|
||
XValidEmailDirective,
|
||
XValidPhoneNumberDirective,
|
||
],
|
||
imports: [CommonModule, IonicModule, FormsModule],
|
||
exports: [
|
||
//
|
||
IonicModule,
|
||
FormsModule,
|
||
CommonModule,
|
||
|
||
//
|
||
// Directives
|
||
XVarDirective,
|
||
XFocusDirective,
|
||
XColorDirective,
|
||
XSliderDirective,
|
||
XRenderDirective,
|
||
XOnEnterDirective,
|
||
XOnEscapeDirective,
|
||
XFormatterDirective,
|
||
XDroppableDirective,
|
||
XClipboardDirective,
|
||
XFileReaderDirective,
|
||
XOutsideClickDirective,
|
||
XMouseHandlerDirective,
|
||
XFocusedHandlerDirective,
|
||
XScrollBehaviourDirective,
|
||
XStopClickPropagationDirective,
|
||
|
||
//
|
||
// Pipes ...
|
||
XAsPipe,
|
||
XLogPipe,
|
||
XSafeHtmlPipe,
|
||
XFormatterPipe,
|
||
|
||
//
|
||
// Validators ...
|
||
XValidUrlDirective,
|
||
XValueMatchDirective,
|
||
XValidEmailDirective,
|
||
XValidPhoneNumberDirective,
|
||
],
|
||
})
|
||
export class XDirectivesModule {}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\pipes\x-as.pipe.ts
|
||
|
||
import { Pipe, PipeTransform } from '@angular/core';
|
||
|
||
@Pipe({
|
||
name: 'xAs',
|
||
pure: true,
|
||
})
|
||
export class XAsPipe implements PipeTransform {
|
||
/**
|
||
* for casting a dynamic template var to specific type ...
|
||
*
|
||
* @param value the pure template var ...
|
||
* @param _type the type which required to cast value to it ...
|
||
* @returns a type casted var ...
|
||
*/
|
||
transform<T>(value: any, _type: (new (...args: any[]) => T) | T): T {
|
||
return value as T;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\pipes\x-formatter.pipe.ts
|
||
|
||
import { Pipe, PipeTransform } from '@angular/core';
|
||
import { applyFormat, clearFormat } from '../tools/x-formatter.tools';
|
||
import { XFormatterOption, XFormatterType } from '../typings/x.typings';
|
||
|
||
@Pipe({
|
||
name: 'xFormatter',
|
||
pure: true,
|
||
})
|
||
export class XFormatterPipe implements PipeTransform {
|
||
//
|
||
private defaultFormatterOption: XFormatterOption = {
|
||
type: XFormatterType.ApplyLocale,
|
||
};
|
||
|
||
//
|
||
transform(value: any, options?: XFormatterOption): string {
|
||
return this.format(options, value);
|
||
}
|
||
|
||
//
|
||
clearFormat(value: any, options?: XFormatterOption, clearLocale = false) {
|
||
//
|
||
options = {
|
||
...this.defaultFormatterOption,
|
||
...options,
|
||
};
|
||
|
||
//
|
||
return clearFormat(options, clearLocale, value) || '';
|
||
}
|
||
|
||
//
|
||
private format(options: XFormatterOption, value: any) {
|
||
return applyFormat(
|
||
{ ...this.defaultFormatterOption, ...options },
|
||
value ? value.toString() : ''
|
||
);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\pipes\x-log.pipe.ts
|
||
|
||
import { Pipe, PipeTransform } from '@angular/core';
|
||
|
||
@Pipe({
|
||
name: 'xLog',
|
||
pure: true,
|
||
})
|
||
export class XLogPipe implements PipeTransform {
|
||
/**
|
||
* do a console log from a pipe
|
||
*
|
||
* @param value the specified value
|
||
* @param args it is optional and unused here
|
||
*/
|
||
transform(value: any, ...args: any[]): any {
|
||
//
|
||
console.log('XLogPipe: ', value);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\pipes\x-safe-html.pipe.ts
|
||
|
||
import { Pipe, PipeTransform } from '@angular/core';
|
||
import { DomSanitizer } from '@angular/platform-browser';
|
||
|
||
@Pipe({
|
||
name: 'xSafeHTML',
|
||
pure: true,
|
||
})
|
||
export class XSafeHtmlPipe implements PipeTransform {
|
||
//
|
||
constructor(private sanitizer: DomSanitizer) {}
|
||
|
||
//
|
||
transform(value: any, args?: any): any {
|
||
return this.sanitizer.bypassSecurityTrustHtml(value);
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tokens\x-injectable-tokens.ts
|
||
|
||
import { InjectionToken } from '@angular/core';
|
||
import { XFrameworkCoreConfig } from '../config/x-framework-core.config';
|
||
|
||
export const X_FRAMEWORK_CORE_CONFIG = new InjectionToken<XFrameworkCoreConfig>(
|
||
'x_config'
|
||
);
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-array.tools.ts
|
||
|
||
//
|
||
//#region Array Tools ...
|
||
|
||
import { XOneOrManyType } from '../typings/x.typings';
|
||
import { isArray } from './x-type-detect.tools';
|
||
|
||
/**
|
||
* retrieve last item of an Array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function lastItem<T>(list: XOneOrManyType<T>) {
|
||
//
|
||
if (!list || !hasChild(list)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const listArray = toArray(list);
|
||
|
||
//
|
||
return listArray[listArray.length - 1];
|
||
}
|
||
|
||
/**
|
||
* extract and retrieve specific item of an array ...
|
||
*
|
||
* @param index index of Array Item ...
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function nthItem<T>(index: number, list: XOneOrManyType<T>) {
|
||
//
|
||
if (!list || !hasChild(list)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const listArray = toArray(list);
|
||
if (index < 0) {
|
||
try {
|
||
return listArray[listArray.length - 1 + index];
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
//
|
||
try {
|
||
return listArray[index];
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* extract specific range of items from an array ...
|
||
*
|
||
* @param index extracting start index ...
|
||
* @param count number of extracting items ...
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param reverse optional param to determines extracting direction ...
|
||
*/
|
||
export function nthItems<T>(
|
||
index: number,
|
||
count: number,
|
||
list: XOneOrManyType<T>,
|
||
reverse?: boolean
|
||
) {
|
||
//
|
||
if (!list || !hasChild(list) || count === 0) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
let mIndex = index;
|
||
const listArray = toArray(list);
|
||
if (index < 0) {
|
||
//
|
||
mIndex = listArray.length - 1 + index;
|
||
}
|
||
|
||
//
|
||
let mCount = count;
|
||
if (mCount < 0) {
|
||
//
|
||
mIndex += count;
|
||
mCount = count * -1;
|
||
}
|
||
|
||
//
|
||
const result = listArray.splice(mIndex, mCount);
|
||
if (reverse) {
|
||
result.reverse();
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* determines an array has childs or not ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function hasChild<T>(list: XOneOrManyType<T>) {
|
||
return list && toArray(list).length > 0;
|
||
}
|
||
|
||
/**
|
||
* count an array childs ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function countChild<T>(list: XOneOrManyType<T>) {
|
||
return toArray(list).length;
|
||
}
|
||
|
||
/**
|
||
* convert an indexable object to array ...
|
||
*
|
||
* @param index indexed object ...
|
||
*/
|
||
export function getArrayOf<T>(index: { [key: string]: T }): T[] {
|
||
//
|
||
const result: T[] = [];
|
||
|
||
//
|
||
Object.keys(index).forEach((key) => {
|
||
//
|
||
result.push(index[key] as T);
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* merge all items inside collection of items ...
|
||
* @param args a collection of XOneOrManyOfType items ...
|
||
*/
|
||
export function mergeList<T>(...args: XOneOrManyType<T>[]) {
|
||
//
|
||
const result: T[] = [];
|
||
|
||
//
|
||
args.forEach((arg) => {
|
||
result.push(...toArray(arg));
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert value to array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function toArray<T>(list: XOneOrManyType<T>) {
|
||
//
|
||
if (!list) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
if (isArray(list)) {
|
||
return list as T[];
|
||
}
|
||
|
||
//
|
||
return [list as T];
|
||
}
|
||
|
||
/**
|
||
* convert a value of specific type to array of another type ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<TSource> object ...
|
||
* @returns an instance of TDest[] object ...
|
||
*/
|
||
export function convertArray<TSource, TDest>(
|
||
list: XOneOrManyType<TSource>
|
||
): XOneOrManyType<TDest> {
|
||
//
|
||
let array = toArray(list);
|
||
|
||
//
|
||
const result: TDest[] = !hasChild(array)
|
||
? []
|
||
: array.map((i) => i as any as TDest);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param callback A function that accepts up to three arguments.
|
||
* The map method calls the callbackfn function one time for each element in the array.
|
||
*/
|
||
export function mapArray<T>(
|
||
list: XOneOrManyType<T>,
|
||
callback: (value: T, index: number, array: T[]) => T
|
||
) {
|
||
//
|
||
if (!list) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const pList = toArray(list);
|
||
|
||
//
|
||
return pList.map(callback);
|
||
}
|
||
|
||
/**
|
||
* remove specific index of an array objects and return cleared array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param index specific item index ...
|
||
*/
|
||
export function removeItemByIndex<T>(list: XOneOrManyType<T>, index: number) {
|
||
//
|
||
if (!hasChild(list) || index < 0 || index > countChild(list) - 1) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
return toArray(list).splice(index, 1);
|
||
}
|
||
|
||
/**
|
||
* remove specific item of an array and return cleared array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param item specific item ...
|
||
*/
|
||
export function removeItem<T>(list: XOneOrManyType<T>, item: T) {
|
||
//
|
||
if (!hasChild(list) || !item) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
const listArray = toArray(list);
|
||
const iIndex = listArray.indexOf(item);
|
||
if (iIndex === -1) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
return listArray.splice(iIndex, 1);
|
||
}
|
||
|
||
/**
|
||
* check an array contains an specific item or not ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param item specific item ...
|
||
*/
|
||
export function isExists<T>(list: XOneOrManyType<T>, item: T) {
|
||
return toArray(list).findIndex((i) => i === item) !== -1;
|
||
}
|
||
|
||
/**
|
||
* sort array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
* @param compareFn campare function ...
|
||
*/
|
||
export function sort<T>(
|
||
list: XOneOrManyType<T>,
|
||
compareFn?: (a: T, b: T) => number
|
||
) {
|
||
//
|
||
const array = toArray(list);
|
||
var result = array.sort(compareFn);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* retrieve only unique members of an Array ...
|
||
*
|
||
* @param list an instance of XOneOrManyType<any> object ...
|
||
*/
|
||
export function onlyUniques<T>(list: XOneOrManyType<T>) {
|
||
return toArray(list).filter((v, i, s) => s.indexOf(v) === i);
|
||
}
|
||
|
||
/**
|
||
* Check two Array is Equals or not ...
|
||
*
|
||
* @param a
|
||
* @param b
|
||
* @returns
|
||
*/
|
||
export function isXEqual<T>(a: T[], b: T[]): boolean {
|
||
if (a.length !== b.length) return false;
|
||
return a.every(
|
||
(value, index) =>
|
||
JSON.stringify(value) === JSON.stringify(b[index]) &&
|
||
typeof value === typeof b[index]
|
||
);
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-color.tools.ts
|
||
|
||
import {
|
||
isNumber,
|
||
isString,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import {
|
||
XColor,
|
||
XRGBAColor,
|
||
XHSVAColor,
|
||
XHSLAColor,
|
||
XColorIdentifier,
|
||
XColorDescribtor,
|
||
XColorBrightnessLevel,
|
||
XColorFormatIdentifier,
|
||
} from '../typings/x-color.typings';
|
||
import { toNumber, toXString } from './x-type-convert.tools';
|
||
|
||
//
|
||
//#region XColor tools ..
|
||
/**
|
||
* retrieve a color name ...
|
||
*
|
||
* @param color the colorname
|
||
* @param level the color brightness which default is Regular
|
||
*/
|
||
export function getXColorName(
|
||
color: XColorIdentifier,
|
||
level: XColorBrightnessLevel = XColorBrightnessLevel.Regular
|
||
) {
|
||
//
|
||
const mColor = color.toString();
|
||
return level === XColorBrightnessLevel.Regular
|
||
? mColor
|
||
: mColor + `-${level.toString()}`;
|
||
}
|
||
|
||
/**
|
||
* retrieve specific color CSS Variable Name ...
|
||
*
|
||
* @param color Color name
|
||
* @param isContrast determines to get Text Color on Color var name
|
||
* @param level determines color brightness level
|
||
*/
|
||
export function getXColorCssVariableName(
|
||
color: XColorIdentifier,
|
||
isContrast: boolean = false,
|
||
level: XColorBrightnessLevel = XColorBrightnessLevel.Regular
|
||
) {
|
||
//
|
||
return `--x-color-${color.toLowerCase()}${
|
||
level === XColorBrightnessLevel.Regular ? '' : '-' + level.toLowerCase()
|
||
}${!!isContrast ? '-contrast' : ''}`;
|
||
}
|
||
|
||
/**
|
||
* retrieve a color class \ name ...
|
||
*
|
||
* @param color the colorname
|
||
* @param level the color brightness which default is Regular
|
||
*/
|
||
export function getXColorClassName(
|
||
color: XColorIdentifier,
|
||
level: XColorBrightnessLevel = XColorBrightnessLevel.Regular
|
||
) {
|
||
//
|
||
if (color.toString() === 'inherit') {
|
||
return 'cb-inherit';
|
||
}
|
||
|
||
//
|
||
const mColor = 'mat-' + color.toString();
|
||
return level === XColorBrightnessLevel.Regular
|
||
? mColor
|
||
: mColor + `-${level.toString()}`;
|
||
}
|
||
|
||
/**
|
||
* retrieve a color foreground class name ...
|
||
*
|
||
* @param color the colorname
|
||
* @param level the color brightness which default is Regular
|
||
*/
|
||
export function getXColorForegroundClassName(color: XColorIdentifier) {
|
||
//
|
||
if (color.toString() === 'inherit') {
|
||
return 'cb-inherit';
|
||
}
|
||
|
||
//
|
||
const mColor = 'c-' + color.toString();
|
||
return mColor;
|
||
}
|
||
|
||
/**
|
||
* parse a color identifier and return it's descriptor ...
|
||
*
|
||
* @param color the color identifier to parse ...
|
||
*/
|
||
export function parseXColor(color: XColorIdentifier): XColorDescribtor {
|
||
//
|
||
const strColor = color.toString().trim().toLowerCase();
|
||
const isContrast = strColor.includes('contrast');
|
||
const brightnessLevel: XColorBrightnessLevel = strColor.includes('tint')
|
||
? XColorBrightnessLevel.Tint
|
||
: strColor.includes('shade')
|
||
? XColorBrightnessLevel.Shade
|
||
: XColorBrightnessLevel.Regular;
|
||
const name = strColor
|
||
.replace('-', '')
|
||
.replace('contrast', '')
|
||
.replace(brightnessLevel.toString(), '') as XColor;
|
||
|
||
//
|
||
const result: XColorDescribtor = {
|
||
name,
|
||
brightnessLevel,
|
||
isContrast,
|
||
};
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Color Parsers / Converters ...
|
||
//
|
||
//#region RGBA Source ...
|
||
/**
|
||
* determine a color is XRGBAColor or not ...
|
||
*
|
||
* @param v an input color representation ...
|
||
*/
|
||
export function isRGB(v: any) {
|
||
//
|
||
if (isNullOrUndefined(v)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const color = v as XRGBAColor;
|
||
if (isNullOrUndefined(color)) {
|
||
//
|
||
const result =
|
||
!isNullOrUndefined(v.r) &&
|
||
isNumber(v.r) &&
|
||
!isNullOrUndefined(v.g) &&
|
||
isNumber(v.g) &&
|
||
!isNullOrUndefined(v.b) &&
|
||
isNumber(v.b);
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
if (
|
||
isString(v) &&
|
||
toXString(v).includes('rgb') &&
|
||
!toXString(v).includes('rgba')
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* determine a color is XRGBAColor or not ...
|
||
*
|
||
* @param v an input color representation ...
|
||
*/
|
||
export function isRGBA(v: any) {
|
||
//
|
||
if (isNullOrUndefined(v)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const color = v as XRGBAColor;
|
||
if (isNullOrUndefined(color)) {
|
||
//
|
||
const result =
|
||
!isNullOrUndefined(v.r) &&
|
||
isNumber(v.r) &&
|
||
!isNullOrUndefined(v.g) &&
|
||
isNumber(v.g) &&
|
||
!isNullOrUndefined(v.b) &&
|
||
isNumber(v.b) &&
|
||
!isNullOrUndefined(v.a) &&
|
||
isNumber(v.a);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
if (isString(v) && toXString(v).includes('rgba')) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* convert an rgb color to hex representation ...
|
||
*
|
||
* @param color an instance of XRGBAColor ...
|
||
*/
|
||
export function rgbaToHex(color: XRGBAColor): string {
|
||
//
|
||
const r = color.r < 0 ? 0 : color.r > 255 ? 255 : color.r;
|
||
const g = color.g < 0 ? 0 : color.g > 255 ? 255 : color.g;
|
||
const b = color.b < 0 ? 0 : color.b > 255 ? 255 : color.b;
|
||
const a = color.a < 0 ? 0 : color.a > 1 ? 1 : color.a;
|
||
|
||
//
|
||
let sr = r.toString(16);
|
||
let sg = g.toString(16);
|
||
let sb = b.toString(16);
|
||
let sa = Math.round(a * 255).toString(16);
|
||
|
||
//
|
||
sr = sr.length === 1 ? '0' + sr : sr;
|
||
sg = sg.length === 1 ? '0' + sg : sg;
|
||
sb = sb.length === 1 ? '0' + sb : sb;
|
||
sa = sa.length === 1 ? '0' + sa : sa;
|
||
|
||
//
|
||
const result = '#' + sr + sg + sb + sa;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert an rgb color to hex representation ...
|
||
*
|
||
* @param color an instance of XRGBAColor ...
|
||
* @param allowHex8 determines hext string length be 8 char or not ...
|
||
*/
|
||
export function rgbaToHex1(
|
||
color: XRGBAColor,
|
||
allowHex8: boolean = true
|
||
): string {
|
||
//
|
||
let result =
|
||
'#' +
|
||
// tslint:disable-next-line:no-bitwise
|
||
((1 << 24) | (color.r << 16) | (color.g << 8) | color.b)
|
||
.toString(16)
|
||
.substr(1);
|
||
|
||
//
|
||
if (
|
||
result[1] === result[2] &&
|
||
result[3] === result[4] &&
|
||
result[5] === result[6] &&
|
||
color.a === 1 &&
|
||
!allowHex8
|
||
) {
|
||
result = '#' + result[1] + result[3] + result[5];
|
||
}
|
||
|
||
//
|
||
if (allowHex8) {
|
||
// tslint:disable-next-line:no-bitwise
|
||
result += ((1 << 8) | Math.round(color.a * 255)).toString(16).substr(1);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* get an rgb string form color representation ...
|
||
*
|
||
* @param color an instance of XRGBAColor ...
|
||
*/
|
||
export function rgbString(color: XRGBAColor): string {
|
||
//
|
||
if (isNullOrUndefined(color)) {
|
||
return 'rgba(0, 0, 0, 1)';
|
||
}
|
||
|
||
//
|
||
const r = color.r < 0 ? 0 : color.r > 255 ? 255 : color.r;
|
||
const g = color.g < 0 ? 0 : color.g > 255 ? 255 : color.g;
|
||
const b = color.b < 0 ? 0 : color.b > 255 ? 255 : color.b;
|
||
|
||
//
|
||
const result = 'rgb(' + r + ',' + g + ',' + b + ')';
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* get an rgba string form color representation ...
|
||
*
|
||
* @param color an instance of XRGBAColor ...
|
||
*/
|
||
export function rgbaString(color: XRGBAColor): string {
|
||
//
|
||
if (isNullOrUndefined(color)) {
|
||
return 'rgba(0, 0, 0, 1)';
|
||
}
|
||
|
||
//
|
||
const r = color.r < 0 ? 0 : color.r > 255 ? 255 : color.r;
|
||
const g = color.g < 0 ? 0 : color.g > 255 ? 255 : color.g;
|
||
const b = color.b < 0 ? 0 : color.b > 255 ? 255 : color.b;
|
||
const a = color.a < 0 ? 0 : color.a > 1 ? 1 : color.a;
|
||
|
||
//
|
||
const result = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert hsva to XHSVAColor ...
|
||
*
|
||
* @param rgba an XRGBAColor representation of color ...
|
||
*/
|
||
export function rgbaToHsva(rgba: XRGBAColor): XHSVAColor {
|
||
//
|
||
let result: XHSVAColor = null;
|
||
|
||
//
|
||
// Validate Args ...
|
||
if (isNullOrUndefined(rgba)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
rgba.r /= 255;
|
||
rgba.g /= 255;
|
||
rgba.b /= 255;
|
||
|
||
//
|
||
let a = Math.min(rgba.a, 1);
|
||
|
||
//
|
||
let max = Math.max(rgba.r, rgba.g, rgba.b);
|
||
let min = Math.min(rgba.r, rgba.g, rgba.b);
|
||
|
||
//
|
||
let h,
|
||
s,
|
||
v = max;
|
||
var d = max - min;
|
||
s = max == 0 ? 0 : d / max;
|
||
if (max == min) {
|
||
h = 0; // achromatic
|
||
} else {
|
||
switch (max) {
|
||
//
|
||
case rgba.r:
|
||
h = (rgba.g - rgba.b) / d + (rgba.g < rgba.b ? 6 : 0);
|
||
break;
|
||
|
||
//
|
||
case rgba.g:
|
||
h = (rgba.b - rgba.r) / d + 2;
|
||
break;
|
||
|
||
//
|
||
case rgba.b:
|
||
h = (rgba.r - rgba.g) / d + 4;
|
||
break;
|
||
}
|
||
|
||
//
|
||
h /= 6;
|
||
}
|
||
|
||
//
|
||
return {
|
||
h,
|
||
s,
|
||
v,
|
||
a
|
||
}
|
||
}
|
||
|
||
/**
|
||
* converts an string to RGBA instance ...
|
||
*
|
||
* @param value input string value ...
|
||
* @returns an instance of XRGBAColor ...
|
||
*/
|
||
export function stringToRGBA(value: string): XRGBAColor {
|
||
//
|
||
// validate args ...
|
||
if (!isRGBA(value) || isNullOrEmptyString(value)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
// define default result ...
|
||
let result: XRGBAColor = null;
|
||
|
||
//
|
||
// replace color token ...
|
||
value = value.includes('rgba')
|
||
? value.replace('rgba', '')
|
||
: value.includes('rgb')
|
||
? value.replace('rgb', '')
|
||
: value;
|
||
|
||
//
|
||
// Replace paranteses ...
|
||
value = value.replace('(', '').replace(')', '').replace(';', '');
|
||
|
||
//
|
||
// Convert to array ...
|
||
const valuesArr = value.split(',');
|
||
if (valuesArr.length === 3) {
|
||
valuesArr.push('1');
|
||
}
|
||
|
||
//
|
||
// Prepare Materials ...
|
||
const r = toNumber(valuesArr[0]);
|
||
const g = toNumber(valuesArr[1]);
|
||
const b = toNumber(valuesArr[2]);
|
||
const a = toNumber(valuesArr[3]);
|
||
|
||
//
|
||
// Create result ...
|
||
result = {
|
||
r,
|
||
g,
|
||
b,
|
||
a,
|
||
};
|
||
|
||
//
|
||
// return result ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* denormalize XRGBAColor instance ...
|
||
*
|
||
* @param rgba an XRGBAColor representation of color ...
|
||
*/
|
||
export function denormalizeRGBA(color: XRGBAColor): XRGBAColor {
|
||
//
|
||
const result: XRGBAColor = {
|
||
r: Math.round(color.r * 255),
|
||
g: Math.round(color.g * 255),
|
||
b: Math.round(color.b * 255),
|
||
a: color.a,
|
||
};
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region HEX Source ...
|
||
/**
|
||
* convert hex to HSV ...
|
||
*
|
||
* @param color string representor ...
|
||
*/
|
||
export function hexToHsva(hex: string): XHSVAColor {
|
||
//
|
||
let result: XHSVAColor = null;
|
||
|
||
//
|
||
// validate args ...
|
||
if (isNullOrEmptyString(hex) || !isHEX(hex)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// normalize hex ...
|
||
hex = normalizeHexColor(hex, 8);
|
||
|
||
//
|
||
// Convert hex to rgba ...
|
||
const rgba = hexToRgba(hex);
|
||
if (isNullOrUndefined(rgba)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// Generate result ...
|
||
result = rgbaToHsva(rgba);
|
||
|
||
//
|
||
// return result ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert hex to rgba ...
|
||
*
|
||
* @param hex an string which represent color hex ...
|
||
*/
|
||
export function hexToRgba(hex: string): XRGBAColor {
|
||
//
|
||
let r = '0';
|
||
let g = '0';
|
||
let b = '0';
|
||
let a: any = 1;
|
||
|
||
//
|
||
if (hex.length === 7) {
|
||
//
|
||
r = '0x' + hex[1] + hex[1];
|
||
g = '0x' + hex[2] + hex[2];
|
||
b = '0x' + hex[3] + hex[3];
|
||
a = '0x' + hex[4] + hex[4];
|
||
} else if (hex.length === 9) {
|
||
//
|
||
r = '0x' + hex[1] + hex[2];
|
||
g = '0x' + hex[3] + hex[4];
|
||
b = '0x' + hex[5] + hex[6];
|
||
a = '0x' + hex[7] + hex[8];
|
||
}
|
||
|
||
//
|
||
a = +(a / 255).toFixed(3);
|
||
|
||
//
|
||
const result: XRGBAColor = {
|
||
r: +r,
|
||
g: +g,
|
||
b: +b,
|
||
a,
|
||
};
|
||
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @param hex an string ...
|
||
*/
|
||
export function normalizeHexColor(hex: string, forceLength: 6 | 8 = 8) {
|
||
//
|
||
const isValid = isHEX(hex);
|
||
if (!isValid) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
hex = hex.startsWith('#') ? hex.replace('#', '') : hex;
|
||
hex = hex.toLowerCase().trim();
|
||
|
||
//
|
||
let result = '';
|
||
const hexLength = hex.length;
|
||
const hexArr = Array.from(hex);
|
||
|
||
//
|
||
// 6 Length ...
|
||
if (forceLength === 6) {
|
||
//
|
||
if (hexLength === 6) {
|
||
result = hex;
|
||
} else if (hexLength === 3 || hexLength === 4) {
|
||
result =
|
||
hexArr[0] + hexArr[0] + hexArr[1] + hexArr[1] + hexArr[2] + hexArr[2];
|
||
}
|
||
|
||
//
|
||
return `#${result}`;
|
||
}
|
||
|
||
//
|
||
// 8 Length ...
|
||
if (hexLength === 8) {
|
||
result = hex;
|
||
} else if (hexLength === 7) {
|
||
result =
|
||
hexArr[0] +
|
||
hexArr[1] +
|
||
hexArr[2] +
|
||
hexArr[3] +
|
||
hexArr[4] +
|
||
hexArr[5] +
|
||
'f' +
|
||
hexArr[6];
|
||
} else if (hexLength === 6) {
|
||
result = hex + 'ff';
|
||
} else if (hexLength === 4) {
|
||
result =
|
||
hexArr[0] +
|
||
hexArr[0] +
|
||
hexArr[1] +
|
||
hexArr[1] +
|
||
hexArr[2] +
|
||
hexArr[2] +
|
||
hexArr[3] +
|
||
hexArr[3];
|
||
} else if (hexLength === 3) {
|
||
result =
|
||
hexArr[0] + hexArr[0] + hexArr[1] + hexArr[1] + hexArr[2] + hexArr[2];
|
||
}
|
||
|
||
//
|
||
return `#${result}`;
|
||
}
|
||
|
||
/**
|
||
* determines an string is hex color or not ...
|
||
*
|
||
* @param hex an string ...
|
||
* @returns boolean
|
||
*/
|
||
export function isHEX(hex: string) {
|
||
//
|
||
if (isNullOrEmptyString(hex) || isNullOrEmptyString(hex.trim())) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
hex = hex.toLowerCase().trim().replace('#', '');
|
||
|
||
//
|
||
const availableLength = [3, 4, 6, 8];
|
||
const availableDigits = [
|
||
'0',
|
||
'1',
|
||
'2',
|
||
'3',
|
||
'4',
|
||
'5',
|
||
'6',
|
||
'7',
|
||
'8',
|
||
'9',
|
||
'a',
|
||
'b',
|
||
'c',
|
||
'd',
|
||
'e',
|
||
'f',
|
||
];
|
||
|
||
//
|
||
let result = availableLength.findIndex((l) => hex.length === l) > -1;
|
||
if (!!result) {
|
||
result = Array.from(hex).every((char) => availableDigits.includes(char));
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region HSVA Source ...
|
||
/**
|
||
* determine a color is XRGBAColor or not ...
|
||
*
|
||
* @param v an input color representation ...
|
||
*/
|
||
export function isHSVA(v: any) {
|
||
//
|
||
if (isNullOrUndefined(v)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const color = v as XHSVAColor;
|
||
if (isNullOrUndefined(color)) {
|
||
//
|
||
const result =
|
||
!isNullOrUndefined(v.h) &&
|
||
isNumber(v.h) &&
|
||
!isNullOrUndefined(v.s) &&
|
||
isNumber(v.s) &&
|
||
!isNullOrUndefined(v.v) &&
|
||
isNumber(v.v) &&
|
||
!isNullOrUndefined(v.a) &&
|
||
isNumber(v.a);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* convert hsv to hex ...
|
||
*
|
||
* @param color an instance of XHSVColor ...
|
||
*/
|
||
export function hsvaToHex(color: XHSVAColor): string {
|
||
//
|
||
const i = Math.floor(color.h * 6);
|
||
const f = color.h * 6 - i;
|
||
const p = color.v * (1 - color.s);
|
||
const q = color.v * (1 - f * color.s);
|
||
const t = color.v * (1 - (1 - f) * color.s);
|
||
|
||
//
|
||
let r = 0;
|
||
let g = 0;
|
||
let b = 0;
|
||
|
||
//
|
||
switch (i % 6) {
|
||
case 0:
|
||
r = color.v;
|
||
g = t;
|
||
b = p;
|
||
break;
|
||
case 1:
|
||
r = q;
|
||
g = color.v;
|
||
b = p;
|
||
break;
|
||
case 2:
|
||
r = p;
|
||
g = color.v;
|
||
b = t;
|
||
break;
|
||
case 3:
|
||
r = p;
|
||
g = q;
|
||
b = color.v;
|
||
break;
|
||
case 4:
|
||
r = t;
|
||
g = p;
|
||
b = color.v;
|
||
break;
|
||
case 5:
|
||
r = color.v;
|
||
g = p;
|
||
b = q;
|
||
break;
|
||
}
|
||
|
||
//
|
||
r = Math.floor(r * 255) + 256;
|
||
g = Math.floor(g * 255) + 256;
|
||
b = Math.floor(b * 255) + 256;
|
||
|
||
//
|
||
const result =
|
||
'#' +
|
||
r.toString(16).slice(1) +
|
||
g.toString(16).slice(1) +
|
||
b.toString(16).slice(1);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert hsva to XHSLAColor ...
|
||
*
|
||
* @param hsva an XHSVAColor representation of color ...
|
||
*/
|
||
export function hsvaToHsla(hsva: XHSVAColor): XHSLAColor {
|
||
//
|
||
let s = hsva.s;
|
||
const h = hsva.h;
|
||
const v = hsva.v;
|
||
const a = hsva.a;
|
||
|
||
//
|
||
let result: XHSLAColor = {};
|
||
|
||
//
|
||
if (v === 0) {
|
||
//
|
||
result = {
|
||
h,
|
||
s: 0,
|
||
l: 0,
|
||
a,
|
||
};
|
||
} else if (s === 0 && v === 1) {
|
||
//
|
||
result = {
|
||
h,
|
||
s: 1,
|
||
l: 1,
|
||
a,
|
||
};
|
||
} else {
|
||
//
|
||
const l = (v * (2 - s)) / 2;
|
||
s = (v * s) / (1 - Math.abs(2 * l - 1));
|
||
|
||
//
|
||
result = {
|
||
h,
|
||
s,
|
||
l,
|
||
a,
|
||
};
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert hsv to rgba ...
|
||
*
|
||
* @param color an instance of XHSVColor ...
|
||
*/
|
||
export function hsvaToRgba(hsva: XHSVAColor): XRGBAColor {
|
||
//
|
||
const h = hsva.h;
|
||
const s = hsva.s;
|
||
const v = hsva.v;
|
||
const a = hsva.a;
|
||
|
||
//
|
||
let r: number;
|
||
let g: number;
|
||
let b: number;
|
||
|
||
//
|
||
const i = Math.floor(h * 6);
|
||
const f = h * 6 - i;
|
||
const p = v * (1 - s);
|
||
const q = v * (1 - f * s);
|
||
const t = v * (1 - (1 - f) * s);
|
||
|
||
//
|
||
switch (i % 6) {
|
||
case 0:
|
||
(r = v), (g = t), (b = p);
|
||
break;
|
||
case 1:
|
||
(r = q), (g = v), (b = p);
|
||
break;
|
||
case 2:
|
||
(r = p), (g = v), (b = t);
|
||
break;
|
||
case 3:
|
||
(r = p), (g = q), (b = v);
|
||
break;
|
||
case 4:
|
||
(r = t), (g = p), (b = v);
|
||
break;
|
||
case 5:
|
||
(r = v), (g = p), (b = q);
|
||
break;
|
||
}
|
||
|
||
//
|
||
const result: XRGBAColor = {
|
||
r,
|
||
g,
|
||
b,
|
||
a,
|
||
};
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert string representation of a color to XHSVAColor ...
|
||
*
|
||
* @param colorString an string representation of a color ...
|
||
*/
|
||
export function stringToHsva(colorString: string = ''): XHSVAColor {
|
||
//
|
||
// Validate Args ...
|
||
if (isNullOrEmptyString(colorString)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
// Result ...
|
||
let result: XHSVAColor = null;
|
||
|
||
//
|
||
// Get Type ...
|
||
const type = isHEX(colorString)
|
||
? 'hex'
|
||
: isRGBA(colorString)
|
||
? 'rgba'
|
||
: isRGB(colorString)
|
||
? 'rgb'
|
||
: isHSVA(colorString)
|
||
? 'hsva'
|
||
: isHSLA(colorString)
|
||
? 'hsla'
|
||
: 'unknown';
|
||
|
||
//
|
||
// get result value based on input type ...
|
||
switch (type) {
|
||
//
|
||
// 1 Hex ...
|
||
case 'hex':
|
||
result = hexToHsva(colorString);
|
||
break;
|
||
|
||
//
|
||
// 2 RGB ...
|
||
// 3 RGBA ...
|
||
case 'rgb':
|
||
case 'rgba':
|
||
//
|
||
const rgba = stringToRGBA(colorString);
|
||
result = rgbaToHsva(rgba);
|
||
break;
|
||
|
||
//
|
||
result = null;
|
||
break;
|
||
|
||
//
|
||
// 5 HSLA ...
|
||
case 'hsla':
|
||
const hsla = stringToHsla(colorString);
|
||
result = hslaToHsva(hsla);
|
||
break;
|
||
|
||
//
|
||
// 4 HSVA ...
|
||
// 6 Unknown ...
|
||
case 'hsva':
|
||
case 'unknown':
|
||
result = null;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// return result ...
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region HSLA Source ...
|
||
/**
|
||
* determine a color is XRGBAColor or not ...
|
||
*
|
||
* @param v an input color representation ...
|
||
*/
|
||
export function isHSLA(v: any) {
|
||
//
|
||
if (isNullOrUndefined(v)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const color = v as XHSLAColor;
|
||
if (isNullOrUndefined(color)) {
|
||
//
|
||
const result =
|
||
!isNullOrUndefined(v.h) &&
|
||
isNumber(v.h) &&
|
||
!isNullOrUndefined(v.s) &&
|
||
isNumber(v.s) &&
|
||
!isNullOrUndefined(v.l) &&
|
||
isNumber(v.l) &&
|
||
!isNullOrUndefined(v.a) &&
|
||
isNumber(v.a);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* convert hsla to XHSVAColor ...
|
||
*
|
||
* @param hsla an XHSLAColor representation of color ...
|
||
*/
|
||
export function hslaToHsva(hsla: XHSLAColor): XHSVAColor {
|
||
//
|
||
let s = Math.min(hsla.s, 1);
|
||
const h = Math.min(hsla.h, 1);
|
||
const l = Math.min(hsla.l, 1);
|
||
const a = Math.min(hsla.a, 1);
|
||
|
||
//
|
||
let result: XHSVAColor = {};
|
||
|
||
//
|
||
if (l === 0) {
|
||
result = {
|
||
h,
|
||
s: 0,
|
||
v: 0,
|
||
a: 0,
|
||
};
|
||
} else {
|
||
//
|
||
const v = l + (s * (1 - Math.abs(2 * l - 1))) / 2;
|
||
s = (2 * (v - l)) / v;
|
||
|
||
//
|
||
result = {
|
||
h,
|
||
s,
|
||
v,
|
||
a,
|
||
};
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* get an hsla string form color representation ...
|
||
*
|
||
* @param color an instance of XHSLAColor ...
|
||
*/
|
||
export function hslaString(color: XHSLAColor): string {
|
||
//
|
||
if (isNullOrUndefined(color)) {
|
||
return 'hsla(0, 100%, 100%, 1)';
|
||
}
|
||
|
||
//
|
||
const result =
|
||
'hsla(' + color.h + ',' + color.s + '%,' + color.l + '%,' + color.a + ')';
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* converts string to XHSLAColor ...
|
||
*
|
||
* @param value string value ...
|
||
* @returns instance of XHSLAColor instance ...
|
||
*/
|
||
export function stringToHsla(value: string): XHSLAColor {
|
||
//
|
||
let result: XHSLAColor = null;
|
||
|
||
//
|
||
// Validate Args ...
|
||
if (isNullOrEmptyString(value) || !value.includes('hsla')) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// clear unused chars ...
|
||
const hslaArray = value
|
||
.replace('%', '')
|
||
.replace('(', '')
|
||
.replace(')', '')
|
||
.replace(';', '')
|
||
.split(',');
|
||
if (hslaArray.length < 4) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// generate required parts ...
|
||
const h = toNumber(hslaArray[0]);
|
||
const s = toNumber(hslaArray[1]);
|
||
const l = toNumber(hslaArray[2]);
|
||
const a = toNumber(hslaArray[3]);
|
||
|
||
//
|
||
// Create result ...
|
||
result = {
|
||
h,
|
||
s,
|
||
l,
|
||
a,
|
||
};
|
||
|
||
//
|
||
// return result ...
|
||
return result;
|
||
}
|
||
//#endregion
|
||
//#endregion
|
||
|
||
/**
|
||
* format input color ...
|
||
*
|
||
* @param hsva an XHSVAColor representation of a color ...
|
||
* @param format the type of output ...
|
||
* @param allowHex8 convert to 8 length string or not ...
|
||
*/
|
||
export function formatColor(
|
||
hsva: XHSVAColor,
|
||
format: XColorFormatIdentifier,
|
||
allowHex8: boolean
|
||
): string {
|
||
//
|
||
if (isNullOrUndefined(hsva)) {
|
||
hsva = {
|
||
h: 0,
|
||
s: 0,
|
||
v: 0,
|
||
a: 1,
|
||
};
|
||
}
|
||
|
||
//
|
||
if (hsva.a < 1) {
|
||
//
|
||
switch (format) {
|
||
//
|
||
case 'hsla':
|
||
//
|
||
const hsla = hsvaToHsla(hsva);
|
||
|
||
//
|
||
const hslaColor: XHSLAColor = {
|
||
h: Math.round(hsla.h * 360),
|
||
s: Math.round(hsla.s * 100),
|
||
l: Math.round(hsla.l * 100),
|
||
a: Math.round(hsla.a * 100) / 100,
|
||
};
|
||
|
||
//
|
||
return hslaString(hslaColor);
|
||
|
||
//
|
||
default:
|
||
//
|
||
if (allowHex8 && format === 'hex') {
|
||
return rgbaToHex1(denormalizeRGBA(hsvaToRgba(hsva)), allowHex8);
|
||
}
|
||
|
||
//
|
||
const rgba = denormalizeRGBA(hsvaToRgba(hsva));
|
||
rgba.a = Math.round(rgba.a * 100) / 100;
|
||
|
||
//
|
||
return rgbaString(rgba);
|
||
}
|
||
} else {
|
||
//
|
||
switch (format) {
|
||
//
|
||
case 'hsla':
|
||
//
|
||
const hsla = hsvaToHsla(hsva);
|
||
|
||
//
|
||
const hslaColor: XHSLAColor = {
|
||
h: Math.round(hsla.h * 360),
|
||
s: Math.round(hsla.s * 100),
|
||
l: Math.round(hsla.l * 100),
|
||
a: Math.round(hsla.a * 100) / 100,
|
||
};
|
||
|
||
//
|
||
return hslaString(hslaColor);
|
||
|
||
//
|
||
case 'rgba':
|
||
//
|
||
const rgbaColor = denormalizeRGBA(hsvaToRgba(hsva));
|
||
|
||
//
|
||
return rgbaString(rgbaColor);
|
||
|
||
//
|
||
default:
|
||
return rgbaToHex1(denormalizeRGBA(hsvaToRgba(hsva)), allowHex8);
|
||
}
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-date-time.tools.ts
|
||
|
||
import {
|
||
isDate,
|
||
isString,
|
||
isNumber,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import * as moment_ from 'jalali-moment';
|
||
const moment = moment_;
|
||
import { Moment, unitOfTime } from 'jalali-moment';
|
||
import { toXString } from './x-type-convert.tools';
|
||
import { toPersianNumbers } from './x-string.tools';
|
||
import { XLocale } from '../typings/x-translation.typings';
|
||
import { XUnitOfTime } from '../typings/x-date-time.typings';
|
||
|
||
//
|
||
//#region Date Time Utils ...
|
||
export function isDefaultUTCDate(utcDate: Date | string | number): boolean {
|
||
//
|
||
var dateString = isNullOrUndefined(utcDate)
|
||
? '0001-01-01T00:00:00'
|
||
: toXString(utcDate);
|
||
if (
|
||
dateString === '0001-01-01T00:00:00' ||
|
||
dateString === '1901-01-01T00:00:00.000Z'
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
const mDateString = fromUtcDate(utcDate).toISOString();
|
||
if (
|
||
mDateString === '0001-01-01T00:00:00' ||
|
||
mDateString === '1901-01-01T00:00:00.000Z'
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* convert a UTC date to locale ...
|
||
*/
|
||
export function fromUtcDate(utcDate: Date | string | number): Date {
|
||
//
|
||
const mUtcDate = new Date(utcDate);
|
||
|
||
//
|
||
const utcDateObject = Date.UTC(
|
||
mUtcDate.getFullYear(),
|
||
mUtcDate.getMonth(),
|
||
mUtcDate.getDate(),
|
||
mUtcDate.getHours(),
|
||
mUtcDate.getMinutes(),
|
||
mUtcDate.getSeconds(),
|
||
mUtcDate.getMilliseconds()
|
||
);
|
||
|
||
//
|
||
return new Date(utcDateObject);
|
||
}
|
||
|
||
export function fromUtcString(utcDateString: string): Date {
|
||
//
|
||
const utcDate = new Date(utcDateString);
|
||
|
||
//
|
||
return fromUtcDate(utcDate);
|
||
}
|
||
|
||
export function fromUtc(date: Date | string) {
|
||
return isDate(date)
|
||
? fromUtcDate(date)
|
||
: isString(date)
|
||
? fromUtcString(date.toString())
|
||
: new Date();
|
||
}
|
||
|
||
/**
|
||
* format a Date to specific format
|
||
* and return the formatted string, based on forLocal ...
|
||
*/
|
||
export function formatDate(
|
||
date: Date | string,
|
||
forLocale: XLocale,
|
||
format: string,
|
||
isUtc: boolean = false,
|
||
toUtc: boolean = false
|
||
) {
|
||
//
|
||
let momentDate = isUtc ? moment(fromUtc(date)) : moment(date);
|
||
|
||
//
|
||
if (toUtc) {
|
||
momentDate = momentDate.utc();
|
||
}
|
||
|
||
//
|
||
let result = momentDate.format(format);
|
||
|
||
//
|
||
if (forLocale === 'fa-IR') {
|
||
result = toPersianNumbers(result);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function getMomentInstance(
|
||
input?: string | number | Date,
|
||
isUtc?: boolean
|
||
): Moment {
|
||
//
|
||
let startDate = moment(input);
|
||
|
||
//
|
||
if (isUtc) {
|
||
startDate = moment(input).utc();
|
||
}
|
||
|
||
//
|
||
return startDate;
|
||
}
|
||
|
||
export function getDateFormatString(locale?: XLocale) {
|
||
//
|
||
if (locale === 'fa-IR') {
|
||
return 'HH:mm:ss jYYYY/jMM/jDD';
|
||
}
|
||
|
||
//
|
||
return 'YYYY-MM-DD HH:mm:ss';
|
||
}
|
||
|
||
export function getDateOfBirthDateFormatString(locale?: XLocale) {
|
||
//
|
||
if (locale === 'fa-IR') {
|
||
return 'jYYYY/jMM/jDD';
|
||
}
|
||
|
||
//
|
||
return 'YYYY/MM/DD';
|
||
}
|
||
|
||
export function getErrorDateFormatString(locale?: XLocale) {
|
||
//
|
||
if (locale === 'fa-IR') {
|
||
return 'HH:mm:ss-jYYYY/jMM/jDD';
|
||
}
|
||
|
||
//
|
||
return 'YYYY-MM-DD HH:mm:ss';
|
||
}
|
||
|
||
export function getRegularDateFormatString(locale?: XLocale) {
|
||
//
|
||
if (locale === 'fa-IR') {
|
||
return 'HH:mm:ss jYYYY-jMM-jDD';
|
||
}
|
||
|
||
//
|
||
return 'YYYY-MM-DD HH:mm:ss';
|
||
}
|
||
|
||
export function getJustYearFormatString(locale?: XLocale) {
|
||
//
|
||
if (locale === 'fa-IR') {
|
||
return 'jYYYY';
|
||
}
|
||
|
||
//
|
||
return 'YYYY';
|
||
}
|
||
|
||
export function getYear(momentDate: Moment) {
|
||
return momentDate.format('YYYY');
|
||
}
|
||
|
||
export function getMonth(momentDate: Moment) {
|
||
return momentDate.format('MM');
|
||
}
|
||
|
||
export function getDay(momentDate: Moment) {
|
||
return momentDate.format('DD');
|
||
}
|
||
|
||
export function getHours(momentDate: Moment) {
|
||
return momentDate.format('HH');
|
||
}
|
||
|
||
export function getMinutes(momentDate: Moment) {
|
||
return momentDate.format('mm');
|
||
}
|
||
|
||
export function getSeconds(momentDate: Moment) {
|
||
return momentDate.format('ss');
|
||
}
|
||
|
||
export function getMilliseconds(momentDate: Moment) {
|
||
return momentDate.format('SSS');
|
||
}
|
||
|
||
export function getUTCDate(date?: any) {
|
||
//
|
||
if (!date) {
|
||
date = new Date();
|
||
}
|
||
|
||
//
|
||
const mDate = new Date(date).toUTCString();
|
||
|
||
//
|
||
return new Date(mDate);
|
||
}
|
||
|
||
export function getUTCDateString(date?: any) {
|
||
//
|
||
if (!date) {
|
||
date = new Date();
|
||
}
|
||
|
||
//
|
||
const mDate = new Date(date).toUTCString();
|
||
|
||
//
|
||
return mDate;
|
||
}
|
||
|
||
export function createDate(
|
||
year?: string,
|
||
month?: string,
|
||
day?: string,
|
||
hours?: string,
|
||
minutes?: string,
|
||
seconds?: string,
|
||
milliseconds?: string
|
||
) {
|
||
//
|
||
const result = new Date();
|
||
|
||
//
|
||
if (year) {
|
||
result.setFullYear(+year);
|
||
}
|
||
|
||
//
|
||
if (month) {
|
||
result.setMonth(+month - 1);
|
||
}
|
||
|
||
//
|
||
if (day) {
|
||
result.setDate(+day);
|
||
}
|
||
|
||
//
|
||
if (hours) {
|
||
result.setHours(+hours);
|
||
}
|
||
|
||
//
|
||
if (minutes) {
|
||
result.setMinutes(+minutes);
|
||
}
|
||
|
||
//
|
||
if (seconds) {
|
||
result.setSeconds(+seconds);
|
||
}
|
||
|
||
//
|
||
if (milliseconds) {
|
||
result.setMilliseconds(+milliseconds);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function getUnitOfTimeForLocale(
|
||
unit: XUnitOfTime,
|
||
locale: XLocale = 'en-US'
|
||
) {
|
||
//
|
||
let result: unitOfTime.DurationConstructor = null;
|
||
|
||
//
|
||
switch (unit) {
|
||
//
|
||
case XUnitOfTime.Year:
|
||
//
|
||
switch (locale) {
|
||
//
|
||
case 'en-US':
|
||
result = 'year';
|
||
break;
|
||
|
||
//
|
||
case 'fa-IR':
|
||
result = 'jYear';
|
||
break;
|
||
}
|
||
break;
|
||
|
||
//
|
||
case XUnitOfTime.Month:
|
||
//
|
||
switch (locale) {
|
||
//
|
||
case 'en-US':
|
||
result = 'month';
|
||
break;
|
||
|
||
//
|
||
case 'fa-IR':
|
||
result = 'jMonth';
|
||
break;
|
||
}
|
||
break;
|
||
|
||
//
|
||
case XUnitOfTime.Day:
|
||
//
|
||
switch (locale) {
|
||
//
|
||
case 'en-US':
|
||
result = 'day';
|
||
break;
|
||
|
||
//
|
||
case 'fa-IR':
|
||
result = 'jDay';
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* add specific amount of year to start date ...
|
||
*
|
||
* @param date start date ...
|
||
* @param value amount of specific unit of time ...
|
||
* @param locale the locale which required to date handling ...
|
||
*/
|
||
export function addYear(
|
||
date: string | number | Date,
|
||
value: number,
|
||
locale: XLocale = 'en-US'
|
||
) {
|
||
//
|
||
if (isNullOrUndefined(date) || isNullOrEmptyString(locale)) {
|
||
return getMomentInstance(date);
|
||
}
|
||
|
||
//
|
||
let yearSpecifier = getUnitOfTimeForLocale(XUnitOfTime.Year, locale);
|
||
if (isNullOrUndefined(yearSpecifier)) {
|
||
yearSpecifier = 'year';
|
||
}
|
||
|
||
//
|
||
return getMomentInstance(date).add(value, yearSpecifier).toDate();
|
||
}
|
||
|
||
/**
|
||
* add specific amount of month to start date ...
|
||
*
|
||
* @param date start date ...
|
||
* @param value amount of specific unit of time ...
|
||
* @param locale the locale which required to date handling ...
|
||
*/
|
||
export function addMonth(
|
||
date: string | number | Date,
|
||
value: number,
|
||
locale: XLocale = 'en-US'
|
||
) {
|
||
//
|
||
if (isNullOrUndefined(date) || isNullOrEmptyString(locale)) {
|
||
return getMomentInstance(date);
|
||
}
|
||
|
||
//
|
||
let yearSpecifier = getUnitOfTimeForLocale(XUnitOfTime.Month, locale);
|
||
if (isNullOrUndefined(yearSpecifier)) {
|
||
yearSpecifier = 'month';
|
||
}
|
||
|
||
//
|
||
return getMomentInstance(date).add(value, yearSpecifier).toDate();
|
||
}
|
||
|
||
/**
|
||
* add specific amount of days to start date ...
|
||
*
|
||
* @param date start date ...
|
||
* @param value amount of specific unit of time ...
|
||
* @param locale the locale which required to date handling ...
|
||
*/
|
||
export function addDay(
|
||
date: string | number | Date,
|
||
value: number,
|
||
locale: XLocale = 'en-US'
|
||
) {
|
||
//
|
||
if (isNullOrUndefined(date) || isNullOrEmptyString(locale)) {
|
||
return getMomentInstance(date);
|
||
}
|
||
|
||
//
|
||
let yearSpecifier = getUnitOfTimeForLocale(XUnitOfTime.Day, locale);
|
||
if (isNullOrUndefined(yearSpecifier)) {
|
||
yearSpecifier = 'day';
|
||
}
|
||
|
||
//
|
||
return getMomentInstance(date).add(value, yearSpecifier).toDate();
|
||
}
|
||
|
||
export function addUnitOfTime(
|
||
unit?: XUnitOfTime,
|
||
value?: number,
|
||
date?: string | number | Date,
|
||
locale?: XLocale
|
||
) {
|
||
//
|
||
if (isNullOrUndefined(unit)) {
|
||
unit = XUnitOfTime.Year;
|
||
}
|
||
|
||
//
|
||
if (isNullOrUndefined(date)) {
|
||
date = new Date();
|
||
}
|
||
|
||
//
|
||
if (isNullOrUndefined(locale)) {
|
||
locale = 'en-US';
|
||
}
|
||
|
||
//
|
||
if (isNullOrUndefined(value)) {
|
||
value = 0;
|
||
}
|
||
|
||
//
|
||
return getMomentInstance(date)
|
||
.add(value, getUnitOfTimeForLocale(unit, locale))
|
||
.toDate();
|
||
}
|
||
|
||
/**
|
||
* get date time format string of given value ...
|
||
*/
|
||
export function toTimeFormat(value: number) {
|
||
//
|
||
if (value < 10) {
|
||
return `0${value}`;
|
||
} else {
|
||
return `${value}`;
|
||
}
|
||
}
|
||
|
||
export function addSecconds(value?: Date, secconds?: number) {
|
||
//
|
||
let result = new Date();
|
||
|
||
//
|
||
if (value) {
|
||
result = value;
|
||
}
|
||
|
||
//
|
||
if (secconds) {
|
||
result = new Date(result.getTime() + secconds * 1000);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function addMinutes(value?: Date, minutes?: number) {
|
||
return addSecconds(value, minutes ? minutes * 60 : minutes);
|
||
}
|
||
|
||
export function addHours(value?: Date, hours?: number) {
|
||
return addMinutes(value, hours ? hours * 60 : hours);
|
||
}
|
||
|
||
export function isExpiredDate(date: Date | string | number) {
|
||
//
|
||
const nowMills = new Date().getTime();
|
||
const mDateTimeMills = new Date(date).getTime();
|
||
|
||
//
|
||
return nowMills > mDateTimeMills;
|
||
}
|
||
|
||
export function isExpiredUTCDate(utcDate: Date | string | number) {
|
||
//
|
||
const nowUTCString = new Date().toUTCString();
|
||
const nowMills = fromUtcDate(nowUTCString).getTime();
|
||
const mUtcDateTimeMills = fromUtcDate(utcDate).getTime();
|
||
|
||
//
|
||
return nowMills > mUtcDateTimeMills;
|
||
}
|
||
|
||
/**
|
||
* convert a date to it's milliseconds representation format ...
|
||
*
|
||
* @param date date representer
|
||
*/
|
||
export function getMills(date?: Date | any) {
|
||
//
|
||
let mDate: Date;
|
||
if (!date) {
|
||
mDate = new Date();
|
||
} else {
|
||
mDate = new Date(date);
|
||
}
|
||
|
||
//
|
||
return mDate.getTime();
|
||
}
|
||
|
||
/**
|
||
* convert any object to date ...
|
||
*/
|
||
export function momentToDate(date: any) {
|
||
return new Date(moment(date.toString()).format());
|
||
}
|
||
|
||
/**
|
||
* check and compare two date must be same ...
|
||
*/
|
||
export function isSameDate(sourceDate: any, destDate: any) {
|
||
//
|
||
const sourceTime = new Date(sourceDate).getTime();
|
||
const destTime = new Date(destDate).getTime();
|
||
|
||
//
|
||
return sourceDate === destDate;
|
||
}
|
||
|
||
/**
|
||
* check a given value has a date or not ...
|
||
*
|
||
* @param source given value to check ...
|
||
*/
|
||
export function isValueDate(source: any) {
|
||
//
|
||
let result = isDate(source);
|
||
if (!result && (isString(source) || isNumber(source))) {
|
||
//
|
||
let d: Date = null;
|
||
try {
|
||
d = new Date(source);
|
||
} catch {}
|
||
|
||
//
|
||
result = !isNullOrUndefined(d) && isDate(d);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-exception.tools.ts
|
||
|
||
import {
|
||
keys,
|
||
getVal,
|
||
fromJson,
|
||
parseJson,
|
||
toJsonString,
|
||
} from './x-object.tools';
|
||
import { toNumber } from './x-type-convert.tools';
|
||
import { toNormalString } from './x-string.tools';
|
||
import { HttpErrorResponse } from '@angular/common/http';
|
||
import { XExceptions, XException } from '../typings/x-exception.typings';
|
||
import { isNumber, isString, isNullOrUndefined } from './x-type-detect.tools';
|
||
import { XExceptionIDs, Exceptions } from '../constants/x-exception.resources';
|
||
|
||
export function getXException(exception: XExceptionIDs | XExceptions) {
|
||
//
|
||
const isExId = isNumber(exception);
|
||
const exceptionKey = isExId ? getVal(XExceptionIDs, exception) : exception;
|
||
|
||
//
|
||
return Exceptions[exceptionKey];
|
||
}
|
||
|
||
export function getXExceptionsArray() {
|
||
//
|
||
const result: XException[] =
|
||
keys(Exceptions).map((key: any) => Exceptions[key]) || [];
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function getXExceptionByErrorId(errorId: number) {
|
||
//
|
||
const result = getXExceptionsArray().find((e) => e.id === toNumber(errorId));
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Prepare and Return Specific Error object
|
||
*/
|
||
export function getError(error: XExceptionIDs | XExceptions | XException) {
|
||
//
|
||
const isExId = isNumber(error);
|
||
const isExTitle = isString(error);
|
||
|
||
//
|
||
return new Error(
|
||
toJsonString(
|
||
isExId
|
||
? getXException(error as XExceptionIDs)
|
||
: isExTitle
|
||
? getXException(error as XExceptions)
|
||
: (error as XException)
|
||
)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* extract Exception information of given error param
|
||
*/
|
||
export function getErrorException(err: any = undefined) {
|
||
//
|
||
if (isNullOrUndefined(err)) {
|
||
err = Exceptions.Unknown;
|
||
}
|
||
|
||
//
|
||
let exception: XException;
|
||
|
||
//
|
||
if (err instanceof HttpErrorResponse) {
|
||
err = err.error;
|
||
} else if (err instanceof Error) {
|
||
err = parseJson(err.message);
|
||
} else {
|
||
try {
|
||
err = parseJson(toNormalString(err));
|
||
} catch {}
|
||
}
|
||
|
||
//
|
||
if (isValidException(err)) {
|
||
exception = getXExceptionByErrorId(err.id);
|
||
} else if (isNumber(err) || isString(err)) {
|
||
exception = getXException(err);
|
||
} else if (err.id && isNumber(err.id)) {
|
||
exception = getXExceptionByErrorId(err.id);
|
||
}
|
||
|
||
//
|
||
if (!exception) {
|
||
exception = Exceptions.Unknown;
|
||
}
|
||
|
||
//
|
||
return exception;
|
||
}
|
||
|
||
/**
|
||
* check an object is Valid Exception or not ...
|
||
*/
|
||
export function isValidException(err: any) {
|
||
//
|
||
if (isNullOrUndefined(err)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
if (err.id && isNumber(err.id) && err.message && isString(err.message)) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
if (err.hasOwnProperty('id') && err.hasOwnProperty('message')) {
|
||
try {
|
||
const jExp = fromJson<XException>(err);
|
||
if (jExp.id && isNumber(jExp) && jExp.message && isString(jExp.message)) {
|
||
return true;
|
||
}
|
||
} catch {}
|
||
}
|
||
|
||
//
|
||
const jsonStr = toNormalString(toJsonString(err));
|
||
if (jsonStr.indexOf('id') !== -1 && jsonStr.indexOf('message') !== -1) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
export function throwException(
|
||
exception: XExceptionIDs | XExceptions | XException
|
||
): never {
|
||
//
|
||
throw getError(exception);
|
||
}
|
||
|
||
export type XExceptionIdentifier =
|
||
| XExceptionIDs
|
||
| XExceptions
|
||
| XException
|
||
| string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-file.tools.ts
|
||
|
||
import {
|
||
XMimeType,
|
||
XRouterTarget,
|
||
XMimeTypeIdentifier,
|
||
XRouterTargetIdentifier,
|
||
} from '../typings/x.typings';
|
||
import {
|
||
isString,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import {
|
||
XFileType,
|
||
XFileInfos,
|
||
TypesMatcher,
|
||
XGeneralThumbnails,
|
||
} from '../constants/x-file.enum';
|
||
import { hasChild } from './x-array.tools';
|
||
import { generateUuid } from './x-uuid-tools';
|
||
import { isSameObject } from './x-object.tools';
|
||
import { toNormalString } from './x-string.tools';
|
||
import { toXString } from './x-type-convert.tools';
|
||
import { DomSanitizer } from '@angular/platform-browser';
|
||
import { XResourceIDs } from '../constants/x-translation.resources';
|
||
|
||
//
|
||
//#region Definitions ...
|
||
export interface XFileBlob {
|
||
lastModified: number;
|
||
name: string;
|
||
size: number;
|
||
type: string;
|
||
}
|
||
|
||
const defaultXFileBlob: XFileBlob = {
|
||
lastModified: 0,
|
||
name: '',
|
||
size: 0,
|
||
type: '',
|
||
};
|
||
//#endregion
|
||
|
||
//
|
||
//#region Helper Methdos ...
|
||
/**
|
||
* extract a file's extension ...
|
||
*
|
||
* @param fileName the file which going to get it's extension
|
||
*/
|
||
export function getExtension(fileName: string) {
|
||
//
|
||
const index = fileName.lastIndexOf('.');
|
||
if (index === -1) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
return fileName.substr(index, fileName.length - index);
|
||
}
|
||
|
||
/**
|
||
* find a file representer object ...
|
||
*
|
||
* @param path file path ...
|
||
* @returns an info object which represent informations about file ...
|
||
*/
|
||
export function getFileInfo(path: string) {
|
||
//
|
||
if (isNullOrEmptyString(path)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const ext = getExtension(path);
|
||
if (isNullOrEmptyString(ext)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const infoObj = XFileInfos.find(
|
||
(inf) => toNormalString(inf.extension) === toNormalString(ext)
|
||
);
|
||
if (isNullOrUndefined(infoObj)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
return infoObj;
|
||
}
|
||
|
||
/**
|
||
* determines an object instance is XFileBlob instance or not ...
|
||
*
|
||
* @param value any object instance ...
|
||
* @returns a boolean value ...
|
||
*/
|
||
export function isXFileBlob(value: any) {
|
||
return isSameObject(value, defaultXFileBlob);
|
||
}
|
||
|
||
/**
|
||
* determines an extension's which exists or not in list
|
||
*
|
||
* @param allowedExtensions the extensions list
|
||
* @param fileExtension the file extensons which searched in list
|
||
*/
|
||
export function isExistsExtension(
|
||
allowedExtensions: string[],
|
||
fileExtension: string
|
||
) {
|
||
//
|
||
if (!fileExtension || !hasChild(allowedExtensions)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
let result = false;
|
||
allowedExtensions.forEach((ext) => {
|
||
//
|
||
if (ext.trim().toLowerCase() === fileExtension.trim().toLowerCase()) {
|
||
//
|
||
result = true;
|
||
}
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* check a file extension is valid and exists in given collection ...
|
||
* @param file input source
|
||
* @param allowedExtensions allowed file extensions ...
|
||
*/
|
||
export function isExtensionOk(file: File, allowedExtensions: string[]) {
|
||
//
|
||
if (!file || !hasChild(allowedExtensions)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const fileExt = getExtension(file.name);
|
||
const result = isExistsExtension(allowedExtensions, fileExt);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Determine the File Size Limitation Passed ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isSizeOk(file: File, maxSingleFileSize: number) {
|
||
return file.size <= maxSingleFileSize;
|
||
}
|
||
|
||
/**
|
||
* Determine the File Size Limitation Passed ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isSizeOkForThumb(file: File, maxSingleFileThumbSize: number) {
|
||
return file.size <= maxSingleFileThumbSize;
|
||
}
|
||
|
||
/**
|
||
* Determine the File is Image or not ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isImage(file: File | Blob | XFileBlob | string) {
|
||
//
|
||
if (file instanceof File || (file instanceof Blob && file.type)) {
|
||
return file.type.toLowerCase().indexOf(TypesMatcher.IMAGE) !== -1;
|
||
} else if (isXFileBlob(file)) {
|
||
//
|
||
const blob = file as XFileBlob;
|
||
const path = !isNullOrUndefined(blob) ? blob.name : '';
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const result =
|
||
obj.type === XFileType.Image ||
|
||
obj.type === XFileType.CoverImage ||
|
||
obj.type === XFileType.ProfileImage;
|
||
return result;
|
||
} else if (isString(file)) {
|
||
//
|
||
const path = toXString(file);
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const result =
|
||
obj.type === XFileType.Image ||
|
||
obj.type === XFileType.CoverImage ||
|
||
obj.type === XFileType.ProfileImage;
|
||
return result;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Determine the File is Video or not ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isVideo(file: File | Blob | XFileBlob | string) {
|
||
//
|
||
if (file instanceof File || (file instanceof Blob && file.type)) {
|
||
return file.type.toLowerCase().indexOf(TypesMatcher.VIDEO) !== -1;
|
||
} else if (isXFileBlob(file)) {
|
||
//
|
||
const blob = file as XFileBlob;
|
||
const path = !isNullOrUndefined(blob) ? blob.name : '';
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Video;
|
||
} else if (isString(file)) {
|
||
//
|
||
const path = toXString(file);
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Video;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Determine the File is Audio or not ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isAudio(file: File | Blob | XFileBlob | string) {
|
||
//
|
||
if (file instanceof File || (file instanceof Blob && file.type)) {
|
||
return file.type.toLowerCase().indexOf(TypesMatcher.AUDIO) !== -1;
|
||
} else if (isXFileBlob(file)) {
|
||
//
|
||
const blob = file as XFileBlob;
|
||
const path = !isNullOrUndefined(blob) ? blob.name : '';
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Video;
|
||
} else if (isString(file)) {
|
||
//
|
||
const path = toXString(file);
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Video;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Determine the File is Document or not ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isDocument(file: File | Blob | XFileBlob | string) {
|
||
//
|
||
if (file instanceof File || (file instanceof Blob && file.type)) {
|
||
return !isImage(file) && !isAudio(file) && !isVideo(file);
|
||
} else if (isXFileBlob(file)) {
|
||
//
|
||
const blob = file as XFileBlob;
|
||
const path = !isNullOrUndefined(blob) ? blob.name : '';
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Document;
|
||
} else if (isString(file)) {
|
||
//
|
||
const path = toXString(file);
|
||
const obj = getFileInfo(path);
|
||
if (isNullOrUndefined(obj)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return obj.type === XFileType.Document;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Image ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isImageAndSizeOk(file: File, maxSingleFileSize: number) {
|
||
return isSizeOk(file, maxSingleFileSize) && isImage(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Audio ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isAudioAndSizeOk(file: File, maxSingleFileSize: number) {
|
||
return isSizeOk(file, maxSingleFileSize) && isAudio(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Video ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isVideoAndSizeOk(file: File, maxSingleFileSize: number) {
|
||
return isSizeOk(file, maxSingleFileSize) && isVideo(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Document ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isDocumentAndSizeOk(file: File, maxSingleFileSize: number) {
|
||
return isSizeOk(file, maxSingleFileSize) && isDocument(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Image ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isImageAndSizeOkForThumb(
|
||
file: File,
|
||
maxSingleFileThumbSize: number
|
||
) {
|
||
return isSizeOkForThumb(file, maxSingleFileThumbSize) && isImage(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Audio ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isAudioAndSizeOkForThumb(
|
||
file: File,
|
||
maxSingleFileThumbSize: number
|
||
) {
|
||
return isSizeOkForThumb(file, maxSingleFileThumbSize) && isAudio(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Video ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isVideoAndSizeOkForThumb(
|
||
file: File,
|
||
maxSingleFileThumbSize: number
|
||
) {
|
||
return isSizeOkForThumb(file, maxSingleFileThumbSize) && isVideo(file);
|
||
}
|
||
|
||
/**
|
||
* Check file size is ok and type is Document ...
|
||
* @param file File instance ...
|
||
*/
|
||
export function isDocumentAndSizeOkForThumb(
|
||
file: File,
|
||
maxSingleFileThumbSize: number
|
||
) {
|
||
return isSizeOkForThumb(file, maxSingleFileThumbSize) && isDocument(file);
|
||
}
|
||
|
||
/**
|
||
* retrieve type of a file identifier ...
|
||
*
|
||
* @param file an identifier to a file ...
|
||
* @returns XFileType ...
|
||
*/
|
||
export function getFileType(file: File | Blob | XFileBlob | string | any) {
|
||
//
|
||
const isFile = file instanceof File || file instanceof Blob;
|
||
if (isFile) {
|
||
//
|
||
const mFile = file as Blob;
|
||
if (isImage(mFile)) {
|
||
return XFileType.Image;
|
||
} else if (isAudio(mFile)) {
|
||
return XFileType.Audio;
|
||
} else if (isVideo(mFile)) {
|
||
return XFileType.Video;
|
||
} else {
|
||
return XFileType.Document;
|
||
}
|
||
} else if ((file as any).type) {
|
||
return (file as any).type as XFileType;
|
||
} else if (isXFileBlob(file)) {
|
||
//
|
||
const obj = file as XFileBlob;
|
||
const path = obj.name;
|
||
const info = getFileInfo(path);
|
||
if (isNullOrUndefined(info)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
return info.type;
|
||
} else if (isString(file)) {
|
||
//
|
||
const path = toXString(file);
|
||
const info = getFileInfo(path);
|
||
if (isNullOrUndefined(info)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
return info.type;
|
||
} else {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function generateFileName(blob: Blob, prefix?: string) {
|
||
//
|
||
const type = getFileType(blob);
|
||
const result = `${
|
||
isNullOrEmptyString(prefix) ? '' : prefix + '_'
|
||
}${generateUuid()}.${
|
||
type === XFileType.Image
|
||
? 'jpg'
|
||
: type === XFileType.Audio
|
||
? 'mp3'
|
||
: type === XFileType.Video
|
||
? 'mp4'
|
||
: 'doc'
|
||
}`;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function getGeneralThumbnail(
|
||
file: File | Blob | XFileBlob | string | any
|
||
) {
|
||
//
|
||
let result = XGeneralThumbnails.UNKNOWN;
|
||
const type = getFileType(file);
|
||
|
||
//
|
||
switch (type) {
|
||
//
|
||
case XFileType.Audio:
|
||
result = XGeneralThumbnails.AUDIO;
|
||
break;
|
||
|
||
//
|
||
case XFileType.Video:
|
||
result = XGeneralThumbnails.VIDEO;
|
||
break;
|
||
case XFileType.Image:
|
||
result = XGeneralThumbnails.IMAGE;
|
||
break;
|
||
|
||
//
|
||
case XFileType.Document:
|
||
default:
|
||
result = XGeneralThumbnails.DOCUMENT;
|
||
break;
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* represent File instance as FileBlob ...
|
||
* @param file the File instance
|
||
*/
|
||
export function toFileBlob(file: File): XFileBlob {
|
||
return {
|
||
lastModified: file.lastModified,
|
||
type: file.type,
|
||
name: file.name,
|
||
size: file.size,
|
||
} as XFileBlob;
|
||
}
|
||
|
||
/**
|
||
* represent File instance as JSON String ...
|
||
* @param file the File instance
|
||
*/
|
||
export function fileToJsonString(file: File): string {
|
||
return JSON.stringify(toFileBlob(file));
|
||
}
|
||
|
||
/**
|
||
* parse FileBlob from a JSON String ...
|
||
* @param file the File instance
|
||
*/
|
||
export function fileFromJsonString(value: string): XFileBlob | null {
|
||
try {
|
||
return JSON.parse(value) as XFileBlob;
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function toFileBlobs(files: Set<File>): XFileBlob[] {
|
||
//
|
||
const result: XFileBlob[] = [];
|
||
|
||
//
|
||
files.forEach((f) => {
|
||
result.push(toFileBlob(f));
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function dataURLtoFile(dataurl: string | any, filename: string) {
|
||
//
|
||
const arr = dataurl.split(',');
|
||
const mime = arr[0].match(/:(.*?);/)[1];
|
||
const bstr = atob(arr[1]);
|
||
let n = bstr.length;
|
||
const u8arr = new Uint8Array(n);
|
||
|
||
while (n--) {
|
||
u8arr[n] = bstr.charCodeAt(n);
|
||
}
|
||
|
||
//
|
||
return new File([u8arr], filename, { type: mime });
|
||
}
|
||
|
||
export function blobToFile(theBlob: Blob, fileName: string): File {
|
||
//
|
||
const b: any = theBlob;
|
||
|
||
//
|
||
b.lastModifiedDate = new Date();
|
||
b.name = fileName;
|
||
|
||
//
|
||
return theBlob as File;
|
||
}
|
||
|
||
export function getFileTypeResourceId(type: XFileType) {
|
||
switch (type) {
|
||
//
|
||
case XFileType.Audio:
|
||
return XResourceIDs.audio;
|
||
|
||
//
|
||
case XFileType.Video:
|
||
return XResourceIDs.video;
|
||
|
||
//
|
||
case XFileType.Document:
|
||
return XResourceIDs.document;
|
||
|
||
//
|
||
case XFileType.ProfileImage:
|
||
return XResourceIDs.avatar;
|
||
|
||
//
|
||
case XFileType.CoverImage:
|
||
return XResourceIDs.cover_image;
|
||
|
||
//
|
||
case XFileType.Image:
|
||
return XResourceIDs.image;
|
||
|
||
//
|
||
default:
|
||
return XResourceIDs.unknown;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* return file width and height ...
|
||
*
|
||
* @param file source image file
|
||
*/
|
||
export async function getImageDimensions(file: File) {
|
||
//
|
||
if (!file || !isImage(file)) {
|
||
throw new Error('Invalid Args ...');
|
||
}
|
||
|
||
//
|
||
return new Promise<{ width: number; height: number }>((res, err) => {
|
||
//
|
||
const reader: FileReader = new FileReader();
|
||
|
||
//
|
||
reader.onloadend = (e: any) => {
|
||
//
|
||
const dataUrl = e.target.result as string;
|
||
|
||
//
|
||
const img = new Image();
|
||
img.onload = () => {
|
||
//
|
||
res({
|
||
width: img.width,
|
||
height: img.height,
|
||
});
|
||
};
|
||
|
||
//
|
||
img.src = dataUrl;
|
||
};
|
||
|
||
//
|
||
reader.onerror = () => {
|
||
err('Error on Reading Image');
|
||
};
|
||
|
||
//
|
||
reader.readAsDataURL(file);
|
||
});
|
||
}
|
||
|
||
export function isImageType(type: XFileType) {
|
||
switch (type) {
|
||
//
|
||
case XFileType.Image:
|
||
case XFileType.CoverImage:
|
||
case XFileType.ProfileImage:
|
||
return true;
|
||
|
||
//
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
//#region Canvas & Image & ArrayBuffer & Blob & File Manipulation Tools ...
|
||
export function resetExifOrientation(srcBase64: string): Promise<string> {
|
||
try {
|
||
const exifRotation = getExifRotation(srcBase64);
|
||
if (exifRotation > 1) {
|
||
return transformBase64BasedOnExifRotation(srcBase64, exifRotation);
|
||
} else {
|
||
return Promise.resolve(srcBase64);
|
||
}
|
||
} catch (ex) {
|
||
return Promise.reject(ex);
|
||
}
|
||
}
|
||
|
||
export function transformBase64BasedOnExifRotation(
|
||
srcBase64: string,
|
||
exifRotation: number
|
||
): Promise<string> {
|
||
return new Promise((resolve, reject) => {
|
||
const img = new Image();
|
||
img.onload = () => {
|
||
const width = img.width;
|
||
const height = img.height;
|
||
const canvas = document.createElement('canvas');
|
||
const ctx = canvas.getContext('2d');
|
||
|
||
if (ctx) {
|
||
if (4 < exifRotation && exifRotation < 9) {
|
||
canvas.width = height;
|
||
canvas.height = width;
|
||
} else {
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
}
|
||
transformCanvas(ctx, exifRotation, width, height);
|
||
ctx.drawImage(img, 0, 0);
|
||
resolve(canvas.toDataURL());
|
||
} else {
|
||
reject(new Error('No context'));
|
||
}
|
||
};
|
||
img.src = srcBase64;
|
||
});
|
||
}
|
||
|
||
export function resizeCanvas(
|
||
canvas: HTMLCanvasElement,
|
||
width: number,
|
||
height: number,
|
||
// tslint:disable-next-line:no-shadowed-variable
|
||
resizeCanvas: boolean = true
|
||
) {
|
||
const widthSource = canvas.width;
|
||
const heightSource = canvas.height;
|
||
width = Math.round(width);
|
||
height = Math.round(height);
|
||
|
||
const ratioW = widthSource / width;
|
||
const ratioH = heightSource / height;
|
||
const ratioWHalf = Math.ceil(ratioW / 2);
|
||
const ratioHHalf = Math.ceil(ratioH / 2);
|
||
|
||
const ctx = canvas.getContext('2d');
|
||
if (ctx) {
|
||
const img = ctx.getImageData(0, 0, widthSource, heightSource);
|
||
const img2 = ctx.createImageData(width, height);
|
||
const data = img.data;
|
||
const data2 = img2.data;
|
||
|
||
for (let j = 0; j < height; j++) {
|
||
for (let i = 0; i < width; i++) {
|
||
//
|
||
const x2 = (i + j * width) * 4;
|
||
const centerY = j * ratioH;
|
||
let weight = 0;
|
||
let weights = 0;
|
||
let weightsAlpha = 0;
|
||
let gxR = 0;
|
||
let gxG = 0;
|
||
let gxB = 0;
|
||
let gxA = 0;
|
||
|
||
//
|
||
const xxStart = Math.floor(i * ratioW);
|
||
const yyStart = Math.floor(j * ratioH);
|
||
|
||
//
|
||
let xxStop = Math.ceil((i + 1) * ratioW);
|
||
let yyStop = Math.ceil((j + 1) * ratioH);
|
||
xxStop = Math.min(xxStop, widthSource);
|
||
yyStop = Math.min(yyStop, heightSource);
|
||
|
||
//
|
||
for (let yy = yyStart; yy < yyStop; yy++) {
|
||
//
|
||
const dy = Math.abs(centerY - yy) / ratioHHalf;
|
||
const centerX = i * ratioW;
|
||
const w0 = dy * dy; // pre-calc part of w
|
||
|
||
//
|
||
for (let xx = xxStart; xx < xxStop; xx++) {
|
||
//
|
||
const dx = Math.abs(centerX - xx) / ratioWHalf;
|
||
const w = Math.sqrt(w0 + dx * dx);
|
||
|
||
//
|
||
if (w >= 1) {
|
||
// pixel too far
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// hermite filter
|
||
weight = 2 * w * w * w - 3 * w * w + 1;
|
||
const posX = 4 * (xx + yy * widthSource);
|
||
|
||
//
|
||
// alpha
|
||
gxA += weight * data[posX + 3];
|
||
weightsAlpha += weight;
|
||
|
||
//
|
||
// colors
|
||
if (data[posX + 3] < 255) {
|
||
weight = (weight * data[posX + 3]) / 250;
|
||
}
|
||
gxR += weight * data[posX];
|
||
gxG += weight * data[posX + 1];
|
||
gxB += weight * data[posX + 2];
|
||
weights += weight;
|
||
}
|
||
}
|
||
|
||
//
|
||
data2[x2] = gxR / weights;
|
||
data2[x2 + 1] = gxG / weights;
|
||
data2[x2 + 2] = gxB / weights;
|
||
data2[x2 + 3] = gxA / weightsAlpha;
|
||
}
|
||
}
|
||
|
||
//
|
||
// clear and resize canvas
|
||
if (resizeCanvas) {
|
||
//
|
||
canvas.width = width;
|
||
canvas.height = height;
|
||
} else {
|
||
ctx.clearRect(0, 0, widthSource, heightSource);
|
||
}
|
||
|
||
//
|
||
// draw
|
||
ctx.putImageData(img2, 0, 0);
|
||
}
|
||
}
|
||
|
||
//
|
||
export function getExifRotation(imageBase64: string): number {
|
||
//
|
||
const view = new DataView(base64ToArrayBuffer(imageBase64));
|
||
if (view.getUint16(0, false) !== 0xffd8) {
|
||
return -2;
|
||
}
|
||
|
||
//
|
||
const length = view.byteLength;
|
||
let offset = 2;
|
||
while (offset < length) {
|
||
//
|
||
if (view.getUint16(offset + 2, false) <= 8) {
|
||
return -1;
|
||
}
|
||
|
||
//
|
||
const marker = view.getUint16(offset, false);
|
||
offset += 2;
|
||
if (marker === 0xffe1) {
|
||
//
|
||
if (view.getUint32((offset += 2), false) !== 0x45786966) {
|
||
return -1;
|
||
}
|
||
|
||
//
|
||
const little = view.getUint16((offset += 6), false) === 0x4949;
|
||
offset += view.getUint32(offset + 4, little);
|
||
const tags = view.getUint16(offset, little);
|
||
offset += 2;
|
||
|
||
//
|
||
for (let i = 0; i < tags; i++) {
|
||
if (view.getUint16(offset + i * 12, little) === 0x0112) {
|
||
return view.getUint16(offset + i * 12 + 8, little);
|
||
}
|
||
}
|
||
// tslint:disable-next-line:no-bitwise
|
||
} else if ((marker & 0xff00) !== 0xff00) {
|
||
break;
|
||
} else {
|
||
offset += view.getUint16(offset, false);
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
export function base64ToArrayBuffer(imageBase64: string) {
|
||
//
|
||
imageBase64 = imageBase64.replace(/^data\:([^\;]+)\;base64,/gim, '');
|
||
const binaryString = atob(imageBase64);
|
||
const len = binaryString.length;
|
||
const bytes = new Uint8Array(len);
|
||
|
||
//
|
||
for (let i = 0; i < len; i++) {
|
||
bytes[i] = binaryString.charCodeAt(i);
|
||
}
|
||
|
||
//
|
||
return bytes.buffer;
|
||
}
|
||
|
||
export function transformCanvas(
|
||
ctx: any,
|
||
orientation: number,
|
||
width: number,
|
||
height: number
|
||
) {
|
||
switch (orientation) {
|
||
case 2:
|
||
ctx.transform(-1, 0, 0, 1, width, 0);
|
||
break;
|
||
case 3:
|
||
ctx.transform(-1, 0, 0, -1, width, height);
|
||
break;
|
||
case 4:
|
||
ctx.transform(1, 0, 0, -1, 0, height);
|
||
break;
|
||
case 5:
|
||
ctx.transform(0, 1, 1, 0, 0, 0);
|
||
break;
|
||
case 6:
|
||
ctx.transform(0, 1, -1, 0, height, 0);
|
||
break;
|
||
case 7:
|
||
ctx.transform(0, -1, -1, 0, height, width);
|
||
break;
|
||
case 8:
|
||
ctx.transform(0, -1, 1, 0, 0, width);
|
||
break;
|
||
}
|
||
}
|
||
|
||
export function arrayBufferToBase64(
|
||
arrBuffer: ArrayBuffer | SharedArrayBuffer
|
||
) {
|
||
//
|
||
try {
|
||
const base64 = btoa(
|
||
new Uint8Array(arrBuffer).reduce(
|
||
(data, byte) => data + String.fromCharCode(byte),
|
||
''
|
||
)
|
||
);
|
||
|
||
//
|
||
return base64;
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function arrayBufferToBase64Image(
|
||
sanitizer: DomSanitizer,
|
||
arrBuffer: ArrayBuffer | SharedArrayBuffer
|
||
) {
|
||
//
|
||
try {
|
||
//
|
||
const base64 = arrayBufferToBase64(arrBuffer);
|
||
|
||
//
|
||
const imageData = 'data:image/png;base64,' + base64;
|
||
return sanitizer.bypassSecurityTrustUrl(imageData);
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export function getBlobURL(fileName: string, fileBlob: Blob) {
|
||
const result = window.URL.createObjectURL(blobToFile(fileBlob, fileName));
|
||
return result;
|
||
}
|
||
|
||
export function toSafeUrl(sanitizer: DomSanitizer, url: any) {
|
||
return sanitizer.bypassSecurityTrustUrl(url);
|
||
}
|
||
|
||
export function removeElement(element: any) {
|
||
//
|
||
if (element) {
|
||
element.remove();
|
||
}
|
||
|
||
//
|
||
element = null;
|
||
}
|
||
|
||
export async function createCanvas(width: number, height: number) {
|
||
//
|
||
const result = document.createElement('canvas');
|
||
|
||
//
|
||
result.width = width;
|
||
result.height = height;
|
||
|
||
//
|
||
return Promise.resolve(result);
|
||
}
|
||
|
||
export async function clipImageToCanvas(
|
||
image: CanvasImageSource,
|
||
clipStartX: number,
|
||
clipStartY: number,
|
||
clipWidth: number,
|
||
clipHeight: number
|
||
) {
|
||
//
|
||
const canvas = await createCanvas(Math.abs(clipWidth), Math.abs(clipHeight));
|
||
//
|
||
const context = canvas.getContext('2d');
|
||
//
|
||
context.drawImage(
|
||
image,
|
||
clipStartX,
|
||
clipStartY,
|
||
clipWidth,
|
||
clipHeight,
|
||
0,
|
||
0,
|
||
canvas.width,
|
||
canvas.height
|
||
);
|
||
//
|
||
removeElement(image);
|
||
return canvas;
|
||
}
|
||
|
||
export async function dataUrlToImage(
|
||
dataUrl: string
|
||
): Promise<HTMLImageElement> {
|
||
//
|
||
return new Promise((resolve) => {
|
||
//
|
||
if (!dataUrl) {
|
||
resolve(null);
|
||
}
|
||
|
||
//
|
||
const image = new Image();
|
||
|
||
//
|
||
image.onload = () => {
|
||
resolve(image);
|
||
};
|
||
|
||
//
|
||
image.onerror = () => {
|
||
resolve(null);
|
||
};
|
||
|
||
//
|
||
image.src = dataUrl;
|
||
});
|
||
}
|
||
|
||
export async function blobToImage(blob: Blob): Promise<HTMLImageElement> {
|
||
//
|
||
return new Promise((resolve) => {
|
||
//
|
||
if (!blob) {
|
||
resolve(null);
|
||
}
|
||
|
||
//
|
||
const url = URL.createObjectURL(blob);
|
||
const image = new Image();
|
||
|
||
//
|
||
image.onload = () => {
|
||
//
|
||
URL.revokeObjectURL(url);
|
||
|
||
//
|
||
resolve(image);
|
||
};
|
||
|
||
//
|
||
image.onerror = () => {
|
||
resolve(null);
|
||
};
|
||
|
||
//
|
||
image.src = url;
|
||
});
|
||
}
|
||
|
||
export async function canvasToDataUrl(
|
||
canvas: HTMLCanvasElement,
|
||
mimeType?: XMimeTypeIdentifier
|
||
) {
|
||
//
|
||
if (!canvas) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
if (!mimeType) {
|
||
mimeType = XMimeType.ImagePNG;
|
||
}
|
||
|
||
//
|
||
const result = canvas.toDataURL(mimeType);
|
||
|
||
//
|
||
return Promise.resolve(result);
|
||
}
|
||
|
||
export async function canvasToBlob(
|
||
canvas: HTMLCanvasElement,
|
||
mimeType?: XMimeTypeIdentifier,
|
||
quality?: number
|
||
): Promise<Blob> {
|
||
//
|
||
return new Promise((resolve) => {
|
||
//
|
||
if (!canvas) {
|
||
resolve(null);
|
||
}
|
||
|
||
//
|
||
if (!mimeType) {
|
||
mimeType = XMimeType.ImagePNG;
|
||
}
|
||
|
||
//
|
||
if (!quality || quality > 1 || quality < 0) {
|
||
quality = 1;
|
||
}
|
||
|
||
//
|
||
canvas.toBlob(
|
||
(blob) => {
|
||
resolve(blob);
|
||
},
|
||
mimeType,
|
||
quality
|
||
);
|
||
});
|
||
}
|
||
|
||
export async function downloadCanvas(
|
||
canvas: HTMLCanvasElement,
|
||
mimeType?: XMimeTypeIdentifier,
|
||
fileName?: string
|
||
) {
|
||
//
|
||
if (!canvas) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
if (!fileName) {
|
||
fileName = `${generateUuid()}.png`;
|
||
}
|
||
|
||
//
|
||
const dataUrl = await canvasToDataUrl(canvas, mimeType);
|
||
if (!dataUrl) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
downloadFileByUrl(dataUrl, fileName);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Download File Actions ...
|
||
export function downloadArrayBufferedFile(fileName: string, fileBlob: Blob) {
|
||
//
|
||
try {
|
||
//
|
||
const url = getBlobURL(fileName, fileBlob);
|
||
|
||
//
|
||
const downloadAnchor = document.createElement('a');
|
||
downloadAnchor.href = url;
|
||
downloadAnchor.download = fileName;
|
||
|
||
//
|
||
downloadAnchor.click();
|
||
} catch {}
|
||
}
|
||
|
||
export function downloadFileByUrl(url: string, fileName: string) {
|
||
//
|
||
const downloadAnchor = document.createElement('a');
|
||
|
||
//
|
||
downloadAnchor.href = url;
|
||
downloadAnchor.target = XRouterTarget.BLANK;
|
||
downloadAnchor.download = fileName;
|
||
|
||
//
|
||
downloadAnchor.click();
|
||
downloadAnchor.remove();
|
||
}
|
||
|
||
/**
|
||
* Method is use to download file.
|
||
*
|
||
* @param data - Array Buffer data
|
||
* @param type - type of the document.
|
||
* @param fileName - name of file.
|
||
* @param target - link target.
|
||
*/
|
||
export function downloadFile(
|
||
data: any,
|
||
mimeType?: string,
|
||
fileName?: string,
|
||
target: XRouterTargetIdentifier = XRouterTarget.BLANK
|
||
): void {
|
||
//
|
||
if (isNullOrUndefined(data)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Wrap by try/catch ...
|
||
try {
|
||
//
|
||
// Prepare Blob based on mimeType ...
|
||
let blob: Blob = null;
|
||
if (isNullOrEmptyString(mimeType)) {
|
||
blob = new Blob([data]);
|
||
} else {
|
||
blob = new Blob([data], { type: mimeType });
|
||
}
|
||
|
||
//
|
||
// Prepare Url ...
|
||
const url = window.URL.createObjectURL(blob);
|
||
|
||
//
|
||
// Create Anchor ...
|
||
const downloadAnchor = document.createElement('a');
|
||
downloadAnchor.href = url;
|
||
|
||
//
|
||
// Prepare Target ...
|
||
if (!isNullOrEmptyString(target)) {
|
||
downloadAnchor.target = target;
|
||
}
|
||
|
||
//
|
||
// Attach FileName ...
|
||
if (!isNullOrEmptyString(fileName)) {
|
||
downloadAnchor.download = fileName;
|
||
}
|
||
|
||
//
|
||
// Click to Download ...
|
||
downloadAnchor.click();
|
||
} catch {}
|
||
}
|
||
//#endregion
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-formatter.tools.ts
|
||
|
||
import { hasChild } from './x-array.tools';
|
||
import { removeAll } from './x-string.tools';
|
||
import { throwException } from './x-exception.tools';
|
||
import { isNullOrEmptyString } from './x-type-detect.tools';
|
||
import { applyLocale } from '../typings/x-translation.typings';
|
||
import { XExceptionIDs } from '../constants/x-exception.resources';
|
||
import { XFormatterOption, XFormatterType } from '../typings/x.typings';
|
||
|
||
/**
|
||
* apply a format to a string ...
|
||
*
|
||
* @param options format options ...
|
||
* @param value a value which required to format ...
|
||
*/
|
||
export function applyFormat(options: XFormatterOption, value: string) {
|
||
//
|
||
value = value ? value.toString() : '';
|
||
options = {
|
||
...(!options ? { type: XFormatterType.ApplyLocale } : options),
|
||
};
|
||
|
||
//
|
||
const type = options.type;
|
||
|
||
//
|
||
// Validate Options Based on Type ...
|
||
switch (type) {
|
||
//
|
||
case XFormatterType.ApplyLocale:
|
||
validateLocale(options);
|
||
break;
|
||
|
||
//
|
||
case XFormatterType.FormatCurrencyAndApplyLocale:
|
||
validateLocale(options);
|
||
validateCurrency(options);
|
||
validateFormatter(options);
|
||
break;
|
||
|
||
//
|
||
case XFormatterType.StringFormatterAndApplyLocale:
|
||
validateLocale(options);
|
||
validatePattern(options);
|
||
validateFormatter(options);
|
||
break;
|
||
|
||
//
|
||
case XFormatterType.FormatCurrency:
|
||
validateCurrency(options);
|
||
validateFormatter(options);
|
||
break;
|
||
|
||
//
|
||
case XFormatterType.StringFormatter:
|
||
validatePattern(options);
|
||
validateFormatter(options);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Prepared Formatted Value ...
|
||
let result = isCurrencyType(options)
|
||
? getCurrencyFormattedValue(options, value)
|
||
: isStringFormatterType(options)
|
||
? getStringFormattedValue(options, value)
|
||
: value || '';
|
||
|
||
//
|
||
// Apply Locale if Localeable Input Type ...
|
||
if (isLocaleType(options)) {
|
||
result = getLocaleFormattedValue(options, result);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* clear applied format ...
|
||
*
|
||
* @param options format options ...
|
||
* @param clearLocale clear applies locale ...
|
||
* @param value a value wich using to clear formatt ...
|
||
*/
|
||
export function clearFormat(
|
||
options: XFormatterOption,
|
||
clearLocale: boolean,
|
||
value: string
|
||
) {
|
||
//
|
||
let result = value.toString() || '';
|
||
|
||
//
|
||
const seperator = isNullOrEmptyString(options.seperator)
|
||
? ''
|
||
: options.seperator;
|
||
|
||
//
|
||
// Remove All occurence of seperator ...
|
||
result = removeAll(value, seperator, true);
|
||
|
||
//
|
||
// Currency Lable ...
|
||
if (isCurrencyType(options) && !isNullOrEmptyString(options.currencyLable)) {
|
||
result = result.replace(options.currencyLable, '').trim();
|
||
}
|
||
|
||
//
|
||
// Change Locale to Default ...
|
||
if (isLocaleType(options)) {
|
||
result = !isNullOrEmptyString(result)
|
||
? applyLocale(
|
||
result,
|
||
clearLocale ? 'en-US' : options.locale ? options.locale : 'en-US'
|
||
)
|
||
: '';
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
//
|
||
//#region applyFormat Function Helpers ...
|
||
//
|
||
function validateLocale(options: XFormatterOption) {
|
||
//
|
||
// || isNullOrEmptyString(options.locale)
|
||
if (!options) {
|
||
throwInvalidArgException();
|
||
}
|
||
}
|
||
|
||
//
|
||
function validateCurrency(options: XFormatterOption) {
|
||
//
|
||
// || isNullOrEmptyString(options.currencyLable)
|
||
if (!options) {
|
||
throwInvalidArgException();
|
||
}
|
||
}
|
||
|
||
//
|
||
function validateFormatter(options: XFormatterOption) {
|
||
//
|
||
// || isNullOrEmptyString(options.seperator)
|
||
if (!options) {
|
||
throwInvalidArgException();
|
||
}
|
||
}
|
||
|
||
//
|
||
function validatePattern(options: XFormatterOption) {
|
||
if (!options || !options.pattern) {
|
||
throwInvalidArgException();
|
||
}
|
||
}
|
||
|
||
//
|
||
function isCurrencyType(options: XFormatterOption) {
|
||
//
|
||
if (!options || !options.type) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
switch (options.type) {
|
||
//
|
||
case XFormatterType.FormatCurrency:
|
||
case XFormatterType.FormatCurrencyAndApplyLocale:
|
||
return true;
|
||
|
||
//
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
function isStringFormatterType(options: XFormatterOption) {
|
||
//
|
||
if (!options || !options.type) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
switch (options.type) {
|
||
//
|
||
case XFormatterType.StringFormatter:
|
||
case XFormatterType.StringFormatterAndApplyLocale:
|
||
return true;
|
||
|
||
//
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
function isLocaleType(options: XFormatterOption) {
|
||
//
|
||
if (!options || !options.type) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
switch (options.type) {
|
||
//
|
||
case XFormatterType.ApplyLocale:
|
||
case XFormatterType.FormatCurrencyAndApplyLocale:
|
||
case XFormatterType.StringFormatterAndApplyLocale:
|
||
return true;
|
||
|
||
//
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
function throwInvalidArgException() {
|
||
throwException(XExceptionIDs.InvalidArgs);
|
||
}
|
||
|
||
//
|
||
function getLocaleFormattedValue(options: XFormatterOption, value: any) {
|
||
//
|
||
const mValue = value ? (value.toString() as string) : '';
|
||
return applyLocale(mValue, options.locale);
|
||
}
|
||
|
||
//
|
||
function getStringFormattedValue(options: XFormatterOption, value: any) {
|
||
//
|
||
const mValue = value ? (value.toString() as string) : '';
|
||
|
||
//
|
||
if (!hasChild(options.pattern)) {
|
||
return mValue;
|
||
}
|
||
|
||
//
|
||
let mSource = mValue;
|
||
let mResultValue = '';
|
||
options.pattern.forEach((l, i) => {
|
||
if (mSource.length >= l) {
|
||
//
|
||
const selected = mSource.substring(0, l);
|
||
|
||
//
|
||
mResultValue +=
|
||
i === options.pattern.length
|
||
? selected
|
||
: `${selected}${options.seperator}`;
|
||
|
||
//
|
||
mSource = mSource.substr(l, mValue.length);
|
||
}
|
||
});
|
||
|
||
//
|
||
if (mSource.length > 0) {
|
||
mResultValue += `${mSource}`;
|
||
}
|
||
|
||
//
|
||
return mResultValue;
|
||
}
|
||
|
||
//
|
||
function getCurrencyFormattedValue(options: XFormatterOption, value: any) {
|
||
//
|
||
const mValue = value ? ((+value).toString() as string) : '';
|
||
const formattedValue = mValue.replace(
|
||
/\B(?=(\d{3})+(?!\d))/g,
|
||
options.seperator
|
||
);
|
||
|
||
//
|
||
const result = !isNullOrEmptyString(options.currencyLable)
|
||
? `${formattedValue} ${options.currencyLable}`
|
||
: formattedValue;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-number.tools.ts
|
||
|
||
//
|
||
//#region Number Tools ...
|
||
/**
|
||
* generate a random number in specific range ...
|
||
*/
|
||
export function random(min?: number, max?: number) {
|
||
//
|
||
if (!min) {
|
||
min = 0;
|
||
}
|
||
|
||
//
|
||
if (!max) {
|
||
max = 1000;
|
||
}
|
||
|
||
//
|
||
min = Math.ceil(min);
|
||
max = Math.floor(max);
|
||
|
||
//
|
||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-object.tools.ts
|
||
|
||
import {
|
||
isDate,
|
||
isArray,
|
||
getType,
|
||
isObject,
|
||
DataTypes,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import {
|
||
XDeep,
|
||
XDeepPartial,
|
||
XBaseKeyValue,
|
||
XModelFieldTypeIndex,
|
||
} from '../typings/x.typings';
|
||
import { Type } from '@angular/core';
|
||
import { isSameDate } from './x-date-time.tools';
|
||
import { countChild, hasChild, lastItem, onlyUniques } from './x-array.tools';
|
||
|
||
//
|
||
//#region Object Tools ...
|
||
/**
|
||
* this is an extension on objects which returns a not refrence copy of an object ...
|
||
*/
|
||
export function clone(obj: any) {
|
||
return Object.assign({}, obj);
|
||
}
|
||
|
||
/**
|
||
* clone an object using JSON ...
|
||
*
|
||
* @param obj source object
|
||
*/
|
||
export function cloneJson<T>(obj: T) {
|
||
return JSON.parse(JSON.stringify(obj)) as T;
|
||
}
|
||
|
||
/**
|
||
* an extension on objects which convert an object to string ...
|
||
*
|
||
* @param obj source object
|
||
*/
|
||
export function toJsonString(obj: any) {
|
||
return JSON.stringify(obj);
|
||
}
|
||
|
||
/**
|
||
* parse a json string to specific type ...
|
||
*
|
||
* @param jsonString a json string to parse ...
|
||
*/
|
||
export function parseJson<T>(jsonString: string) {
|
||
return JSON.parse(jsonString) as T;
|
||
}
|
||
|
||
/**
|
||
* convert object to json string and parse from it ...
|
||
*
|
||
* @param val any object ...
|
||
*/
|
||
export function fromJson<T>(val: any): T {
|
||
return JSON.parse(JSON.stringify(val)) as T;
|
||
}
|
||
|
||
/**
|
||
* assign a Value to an Object ...
|
||
*
|
||
* @param source source object which attached values to it ...
|
||
* @param keyValues key/value pairs to attach to source ...
|
||
*/
|
||
export function assign(
|
||
source: object,
|
||
...keyValues: { key: string; value: any }[]
|
||
) {
|
||
//
|
||
keyValues.forEach((kv) => {
|
||
source[kv.key] = kv.value;
|
||
});
|
||
|
||
//
|
||
return source;
|
||
}
|
||
|
||
/**
|
||
* an extension on objects which returns its keys array ...
|
||
*
|
||
* @param obj source object
|
||
*/
|
||
export function keys(obj: any) {
|
||
//
|
||
if (isNullOrUndefined(obj)) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
return Object.keys(obj);
|
||
}
|
||
|
||
/**
|
||
* return entries of objects ...
|
||
*
|
||
* @param obj object
|
||
*/
|
||
export function entries(obj: any) {
|
||
return Object.entries(obj);
|
||
}
|
||
|
||
/**
|
||
* an extension on objects which returns its values array ...
|
||
*
|
||
* @param obj source object
|
||
*/
|
||
export function values(obj: any) {
|
||
return Object.values(obj);
|
||
}
|
||
|
||
/**
|
||
* iterate over object keys ...
|
||
*
|
||
* @param obj source object
|
||
*/
|
||
export function iterate(obj: any) {
|
||
//
|
||
if (isObject(obj)) {
|
||
//
|
||
for (const property in obj) {
|
||
//
|
||
if (obj.hasOwnProperty(property)) {
|
||
//
|
||
if (isObject(obj[property])) {
|
||
iterate(obj[property]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* retrieve prototype of an object ...
|
||
*
|
||
* @param object source object ...
|
||
*/
|
||
export function getPrototypeOf(object: any) {
|
||
if (Object.getPrototypeOf) {
|
||
return Object.getPrototypeOf(object);
|
||
} else {
|
||
return object.constructor.prototype;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* retrieve Object Key name ...
|
||
*
|
||
* @param propName Object Prop Name
|
||
*/
|
||
export function nameof<T>(propName: keyof T) {
|
||
return propName;
|
||
}
|
||
|
||
/**
|
||
* retrieve Object Key name ...
|
||
*
|
||
* @param propName Object Prop Name
|
||
*/
|
||
export function nameofType<T>(type: Type<T>, propName: keyof T) {
|
||
return propName.toString();
|
||
}
|
||
|
||
/**
|
||
* retrieve Object Key name ...
|
||
*
|
||
* @param propName Object Prop Name
|
||
*/
|
||
export function nameofInstance<T>(obj: T, propName: keyof T) {
|
||
return propName.toString();
|
||
}
|
||
|
||
/**
|
||
* Retrieve Property Type ...
|
||
*
|
||
* @param obj
|
||
* @param key
|
||
* @returns
|
||
*/
|
||
export function getPropertyType<T, K extends keyof T>(obj: T, key: K): T[K] {
|
||
return obj[key];
|
||
}
|
||
|
||
/**
|
||
* Merge two Object ...
|
||
*
|
||
* @param argA Object A
|
||
* @param argB Object B
|
||
*/
|
||
export function merge<T>(argA: Partial<T>, argB: Partial<T>): Partial<T> | any {
|
||
//
|
||
const result = {} as Partial<T>;
|
||
|
||
//
|
||
// Handle ARG A ...
|
||
if (argA) {
|
||
//
|
||
const aKeys = keys(argA);
|
||
if (hasChild(aKeys)) {
|
||
//
|
||
aKeys.forEach((k) => {
|
||
//
|
||
const aValue = argA[k];
|
||
if (aValue) {
|
||
result[k] = aValue;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
//
|
||
// Handle ARG B ...
|
||
if (argB) {
|
||
//
|
||
const bKeys = keys(argB);
|
||
if (hasChild(bKeys)) {
|
||
//
|
||
bKeys.forEach((k) => {
|
||
//
|
||
const bValue = argB[k];
|
||
if (bValue) {
|
||
result[k] = bValue;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export function mergeAll<T>(
|
||
source: Partial<T>,
|
||
...args: Partial<T>[]
|
||
): Partial<T> | any {
|
||
//
|
||
let result = {
|
||
...source,
|
||
} as Partial<T>;
|
||
|
||
//
|
||
args.forEach((arg) => {
|
||
result = merge(result, arg);
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* extract partial content of an object ...
|
||
*
|
||
* @param source source object ...
|
||
* @param modelKeys the object keys for extracting ...
|
||
*/
|
||
export function toPartialObject<T>(
|
||
source: T,
|
||
modelKeys: Array<Partial<keyof T>>
|
||
) {
|
||
//
|
||
if (!source || !hasChild(modelKeys)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const result: Partial<T> = {};
|
||
modelKeys.forEach((k) => {
|
||
if (source[k]) {
|
||
assign(result, { key: k.toString(), value: source[k] });
|
||
}
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert a literal object to map ...
|
||
*
|
||
* @param obj an object to convert ...
|
||
*/
|
||
export function toMap<T>(obj: any): Map<string, T> {
|
||
return new Map(Object.entries(obj));
|
||
}
|
||
|
||
/**
|
||
* retrieve property value ...
|
||
*
|
||
* @param object the context object ...
|
||
* @param prop the property name ...
|
||
*/
|
||
export function getValue<T>(object: T, prop: keyof T) {
|
||
//
|
||
if (object && object[prop]) {
|
||
return object[prop];
|
||
} else {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* retrieve and return an object Filed Names ...
|
||
*
|
||
* @param object the input object of a type ...
|
||
*/
|
||
export function getFieldNames<T>(object: T): XModelFieldTypeIndex<T> {
|
||
return mergeAll<XModelFieldTypeIndex<T>>(
|
||
{},
|
||
...(Object.keys(object).map((k) => {
|
||
return assign({}, { key: k, value: k });
|
||
}) as XModelFieldTypeIndex<T>[])
|
||
);
|
||
}
|
||
|
||
/**
|
||
* retrieve a property value from an object by providing path
|
||
*
|
||
* @param object the model which going to parse
|
||
* @param propertyPath the . seperated property path
|
||
* @returns the object value for specified property
|
||
*/
|
||
export function getPropertyValue<T>(object: T, propertyPath?: string) {
|
||
//
|
||
if (!object || isNullOrEmptyString(propertyPath)) {
|
||
return object;
|
||
}
|
||
|
||
//
|
||
var prop,
|
||
props = propertyPath.split('.');
|
||
|
||
//
|
||
for (var i = 0, iLen = props.length - 1; i < iLen; i++) {
|
||
//
|
||
prop = props[i];
|
||
|
||
//
|
||
var candidate = object[prop];
|
||
|
||
//
|
||
if (candidate !== undefined) {
|
||
object = candidate;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
return object[props[i]];
|
||
}
|
||
|
||
/**
|
||
* set value to specified nested object model ...
|
||
*
|
||
* @param object the model which going to parse
|
||
* @param propertyPath the . seperated property path
|
||
* @param value the value which needs to assign
|
||
* @param forceCreate if object is undefined create it
|
||
*/
|
||
export function setPropertyValue<T>(
|
||
object: T,
|
||
propertyPath: string,
|
||
value?: any,
|
||
forceCreate?: boolean
|
||
) {
|
||
//
|
||
if (!object || isNullOrEmptyString(propertyPath)) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
var prop,
|
||
props = propertyPath.split('.');
|
||
|
||
//
|
||
for (var i = 0, iLen = props.length - 1; i < iLen; i++) {
|
||
//
|
||
prop = props[i];
|
||
|
||
//
|
||
var candidate = object[prop];
|
||
|
||
//
|
||
if (candidate !== undefined) {
|
||
object = candidate;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
object[props[i]] = value;
|
||
}
|
||
|
||
/**
|
||
* retrieve all available property paths of an object
|
||
*
|
||
* @param object the model which going to parse
|
||
* @param prefix the prefix path if reeds to assign
|
||
* @param extractSchema if true extracted arrays instead of objects
|
||
* @param containsChildsObjectHeaders if true the result will contains nested objects headers
|
||
* @returns an array of string which contains all property paths which mach the specified options
|
||
*/
|
||
export function getPropertyPaths<T = any>(
|
||
object: T,
|
||
prefix?: string,
|
||
extractSchema: boolean = false,
|
||
containsChildsObjectHeaders: boolean = false
|
||
) {
|
||
//
|
||
// Create empty result Array ...
|
||
const result: string[] = [];
|
||
|
||
//
|
||
// Check object exists ...
|
||
if (!object) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// get Object keys and check object contains key ...
|
||
const objectKeys = keys(object);
|
||
if (!hasChild(objectKeys)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
// loop through keys ...
|
||
for (let i = 0; i < objectKeys.length; i++) {
|
||
//
|
||
//#region Extarct required info ...
|
||
//
|
||
// Current key for process ...
|
||
const key = objectKeys[i];
|
||
|
||
//
|
||
// the master object value based on current key ...
|
||
const value = object[key];
|
||
|
||
//
|
||
// prepare prefix for current key ...
|
||
const keyPath = isNullOrEmptyString(prefix) ? key : `${prefix}.${key}`;
|
||
//#endregion
|
||
|
||
//
|
||
// determine the value related to current key is an iterable object
|
||
// and required to handle it as nested object or not ...
|
||
const canResurse = isObject(value) || isArray(value);
|
||
if (canResurse) {
|
||
//
|
||
// if value must recursivly checked (Nested Objects) ...
|
||
|
||
//
|
||
// if containsChildsObjectHeaders set to true add keyPath to result ...
|
||
if (!!containsChildsObjectHeaders) {
|
||
result.push(keyPath);
|
||
}
|
||
|
||
//
|
||
// define current value empty paths array ...
|
||
let partPaths: string[] = [];
|
||
if (!!extractSchema) {
|
||
//
|
||
// if extractSchema set to true ...
|
||
|
||
//
|
||
// For array nested values add .0 path az first argumentt ...
|
||
if (isArray(value)) {
|
||
result.push(`${keyPath}.0`);
|
||
}
|
||
|
||
//
|
||
// get value path parts recursively based on type of value ...
|
||
partPaths = isArray(value)
|
||
? //
|
||
// for Array Values retrieve only first childs type paths ...
|
||
getPropertyPaths(
|
||
(value as any[])[0],
|
||
`${keyPath}.0`,
|
||
extractSchema,
|
||
containsChildsObjectHeaders
|
||
)
|
||
: //
|
||
// for Object Values retrieve all including keys ...
|
||
getPropertyPaths(
|
||
value,
|
||
keyPath,
|
||
extractSchema,
|
||
containsChildsObjectHeaders
|
||
);
|
||
} else {
|
||
//
|
||
// if extractSchema set to false ...
|
||
// retrieve all available paths recursivly as an Object ...
|
||
partPaths = getPropertyPaths(
|
||
value,
|
||
keyPath,
|
||
extractSchema,
|
||
containsChildsObjectHeaders
|
||
);
|
||
}
|
||
|
||
//
|
||
// Check part Paths hasChild or not and attach proper values to result ...
|
||
if (hasChild(partPaths)) {
|
||
result.push(...partPaths);
|
||
} else {
|
||
result.push(keyPath);
|
||
}
|
||
} else {
|
||
//
|
||
// if value isprimitive type and no Nested Object ...
|
||
result.push(keyPath);
|
||
}
|
||
}
|
||
|
||
//
|
||
// return result ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* retrieve an specified object schema property paths ...
|
||
*
|
||
* @param object the model which going to parse
|
||
* @returns an array of string which contains all object's schema property paths
|
||
*/
|
||
export function getSchemaPaths<T = any>(object: T) {
|
||
return getPropertyPaths(object, undefined, true, true);
|
||
}
|
||
|
||
/**
|
||
* generate an object based on given property paths ...
|
||
*
|
||
* @param paths an string array which represent all property paths of an Object ...
|
||
* @param defaultValue determines default value which set to generated object's primitive properties ...
|
||
* @returns an specified type object
|
||
*/
|
||
export function generateObjectFromPaths<T = any>(
|
||
paths: string[],
|
||
assginPropertyName: boolean = false,
|
||
defaultValue: any = null
|
||
): XDeep<T> {
|
||
//
|
||
// Check paths contains childs ...
|
||
if (!hasChild(paths)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
// create empty result ...
|
||
let result = {} as XDeep<T>;
|
||
|
||
//
|
||
// loop through all paths ...
|
||
for (let i = 0; i < paths.length; i++) {
|
||
//
|
||
// current property path ...
|
||
const path = paths[i];
|
||
|
||
//
|
||
// filter all paths and exclude current path from them ...
|
||
const filteredPaths = paths.filter((p) => p.includes(path) && p !== path);
|
||
|
||
//
|
||
// if filtered paths contains any childs this means current property is a nested object or array ...
|
||
const isNode = countChild(filteredPaths) > 0;
|
||
|
||
//
|
||
// if filtered paths contains any childs including current path +'.0' this means current property is a nested array ...
|
||
const isArray = isNode && filteredPaths.includes(`${path}.0`);
|
||
|
||
//
|
||
if (!!assginPropertyName) {
|
||
//
|
||
const pathParts = path.includes('.') ? path.split('.') : [];
|
||
defaultValue = hasChild(pathParts) ? lastItem(pathParts) : path;
|
||
}
|
||
|
||
//
|
||
// set proper value to result object's current property as following:
|
||
// - if is a node set {};
|
||
// - if is an array set [];
|
||
// - if primitive or else set defaultValue;
|
||
setPropertyValue(result, path, isNode ? (isArray ? [] : {}) : defaultValue);
|
||
}
|
||
|
||
//
|
||
// return result object ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* generate an object based on given property paths ...
|
||
*
|
||
* @param paths an string array which represent all property paths of an Object ...
|
||
* @param defaultValue determines default value which set to generated object's primitive properties ...
|
||
* @returns an specified type object
|
||
*/
|
||
export function generatePartialObjectFromPaths<T = any>(
|
||
paths: string[],
|
||
assginPropertyName: boolean = false,
|
||
defaultValue: any = null
|
||
): XDeepPartial<T> {
|
||
//
|
||
// Check paths contains childs ...
|
||
if (!hasChild(paths)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
// create empty result ...
|
||
let result = {} as XDeepPartial<T>;
|
||
|
||
//
|
||
// loop through all paths ...
|
||
for (let i = 0; i < paths.length; i++) {
|
||
//
|
||
// current property path ...
|
||
const path = paths[i];
|
||
|
||
//
|
||
// filter all paths and exclude current path from them ...
|
||
const filteredPaths = paths.filter((p) => p.includes(path) && p !== path);
|
||
|
||
//
|
||
// if filtered paths contains any childs this means current property is a nested object or array ...
|
||
const isNode = countChild(filteredPaths) > 0;
|
||
|
||
//
|
||
// if filtered paths contains any childs including current path +'.0' this means current property is a nested array ...
|
||
const isArray = isNode && filteredPaths.includes(`${path}.0`);
|
||
|
||
//
|
||
if (!!assginPropertyName) {
|
||
//
|
||
const pathParts = path.includes('.') ? path.split('.') : [];
|
||
defaultValue = hasChild(pathParts) ? lastItem(pathParts) : path;
|
||
}
|
||
|
||
//
|
||
// set proper value to result object's current property as following:
|
||
// - if is a node set {};
|
||
// - if is an array set [];
|
||
// - if primitive or else set defaultValue;
|
||
setPropertyValue(result, path, isNode ? (isArray ? [] : {}) : defaultValue);
|
||
}
|
||
|
||
//
|
||
// return result object ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* generate an Schema object which represent given object ...
|
||
*
|
||
* @param object the model which going to parse
|
||
* @param defaultValue determines default value which set to Schema object's primitive properties ...
|
||
* @returns an Schema object
|
||
*/
|
||
export function getSchema<T = any>(
|
||
object: T,
|
||
defaultValue: any = null
|
||
): XDeep<T> {
|
||
//
|
||
const paths = getSchemaPaths(object);
|
||
const result = generateObjectFromPaths<T>(paths, true, defaultValue);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* generate an Schema object which represent given object ...
|
||
*
|
||
* @param object the model which going to parse
|
||
* @param defaultValue determines default value which set to Schema object's primitive properties ...
|
||
* @returns an Schema object
|
||
*/
|
||
export function getPartialSchema<T = any>(
|
||
object: T,
|
||
defaultValue: any = null
|
||
): XDeepPartial<T> {
|
||
//
|
||
const paths = getSchemaPaths(object);
|
||
const result = generatePartialObjectFromPaths<T>(paths, true, defaultValue);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* retrieve all exists path required to model actions ...
|
||
*
|
||
* @param object input object
|
||
* @returns an array of required paths for model actions
|
||
*/
|
||
export function extractModelInfoPaths<T = any>(object: T) {
|
||
//
|
||
const schemaPaths = getSchemaPaths(object);
|
||
const result = onlyUniques(schemaPaths.map((part) => part.replace('.0', '')));
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* retrieve an object of all available paths to model actions ...
|
||
*
|
||
* @param object input object
|
||
* @returns an object which filled by required paths
|
||
*/
|
||
export function extractModelInfoObject<T = any>(object: T) {
|
||
//
|
||
const modelInfoPaths = extractModelInfoPaths(object);
|
||
const modelInfoKeyValuePairs = modelInfoPaths.map((path) => {
|
||
//
|
||
const result: XBaseKeyValue<string> = {
|
||
key: path,
|
||
value: path,
|
||
};
|
||
|
||
//
|
||
return assign({}, result);
|
||
});
|
||
const result = mergeAll({}, ...modelInfoKeyValuePairs) as any;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Same Checkers ...
|
||
/**
|
||
* Check two object of Type is Same or not ...
|
||
*
|
||
* @param source the source object which required to type check
|
||
* @param dest the dest object which checked type with source
|
||
* @param forceMemberTypes determines all property types in each object must be same as type in other one. default is false
|
||
*/
|
||
export function isSameType(source: any, dest: any, forceMemberTypes = false) {
|
||
//
|
||
if (!source || !dest) {
|
||
return !source && !dest;
|
||
}
|
||
|
||
//
|
||
const sType = getType(source);
|
||
const dType = getType(dest);
|
||
|
||
//
|
||
if (sType !== dType) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
if (sType === DataTypes.Object) {
|
||
//
|
||
// get Keys ...
|
||
const sourceKeys = keys(source);
|
||
const destKeys = keys(dest);
|
||
|
||
//
|
||
if (countChild(sourceKeys) !== countChild(destKeys)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const isAllSourceKeyExistsInDestKeys = sourceKeys.every((k) =>
|
||
destKeys.includes(k)
|
||
);
|
||
const isAllDestKeyExistsInSourceKeys = destKeys.every((k) =>
|
||
sourceKeys.includes(k)
|
||
);
|
||
|
||
//
|
||
if (!isAllSourceKeyExistsInDestKeys || !isAllDestKeyExistsInSourceKeys) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
if (forceMemberTypes) {
|
||
//
|
||
let memberTypesResult = true;
|
||
sourceKeys.forEach((k) => {
|
||
//
|
||
const kInSourceType = getType(source[k]);
|
||
const kInDestType = getType(dest[k]);
|
||
|
||
//
|
||
if (kInDestType !== kInSourceType) {
|
||
memberTypesResult = false;
|
||
}
|
||
});
|
||
|
||
//
|
||
if (!memberTypesResult) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Check Source and Destination array is Same ...
|
||
*
|
||
* @param source source array
|
||
* @param dest destination array
|
||
*/
|
||
export function isSameArray(
|
||
source: any[],
|
||
dest: any[],
|
||
forceCheckType?: boolean
|
||
): boolean {
|
||
//
|
||
if (!source || !dest) {
|
||
return (!source && !dest) as boolean;
|
||
}
|
||
|
||
//
|
||
if (source.length !== dest.length) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
if (!isSameType(source, dest)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const result = source.sort().every((v, i) => {
|
||
//
|
||
const s = v;
|
||
const d = dest.sort()[i];
|
||
|
||
//
|
||
if (!!forceCheckType) {
|
||
if (!isSameType(s, d)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
if (isArray(s)) {
|
||
return isSameArray(s, d, forceCheckType);
|
||
}
|
||
|
||
//
|
||
if (isObject(s)) {
|
||
return isSameObject(s, d, forceCheckType);
|
||
}
|
||
|
||
//
|
||
return v === dest.sort()[i];
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Check and Compare source and dest objects ...
|
||
*
|
||
* @param source source object
|
||
* @param dest destination object
|
||
* @param forceSameType check type of each member
|
||
*/
|
||
export function isSameObject(
|
||
source: object,
|
||
dest: object,
|
||
forceCheckType?: boolean
|
||
): boolean {
|
||
//
|
||
if (!source || !dest) {
|
||
return (!source && !dest) as boolean;
|
||
}
|
||
|
||
//
|
||
const sKeysArr = Object.keys(source);
|
||
const dKeysArr = Object.keys(dest);
|
||
|
||
//
|
||
const isSameKeys = isSameArray(sKeysArr, dKeysArr, forceCheckType);
|
||
if (!isSameKeys) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const result = sKeysArr.every((v, i) => {
|
||
//
|
||
const s = source[v];
|
||
const d = dest[v];
|
||
|
||
//
|
||
if (!!forceCheckType) {
|
||
if (!isSameType(s, d)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//
|
||
if (isArray(s)) {
|
||
return isSameArray(s, d, forceCheckType);
|
||
}
|
||
|
||
//
|
||
if (isDate(s)) {
|
||
return isSameDate(s, d);
|
||
}
|
||
|
||
//
|
||
if (isObject(s)) {
|
||
return isSameObject(s, d, forceCheckType);
|
||
}
|
||
|
||
//
|
||
return s === d;
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* Check Interface Types ...
|
||
*/
|
||
export function isOfType<T>(value: any, keys: (keyof T)[]): value is T {
|
||
return (
|
||
typeof value === "object" &&
|
||
value !== null &&
|
||
keys.every(k => k in value)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Create a Type Guard Function ...
|
||
*
|
||
* @param keys
|
||
* @returns
|
||
*/
|
||
export function typeGuard<T>(keys: (keyof T)[]) {
|
||
return (value: any): value is T =>
|
||
typeof value === "object" &&
|
||
value !== null &&
|
||
keys.every(k => k in value);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Enum Utils ...
|
||
/**
|
||
* return Keys of Enum ...
|
||
*/
|
||
// tslint:disable-next-line: ban-types
|
||
export function getKeys(T: Object) {
|
||
//
|
||
const result: string[] = [];
|
||
Object.keys(T).forEach((key) => {
|
||
//
|
||
const valProperty = parseInt(key, 10);
|
||
if (!isNaN(valProperty) && valProperty >= 0) {
|
||
result.push(T[valProperty]);
|
||
}
|
||
});
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* return a cross value of key ...
|
||
*/
|
||
// tslint:disable-next-line:ban-types
|
||
export function getVal(T: Object, value: number | string) {
|
||
//
|
||
if (!T || isNullOrUndefined(value)) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
if (!isNaN(parseInt(value.toString(), 10))) {
|
||
return T[value];
|
||
}
|
||
|
||
//
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* convert an enumerable object to object ..
|
||
*
|
||
* @param T an enum object ...
|
||
*/
|
||
// tslint:disable-next-line:ban-types
|
||
export function toObject(T: Object) {
|
||
return Object.assign({}, T);
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Component Tools ...
|
||
/**
|
||
* Access Specified Component Selector ...
|
||
*
|
||
* @param component
|
||
* @returns
|
||
*/
|
||
export function getComponentSelector<T>(component: Type<T>): string | null {
|
||
return (component as any).ɵcmp?.selectors?.[0]?.[0] ?? null;
|
||
}
|
||
|
||
/**
|
||
* Access Specified Component's Name ...
|
||
*
|
||
* @param component
|
||
* @returns
|
||
*/
|
||
export function getComponentName<T>(component: Type<T>): string | null {
|
||
return component.toString();
|
||
}
|
||
|
||
/**
|
||
* Check Specified Value is inside Keys of Specified Type or not ...
|
||
*
|
||
* @param obj
|
||
* @param key
|
||
* @returns
|
||
*/
|
||
export function isXKeyOf<T extends object>(
|
||
obj: T,
|
||
key: PropertyKey
|
||
): key is keyof T {
|
||
return key in obj;
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Wait For Element ...
|
||
/**
|
||
* Wait for Element Exists ...
|
||
*
|
||
* @param selector
|
||
* @returns
|
||
*/
|
||
export function waitForXElement(selector: string): Promise<HTMLElement> {
|
||
//
|
||
// Validate Selector ...
|
||
if (isNullOrEmptyString(selector)) {
|
||
return Promise.resolve(undefined);
|
||
}
|
||
|
||
//
|
||
return new Promise((resolve) => {
|
||
//
|
||
// Try immediately
|
||
const el = document.querySelector<HTMLElement>(selector);
|
||
if (el) {
|
||
resolve(el);
|
||
return;
|
||
}
|
||
|
||
// Otherwise, observe DOM changes
|
||
const observer = new MutationObserver(() => {
|
||
const el = document.querySelector<HTMLElement>(selector);
|
||
if (el) {
|
||
resolve(el);
|
||
observer.disconnect();
|
||
}
|
||
});
|
||
|
||
observer.observe(document.body, {
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Wait for Elements Exists ...
|
||
*
|
||
* @param selector
|
||
* @returns
|
||
*/
|
||
export function waitForXElements(selector: string): Promise<HTMLElement[]> {
|
||
//
|
||
// Validate Selector ...
|
||
if (isNullOrEmptyString(selector)) {
|
||
return Promise.resolve([]);
|
||
}
|
||
|
||
//
|
||
return new Promise((resolve) => {
|
||
//
|
||
// Try immediately
|
||
const els = document.querySelectorAll<HTMLElement>(selector);
|
||
if (els) {
|
||
resolve(Array.from(els));
|
||
return;
|
||
}
|
||
|
||
// Otherwise, observe DOM changes
|
||
const observer = new MutationObserver(() => {
|
||
const els = document.querySelectorAll<HTMLElement>(selector);
|
||
if (els) {
|
||
resolve(Array.from(els));
|
||
observer.disconnect();
|
||
}
|
||
});
|
||
|
||
observer.observe(document.body, {
|
||
childList: true,
|
||
subtree: true,
|
||
});
|
||
});
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-observable.tools.ts
|
||
|
||
import {
|
||
of,
|
||
from,
|
||
Subject,
|
||
forkJoin,
|
||
Observable,
|
||
isObservable,
|
||
combineLatest,
|
||
} from 'rxjs';
|
||
import {
|
||
map,
|
||
first,
|
||
finalize,
|
||
switchMap,
|
||
distinctUntilChanged,
|
||
} from 'rxjs/operators';
|
||
import {
|
||
isObject,
|
||
isPromise,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import { keys } from './x-object.tools';
|
||
import { EventEmitter, Type } from '@angular/core';
|
||
import { hasChild, toArray } from './x-array.tools';
|
||
import {
|
||
XHasAction,
|
||
XOneOrManyType,
|
||
XPropertyType,
|
||
XStandardType,
|
||
} from '../typings/x.typings';
|
||
|
||
//
|
||
//#region Handlers ...
|
||
export function applyFinally<T>(obs: Observable<T>, action: () => void) {
|
||
return obs.pipe(finalize(action));
|
||
}
|
||
|
||
export function hasValue<T>(obs: Observable<T>) {
|
||
return obs.pipe(map((res) => !isNullOrUndefined(res)));
|
||
}
|
||
|
||
export function hasStringValue(obs: Observable<string>) {
|
||
return obs.pipe(map((res) => !isNullOrEmptyString(res)));
|
||
}
|
||
|
||
export function notValue(obs: Observable<boolean>) {
|
||
return obs.pipe(map((res) => (isNullOrUndefined(res) ? true : !res)));
|
||
}
|
||
|
||
export function toPromise<T>(value: XStandardType<T>) {
|
||
return toObservable(value).pipe(first()).toPromise();
|
||
}
|
||
|
||
export function toObservable<T>(value: XStandardType<T>) {
|
||
//
|
||
let result: Observable<T>;
|
||
|
||
//
|
||
if (isObservable<T>(value)) {
|
||
result = value as Observable<T>;
|
||
} else if (isPromise(value)) {
|
||
result = from(value as Promise<T>);
|
||
} else {
|
||
result = of(value as T);
|
||
}
|
||
|
||
//
|
||
return result.pipe(first());
|
||
}
|
||
|
||
/**
|
||
* filter an array by providing an observable condition ...
|
||
* @param list an instance of XStandardType<XOneOrMany<T>>
|
||
* @param condition a condition
|
||
* @returns array result ...
|
||
*/
|
||
export function filterList<T>(
|
||
list: XStandardType<XOneOrManyType<T>>,
|
||
condition: (item: T) => XStandardType<boolean>
|
||
) {
|
||
return toObservable(list)
|
||
.pipe(map((valueType) => toArray(valueType)))
|
||
.pipe(
|
||
switchMap((array) =>
|
||
combineLatest(
|
||
array.map((item) =>
|
||
toObservable(condition(item)).pipe(
|
||
distinctUntilChanged(),
|
||
map((result) => (result ? item : null))
|
||
)
|
||
)
|
||
)
|
||
),
|
||
map((resultArray) => resultArray.filter((action) => action))
|
||
);
|
||
}
|
||
|
||
export function flatObject<T>(input: T): Observable<any> {
|
||
//
|
||
let result = {};
|
||
let afterJoin = {};
|
||
|
||
//
|
||
const inputKeys = keys(input);
|
||
if (!hasChild(inputKeys)) {
|
||
return of(result);
|
||
}
|
||
|
||
//
|
||
for (const key of inputKeys) {
|
||
//
|
||
const item = input[key];
|
||
|
||
//
|
||
const isItemObject = isObject(item);
|
||
if (isItemObject) {
|
||
//
|
||
if (item instanceof EventEmitter || item instanceof Subject) {
|
||
afterJoin[key] = item;
|
||
} else {
|
||
result[key] = flatObject(item);
|
||
}
|
||
} else {
|
||
result[key] = toObservable(item);
|
||
}
|
||
}
|
||
|
||
//
|
||
return forkJoin(result).pipe(
|
||
map((res) => {
|
||
return {
|
||
//
|
||
...(res as any),
|
||
|
||
//
|
||
...afterJoin,
|
||
};
|
||
})
|
||
);
|
||
}
|
||
|
||
export function nextSubjectWhenElementExists<TAction>(
|
||
action: XPropertyType<XHasAction<TAction>, 'action'>,
|
||
className: string,
|
||
actionProvider: Subject<XHasAction<TAction>>,
|
||
delay: number = 200,
|
||
payload?: any
|
||
) {
|
||
//
|
||
// Validate ...
|
||
if (
|
||
isNullOrUndefined(action) ||
|
||
isNullOrEmptyString(className) ||
|
||
isNullOrUndefined(actionProvider)
|
||
) {
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Query to Select Target Elements ...
|
||
const elements: NodeListOf<Element> = document.querySelectorAll(
|
||
`.${className}`
|
||
);
|
||
|
||
//
|
||
if (isNullOrUndefined(elements) || !hasChild(elements)) {
|
||
//
|
||
setTimeout(
|
||
() =>
|
||
nextSubjectWhenElementExists(
|
||
action,
|
||
className,
|
||
actionProvider,
|
||
delay,
|
||
payload
|
||
),
|
||
delay
|
||
);
|
||
return;
|
||
}
|
||
|
||
//
|
||
actionProvider.next({ action, payload });
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-page.tools.ts
|
||
|
||
import { toPromise } from './x-observable.tools';
|
||
import { XPage } from '../typings/x-page.typings';
|
||
import { hasChild, toArray } from './x-array.tools';
|
||
import { XOneOrManyType } from '../typings/x.typings';
|
||
import { mergeRoutes, toNormalString } from './x-string.tools';
|
||
import { isNullOrEmptyString, isNullOrUndefined } from './x-type-detect.tools';
|
||
|
||
export async function toFlatPages(pages: XOneOrManyType<XPage>) {
|
||
//
|
||
const result: XPage[] = [];
|
||
|
||
//
|
||
if (!pages || !hasChild(pages)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
const pagesArray = toArray(pages);
|
||
for (const page of pagesArray) {
|
||
//
|
||
const childsArray = await toPromise(page.childs);
|
||
const isParent = hasChild(childsArray);
|
||
|
||
//
|
||
result.push(page);
|
||
|
||
//
|
||
if (isParent) {
|
||
//
|
||
const childsRes = await toFlatPages(page.childs);
|
||
result.push(...childsRes);
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export async function findPageByRoute(
|
||
pages: XOneOrManyType<XPage>,
|
||
route: XOneOrManyType<string>
|
||
) {
|
||
//
|
||
let result: XPage = null;
|
||
|
||
//
|
||
if (!hasChild(pages) || !hasChild(route)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
const pRoute = mergeRoutes(route);
|
||
const pPages = await toFlatPages(pages);
|
||
if (!hasChild(pPages)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
for (const page of pPages) {
|
||
//
|
||
if (hasChild(page.route)) {
|
||
//
|
||
const pageRoute = mergeRoutes(page.route);
|
||
if (
|
||
!isNullOrEmptyString(pageRoute) &&
|
||
toNormalString(pageRoute) === toNormalString(pRoute)
|
||
) {
|
||
result = page;
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export async function containsPagesByRoute(
|
||
pages: XOneOrManyType<XPage>,
|
||
route: XOneOrManyType<string>
|
||
) {
|
||
//
|
||
const result: XPage[] = [];
|
||
|
||
//
|
||
if (!hasChild(pages) || !hasChild(route)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
const pRoute = mergeRoutes(route);
|
||
if (isNullOrEmptyString(pRoute)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
const pPages = await toFlatPages(pages);
|
||
if (!hasChild(pPages)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
for (const page of pPages) {
|
||
//
|
||
if (hasChild(page.route)) {
|
||
//
|
||
const pageRoute = mergeRoutes(page.route);
|
||
if (
|
||
!isNullOrEmptyString(pageRoute) &&
|
||
toNormalString(pRoute).includes(toNormalString(pageRoute))
|
||
) {
|
||
result.push(page);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
export async function parentPagesByRoute(
|
||
pages: XOneOrManyType<XPage>,
|
||
route: XOneOrManyType<string>
|
||
) {
|
||
//
|
||
let result: XPage[] = [];
|
||
|
||
//
|
||
if (!hasChild(pages) || !hasChild(route)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
const parentPages = await containsPagesByRoute(pages, route);
|
||
const foundedPage = await findPageByRoute(pages, route);
|
||
if (!hasChild(parentPages) || isNullOrUndefined(foundedPage)) {
|
||
return result;
|
||
}
|
||
|
||
//
|
||
result = parentPages.filter(
|
||
(i) => toNormalString(i.id) !== toNormalString(foundedPage.id)
|
||
);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-string.tools.ts
|
||
|
||
import { Md5 } from 'md5-typescript';
|
||
import { hasChild, toArray } from './x-array.tools';
|
||
import { XOneOrManyType } from '../typings/x.typings';
|
||
import { isNullOrEmptyString, isString } from './x-type-detect.tools';
|
||
|
||
//
|
||
export const XStringPlaceHolder = '(%$s)';
|
||
|
||
export const XEnDigits: string[] = [
|
||
'0',
|
||
'1',
|
||
'2',
|
||
'3',
|
||
'4',
|
||
'5',
|
||
'6',
|
||
'7',
|
||
'8',
|
||
'9',
|
||
];
|
||
export const XFaDigits: string[] = [
|
||
'۰',
|
||
'۱',
|
||
'۲',
|
||
'۳',
|
||
'۴',
|
||
'۵',
|
||
'۶',
|
||
'۷',
|
||
'۸',
|
||
'۹',
|
||
];
|
||
|
||
//
|
||
//#region String Utils ...
|
||
/**
|
||
* determines given string is empty or not ...
|
||
*/
|
||
export function isEmpty(value: string) {
|
||
//
|
||
if (isString(value) && value.length === 0) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* return digits of given string ...
|
||
*/
|
||
export function getDigits(value: string) {
|
||
//
|
||
if (!isString(value)) {
|
||
throw new Error('Invalid Parameter ...');
|
||
}
|
||
|
||
//
|
||
let result = '';
|
||
for (let i = 0; i < value.length; i++) {
|
||
//
|
||
const chr = value.substr(i, 1);
|
||
if (chr in XEnDigits) {
|
||
//
|
||
result += chr;
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* return non digits of given string ...
|
||
*/
|
||
export function getNonDigits(value: string) {
|
||
//
|
||
if (!isString(value)) {
|
||
throw new Error('Invalid Parameter ...');
|
||
}
|
||
|
||
//
|
||
value = toEnNumbers(value);
|
||
|
||
//
|
||
let result = '';
|
||
for (let i = 0; i < value.length; i++) {
|
||
//
|
||
const chr = value.substr(i, 1);
|
||
if (!(chr in XEnDigits)) {
|
||
//
|
||
result += chr;
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* determine an expression contains only digits
|
||
*/
|
||
export function isOnlyDigits(value: string) {
|
||
//
|
||
if (isEmpty(value)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const pattern = /^\d+$/;
|
||
return pattern.test(value);
|
||
}
|
||
|
||
/**
|
||
* merge several parts of a url ...
|
||
*
|
||
* @param route an instance of url tree array ...
|
||
*/
|
||
export function mergeRoutes(route: XOneOrManyType<string>) {
|
||
//
|
||
if (!hasChild(route)) {
|
||
return '/';
|
||
}
|
||
|
||
//
|
||
try {
|
||
return toArray(route).join('/').replace('//', '/');
|
||
} catch {}
|
||
|
||
//
|
||
return '/';
|
||
}
|
||
|
||
/**
|
||
* format string formatter ...
|
||
*
|
||
* @param value an string to format ...
|
||
* @param args the args for string formatter ...
|
||
*/
|
||
export function stringFormatter(value: string, ...args: any) {
|
||
//
|
||
if (!isString(value)) {
|
||
throw new Error('first arg must be an string ...');
|
||
}
|
||
|
||
//
|
||
if (args.length < 1) {
|
||
throw new Error('there mest be values ...');
|
||
}
|
||
|
||
//
|
||
const holder = XStringPlaceHolder;
|
||
let numberOfHolders = 0;
|
||
|
||
//
|
||
if (value.length < holder.length) {
|
||
throw new Error('the sting doesnt contain any holder ...');
|
||
}
|
||
|
||
//
|
||
// tslint:disable-next-line:no-shadowed-variable
|
||
for (let i = 0; i < value.length; i++) {
|
||
//
|
||
const indexStr = value.substr(i, holder.length);
|
||
|
||
//
|
||
if (indexStr === holder) {
|
||
numberOfHolders++;
|
||
}
|
||
}
|
||
|
||
//
|
||
if (numberOfHolders !== args.length) {
|
||
throw new Error('theholders and parameters counts must be same ...');
|
||
}
|
||
|
||
//
|
||
// tslint:disable-next-line:prefer-for-of
|
||
for (let i = 0; i < args.length; i++) {
|
||
//
|
||
const a = value.indexOf(holder);
|
||
|
||
//
|
||
value =
|
||
value.substr(0, a) +
|
||
args[i].toString() +
|
||
value.substr(a + holder.length, value.length - (a + holder.length));
|
||
}
|
||
|
||
//
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* change all persian and arabic numers to english digits
|
||
*/
|
||
export function toEnNumbers(value: string): string {
|
||
//
|
||
let result = value ? value.toString() : '';
|
||
|
||
//
|
||
const persianNumbers = [
|
||
/۰/g,
|
||
/۱/g,
|
||
/۲/g,
|
||
/۳/g,
|
||
/۴/g,
|
||
/۵/g,
|
||
/۶/g,
|
||
/۷/g,
|
||
/۸/g,
|
||
/۹/g,
|
||
];
|
||
const arabicNumbers = [
|
||
/٠/g,
|
||
/١/g,
|
||
/٢/g,
|
||
/٣/g,
|
||
/٤/g,
|
||
/٥/g,
|
||
/٦/g,
|
||
/٧/g,
|
||
/٨/g,
|
||
/٩/g,
|
||
];
|
||
|
||
//
|
||
for (let i = 0; i < 10; i++) {
|
||
if (!isNullOrEmptyString(result)) {
|
||
result = result
|
||
.replace(persianNumbers[i], i.toString())
|
||
.replace(arabicNumbers[i], i.toString());
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* change all english digits to persian digits
|
||
*/
|
||
export function toPersianNumbers(value: string): string {
|
||
//
|
||
let result = value;
|
||
|
||
//
|
||
for (let i = 0; i < 10; i++) {
|
||
result = result.replace(new RegExp(i.toString(), 'g'), XFaDigits[i]);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* remove all spaces on string value ...
|
||
*
|
||
* @param value an string value ...
|
||
*/
|
||
export function removeSpaces(value: string): string {
|
||
return value.replace(/\s/g, '');
|
||
}
|
||
|
||
/**
|
||
* remove margin spaces and make text lowercase
|
||
*/
|
||
export function toNormalString(value: string): string {
|
||
return isNullOrEmptyString(value) ? '' : value.trim().toLowerCase();
|
||
}
|
||
|
||
/**
|
||
* Capitalize an string ...
|
||
*
|
||
* @param value input string ..
|
||
* @returns string
|
||
*/
|
||
export function capital(value: string): string {
|
||
//
|
||
if (isNullOrEmptyString(value) || isNullOrEmptyString(value.trim())) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
value = value.trim();
|
||
const firstChar = value.charAt(0).toLocaleUpperCase();
|
||
const otherChars = value.slice(1);
|
||
|
||
//
|
||
const result = `${firstChar}${otherChars}`;
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert an string to Md5 ...
|
||
*
|
||
* @param value an string which going to convert
|
||
*/
|
||
export function toMd5(value: string) {
|
||
return isNullOrEmptyString(value) ? '' : Md5.init(value);
|
||
}
|
||
|
||
/**
|
||
* convert given string to array buffer ...
|
||
*
|
||
* @param value the string which need to convert
|
||
*/
|
||
export function toArrayBuffer(value: string) {
|
||
//
|
||
if (!value || value.length === 0) {
|
||
return null;
|
||
}
|
||
|
||
//
|
||
const stringLength = value.length;
|
||
const buffer = new ArrayBuffer(stringLength * 2);
|
||
const bufferView = new Uint16Array(buffer);
|
||
|
||
//
|
||
for (let i = 0; i < stringLength; i++) {
|
||
bufferView[i] = value.charCodeAt(i);
|
||
}
|
||
|
||
//
|
||
return buffer;
|
||
}
|
||
|
||
/**
|
||
* convert byte array to string ...
|
||
*
|
||
* @param buffer the bytes array of an string
|
||
*/
|
||
export function fromArryBuffer(buffer: ArrayBuffer) {
|
||
return String.fromCharCode.apply(null, Array.from(new Uint16Array(buffer)));
|
||
}
|
||
|
||
/**
|
||
* escape reg exp chars from an string ...
|
||
*
|
||
* @param source given string value to escape
|
||
* @returns escaped source value
|
||
*/
|
||
export function escapeRegExp(source: string) {
|
||
return source.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||
}
|
||
|
||
/**
|
||
* find all indexes of an string inside another and return them as an array ...
|
||
*/
|
||
export function findAllIndex(source: string, query: string) {
|
||
//
|
||
const result: number[] = [];
|
||
|
||
//
|
||
const regExp = new RegExp(escapeRegExp(query), 'gi');
|
||
let match: any;
|
||
// tslint:disable-next-line:no-conditional-assignment
|
||
while ((match = regExp.exec(source)) !== null) {
|
||
result.push(match.index);
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* insert a text to specific position on another text ...
|
||
*/
|
||
export function insertText(source: string, insertedText: string, pos: number) {
|
||
//
|
||
if (!source && !insertText) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
if (!source && insertText) {
|
||
return insertedText;
|
||
}
|
||
|
||
//
|
||
if (pos > source.length) {
|
||
return source + insertedText;
|
||
}
|
||
|
||
//
|
||
return [source.slice(0, pos), insertedText, source.slice(pos)].join('');
|
||
}
|
||
|
||
/**
|
||
* remove all occurence of an string inside of another string
|
||
*/
|
||
export function removeAll(
|
||
source: string,
|
||
removedString: string,
|
||
caseSensitive = false
|
||
) {
|
||
//
|
||
if (isNullOrEmptyString(removedString)) {
|
||
removedString = '';
|
||
}
|
||
|
||
//
|
||
const regExp = new RegExp(
|
||
removedString.toString(),
|
||
caseSensitive ? 'gi' : 'g'
|
||
);
|
||
|
||
//
|
||
if (isNullOrEmptyString(source)) {
|
||
source = '';
|
||
}
|
||
|
||
//
|
||
const result = source.toString().replace(regExp, '');
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* extract all unique characters of an string ...
|
||
*
|
||
* @param value source string
|
||
*/
|
||
export function extractUniqueChars(value: string) {
|
||
//
|
||
if (isNullOrEmptyString(value)) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
let result = '';
|
||
|
||
//
|
||
// tslint:disable-next-line:prefer-for-of
|
||
for (let i = 0; i < value.length; i++) {
|
||
if (result.indexOf(value.charAt(i)) === -1) {
|
||
result += value[i];
|
||
}
|
||
}
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* check an string contains unique chars or not ...
|
||
*
|
||
* @param value source string
|
||
*/
|
||
export function hasUniqueChar(value: string) {
|
||
//
|
||
if (isNullOrEmptyString(value)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const uniqueChars = extractUniqueChars(value);
|
||
if (isNullOrEmptyString(uniqueChars)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
// const valueCharsArray = Array.from(value);
|
||
const uniqueCharsArray = Array.from(uniqueChars);
|
||
const findUniquArray = uniqueCharsArray.map((v) => {
|
||
//
|
||
const resultRes = findAllIndex(value, v);
|
||
|
||
//
|
||
return resultRes && resultRes.length === 1;
|
||
});
|
||
|
||
//
|
||
const result = findUniquArray.includes(true);
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* convert an array object to list string ...
|
||
*
|
||
* @param values an array object to convert it to list string
|
||
* @param seperator list seperator ...
|
||
*/
|
||
export function toListString(
|
||
values: XOneOrManyType<string>,
|
||
seperator: string = ','
|
||
) {
|
||
//
|
||
const valueArr = toArray(values);
|
||
if (!hasChild(valueArr)) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
return valueArr.join(seperator);
|
||
}
|
||
|
||
/**
|
||
* convert a list string to string array ..
|
||
*
|
||
* @param listString a list string
|
||
* @param seperator list seperator ...
|
||
*/
|
||
export function parseListString(listString: string, seperator: string = ',') {
|
||
//
|
||
if (!isNullOrEmptyString(listString)) {
|
||
return [];
|
||
}
|
||
|
||
//
|
||
return listString.split(seperator);
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-task.tools.ts
|
||
|
||
export const taskIdStartKey = '_[';
|
||
export const taskIdEndKey = ']';
|
||
|
||
/**
|
||
* check if task name contains id ...
|
||
*
|
||
* @param key the task name ...
|
||
*/
|
||
export function hasTaskId(key: string | any) {
|
||
//
|
||
if (!key) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
const mKey = key.toString() as string;
|
||
return mKey.includes(taskIdStartKey) && mKey.includes(taskIdEndKey);
|
||
}
|
||
|
||
/**
|
||
* retrieve and extract the raw task name from a task name ...
|
||
*
|
||
* @param key the task name ...
|
||
*/
|
||
export function getTaskName(key: string | any) {
|
||
//
|
||
if (!key) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
const mKey = key.toString() as string;
|
||
|
||
//
|
||
if (!hasTaskId(mKey)) {
|
||
return mKey;
|
||
}
|
||
|
||
//
|
||
const taskId = getTaskId(mKey);
|
||
const taskIdString = `${taskIdStartKey}${taskId}${taskIdEndKey}`;
|
||
const result = mKey.replace(taskIdString, '');
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* retrieve and extract the id inside a task name ...
|
||
*
|
||
* @param key the task name ...
|
||
*/
|
||
export function getTaskId(key: string | any) {
|
||
//
|
||
// Validate Args ...
|
||
if (!key || !hasTaskId(key)) {
|
||
return '';
|
||
}
|
||
|
||
//
|
||
// Task Id ...
|
||
let result = key.toString() as string;
|
||
|
||
//
|
||
// Validating Info ...
|
||
let index = result.indexOf(taskIdStartKey);
|
||
|
||
//
|
||
result = result.substr(index, result.length);
|
||
result = result.replace(taskIdStartKey, '');
|
||
|
||
//
|
||
index = result.indexOf(taskIdEndKey);
|
||
result = result.substring(0, index);
|
||
|
||
//
|
||
// Return Result ...
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* prepare a Task With ID and return ...
|
||
*
|
||
* @param key the Task Name ...
|
||
* @param id th ID ...
|
||
*/
|
||
export function setTaskId(key: string | any, id: string | any) {
|
||
return `${key.toString()}${taskIdStartKey}${id.toString()}${taskIdEndKey}`;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-to-form-data.ts
|
||
|
||
import {
|
||
isDate,
|
||
isNull,
|
||
isFile,
|
||
isBlob,
|
||
isArray,
|
||
isObject,
|
||
isBoolean,
|
||
isUndefined,
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString,
|
||
} from './x-type-detect.tools';
|
||
import { blobToFile, generateFileName } from './x-file.tools';
|
||
|
||
export interface XToFormDataOptions {
|
||
/**
|
||
* include array indices in FormData keys
|
||
* defaults to false
|
||
*/
|
||
indices?: boolean;
|
||
|
||
/**
|
||
* treat null values like undefined values and ignore them
|
||
* defaults to false
|
||
*/
|
||
nullsAsUndefineds?: boolean;
|
||
|
||
/**
|
||
* convert true or false to 1 or 0 respectively
|
||
* defaults to false
|
||
*/
|
||
booleansAsIntegers?: boolean;
|
||
}
|
||
|
||
/**
|
||
* Convert an Object to FormData ...
|
||
*
|
||
* @param source the object which going to convert to FormData ...
|
||
* @param options Converter Options ...
|
||
* @param formData an exists FormData instance which apply object to it ...
|
||
* @param keysPrefix key prefix for FormData Values ...
|
||
*/
|
||
export function toFormData(
|
||
source: any,
|
||
options?: XToFormDataOptions,
|
||
formData?: FormData,
|
||
keysPrefix?: string
|
||
) {
|
||
//
|
||
//#region Prepare Options ...
|
||
options = options || {};
|
||
|
||
options.indices = isNullOrUndefined(options.indices) ? true : options.indices;
|
||
|
||
options.nullsAsUndefineds = isNullOrUndefined(options.nullsAsUndefineds)
|
||
? false
|
||
: options.nullsAsUndefineds;
|
||
|
||
options.booleansAsIntegers = isNullOrUndefined(options.booleansAsIntegers)
|
||
? false
|
||
: options.booleansAsIntegers;
|
||
//#endregion
|
||
|
||
//
|
||
formData = formData || new FormData();
|
||
|
||
//
|
||
//#region Do Convertion ...
|
||
if (isUndefined(source)) {
|
||
return formData;
|
||
} else if (isNull(source)) {
|
||
//
|
||
if (!options.nullsAsUndefineds) {
|
||
formData.append(keysPrefix, '');
|
||
}
|
||
} else if (isBoolean(source)) {
|
||
//
|
||
if (options.booleansAsIntegers) {
|
||
formData.append(keysPrefix, source ? '1' : '0');
|
||
} else {
|
||
formData.append(keysPrefix, source);
|
||
}
|
||
} else if (isArray(source)) {
|
||
//
|
||
if (source.length) {
|
||
source.forEach((value: any, index: number) => {
|
||
const key = keysPrefix + '[' + (options.indices ? index : '') + ']';
|
||
formData = toFormData(value, options, formData, key);
|
||
});
|
||
}
|
||
} else if (isDate(source)) {
|
||
formData.append(keysPrefix, source.toISOString());
|
||
} else if (isObject(source) && !isFile(source) && !isBlob(source)) {
|
||
//
|
||
Object.keys(source).forEach((prop) => {
|
||
//
|
||
const value = source[prop];
|
||
|
||
//
|
||
if (isArray(value)) {
|
||
while (prop.length > 2 && prop.lastIndexOf('[]') === prop.length - 2) {
|
||
prop = prop.substring(0, prop.length - 2);
|
||
}
|
||
}
|
||
|
||
//
|
||
const key = keysPrefix ? keysPrefix + '[' + prop + ']' : prop;
|
||
|
||
//
|
||
formData = toFormData(value, options, formData, key);
|
||
});
|
||
} else if (isFile(source) || isBlob(source)) {
|
||
//
|
||
let file: File = null;
|
||
if (isFile(source)) {
|
||
file = source as File;
|
||
} else if (isBlob(source)) {
|
||
//
|
||
const blob = source as Blob;
|
||
const fileName = generateFileName(blob);
|
||
file = blobToFile(blob, fileName);
|
||
}
|
||
|
||
//
|
||
formData.append(keysPrefix, file, file.name);
|
||
} else {
|
||
formData.append(keysPrefix, source.toString());
|
||
}
|
||
//#endregion
|
||
|
||
return formData;
|
||
}
|
||
|
||
/**
|
||
* log an instance of FormData object's Content in Console ...
|
||
*/
|
||
export async function getFormDataContent(source: FormData) {
|
||
return await new Response(source).text();
|
||
}
|
||
|
||
/**
|
||
* log an instance of FormData object's Content in Console ...
|
||
*/
|
||
export async function logFormData(source: FormData) {
|
||
//
|
||
const result = await getFormDataContent(source);
|
||
console.log(result);
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-type-convert.tools.ts
|
||
|
||
//
|
||
//#region Type Converter ...
|
||
/**
|
||
* convert given object to string ...
|
||
*/
|
||
export function toXString(object: any) {
|
||
//
|
||
try {
|
||
//
|
||
return String(object);
|
||
} catch (error) {
|
||
//
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* convert given object to number ...
|
||
*/
|
||
export function toNumber(object: any) {
|
||
//
|
||
try {
|
||
//
|
||
return Number(object);
|
||
} catch (error) {
|
||
//
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* convert given object to date ...
|
||
*/
|
||
export function toDate(object: any) {
|
||
//
|
||
try {
|
||
//
|
||
return new Date(object);
|
||
} catch (error) {
|
||
//
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* convert given object to boolean ...
|
||
*/
|
||
export function toBoolean(object: any) {
|
||
//
|
||
try {
|
||
//
|
||
// tslint:disable-next-line:no-eval
|
||
return Boolean(eval(object));
|
||
} catch (error) {
|
||
//
|
||
throw error;
|
||
}
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-type-defaults.tools.ts
|
||
|
||
import {
|
||
isArray,
|
||
isObject,
|
||
isNumber,
|
||
isString,
|
||
isBoolean,
|
||
} from './x-type-detect.tools';
|
||
import { XStandardType } from '../typings/x.typings';
|
||
import { toObservable, toPromise } from './x-observable.tools';
|
||
import { Observable } from 'rxjs';
|
||
import { map } from 'rxjs/operators';
|
||
|
||
export async function getDefaultValueAsync<T>(t: XStandardType<T>): Promise<T> {
|
||
//
|
||
let result: any;
|
||
|
||
//
|
||
const tVal = await toPromise(toObservable<T>(t));
|
||
|
||
//
|
||
if (isBoolean(tVal)) {
|
||
result = false;
|
||
} else if (isNumber(tVal)) {
|
||
result = 0;
|
||
} else if (isString(tVal)) {
|
||
result = '';
|
||
} else if (isObject(tVal) && !isArray(tVal)) {
|
||
result = null;
|
||
} else if (isArray(tVal)) {
|
||
result = [];
|
||
} else {
|
||
result = undefined;
|
||
}
|
||
|
||
//
|
||
return result as T;
|
||
}
|
||
|
||
export function getDefaultValue<T>(t: XStandardType<T>): Observable<T> {
|
||
//
|
||
return toObservable<T>(t).pipe(
|
||
map((tVal) => {
|
||
//
|
||
let result: any;
|
||
|
||
//
|
||
if (isBoolean(tVal)) {
|
||
result = false;
|
||
} else if (isNumber(tVal)) {
|
||
result = 0;
|
||
} else if (isString(tVal)) {
|
||
result = '';
|
||
} else if (isObject(tVal) && !isArray(tVal)) {
|
||
result = null;
|
||
} else if (isArray(tVal)) {
|
||
result = [];
|
||
} else {
|
||
result = undefined;
|
||
}
|
||
|
||
//
|
||
return result as T;
|
||
})
|
||
);
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-type-detect.tools.ts
|
||
|
||
/**
|
||
* Custom Data Types ...
|
||
*/
|
||
export const DataTypes = {
|
||
Null: 'null',
|
||
Undefined: 'undefined',
|
||
String: 'string',
|
||
Number: 'number',
|
||
Boolean: 'boolean',
|
||
Object: 'object',
|
||
Function: 'function',
|
||
};
|
||
|
||
/**
|
||
* determines type of an object
|
||
*
|
||
* @param variable specified object
|
||
*/
|
||
export function getType(variable: any) {
|
||
return typeof variable;
|
||
}
|
||
|
||
//
|
||
//#region Type Checker ...
|
||
/**
|
||
* determine a var is null or not ...
|
||
*/
|
||
export function isNull(variable: any) {
|
||
//
|
||
if (
|
||
!variable &&
|
||
(variable === null || getType(variable) === DataTypes.Null)
|
||
) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* determine a var is undefined ...
|
||
*/
|
||
export function isUndefined(variable: any) {
|
||
//
|
||
if (getType(variable) === DataTypes.Undefined) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* setermine a var is null or undefined ...
|
||
*/
|
||
export function isNullOrUndefined(variable: any) {
|
||
//
|
||
if (isNull(variable) || isUndefined(variable)) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
export function isNullOrEmptyString(variable: string) {
|
||
//
|
||
if (isNull(variable) || isUndefined(variable) || variable.length === 0) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
export function isNullOrZeroLength(variable: any[]) {
|
||
//
|
||
if (isNullOrUndefined(variable)) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return variable.length === 0;
|
||
}
|
||
|
||
/**
|
||
* determine a var is string or not ...
|
||
*/
|
||
export function isString(variable: any) {
|
||
//
|
||
if (getType(variable) === DataTypes.String) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* determine a var is Number or not ...
|
||
*/
|
||
export function isNumber(variable: any) {
|
||
//
|
||
if (getType(variable) === DataTypes.Number) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
var numValue = parseInt(variable, 10);
|
||
if (isNaN(numValue)) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* determine a var is boolean or not ...
|
||
*/
|
||
export function isBoolean(variable: any) {
|
||
//
|
||
if (getType(variable) === DataTypes.Boolean) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* determine a object is Array or not ...
|
||
*
|
||
* IMPORTANT: an array must be an object ...
|
||
*/
|
||
export function isArray(value: any) {
|
||
return value && Array.isArray(value);
|
||
}
|
||
|
||
/**
|
||
* determine a var is object or not ...
|
||
*/
|
||
export function isObject(variable: any) {
|
||
//
|
||
return (
|
||
variable &&
|
||
getType(variable) === DataTypes.Object &&
|
||
variable === Object(variable)
|
||
);
|
||
}
|
||
|
||
/**
|
||
* determine a var is function or not ...
|
||
*/
|
||
export function isFunction(variable: any) {
|
||
//
|
||
if (getType(variable) === DataTypes.Function) {
|
||
return true;
|
||
}
|
||
|
||
//
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* determine a var is Blob ...
|
||
*/
|
||
export function isBlob(value: any) {
|
||
return (
|
||
value &&
|
||
typeof value.size === 'number' &&
|
||
typeof value.type === 'string' &&
|
||
typeof value.slice === 'function'
|
||
);
|
||
}
|
||
|
||
/**
|
||
* check an input arg is a date object or not ...
|
||
*
|
||
* @param source any arg which required to check
|
||
*/
|
||
export function isDate(source: any) {
|
||
return (
|
||
source &&
|
||
isObject(source) &&
|
||
(source instanceof Date ||
|
||
isFunction(source.getMonth) ||
|
||
Object.prototype.toString.call(source) === '[object Date]')
|
||
);
|
||
}
|
||
|
||
/**
|
||
* determine a var is File ...
|
||
*/
|
||
export function isFile(value: any) {
|
||
return (
|
||
isBlob(value) &&
|
||
typeof value.name === 'string' &&
|
||
(typeof value.lastModifiedDate === 'object' ||
|
||
typeof value.lastModified === 'number')
|
||
);
|
||
}
|
||
|
||
/**
|
||
* check wheather an object is promise or not ...
|
||
*/
|
||
export function isPromise(variable: any) {
|
||
if (!isNullOrUndefined(variable) && isFunction(variable.then)) {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\tools\x-uuid-tools.ts
|
||
|
||
import { v4 as uuidv4 } from 'uuid';
|
||
import { v5 as uuidv5 } from 'uuid';
|
||
|
||
export const DEFAULT_NAMESPACE = 'SaherElm IT Center';
|
||
export function generateUuid(
|
||
prefix?: string,
|
||
content?: string,
|
||
nameSpace: string = DEFAULT_NAMESPACE
|
||
) {
|
||
//
|
||
const uId = content ? uuidv5(content, nameSpace) : uuidv4();
|
||
const result = prefix ? `${prefix}_${uId}` : uId;
|
||
|
||
//
|
||
return result;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-base-component.typings.ts
|
||
|
||
export const DEFAULT_EXPORT_TYPING_BASE = 'default';
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-color.typings.ts
|
||
|
||
//
|
||
import { XBaseKeyValue } from './x.typings';
|
||
|
||
//#region Color Tools ...
|
||
export interface XColorDescribtor {
|
||
name: XColor;
|
||
brightnessLevel: XColorBrightnessLevel;
|
||
isContrast?: boolean;
|
||
}
|
||
|
||
export enum XColor {
|
||
Primary = 'primary',
|
||
Secondary = 'secondary',
|
||
Tertiary = 'tertiary',
|
||
Success = 'success',
|
||
Warning = 'warning',
|
||
Danger = 'danger',
|
||
Dark = 'dark',
|
||
Medium = 'medium',
|
||
Light = 'light',
|
||
//
|
||
Transparent = 'cb-inherit',
|
||
}
|
||
|
||
export enum XColorWithBrightness {
|
||
//
|
||
PrimaryTint = 'primary-tint',
|
||
Primary = 'primary',
|
||
PrimaryShade = 'primary-shade',
|
||
//
|
||
SecondaryTint = 'secondary-tint',
|
||
Secondary = 'secondary',
|
||
SecondaryShade = 'secondary-shade',
|
||
//
|
||
TertiaryTint = 'tertiary-tint',
|
||
Tertiary = 'tertiary',
|
||
TertiaryShade = 'tertiary-shade',
|
||
//
|
||
SuccessTint = 'success-tint',
|
||
Success = 'success',
|
||
SuccessShade = 'success-shade',
|
||
//
|
||
WarningTint = 'warning-tint',
|
||
Warning = 'warning',
|
||
WarningShade = 'warning-shade',
|
||
//
|
||
DangerTint = 'danger-tint',
|
||
Danger = 'danger',
|
||
DangerShade = 'danger-shade',
|
||
//
|
||
DarkTint = 'dark-tint',
|
||
Dark = 'dark',
|
||
DarkShade = 'dark-shade',
|
||
//
|
||
MediumTint = 'medium-tint',
|
||
Medium = 'medium',
|
||
MediumShade = 'medium-shade',
|
||
//
|
||
LightTint = 'light-tint',
|
||
Light = 'light',
|
||
LightShade = 'light-shade',
|
||
//
|
||
Transparent = 'cb-inherit',
|
||
}
|
||
|
||
export type XColorIdentifier = XColor | XColorWithBrightness | string;
|
||
|
||
export enum XColorBrightnessLevel {
|
||
Tint = 'tint',
|
||
Regular = 'regular',
|
||
Shade = 'shade',
|
||
}
|
||
|
||
export interface XRGBAColor {
|
||
r?: number;
|
||
g?: number;
|
||
b?: number;
|
||
a?: number;
|
||
}
|
||
|
||
export interface XHSVAColor {
|
||
h?: number;
|
||
s?: number;
|
||
v?: number;
|
||
a?: number;
|
||
}
|
||
|
||
export interface XHSLAColor {
|
||
h?: number;
|
||
s?: number;
|
||
l?: number;
|
||
a?: number;
|
||
}
|
||
|
||
export enum XColorFormat {
|
||
XHEX = 'hex',
|
||
XRGBA = 'rgba',
|
||
XHSLA = 'hsla',
|
||
XHSVA = 'hsva',
|
||
}
|
||
|
||
export type XColorFormatIdentifier = XColorFormat | string;
|
||
|
||
export interface XColorKeyValue extends XBaseKeyValue<string> {}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-date-time.typings.ts
|
||
|
||
export enum XUnitOfTime {
|
||
Year,
|
||
Month,
|
||
Day
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-exception.typings.ts
|
||
|
||
import { XExceptionIDs, Exceptions } from '../constants/x-exception.resources';
|
||
|
||
export interface XException {
|
||
id: number;
|
||
message: string;
|
||
payload?: any[];
|
||
}
|
||
|
||
export type XExceptionIndex = {
|
||
[key in keyof typeof XExceptionIDs]: XException;
|
||
};
|
||
|
||
export type XExceptions = keyof typeof Exceptions;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-manager.typings.ts
|
||
|
||
export enum XUiEvent {
|
||
//
|
||
StartLoading,
|
||
StopLoading,
|
||
|
||
//
|
||
Disabled,
|
||
Enabled,
|
||
|
||
//
|
||
Locked,
|
||
UnLocked,
|
||
|
||
//
|
||
BackPrevented,
|
||
BackReleased,
|
||
|
||
//
|
||
Ready
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-notification.typings.ts
|
||
|
||
import {
|
||
AlertInput,
|
||
ToastOptions,
|
||
ModalOptions,
|
||
AlertOptions,
|
||
ComponentRef,
|
||
PickerOptions,
|
||
PopoverOptions,
|
||
LoadingOptions,
|
||
ActionSheetOptions,
|
||
} from '@ionic/core';
|
||
import { XResourceIdentifier } from './x-translation.typings';
|
||
import { XExceptions, XException } from './x-exception.typings';
|
||
import { XSpinnerIdentifier, XOneOrManyType } from './x.typings';
|
||
import { XExceptionIDs } from '../constants/x-exception.resources';
|
||
import { XResourceIDs } from '../constants/x-translation.resources';
|
||
|
||
//
|
||
//#region Typings for Dialogs and Notifications ...
|
||
/**
|
||
* Action Type for Notifications in Audio Service
|
||
*/
|
||
export enum XActionType {
|
||
User,
|
||
System,
|
||
Capture,
|
||
}
|
||
|
||
/**
|
||
* represent a single notification sound for specific actions
|
||
*/
|
||
export interface XNotificationSound {
|
||
type: XActionType;
|
||
resourcePath: string;
|
||
}
|
||
|
||
/**
|
||
* represent a group of notification sounds and coresponding actions
|
||
*/
|
||
export interface NotificationSoundIndex {
|
||
[name: string]: XNotificationSound;
|
||
}
|
||
|
||
export interface XNotificationParams {
|
||
type?: XActionType;
|
||
opt?: ToastOptions;
|
||
playSound?: boolean;
|
||
dissmissable: boolean;
|
||
onDidDismiss?: () => void;
|
||
onWillDismiss?: () => void;
|
||
}
|
||
|
||
export interface XTypedNotificationParams extends XNotificationParams {
|
||
message: string | XResourceIDs;
|
||
}
|
||
|
||
export interface XErrorNotificationParams extends XNotificationParams {
|
||
exception: XExceptionIDs | XExceptions | XException | any;
|
||
}
|
||
|
||
type XXActionModalOptions = Pick<
|
||
Partial<ActionSheetOptions>,
|
||
| 'id'
|
||
| 'animated'
|
||
| 'backdropDismiss'
|
||
| 'cssClass'
|
||
| 'keyboardClose'
|
||
| 'translucent'
|
||
>;
|
||
export interface XActionModalOptions extends XXActionModalOptions {
|
||
//
|
||
type?: XActionType;
|
||
playSound?: boolean;
|
||
header?: XResourceIdentifier;
|
||
subHeader?: XResourceIdentifier;
|
||
buttons?: XModalButton[];
|
||
|
||
//
|
||
hasYes?: boolean;
|
||
yesRole?: XModalButtonRoleIdentifier;
|
||
yesHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasNo?: boolean;
|
||
noRole?: XModalButtonRoleIdentifier;
|
||
noHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasOk?: boolean;
|
||
okRole?: XModalButtonRoleIdentifier;
|
||
okHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasRetry?: boolean;
|
||
retryRole?: XModalButtonRoleIdentifier;
|
||
retryHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasAccept?: boolean;
|
||
acceptRole?: XModalButtonRoleIdentifier;
|
||
acceptHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasCancel?: boolean;
|
||
cancelRole?: XModalButtonRoleIdentifier;
|
||
cancelHandler?: () => boolean | void | Promise<boolean>;
|
||
|
||
hasDismiss?: boolean;
|
||
dismissRole?: XModalButtonRoleIdentifier;
|
||
dismissHandler?: () => boolean | void | Promise<boolean>;
|
||
}
|
||
|
||
type XXModalOptions = Pick<
|
||
Partial<ModalOptions>,
|
||
| 'componentProps'
|
||
| 'showBackdrop'
|
||
| 'backdropDismiss'
|
||
| 'cssClass'
|
||
| 'animated'
|
||
| 'component'
|
||
| 'keyboardClose'
|
||
| 'id'
|
||
>;
|
||
export interface XModalOptions extends XXModalOptions {
|
||
component: ComponentRef;
|
||
autoHeight?: boolean;
|
||
fullScreen?: boolean;
|
||
}
|
||
|
||
type XXPopOverOptions = Pick<
|
||
Partial<PopoverOptions>,
|
||
| 'animated'
|
||
| 'backdropDismiss'
|
||
| 'componentProps'
|
||
| 'cssClass'
|
||
| 'component'
|
||
| 'id'
|
||
| 'showBackdrop'
|
||
| 'translucent'
|
||
| 'keyboardClose'
|
||
| 'event'
|
||
>;
|
||
export interface XPopoverOptions extends XXPopOverOptions {
|
||
component: ComponentRef;
|
||
}
|
||
|
||
type XXLoadingOptions = Pick<
|
||
Partial<LoadingOptions>,
|
||
| 'animated'
|
||
| 'backdropDismiss'
|
||
| 'cssClass'
|
||
| 'duration'
|
||
| 'id'
|
||
| 'keyboardClose'
|
||
| 'showBackdrop'
|
||
| 'translucent'
|
||
| 'message'
|
||
>;
|
||
|
||
// tslint:disable-next-line:no-empty-interface
|
||
export interface XLoadingOptions extends XXLoadingOptions {
|
||
spinner?: XSpinnerIdentifier;
|
||
}
|
||
|
||
type XXAlertOptions = Pick<
|
||
Partial<AlertOptions>,
|
||
| 'animated'
|
||
| 'translucent'
|
||
| 'backdropDismiss'
|
||
| 'id'
|
||
| 'keyboardClose'
|
||
| 'cssClass'
|
||
>;
|
||
|
||
export enum XModalButtonRole {
|
||
Cancel = 'cancel',
|
||
Selected = 'selected',
|
||
Destructive = 'destructive',
|
||
}
|
||
|
||
export type XModalButtonRoleIdentifier = XModalButtonRole | string;
|
||
|
||
export interface XModalButton {
|
||
text: XResourceIdentifier;
|
||
role?: XModalButtonRoleIdentifier;
|
||
cssClass?: XOneOrManyType<string>;
|
||
handler?: (
|
||
value?: any
|
||
) =>
|
||
| boolean
|
||
| void
|
||
| {
|
||
[key: string]: any;
|
||
}
|
||
| any;
|
||
}
|
||
|
||
export type XAlertInputType =
|
||
| 'date'
|
||
| 'email'
|
||
| 'number'
|
||
| 'password'
|
||
| 'search'
|
||
| 'tel'
|
||
| 'text'
|
||
| 'url'
|
||
| 'time'
|
||
| 'checkbox'
|
||
| 'radio';
|
||
|
||
export interface XModalInput {
|
||
id?: string;
|
||
value?: any;
|
||
name?: string;
|
||
checked?: boolean;
|
||
disabled?: boolean;
|
||
min?: string | number;
|
||
max?: string | number;
|
||
type?: XAlertInputType;
|
||
label?: XResourceIdentifier;
|
||
placeholder?: XResourceIdentifier;
|
||
handler?: (input: AlertInput) => void;
|
||
}
|
||
|
||
export interface XAlertOptions extends XXAlertOptions {
|
||
header?: XResourceIdentifier;
|
||
subHeader?: XResourceIdentifier;
|
||
message: XResourceIdentifier;
|
||
inputs?: XModalInput[];
|
||
buttons?: XModalButton[];
|
||
}
|
||
|
||
type XXPickerOptions = Pick<
|
||
Partial<PickerOptions>,
|
||
'animated' | 'backdropDismiss' | 'id' | 'cssClass' | 'keyboardClose'
|
||
>;
|
||
|
||
export interface XPickerColumn {
|
||
name: string;
|
||
align?: string;
|
||
selectedIndex?: number;
|
||
prevSelected?: number;
|
||
prefix?: string;
|
||
suffix?: string;
|
||
options: XPickerColumnOption[];
|
||
cssClass?: string | string[];
|
||
columnWidth?: string;
|
||
prefixWidth?: string;
|
||
suffixWidth?: string;
|
||
optionsWidth?: string;
|
||
refresh?: () => void;
|
||
}
|
||
|
||
export interface XPickerColumnOption {
|
||
text?: XResourceIdentifier;
|
||
value: any;
|
||
disabled?: boolean;
|
||
duration?: number;
|
||
transform?: string;
|
||
selected?: boolean;
|
||
}
|
||
|
||
export interface XPickerOptions extends XXPickerOptions {
|
||
buttons?: XModalButton[];
|
||
columns: XPickerColumn[];
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-page.typings.ts
|
||
|
||
import { XOneOrManyType } from './x.typings';
|
||
import { XResourceIdentifier } from './x-translation.typings';
|
||
|
||
export interface XPage {
|
||
id: string;
|
||
name: string;
|
||
icon?: string;
|
||
baseRoute: string;
|
||
title: XResourceIdentifier;
|
||
route: XOneOrManyType<string>;
|
||
childs?: XOneOrManyType<XPage>;
|
||
description?: XResourceIdentifier;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-query.typings.ts
|
||
|
||
export interface XBaseDataPagerQuery {
|
||
filter?: string;
|
||
pageNumber: number;
|
||
rowsInPage: number;
|
||
}
|
||
|
||
export interface XBaseDataPagerQueryResult<T = any> {
|
||
count: number;
|
||
items: T[];
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-setting.typings.ts
|
||
|
||
export type XOrientation = 'landscape' | 'portrait';
|
||
|
||
export enum XDeviceTypes {
|
||
Unknown,
|
||
Mobile,
|
||
Tablet,
|
||
Desktop
|
||
}
|
||
|
||
export interface XDeviceInfo {
|
||
os: string;
|
||
osVersion: string;
|
||
browser: string;
|
||
userAgent: string;
|
||
deviceType: XDeviceTypes;
|
||
userId?: number;
|
||
|
||
identifier?: string;
|
||
token?: string;
|
||
}
|
||
|
||
export type XCssProperties =
|
||
| 'x-app-bar-color'
|
||
| 'ui-direction'
|
||
| 'toolbar-height'
|
||
| string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-storage.typings.ts
|
||
|
||
/**
|
||
* represent a single item which can be stored ...
|
||
*/
|
||
export interface XStorageItem {
|
||
key: string;
|
||
value: string;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-task-manager.typings.ts
|
||
|
||
import { Observable } from 'rxjs';
|
||
import { XException } from './x-exception.typings';
|
||
|
||
export enum XTaskPriority {
|
||
High,
|
||
Medium,
|
||
Regular,
|
||
Weak
|
||
}
|
||
|
||
export interface XTask<T> {
|
||
affectLoading?: boolean;
|
||
name: string;
|
||
priority: XTaskPriority;
|
||
task: Observable<T>;
|
||
result?: T;
|
||
error?: XException;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-theme-manager.typings.ts
|
||
|
||
export enum XThemeType {
|
||
Light = 'light',
|
||
Dark = 'dark',
|
||
}
|
||
|
||
export type XThemeTypeIdentifier = XThemeType | string;
|
||
|
||
export enum XThemeCssVars {
|
||
//
|
||
//#region Primary ...
|
||
XColorPrimary = 'x-color-primary',
|
||
XColorPrimaryContrast = 'x-color-primary-contrast',
|
||
|
||
XColorPrimaryShade = 'x-color-primary-shade',
|
||
XColorPrimaryShadeContrast = 'x-color-primary-shade-contrast',
|
||
|
||
XColorPrimaryTint = 'x-color-primary-tint',
|
||
XColorPrimaryTintContrast = 'x-color-primary-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Secondary ...
|
||
XColorSecondary = 'x-color-secondary',
|
||
XColorSecondaryContrast = 'x-color-secondary-contrast',
|
||
|
||
XColorSecondaryShade = 'x-color-secondary-shade',
|
||
XColorSecondaryShadeContrast = 'x-color-secondary-shade-contrast',
|
||
|
||
XColorSecondaryTint = 'x-color-secondary-tint',
|
||
XColorSecondaryTintContrast = 'x-color-secondary-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Tertiary ...
|
||
XColorTertiary = 'x-color-tertiary',
|
||
XColorTertiaryContrast = 'x-color-tertiary-contrast',
|
||
|
||
XColorTertiaryShade = 'x-color-tertiary-shade',
|
||
XColorTertiaryShadeContrast = 'x-color-tertiary-shade-contrast',
|
||
|
||
XColorTertiaryTint = 'x-color-tertiary-tint',
|
||
XColorTertiaryTintContrast = 'x-color-tertiary-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Success ...
|
||
XColorSuccess = 'x-color-success',
|
||
XColorSuccessContrast = 'x-color-success-contrast',
|
||
|
||
XColorSuccessShade = 'x-color-success-shade',
|
||
XColorSuccessShadeContrast = 'x-color-success-shade-contrast',
|
||
|
||
XColorSuccessTint = 'x-color-success-tint',
|
||
XColorSuccessTintContrast = 'x-color-success-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Warning ...
|
||
XColorWarning = 'x-color-warning',
|
||
XColorWarningContrast = 'x-color-warning-contrast',
|
||
|
||
XColorWarningShade = 'x-color-warning-shade',
|
||
XColorWarningShadeContrast = 'x-color-warning-shade-contrast',
|
||
|
||
XColorWarningTint = 'x-color-warning-tint',
|
||
XColorWarningTintContrast = 'x-color-warning-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Danger ...
|
||
XColorDanger = 'x-color-danger',
|
||
XColorDangerContrast = 'x-color-danger-contrast',
|
||
|
||
XColorDangerShade = 'x-color-danger-shade',
|
||
XColorDangerShadeContrast = 'x-color-danger-shade-contrast',
|
||
|
||
XColorDangerTint = 'x-color-danger-tint',
|
||
XColorDangerTintContrast = 'x-color-danger-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Dark ...
|
||
XColorDark = 'x-color-dark',
|
||
XColorDarkContrast = 'x-color-dark-contrast',
|
||
|
||
XColorDarkShade = 'x-color-dark-shade',
|
||
XColorDarkShadeContrast = 'x-color-dark-shade-contrast',
|
||
|
||
XColorDarkTint = 'x-color-dark-tint',
|
||
XColorDarkTintContrast = 'x-color-dark-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Medium ...
|
||
XColorMedium = 'x-color-medium',
|
||
XColorMediumContrast = 'x-color-medium-contrast',
|
||
|
||
XColorMediumShade = 'x-color-medium-shade',
|
||
XColorMediumShadeContrast = 'x-color-medium-shade-contrast',
|
||
|
||
XColorMediumTint = 'x-color-medium-tint',
|
||
XColorMediumTintContrast = 'x-color-medium-tint-contrast',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Light ...
|
||
XColorLight = 'x-color-light',
|
||
XColorLightContrast = 'x-color-light-contrast',
|
||
|
||
XColorLightShade = 'x-color-light-shade',
|
||
XColorLightShadeContrast = 'x-color-light-shade-contrast',
|
||
|
||
XColorLightTint = 'x-color-light-tint',
|
||
XColorLightTintContrast = 'x-color-light-tint-contrast',
|
||
//#endregion
|
||
}
|
||
|
||
export type XThemeCssVarsIdentifier = XThemeCssVars | string;
|
||
|
||
export type XThemeDescriptorColors = keyof typeof XThemeCssVars;
|
||
|
||
export type XThemeColors = {
|
||
[key in XThemeDescriptorColors]: string;
|
||
};
|
||
|
||
export interface XThemeDescriptor {
|
||
type: XThemeTypeIdentifier;
|
||
colors: XThemeColors;
|
||
}
|
||
|
||
export interface XThemePack {
|
||
name: string;
|
||
light: XThemeDescriptor;
|
||
dark: XThemeDescriptor;
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x-translation.typings.ts
|
||
|
||
import { XResourceIDs } from '../constants/x-translation.resources';
|
||
import { toEnNumbers, toPersianNumbers } from '../tools/x-string.tools';
|
||
|
||
export declare type XLanguageDirection = 'ltr' | 'rtl';
|
||
export declare type XLocale = 'en-US' | 'fa-IR';
|
||
|
||
export interface XLanguageDescriptor {
|
||
name: string;
|
||
locale: XLocale;
|
||
language: string;
|
||
direction: XLanguageDirection;
|
||
resources?: XTranslationItem[];
|
||
}
|
||
|
||
export interface XLanguageDescriptorIndex {
|
||
[name: string]: XLanguageDescriptor;
|
||
}
|
||
|
||
export type XTranslationId = keyof typeof XResourceIDs;
|
||
|
||
export interface XTranslationItem {
|
||
id: XTranslationId | string;
|
||
value: string;
|
||
}
|
||
|
||
export interface XTranslationIndex {
|
||
[name: string]: XTranslationItem;
|
||
}
|
||
|
||
export interface XLocalesIndex {
|
||
[key: string]: XTranslationIndex;
|
||
}
|
||
|
||
export interface GetDateProps {
|
||
date?: Date;
|
||
locale?: XLocale;
|
||
dateFormat?: string;
|
||
toUtc?: boolean;
|
||
}
|
||
|
||
export function applyLocale(content: string, locale: XLocale = 'en-US') {
|
||
switch (locale) {
|
||
case 'en-US':
|
||
return toEnNumbers(content);
|
||
|
||
case 'fa-IR':
|
||
return toPersianNumbers(content);
|
||
}
|
||
}
|
||
|
||
export type XResourceIdentifier = XResourceIDs | XTranslationId | string;
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\typings\x.typings.ts
|
||
|
||
import { Observable } from 'rxjs';
|
||
import { XFileBlob } from '../tools/x-file.tools';
|
||
import { XLocale } from './x-translation.typings';
|
||
import { CountryCode, PhoneNumber } from 'libphonenumber-js';
|
||
|
||
//
|
||
//#region General ...
|
||
export type XStandardType<T> = Observable<T> | Promise<T> | T;
|
||
|
||
export type XOneOrManyType<T> = T | T[];
|
||
|
||
export type XFormControlState = 'VALID' | 'INVALID' | 'PENDING' | 'DISABLED';
|
||
|
||
export type XRouterDirection = 'root' | 'forward' | 'back';
|
||
|
||
export type XFileReaderInputType = File | Blob | XFileBlob | string;
|
||
|
||
export enum XRouterTarget {
|
||
TOP = '_top',
|
||
SELF = '_self',
|
||
BLANK = '_blank',
|
||
PARENT = '_parent',
|
||
}
|
||
|
||
export type XRouterTargetIdentifier = XRouterTarget | string;
|
||
|
||
export enum XMimeType {
|
||
//
|
||
//#region Applications ...
|
||
ApplicationOctetStream = 'application/octet-stream',
|
||
ApplicationPDF = 'application/pdf',
|
||
ApplicationZIP = 'application/zip',
|
||
ApplicationAtomXML = 'application/atom+xml',
|
||
ApplicationGZIP = 'application/gzip',
|
||
ApplicationJSON = 'application/json',
|
||
ApplicationJWT = 'application/jwt',
|
||
ApplicationMP4 = 'application/mp4',
|
||
ApplicationRTF = 'application/rtf',
|
||
ApplicationSQL = 'application/sql',
|
||
ApplicationWSDLXML = 'application/wsdl+xml',
|
||
ApplicationXWWWFormURLEncoded = 'application/x-www-form-urlencoded',
|
||
ApplicationXX509CaCert = 'application/x-x509-ca-cert',
|
||
ApplicationXML = 'application/xml',
|
||
ApplicationJavascript = 'application/javascript',
|
||
ApplicationECMAScript = 'application/ecmascript',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Audios ...
|
||
Audio3GPP = 'audio/3gpp',
|
||
AudioAAC = 'audio/aac',
|
||
AudioAMR = 'audio/AMR',
|
||
AudioMPA = 'audio/MPA',
|
||
AudioMP4 = 'audio/mp4',
|
||
AudioMPEG = 'audio/mpeg',
|
||
AudioOGG = 'audio/ogg',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Fonts ...
|
||
FontCollection = 'font/collection',
|
||
FontOTF = 'font/otf',
|
||
FontSFNT = 'font/sfnt',
|
||
FontTTF = 'font/ttf',
|
||
FontWOFF = 'font/woff',
|
||
FontWOFF2 = 'font/woff2',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Image ...
|
||
ImageBMP = 'image/bmp',
|
||
ImageGIF = 'image/gif',
|
||
ImageJPEG = 'image/jpg',
|
||
ImagePNG = 'image/png',
|
||
ImageSVG = 'image/svg+xml',
|
||
ImageTIFF = 'image/tiff',
|
||
ImageWMF = 'image/wmf',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Messages ...
|
||
MessageSIP = 'message/sip',
|
||
MessageSIPFrag = 'message/sipfrag',
|
||
Message = 'message/',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Multipart ...
|
||
MultipartEncrypted = 'multipart/encrypted',
|
||
MultipartFormData = 'multipart/form-data',
|
||
MultipartHeaderSET = 'multipart/header-set',
|
||
MultipartRelated = 'multipart/related',
|
||
MultipartReport = 'multipart/report',
|
||
MultipartSigned = 'multipart/signed',
|
||
MultipartVoiceMessage = 'multipart/voice-message',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Text ...
|
||
TextCalendar = 'text/calendar',
|
||
TextCSS = 'text/css',
|
||
TextCSV = 'text/csv',
|
||
TextCSVSchema = 'text/csv-schema',
|
||
TextDirectory = 'text/directory',
|
||
TextDNS = 'text/dns',
|
||
TextHTML = 'text/html',
|
||
TextECMAScript = 'text/ecmascript',
|
||
TextJavascript = 'text/javascript',
|
||
TextMarkdown = 'text/markdown',
|
||
TextPlain = 'text/plain',
|
||
TextRTF = 'text/rtf',
|
||
TextStrings = 'text/strings',
|
||
TextVCard = 'text/vcard',
|
||
TextXML = 'text/xml',
|
||
//#endregion
|
||
|
||
//
|
||
//#region Video ...
|
||
Video3GPP = 'video/3gpp',
|
||
Video3GPP2 = 'video/3gpp2',
|
||
VideoH265 = 'video/H265',
|
||
VideoJPEG = 'video/JPEG',
|
||
VideoMP4 = 'video/mp4',
|
||
VideoMPV = 'video/MPV',
|
||
VideoMPEG = 'video/mpeg',
|
||
VideoOGG = 'video/ogg',
|
||
VideoQuicktime = 'video/quicktime',
|
||
//#endregion
|
||
}
|
||
|
||
export type XMimeTypeIdentifier = XMimeType | string;
|
||
|
||
export enum XSpinner {
|
||
Lines = 'lines',
|
||
LinesSmall = 'lines-small',
|
||
Dots = 'dots',
|
||
Bubbles = 'bubbles',
|
||
Circles = 'circles',
|
||
Circular = 'circular',
|
||
Crescent = 'crescent',
|
||
}
|
||
|
||
export type XSpinnerIdentifier = XSpinner | string | any;
|
||
|
||
export type XCountryCode = CountryCode;
|
||
|
||
export type XPhoneNumber = PhoneNumber;
|
||
|
||
export enum XFormatterType {
|
||
ApplyLocale = 'apply_locale',
|
||
FormatCurrency = 'format_currency',
|
||
StringFormatter = 'string_formatter',
|
||
FormatCurrencyAndApplyLocale = 'format_currency_apply_locale',
|
||
StringFormatterAndApplyLocale = 'string_formatter_apply_locale',
|
||
}
|
||
|
||
export interface XFormatterOption {
|
||
type: XFormatterType;
|
||
locale?: XLocale;
|
||
seperator?: string;
|
||
currencyLable?: string;
|
||
pattern?: number[];
|
||
}
|
||
|
||
export enum XDialogResult {
|
||
Cancel,
|
||
Ok,
|
||
Retry,
|
||
Opened,
|
||
Restart,
|
||
}
|
||
|
||
export interface XBaseKeyValue<T> {
|
||
key: string;
|
||
value: T;
|
||
}
|
||
|
||
export interface XKeyValue<TKey, TValue> {
|
||
key: TKey;
|
||
value: TValue;
|
||
}
|
||
|
||
export interface XHasAction<T = any> {
|
||
action: T;
|
||
payload?: any
|
||
}
|
||
|
||
export type XKey<T> = keyof T;
|
||
export type XKeysOfXType<T, U> = { [K in keyof T]: T[K] extends U ? K : never }[keyof T];
|
||
export type XStringKeys<T> = Extract<XKey<T>, string>;
|
||
export type XValueOf<T> = T[XKey<T>];
|
||
export type XRef<T = any> = { value: T };
|
||
export type XPropertyType<T, K extends keyof T> = T[K];
|
||
export type XModelFieldTypeIndex<T> = {
|
||
[key in XKey<T>]: string;
|
||
};
|
||
export type XPartialModelFieldNames<T> = XOneOrManyType<
|
||
Partial<XKey<XModelFieldTypeIndex<T>>>
|
||
>;
|
||
export type XDeep<T> = keyof T & T extends object
|
||
? { [P in keyof T]: XDeep<T[P]> }
|
||
: T;
|
||
export type XDeepPartial<T> = T extends Function
|
||
? T
|
||
: T extends object
|
||
? { [P in keyof T]?: XDeepPartial<T[P]> }
|
||
: T;
|
||
|
||
export type XModelKeyType<T = any> = keyof Partial<T> | string;
|
||
|
||
export type XModelFieldsType<T = any> = XOneOrManyType<XModelKeyType<T>>;
|
||
|
||
export type XModelKeyProvider<T = any> = (
|
||
key: XModelKeyType<T>
|
||
) => XStandardType<string>;
|
||
|
||
export type XModelValueProvider<T> = (
|
||
key: XModelKeyType<T>,
|
||
value: any
|
||
) => XStandardType<any>;
|
||
|
||
export interface XModelProperty<T = any>
|
||
extends XKeyValue<XModelKeyType<T>, any> {
|
||
prefix?: string;
|
||
}
|
||
|
||
export type XGConstructor<T = {}> = new (...args: any[]) => T;
|
||
export type XConstructor = new (...args: any[]) => {};
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\validators\x-general-validators.ts
|
||
|
||
import {
|
||
XPhoneNumber,
|
||
XCountryCode,
|
||
XOneOrManyType
|
||
} from '../typings/x.typings';
|
||
import {
|
||
isNullOrUndefined,
|
||
isNullOrEmptyString
|
||
} from '../tools/x-type-detect.tools';
|
||
import { hasChild, toArray } from '../tools/x-array.tools';
|
||
import { throwException } from '../tools/x-exception.tools';
|
||
import { parsePhoneNumberFromString } from 'libphonenumber-js';
|
||
import { XExceptionIDs } from '../constants/x-exception.resources';
|
||
|
||
//
|
||
//#region Custom Type Checker and Converters ...
|
||
/**
|
||
* check specified value is Valid URL Address or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
*/
|
||
export function isValidURL(value: string) {
|
||
//
|
||
const pattern = new RegExp(
|
||
'^(https?:\\/\\/)?' + // protocol
|
||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' + // domain name
|
||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // ip (v4) address
|
||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port
|
||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||
'(\\#[-a-z\\d_]*)?$',
|
||
'i'
|
||
);
|
||
|
||
//
|
||
return pattern.test(value);
|
||
}
|
||
|
||
/**
|
||
* check specified value is Valid URL Address or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
*/
|
||
export function isValidEmail(value: string) {
|
||
//
|
||
const pattern = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/gim;
|
||
|
||
//
|
||
return pattern.test(value);
|
||
}
|
||
|
||
/**
|
||
* check specified value is Valid Phone Number or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
* @param defaultCountryCode an optional value which used for country code if not exists in value
|
||
*/
|
||
export function isValidPhoneNumber(
|
||
value: string,
|
||
defaultCountryCode?: XCountryCode
|
||
) {
|
||
//
|
||
const mParsedPhoneNumber = parsePhoneNumber(value, defaultCountryCode);
|
||
if (!mParsedPhoneNumber) {
|
||
return false;
|
||
}
|
||
|
||
//
|
||
return mParsedPhoneNumber.isValid();
|
||
}
|
||
|
||
/**
|
||
* parse an string as phone number and extract several information of it ...
|
||
*
|
||
* @param value specified string is represent phone number ...
|
||
* @param defaultCountryCode an optional value which used for country code if not exists in value
|
||
*/
|
||
export function parsePhoneNumber(
|
||
value: string,
|
||
defaultCountryCode?: XCountryCode
|
||
): XPhoneNumber {
|
||
//
|
||
try {
|
||
return parsePhoneNumberFromString(value, defaultCountryCode);
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* normalize specified phone number and format it ...
|
||
*
|
||
* @param value specified string which required to normalized ...
|
||
* @param defaultCountryCode an optional value which used for country code if not exists in value
|
||
*/
|
||
export function normalizePhoneNumber(
|
||
value: string,
|
||
defaultCountryCode?: XCountryCode
|
||
) {
|
||
//
|
||
try {
|
||
//
|
||
const parsedNumber = parsePhoneNumber(value, defaultCountryCode);
|
||
if (!parsedNumber) {
|
||
throw new Error('can not Parse Phone Number ...');
|
||
}
|
||
|
||
//
|
||
return parsedNumber.number.toString();
|
||
} catch {
|
||
return null;
|
||
}
|
||
}
|
||
//#endregion
|
||
|
||
//
|
||
//#region Data Validators from Several Types ...
|
||
export class XValidators {
|
||
//
|
||
private static throwInvalidArgsException() {
|
||
throwException(XExceptionIDs.InvalidArgs);
|
||
}
|
||
|
||
/**
|
||
* check args not Null or Undefined ...
|
||
*
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateNotNull(...args: any[]) {
|
||
//
|
||
const isValid = args.every(arg => !isNullOrUndefined(arg));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check args not empty string or null or undefined ...
|
||
*
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateNotEmpty(...args: string[]) {
|
||
//
|
||
const isValid = args.every(arg => !isNullOrEmptyString(arg));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check args must have childs ...
|
||
*
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateHasChilds(...args: any[][]) {
|
||
//
|
||
const isValid = args.every(arg => hasChild(arg));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args not equal to specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateNotEquals<T>(values: XOneOrManyType<T>, ...args: T[]) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => !mValues.includes(arg));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args equal to specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateEquals<T>(values: XOneOrManyType<T>, ...args: T[]) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => mValues.includes(arg));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args bigger than specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateBiggerThan(values: number | number[], ...args: number[]) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => mValues.every(n => arg > n));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args less than specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateLessThan(values: number | number[], ...args: number[]) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => mValues.every(n => arg < n));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args bigger than or equals to specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateBiggerThanOrEquals(
|
||
values: number | number[],
|
||
...args: number[]
|
||
) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => mValues.every(n => arg >= n));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check all args less than or equals to specified values ...
|
||
*
|
||
* @param values a single or collection value which going to compare
|
||
* @param args any args which required to check
|
||
*/
|
||
static validateLessThanOrEquals(
|
||
values: number | number[],
|
||
...args: number[]
|
||
) {
|
||
//
|
||
const mValues = toArray(values);
|
||
|
||
//
|
||
const isValid = args.every(arg => mValues.every(n => arg <= n));
|
||
if (!isValid) {
|
||
XValidators.throwInvalidArgsException();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check specified value is Valid URL Address or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
*/
|
||
static validateURL(value: string) {
|
||
//
|
||
XValidators.validateNotEmpty(value);
|
||
|
||
//
|
||
if (!isValidURL(value)) {
|
||
throwException(XExceptionIDs.InvalidEmailAddress);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check specified value is Valid Email Address or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
*/
|
||
static validateEmailAddress(value: string) {
|
||
//
|
||
XValidators.validateNotEmpty(value);
|
||
|
||
//
|
||
if (!isValidEmail(value)) {
|
||
throwException(XExceptionIDs.InvalidEmailAddress);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* check specified value is Valid Phone Number or not ...
|
||
*
|
||
* @param value specified string which required to check
|
||
* @param defaultCountryCode an optional value which used for country code if not exists in value
|
||
*/
|
||
static validatePhoneNumber(value: string, defaultCountryCode?: XCountryCode) {
|
||
//
|
||
XValidators.validateNotEmpty(value);
|
||
|
||
//
|
||
if (!isValidPhoneNumber(value, defaultCountryCode)) {
|
||
throwException(XExceptionIDs.InvalidMobileNumber);
|
||
}
|
||
}
|
||
}
|
||
//#endregion
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\validators\x-valid-email.directive.ts
|
||
|
||
import { Directive } from '@angular/core';
|
||
import { isValidEmail } from './x-general-validators';
|
||
import { Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xValidEmail]'
|
||
})
|
||
export class XValidEmailDirective implements Validator {
|
||
//
|
||
private errorObject = {
|
||
xValidEmail: true
|
||
};
|
||
|
||
validate(control: AbstractControl): ValidationErrors {
|
||
//
|
||
const sourceValue =
|
||
control && control.value ? (control.value as string) : null;
|
||
|
||
//
|
||
let isValid = false;
|
||
try {
|
||
isValid = isValidEmail(sourceValue);
|
||
} catch {}
|
||
|
||
//
|
||
return !isValid ? this.errorObject : null;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\validators\x-valid-phone-number.directive.ts
|
||
|
||
import { XCountryCode } from '../typings/x.typings';
|
||
import { Directive, Input, Inject } from '@angular/core';
|
||
import { isValidPhoneNumber } from './x-general-validators';
|
||
import { X_FRAMEWORK_CORE_CONFIG } from '../tokens/x-injectable-tokens';
|
||
import { XFrameworkCoreConfig } from '../config/x-framework-core.config';
|
||
import { Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xValidPhoneNumber]'
|
||
})
|
||
export class XValidPhoneNumberDirective implements Validator {
|
||
//
|
||
private errorObject = {
|
||
xValidMobile: true
|
||
};
|
||
|
||
//
|
||
@Input()
|
||
defaultCountryCode: XCountryCode = this.config.defaultCountryCode;
|
||
|
||
constructor(
|
||
@Inject(X_FRAMEWORK_CORE_CONFIG) private config: XFrameworkCoreConfig
|
||
) {}
|
||
|
||
validate(control: AbstractControl): ValidationErrors {
|
||
//
|
||
const value = control && control.value ? (control.value as string) : null;
|
||
|
||
//
|
||
const isValid = isValidPhoneNumber(value, this.defaultCountryCode);
|
||
|
||
//
|
||
return !isValid ? this.errorObject : null;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\validators\x-valid-url.directive.ts
|
||
|
||
import { Directive, Input } from '@angular/core';
|
||
import { isValidURL } from './x-general-validators';
|
||
import { Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xValidUrl]'
|
||
})
|
||
export class XValidUrlDirective implements Validator {
|
||
//
|
||
private errorObject = {
|
||
xValidUrl: true
|
||
};
|
||
|
||
@Input()
|
||
isOptional: boolean;
|
||
|
||
constructor() {}
|
||
|
||
validate(control: AbstractControl): ValidationErrors {
|
||
//
|
||
const sourceValue =
|
||
control && control.value ? (control.value as string) : null;
|
||
|
||
//
|
||
let isValid = false;
|
||
if (!sourceValue && this.isOptional) {
|
||
isValid = true;
|
||
} else {
|
||
isValid = sourceValue && isValidURL(sourceValue);
|
||
}
|
||
|
||
//
|
||
return !isValid ? this.errorObject : null;
|
||
}
|
||
}
|
||
|
||
### FILE: C:\Users\SaherElm\Documents\Projects\xSaherelmWorkspace\Modules\xFrameworkCoreHolder\projects\x-framework-core\src\lib\validators\x-value-match.directive.ts
|
||
|
||
import {
|
||
NgModel,
|
||
Validator,
|
||
AbstractControl,
|
||
ValidationErrors
|
||
} from '@angular/forms';
|
||
import { Directive, Input } from '@angular/core';
|
||
import { isNullOrEmptyString } from '../tools/x-type-detect.tools';
|
||
|
||
@Directive({
|
||
// tslint:disable-next-line:directive-selector
|
||
selector: '[xValueMatch]'
|
||
})
|
||
export class XValueMatchDirective implements Validator {
|
||
private errorObject = {
|
||
xValueMatch: true
|
||
};
|
||
|
||
//
|
||
@Input('xValueMatch')
|
||
matchTo: NgModel;
|
||
|
||
//
|
||
validate(control: AbstractControl): ValidationErrors {
|
||
//
|
||
if (!control) {
|
||
return this.errorObject;
|
||
}
|
||
const value = control.value as string;
|
||
|
||
//
|
||
if (!this.matchTo) {
|
||
return this.errorObject;
|
||
}
|
||
const destControl = this.matchTo.control;
|
||
if (!destControl) {
|
||
return this.errorObject;
|
||
}
|
||
|
||
//
|
||
const destValue = destControl.value;
|
||
|
||
//
|
||
const isValid =
|
||
!isNullOrEmptyString(destValue) &&
|
||
!isNullOrEmptyString(value) &&
|
||
value === destValue;
|
||
|
||
//
|
||
if (isValid && destControl.invalid) {
|
||
destControl.updateValueAndValidity();
|
||
}
|
||
|
||
//
|
||
return !isValid ? this.errorObject : null;
|
||
}
|
||
}
|