@universis/common
Version:
Universis - common directives and services
1,085 lines (1,072 loc) • 269 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, isDevMode, Injectable, Component, Input, EventEmitter, Output, Pipe, Directive, Inject, ChangeDetectorRef, Optional, NgModule, CUSTOM_ELEMENTS_SCHEMA, ViewEncapsulation, ErrorHandler, SkipSelf } from '@angular/core';
import * as i1 from '@ngx-translate/core';
import { TranslatePipe, TranslateModule } from '@ngx-translate/core';
import * as i2 from '@angular/common/http';
import { HttpErrorResponse, HttpClientModule, HttpClient } from '@angular/common/http';
import * as i1$1 from '@themost/angular';
import { DATA_CONTEXT_CONFIG, AngularDataContext, MostModule } from '@themost/angular';
import { BehaviorSubject, Observable, Subject, lastValueFrom } from 'rxjs';
import 'jquery';
import 'bootstrap/js/dist/modal';
import * as i4 from '@angular/common';
import { DecimalPipe, DatePipe, CommonModule } from '@angular/common';
import * as i2$1 from 'ngx-bootstrap/modal';
import * as _Toast from 'bootstrap/js/dist/toast';
import * as _numeral from 'numeral';
import 'numeral/locales';
import * as _ from 'lodash';
import { template, uniqBy, slice } from 'lodash';
import * as i1$2 from '@angular/router';
import { NavigationEnd, NavigationStart, DefaultUrlSerializer, PRIMARY_OUTLET, RouterModule, ActivatedRoute } from '@angular/router';
import { Args, ResponseError } from '@themost/client';
import { skip, filter, first, map, takeUntil } from 'rxjs/operators';
import { X509 } from 'jsrsasign';
import * as FileSaver from 'file-saver';
import * as XLSX from 'xlsx';
import { EventSourcePolyfill } from 'event-source-polyfill';
import { FormsModule } from '@angular/forms';
import { AES, enc, lib, SHA256, SHA1 } from 'crypto-js';
let APP_CONFIGURATION = new InjectionToken('app.configuration');
/**
*
* This Service is used to get or set global configuration for the project
* @export
* @class ConfigurationService
*/
class ConfigurationService {
constructor(_translateService, _injector, _http) {
this._translateService = _translateService;
this._injector = _injector;
this._http = _http;
this.loaded = new BehaviorSubject(null);
//
}
/**
*
* Load Configs saved in Project
* @returns {Promise<any>}
* @memberof ConfigurationService
*/
async load() {
if (this.config) {
return true;
}
// get environment
const env = isDevMode() ? 'development' : 'production';
// load configuration based on environment
// e.g. assets/config/app.production.json or
// assets/config/app.development.json
try {
return await this.loadFrom(`assets/config/app.${env}.json`);
}
catch (err) {
if (err.status === 404) { // not found
// load default application configuration
return await this.loadFrom(`assets/config/app.json`);
}
throw err;
}
}
async loadFrom(url) {
// get configuration from url
this.config = await new Promise((resolve, reject) => {
this._http.get(url).subscribe(result => {
return resolve(result);
}, err => {
return reject(err);
});
});
// get DATA_CONTEXT_CONFIG
const dataContextConfig = this._injector.get(DATA_CONTEXT_CONFIG);
// IMPORTANT: Set DATA_CONTEXT_CONFIG base URI from configuration
dataContextConfig.base = this.config.settings.remote.server;
// set locale for translate service
this._translateService.use(this.currentLocale);
// emit event for loaded configuration
this.loaded.next(this.config);
// return
return true;
}
/**
* Gets current application settings
*/
get settings() {
return this.config && this.config.settings;
}
/**
* Gets the current user language
*/
get currentLocale() {
const currentLang = localStorage.getItem('currentLang');
if (currentLang) {
return currentLang;
}
if (this.settings &&
this.settings.i18n &&
this.settings.i18n.defaultLocale) {
// return current language
return this.settings.i18n.defaultLocale;
}
// use fallback language
return 'en';
}
set currentLocale(locale) {
// save current locale
localStorage.setItem('currentLang', locale);
// set locale for translate service
this._translateService.use(locale);
}
}
ConfigurationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ConfigurationService, deps: [{ token: i1.TranslateService }, { token: i0.Injector }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
ConfigurationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ConfigurationService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ConfigurationService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.TranslateService }, { type: i0.Injector }, { type: i2.HttpClient }]; } });
var DIALOG_BUTTONS;
(function (DIALOG_BUTTONS) {
DIALOG_BUTTONS[DIALOG_BUTTONS["Ok"] = 1] = "Ok";
DIALOG_BUTTONS[DIALOG_BUTTONS["Yes"] = 2] = "Yes";
DIALOG_BUTTONS[DIALOG_BUTTONS["No"] = 4] = "No";
DIALOG_BUTTONS[DIALOG_BUTTONS["Abort"] = 8] = "Abort";
DIALOG_BUTTONS[DIALOG_BUTTONS["Retry"] = 16] = "Retry";
DIALOG_BUTTONS[DIALOG_BUTTONS["Ignore"] = 32] = "Ignore";
DIALOG_BUTTONS[DIALOG_BUTTONS["Cancel"] = 64] = "Cancel";
DIALOG_BUTTONS[DIALOG_BUTTONS["YesNo"] = 6] = "YesNo";
DIALOG_BUTTONS[DIALOG_BUTTONS["AbortRetryIgnore"] = 54] = "AbortRetryIgnore";
DIALOG_BUTTONS[DIALOG_BUTTONS["OkCancel"] = 65] = "OkCancel";
DIALOG_BUTTONS[DIALOG_BUTTONS["YesNoCancel"] = 70] = "YesNoCancel";
})(DIALOG_BUTTONS || (DIALOG_BUTTONS = {}));
/**
*
* A modal dialog component with ok and cancel buttons
* @export
* @class DialogComponent
*/
class DialogComponent {
constructor(_element, _translateService) {
this._element = _element;
this._translateService = _translateService;
this.title = '';
this.message = '';
this.buttons = DIALOG_BUTTONS.Ok;
this.language = 'en';
this.language = this._translateService.currentLang;
}
bitwiseAnd(a, b) {
return a & b;
}
/**
* Shows modal dialog
* @returns Promise<any>
*/
show() {
return new Promise((resolve, reject) => {
if (this.modalRef) {
this.modalRef.one('hide.bs.modal', () => {
// get related target if any
const result = this.modalRef.data('result');
// return result
return resolve(result);
});
const modalRef = this.modalRef;
modalRef.modal('show');
}
else {
reject('Modal element may not be empty at this context');
}
});
}
/**
* Hides modal dialog
* @param value
*/
hide(value) {
this.modalRef.data('result', value);
const modalRef = this.modalRef;
modalRef.modal('hide');
}
/**
* Converts modal buttons classes modal-ok, modal-yes-no etc to dialog buttons
* @param {Array<string>} classList
*/
classListToButtons(classList) {
return classList.map(classListElement => {
// maps each item to an array of matches (if match)
return /^modal(-ok)?(-yes)?(-no)?(-abort)?(-retry)?(-ignore)?(-cancel)?/ig.exec(classListElement);
}).filter(match => {
// filter not matched elements
return match != null;
}).map((match) => {
// maps each match as an array of 2 ^ k results
// @ts-ignore
return match.map((item, k) => {
if (item && k > 0) {
return Math.pow(2, k - 1);
}
return 0;
}).reduce((a, b) => {
// return a sum of results
return a + b;
});
}).reduce((a, b) => {
// return a final sum of results
return a | b;
});
}
async ngOnInit() {
// get element classes
const classList = Array.from(this._element.nativeElement.classList);
// get buttons from element class list
const classListButtons = this.classListToButtons(classList);
// if element has button classes (modal-ok, modal-yes-no etc)
if (classListButtons) {
// set dialog buttons
this.buttons = classListButtons;
}
this.modalRef = jQuery(this._element.nativeElement);
// initialize modal
const modalRef = this.modalRef;
modalRef.modal({
backdrop: 'static',
focus: true,
keyboard: false,
show: false
});
}
}
DialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DialogComponent, deps: [{ token: i0.ElementRef }, { token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DialogComponent, selector: "universis-dialog.modal", inputs: { title: "title", message: "message", theme: "theme" }, ngImport: i0, template: `
<div class="modal-dialog" [ngClass]="theme" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{title | translate}}</h4>
</div>
<div class="modal-body" [innerHTML]="message"></div>
<div class="modal-footer">
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 1)"
(click)="hide('ok')" class="btn btn-theme btn-ok" [translate]="'OK'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 2)"
(click)="hide('yes')" class="btn btn-theme btn-yes" [translate]="'Yes'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 4)"
(click)="hide('no')" class="btn btn-gray-100 btn-no" [translate]="'No'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 8)"
(click)="hide('abort')" class="btn btn-danger btn-abort" [translate]="'Abort'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 16)"
(click)="hide('retry')" class="btn btn-gray-100 btn-retry" [translate]="'Retry'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 32)"
(click)="hide('ignore')" class="btn btn-gray-100 btn-ignore" [translate]="'Ignore'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 64)"
(click)="hide('cancel')" class="btn btn-gray-100 btn-cancel" [translate]="'Cancel'"></button>
</div>
</div>
</div>
`, isInline: true, styles: [".modal-dialog .modal-body{margin-top:0;margin-bottom:0}.modal-footer{border-top:0}.btn{text-transform:uppercase;font-size:16px}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DialogComponent, decorators: [{
type: Component,
args: [{ selector: 'universis-dialog.modal', template: `
<div class="modal-dialog" [ngClass]="theme" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">{{title | translate}}</h4>
</div>
<div class="modal-body" [innerHTML]="message"></div>
<div class="modal-footer">
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 1)"
(click)="hide('ok')" class="btn btn-theme btn-ok" [translate]="'OK'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 2)"
(click)="hide('yes')" class="btn btn-theme btn-yes" [translate]="'Yes'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 4)"
(click)="hide('no')" class="btn btn-gray-100 btn-no" [translate]="'No'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 8)"
(click)="hide('abort')" class="btn btn-danger btn-abort" [translate]="'Abort'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 16)"
(click)="hide('retry')" class="btn btn-gray-100 btn-retry" [translate]="'Retry'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 32)"
(click)="hide('ignore')" class="btn btn-gray-100 btn-ignore" [translate]="'Ignore'"></button>
<button [lang]="language" type="button" *ngIf="bitwiseAnd(buttons, 64)"
(click)="hide('cancel')" class="btn btn-gray-100 btn-cancel" [translate]="'Cancel'"></button>
</div>
</div>
</div>
`, styles: [".modal-dialog .modal-body{margin-top:0;margin-bottom:0}.modal-footer{border-top:0}.btn{text-transform:uppercase;font-size:16px}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.TranslateService }]; }, propDecorators: { title: [{
type: Input
}], message: [{
type: Input
}], theme: [{
type: Input
}] } });
/**
*
* Displays a Modal window or a type of Notification (based on choice the color changes)
* @export
* @class ModalService
*/
class ModalService {
constructor(componentFactoryResolver, appRef, injector, modalService) {
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.injector = injector;
this.modalService = modalService;
this.config = {
ignoreBackdropClick: true,
keyboard: false,
initialState: null,
class: 'modal-content-base'
};
}
showDialog(title, message, buttons = DIALOG_BUTTONS.Ok, extras) {
const componentRef = this.componentFactoryResolver
.resolveComponentFactory(DialogComponent)
.create(this.injector);
componentRef.instance.title = title;
componentRef.instance.message = message;
componentRef.instance.buttons = buttons;
if (extras) {
componentRef.instance.theme = extras.theme;
}
// attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(componentRef.hostView);
// get DOM element from component
const modalElement = componentRef.hostView
.rootNodes[0];
// append DOM element to the body
document.body.appendChild(modalElement);
return componentRef.instance.ngOnInit().then(() => {
// show dialog
return componentRef.instance.show().then(result => {
// detach view
this.appRef.detachView(componentRef.hostView);
// destroy component ref
componentRef.destroy();
//
return Promise.resolve(result);
});
});
}
showWarningDialog(title, message, buttons = DIALOG_BUTTONS.OkCancel) {
return this.showDialog('', `<div class="text-center">
<div class="icon-circle icon-circle-warning">
<i class="fa fa-exclamation"></i>
</div>
<div class="font-2xl font-weight-bold mt-2">
${title}
</div>
<p class="mt-2">
${message}
</p>
</div>
`, buttons, {
theme: 'modal-dialog-warning'
});
}
showSuccessDialog(title, message, buttons = DIALOG_BUTTONS.Ok) {
return this.showDialog('', `<div class="text-center">
<div class="icon-circle icon-circle-success">
<i class="fa fa-check"></i>
</div>
<div class="font-2xl font-weight-bold mt-2">
${title}
</div>
<p class="mt-2">
${message}
</p>
</div>
`, buttons, {
theme: 'modal-dialog-success'
});
}
showErrorDialog(title, message, buttons = DIALOG_BUTTONS.Ok) {
return this.showDialog('', `<div class="text-center">
<div class="icon-circle icon-circle-danger">
<i class="fa fa-times"></i>
</div>
<div class="font-2xl font-weight-bold mt-2">
${title}
</div>
<p class="mt-2">
${message}
</p>
</div>
`, buttons, {
theme: 'modal-dialog-danger'
});
}
showInfoDialog(title, message, buttons = DIALOG_BUTTONS.Ok) {
return this.showDialog('', `<div class="text-center">
<div class="icon-circle icon-circle-info">
<i class="fa fa-info"></i>
</div>
<div class="font-2xl font-weight-bold mt-2">
${title}
</div>
<p class="mt-2">
${message}
</p>
</div>
`, buttons, {
theme: 'modal-dialog-info'
});
}
openModal(template, customClass) {
let config;
if (customClass) {
config = JSON.parse(JSON.stringify(this.config));
config.class = customClass;
}
else {
config = this.config;
}
return this.modalRef = this.modalService.show(template, config);
}
openModalComponent(template, options) {
return this.modalRef = this.modalService.show(template, options);
}
}
ModalService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ModalService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }, { token: i2$1.BsModalService }], target: i0.ɵɵFactoryTarget.Injectable });
ModalService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ModalService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ModalService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }, { type: i2$1.BsModalService }]; } });
/**
*
* Component for Card-Box element with Inputs:
* Usage <universis-msgbox [title]="HelloWorld" ...></universis-msgbox>
* @Input() title: Title of Box
* @Input() icon: Icon displayed on the left of the element
* @Input() info: The Status displayed on user
* @Input() message: Explanation of the status
* @Input() extraMessage: Some extra guidance
* @Input() actionButton: Text displayed as Text in button
* @Input() actionText: Text displayed as an action
* @Input() disableBut: Disable button
* @export
*/
class MsgboxComponent {
constructor() {
// Default class sets the color to green, otherwise pass it the correct bootstrap class
this.buttonClass = 'btn-success';
// Usage (action)="someFunction()"
this.action = new EventEmitter();
}
clicked() {
this.action.emit();
}
}
MsgboxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MsgboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
MsgboxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: MsgboxComponent, selector: "universis-msgbox", inputs: { title: "title", icon: "icon", info: "info", message: "message", extraMessage: "extraMessage", actionButton: "actionButton", actionText: "actionText", disableBut: "disableBut", buttonClass: "buttonClass" }, outputs: { action: "action" }, ngImport: i0, template: "<div class=\"card\">\n <div class=\"msgbox_main-container\">\n <div class=\"msgbox_icon\">\n <span class=\"fa-4x far {{icon}}\" style=\"color:#678898;\"></span>\n </div>\n <div class=\"msgbox_details\">\n <div *ngIf=\"title && !title.includes('title')\" class=\"msgbox_title\" id=\"title\">{{title}}</div>\n <div class=\"font pt-3 msgbox_item\" id=\"message\">{{message}}</div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"extraMessage && !extraMessage.includes('extraMessage')\">{{extraMessage}}</div>\n <div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"actionButton && !actionButton.includes('actionButton')\">\n <button type=\"button\" class=\"btn s--btn\" [ngClass]=\"buttonClass\" [disabled]=\"disableBut\" (click)=\"clicked()\">{{actionButton}}</button>\n </div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"actionText && !actionText.includes('actionText')\" id=\"text\">\n <span><span class=\"fa-1x icon-arrow-right\"></span>{{actionText}}</span>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".msgbox_main-container{display:flex;margin:30px 40px}.msgbox_title{text-transform:uppercase;color:#536c79}.msgbox_details{display:flex;flex-direction:column;justify-content:center}.msgbox_icon{padding-right:60px;padding-left:20px;display:flex;align-items:center}.msgbox_item{display:flex}@media screen and (max-width: 600px){.msgbox_main-container{flex-direction:column;align-items:center}.msgbox_title{text-align:center;justify-content:center;padding:1rem 5px 0}.msgbox_item{justify-content:center;text-align:center}.msgbox_icon{padding-right:0;padding-left:0;justify-content:center}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MsgboxComponent, decorators: [{
type: Component,
args: [{ selector: 'universis-msgbox', template: "<div class=\"card\">\n <div class=\"msgbox_main-container\">\n <div class=\"msgbox_icon\">\n <span class=\"fa-4x far {{icon}}\" style=\"color:#678898;\"></span>\n </div>\n <div class=\"msgbox_details\">\n <div *ngIf=\"title && !title.includes('title')\" class=\"msgbox_title\" id=\"title\">{{title}}</div>\n <div class=\"font pt-3 msgbox_item\" id=\"message\">{{message}}</div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"extraMessage && !extraMessage.includes('extraMessage')\">{{extraMessage}}</div>\n <div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"actionButton && !actionButton.includes('actionButton')\">\n <button type=\"button\" class=\"btn s--btn\" [ngClass]=\"buttonClass\" [disabled]=\"disableBut\" (click)=\"clicked()\">{{actionButton}}</button>\n </div>\n <div class=\"pt-3 msgbox_item\" *ngIf=\"actionText && !actionText.includes('actionText')\" id=\"text\">\n <span><span class=\"fa-1x icon-arrow-right\"></span>{{actionText}}</span>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".msgbox_main-container{display:flex;margin:30px 40px}.msgbox_title{text-transform:uppercase;color:#536c79}.msgbox_details{display:flex;flex-direction:column;justify-content:center}.msgbox_icon{padding-right:60px;padding-left:20px;display:flex;align-items:center}.msgbox_item{display:flex}@media screen and (max-width: 600px){.msgbox_main-container{flex-direction:column;align-items:center}.msgbox_title{text-align:center;justify-content:center;padding:1rem 5px 0}.msgbox_item{justify-content:center;text-align:center}.msgbox_icon{padding-right:0;padding-left:0;justify-content:center}}\n"] }]
}], propDecorators: { title: [{
type: Input
}], icon: [{
type: Input
}], info: [{
type: Input
}], message: [{
type: Input
}], extraMessage: [{
type: Input
}], actionButton: [{
type: Input
}], actionText: [{
type: Input
}], disableBut: [{
type: Input
}], buttonClass: [{
type: Input
}], action: [{
type: Output
}] } });
/**
*
* A native spinner component
* @export
* @class SpinnerComponent
* @implements {OnInit}
*/
class SpinnerComponent {
constructor() { }
ngOnInit() {
//
}
}
SpinnerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
SpinnerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: SpinnerComponent, selector: "universis-spinner", ngImport: i0, template: `
<div class="s--spinner">
<div class="sk-three-bounce">
<div class="sk-child sk-bounce1"></div>
<div class="sk-child sk-bounce2"></div>
<div class="sk-child sk-bounce3"></div>
</div>
</div>
`, isInline: true, styles: ["@import\"spinkit/css/spinners/7-three-bounce.css\";.s--spinner{position:fixed;width:100%;height:100%;top:0;background-color:#7f7f7f80;z-index:10000;display:flex!important;justify-content:center!important;align-items:center!important}@media screen and (-ms-high-contrast: active),(-ms-high-contrast: none){.s--spinner .sk-three-bounce{display:table-cell}}.sk-three-bounce{margin:40px auto;width:80px;text-align:center}.sk-three-bounce .sk-child{width:20px;height:20px;background-color:#333;border-radius:100%;display:inline-block;animation:sk-three-bounce 1.4s ease-in-out 0s infinite both}.sk-three-bounce .sk-bounce1{animation-delay:-.32s}.sk-three-bounce .sk-bounce2{animation-delay:-.16s}@keyframes sk-three-bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}\n"] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SpinnerComponent, decorators: [{
type: Component,
args: [{ selector: 'universis-spinner', template: `
<div class="s--spinner">
<div class="sk-three-bounce">
<div class="sk-child sk-bounce1"></div>
<div class="sk-child sk-bounce2"></div>
<div class="sk-child sk-bounce3"></div>
</div>
</div>
`, styles: ["@import\"spinkit/css/spinners/7-three-bounce.css\";.s--spinner{position:fixed;width:100%;height:100%;top:0;background-color:#7f7f7f80;z-index:10000;display:flex!important;justify-content:center!important;align-items:center!important}@media screen and (-ms-high-contrast: active),(-ms-high-contrast: none){.s--spinner .sk-three-bounce{display:table-cell}}.sk-three-bounce{margin:40px auto;width:80px;text-align:center}.sk-three-bounce .sk-child{width:20px;height:20px;background-color:#333;border-radius:100%;display:inline-block;animation:sk-three-bounce 1.4s ease-in-out 0s infinite both}.sk-three-bounce .sk-bounce1{animation-delay:-.32s}.sk-three-bounce .sk-bounce2{animation-delay:-.16s}@keyframes sk-three-bounce{0%,80%,to{transform:scale(0)}40%{transform:scale(1)}}\n"] }]
}], ctorParameters: function () { return []; } });
const Toast = _Toast.default || _Toast;
/**
*
* A native spinner component
* @export
* @class SpinnerComponent
* @implements {OnInit}
*/
class ToastComponent {
constructor(_element) {
this._element = _element;
this.autoHide = true;
this.delay = 5000;
this.dateCreated = new Date();
}
ngOnInit() {
}
ngAfterViewInit() {
this.toast = new Toast(this._element.nativeElement, {
animation: false,
autohide: this.autoHide,
delay: this.delay
});
return this.toast.show();
}
show() {
if (this.toast) {
this.toast.show();
}
}
hide() {
const container = document.body.getElementsByClassName('universis-toast-container')[0];
if (container.getElementsByClassName('show').length === 1) {
container.classList.add('hidden');
}
if (this.toast) {
this.toast.hide();
}
}
}
ToastComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ToastComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
ToastComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: ToastComponent, selector: "universis-toast.toast", inputs: { title: "title", message: "message", autoHide: "autoHide", delay: "delay" }, ngImport: i0, template: `
<div class="toast-header d-flex p-0">
<strong class="mr-auto">{{ title }}</strong>
<button type="button" class="ml-2 mb-1 align-self-start close" data-dismiss="toast" (click)="hide();" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="toast-body p-0">
<div class="toast-body-content" [innerHTML]="message"></div>
</div>
<div class="toast-header p-0">
<small class="toast-date">{{ dateCreated | date: 'shortTime'}}</small>
</div>
`, isInline: true, styles: [":host{z-index:auto}\n"], dependencies: [{ kind: "pipe", type: i4.DatePipe, name: "date" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ToastComponent, decorators: [{
type: Component,
args: [{ selector: 'universis-toast.toast', template: `
<div class="toast-header d-flex p-0">
<strong class="mr-auto">{{ title }}</strong>
<button type="button" class="ml-2 mb-1 align-self-start close" data-dismiss="toast" (click)="hide();" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="toast-body p-0">
<div class="toast-body-content" [innerHTML]="message"></div>
</div>
<div class="toast-header p-0">
<small class="toast-date">{{ dateCreated | date: 'shortTime'}}</small>
</div>
`, styles: [":host{z-index:auto}\n"] }]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { title: [{
type: Input
}], message: [{
type: Input
}], autoHide: [{
type: Input
}], delay: [{
type: Input
}] } });
/**
* @export
* @class ToastService
*/
class ToastService {
constructor(componentFactoryResolver, appRef, injector) {
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.injector = injector;
}
/**
* Shows a toast message
* @param {string} title A string which represents message title
* @param {string} message A string which represents message body
* @param {boolean=} autoHide A boolean which indicates whether a message will auto hide or not
* @param {number=} delay A number which indicates the number of milliseconds before auto hide message
*/
show(title, message, autoHide = true, delay = 5000) {
// search for toast container
let container = document.body.getElementsByClassName('universis-toast-container')[0];
if (container == null) {
// create toast container
container = document.createElement('div');
container.classList.add('universis-toast-container', 'p-3');
// append to boyd
document.body.appendChild(container);
}
// create a component reference for toast component
const componentRef = this.componentFactoryResolver
.resolveComponentFactory(ToastComponent)
.create(this.injector);
componentRef.instance.title = title;
componentRef.instance.message = message;
componentRef.instance.autoHide = autoHide;
componentRef.instance.delay = delay;
componentRef.location.nativeElement.classList.add('show');
// attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(componentRef.hostView);
// get DOM element from component
const domElem = componentRef.hostView.rootNodes[0];
// append DOM element to the body
container.appendChild(domElem);
container.classList.remove('hidden');
setTimeout(() => {
componentRef.instance.hide();
}, delay);
}
// noinspection JSMethodCanBeStatic
/**
* Clears toast messages
*/
clear() {
// search for toast container
const container = document.body.getElementsByClassName('universis-toast-container')[0];
if (container) {
// remove children
while (container.firstChild) {
container.removeChild(container.firstChild);
}
}
}
}
ToastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ToastService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
ToastService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ToastService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ToastService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }]; } });
function round(x, n) {
if (typeof x !== 'number') {
return 0;
}
if (n) {
return parseFloat(x.toFixed(n));
}
return Math.round(x);
}
class GradeScale {
constructor(_locale, scale = null) {
this._locale = _locale;
this.scale = scale;
this.formatPrecision = 2;
this.scalePrecision = 2;
// init decimal pipe
this._formatter = new DecimalPipe(this._locale);
// get decimal separator regular expression
// @ts-ignore
this._decimalCharRegExp = new RegExp('\\' + this._formatter.transform(0.1, '1.1-1').substr(1, 1), 'ig');
if (scale) {
this.id = scale['id'];
this.name = scale['name'];
this.scaleType = scale['scaleType'];
this.scaleFactor = scale['scaleFactor'];
this.scaleBase = scale['scaleBase'];
this.formatPrecision = scale['formatPrecision'];
this.scalePrecision = scale['scalePrecision'];
this.values = scale['values'];
}
}
/**
* Formats the specified based on this grade scale and returns the formatted value
* @param {number} grade
* @returns string
*/
format(grade) {
if (this.scaleType === 0) {
if (typeof this.scaleFactor !== 'number') {
throw new TypeError('Grade scale factor must be a number.');
}
if (this.scaleFactor <= 0) {
throw new TypeError('Grade scale factor must greater than zero.');
}
// arithmetic grade scale
if (typeof grade === 'number') {
// get final grade by applying rounding
const finalGrade = round((grade / this.scaleFactor), this.formatPrecision);
// return formatted value based on the current locale
const result = this._formatter.transform(finalGrade, `1.${this.formatPrecision}-${this.formatPrecision}`);
if (result != null) {
return result;
}
}
return '';
}
else if (this.scaleType === 1 || this.scaleType === 3) {
let finalValue = round(grade, this.scalePrecision);
if (this.values != null) {
let findValue = this.values.find(x => {
return finalValue >= x.valueFrom && finalValue <= x.valueTo;
});
if (findValue) {
return findValue.name;
}
}
throw new RangeError('Out of range value for grade');
}
throw new Error('Not yet implemented');
}
/**
* Converts the given grade to the equivalent grade value base on this grade scale
* @param grade
*/
convert(grade) {
if (this.scaleType === 0) {
let finalGrade;
// if grade is a number
if (typeof grade === 'undefined' || grade === null) {
return;
}
else if (typeof grade === 'number') {
finalGrade = grade;
}
else if (typeof grade === 'string') {
// try to convert the given grade
finalGrade = parseFloat(grade.replace(this._decimalCharRegExp, '.'));
if (isNaN(finalGrade)) {
return;
}
}
if (typeof this.scaleFactor !== 'number') {
throw new TypeError('Grade scale factor must be a number.');
}
if (this.scaleFactor <= 0) {
throw new TypeError('Grade scale factor must greater than zero.');
}
// validate grade
const res = round((finalGrade * this.scaleFactor), this.formatPrecision + 1);
// throw error if result is greater than 1
if (res < 0 || res > 1) {
throw new Error('Grade is out of range. It must be between 0 to 1.');
}
return res;
}
else if (this.scaleType === 1 || this.scaleType === 3) {
if (this.values) {
let findValue = this.values.find(x => {
return x.name === grade || x.alternateName === grade;
});
if (findValue) {
return findValue.exactValue;
}
}
throw new RangeError('Out of range value for grade');
}
throw new Error('Not yet implemented');
}
}
class GradeScaleService {
constructor(_context, _configurationService) {
this._context = _context;
this._configurationService = _configurationService;
//
}
/**
* Gets all the available grade scales
*/
getGradeScales() {
if (this._gradeScales) {
return Promise.resolve(this._gradeScales);
}
return this._context.model('GradeScales').getItems().then(result => {
const locale = this._configurationService.currentLocale;
this._gradeScales = result.map(x => {
return Object.assign(new GradeScale(locale), x);
});
return Promise.resolve(this._gradeScales);
}, (err) => {
console.log(err);
return null;
});
}
/**
* Gets a grade scale based on the given identifier
* @param {*} id
*/
getGradeScale(id) {
if (this._gradeScales) {
return Promise.resolve(this._gradeScales.find(value => {
return value.id === id;
}));
}
return this.getGradeScales().then(res => {
if (res == null) {
return;
}
return Promise.resolve(res.find(value => {
return value.id === id;
}));
});
}
}
GradeScaleService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GradeScaleService, deps: [{ token: i1$1.AngularDataContext }, { token: ConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable });
GradeScaleService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GradeScaleService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GradeScaleService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1$1.AngularDataContext }, { type: ConfigurationService }]; } });
class GradePipe {
constructor(_gradeScaleService) {
this._gradeScaleService = _gradeScaleService;
//
}
transform(value, gradeScale) {
if (gradeScale instanceof GradeScale) {
return Promise.resolve(gradeScale.format(value));
}
return this._gradeScaleService.getGradeScale(gradeScale).then(result => {
if (typeof result === 'undefined') {
return Promise.reject(new Error('The specified grade scale cannot be found or is inaccessible'));
}
return Promise.resolve(result.format(value));
});
}
}
GradePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GradePipe, deps: [{ token: GradeScaleService }], target: i0.ɵɵFactoryTarget.Pipe });
GradePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: GradePipe, name: "grade" });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GradePipe, decorators: [{
type: Pipe,
args: [{
name: 'grade'
}]
}], ctorParameters: function () { return [{ type: GradeScaleService }]; } });
/**
*
* Displays Loading Spinner
* @export
* @class LoadingService
*/
class LoadingService {
constructor(componentFactoryResolver, appRef, injector) {
this.componentFactoryResolver = componentFactoryResolver;
this.appRef = appRef;
this.injector = injector;
this.componentRef = null;
}
appendComponentToBody(component) {
// do nothing if component ref already exists
if (this.componentRef) {
return;
}
// create a component reference from the component
this.componentRef = this.componentFactoryResolver
.resolveComponentFactory(component)
.create(this.injector);
// attach component to the appRef so that it's inside the ng component tree
this.appRef.attachView(this.componentRef.hostView);
// get DOM element from component
const domElem = this.componentRef.hostView
.rootNodes[0];
// append DOM element to the body
document.body.appendChild(domElem);
}
/**
*
* Toggles show/hide state of spinner
*/
toggle() {
if (this.componentRef) {
this.hideLoading();
}
else {
this.showLoading();
}
}
/**
*
* Shows spinner
*/
showLoading() {
if (this.componentRef == null) {
this.appendComponentToBody(SpinnerComponent);
}
}
/**
*
* Hides spinner
*/
hideLoading() {
if (this.componentRef) {
this.appRef.detachView(this.componentRef.hostView);
this.componentRef.destroy();
this.componentRef = null;
}
}
}
LoadingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LoadingService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
LoadingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LoadingService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LoadingService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }]; } });
/**
*
* Custom DatePipe representation
* @export
* @class LocalizedDatePipe
* @implements {PipeTransform}
*/
class LocalizedDatePipe {
constructor(translateService) {
this.translateService = translateService;
}
/**
*
* Converts Date value that been passed
* @param {*} value The Date that needs to be converted
* @param {string} [pattern='mediumDate'] Pattern of Date
* @returns {*} Converted Date
* @memberof LocalizedDatePipe
*/
transform(value, pattern = 'mediumDate') {
const datePipe = new DatePipe(this.translateService.currentLang);
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}$/.test(value)) {
return datePipe.transform(new Date(value + ':00'), pattern);
}
return datePipe.transform(value, pattern);
}
}
LocalizedDatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedDatePipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe });
LocalizedDatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: LocalizedDatePipe, name: "localizedDate", pure: false });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: LocalizedDatePipe, decorators: [{
type: Pipe,
args: [{
name: 'localizedDate',
pure: false
}]
}], ctorParameters: function () { return [{ type: i1.TranslateService }]; } });
async function registration(_numeral) {
await _numeral.register('locale', 'el', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'χιλ',
million: 'εκ',
billion: 'δισ',
trillion: 'τρισ'
},
ordinal: function (number) {
return 'ο';
},
currency: {
symbol: '€'
}
});
await _numeral.register('locale', 'el-gr', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'χιλ',
million: 'εκ',
billion: 'δισ',
trillion: 'τρισ'
},
ordinal: function (number) {
return 'ο';
},
currency: {
symbol: '€'
}
});
await _numeral.register('locale', 'cy', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'χιλ',
million: 'εκ',
billion: 'δισ',
trillion: 'τρισ'
},
ordinal: function (number) {
return 'ο';
},
currency: {
symbol: '€'
}
});
await _numeral.register('locale', 'cy-cy', {
delimiters: {
thousands: '.',
decimal: ','
},
abbreviations: {
thousand: 'χιλ',
million: 'εκ',
billion: 'δισ',
trillion: 'τρισ'
},
ordinal: function (number) {
return 'ο';
},
currency: {
symbol: '€'
}
});
}
const numeral = _numeral.default || _numeral;
class SemesterPipe {
constructor(_translateService) {
this._translateService = _translateService;
const numeralWithLocales = numeral;
if (numeralWithLocales.locales['el'] == null) {
registration(numeral).then(async () => {
await Promise.resolve();
});
}
}
transform(value, pattern = 'long') {
if (typeof value === 'object') {
value = value.id;
}
if (value >= 250) {
return this._translateService.instant(`Semester.full.${value}`);
}
numeral.locale(this._translateService.currentLang);
return this._translateService.instant(`Semester.${pattern}`, {
value: value,
ordinal: numeral(value).format('o')
});
}
}
SemesterPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SemesterPipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe });
SemesterPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: SemesterPipe, name: "semester", pure: false });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: SemesterPipe, decorators: [{
type: Pipe,
args: [{
name: 'semester',
pure: false
}]
}], ctorParameters: function () { return [{ type: i1.TranslateService }]; } });
/**
* Template Pipe is an impure pipe that can escape
* HTML and inter