UNPKG

@dotgov/core

Version:

DGS core.

854 lines (835 loc) 30 kB
import { EventEmitter, Injectable, ɵɵdefineInjectable, ɵɵinject, Inject, ReflectiveInjector, ComponentFactoryResolver, Pipe, ChangeDetectorRef, APP_INITIALIZER, NgModule, CUSTOM_ELEMENTS_SCHEMA, Component, Input, Directive, ElementRef } from '@angular/core'; import { HttpHeaders, HttpClient, HttpClientModule } from '@angular/common/http'; import { CommonModule } from '@angular/common'; import { TranslatePipe, TranslateService } from '@ngx-translate/core'; class StorageService { constructor() { this._storage = {}; this._inProgress = {}; } get(key) { return this._storage[key]; } set(key, value) { this._storage[key] = value; } remove(key, taskId) { const found = this._storage[key]; if (taskId && found && Array.isArray(found)) { const index = found.findIndex(f => f.taskId === taskId); if (index > -1) { found.splice(index, 1); if (found.length > 0) { this._storage[key] = found; return; } } else { return found; } } delete this._storage[key]; } removeMatched(match) { Object.keys(this._storage).forEach(key => { if (key.indexOf(match) !== -1) { this.remove(key); } }); Object.keys(this._inProgress).forEach(key => { if (key.indexOf(match) !== -1) { this.deleteProgress(key); } }); } clearCache() { this._inProgress = {}; this._storage = {}; } getProgress(key) { return this._inProgress[key]; } deleteProgress(key) { delete this._inProgress[key]; } setProgress(key) { this._inProgress[key] = new EventEmitter(); } } StorageService.decorators = [ { type: Injectable } ]; StorageService.ctorParameters = () => []; class LoginMetadata { } LoginMetadata.samlRequestIdKey = 'EP_samlRequestID_key'; LoginMetadata.samlRelayStateKey = 'RelayState'; LoginMetadata.samlResponsePrefixKey = 'SAMLResponse_'; LoginMetadata.samlResponsePartsCountKey = 'SAMLResponsePartsCount'; LoginMetadata.externalSessionIndexKey = 'externalSessionIndex'; LoginMetadata.userContext = 'userContext'; LoginMetadata.activeRole = 'activeRole'; class Debugger { constructor() { } init(environment) { const debugAll = environment.debug === true; this._environment = environment; this._buttonsDebug = debugAll || (environment.debug && environment.debug['buttons'] === true); this._missingFieldsDebug = debugAll || (environment.debug && environment.debug['missingFields'] === true); } log(...messages) { this.action('log', ...messages); } warn(...messages) { this.action('warn', ...messages); } error(...messages) { this.action('error', ...messages); } info(...messages) { this.action('info', ...messages); } debug(...messages) { this.action('debug', ...messages); } action(method, ...messages) { const shouldRuntimeDebug = window['dgs_debug'] === true; const debug = this._environment.debug; if (!debug || (typeof debug !== 'object' && typeof debug !== 'boolean')) { return; } const shouldDebug = debug === true || debug['logs'] === true || (debug['logs'] && debug['logs'][method] === true); if (shouldDebug || shouldRuntimeDebug) { console[method](...messages); } } } class Helper { static validValue(val) { const type = typeof val; if (val === undefined) { return false; } else if (type === 'string') { return val !== ''; } else if (type === 'number') { return Number.isFinite(val); } else { return true; } } /** * @param _date * @param showTime Decide if we should show the time as well or not * @param forControl Decide if should return format dd/mm/yyyy * @returns YYYY-MM-DD HH:mm */ static formatDate(_date, showTime = true, forControl = false) { if (!_date) { return; } const date = Helper.convertToDate(_date); const pad = n => (n <= 9 ? `0${n}` : n); const time = ` ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`; if (forControl) { return `${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${date.getFullYear()}${showTime ? time : ''}`.trim(); } // For .post send MM/dd/yyyy HH:mm:ss. return `${pad(date.getMonth() + 1)}/${pad(date.getDate())}/${date.getFullYear()}${showTime ? time : ''}`.trim(); } static stringToDate(strDate, dayFirst = false) { // IE11 fix, if match: "2018-03-14 04:31:56.142" // Invalid date fix: 01/02/2018 => 01, 02, 2017; 2018-02-01 => 2018, 02, 01 let res = strDate.match(/\d+/gim).map(res => Number(res)); let [MM, dd, YYYY, HH, mm, ss] = res; if (dayFirst) { [dd, MM, YYYY] = res; } else if (MM > 12) { // First was year, transforming to correspond. [YYYY, MM, dd] = res; } const sanitize = num => (num !== undefined ? num : 0); return new Date(sanitize(YYYY), sanitize(Number(MM) - 1), sanitize(dd), sanitize(HH), sanitize(mm), sanitize(ss)); } static convertToDate(d) { if (d === undefined || d === null) { return NaN; } const isDate = d.constructor === Date; const isArray = d.constructor === Array; const isNum = d.constructor === Number; const isString = d.constructor === String; const isObject = typeof d === 'object'; return ((isDate && d) || (isArray && new Date(d[0], d[1], d[2])) || (isNum && new Date(d)) || (isString && Helper.stringToDate(d)) || (isObject && new Date(d.year, d.month, d.date)) || NaN); } static camelize(str) { const capitalize = _str => _str.charAt(0).toUpperCase() + _str.toLowerCase().slice(1); const string = str .toLowerCase() .replace(/[^A-Za-z0-9]/g, ' ') .split(' ') .reduce((result, word) => result + capitalize(word.toLowerCase())); return string.charAt(0).toLowerCase() + string.slice(1); } static isValidUrl(uri) { try { new URL(uri); } catch (_) { return false; } return true; } } class AppConfigService { constructor(environment) { this.environment = environment; } load() { const jsonFile = this.environment.settingsUrl; return new Promise((resolve, reject) => { fetch(jsonFile) .then(response => response.json()) .then((data) => { AppConfigService.settings = data; if (!Helper.isValidUrl(AppConfigService.settings.apiUrl)) { this.setEnvironmentAPIURI(); } ; resolve(); }) .catch((response) => { reject(`Could not load file '${jsonFile}': ${JSON.stringify(response)}`); }); }); } setEnvironmentAPIURI() { AppConfigService.settings['apiUrl'] = this.environment.apiUrl; } } AppConfigService.settings = {}; AppConfigService.ɵprov = ɵɵdefineInjectable({ factory: function AppConfigService_Factory() { return new AppConfigService(ɵɵinject("environment")); }, token: AppConfigService, providedIn: "platform" }); AppConfigService.decorators = [ { type: Injectable, args: [{ providedIn: 'platform', },] } ]; AppConfigService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: ['environment',] }] } ]; class ApiResponse { constructor(data, error) { this.data = data; this.error = error; } } class ApiService extends StorageService { constructor(httpClient, appConfig, customAuthenticator, environment) { super(); this.httpClient = httpClient; this.appConfig = appConfig; this.customAuthenticator = customAuthenticator; this.environment = environment; this.sanitizeMark = '___mk___'; } /** * Make GET request to api * @param point * @param args * @param parameters * @param options */ get(point, args = [], parameters = {}, options = {}) { return this.request('GET', point, parameters, options, undefined, ...args); } /** * Make DELETE request to api * @param point * @param args * @param parameters * @param options */ delete(point, args = [], parameters = {}, options = {}, body = {}) { return this.request('DELETE', point, parameters, options, body, ...args); } /** * Make OPTIONS request to api * @param point * @param args * @param parameters * @param options */ options(point, args = [], parameters = {}, options = {}) { return this.request('OPTIONS', point, parameters, options, undefined, ...args); } /** * Make POST request to api * @param point * @param args * @param parameters * @param options */ post(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('POST', point, parameters, options, body, ...args); } /** * Make PATCH request to api * @param point * @param args * @param parameters * @param options */ patch(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('PATCH', point, parameters, options, body, ...args); } /** * Make PUT request to api * @param point * @param args * @param parameters * @param options */ put(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('PUT', point, parameters, options, body, ...args); } /** * Return generated url * @param point * @param args * @param parameters * @param body * @param options */ getURL(point, args = [], parameters = {}, body = {}, options = {}) { return this.request('getURL', point, parameters, options, body, ...args); } get apiRenameList() { return ['Name', 'Title']; } get API() { return AppConfigService.settings.apiUrl; } rename(origin, target) { this.languages.forEach(lang => { const from = `${origin}_${lang}`; const to = `${origin}`; if (target) { return; } if (target.hasOwnProperty(from) && !target.hasOwnProperty(to)) { target[to] = target[from]; delete target[from]; } }); } /** * Generates final url from api_url + view + query parameters; * @param url * @param parameters * @param args */ generateUrl(url, parameters, ...args) { const endUrl = `${url}${args.length ? `/${args.join('/')}` : ''}`; const queryParams = Object.keys(parameters) .map(key => `${key}=${this.sanitize(parameters[key])}`) .join('&'); return `${endUrl}${queryParams ? `?${queryParams}` : ''}`; } sanitize(item) { const exists = item !== undefined && item !== null; const isNum = val => val.constructor === Number; const isString = val => val.constructor === String; if (!exists) { return item; } if (isString(item)) { return item.trim(); } if (isNum(item)) { return item; } if (item && Array.isArray(item)) { item = item.map(curr => { if (!curr) { return curr; } if (curr.hasOwnProperty('value')) { curr.value = !!curr.value ? curr.value.toString() : null; } return curr; }); } return JSON.stringify(item); } /** * If data contains fields like Name_ru/Name_ro/Name_en transform it into Name. * @param data */ resolve(response) { if (response && response.data && Array.isArray(response.data)) { response.data.forEach(item => { this.apiRenameList.forEach(renameOrigin => { this.rename(renameOrigin, item); }); }); } // Already been sanitized if (response && response.hasOwnProperty(this.sanitizeMark)) { return response; } return { data: response, error: null, [this.sanitizeMark]: true, }; } /** * Private Abstract request function * @param method * @param point * @param parameters * @param options * @param args */ request(method, point, parameters, options, body = null, ...args) { if (!method) { console.warn('Something went wrong with API service.'); return; } let apiUrl = this.API; // If is already complete url i should not concat with api url. const fullUrl = new RegExp('^(?:[a-z]+:)?//', 'i'); if (fullUrl.test(point)) { apiUrl = ''; } method = method.toLowerCase(); const url = this.generateUrl((options['apiUrl'] || apiUrl) + point, parameters, ...args); if (method === 'geturl') { return url; } const cacheUrl = `${url}|${method}`; return new Promise(resolve => { const cache = super.get(cacheUrl); const progress = super.getProgress(cacheUrl); const skipCache = options['skipCache'] || false; if (cache && skipCache !== true) { // Extract response from already finished request return resolve(cache); } else if (progress && skipCache !== true) { // Extract response from already existing request in progress progress.subscribe(response => { super.deleteProgress(cacheUrl); const resolvedData = this.resolve(response); return resolve(resolvedData); }); } else { const cachingMethod = method === 'get' || method === 'options'; let callParameters = []; // Add headers const defaultHeaders = { 'Pragma': 'no-cache', 'Cache-control': -1, 'ngsw-bypass': '' }; const headers = Object.assign(defaultHeaders, options['headers'] || {}); this.authenticator(headers, options); options['headers'] = new HttpHeaders(this.cleanHeaders(headers)); if (cachingMethod) { callParameters = [url, options]; // Request not in cache/progress so we set it. super.setProgress(cacheUrl); } else if (method === 'delete') { callParameters = [url, options, body || {}]; } else { callParameters = [url, body || {}, options]; } this.httpClient[method](...callParameters) .toPromise() .then(rawData => { const resolvedData = this.resolve(rawData); if (cachingMethod) { super.set(cacheUrl, resolvedData); } const getProgress = super.getProgress(cacheUrl); if (getProgress) { getProgress.emit(resolvedData); super.deleteProgress(cacheUrl); } return resolve(resolvedData); }) .catch(error => { const res = { data: null, error }; const getProgress = super.getProgress(cacheUrl); if (getProgress) { getProgress.emit(res); super.deleteProgress(cacheUrl); } return resolve(res); }); } }); } authenticator(headers, options) { if (!this.customAuthenticator) { return this.defaultAuthenticator(headers, options); } return this.customAuthenticator(headers, options); } defaultAuthenticator(headers, options) { const auth = JSON.parse(localStorage.getItem('auth')); const externalSessionIndex = JSON.parse(localStorage.getItem(LoginMetadata.externalSessionIndexKey)); if (auth && !headers.hasOwnProperty('Authorization')) { headers['Authorization'] = `${auth.tokenType} ${auth.token}`; } if (externalSessionIndex && !headers.hasOwnProperty(LoginMetadata.externalSessionIndexKey)) { headers[`x-${LoginMetadata.externalSessionIndexKey}`] = `${externalSessionIndex}`; } const contextFromStorage = localStorage.getItem(LoginMetadata.userContext); const userContext = localStorage.getItem(LoginMetadata.activeRole) || (contextFromStorage && contextFromStorage !== 'undefined' && contextFromStorage !== 'null' ? JSON.parse(contextFromStorage) : {}).role; if (!options['skipRole'] && userContext) { headers['x-Current-Role'] = `${userContext}`; } } cleanHeaders(headers) { const cleaned = {}; Object.keys(headers).forEach(key => { const value = headers[key]; if (value !== null && value !== undefined) { cleaned[key] = value; } }); return cleaned; } get languages() { return ['en', 'ro', 'ru']; } } ApiService.decorators = [ { type: Injectable } ]; ApiService.ctorParameters = () => [ { type: HttpClient }, { type: AppConfigService }, { type: undefined, decorators: [{ type: Inject, args: ['authenticator',] }] }, { type: undefined, decorators: [{ type: Inject, args: ['environment',] }] } ]; class FactoryService { constructor(resolver, environment = {}) { this.resolver = resolver; this.environment = environment; this.debug = Boolean(this.environment.debug); } /** * How to use: * // html * <div #container></div> * // class * @ViewChild('container', { read: ViewContainerRef }) container; * // ngAfterViewInit * const factory = this.factoryService.componentByName('ComponentName'); * this.container.createComponent(factory); * this.ref.detectChanges(); * * @param componentName */ componentByName(componentName, target, inputs) { const factories = Array.from(this.resolver['_factories'].keys()); const factoryClass = factories.find((x) => x.name === componentName); if (!factoryClass) { if (this.debug) { console.warn(`Could not load ${componentName}`); } return; } return this.createComponent(factoryClass, inputs, target); } /** * How to use: * // html * <div #container></div> * // class * @ViewChild('container', { read: ViewContainerRef }) container; * // ngAfterViewInit * const factory = this.factoryService.componentbySelector('component-selector'); * this.container.createComponent(factory); * this.ref.detectChanges(); * * @param componentName */ componentbySelector(componentSelector, componentFactories, target, inputs = {}) { if (!componentSelector) { if (this.debug) { console.warn('Started client-control with no target component.'); } return FactoryService.NOT_FOUND; } let res; componentFactories.forEach((value) => { if (value && value.selector === componentSelector) { res = this.createComponent(value.factoryClass, inputs, target); return; } }); if (!res) { if (this.debug) { console.warn(`Could not load ${componentSelector}`); } return FactoryService.NOT_FOUND; } if (!res.create) { return FactoryService.HAS_ROUTE; } return res; } createComponent(factoryClass, inputs, target) { if (!target || !target.insert) { if (this.debug) { console.warn(`Could not get target for `, factoryClass, '|', target); } return FactoryService.NOT_FOUND; } if (!factoryClass) { if (this.debug) { console.warn(`Could not load factory class`); } return FactoryService.NOT_FOUND; } const inputProviders = Object.keys(inputs).map(inputName => { return { provide: inputName, useValue: inputs[inputName] }; }); const resolvedInputs = ReflectiveInjector.resolve(inputProviders); // We create an injector out of the data we want to pass down and this components injector const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, target.parentInjector); // We create a factory out of the component we want to create const factory = this.resolver.resolveComponentFactory(factoryClass); // We create the component using the factory and the injector const component = factory.create(injector); // We insert the component into the dom container target.insert(component.hostView); Object.keys(inputs).forEach(input => { component.instance[input] = inputs[input]; }); return component; } } FactoryService.HAS_ROUTE = null; FactoryService.NOT_FOUND = undefined; FactoryService.decorators = [ { type: Injectable } ]; FactoryService.ctorParameters = () => [ { type: ComponentFactoryResolver }, { type: undefined, decorators: [{ type: Inject, args: ['environment',] }] } ]; class DGSNotificationService { constructor() { this.notifyEvent = new EventEmitter(); } error(message, title) { this.emit({ type: 'error', message, title }); } info(message, title) { this.emit({ type: 'info', message, title }); } success(message, title) { this.emit({ type: 'success', message, title }); } warning(message, title) { this.emit({ type: 'warning', message, title }); } subscription(cb) { return this.notifyEvent.subscribe(cb); } emit(data) { this.notifyEvent.emit(data); } } DGSNotificationService.decorators = [ { type: Injectable } ]; class DGSLowerTranslatePipe { constructor(translate, _ref) { this.translate = translate; this._ref = _ref; this.translatePipe = new TranslatePipe(this.translate, this._ref); } transform(value = '', ...args) { const isString = typeof value === 'string'; let newValue = value; if (isString) { newValue = value.toLowerCase() || ' '; } const translation = this.translatePipe.transform(newValue, ...args); if (translation === newValue && isString) { return value; } return translation; } } DGSLowerTranslatePipe.decorators = [ { type: Pipe, args: [{ name: 'ltranslate', pure: false },] } ]; DGSLowerTranslatePipe.ctorParameters = () => [ { type: TranslateService }, { type: ChangeDetectorRef } ]; function init_app(appConfig) { const config = () => appConfig.load(); return config; } class DGSCoreModule { static forRoot(environment, authenticator) { return { ngModule: DGSCoreModule, providers: [ AppConfigService, { provide: APP_INITIALIZER, useFactory: init_app, deps: [AppConfigService], multi: true }, ApiService, StorageService, FactoryService, DGSNotificationService, { provide: 'environment', useValue: environment }, { provide: 'authenticator', useValue: authenticator }, ], }; } } DGSCoreModule.decorators = [ { type: NgModule, args: [{ declarations: [ DGSLowerTranslatePipe, ], imports: [ CommonModule, HttpClientModule, ], exports: [ DGSLowerTranslatePipe, ], providers: [], schemas: [CUSTOM_ELEMENTS_SCHEMA], },] } ]; class Lang { constructor(Name, Code, Icon = 'fa fa-globe') { this.Name = Name; this.Code = Code; this.Icon = Icon; } } class Auth { constructor(expires, expiresIn, issued, token, tokenType, role, username) { this.expires = expires; this.expiresIn = expiresIn; this.issued = issued; this.token = token; this.tokenType = tokenType; this.role = role; this.username = username; } static fromResponse(response) { return new Auth(response['.expires'], response['expires_in'], response['.issued'], response['access_token'], response['token_type'], response['role'], response['userName']); } } class DGSLoadingComponent { get loading() { return this._loading; } set loading(loading) { this._loading = loading; } } DGSLoadingComponent.decorators = [ { type: Component, args: [{ selector: 'dgs-loading', template: "<div *ngIf=\"loading\" class=\"loading\">\r\n <div class=\"spinner-border text-primary loading__element\" role=\"status\">\r\n <span class=\"sr-only\">Loading...</span>\r\n </div>\r\n</div>\r\n", styles: [".loadingContainer{bottom:0;left:0;position:fixed;right:0;top:0;z-index:99999}.loadingBack{background-color:#fff;bottom:0;left:0;opacity:.5;position:absolute;right:0;top:0;z-index:99}.spinner{left:50%;position:relative;top:50%;z-index:999}"] },] } ]; DGSLoadingComponent.propDecorators = { loading: [{ type: Input }] }; class NumberFiledsValidatorDirective { constructor(elRef) { this.noValidate = false; this.elemenet = elRef.nativeElement; } ngOnInit() { const restricted = [ 69, 187, 188, 189, ]; this.elemenet.addEventListener('keydown', event => { if (this.noValidate) { return; } if (restricted.indexOf(event.keyCode) !== -1) { event.preventDefault(); } }); this.elemenet.addEventListener('paste', event => { setTimeout(() => { if (this.noValidate || !this || !event || !event.target || !event.target['value']) { return; } if (!event.target['value']) { event.target['value'] = ''; } }); }); } } NumberFiledsValidatorDirective.decorators = [ { type: Directive, args: [{ selector: `[type='number']`, },] } ]; NumberFiledsValidatorDirective.ctorParameters = () => [ { type: ElementRef } ]; NumberFiledsValidatorDirective.propDecorators = { noValidate: [{ type: Input }] }; const components = [ DGSLoadingComponent, ]; class DGSUICoreModule { } DGSUICoreModule.decorators = [ { type: NgModule, args: [{ declarations: [ ...components, NumberFiledsValidatorDirective, ], imports: [ CommonModule, ], exports: [ ...components, NumberFiledsValidatorDirective, ], providers: [], },] } ]; // LIB /** * Generated bundle index. Do not edit. */ export { ApiResponse, ApiService, AppConfigService, Auth, DGSCoreModule, DGSLoadingComponent, DGSLowerTranslatePipe, DGSNotificationService, DGSUICoreModule, Debugger, FactoryService, Helper, Lang, LoginMetadata, StorageService, init_app as ɵa, DGSLowerTranslatePipe as ɵb, AppConfigService as ɵc, ApiService as ɵe, StorageService as ɵf, FactoryService as ɵg, DGSNotificationService as ɵh, DGSLoadingComponent as ɵi, NumberFiledsValidatorDirective as ɵj }; //# sourceMappingURL=dotgov-core.js.map