[ACS-3576] Map aspect actions with the aspect picker dropdown (#2713)

* rebased

* rebased

* unit tests

* linting

* publicApiCall

* renamed method formatAspects to parseAspectsToSelectOptions

* added getter cardViewStyle

* removing business logic from the ui component

* moved 'loadAspects()' to actions.service.ts

* preview fix

* removed duplicate
This commit is contained in:
Nikita Maliarchuk 2022-10-18 16:49:20 +02:00 committed by GitHub
parent 2d6375aad1
commit 77c5ac0c96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 162 additions and 63 deletions

View File

@ -35,6 +35,7 @@ import { By } from '@angular/platform-browser';
import { dummyNodeInfo } from '../mock/node.mock'; import { dummyNodeInfo } from '../mock/node.mock';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { ActionsService } from '../services/actions.service'; import { ActionsService } from '../services/actions.service';
import { dummyAspects } from '../mock/aspects.mock';
describe('ManageRulesSmartComponent', () => { describe('ManageRulesSmartComponent', () => {
let fixture: ComponentFixture<ManageRulesSmartComponent>; let fixture: ComponentFixture<ManageRulesSmartComponent>;
@ -60,6 +61,7 @@ describe('ManageRulesSmartComponent', () => {
debugElement = fixture.debugElement; debugElement = fixture.debugElement;
folderRulesService = TestBed.inject<FolderRulesService>(FolderRulesService); folderRulesService = TestBed.inject<FolderRulesService>(FolderRulesService);
actionsService = TestBed.inject<ActionsService>(ActionsService); actionsService = TestBed.inject<ActionsService>(ActionsService);
actionsService.aspects$ = of(dummyAspects);
}); });
}) })
); );

View File

@ -51,6 +51,12 @@ export const actionDefListMock: ActionDefinitionList = {
type: 'd:boolean', type: 'd:boolean',
multiValued: false, multiValued: false,
mandatory: false mandatory: false
},
{
name: 'aspect-name',
type: 'd:qname',
multiValued: false,
mandatory: false
} }
], ],
name: 'mock-action-1-definition', name: 'mock-action-1-definition',
@ -85,6 +91,14 @@ const actionParam2TransformedMock: ActionParameterDefinitionTransformed = {
displayLabel: 'mock-action-parameter-boolean' displayLabel: 'mock-action-parameter-boolean'
}; };
const actionParam3TransformedMock: ActionParameterDefinitionTransformed = {
name: 'aspect-name',
type: 'd:qname',
multiValued: false,
mandatory: false,
displayLabel: 'aspect-name'
};
const action1TransformedMock: ActionDefinitionTransformed = { const action1TransformedMock: ActionDefinitionTransformed = {
id: 'mock-action-1-definition', id: 'mock-action-1-definition',
name: 'mock-action-1-definition', name: 'mock-action-1-definition',
@ -92,7 +106,7 @@ const action1TransformedMock: ActionDefinitionTransformed = {
title: 'Action 1 title', title: 'Action 1 title',
applicableTypes: [], applicableTypes: [],
trackStatus: false, trackStatus: false,
parameterDefinitions: [actionParam1TransformedMock, actionParam2TransformedMock] parameterDefinitions: [actionParam1TransformedMock, actionParam2TransformedMock, actionParam3TransformedMock]
}; };
const action2TransformedMock: ActionDefinitionTransformed = { const action2TransformedMock: ActionDefinitionTransformed = {

View File

@ -0,0 +1,41 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Aspect } from '../model/aspect.model';
export const dummyAspects: Aspect[] = [
{
value: 'cm:aspect1',
label: 'Label 1'
},
{
value: 'cm:aspect2',
label: 'Label 2'
},
{
value: 'cm:aspect3',
label: 'Label 3'
}
];

View File

@ -23,18 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>. * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/ */
export interface AspectModel {
id: string;
description: string;
namespaceUri: string;
namespacePrefix: string;
}
export interface Aspect { export interface Aspect {
includedInSupertypeQuery: boolean; value: string;
isContainer: boolean; label: string;
model: AspectModel;
id: string;
title: string;
parentId: string;
} }

View File

@ -1,6 +1,7 @@
<div class="aca-rule-action-list__item " *ngFor="let control of formControls"> <div class="aca-rule-action-list__item " *ngFor="let control of formControls">
<aca-rule-action <aca-rule-action
[actionDefinitions]="actionDefinitions" [actionDefinitions]="actionDefinitions"
[aspects]="aspects"
[readOnly]="readOnly" [readOnly]="readOnly"
[formControl]="control"> [formControl]="control">
</aca-rule-action> </aca-rule-action>

View File

@ -28,6 +28,7 @@ import { ControlValueAccessor, FormArray, FormControl, NG_VALUE_ACCESSOR, Valida
import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model'; import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { ruleActionValidator } from '../validators/rule-actions.validator'; import { ruleActionValidator } from '../validators/rule-actions.validator';
import { Aspect } from '../../model/aspect.model';
@Component({ @Component({
selector: 'aca-rule-action-list', selector: 'aca-rule-action-list',
@ -48,6 +49,8 @@ export class RuleActionListUiComponent implements ControlValueAccessor, OnDestro
actionDefinitions: ActionDefinitionTransformed[] = []; actionDefinitions: ActionDefinitionTransformed[] = [];
@Input() @Input()
readOnly = false; readOnly = false;
@Input()
aspects: Aspect[] = [];
formArray = new FormArray([]); formArray = new FormArray([]);
private formArraySubscription: Subscription; private formArraySubscription: Subscription;

View File

@ -16,6 +16,7 @@
<adf-card-view <adf-card-view
data-automation-id="rule-action-card-view" data-automation-id="rule-action-card-view"
[properties]="cardViewItems" [properties]="cardViewItems"
[ngStyle]="cardViewStyle"
[editable]="!readOnly"> [editable]="!readOnly">
</adf-card-view> </adf-card-view>

View File

@ -24,7 +24,7 @@
*/ */
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CardViewBoolItemModel, CardViewComponent, CardViewTextItemModel, CoreTestingModule } from '@alfresco/adf-core'; import { CardViewBoolItemModel, CardViewComponent, CardViewSelectItemModel, CardViewTextItemModel, CoreTestingModule } from '@alfresco/adf-core';
import { RuleActionUiComponent } from './rule-action.ui-component'; import { RuleActionUiComponent } from './rule-action.ui-component';
import { actionsTransformedListMock } from '../../mock/actions.mock'; import { actionsTransformedListMock } from '../../mock/actions.mock';
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
@ -77,9 +77,10 @@ describe('RuleActionUiComponent', () => {
expect(cardView.properties.length).toBe(0); expect(cardView.properties.length).toBe(0);
changeMatSelectValue('rule-action-select', 'mock-action-1-definition'); changeMatSelectValue('rule-action-select', 'mock-action-1-definition');
expect(cardView.properties.length).toBe(2); expect(cardView.properties.length).toBe(3);
expect(cardView.properties[0]).toBeInstanceOf(CardViewTextItemModel); expect(cardView.properties[0]).toBeInstanceOf(CardViewTextItemModel);
expect(cardView.properties[1]).toBeInstanceOf(CardViewBoolItemModel); expect(cardView.properties[1]).toBeInstanceOf(CardViewBoolItemModel);
expect(cardView.properties[2]).toBeInstanceOf(CardViewSelectItemModel);
changeMatSelectValue('rule-action-select', 'mock-action-2-definition'); changeMatSelectValue('rule-action-select', 'mock-action-2-definition');
expect(cardView.properties.length).toBe(0); expect(cardView.properties.length).toBe(0);

View File

@ -27,10 +27,18 @@ import { Component, forwardRef, Input, OnDestroy, OnInit, ViewEncapsulation } fr
import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { ControlValueAccessor, FormControl, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model'; import { ActionDefinitionTransformed, RuleAction } from '../../model/rule-action.model';
import { CardViewItem } from '@alfresco/adf-core/lib/card-view/interfaces/card-view-item.interface'; import { CardViewItem } from '@alfresco/adf-core/lib/card-view/interfaces/card-view-item.interface';
import { CardViewBoolItemModel, CardViewTextItemModel, CardViewUpdateService, UpdateNotification } from '@alfresco/adf-core'; import {
CardViewBoolItemModel,
CardViewSelectItemModel,
CardViewSelectItemOption,
CardViewTextItemModel,
CardViewUpdateService,
UpdateNotification
} from '@alfresco/adf-core';
import { ActionParameterDefinition } from '@alfresco/js-api'; import { ActionParameterDefinition } from '@alfresco/js-api';
import { Subject } from 'rxjs'; import { of, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Aspect } from '../../model/aspect.model';
@Component({ @Component({
selector: 'aca-rule-action', selector: 'aca-rule-action',
@ -66,6 +74,17 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
this.setDisabledState(isReadOnly); this.setDisabledState(isReadOnly);
} }
private _aspects;
@Input()
get aspects(): Aspect[] {
return this._aspects;
}
set aspects(value) {
this._aspects = this.parseAspectsToSelectOptions(value);
}
isFullWidth = false;
form = new FormGroup({ form = new FormGroup({
actionDefinitionId: new FormControl('', Validators.required) actionDefinitionId: new FormControl('', Validators.required)
}); });
@ -82,6 +101,10 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
return this.actionDefinitions.find((actionDefinition: ActionDefinitionTransformed) => actionDefinition.id === this.selectedActionDefinitionId); return this.actionDefinitions.find((actionDefinition: ActionDefinitionTransformed) => actionDefinition.id === this.selectedActionDefinitionId);
} }
get cardViewStyle() {
return this.isFullWidth ? { width: '100%' } : {};
}
onChange: (action: RuleAction) => void = () => undefined; onChange: (action: RuleAction) => void = () => undefined;
onTouch: () => void = () => undefined; onTouch: () => void = () => undefined;
@ -137,6 +160,7 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
setCardViewProperties() { setCardViewProperties() {
this.cardViewItems = (this.selectedActionDefinition?.parameterDefinitions ?? []).map((paramDef) => { this.cardViewItems = (this.selectedActionDefinition?.parameterDefinitions ?? []).map((paramDef) => {
this.isFullWidth = false;
const cardViewPropertiesModel = { const cardViewPropertiesModel = {
label: paramDef.displayLabel + (paramDef.mandatory ? ' *' : ''), label: paramDef.displayLabel + (paramDef.mandatory ? ' *' : ''),
key: paramDef.name, key: paramDef.name,
@ -158,6 +182,16 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
...cardViewPropertiesModel, ...cardViewPropertiesModel,
value: this.parameters[paramDef.name] ?? false value: this.parameters[paramDef.name] ?? false
}); });
case 'd:qname':
if (paramDef.name === 'aspect-name' && !this.readOnly) {
this.isFullWidth = true;
return new CardViewSelectItemModel({
...cardViewPropertiesModel,
value: (this.parameters[paramDef.name] as string) ?? '',
options$: of(this._aspects)
});
}
/* falls through */
default: default:
return new CardViewTextItemModel({ return new CardViewTextItemModel({
...cardViewPropertiesModel, ...cardViewPropertiesModel,
@ -189,4 +223,21 @@ export class RuleActionUiComponent implements ControlValueAccessor, OnInit, OnDe
this.form.enable(); this.form.enable();
} }
} }
private parseAspectsToSelectOptions(aspects: Aspect[]): CardViewSelectItemOption<unknown>[] {
return aspects
.sort((a, b) => {
if (!a.label && b.label) {
return 1;
}
if (!b.label && a.label) {
return -1;
}
return a.label?.localeCompare(b.label) ?? -1;
})
.map((aspect) => ({
key: aspect.value,
label: aspect.label ? `${aspect.label} [${aspect.value}]` : aspect.value
}));
}
} }

View File

@ -18,6 +18,7 @@
<ng-template #ruleDetails> <ng-template #ruleDetails>
<aca-rule-details <aca-rule-details
[actionDefinitions]="actionDefinitions$ | async" [actionDefinitions]="actionDefinitions$ | async"
[aspects]="aspects$ | async"
[value]="model" [value]="model"
(formValueChanged)="formValue = $event" (formValueChanged)="formValue = $event"
(formValidationChanged)="formValid = $event"> (formValidationChanged)="formValid = $event">

View File

@ -46,6 +46,7 @@ export class EditRuleDialogSmartComponent implements OnInit {
@Output() submitted = new EventEmitter<Partial<Rule>>(); @Output() submitted = new EventEmitter<Partial<Rule>>();
actionDefinitions$ = this.actionsService.actionDefinitionsListing$; actionDefinitions$ = this.actionsService.actionDefinitionsListing$;
loading$ = this.actionsService.loading$; loading$ = this.actionsService.loading$;
aspects$ = this.actionsService.aspects$;
constructor(@Inject(MAT_DIALOG_DATA) public data: EditRuleDialogOptions, private actionsService: ActionsService) { constructor(@Inject(MAT_DIALOG_DATA) public data: EditRuleDialogOptions, private actionsService: ActionsService) {
this.model = this.data?.model || {}; this.model = this.data?.model || {};
@ -68,6 +69,7 @@ export class EditRuleDialogSmartComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.actionsService.loadAspects();
this.actionsService.loadActionDefinitions(); this.actionsService.loadActionDefinitions();
} }
} }

View File

@ -50,6 +50,7 @@
<aca-rule-action-list <aca-rule-action-list
formControlName="actions" formControlName="actions"
[actionDefinitions]="actionDefinitions" [actionDefinitions]="actionDefinitions"
[aspects]="aspects"
[readOnly]="readOnly"> [readOnly]="readOnly">
</aca-rule-action-list> </aca-rule-action-list>
</div> </div>

View File

@ -32,6 +32,7 @@ import { ruleCompositeConditionValidator } from './validators/rule-composite-con
import { FolderRulesService } from '../services/folder-rules.service'; import { FolderRulesService } from '../services/folder-rules.service';
import { ActionDefinitionTransformed } from '../model/rule-action.model'; import { ActionDefinitionTransformed } from '../model/rule-action.model';
import { ruleActionsValidator } from './validators/rule-actions.validator'; import { ruleActionsValidator } from './validators/rule-actions.validator';
import { Aspect } from '../model/aspect.model';
@Component({ @Component({
selector: 'aca-rule-details', selector: 'aca-rule-details',
@ -84,6 +85,8 @@ export class RuleDetailsUiComponent implements OnInit, OnDestroy {
preview: boolean; preview: boolean;
@Input() @Input()
actionDefinitions: ActionDefinitionTransformed[] = []; actionDefinitions: ActionDefinitionTransformed[] = [];
@Input()
aspects: Aspect[] = [];
@Output() @Output()
formValidationChanged = new EventEmitter<boolean>(); formValidationChanged = new EventEmitter<boolean>();

View File

@ -32,6 +32,8 @@ import { take } from 'rxjs/operators';
describe('ActionsService', () => { describe('ActionsService', () => {
let actionsService: ActionsService; let actionsService: ActionsService;
let apiCallSpy;
const params = [{}, {}, {}, {}, {}, ['application/json'], ['application/json']];
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -62,4 +64,13 @@ describe('ActionsService', () => {
expect(await loadingTruePromise).toBeTrue(); expect(await loadingTruePromise).toBeTrue();
expect(await loadingFalsePromise).toBeFalse(); expect(await loadingFalsePromise).toBeFalse();
}); });
it('loadAspects should send correct GET request', async () => {
apiCallSpy = spyOn<any>(actionsService, 'publicApiCall').withArgs(`/action-parameter-constraints/ac-aspects`, 'GET', params).and.returnValue([]);
actionsService.loadAspects();
expect(apiCallSpy).toHaveBeenCalled();
expect(apiCallSpy).toHaveBeenCalledWith(`/action-parameter-constraints/ac-aspects`, 'GET', params);
});
}); });

View File

@ -26,9 +26,10 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { ActionDefinition, ActionDefinitionEntry, ActionDefinitionList, ActionParameterDefinition, ActionsApi } from '@alfresco/js-api'; import { ActionDefinition, ActionDefinitionEntry, ActionDefinitionList, ActionParameterDefinition, ActionsApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core'; import { AlfrescoApiService } from '@alfresco/adf-core';
import { BehaviorSubject, from } from 'rxjs'; import { BehaviorSubject, from, Observable } from 'rxjs';
import { ActionDefinitionTransformed, ActionParameterDefinitionTransformed } from '../model/rule-action.model'; import { ActionDefinitionTransformed, ActionParameterDefinitionTransformed } from '../model/rule-action.model';
import { finalize, map } from 'rxjs/operators'; import { finalize, map } from 'rxjs/operators';
import { Aspect } from '../model/aspect.model';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class ActionsService { export class ActionsService {
@ -36,6 +37,8 @@ export class ActionsService {
actionDefinitionsListing$ = this.actionDefinitionsListingSource.asObservable(); actionDefinitionsListing$ = this.actionDefinitionsListingSource.asObservable();
private loadingSource = new BehaviorSubject<boolean>(false); private loadingSource = new BehaviorSubject<boolean>(false);
loading$ = this.loadingSource.asObservable(); loading$ = this.loadingSource.asObservable();
private aspectsSource = new BehaviorSubject<Aspect[]>([]);
aspects$: Observable<Aspect[]> = this.aspectsSource.asObservable();
private _actionsApi: ActionsApi; private _actionsApi: ActionsApi;
get actionsApi(): ActionsApi { get actionsApi(): ActionsApi {
@ -59,6 +62,14 @@ export class ActionsService {
}); });
} }
loadAspects(): void {
from(this.publicApiCall('/action-parameter-constraints/ac-aspects', 'GET', [{}, {}, {}, {}, {}, ['application/json'], ['application/json']]))
.pipe(map((res) => res.entry.constraintValues.map((entry) => this.formatAspect(entry))))
.subscribe((res) => {
this.aspectsSource.next(res);
});
}
private transformActionDefinition(obj: ActionDefinition | ActionDefinitionEntry): ActionDefinitionTransformed { private transformActionDefinition(obj: ActionDefinition | ActionDefinitionEntry): ActionDefinitionTransformed {
if (this.isActionDefinitionEntry(obj)) { if (this.isActionDefinitionEntry(obj)) {
obj = obj.entry; obj = obj.entry;
@ -89,4 +100,15 @@ export class ActionsService {
private isActionDefinitionEntry(obj): obj is ActionDefinitionEntry { private isActionDefinitionEntry(obj): obj is ActionDefinitionEntry {
return typeof obj.entry !== 'undefined'; return typeof obj.entry !== 'undefined';
} }
private publicApiCall(path: string, httpMethod: string, params?: any[]): Promise<any> {
return this.apiService.getInstance().contentClient.callApi(path, httpMethod, ...params);
}
private formatAspect(aspect): Aspect {
return {
value: aspect.value ?? '',
label: aspect.label ?? ''
};
}
} }

View File

@ -126,19 +126,6 @@ describe('FolderRulesService', () => {
}); });
}); });
describe('loadAspects', () => {
beforeEach(async () => {
apiCallSpy = spyOn<any>(folderRulesService, 'apiCall').withArgs(`/aspects`, 'GET', params).and.returnValue([]);
folderRulesService.loadAspects();
});
it('should send correct GET request', async () => {
expect(apiCallSpy).toHaveBeenCalled();
expect(apiCallSpy).toHaveBeenCalledWith(`/aspects`, 'GET', params);
});
});
describe('createRule', () => { describe('createRule', () => {
beforeEach(async () => { beforeEach(async () => {
spyOn<any>(folderRulesService, 'apiCall') spyOn<any>(folderRulesService, 'apiCall')

View File

@ -32,7 +32,6 @@ import { ContentApiService } from '@alfresco/aca-shared';
import { NodeInfo } from '@alfresco/aca-shared/store'; import { NodeInfo } from '@alfresco/aca-shared/store';
import { RuleCompositeCondition } from '../model/rule-composite-condition.model'; import { RuleCompositeCondition } from '../model/rule-composite-condition.model';
import { RuleSimpleCondition } from '../model/rule-simple-condition.model'; import { RuleSimpleCondition } from '../model/rule-simple-condition.model';
import { Aspect, AspectModel } from '../model/aspect.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -71,8 +70,6 @@ export class FolderRulesService {
loading$ = this.loadingSource.asObservable(); loading$ = this.loadingSource.asObservable();
private deletedRuleIdSource = new BehaviorSubject<string>(null); private deletedRuleIdSource = new BehaviorSubject<string>(null);
deletedRuleId$: Observable<string> = this.deletedRuleIdSource.asObservable(); deletedRuleId$: Observable<string> = this.deletedRuleIdSource.asObservable();
private aspectsSource = new BehaviorSubject<Aspect[]>([]);
aspects$: Observable<Aspect[]> = this.aspectsSource.asObservable();
constructor(private apiService: AlfrescoApiService, private contentApi: ContentApiService) {} constructor(private apiService: AlfrescoApiService, private contentApi: ContentApiService) {}
@ -173,14 +170,6 @@ export class FolderRulesService {
).subscribe({ error: (error) => console.error(error) }); ).subscribe({ error: (error) => console.error(error) });
} }
loadAspects(): void {
from(this.apiCall('/aspects', 'GET', [{}, {}, {}, {}, {}, ['application/json'], ['application/json']]))
.pipe(map((res) => res.list.entries.map((entry) => this.formatAspect(entry.entry))))
.subscribe((res) => {
this.aspectsSource.next(res);
});
}
private apiCall(path: string, httpMethod: string, params?: any[]): Promise<any> { private apiCall(path: string, httpMethod: string, params?: any[]): Promise<any> {
// APIs used by this service are still private and not yet available for public use // APIs used by this service are still private and not yet available for public use
return this.apiService.getInstance().contentPrivateClient.callApi(path, httpMethod, ...params); return this.apiService.getInstance().contentPrivateClient.callApi(path, httpMethod, ...params);
@ -233,24 +222,4 @@ export class FolderRulesService {
parameter: obj.parameter || '' parameter: obj.parameter || ''
}; };
} }
private formatAspect(obj): Aspect {
return {
includedInSupertypeQuery: obj.includedInSupertypeQuery ?? false,
isContainer: obj.isContainer ?? false,
model: this.formatAspectModel(obj.model),
id: obj.id ?? '',
title: obj.title ?? '',
parentId: obj.parentId ?? ''
};
}
private formatAspectModel(obj): AspectModel {
return {
id: obj.id ?? '',
description: obj.description ?? '',
namespaceUri: obj.namespaceUri ?? '',
namespacePrefix: obj.namespacePrefix ?? ''
};
}
} }