src/lib/service/system/system.service.ts
Collection of System Services
Properties |
|
Methods |
|
constructor(backend: BackendService, logger: Logger, eventService: EventService, appCache: AppCacheService, translate: TranslateService)
|
||||||||||||||||||
Defined in src/lib/service/system/system.service.ts:35
|
||||||||||||||||||
Parameters :
|
fetchSystemDefinition | ||||||||
fetchSystemDefinition(user: EoUser)
|
||||||||
Defined in src/lib/service/system/system.service.ts:296
|
||||||||
Fetches the system definition from the server. Provided params are used for storing the recent version in cache.
Parameters :
Returns :
Observable<boolean>
boolean |
Public getCodesystem | ||||||||
getCodesystem(id: string)
|
||||||||
Defined in src/lib/service/system/system.service.ts:120
|
||||||||
Gets a codesystem
Parameters :
Returns :
ICodeSystem
The codesystem object matching the given id |
Public getDefaultValue | ||||||
getDefaultValue(valueType: string)
|
||||||
Defined in src/lib/service/system/system.service.ts:225
|
||||||
Creates a value depending on a given Type
Parameters :
Returns :
any
any |
getFormElementsFromFormModel | ||||||||||||||||
getFormElementsFromFormModel(objectTypeName: string, situation: string, isContextType?: boolean)
|
||||||||||||||||
Defined in src/lib/service/system/system.service.ts:86
|
||||||||||||||||
Get form elements from form model. This is useful if you have to fetch them for a special situation like SEARCH
Parameters :
Returns :
Observable<any[]>
|
Public getObjectType | ||||||||
getObjectType(objectTypeName: string)
|
||||||||
Defined in src/lib/service/system/system.service.ts:75
|
||||||||
Gets an ObjectType by name.
Parameters :
Returns :
ObjectType
the ObjectType matching the given name |
Public getObjectTypeForm | ||||||||||||||||
getObjectTypeForm(objectTypeName: string, situation: string, mode?: string)
|
||||||||||||||||
Defined in src/lib/service/system/system.service.ts:132
|
||||||||||||||||
Get the form model of an object type.
Parameters :
Returns :
Observable<any>
The object type form model |
Public getObjectTypes |
getObjectTypes()
|
Defined in src/lib/service/system/system.service.ts:65
|
Gets all ObjectTypes
Returns :
ObjectType[]
An array containing all object types |
getOrganizationObject | ||||||||
getOrganizationObject(name: string)
|
||||||||
Defined in src/lib/service/system/system.service.ts:376
|
||||||||
Fetches the organization object for a given name.
Parameters :
Returns :
Observable<any>
|
getOrganizationObjectById | ||||||||
getOrganizationObjectById(id: string)
|
||||||||
Defined in src/lib/service/system/system.service.ts:366
|
||||||||
Retrieve an organization object by its ID
Parameters :
Returns :
Observable<any>
|
getOrganizationObjects | ||||||||
getOrganizationObjects(names: string[])
|
||||||||
Defined in src/lib/service/system/system.service.ts:386
|
||||||||
Fetches a collection of organization objects
Parameters :
Returns :
Observable<IOrganizationObjects[]>
A Array of Organization Objects |
getRoles |
getRoles()
|
Defined in src/lib/service/system/system.service.ts:396
|
Fetches a collection of organization roles
Returns :
Observable<OrgRole[]>
A Array of Organization Roles |
Public getSystemDefinition | ||||||||
getSystemDefinition(user: EoUser)
|
||||||||
Defined in src/lib/service/system/system.service.ts:180
|
||||||||
Fetches the backends system definition and updates system$ Observable. Subscribe to the system$ observable instead of calling this function, otherwise you'll trigger fetching the system definition every time.
Parameters :
Returns :
Observable<boolean>
true when successfull |
Public implementsType | ||||||||||||
implementsType(type: ObjectType, superTypeName: string)
|
||||||||||||
Defined in src/lib/service/system/system.service.ts:110
|
||||||||||||
Checks whether or not the given type implements a given supertype
Parameters :
Returns :
boolean
|
Public system$ |
system$:
|
Type : Observable<any>
|
Default value : this.systemSource.asObservable()
|
Defined in src/lib/service/system/system.service.ts:30
|
system | ||||
getsystem()
|
||||
Defined in src/lib/service/system/system.service.ts:56
|
||||
setsystem(s: )
|
||||
Defined in src/lib/service/system/system.service.ts:52
|
||||
Parameters :
Returns :
void
|
import {forkJoin as observableForkJoin, of, Observable, ReplaySubject} from 'rxjs';
import {catchError, tap, map, switchMap} from 'rxjs/operators';
import {Injectable} from '@angular/core';
import {IOrganizationObjects} from '../../interface/organization-objects.interface';
import {BackendService} from '../backend/backend.service';
import {AppCacheService} from '../cache/app-cache.service';
import {Logger} from '../logger/logger';
import {ObjectType} from '../../model/object-type.model';
import {EoUser} from '../../model/eo-user.model';
import {cloneDeep} from 'lodash-es';
import {OrgRole} from '../../model/org.model';
import {Utils} from '../../util/utils';
import {ICodeSystem} from './systemdefinition.interface';
import {EventService} from '../events/event.service';
import {EnaioEvent} from '../events/events';
import moment from 'moment';
import {TranslateService} from "@ngx-translate/core";
/**
* Collection of System Services
*/
@Injectable({
providedIn: 'root'
})
export class SystemService {
private _system;
private systemSource = new ReplaySubject<any>();
public system$: Observable<any> = this.systemSource.asObservable();
// session cache for object type forms
private objectTypeForms: any[] = [];
private user: EoUser;
private cachedRoles: OrgRole[] = [];
constructor(private backend: BackendService,
private logger: Logger,
private eventService: EventService,
private appCache: AppCacheService,
private translate: TranslateService) {
this.eventService.on(EnaioEvent.SYSTEM_STATUS_SCHEMA_CHANGED).subscribe(() => {
this.fetchSystemDefinition(this.user);
})
// subscribe to language changes to recall the system types
this.translate.onLangChange.subscribe(() => {
this.resendSystemTypes();
});
}
set system(s){
this._system = s;
}
get system(){
return JSON.parse(JSON.stringify(this._system));
}
/**
* Gets all ObjectTypes
*
* @returns An array containing all object types
*/
public getObjectTypes(): ObjectType[] {
return this.system.types;
}
/**
* Gets an ObjectType by name.
*
* @param objectTypeName The name of the object type
* @returns the ObjectType matching the given name
*/
public getObjectType(objectTypeName: string): ObjectType {
return this.system.types.find(t => t.name === objectTypeName);
}
/**
* Get form elements from form model. This is useful if you have to fetch them
* for a special situation like SEARCH
* @param objectTypeName ObjectType to fetch elements for
* @param situation Form model situation to be fetched
* @param isContextType Flag indicating that the form model should be fetched for a context mode
*/
getFormElementsFromFormModel(objectTypeName: string, situation: string, isContextType?: boolean): Observable<any[]> {
return this.getObjectTypeForm(objectTypeName, situation, isContextType ? 'CONTEXT' : null).pipe(
switchMap(model => {
const elements = [];
this.processFormModelElements(model, elements);
return of(elements);
}))
}
private processFormModelElements(model: any, elements: any[]) {
model.elements.forEach(e => {
if(e.type !== "o2mGroup" && e.type !== "o2mGroupStack") {
elements.push(e);
} else if(e.elements && e.elements.length) {
this.processFormModelElements(e, elements);
}
})
}
/**
* Checks whether or not the given type implements a given supertype
* @param type Type to be checked
* @param superTypeName Name of the supertype
*/
public implementsType(type: ObjectType, superTypeName: string): boolean {
return type.name === superTypeName || (type.implements && type.implements.indexOf(superTypeName) !== -1);
}
/**
* Gets a codesystem
*
* @param id The codesystems id
* @returns The codesystem object matching the given id
*/
public getCodesystem(id: string): ICodeSystem {
return this.system.codesystems.find(t => t.id === id || t.name === id);
}
/**
* Get the form model of an object type.
*
* @param objectTypeName The object type name
* @param situation The form situation to be fetched
* @param mode Form mode to fetch (e.g. CONTEXT)
* @returns The object type form model
*/
public getObjectTypeForm(objectTypeName: string, situation: string, mode?: string): Observable<any> {
/** check if we have a cached form first */
let cachedForm;
let i = 0;
while (!cachedForm && i < this.objectTypeForms.length) {
if (this.objectTypeForms[i].name === objectTypeName &&
this.objectTypeForms[i].mode === mode &&
this.objectTypeForms[i].situation === situation) {
cachedForm = this.objectTypeForms[i];
}
i++;
}
if (cachedForm) {
/** return a clone of the cached model as otherwise model changes will be added to the chached model */
return of(cloneDeep(cachedForm));
} else {
let uri = `/ui/form/${objectTypeName}?situation=${situation}`;
uri += !!mode ? `&formmode=${mode}` : '';
/** fetch and cache the requested form, if no cached version was found */
return this.backend.getViaTempCache(uri, () => this.backend
.getJson(uri)
.pipe(
map(res => {
if (objectTypeName === 'sysdmscontenttemplate') {
res.elements[0].elements.forEach(el => {
el.label = this.translate.instant('eo.global.templateParam.' + el.name);
});
}
return res;
}),
tap((model) => this.objectTypeForms.push(cloneDeep(model)))
));
}
}
/**
* Fetches the backends system definition and updates system$ Observable.
* Subscribe to the system$ observable instead of calling this function, otherwise you'll trigger fetching the
* system definition every time.
*
* @param user The user to load the system definition for
* @returns true when successfull
*/
public getSystemDefinition(user: EoUser): Observable<boolean> {
this.user = user;
// todo: temporary: OrgChanges could not be recognized but affect object definition
return this.fetchSystemDefinition(user);
// todo: enable again when OrgChanges are recognizable (DO NOT DELETE!)
// // is there a cached version
// return this.appCache
// .getItem(this.appCache.SYSTEM_DEFINITION)
// .catch((error) => {
// this.logger.error('Error fetching cached version of system definition.', error);
// return this.fetchSystemDefinition(user);
// })
// .flatMap((cachedSystemDefinition: any) => {
//
// // yes? then check if it's up to date
// if (cachedSystemDefinition) {
//
// if (
// user.schema.version !== cachedSystemDefinition.info.version ||
// user.id !== cachedSystemDefinition.info.user ||
// user.getSchemaLocale() !== cachedSystemDefinition.info.locale
// ) {
// return this.fetchSystemDefinition(user);
// } else {
// // cache is up to date. return the cached one
// this.logger.debug('System definition is up to date, using cached version.', cachedSystemDefinition);
// this.system = cachedSystemDefinition;
// this.systemSource.next(this.system);
// return of(true);
// }
// } else {
// // no cached systemDefinition found
// return this.fetchSystemDefinition(user);
// }
// });
}
/**
* Creates a value depending on a given Type
*
* @param string valueType
* @returns any
*/
public getDefaultValue(valueType: string): any {
let defaultValue;
switch (valueType) {
case 'CURRENT_USER': {
defaultValue = this.user.name;
break;
}
case 'CURRENT_USER_NAME': {
defaultValue = this.user.title;
break;
}
case 'CURRENT_DATETIME': {
defaultValue = new Date();
break;
}
case 'CURRENT_DATE': {
defaultValue = moment().startOf('day').format('yyyy-MM-DD');
break;
}
case 'YEAR': {
defaultValue = moment().year();
break;
}
case 'MONTH': {
defaultValue = moment().month() + 1;
break;
}
case 'DAY': {
defaultValue = moment().date();
break;
}
case 'HOUR': {
defaultValue = moment().hour();
break;
}
case 'MINUTE': {
defaultValue = moment().minute();
break;
}
case 'SECOND': {
defaultValue = moment().second();
break;
}
case 'WEEK_OF_YEAR': {
defaultValue = moment().isoWeek();
break;
}
case 'FIRST_DAY_OF_WEEK': {
defaultValue = moment().startOf('isoWeek').toDate();
break;
}
case 'FIRST_DAY_OF_MONTH': {
defaultValue = moment().startOf('month').toDate();
break;
}
case 'FIRST_DAY_OF_YEAR': {
defaultValue = moment().startOf('year').toDate();
break;
}
}
return defaultValue;
}
/**
* Fetches the system definition from the server. Provided params are used for storing the
* recent version in cache.
*
* @param user The user to fetch the system definition for
* @return boolean
*/
fetchSystemDefinition(user: EoUser): Observable<boolean> {
const fetches = [
this.backend.getJson('/system/type/list?elements=true&basetypes=true'),
this.backend.getJson('/system/cs/list?elements=true')
];
return observableForkJoin(fetches)
.pipe(
catchError(Utils.catch((error) => {
this.logger.error('Error fetching recent version of system definition from server.', error);
this.systemSource.error('Error fetching recent version of system definition from server.');
})),
map((data) => {
this.objectTypeForms = [];
const system = {
/**
* info about the current system definition
*/
info: {
user: user.id,
locale: user.getSchemaLocale(),
version: user.schema.version
},
/**
* supported backend locales
*/
locales: user.schema.supportedLocales,
/**
* object type definitions
*/
types: [],
/**
* codesystems cache
*/
codesystems: []
};
const types = data[0];
system.types = types.map(t => new ObjectType(t));
system.codesystems = data[1];
const commonEntries = system.codesystems.find(c => c.id === 'B0E3563DC67140D6984A368095DE0F0B')?.entries?.find(e => e.data === 'group_common');
if (commonEntries) {
const translatedText = this.translate.instant('eo.quicksearch.result.group.global');
commonEntries.defaultrepresentation = translatedText;
commonEntries.label = translatedText;
commonEntries.subentries.forEach(sub => {
sub.defaultrepresentation = translatedText + ' / ' + sub.label;
sub.label = sub.defaultrepresentation;
});
}
this.system = system;
this.systemSource.next(system);
this.logger.debug('Fetched new version of system definition (user: ' + user.id + ', version: ' + user.schema.version + ').');
this.appCache
.setItem(this.appCache.SYSTEM_DEFINITION, system)
.subscribe(() => {
this.logger.debug('Cached recent version');
}, Utils.logError(null, 'Error caching recent version of system definition.'));
return true;
}));
}
/**
* Retrieve an organization object by its ID
* @param id ID of org object
*/
getOrganizationObjectById(id: string): Observable<any> {
return this.backend.getJson(`/organization/id/${id}`)
}
/**
* Fetches the organization object for a given name.
*
* @param name The name to fetch object for
* @returns
*/
getOrganizationObject(name: string): Observable<any> {
return this.getOrganizationObjects([name]).pipe(map(res => res[0]));
}
/**
* Fetches a collection of organization objects
*
* @param names Array of names to fetch objects for
* @returns A Array of Organization Objects
*/
getOrganizationObjects(names: string[]): Observable<IOrganizationObjects[]> {
const toFetch: Observable<IOrganizationObjects>[] = names.map(name => this.backend.getJson(`/organization/name/${name}`).pipe(catchError(error => of({id: name, active: false}))));
return observableForkJoin(toFetch);
}
/**
* Fetches a collection of organization roles
*
* @return A Array of Organization Roles
*/
getRoles(): Observable<OrgRole[]> {
if (this.cachedRoles.length) {
return of(this.cachedRoles);
} else {
return this.backend
.get('/organization/role')
.pipe(
map(o => o as OrgRole[]),
tap(roles => (this.cachedRoles = roles as OrgRole[]))
);
}
}
/**
* Re-emits the current system types to trigger system events.
* Updating the translations of system types for 'sysdmscontenttemplate'.
*
* @remarks
* This method is intended to be used internally within the service to ensure that system type translations are kept up to date.
*
*/
private resendSystemTypes(): void {
if (this._system) {
this.systemSource.next(this._system);
}
}
}