Initial Commit on git.saherelm.ir ...
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
# Only exists if Bazel was run
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# profiling files
|
||||||
|
chrome-profiler-events*.json
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# misc
|
||||||
|
/.sass-cache
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
#
|
||||||
|
documentation
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
#
|
||||||
|
.angular
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# XFrameworkCore
|
||||||
|
|
||||||
|
this is xFramework's core module and conatins core features of XFramework Library.
|
||||||
|
|
||||||
|
## Maintainer
|
||||||
|
|
||||||
|
Hadi Khazaee asl
|
||||||
|
|
||||||
|
[https://www.saherelm.ir](https://www.saherelm.ir)
|
||||||
|
|
||||||
|
[hadi_khazaee_asl@yahoo.com](mailto:hadi_khazaee_asl@yahoo.com)
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"cli": {
|
||||||
|
"analytics": false
|
||||||
|
},
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"x-framework-core": {
|
||||||
|
"projectType": "library",
|
||||||
|
"root": "projects/x-framework-core",
|
||||||
|
"sourceRoot": "projects/x-framework-core/src",
|
||||||
|
"prefix": "x",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:ng-packagr",
|
||||||
|
"options": {
|
||||||
|
"project": "projects/x-framework-core/ng-package.json"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"tsConfig": "projects/x-framework-core/tsconfig.lib.prod.json"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"tsConfig": "projects/x-framework-core/tsconfig.lib.json"
|
||||||
|
},
|
||||||
|
"ivy": {
|
||||||
|
"tsConfig": "projects/x-framework-core/tsconfig.lib.ivy.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"main": "projects/x-framework-core/src/test.ts",
|
||||||
|
"tsConfig": "projects/x-framework-core/tsconfig.spec.json",
|
||||||
|
"karmaConfig": "projects/x-framework-core/karma.conf.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultProject": "x-framework-core"
|
||||||
|
}
|
||||||
Vendored
+758
@@ -0,0 +1,758 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"name": "x-framework-core-holder",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "an isolation layoer of xFrameworkCore module",
|
||||||
|
"keywords": [
|
||||||
|
"x-framework",
|
||||||
|
"x-framework-core"
|
||||||
|
],
|
||||||
|
"homepage": "https://saherelm.ir",
|
||||||
|
"author": {
|
||||||
|
"name": "Hadi Khazaee Asl",
|
||||||
|
"email": "hadi_khazaee_asl@yahoo.com",
|
||||||
|
"url": "https://saherelm.ir"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"publishModule": "npm run buildModule && npm run packModule",
|
||||||
|
"build:ivy": "ng build x-framework-core --configuration=ivy",
|
||||||
|
"serveDocs": "compodoc -p projects/x-framework-core/tsconfig.lib.json --theme material -s",
|
||||||
|
"buildModule": "npm run preBuildModule && ng build x-framework-core --configuration production",
|
||||||
|
"packModule": "cd dist/x-framework-core && npm pack && shx mv *.tgz ../../../../pack && cd ../..",
|
||||||
|
"preBuildModule": "shx true --silent mkdir ../../pack && shx true --silent rm -rf dist && shx true --silent rm ../../pack/x-framework-core*.tgz",
|
||||||
|
"generateDocs": "compodoc -p projects/x-framework-core/tsconfig.lib.json --theme material --hideGenerator --disableSourceCode --disableDomTree --disableTemplateTab --disableStyleTab --disablePrivate --disableLifeCycleHooks --disableRoutesGraph --disableCoverage --customFavicon ../xFrameworkDocuments/Resources/favicon.png --customLogo ../xFrameworkDocuments/Resources/favicon.png"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "~12.0.4",
|
||||||
|
"@angular/common": "~12.0.4",
|
||||||
|
"@angular/compiler": "~12.0.4",
|
||||||
|
"@angular/core": "~12.0.4",
|
||||||
|
"@angular/forms": "~12.0.4",
|
||||||
|
"@angular/platform-browser": "~12.0.4",
|
||||||
|
"@angular/platform-browser-dynamic": "~12.0.4",
|
||||||
|
"@angular/router": "~12.0.4",
|
||||||
|
"rxjs": "~6.6.0",
|
||||||
|
"tslib": "^2.1.0",
|
||||||
|
"zone.js": "~0.11.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "~12.0.4",
|
||||||
|
"@angular/cdk": "^12.1.2",
|
||||||
|
"@angular/cli": "~12.0.4",
|
||||||
|
"@angular/compiler-cli": "~12.0.4",
|
||||||
|
"@angular/material": "^12.1.2",
|
||||||
|
"@angular/material-moment-adapter": "^12.1.2",
|
||||||
|
"@compodoc/compodoc": "^1.1.14",
|
||||||
|
"@ionic/angular": "^5.6.11",
|
||||||
|
"@types/jasmine": "~3.6.0",
|
||||||
|
"@types/node": "^12.11.1",
|
||||||
|
"@types/uuid": "^8.3.1",
|
||||||
|
"ionicons": "^5.5.2",
|
||||||
|
"jalali-moment": "^3.3.10",
|
||||||
|
"jasmine-core": "~3.7.0",
|
||||||
|
"karma": "~6.3.0",
|
||||||
|
"karma-chrome-launcher": "~3.1.0",
|
||||||
|
"karma-coverage": "~2.0.3",
|
||||||
|
"karma-jasmine": "~4.0.0",
|
||||||
|
"karma-jasmine-html-reporter": "^1.5.0",
|
||||||
|
"libphonenumber-js": "^1.9.22",
|
||||||
|
"md5-typescript": "^1.0.5",
|
||||||
|
"moment": "^2.29.1",
|
||||||
|
"ng-packagr": "^12.0.0",
|
||||||
|
"shx": "^0.3.3",
|
||||||
|
"typescript": "~4.2.3",
|
||||||
|
"undefined": "^0.1.0",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# XFrameworkCore
|
||||||
|
|
||||||
|
this is xFramework's core module and conatins core features of XFramework Library.
|
||||||
|
|
||||||
|
## Maintainer
|
||||||
|
|
||||||
|
Hadi Khazaee asl
|
||||||
|
|
||||||
|
<https://www.saherelm.ir>
|
||||||
|
|
||||||
|
hadi_khazaee_asl@yahoo.com
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// Karma configuration file, see link for more information
|
||||||
|
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||||
|
|
||||||
|
module.exports = function (config) {
|
||||||
|
config.set({
|
||||||
|
basePath: '',
|
||||||
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
|
plugins: [
|
||||||
|
require('karma-jasmine'),
|
||||||
|
require('karma-chrome-launcher'),
|
||||||
|
require('karma-jasmine-html-reporter'),
|
||||||
|
require('karma-coverage'),
|
||||||
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
|
],
|
||||||
|
client: {
|
||||||
|
jasmine: {
|
||||||
|
// you can add configuration options for Jasmine here
|
||||||
|
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||||
|
// for example, you can disable the random execution with `random: false`
|
||||||
|
// or set a specific seed with `seed: 4321`
|
||||||
|
},
|
||||||
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
|
},
|
||||||
|
jasmineHtmlReporter: {
|
||||||
|
suppressAll: true // removes the duplicated traces
|
||||||
|
},
|
||||||
|
coverageReporter: {
|
||||||
|
dir: require('path').join(__dirname, '../../coverage/x-framework-core'),
|
||||||
|
subdir: '.',
|
||||||
|
reporters: [
|
||||||
|
{ type: 'html' },
|
||||||
|
{ type: 'text-summary' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
reporters: ['progress', 'kjhtml'],
|
||||||
|
port: 9876,
|
||||||
|
colors: true,
|
||||||
|
logLevel: config.LOG_INFO,
|
||||||
|
autoWatch: true,
|
||||||
|
browsers: ['Chrome'],
|
||||||
|
singleRun: false,
|
||||||
|
restartOnFileChange: true
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../dist/x-framework-core",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public-api.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "x-framework-core",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "core features of xFramework",
|
||||||
|
"keywords": [
|
||||||
|
"x-framework",
|
||||||
|
"x-framework-core"
|
||||||
|
],
|
||||||
|
"homepage": "https://saherelm.ir",
|
||||||
|
"author": {
|
||||||
|
"name": "Hadi Khazaee Asl",
|
||||||
|
"email": "hadi_khazaee_asl@yahoo.com",
|
||||||
|
"url": "https://saherelm.ir"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^12.0.4",
|
||||||
|
"@angular/core": "^12.0.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { XLoggable } from './x-loggable';
|
||||||
|
|
||||||
|
export abstract class XBaseService extends XLoggable {
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
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];
|
||||||
|
};
|
||||||
@@ -0,0 +1,429 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export enum XCrudAction {
|
||||||
|
Add = 'add',
|
||||||
|
Update = 'update',
|
||||||
|
Delete = 'delete'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type XCrudActionIdentifier = XCrudAction | string;
|
||||||
@@ -0,0 +1,359 @@
|
|||||||
|
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
|
||||||
|
};
|
||||||
@@ -0,0 +1,588 @@
|
|||||||
|
//
|
||||||
|
//#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
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
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}`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export enum XSettingsStorageKey {
|
||||||
|
Locale = '[SETTINGS] Locale'
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const DEFAULT_JAVASCRIPT_VOID_HREF = 'javascript:void(0)';
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
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() : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,187 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,329 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
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}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
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> {}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { XBaseDto } from "./x-base-dto";
|
||||||
|
|
||||||
|
export interface XGroupedDataDto<T, TGroupedy> extends XBaseDto {
|
||||||
|
groupedBy: TGroupedy;
|
||||||
|
members: Array<T>;
|
||||||
|
timeStamp: Date;
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
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 {}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
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() : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
import { XFrameworkCoreConfig } from '../config/x-framework-core.config';
|
||||||
|
|
||||||
|
export const X_FRAMEWORK_CORE_CONFIG = new InjectionToken<XFrameworkCoreConfig>(
|
||||||
|
'x_config'
|
||||||
|
);
|
||||||
@@ -0,0 +1,309 @@
|
|||||||
|
//
|
||||||
|
//#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 diff suppressed because it is too large
Load Diff
@@ -0,0 +1,574 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
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 diff suppressed because it is too large
Load Diff
@@ -0,0 +1,287 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
//#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 diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,516 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
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}`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
//#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
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
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;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const DEFAULT_EXPORT_TYPING_BASE = 'default';
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
//
|
||||||
|
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
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export enum XUnitOfTime {
|
||||||
|
Year,
|
||||||
|
Month,
|
||||||
|
Day
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export enum XUiEvent {
|
||||||
|
//
|
||||||
|
StartLoading,
|
||||||
|
StopLoading,
|
||||||
|
|
||||||
|
//
|
||||||
|
Disabled,
|
||||||
|
Enabled,
|
||||||
|
|
||||||
|
//
|
||||||
|
Locked,
|
||||||
|
UnLocked,
|
||||||
|
|
||||||
|
//
|
||||||
|
BackPrevented,
|
||||||
|
BackReleased,
|
||||||
|
|
||||||
|
//
|
||||||
|
Ready
|
||||||
|
}
|
||||||
@@ -0,0 +1,262 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export interface XBaseDataPagerQuery {
|
||||||
|
filter?: string;
|
||||||
|
pageNumber: number;
|
||||||
|
rowsInPage: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface XBaseDataPagerQueryResult<T = any> {
|
||||||
|
count: number;
|
||||||
|
items: T[];
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* represent a single item which can be stored ...
|
||||||
|
*/
|
||||||
|
export interface XStorageItem {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
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;
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,316 @@
|
|||||||
|
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
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
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 {}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// 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);
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.lib.json",
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"enableIvy": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"declaration": true,
|
||||||
|
"declarationMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2018"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
|
{
|
||||||
|
"extends": "./tsconfig.lib.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"declarationMap": false
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"compilationMode": "partial"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||||
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"sourceMap": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"module": "es2020",
|
||||||
|
"declaration": false,
|
||||||
|
"importHelpers": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"outDir": "./dist/out-tsc",
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"lib": [
|
||||||
|
"es2018",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"x-framework-core": [
|
||||||
|
"dist/x-framework-core/x-framework-core",
|
||||||
|
"dist/x-framework-core"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"strictTemplates": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"strictInputAccessModifiers": true,
|
||||||
|
"enableI18nLegacyMessageIdFormat": false
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user