From 7c29f95ba0dcf74cb06944b473cc83c4a128ea86 Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Thu, 14 Nov 2024 12:28:02 +0200 Subject: [PATCH] [angular-18-override-references]: Add generate stakeholders from file. Add configuration to enable generate stakeholders from file and override references. Currently enabled only for development. --- .../edit-stakeholder.component.ts | 26 +-- .../manageStakeholders.component.html | 75 ++++++- .../manageStakeholders.component.ts | 187 +++++++++++++++--- monitor-admin/topic/indicators.component.html | 19 +- monitor-admin/topic/indicators.component.ts | 104 ++++------ monitor-admin/topic/topic.component.html | 41 ++-- monitor-admin/utils/indicator-utils.ts | 13 +- .../utils/stakeholder-base.component.ts | 25 ++- monitor/services/stakeholder.service.ts | 14 +- services/upload-file.service.ts | 39 ++++ 10 files changed, 403 insertions(+), 140 deletions(-) create mode 100644 services/upload-file.service.ts diff --git a/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts b/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts index 27aa2ef3..7b9076f5 100644 --- a/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts +++ b/monitor-admin/general/edit-stakeholder/edit-stakeholder.component.ts @@ -161,7 +161,6 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { public isFull: boolean; public loading: boolean = false; public typesByRole: Option[]; - public statsProfiles: string[]; /** * Photo upload * */ @@ -176,8 +175,9 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { constructor(private fb: UntypedFormBuilder, private stakeholderService: StakeholderService, - private statsProfileService: StatsProfilesService, - private utilsService: UtilitiesService, private userManagementService: UserManagementService,) { + private utilsService: UtilitiesService, + private userManagementService: UserManagementService, + protected statsProfileService: StatsProfilesService) { super(); } @@ -201,11 +201,7 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.user = user; if (this.isCurator) { - this.subscriptions.push(this.statsProfileService.getStatsProfiles().subscribe(statsProfiles => { - this.statsProfiles = statsProfiles; - }, error => { - this.statsProfiles = []; - })); + this.setStatsProfiles(); } else { this.statsProfiles = []; } @@ -297,6 +293,14 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { })); } + public get isStandalone() { + return this.stakeholderCategory?.value !== 'dependent'; + } + + public get isUmbrella() { + return this.stakeholderCategory?.value === 'umbrella'; + } + public get isDefault() { return this.stakeholderCategory?.value === 'templates'; } @@ -340,7 +344,7 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { }); } - onTypeChange(value, defaultStakeholders: Stakeholder[]) { + onTypeChange(value: string, defaultStakeholders: Stakeholder[]) { this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, (this.isDefault && !this.isNew) ? [] : Validators.required)); this.defaultStakeholdersOptions = [{ label: 'New blank profile', @@ -384,8 +388,8 @@ export class EditStakeholderComponent extends StakeholderBaseComponent { this.removePhoto(); this.subscriptions.push(this.stakeholderService.buildStakeholder( this.stakeholderFb.getRawValue(), copyId, - this.stakeholderCategory.value !== 'dependent', - this.stakeholderCategory.value === 'umbrella') + this.isStandalone, + this.isUmbrella) .subscribe(stakeholder => { this.notification.entity = stakeholder._id; this.notification.stakeholder = stakeholder.alias; diff --git a/monitor-admin/manageStakeholders/manageStakeholders.component.html b/monitor-admin/manageStakeholders/manageStakeholders.component.html index 554c1dae..960fa4be 100644 --- a/monitor-admin/manageStakeholders/manageStakeholders.component.html +++ b/monitor-admin/manageStakeholders/manageStakeholders.component.html @@ -5,6 +5,9 @@ + Edit -
  • +
  • Cache Indicators
  • @@ -76,6 +79,76 @@ + + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    {{file.files.item(0).name}}
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + placeholder="Stats Profile">
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    = []; @Input() public defaultStakeholders: Stakeholder[]; /** @@ -37,28 +42,37 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone public user = null; public callback: Function; /** - * Grid or List View - */ - @ViewChild('editStakeholderModal', { static: true }) editStakeholderModal: AlertModal; - @ViewChild('deleteStakeholderModal', { static: true }) deleteStakeholderModal: AlertModal; - @ViewChild('editStakeholderComponent', { static: true }) editStakeholderComponent: EditStakeholderComponent; - + * Build Multi Stakeholders + * */ + public indexFields: any[]; + public stakeholderFb: UntypedFormGroup; + public loading: boolean = false; + public typesByRole: Option[] = []; + public defaultStakeholdersOptions: Option[]; + @ViewChild('editStakeholderModal', {static: true}) editStakeholderModal: AlertModal; + @ViewChild('buildStakeholderModal') buildStakeholderModal: AlertModal; + @ViewChild('deleteStakeholderModal', {static: true}) deleteStakeholderModal: AlertModal; + @ViewChild('editStakeholderComponent', {static: true}) editStakeholderComponent: EditStakeholderComponent; + constructor(private stakeholderService: StakeholderService, private cacheIndicatorsService: CacheIndicatorsService, - protected cdr: ChangeDetectorRef) { + private fb: FormBuilder, + private uploadFileService: UploadFileService, + protected cdr: ChangeDetectorRef, + protected statsProfileService: StatsProfilesService) { super(); } - + ngOnInit(): void { super.ngOnInit(); - if(this.stakeholderCategory.value === 'templates') { + if (this.stakeholderCategory.value === 'templates') { this.message = 'Create a new ' + this.stakeholderCategory.name + ' profile.'; } else { this.message = 'Create a new ' + this.stakeholderCategory.name + ' profile by selecting a type and generate indicators based on a default or a blank profile.'; } } - + hide(element: any) { UIkit.dropdown(element).hide(); } @@ -67,12 +81,83 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone this.aliasesChange.emit(this.aliases); super.changed(); } - + + onTypeChange(value: string, defaultStakeholders: Stakeholder[]) { + this.stakeholderFb.setControl('defaultId', this.fb.control(this.stakeholder.defaultId, Validators.required)); + this.defaultStakeholdersOptions = [{ + label: 'New blank profile', + value: '-1' + }]; + defaultStakeholders.filter(stakeholder => stakeholder.type === value).forEach(stakeholder => { + this.defaultStakeholdersOptions.push({ + label: 'Use ' + stakeholder.name + ' profile', + value: stakeholder._id + }) + }); + } + + public clear() { + this.stakeholderFb = null; + this.indexFields = null; + } + + public buildMultiStakeholderOpen() { + this.setStatsProfiles(); + this.stakeholder = new Stakeholder(null, null, null, + null, null, 'index_id', null, null); + this.typesByRole = this.stakeholderUtils.getTypesByUserRoles(this.user, this.stakeholder.alias); + this.stakeholderFb = this.fb.group({ + alias: this.fb.control(this.stakeholder.alias, Validators.required), + index_name: this.fb.control(this.stakeholder.index_name, Validators.required), + index_id: this.fb.control(this.stakeholder.index_id, Validators.required), + index_shortName: this.fb.control(this.stakeholder.index_shortName), + statsProfile: this.fb.control(this.stakeholder.statsProfile, Validators.required), + locale: this.fb.control(this.stakeholder.locale, Validators.required), + type: this.fb.control(this.stakeholder.type, Validators.required), + visibility: this.fb.control(this.stakeholder.visibility, Validators.required), + defaultId: this.fb.control(this.stakeholder.defaultId, Validators.required) + }); + this.subscriptions.push(this.stakeholderFb.get('type').valueChanges.subscribe(value => { + this.onTypeChange(value, this.defaultStakeholders); + })); + if(this.buildStakeholderModal) { + this.buildStakeholderModal.alertTitle = 'Generate Profiles from File'; + this.buildStakeholderModal.cancelButtonText = 'Cancel'; + this.buildStakeholderModal.okButtonLeft = false; + this.buildStakeholderModal.okButtonText = 'Generate'; + this.buildStakeholderModal.alertMessage = false; + this.buildStakeholderModal.stayOpen = true; + this.buildStakeholderModal.open(); + } + } + + private validateIndexFields() { + let stakeholder = this.stakeholderFb.getRawValue(); + let indexes = [stakeholder.index_id, stakeholder.index_name, stakeholder.index_shortName]; + return this.indexFields?.filter(indexField => indexes.filter(index => index && !indexField[index]).length > 0).length === 0; + } + + public generate() { + if(this.validateIndexFields()) { + this.subscriptions.push(this.stakeholderService.buildStakeholders( + this.stakeholderFb.getRawValue(), this.indexFields, + this.isStandalone, + this.isUmbrella).subscribe(stakeholders => { + stakeholders.forEach(stakeholder => { + this.stakeholders.push(stakeholder); + }) + this.buildStakeholderModal.cancel(); + })); + } else { + NotificationHandler.rise('Check index fields to match with the json from your file.', 'danger'); + } + } + public editStakeholder(stakeholder: Stakeholder = null) { this.index = (stakeholder) ? this.stakeholders.findIndex(value => value._id === stakeholder._id) : -1; if (!stakeholder) { this.stakeholder = new Stakeholder(null, null, null, - null, null, null, null, null); + null, null, null, null, null); } else { this.stakeholder = stakeholder; } @@ -81,10 +166,10 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone this.callback = (stakeholder: Stakeholder) => { let index: number = this.aliases.findIndex(value => value == this.stakeholders[this.index].alias); this.stakeholders[this.index] = stakeholder; - if(index != -1) { + if (index != -1) { this.aliases[index] = stakeholder.alias; } - this.editStakeholderModal.cancel(); + this.editStakeholderModal.cancel(); }; this.editStakeholderModal.alertTitle = 'Edit ' + this.stakeholder.name; this.editStakeholderModal.okButtonText = 'Save Changes'; @@ -93,7 +178,7 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone this.stakeholders.push(stakeholder); this.aliases.push(stakeholder.alias) this.changed(); - this.editStakeholderModal.cancel(); + this.editStakeholderModal.cancel(); }; this.editStakeholderModal.alertTitle = 'Create a new ' + this.stakeholderCategory.name + ' profile'; this.editStakeholderModal.okButtonText = 'Create'; @@ -101,34 +186,34 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone this.editStakeholderModal.cancelButtonText = 'Cancel'; this.editStakeholderModal.okButtonLeft = false; this.editStakeholderModal.alertMessage = false; - this.editStakeholderModal.stayOpen = true; + this.editStakeholderModal.stayOpen = true; this.editStakeholderModal.open(); } - + public createReport(stakeholder: Stakeholder) { this.cacheIndicatorsService.createReport(stakeholder.alias).subscribe(report => { - NotificationHandler.rise('A caching process for ' + stakeholder.name + ' has been started.' ) + NotificationHandler.rise('A caching process for ' + stakeholder.name + ' has been started.') }, error => { console.log(error); NotificationHandler.rise(error.message(), 'danger'); }); } - + public deleteStakeholderOpen(stakeholder: Stakeholder) { this.stakeholder = stakeholder; this.deleteStakeholderModal.alertTitle = 'Delete ' + this.stakeholder.index_name; this.deleteStakeholderModal.cancelButtonText = 'No'; this.deleteStakeholderModal.okButtonText = 'Yes'; - this.deleteStakeholderModal.alertMessage = false; - this.deleteStakeholderModal.stayOpen = true; + this.deleteStakeholderModal.alertMessage = false; + this.deleteStakeholderModal.stayOpen = true; this.deleteStakeholderModal.open(); } - + public deleteStakeholder() { - this.deleteLoading = true; + this.deleteLoading = true; this.index = (this.stakeholder) ? this.stakeholders.findIndex(value => value._id === this.stakeholder._id) : -1; this.subscriptions.push(this.stakeholderService.deleteElement([this.stakeholder._id]).subscribe(() => { - UIkit.notification(this.stakeholder.name+ ' has been successfully deleted', { + UIkit.notification(this.stakeholder.name + ' has been successfully deleted', { status: 'success', timeout: 6000, pos: 'bottom-right' @@ -136,26 +221,26 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone this.stakeholders.splice(this.index, 1); this.aliases = this.aliases.filter(item => item !== this.stakeholder.alias); this.changed(); - this.deleteLoading = false; - this.deleteStakeholderModal.cancel(); + this.deleteLoading = false; + this.deleteStakeholderModal.cancel(); }, error => { UIkit.notification('An error has occurred. Please try again later', { status: 'danger', timeout: 6000, pos: 'bottom-right' }); - this.deleteLoading = false; - this.deleteStakeholderModal.cancel(); + this.deleteLoading = false; + this.deleteStakeholderModal.cancel(); })); } - + changeStakeholderStatus(stakeholder: Stakeholder, visibility: Visibility) { let path = [ stakeholder._id ]; this.subscriptions.push(this.stakeholderService.changeVisibility(path, visibility).subscribe(returnedElement => { stakeholder.visibility = returnedElement.visibility; - UIkit.notification(stakeholder.name+ '\'s status has been successfully changed to ' + stakeholder.visibility.toLowerCase(), { + UIkit.notification(stakeholder.name + '\'s status has been successfully changed to ' + stakeholder.visibility.toLowerCase(), { status: 'success', timeout: 6000, pos: 'bottom-right' @@ -169,6 +254,48 @@ export class ManageStakeholdersComponent extends FilteredStakeholdersBaseCompone })); } + fileChangeEvent(fileInput: any) { + this.loading = true; + this.filesToUpload = >fileInput.target.files; + this.upload(); + } + + upload() { + let observable = this.uploadFileService.upload(this.filesToUpload, 'json'); + if (observable) { + observable.subscribe((json: any) => { + this.indexFields = json; + this.loading = false; + }, (error) => { + console.error("Error importing files", error); + UIkit.notification("Error importing files", { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.loading = false; + }); + } else { + this.loading = false; + } + } + + public get canChooseTemplate(): boolean { + return this.stakeholderFb.get('type').valid && !!this.defaultStakeholdersOptions; + } + + public get isStandalone() { + return this.stakeholderCategory?.value !== 'dependent'; + } + + public get isUmbrella() { + return this.stakeholderCategory?.value === 'umbrella'; + } + + public get isDefault() { + return this.stakeholderCategory?.value === 'templates'; + } + public isManager(stakeholder: Stakeholder): boolean { return this.isCurator() || (Session.isManager(stakeholder.type, stakeholder.alias, this.user)); } diff --git a/monitor-admin/topic/indicators.component.html b/monitor-admin/topic/indicators.component.html index a1800ce2..71258dc7 100644 --- a/monitor-admin/topic/indicators.component.html +++ b/monitor-admin/topic/indicators.component.html @@ -31,14 +31,14 @@
    - - -
    +
      @@ -73,8 +73,7 @@
    {{ indicator.name }}
    - + --
    @@ -143,14 +142,14 @@
    - - -
    +
      diff --git a/monitor-admin/topic/indicators.component.ts b/monitor-admin/topic/indicators.component.ts index db488373..6af5e455 100644 --- a/monitor-admin/topic/indicators.component.ts +++ b/monitor-admin/topic/indicators.component.ts @@ -1,6 +1,5 @@ import { AfterViewInit, - ChangeDetectorRef, Component, HostListener, Input, @@ -10,17 +9,18 @@ import { ViewChild } from "@angular/core"; import { - Format, ImportIndicators, - Indicator, IndicatorImport, + Format, + ImportIndicators, + Indicator, IndicatorPath, - IndicatorSize, IndicatorType, Section, Stakeholder, Visibility } from "../../monitor/entities/stakeholder"; import { - AbstractControl, FormArray, FormGroup, + AbstractControl, + FormGroup, UntypedFormArray, UntypedFormBuilder, UntypedFormControl, @@ -46,6 +46,7 @@ import {IndicatorStakeholderBaseComponent} from "../utils/stakeholder-base.compo import {properties} from "../../../../environments/environment"; import {StatsProfilesService} from "../utils/services/stats-profiles.service"; import {TransitionGroupComponent} from "../../utils/transition-group/transition-group.component"; +import {UploadFileService} from "../../services/upload-file.service"; declare var UIkit; declare var copy; @@ -55,7 +56,7 @@ declare var copy; templateUrl: './indicators.component.html' }) export class IndicatorsComponent extends IndicatorStakeholderBaseComponent implements OnInit, OnChanges, AfterViewInit { - filesToUpload: Array; + filesToUpload: Array = []; errorMessage = ""; @Input() public topicIndex: number = 0; @@ -122,13 +123,13 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple constructor(private layoutService: LayoutService, private stakeholderService: StakeholderService, private statisticsService: StatisticsService, - private statsProfileService: StatsProfilesService, private notificationService: NotificationService, private fb: UntypedFormBuilder, + private uploadFileService: UploadFileService, + private sanitizer: DomSanitizer, protected _router: Router, - private sanitizer: DomSanitizer) { - super() - this.filesToUpload = []; + protected statsProfileService: StatsProfilesService) { + super(); } ngOnInit(): void { @@ -142,11 +143,7 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple this.initReorder(); }); if (this.isCurator) { - this.subscriptions.push(this.statsProfileService.getStatsProfiles().subscribe(statsProfiles => { - this.statsProfiles = [null].concat(statsProfiles); - }, error => { - this.statsProfiles = []; - })); + this.setStatsProfiles([null]); } else { this.statsProfiles = []; } @@ -1435,57 +1432,38 @@ export class IndicatorsComponent extends IndicatorStakeholderBaseComponent imple } upload() { - if (this.filesToUpload.length == 0) { - console.error("There is no selected file to upload."); - UIkit.notification("There is no selected file to upload.", { - status: 'danger', - timeout: 6000, - pos: 'bottom-right' + let observable = this.uploadFileService.upload(this.filesToUpload, 'json'); + if(observable) { + observable.subscribe((json: ImportIndicators) => { + if (json && Array.isArray(json)) { + UIkit.notification("This file is not supported any more. Please export indicators and try again!", { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.finish(); + } else if (!json || json?.indicators.length == 0) { + UIkit.notification("Importing file is empty", { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.finish(); + } else { + this.importIndicatorsAndSave(json); + } + }, (error) => { + console.error("Error importing files", error); + UIkit.notification("Error importing files", { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.finish(); }); - this.finish(); - return; } else { - if (this.filesToUpload[0].name.indexOf(".json") == -1 || (this.filesToUpload[0].type != "application/json")) { - console.error("No valid file type. The required type is JSON"); - UIkit.notification("No valid file type. The required type is JSON", { - status: 'danger', - timeout: 6000, - pos: 'bottom-right' - }); - this.finish(); - return; - } - } - - this.makeFileRequest(this.properties.utilsService + '/upload?type=json', [], this.filesToUpload).then(async (result: string) => { - let json = JSON.parse(result); - // validate file - if (json && Array.isArray(json)) { - UIkit.notification("This file is not supported any more. Please export indicators and try again!", { - status: 'danger', - timeout: 6000, - pos: 'bottom-right' - }); - this.finish(); - } else if (!json || json?.indicators.length == 0) { - UIkit.notification("Importing file is empty", { - status: 'danger', - timeout: 6000, - pos: 'bottom-right' - }); - this.finish(); - } else { - this.importIndicatorsAndSave(json); - } - }, (error) => { - console.error("Error importing files", error); - UIkit.notification("Error importing files", { - status: 'danger', - timeout: 6000, - pos: 'bottom-right' - }); this.finish(); - }); + } } makeFileRequest(url: string, params: Array, files: Array) { diff --git a/monitor-admin/topic/topic.component.html b/monitor-admin/topic/topic.component.html index 8159b44c..51722e9c 100644 --- a/monitor-admin/topic/topic.component.html +++ b/monitor-admin/topic/topic.component.html @@ -28,12 +28,13 @@ - + -
      +
        @@ -107,12 +108,13 @@ {{category.name}} - + -
        +
          @@ -198,9 +200,9 @@
        -
        +
        -
        +