[Trunk | Monitor Dashboard]:

1. indicators.component.ts:
	a. Added fields "import_loading" and "export_loading" and set "editing", to show loading icon and disable edit options while export or import process is ongoing.
	b. Validate schema of indicators' file when importing it (type (chart or number), url, and jsonPath (for number indicators) are requested).
2. indicators.component.html: 
	a. Instead of import or export icon (next to buttons), show loading icon when "import_loading" or "export_loading" is true.
	b. Disable edit options for indicators when "import_loading" or "export_loading" is true and show tooltip.


git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-monitor-portal/trunk/monitor_dashboard@61433 d315682c-612b-4755-9ff5-7f18f6832af3
This commit is contained in:
Konstantina Galouni 2021-07-19 09:50:08 +00:00
parent 94fe302965
commit f51ca5f7ed
2 changed files with 96 additions and 28 deletions

View File

@ -1,12 +1,14 @@
<div *ngIf="stakeholder && canEdit">
<div class="uk-text-right uk-width-expand">
<a class="uk-margin-bottom uk-margin-right " uk-icon="icon:download" title="Export indicators (JSON file)"
<a class="uk-margin-bottom uk-margin-right " [attr.uk-icon]="export_loading ? null : 'icon:download'" title="Export indicators (JSON file)"
(click)="export_indicators()">
<span class="uk-text-small">Export</span>
<span *ngIf="export_loading" class="uk-margin-small-left uk-icon icon-button"><loading [top_margin]="false"></loading></span>
</a>
<div uk-form-custom class="js-upload uk-margin-top">
<input id="exampleInputFile" type="file" class="uk-width-medium" (change)="fileChangeEvent($event)"/>
<a class=" uk-margin-bottom" uk-icon="icon:upload" title="Import indicators (JSON file)"> Import</a>
<a class=" uk-margin-bottom" [attr.uk-icon]="import_loading ? null : 'icon:upload'" title="Import indicators (JSON file)"> Import</a>
<span *ngIf="import_loading" class="uk-margin-small-left uk-icon icon-button"><loading [top_margin]="false"></loading></span>
</div>
</div>
@ -60,8 +62,9 @@
<div class="uk-card uk-card-default uk-card-body uk-position-relative" [class.uk-card-hover]="canReorder">
<ng-container
*ngTemplateOutlet="visibilityOptions; context:{indicator: indicator, sectionId: number._id}"></ng-container>
<div class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i uk-icon="more-vertical" (click)="$event.stopPropagation();$event.preventDefault()"></i>
<div [attr.uk-tooltip]="export_loading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i [class]="export_loading ? 'uk-disabled ' : ' '" uk-icon="more-vertical" (click)="$event.stopPropagation();$event.preventDefault()"></i>
<div #element uk-dropdown="mode: click; pos: bottom-right; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngIf="!editing"><a
@ -164,8 +167,9 @@
<div class="uk-card uk-card-default uk-card-body uk-position-relative" [class.uk-card-hover]="canReorder">
<ng-container
*ngTemplateOutlet="visibilityOptions; context:{indicator: indicator, sectionId: chart._id}"></ng-container>
<div class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i uk-icon="more-vertical" (click)="$event.stopPropagation();$event.preventDefault()"></i>
<div [attr.uk-tooltip]="export_loading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-right uk-margin-small-right uk-margin-small-top clickable">
<i [class]="export_loading ? 'uk-disabled ' : ' '" uk-icon="more-vertical" (click)="$event.stopPropagation();$event.preventDefault()"></i>
<div #element uk-dropdown="mode: click; pos: bottom-right; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
<li *ngIf="!editing"><a
@ -543,8 +547,9 @@
Are you sure you want to proceed?
</modal-alert>-->
<ng-template #visibilityOptions let-indicator="indicator" let-sectionId="sectionId">
<span class="uk-position-top-left uk-margin-small-left uk-margin-small-top clickable visibility">
<span class="clickable color">
<span [attr.uk-tooltip]="export_loading ? 'title:Edit is disabled, while exporting indicators; cls:uk-active' : 'cls: uk-invisible'"
class="uk-position-top-left uk-margin-small-left uk-margin-small-top visibility" [class]="export_loading ? '' : ' clickable '">
<span [class]="export_loading ? 'uk-disabled ' : ' '" class="clickable color">
<icon [name]="stakeholderUtils.visibilityIcon.get(indicator.visibility)"></icon>
</span>
<div #element uk-dropdown="mode: click; pos: bottom-left; delay-hide: 0; flip: false">

View File

@ -45,7 +45,8 @@ declare var UIkit;
export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
filesToUpload: Array<File>;
errorMessage = "";
enableUpload: boolean = true;
import_loading: boolean = false;
export_loading: boolean = false;
@Input()
public properties: EnvProperties = null;
@ -910,6 +911,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
this.filterCharts();
this.filterNumbers();
this.editing = false;
this.import_loading = false;
UIkit.notification("Success! Indicated were imported", {
status: 'success',
timeout: 6000,
@ -923,6 +925,7 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
}));
@ -1233,6 +1236,30 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
for(let chart of charts) {
let exists = false;
let indicatorPath;
// validate indicators' schema from file
let invalid_file_message = "";
if (!chart.type) {
invalid_file_message = "No indicator type is specified. Type should be chart or number.";
} else if(chart.type != "chart" || chart.type != "number") {
invalid_file_message = "Invalid indicator type. Type should be chart or number.";
} else if(chart.type == "number" && !chart.jsonPath) {
invalid_file_message = "No jsonPath is specified for number indicator."
} else if(!chart.url) {
invalid_file_message = "No indicator url is specified.";
}
if(invalid_file_message) {
UIkit.notification("Error on indicators' schema. Type should be chart or number, url is needed and for number indicators, jsonPath is needed as well.", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
break;
}
if (chart.type == "chart") {
indicatorPath = this.indicatorUtils.generateIndicatorByChartUrl(this.statisticsService.getChartSource(chart.url), chart.url, chart.type, this.stakeholder);
for (let section of this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.subcategoryIndex].charts) {
@ -1283,6 +1310,8 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
}else if(indicators.length > 0){
console.log(indicators);
this.saveIndicators(indicators)
@ -1293,12 +1322,17 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
}
}
public export_indicators() {
console.debug("Export indicators");
this.editing = true;
this.export_loading = true;
let indicators = [];
let index: number = 0;
@ -1307,10 +1341,11 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
indicator.indicatorPaths.forEach(indicatorPath => {
console.debug("export number: ", this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath)));
indicators[index] = {
"type": indicator.type, "name": indicator.name, "jsonPath":indicatorPath.jsonPath,
"type": indicator.type, "name": indicator.name, "jsonPath": indicatorPath.jsonPath,
"description": indicator.description, "additionalDescription": indicator.additionalDescription,
"visibility": indicator.visibility, "width": indicator.width, "height": indicator.height,
"url": this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath))};
"url": this.statisticsService.getNumberUrl(indicatorPath.source, this.indicatorUtils.getFullUrl(this.stakeholder, indicatorPath))
};
index++;
});
});
@ -1319,12 +1354,13 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
this.displayCharts.forEach(section => {
section.indicators.forEach(indicator => {
indicator.indicatorPaths.forEach(indicatorPath => {
console.debug("export chart: "+this.getUrlByStakeHolder(indicatorPath));
console.debug("export chart: " + this.getUrlByStakeHolder(indicatorPath));
indicators[index] = {
"type": indicator.type, "name": indicator.name,
"description": indicator.description, "additionalDescription": indicator.additionalDescription,
"visibility": indicator.visibility, "width": indicator.width, "height": indicator.height,
"url": this.getUrlByStakeHolder(indicatorPath)};
"url": this.getUrlByStakeHolder(indicatorPath)
};
index++;
});
});
@ -1339,29 +1375,45 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
window.document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = jsonFileUrl;
a.download = this.stakeholder.alias + "_"+topic.alias + "_" + category.alias + "_" + subCategory.alias + ".json";
a.download = this.stakeholder.alias + "_" + topic.alias + "_" + category.alias + "_" + subCategory.alias + ".json";
a.click();
window.URL.revokeObjectURL(jsonFileUrl);
a.remove(); // remove the element
this.editing = false;
this.export_loading = false;
}
fileChangeEvent(fileInput: any) {
this.editing = true;
this.import_loading = true;
this.filesToUpload = <Array<File>>fileInput.target.files;
this.upload();
}
upload() {
this.enableUpload = false;
// this.errorMessage = "";
console.debug(this.filesToUpload);
if (this.filesToUpload.length == 0) {
console.error("There is no selected file to upload.");
// this.errorMessage = "There is no selected file to upload.";
UIkit.notification("There is no selected file to upload.", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
return;
} else {
if (this.filesToUpload[0].name.indexOf(".json") == -1 || (this.filesToUpload[0].type != "application/json")) {
// this.errorMessage = "No valid file type. The required type is 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.editing = false;
this.import_loading = false;
return;
}
}
@ -1370,11 +1422,28 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
this.makeFileRequest(this.properties.utilsService + '/upload?type=json', [], this.filesToUpload).then(async (result: string) => {
let json_result = JSON.parse(result);
// validate file
if(!json_result || json_result.length == 0) {
UIkit.notification("Importing file is empty", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
} else {
this.importIndicatorsAndSave(json_result);
this.endOfFetching();
}
}, (error) => {
this.enableUpload = true;
console.error("An error occurred");
console.error("Error importing files", error);
UIkit.notification("Error importing files", {
status: 'danger',
timeout: 6000,
pos: 'bottom-right'
});
this.editing = false;
this.import_loading = false;
});
}
@ -1398,10 +1467,4 @@ export class IndicatorsComponent implements OnInit, OnDestroy, OnChanges, AfterV
xhr.send(formData);
});
}
endOfFetching() {
// this.showReport = true;
this.enableUpload = true;
}
}