@dotgov/core
Version:
DGS core.
854 lines (835 loc) • 30 kB
JavaScript
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