Merge remote-tracking branch 'origin/ui-redesign' into ui-redesign

This commit is contained in:
George Kalampokis 2020-07-08 18:26:25 +03:00
commit 7a09d85353
24 changed files with 894 additions and 119 deletions

View File

@ -32,7 +32,8 @@
.card-content { .card-content {
text-align: left; text-align: left;
font: Light 16px/26px Roboto; font-weight: 300;
font-size: 1rem;
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
padding-left: 40px; padding-left: 40px;
@ -200,6 +201,7 @@ input[type="text"] {
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
opacity: 0.75; opacity: 0.75;
font-weight: 400;
} }
.dmp-title, .dmp-title,

View File

@ -68,6 +68,7 @@ input[type="text"] {
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
opacity: 0.75; opacity: 0.75;
font-weight: 400;
} }
.dmp-title, .dmp-title,

View File

@ -68,6 +68,7 @@ input[type="text"] {
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
opacity: 0.75; opacity: 0.75;
font-weight: 400;
} }
.dmp-title, .dmp-title,

View File

@ -68,6 +68,7 @@ input[type="text"] {
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
opacity: 0.75; opacity: 0.75;
font-weight: 400;
} }
.dmp-title, .dmp-title,

View File

@ -24,6 +24,7 @@ import { CommonUiModule } from '@common/ui/common-ui.module';
import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; import { AngularStickyThingsModule } from '@w11k/angular-sticky-things';
import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module'; import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module';
import { DatasetOverviewModule } from './overview/dataset-overview.module'; import { DatasetOverviewModule } from './overview/dataset-overview.module';
import { DatasetCriteriaDialogComponent } from './listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -53,14 +54,16 @@ import { DatasetOverviewModule } from './overview/dataset-overview.module';
DatasetExternalRegistryDialogEditorComponent, DatasetExternalRegistryDialogEditorComponent,
DatasetExternalServiceDialogEditorComponent, DatasetExternalServiceDialogEditorComponent,
DatasetUploadDialogue, DatasetUploadDialogue,
DatasetListingItemComponent DatasetListingItemComponent,
DatasetCriteriaDialogComponent
], ],
entryComponents: [ entryComponents: [
DatasetExternalDataRepositoryDialogEditorComponent, DatasetExternalDataRepositoryDialogEditorComponent,
DatasetExternalDatasetDialogEditorComponent, DatasetExternalDatasetDialogEditorComponent,
DatasetExternalRegistryDialogEditorComponent, DatasetExternalRegistryDialogEditorComponent,
DatasetExternalServiceDialogEditorComponent, DatasetExternalServiceDialogEditorComponent,
DatasetUploadDialogue DatasetUploadDialogue,
DatasetCriteriaDialogComponent
] ]
}) })
export class DatasetModule { } export class DatasetModule { }

View File

@ -0,0 +1,2 @@
<a class="col-auto d-flex pointer" (click)="onClose()"><span class="ml-auto pt-3 material-icons clear-icon">clear</span></a>
<app-dataset-criteria-component [isPublic]="data.isPublic" [status]="data.status" [criteriaFormGroup]="data.formGroup" (filtersChanged)="onFiltersChanged($event)" class="col-auto"></app-dataset-criteria-component>

View File

@ -0,0 +1,38 @@
import { Inject, Component, ViewChild, OnInit, Output, EventEmitter } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
import { FormGroup } from '@angular/forms';
import { DatasetCriteriaComponent } from '../dataset-criteria.component';
import { DatasetCriteria } from '@app/core/query/dataset/dataset-criteria';
@Component({
selector: 'dataset-criteria-dialog-component',
templateUrl: './dataset-criteria-dialog.component.html',
})
export class DatasetCriteriaDialogComponent implements OnInit {
@ViewChild(DatasetCriteriaComponent, { static: true }) criteria: DatasetCriteriaComponent;
constructor(
public dialogRef: MatDialogRef<DatasetCriteriaDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { isPublic: boolean, status: Number, criteria: DatasetCriteria, formGroup: FormGroup, updateDataFn: Function }
) {
}
ngOnInit() {
this.criteria.setCriteria(this.data.criteria);
}
onNoClick(): void {
this.dialogRef.close();
}
onClose(): void {
this.dialogRef.close();
}
onFiltersChanged(event) {
this.data.updateDataFn(this.criteria);
}
}

View File

@ -3,20 +3,20 @@
<h6 class="filters-title">{{'CRITERIA.FILTERS'| translate}}</h6> <h6 class="filters-title">{{'CRITERIA.FILTERS'| translate}}</h6>
<div class="row" style="justify-content: center;"> <div class="row" style="justify-content: center;">
<!-- Search Filter--> <!-- Search Filter-->
<mat-form-field class="col-11 search"> <!-- <mat-form-field class="col-11 search">
<input matInput placeholder="{{'CRITERIA.GRANTS.LIKE'| translate}}" name="grantCriteriaLike" <input matInput placeholder="{{'CRITERIA.GRANTS.LIKE'| translate}}" name="grantCriteriaLike"
[formControl]="formGroup.get('like')"> [formControl]="formGroup.get('like')">
<mat-error *ngIf="formGroup.get('like').hasError('backendError')"> <mat-error *ngIf="formGroup.get('like').hasError('backendError')">
{{formGroup.get('like').getError('backendError').message}}</mat-error> {{formGroup.get('like').getError('backendError').message}}</mat-error>
<mat-icon matSuffix class="style-icon">search</mat-icon> <mat-icon matSuffix class="style-icon">search</mat-icon>
</mat-form-field> </mat-form-field> -->
<!-- End of Search Filter --> <!-- End of Search Filter -->
<!-- Status Filter--> <!-- Status Filter-->
<div class="col-10 gray-container" *ngIf="!isPublic" > <div class="col-10 gray-container" *ngIf="!isPublic" >
<h6 class="category-title">{{'CRITERIA.DATA-SETS.STATUS'| translate}}</h6> <h6 class="category-title">{{'CRITERIA.DATA-SETS.STATUS'| translate}}</h6>
<mat-radio-group aria-label="Select an option" [formControl]="formGroup.get('status')"> <mat-radio-group aria-label="Select an option" [formControl]="formGroup.get('status')">
<mat-list-item><mat-radio-button value="null">{{ 'TYPES.DATASET-STATUS.ANY' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="null" [checked]="!formGroup.get('status').value">{{ 'TYPES.DATASET-STATUS.ANY' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="0" >{{ 'TYPES.DATASET-STATUS.DRAFT' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="0" >{{ 'TYPES.DATASET-STATUS.DRAFT' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="1">{{ 'TYPES.DATASET-STATUS.FINALISED' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="1">{{ 'TYPES.DATASET-STATUS.FINALISED' | translate }}</mat-radio-button></mat-list-item>
</mat-radio-group> </mat-radio-group>
@ -27,7 +27,7 @@
<div class="col-10 gray-container" *ngIf="isPublic"> <div class="col-10 gray-container" *ngIf="isPublic">
<h6 class="category-title">{{ 'FACET-SEARCH.GRANT-STATUS.TITLE' | translate }}</h6> <h6 class="category-title">{{ 'FACET-SEARCH.GRANT-STATUS.TITLE' | translate }}</h6>
<mat-radio-group [formControl]="formGroup.get('grantStatus')"> <mat-radio-group [formControl]="formGroup.get('grantStatus')">
<mat-list-item><mat-radio-button checked value="null">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ANY' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button checked value="null" [checked]="!formGroup.get('grantStatus').value">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ANY' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="0">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ACTIVE' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="0">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ACTIVE' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="1">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.INACTIVE' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="1">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.INACTIVE' | translate }}</mat-radio-button></mat-list-item>
</mat-radio-group> </mat-radio-group>
@ -93,7 +93,7 @@
<div class="col-10 gray-container" *ngIf="isAuthenticated()"> <div class="col-10 gray-container" *ngIf="isAuthenticated()">
<h6 class="category-title">{{'CRITERIA.DATA-SETS.ROLE' | translate }}</h6> <h6 class="category-title">{{'CRITERIA.DATA-SETS.ROLE' | translate }}</h6>
<mat-radio-group aria-label="Select an option" [formControl]="formGroup.get('role')"> <mat-radio-group aria-label="Select an option" [formControl]="formGroup.get('role')">
<mat-list-item><mat-radio-button checked value="null">{{ 'TYPES.DATASET-ROLE.ANY' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button checked value="null" [checked]="!formGroup.get('role').value">{{ 'TYPES.DATASET-ROLE.ANY' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="0">{{ 'TYPES.DATASET-ROLE.OWNER' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="0">{{ 'TYPES.DATASET-ROLE.OWNER' | translate }}</mat-radio-button></mat-list-item>
<mat-list-item><mat-radio-button value="1">{{ 'TYPES.DATASET-ROLE.MEMBER' | translate }}</mat-radio-button></mat-list-item> <mat-list-item><mat-radio-button value="1">{{ 'TYPES.DATASET-ROLE.MEMBER' | translate }}</mat-radio-button></mat-list-item>
</mat-radio-group> </mat-radio-group>

View File

@ -1,5 +1,5 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
@ -48,6 +48,8 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
@Input() dmpSearchEnabled; @Input() dmpSearchEnabled;
@Input() status; @Input() status;
@Input() isPublic: boolean; @Input() isPublic: boolean;
@Input() criteriaFormGroup: FormGroup;
@Output() filtersChanged: EventEmitter<any> = new EventEmitter();
public criteria: any; public criteria: any;
public filteringTagsAsync = false; public filteringTagsAsync = false;
public filteredTags: ExternalSourceItemModel[]; public filteredTags: ExternalSourceItemModel[];
@ -139,6 +141,18 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
// This if is just for passing label on chips of dialog
if (this.formGroup && this.criteriaFormGroup) {
this.formGroup.get('datasetTemplates').setValue(this.criteriaFormGroup.get('datasetTemplates').value);
this.formGroup.get('groupIds').setValue(this.criteriaFormGroup.get('groupIds').value);
this.formGroup.get('grants').setValue(this.criteriaFormGroup.get('grants').value);
this.formGroup.get('collaborators').setValue(this.criteriaFormGroup.get('collaborators').value);
this.formGroup.get('organisations').setValue(this.criteriaFormGroup.get('organisations').value);
this.formGroup.get('tags').setValue(this.criteriaFormGroup.get('tags').value);
}
this.formGroup.get('like').valueChanges this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(x => this.controlModified()); .subscribe(x => this.controlModified());
@ -173,7 +187,7 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(x => this.controlModified()); .subscribe(x => this.controlModified());
// if (this.criteria == null) { this.criteria = {}; } // if (this.criteria == null) { this.criteria = {}; }
this.formGroup.patchValue({'status': this.status !== undefined ? this.status : 'null'}); // this.formGroup.patchValue({'status': this.status !== undefined ? this.status : 'null'});
} }
setCriteria(criteria: DatasetCriteria): void { setCriteria(criteria: DatasetCriteria): void {
@ -192,6 +206,7 @@ export class DatasetCriteriaComponent extends BaseCriteriaComponent implements O
controlModified(): void { controlModified(): void {
this.clearErrorModel(); this.clearErrorModel();
this.filtersChanged.emit();
if (this.refreshCallback != null && if (this.refreshCallback != null &&
(this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2) (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2)
) { ) {

View File

@ -1,4 +1,51 @@
<div class="header-image" *ngIf="isPublic"> <div class="main-content listing-main-container h-100">
<div class="container-fluid">
<div class="d-flex flex-direction-row">
<div class="card mt-0" [style.display]="isVisible ? 'block' : 'none'">
<a class="col-auto d-flex" (click)="closeCard()"><span class="ml-auto pt-3 material-icons clear-icon">clear</span></a>
<div class="card-content info-text mb-0 pt-0">
<p>{{'DATASET-LISTING.TEXT-INFO' | translate}} <u class="pointer" [routerLink]="['/explore']">{{'DATASET-LISTING.LINK-PUBLIC-DATASETS' | translate}}</u> {{'DATASET-LISTING.TEXT-INFO-REST' | translate}}</p>
<p class="mt-4 pt-2">{{'DATASET-LISTING.TEXT-INFO-PAR' | translate}}
<div class="col pl-0 pt-3">
<button mat-raised-button class="add-dataset align-self-center yellow-btn" [routerLink]="['/datasets/new']">
{{'DASHBOARD.ACTIONS.ADD-DATASET' | translate}}
</button>
</div>
</div>
</div>
<div class="filter-btn" [style.right]="dialog.openDialogs.length > 0 ? '446px' : '0px'" [style.width]="hasScrollbar() ? '52px' : '37px'" (click)="openFiltersDialog()">
<button mat-raised-button class="p-0">
<mat-icon class="mr-4">filter_alt</mat-icon>
</button>
</div>
</div>
<div>
<div class="listing row pb-2">
<!-- Search Filter-->
<mat-form-field *ngIf="listingItems.length > 0" appearance="outline" class="search-form ml-auto col-auto" floatLabel="never">
<mat-icon matSuffix>search</mat-icon>
<input matInput placeholder="{{'CRITERIA.DATA-SETS.LIKE'| translate}}" name="likeCriteria" [formControl]="formGroup.get('like')">
<mat-error *ngIf="formGroup.get('like').hasError('backendError')">{{formGroup.get('like').getError('backendError').message}}</mat-error>
</mat-form-field>
<!-- End of Search Filter -->
<div class="col-md-12 col-sm-12 col-md-9">
<div *ngFor="let item of listingItems; let i = index">
<app-dataset-listing-item-component [isPublic]="isPublic" [dataset]="item" [showDivider]="i != (listingItems.length - 1)"></app-dataset-listing-item-component>
</div>
<div *ngIf="listingItems && listingItems.length > 0 && this.startIndex < this.totalCount - 1 && this.pageSize < this.totalCount - 1" class="d-flex justify-content-center">
<button type="button" class="btn-load-more" (click)="loadMore()">{{'GENERAL.ACTIONS.LOAD-MORE' | translate}}</button>
</div>
</div>
<div class="col-md-12 d-flex justify-content-center" *ngIf="listingItems.length === 0">
<span class="empty-list">{{'DATASET-LISTING.EMPTY-LIST' | translate}}</span>
</div>
</div>
</div>
</div>
</div>
<!-- Version 1 -->
<!-- <div class="header-image" *ngIf="isPublic">
<div class="header-text-container"> <div class="header-text-container">
<h3>{{ 'ABOUT.WELCOME' | translate }}</h3> <h3>{{ 'ABOUT.WELCOME' | translate }}</h3>
<h4>{{ 'ABOUT.WELCOME-MESSAGE' | translate }}</h4> <h4>{{ 'ABOUT.WELCOME-MESSAGE' | translate }}</h4>
@ -10,7 +57,6 @@
<div class="card-header card-header-plain d-flex"> <div class="card-header card-header-plain d-flex">
<div class="card-desc d-flex flex-column justify-content-center"> <div class="card-desc d-flex flex-column justify-content-center">
<h4 class="card-title">{{'DASHBOARD.DATASETS' | translate}} {{titlePrefix}}</h4> <h4 class="card-title">{{'DASHBOARD.DATASETS' | translate}} {{titlePrefix}}</h4>
<!-- <p class="card-category">{{'DATASET-LISTING.SUBTITLE' | translate}}</p> -->
</div> </div>
<div class="row ml-auto p-2" *ngIf="!isPublic"> <div class="row ml-auto p-2" *ngIf="!isPublic">
<button mat-raised-button color="primary" class="text-uppercase lightblue-btn" [routerLink]="['/datasets/new']"> <button mat-raised-button color="primary" class="text-uppercase lightblue-btn" [routerLink]="['/datasets/new']">
@ -38,4 +84,4 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->

View File

@ -12,26 +12,162 @@
} }
.header-image { .header-image {
background: url("/assets/images/new-dashboard-bg.png") no-repeat; background: url("/assets/images/new-dashboard-bg.png") no-repeat;
background-size: cover; background-size: cover;
margin-top: 70px; margin-top: 70px;
min-height: 15em; min-height: 15em;
position: relative; position: relative;
} }
.header-text-container { .header-text-container {
background: rgba(255, 255, 255, 0.7); background: rgba(255, 255, 255, 0.7);
position: absolute; position: absolute;
bottom: 0px; bottom: 0px;
padding-left: 5em; padding-left: 5em;
padding-right: 10em; padding-right: 10em;
padding-top: 2em; padding-top: 2em;
padding-bottom: 2em; padding-bottom: 2em;
} }
.explore-dmp-content { .explore-dmp-content {
padding: 30px 15px; padding: 30px 15px;
} }
.main-content {
background-color: #f5f5f5;
padding-top: 9.68rem;
padding-bottom: 3rem;
padding-left: 3rem;
padding-right: 3rem;
margin: 0;
display: flex;
flex-grow: 1;
}
.card {
background: #ffffff 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #00000029;
border-radius: 4px;
// width: 987px;
margin-bottom: 3.75rem;
/* height: 407px; */
opacity: 1;
}
.card-title {
text-align: left;
font: Bold 20px/30px Roboto;
letter-spacing: 0px;
color: #212121;
padding-left: 40px;
/* padding-top: 40px; */
padding-right: 55px;
opacity: 1;
}
.card-content {
text-align: left;
font-weight: 300;
letter-spacing: 0px;
color: #212121;
padding-left: 40px;
padding-top: 36px;
padding-bottom: 36px;
padding-right: 55px;
opacity: 1;
}
.clear-icon {
cursor: pointer;
}
.normal-btn {
min-width: 162px;
max-width: 256px;
height: 40px;
cursor: pointer;
background: #129d99 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #1e202029;
border-radius: 30px;
border: none;
color: #ffffff;
opacity: 1;
line-height: 1;
font-size: 0.87rem;
padding: 0.62rem 1.87rem;
margin-left: 40px;
}
.yellow-btn {
min-width: 162px;
max-width: 256px;
height: 40px;
cursor: pointer;
background: #f7dd72 0% 0% no-repeat padding-box;
border-radius: 30px;
opacity: 1;
border: none;
color: #000000;
opacity: 1;
line-height: 1;
font-size: 0.87rem;
padding: 0.62rem 1.87rem;
font-weight: 700;
}
.info-text {
text-align: left;
font-weight: 300;
font-size: 1rem;
letter-spacing: 0px;
color: #212121;
}
.filter-btn {
position: fixed;
right: 0px;
z-index: 100;
width: 37px;
}
.filter-btn button {
color: white;
background-color: #23bcba;
width: 37px;
height: 45px;
}
.search-form {
// font-size: 12px;
text-align: left;
width: 20rem;
}
.search-form mat-icon {
color: #129d99;
}
.empty-list {
text-align: center;
font-weight: 300;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.pointer:hover {
color: #00b29f;
}
::ng-deep .search-form .mat-form-field-wrapper {
background-color: white !important;
padding-bottom: 0 !important;
}
::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
padding: 0.3rem 0rem 0.6rem 0rem !important;
}
::ng-deep .mat-paginator-container { ::ng-deep .mat-paginator-container {
flex-direction: row-reverse !important; flex-direction: row-reverse !important;

View File

@ -19,6 +19,9 @@ import { takeUntil } from 'rxjs/operators';
import { ExternalTagEditorModel } from '../dataset-wizard/dataset-wizard-editor.model'; import { ExternalTagEditorModel } from '../dataset-wizard/dataset-wizard-editor.model';
import { AuthService } from '@app/core/services/auth/auth.service'; import { AuthService } from '@app/core/services/auth/auth.service';
import { isNullOrUndefined } from 'util'; import { isNullOrUndefined } from 'util';
import { DatasetCriteriaDialogComponent } from './criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component';
import { MatDialog } from '@angular/material';
import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
@Component({ @Component({
selector: 'app-dataset-listing-component', selector: 'app-dataset-listing-component',
@ -29,7 +32,7 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
@ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator; @ViewChild(MatPaginator, { static: true }) _paginator: MatPaginator;
@ViewChild(MatSort, { static: false }) sort: MatSort; @ViewChild(MatSort, { static: false }) sort: MatSort;
@ViewChild(DatasetCriteriaComponent, { static: true }) criteria: DatasetCriteriaComponent; // @ViewChild(DatasetCriteriaComponent, { static: true }) criteria: DatasetCriteriaComponent;
breadCrumbs: Observable<BreadcrumbItem[]>; breadCrumbs: Observable<BreadcrumbItem[]>;
@ -41,11 +44,21 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
listingItems: DatasetListingModel[] = []; listingItems: DatasetListingModel[] = [];
isPublic: boolean = false; isPublic: boolean = false;
public isVisible = true
startIndex: number = 0;
pageSize: number = 5;
criteria: DatasetCriteria;
criteriaFormGroup: FormGroup;
public formGroup = new FormBuilder().group({
like: new FormControl()
});
constructor( constructor(
private datasetService: DatasetService, private datasetService: DatasetService,
private router: Router, private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
public dialog: MatDialog,
private dmpService: DmpService, private dmpService: DmpService,
private language: TranslateService, private language: TranslateService,
private authService: AuthService private authService: AuthService
@ -69,9 +82,10 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
if (this.dmpId != null) { if (this.dmpId != null) {
this.dmpSearchEnabled = false; this.dmpSearchEnabled = false;
const dmp = await this.dmpService.getSingle(this.dmpId).toPromise(); const dmp = await this.dmpService.getSingle(this.dmpId).toPromise();
this.criteria.setCriteria(this.getDefaultCriteria(dmp)); this.criteria = this.getDefaultCriteria(dmp);
// this.criteria.setCriteria(this.getDefaultCriteria(dmp));
this.refresh(); this.refresh();
this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages)); // this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
this.breadCrumbs = observableOf([{ this.breadCrumbs = observableOf([{
parentComponentName: 'DmpEditorComponent', parentComponentName: 'DmpEditorComponent',
label: dmp.label, label: dmp.label,
@ -81,9 +95,10 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
this.titlePrefix = 'for ' + params['dmpLabel']; this.titlePrefix = 'for ' + params['dmpLabel'];
} }
} else { } else {
this.criteria.setCriteria(this.getDefaultCriteria()); this.criteria = this.getDefaultCriteria();
// this.criteria.setCriteria(this.getDefaultCriteria());
this.refresh(); this.refresh();
this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages)); // this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
this.breadCrumbs = observableOf([{ this.breadCrumbs = observableOf([{
parentComponentName: null, parentComponentName: null,
label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'), label: this.language.instant('NAV-BAR.MY-DATASET-DESCRIPTIONS'),
@ -92,69 +107,63 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
} }
if (this.status != null && this.status == DatasetStatus.Draft) { if (this.status != null && this.status == DatasetStatus.Draft) {
this.criteria.setCriteria(this.getDraftCriteria()); this.criteria = this.getDraftCriteria();
this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages)); // this.criteria.setRefreshCallback((resetPages) => this.refresh(resetPages));
this.refresh(); this.refresh();
} }
}); });
this.formGroup.get('like').valueChanges
.pipe(takeUntil(this._destroyed))
.subscribe(x => this.controlModified());
}
controlModified(): void {
// this.clearErrorModel();
// if (this.refreshCallback != null &&
// (this.formGroup.get('like').value == null || this.formGroup.get('like').value.length === 0 || this.formGroup.get('like').value.length > 2)
// ) {
// setTimeout(() => this.refreshCallback(true));
// }
this.criteria.like = this.formGroup.get("like").value;
this.refresh();
} }
refresh(resetPages = false) { refresh(resetPages = false) {
if (this._paginator.pageSize === undefined) this._paginator.pageSize = 10; // if (this._paginator.pageSize === undefined) this._paginator.pageSize = 10;
if (resetPages) this._paginator.pageIndex = 0; // if (resetPages) this._paginator.pageIndex = 0;
const startIndex = this._paginator.pageIndex * this._paginator.pageSize; // const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
let fields: Array<string> = new Array(); let fields: Array<string> = new Array();
fields.push('-modified'); fields.push('-modified');
//if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; } //if (this.sort && this.sort.active) { fields = this.sort.direction === 'asc' ? ['+' + this.sort.active] : ['-' + this.sort.active]; }
const request = new DataTableRequest<DatasetCriteria>(startIndex, this._paginator.pageSize, { fields: fields }); const request = new DataTableRequest<DatasetCriteria>(this.startIndex, this.pageSize, { fields: fields });
let value = this.criteria.formGroup.value; request.criteria = this.criteria;
request.criteria = {
like: value.like,
status: value.status,
allVersions: value.allVersions,
role: value.role
}
if (value.tags) {
request.criteria.tags = value.tags.map(x => (<ExternalTagEditorModel>x));
}
if (value.collaborators) {
request.criteria.collaborators = value.collaborators.map(x => x.id);
}
if (value.dmpIds) {
request.criteria.dmpIds = value.dmpIds.map(x => x.id);
}
if (value.groupIds) {
request.criteria.groupIds = value.groupIds.map(x => x.groupId);
}
if (value.grants) {
request.criteria.grants = value.grants.map(x => x.id);
}
if (value.organisations) {
request.criteria.organisations = value.organisations.map(x => x.id);
}
if (value.datasetTemplates) {
request.criteria.datasetTemplates = value.datasetTemplates.map(x => x.id)
}
if(value.grantStatus) {
request.criteria.grantStatus = value.grantStatus;
}
request.criteria.isPublic = this.isPublic;
// if (this.itemId) {
// // request.criteria.groupIds = [this.itemId];
// request.criteria.allVersions = true;
// }
this.datasetService.getPaged(request).pipe(takeUntil(this._destroyed)).subscribe(result => { this.datasetService.getPaged(request).pipe(takeUntil(this._destroyed)).subscribe(result => {
if (!result) { return []; } if (!result) { return []; }
if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; } // if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
this.totalCount = result.totalCount;
this.listingItems = result.data; this.listingItems = result.data;
}); });
} }
public loadMore() {
this.startIndex = this.startIndex + this.pageSize;
const fields: Array<string> = ["-modified"];
const request = new DataTableRequest<DatasetCriteria>(this.startIndex, this.pageSize, { fields: fields });
request.criteria = this.criteria;
this.datasetService.getPaged(request).pipe(takeUntil(this._destroyed)).subscribe(result => {
if (!result) { return []; }
// if (this._paginator.pageIndex === 0) { this.totalCount = result.totalCount; }
this.listingItems = this.listingItems.concat(result.data);
});
}
pageThisEvent(event) { pageThisEvent(event) {
this.refresh(); this.refresh();
} }
getDefaultCriteria(dmp: any = null): DatasetCriteria { getDefaultCriteria(dmp: any = null): DatasetCriteria {
const defaultCriteria = new DatasetCriteria(); const defaultCriteria = new DatasetCriteria();
if (dmp != null) { if (dmp != null) {
@ -175,6 +184,79 @@ export class DatasetListingComponent extends BaseComponent implements OnInit, IB
.subscribe(); .subscribe();
} }
openFiltersDialog(): void {
const dialogRef = this.dialog.open(DatasetCriteriaDialogComponent, {
width: '456px',
height: '100%',
restoreFocus: false,
data: {
isPublic: this.isPublic,
status: this.status,
criteria: this.criteria,
formGroup: this.criteriaFormGroup,
// criteria: this.grantId ? this.criteria : this.getDefaultCriteria(),
updateDataFn: this.updateDataFn.bind(this)
},
position: { right: '0px;' }
});
dialogRef.afterClosed().subscribe(result => {
});
}
updateDataFn(criteria: DatasetCriteriaComponent): void {
this.criteriaFormGroup = criteria.formGroup;
this.toDatasetCriteria(criteria);
this.refresh();
}
toDatasetCriteria(criteria: DatasetCriteriaComponent) {
let formGroup = criteria.formGroup;
this.criteria = {
like: formGroup.get("like").value,
status: formGroup.get("status").value,
allVersions: formGroup.get("allVersions").value,
role: formGroup.get("role").value
}
if (formGroup.get("tags") && formGroup.get("tags").value) {
this.criteria.tags = formGroup.get("tags").value.map(x => (<ExternalTagEditorModel>x));
}
if (formGroup.get("collaborators") && formGroup.get("collaborators").value) {
this.criteria.collaborators = formGroup.get("collaborators").value.map(x => x.id);
}
if (formGroup.get("dmpIds") && formGroup.get("dmpIds").value) {
this.criteria.dmpIds = formGroup.get("dmpIds").value.map(x => x.id);
}
if (formGroup.get("groupIds") && formGroup.get("groupIds").value) {
this.criteria.groupIds = formGroup.get("groupIds").value.map(x => x.groupId);
}
if (formGroup.get("grants") && formGroup.get("grants").value) {
this.criteria.grants = formGroup.get("grants").value.map(x => x.id);
}
if (formGroup.get("organisations") && formGroup.get("organisations").value) {
this.criteria.organisations = formGroup.get("organisations").value.map(x => x.id);
}
if (formGroup.get("datasetTemplates") && formGroup.get("datasetTemplates").value) {
this.criteria.datasetTemplates = formGroup.get("datasetTemplates").value.map(x => x.id)
}
if (formGroup.get("grantStatus") && formGroup.get("grantStatus").value) {
this.criteria.grantStatus = formGroup.get("grantStatus").value;
}
this.criteria.isPublic = this.isPublic;
// if (this.itemId) {
// // this.criteria.groupIds = [this.itemId];
// this.criteria.allVersions = true;
// }
}
public closeCard(): void {
this.isVisible = false;
}
hasScrollbar(): boolean {
return document.getElementById("main-page").scrollHeight > document.documentElement.clientHeight
}
// rowClicked(dataset: DatasetListingModel) { // rowClicked(dataset: DatasetListingModel) {
// this.router.navigate(['/datasets/edit/' + dataset.id]); // this.router.navigate(['/datasets/edit/' + dataset.id]);
// } // }

View File

@ -1,14 +1,75 @@
<div class="listing-item" *ngIf="!isDeleted"> <div class="dataset-card">
<a [routerLink]="['../datasets/overview/' + dataset.id]" class="pointer">
<div class="d-flex flex-direction-row">
<div class="col-auto dataset-label">{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}</div>
<div class="col-auto ml-auto edited-date">{{'DATASET-LISTING.STATES.EDITED' | translate}}: {{dataset.modified | date:"longDate"}}</div>
</div>
<div class="col-auto dataset-title">{{'DATASET-LISTING.DATASET-DESCRIPTION' | translate}}: {{dataset.label}}</div>
<div class="dataset-subtitle">
<span class="col-auto">{{ roleDisplay(dataset.users) }}</span>
<span>.</span>
<span class="col-auto" *ngIf="dataset.status === 1 && dataset.public === true"><span class="material-icons icon-align">public</span>{{'DATASET-LISTING.STATES.PUBLIC' | translate}}</span>
<span *ngIf="dataset.status === 1 && dataset.public === false" class="col-auto"><span class="material-icons icon-align">done</span>{{ enumUtils.toDmpStatusString(dataset.status) }}</span>
<span *ngIf="dataset.status === 0" class=" col-auto draft"><span class="material-icons icon-align">create</span>{{ enumUtils.toDmpStatusString(dataset.status) }}</span>
<span>.</span>
<span class="col">{{'DATASET-LISTING.COLUMNS.GRANT' | translate}}: {{dataset.grant}}</span>
</div>
<div class="d-flex flex-direction-row pt-3 pb-3">
<div class="col-auto dataset-subtitle">{{'DATASET-LISTING.TOOLTIP.PART-OF' | translate}}
<div class="col-auto dmp-label ml-4">{{'DATASET-LISTING.TOOLTIP.DMP' | translate}}</div>
</div>
<!-- <div class="col-auto dmp-label">{{'DATASET-LISTING.TOOLTIP.DMP' | translate}}</div> -->
<div class="col dmp-title">{{'DATASET-LISTING.TOOLTIP.DMP-FOR' | translate}}: {{dataset.dmp}}</div>
</div>
</a>
<div class="dataset-card-actions">
<a class="col-auto border-right pointer" [matMenuTriggerFor]="exportMenu"><span class="material-icons icon-align pr-2">open_in_new</span>{{'DATASET-LISTING.ACTIONS.EXPORT' | translate}}</a>
<a class="col-auto border-right pointer" (click)="openShareDialog(dataset.dmpId, dataset.dmp)"><span class="material-icons icon-align pr-2">group_add</span>{{'DATASET-LISTING.ACTIONS.INVITE-COLLABORATORS' | translate}}</a>
<a class="col-auto pointer" [matMenuTriggerFor]="actionsMenu"><span class="material-icons icon-align pl-2">more_horiz</span></a>
<!-- <a class="col-auto" [matMenuTriggerFor]="actionsMenu" *ngIf="!publicMode"><span class="material-icons icon-align pl-2">more_horiz</span></a> -->
</div>
<mat-menu #actionsMenu="matMenu">
<button mat-menu-item (click)="openDmpSearchDialogue(dataset.id)" class="menu-item">
<mat-icon>file_copy</mat-icon>{{'DATASET-WIZARD.ACTIONS.COPY-DATASET' | translate}}
</button>
<button mat-menu-item (click)="openConfirm(dataset.id)" class="menu-item">
<mat-icon>delete</mat-icon>{{ 'DATASET-WIZARD.ACTIONS.DELETE' | translate }}
</button>
<!-- <button mat-menu-item *ngIf="needsUpdate(activity)" class="menu-item" (click)="openUpdateDatasetProfileDialogue(activity.id);">
<mat-icon>update</mat-icon>
{{ 'DATASET-WIZARD.ACTIONS.UPDATE-DATASET-PROFILE' | translate }}
</button> -->
</mat-menu>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item (click)="downloadPDF(dataset)">
<i class="fa fa-file-pdf-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.PDF' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadDOCX(dataset)">
<i class="fa fa-file-word-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.DOC' | translate}}</span>
</button>
<button mat-menu-item (click)="downloadXML(dataset)">
<i class="fa fa-file-code-o pr-2"></i>
<span>{{'GENERAL.FILE-TYPES.XML' | translate}}</span>
</button>
</mat-menu>
</div>
<!-- Version 0 -->
<!-- <div class="listing-item" *ngIf="!isDeleted">
<a [routerLink]="getItemLink()"> <a [routerLink]="getItemLink()">
<div class="col"> <div class="col">
<div class="row"> <div class="row">
<div class="col-12 gray-container container-header"> <div class="col-12 gray-container container-header">
<p (click)="$event.stopImmediatePropagation();">{{ dataset.grantAbbreviation }}</p> <p (click)="$event.stopImmediatePropagation();">{{ dataset.grantAbbreviation }}</p> -->
<!-- <p (click)="$event.stopImmediatePropagation(); grantClicked(dataset)">{{ dataset.grantAbbreviation }}</p> --> <!-- <p (click)="$event.stopImmediatePropagation(); grantClicked(dataset)">{{ dataset.grantAbbreviation }}</p> -->
<!-- <button mat-icon-button [matMenuTriggerFor]="actionsMenu" class="ml-auto" (click)="$event.stopImmediatePropagation();"> <!-- <button mat-icon-button [matMenuTriggerFor]="actionsMenu" class="ml-auto" (click)="$event.stopImmediatePropagation();">
<mat-icon class="more-horiz">more_horiz</mat-icon> <mat-icon class="more-horiz">more_horiz</mat-icon>
</button> --> </button> -->
</div> <!-- </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-auto"> <div class="col-auto">
@ -72,7 +133,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div> -->
<!-- <div class="info"> <!-- <div class="info">
<h6>{{ dataset.dmp }}</h6> <h6>{{ dataset.dmp }}</h6>
<p>{{ dataset.grant }}</p> <p>{{ dataset.grant }}</p>
@ -82,7 +143,7 @@
<p>{{ dataset.profile }}</p> <p>{{ dataset.profile }}</p>
</div> </div>
</div> --> </div> -->
</div> <!-- </div>
</a> </a>
</div> </div> -->
<!-- <mat-divider *ngIf="showDivider"></mat-divider> --> <!-- <mat-divider *ngIf="showDivider"></mat-divider> -->

View File

@ -76,3 +76,174 @@ p {
.finalized-bookmark { .finalized-bookmark {
color: #08bd63; color: #08bd63;
} }
.dmp-card,
.dataset-card {
min-width: 712px;
/* min-height: 308px; */
background: #ffffff 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #0000001a;
border-radius: 4px;
opacity: 1;
margin-top: 2.43rem;
margin-bottom: 1rem;
}
.remove-border-bottom ::ng-deep .mat-tab-header {
border-bottom: none;
}
input[type="text"] {
background: #fafafa 0% 0% no-repeat padding-box;
border: 1px solid #d1d1d1;
border-radius: 4px;
opacity: 1;
width: 347px;
height: 56px;
font-family: Arial, FontAwesome;
padding-left: 15px;
}
.edited-date {
text-align: left;
font-weight: 300;
font-family: "Roboto", sans-serif;
line-height: 2.4;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.dmp-label {
background: #129d99 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
opacity: 1;
width: 67px;
height: 37px;
color: #ffffff;
line-height: 2.4;
opacity: 0.75;
}
.dataset-label {
width: 158px;
height: 37px;
background: #f7dd72 0% 0% no-repeat padding-box;
border-radius: 4px 0px;
text-align: left;
line-height: 2.8;
font-size: 0.875rem;
font-weight: 400;
letter-spacing: 0px;
color: #212121;
opacity: 0.75;
}
.dmp-title,
.dataset-title {
text-align: left;
font-weight: 500;
font-family: "Roboto", sans-serif;
font-size: 1rem;
opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #212121;
}
.dataset-subtitle,
.dmp-subtitle {
display: flex;
flex-direction: row;
text-align: left;
font-weight: 400;
font-family: "Roboto", sans-serif;
font-size: 0.875rem;
opacity: 1;
align-items: center;
color: #848484;
}
.dmp-title-draft {
text-align: left;
font-weight: 500;
font-family: "Roboto", sans-serif;
font-size: 1rem;
opacity: 0.81;
padding-top: 0.75rem;
padding-bottom: 0.55rem;
color: #f16868;
}
.icon-align {
display: inline-flex;
vertical-align: middle;
padding-bottom: 0.4rem;
}
.dataset-card-actions,
.dmp-card-actions {
display: flex;
flex-direction: row;
border-top: 1px solid #dbdbdb;
line-height: 4;
color: #848484;
}
.dataset-card-actions a,
.dmp-card-actions a {
color: #848484 !important;
text-decoration: none !important;
}
.dataset-card-actions a:hover,
.dmp-card-actions a:hover {
color: #129d99 !important;
}
.dmp-dataset-descriptions-title {
color: #000000;
opacity: 0.6;
padding-top: 1.5rem;
padding-bottom: 0.8rem;
}
.dmp-dataset-descriptions-name {
color: #000000;
opacity: 0.6;
font-weight: 700;
}
.show-more {
color: black !important;
}
.show-more:hover {
color: #129d99 !important;
}
.btn-load-more {
border: 2px solid #212121;
border-radius: 30px;
opacity: 1;
width: 132px;
height: 40px;
margin-top: 4.125rem;
}
.btn-load-more:hover {
background-color: black;
color: white;
}
.draft {
color: #f16868;
}
.pointer {
cursor: pointer;
}
::ng-deep .mat-menu-panel {
max-width: 282px !important;
}

View File

@ -2,13 +2,28 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing'; import { DatasetListingModel } from '../../../../core/model/dataset/dataset-listing';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { DatasetStatus } from '../../../../core/common/enum/dataset-status'; import { DatasetStatus } from '../../../../core/common/enum/dataset-status';
import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
import { DatasetWizardService } from '@app/core/services/dataset-wizard/dataset-wizard.service';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import * as FileSaver from 'file-saver';
import { DmpInvitationDialogComponent } from '@app/ui/dmp/invitation/dmp-invitation.component';
import { MatDialog } from '@angular/material';
import { DatasetCopyDialogueComponent } from '../../dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.component';
import { FormControl } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { Principal } from '@app/core/model/auth/principal';
import { AuthService } from '@app/core/services/auth/auth.service';
@Component({ @Component({
selector: 'app-dataset-listing-item-component', selector: 'app-dataset-listing-item-component',
templateUrl: './dataset-listing-item.component.html', templateUrl: './dataset-listing-item.component.html',
styleUrls: ['./dataset-listing-item.component.scss'] styleUrls: ['./dataset-listing-item.component.scss']
}) })
export class DatasetListingItemComponent implements OnInit { export class DatasetListingItemComponent extends BaseComponent implements OnInit {
@Input() dataset: DatasetListingModel; @Input() dataset: DatasetListingModel;
@Input() showDivider: boolean = true; @Input() showDivider: boolean = true;
@ -18,19 +33,29 @@ export class DatasetListingItemComponent implements OnInit {
isDraft: boolean; isDraft: boolean;
isDeleted: boolean; isDeleted: boolean;
constructor(private router: Router) { } constructor(
private router: Router,
public enumUtils: EnumUtils,
private datasetWizardService: DatasetWizardService,
public dialog: MatDialog,
private language: TranslateService,
private authentication: AuthService,
private uiNotificationService: UiNotificationService
) {
super();
}
ngOnInit() { ngOnInit() {
if (this.dataset.status === DatasetStatus.Draft) { if (this.dataset.status === DatasetStatus.Draft) {
this.isDraft = true; this.isDraft = true;
this.isDeleted = false; this.isDeleted = false;
} else if (this.dataset.status === DatasetStatus.Deleted) { } else if (this.dataset.status === DatasetStatus.Deleted) {
this.isDeleted = true; this.isDeleted = true;
} }
else { else {
this.isDraft = false; this.isDraft = false;
this.isDeleted = false; this.isDeleted = false;
} }
} }
getItemLink(): string[] { getItemLink(): string[] {
@ -41,6 +66,152 @@ export class DatasetListingItemComponent implements OnInit {
return this.isPublic ? [`/explore-plans/publicOverview/${this.dataset.dmpId}`] : [`/plans/edit/${this.dataset.dmpId}`]; return this.isPublic ? [`/explore-plans/publicOverview/${this.dataset.dmpId}`] : [`/plans/edit/${this.dataset.dmpId}`];
} }
downloadPDF(dataset: DatasetListingModel): void {
this.datasetWizardService.downloadPDF(dataset.id as string)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/pdf' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
});
}
downloadDOCX(dataset: DatasetListingModel): void {
this.datasetWizardService.downloadDOCX(dataset.id as string)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/msword' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
});
}
downloadXML(dataset: DatasetListingModel): void {
this.datasetWizardService.downloadXML(dataset.id as string)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
});
}
getFilenameFromContentDispositionHeader(header: string): string {
const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);
const matches = header.match(regex);
let filename: string;
for (let i = 0; i < matches.length; i++) {
const match = matches[i];
if (match.includes('filename="')) {
filename = match.substring(10, match.length - 1);
break;
} else if (match.includes('filename=')) {
filename = match.substring(9);
break;
}
}
return filename;
}
openShareDialog(dmpRowId: any, dmpRowName: any, activity: any) {
const dialogRef = this.dialog.open(DmpInvitationDialogComponent, {
// height: '250px',
// width: '700px',
restoreFocus: false,
data: {
dmpId: dmpRowId,
dmpName: dmpRowName
}
});
}
openDmpSearchDialogue(dataset: DatasetListingModel) {
const formControl = new FormControl();
const dialogRef = this.dialog.open(DatasetCopyDialogueComponent, {
width: '500px',
restoreFocus: false,
data: {
formControl: formControl,
datasetId: dataset.id,
datasetProfileId: dataset.profile,
datasetProfileExist: false,
confirmButton: this.language.instant('DATASET-WIZARD.DIALOGUE.COPY'),
cancelButton: this.language.instant('DATASET-WIZARD.DIALOGUE.CANCEL')
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed))
.subscribe(result => {
if (result && result.datasetProfileExist) {
const newDmpId = result.formControl.value.id
this.router.navigate(['/datasets/copy/' + result.datasetId], { queryParams: { newDmpId: newDmpId } });
}
});
}
openConfirm(id: string): void {
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
maxWidth: '300px',
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.DELETE'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
isDeleteConfirmation: true
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
this.datasetWizardService.delete(id)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => this.onCallbackSuccess(),
// error => this.onCallbackError(error)
);
}
});
}
onCallbackSuccess(id?: String): void {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
id ? this.router.navigate(['/reload']).then(() => { this.router.navigate(['/datasets', 'edit', id]); }) : this.router.navigate(['/datasets']);
}
roleDisplay(value: any) {
const principal: Principal = this.authentication.current();
let role: number;
if (principal) {
value.forEach(element => {
if (principal.id === element.id) {
role = element.role;
}
});
}
if (role === 0) {
return this.language.instant('DMP-LISTING.OWNER');
}
else if (role === 1) {
return this.language.instant('DMP-LISTING.MEMBER');
}
else {
return this.language.instant('DMP-LISTING.OWNER');
}
}
// onCallbackError(error: any) {
// this.setErrorModel(error.error);
// }
// public setErrorModel(validationErrorModel: ValidationErrorModel) {
// Object.keys(validationErrorModel).forEach(item => {
// (<any>this.dataset.validationErrorModel)[item] = (<any>validationErrorModel)[item];
// });
// }
// grantClicked(dataset: DatasetListingModel) { // grantClicked(dataset: DatasetListingModel) {
// this.router.navigate(['/grants/edit/' + dataset.grantId]); // this.router.navigate(['/grants/edit/' + dataset.grantId]);

View File

@ -29,7 +29,7 @@
<h6 class="category-title">{{ 'FACET-SEARCH.GRANT-STATUS.TITLE' | translate }}</h6> <h6 class="category-title">{{ 'FACET-SEARCH.GRANT-STATUS.TITLE' | translate }}</h6>
<mat-radio-group [formControl]="formGroup.get('grantStatus')"> <mat-radio-group [formControl]="formGroup.get('grantStatus')">
<mat-list-item> <mat-list-item>
<mat-radio-button value="null" checked>{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ANY' | translate }}</mat-radio-button> <mat-radio-button value="null" [checked]="!formGroup.get('grantStatus').value">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ANY' | translate }}</mat-radio-button>
</mat-list-item> </mat-list-item>
<mat-list-item> <mat-list-item>
<mat-radio-button value="0">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ACTIVE' | translate }}</mat-radio-button> <mat-radio-button value="0">{{ 'FACET-SEARCH.GRANT-STATUS.OPTIONS.ACTIVE' | translate }}</mat-radio-button>

View File

@ -8,14 +8,16 @@
<p class="mt-4 pt-2">{{'DMP-LISTING.TEXT-INFO-QUESTION' | translate}} <u>{{'DMP-LISTING.LINK-ZENODO' | translate}}</u> {{'DMP-LISTING.GET-IDEA' | translate}}</p> <p class="mt-4 pt-2">{{'DMP-LISTING.TEXT-INFO-QUESTION' | translate}} <u>{{'DMP-LISTING.LINK-ZENODO' | translate}}</u> {{'DMP-LISTING.GET-IDEA' | translate}}</p>
</div> </div>
</div> </div>
<div class="filter-btn" [style.right]="dialog.openDialogs.length > 0 ? '446px' : '0px'" [style.width]="hasScrollbar() ? '52px' : '37px'" (click)="openFiltersDialog()"><button mat-raised-button class="p-0"> <div class="filter-btn" [style.right]="dialog.openDialogs.length > 0 ? '446px' : '0px'" [style.width]="hasScrollbar() ? '52px' : '37px'" (click)="openFiltersDialog()">
<button mat-raised-button class="p-0">
<mat-icon class="mr-4">filter_alt</mat-icon> <mat-icon class="mr-4">filter_alt</mat-icon>
</button></div> </button>
</div>
</div> </div>
<div> <div>
<div class="listing row pb-2"> <div class="listing row pb-2">
<!-- Search Filter--> <!-- Search Filter-->
<mat-form-field appearance="outline" class="search-form ml-auto col-auto" floatLabel="never"> <mat-form-field *ngIf="listingItems.length > 0" appearance="outline" class="search-form ml-auto col-auto" floatLabel="never">
<mat-icon matSuffix>search</mat-icon> <mat-icon matSuffix>search</mat-icon>
<input matInput placeholder="{{'CRITERIA.DMP.LIKE'| translate}}" name="likeCriteria" [formControl]="formGroup.get('like')"> <input matInput placeholder="{{'CRITERIA.DMP.LIKE'| translate}}" name="likeCriteria" [formControl]="formGroup.get('like')">
<mat-error *ngIf="formGroup.get('like').hasError('backendError')">{{formGroup.get('like').getError('backendError').message}}</mat-error> <mat-error *ngIf="formGroup.get('like').hasError('backendError')">{{formGroup.get('like').getError('backendError').message}}</mat-error>
@ -29,6 +31,9 @@
<button type="button" class="btn-load-more" (click)="loadMore()">{{'GENERAL.ACTIONS.LOAD-MORE' | translate}}</button> <button type="button" class="btn-load-more" (click)="loadMore()">{{'GENERAL.ACTIONS.LOAD-MORE' | translate}}</button>
</div> </div>
</div> </div>
<div class="col-md-12 d-flex justify-content-center" *ngIf="listingItems.length === 0">
<span class="empty-list">{{'DMP-LISTING.EMPTY-LIST' | translate}}</span>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -129,7 +129,7 @@
.card-content { .card-content {
text-align: left; text-align: left;
font: Light 16px/26px Roboto; font-weight: 300;
letter-spacing: 0px; letter-spacing: 0px;
color: #212121; color: #212121;
padding-left: 40px; padding-left: 40px;
@ -202,16 +202,33 @@
.search-form { .search-form {
// font-size: 12px; // font-size: 12px;
text-align: left; text-align: left;
width: 17.5rem; width: 20rem;
} }
.search-form mat-icon { .search-form mat-icon {
color: #129d99; color: #129d99;
} }
.empty-list {
text-align: center;
font-weight: 300;
font-size: 1.25rem;
letter-spacing: 0px;
color: #212121;
opacity: 0.6;
}
.pointer:hover {
color: #00b29f;
}
::ng-deep .search-form .mat-form-field-wrapper { ::ng-deep .search-form .mat-form-field-wrapper {
background-color: white !important; background-color: white !important;
padding-bottom: 0 !important; padding-bottom: 0 !important;
}
::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
padding: 0.3rem 0rem 0.6rem 0rem !important;
} }
// .bot-paginator { // .bot-paginator {

View File

@ -57,7 +57,7 @@ export class DmpListingComponent extends BaseComponent implements OnInit, IBread
criteriaFormGroup: FormGroup; criteriaFormGroup: FormGroup;
public formGroup = new FormBuilder().group({ public formGroup = new FormBuilder().group({
like: new FormControl() like: new FormControl()
}) });
constructor( constructor(
private dmpService: DmpService, private dmpService: DmpService,

View File

@ -40,7 +40,6 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
public enumUtils: EnumUtils, public enumUtils: EnumUtils,
private dmpService: DmpService, private dmpService: DmpService,
private language: TranslateService, private language: TranslateService,
private translate: TranslateService,
private uiNotificationService: UiNotificationService) { private uiNotificationService: UiNotificationService) {
super(); super();
} }
@ -110,13 +109,13 @@ export class DmpListingItemComponent extends BaseComponent implements OnInit {
}); });
} }
if (role === 0) { if (role === 0) {
return this.translate.instant('DMP-LISTING.OWNER'); return this.language.instant('DMP-LISTING.OWNER');
} }
else if (role === 1) { else if (role === 1) {
return this.translate.instant('DMP-LISTING.MEMBER'); return this.language.instant('DMP-LISTING.MEMBER');
} }
else { else {
return this.translate.instant('DMP-LISTING.OWNER'); return this.language.instant('DMP-LISTING.OWNER');
} }
} }

View File

@ -130,11 +130,11 @@ export class ExploreDmpFiltersComponent extends BaseCriteriaComponent implements
} }
OnChange($event) { OnChange($event) {
console.log($event); // console.log($event);
} }
OnIndeterminateChange($event) { OnIndeterminateChange($event) {
console.log($event); // console.log($event);
} }
controlModified() { controlModified() {

View File

@ -454,7 +454,8 @@
"INVOLVED-DATASETS": "Involved Dataset Descriptions", "INVOLVED-DATASETS": "Involved Dataset Descriptions",
"TEMPLATES-INVOLVED": "Dataset Description Templates Involved" "TEMPLATES-INVOLVED": "Dataset Description Templates Involved"
}, },
"VIEW-ALL-VERSIONS": "All versions of" "VIEW-ALL-VERSIONS": "All versions of",
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-PUBLIC-LISTING": { "DMP-PUBLIC-LISTING": {
"TITLE": "Published Data Management Plans", "TITLE": "Published Data Management Plans",
@ -466,7 +467,8 @@
"PUBLISHED": "Public access - Closed DMP", "PUBLISHED": "Public access - Closed DMP",
"INVOLVED-DATASETS": "Involved Dataset Descriptions", "INVOLVED-DATASETS": "Involved Dataset Descriptions",
"TEMPLATES-INVOLVED": "Dataset Description Templates Involved" "TEMPLATES-INVOLVED": "Dataset Description Templates Involved"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-UPLOAD": { "DMP-UPLOAD": {
"TITLE": "Import Data Management Plan", "TITLE": "Import Data Management Plan",
@ -580,6 +582,10 @@
"DATASET-DESCRIPTION": "Dataset Description", "DATASET-DESCRIPTION": "Dataset Description",
"SELECT-DATASETS-TO-CLONE": "Select which datasets to include in the new DMP. Selected datasets will be editable.", "SELECT-DATASETS-TO-CLONE": "Select which datasets to include in the new DMP. Selected datasets will be editable.",
"SELECT-DATASETS-NONE": "Not available Dataset Descriptions for this DMP.", "SELECT-DATASETS-NONE": "Not available Dataset Descriptions for this DMP.",
"TEXT-INFO": "Datasets are documented following pre-defined templates which set the content of dataset descriptions. In Argos, a DMP can contain as many dataset descriptions as the datasets it documents. Browse ",
"TEXT-INFO-REST": " for a look at datasets described in Argos DMPs",
"LINK-PUBLIC-DATASETS": "Public Dataset Descriptions",
"TEXT-INFO-PAR": "New datasets can be added to existing DMPs at any time and be described with more than one template. Dataset descriptions can also be cloned and re-used in other DMPs as well as be deleted without negatively affecting the DMP as a whole.",
"COLUMNS": { "COLUMNS": {
"NAME": "Name", "NAME": "Name",
"REFERNCE": "Reference", "REFERNCE": "Reference",
@ -622,7 +628,8 @@
"VERSION": "DMP Version", "VERSION": "DMP Version",
"PART-OF": "Part of", "PART-OF": "Part of",
"DMP-FOR": "DMP for" "DMP-FOR": "DMP for"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PUBLIC-LISTING": { "DATASET-PUBLIC-LISTING": {
"TITLE": "Published Dataset Descriptions", "TITLE": "Published Dataset Descriptions",
@ -631,7 +638,8 @@
"DMP": "DMP", "DMP": "DMP",
"GRANT": "Grant", "GRANT": "Grant",
"TEMPLATES-INVOLVED": "Dataset Description Template" "TEMPLATES-INVOLVED": "Dataset Description Template"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PROFILE-LISTING": { "DATASET-PROFILE-LISTING": {
"TITLE": "Dataset Description Templates", "TITLE": "Dataset Description Templates",

View File

@ -452,7 +452,8 @@
"INVOLVED-DATASETS": "Descripciones del Dataset implicadas", "INVOLVED-DATASETS": "Descripciones del Dataset implicadas",
"TEMPLATES-INVOLVED": "Plantillas de descripción del Dataset implicadas" "TEMPLATES-INVOLVED": "Plantillas de descripción del Dataset implicadas"
}, },
"VIEW-ALL-VERSIONS": "Todas las versiones de" "VIEW-ALL-VERSIONS": "Todas las versiones de",
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-PUBLIC-LISTING": { "DMP-PUBLIC-LISTING": {
"TITLE": "Plan de Gestión de Datos publicado", "TITLE": "Plan de Gestión de Datos publicado",
@ -464,7 +465,8 @@
"PUBLISHED": "Acceso público - PGD cerrado", "PUBLISHED": "Acceso público - PGD cerrado",
"INVOLVED-DATASETS": "Descripciones del Dataset implicadas", "INVOLVED-DATASETS": "Descripciones del Dataset implicadas",
"TEMPLATES-INVOLVED": "Plantillas del Dataset implicadas" "TEMPLATES-INVOLVED": "Plantillas del Dataset implicadas"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-UPLOAD": { "DMP-UPLOAD": {
"TITLE": "Importar Plan de Gestión de Datos", "TITLE": "Importar Plan de Gestión de Datos",
@ -578,6 +580,10 @@
"DATASET-DESCRIPTION": "Descripción del Dataset", "DATASET-DESCRIPTION": "Descripción del Dataset",
"SELECT-DATASETS-TO-CLONE": "Seleccione qué datasets incluye en el nuevo PDG. Los datasets será editables.", "SELECT-DATASETS-TO-CLONE": "Seleccione qué datasets incluye en el nuevo PDG. Los datasets será editables.",
"SELECT-DATASETS-NONE": "Las descripciones del Dataset no está disponibles para este PGD.", "SELECT-DATASETS-NONE": "Las descripciones del Dataset no está disponibles para este PGD.",
"TEXT-INFO": "Datasets are documented following pre-defined templates which set the content of dataset descriptions. In Argos, a DMP can contain as many dataset descriptions as the datasets it documents. Browse ",
"TEXT-INFO-REST": " for a look at datasets described in Argos DMPs",
"LINK-PUBLIC-DATASETS": "Public Dataset Descriptions",
"TEXT-INFO-PAR": "New datasets can be added to existing DMPs at any time and be described with more than one template. Dataset descriptions can also be cloned and re-used in other DMPs as well as be deleted without negatively affecting the DMP as a whole.",
"COLUMNS": { "COLUMNS": {
"NAME": "Nombre", "NAME": "Nombre",
"REFERNCE": "Referencia", "REFERNCE": "Referencia",
@ -618,7 +624,8 @@
"GRANT": "Subvención", "GRANT": "Subvención",
"TEMPLATES-INVOLVED": "Dataset Description Template", "TEMPLATES-INVOLVED": "Dataset Description Template",
"VERSION": "PGD Versión" "VERSION": "PGD Versión"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PUBLIC-LISTING": { "DATASET-PUBLIC-LISTING": {
"TITLE": "Descripción del Dataset publicada", "TITLE": "Descripción del Dataset publicada",
@ -627,7 +634,8 @@
"DMP": "PGD", "DMP": "PGD",
"GRANT": "Subvención", "GRANT": "Subvención",
"TEMPLATES-INVOLVED": "Plantilla de descripción del Dataset" "TEMPLATES-INVOLVED": "Plantilla de descripción del Dataset"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PROFILE-LISTING": { "DATASET-PROFILE-LISTING": {
"TITLE": "Plantillas de descripción del Dataset", "TITLE": "Plantillas de descripción del Dataset",

View File

@ -453,7 +453,8 @@
"INVOLVED-DATASETS": "Εμπλεκόμενες Περιγραφές Συνόλων Δεδομένων", "INVOLVED-DATASETS": "Εμπλεκόμενες Περιγραφές Συνόλων Δεδομένων",
"TEMPLATES-INVOLVED": "Εμπλεκόμενα Templates Περιγραφών Συνόλων Δεδομένων" "TEMPLATES-INVOLVED": "Εμπλεκόμενα Templates Περιγραφών Συνόλων Δεδομένων"
}, },
"VIEW-ALL-VERSIONS": "Όλες οι εκδόσεις" "VIEW-ALL-VERSIONS": "Όλες οι εκδόσεις",
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-PUBLIC-LISTING": { "DMP-PUBLIC-LISTING": {
"TITLE": "Δημοσιευμένα Σχέδια Διαχείρισης Δεδομένων", "TITLE": "Δημοσιευμένα Σχέδια Διαχείρισης Δεδομένων",
@ -465,7 +466,8 @@
"PUBLISHED": "Δημόσια Πρόσβαση - Κλειστό Σχέδιο Διαχείρισης Δεδομένων", "PUBLISHED": "Δημόσια Πρόσβαση - Κλειστό Σχέδιο Διαχείρισης Δεδομένων",
"INVOLVED-DATASETS": "Εμπλεκόμενες Περιγραφές Συνόλων Δεδομένων", "INVOLVED-DATASETS": "Εμπλεκόμενες Περιγραφές Συνόλων Δεδομένων",
"TEMPLATES-INVOLVED": "Εμπλεκόμενα Templates Περιγραφών Συνόλων Δεδομένων" "TEMPLATES-INVOLVED": "Εμπλεκόμενα Templates Περιγραφών Συνόλων Δεδομένων"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DMP-UPLOAD": { "DMP-UPLOAD": {
"TITLE": "Εισαγωγή Σχεδίου Διαχείρισης Δεδομένων", "TITLE": "Εισαγωγή Σχεδίου Διαχείρισης Δεδομένων",
@ -579,6 +581,10 @@
"DATASET-DESCRIPTION": "Περιγραφή Δεδομένων", "DATASET-DESCRIPTION": "Περιγραφή Δεδομένων",
"SELECT-DATASETS-TO-CLONE": "Επιλογή των συνόλων δεδομένων που θα συμπεριληφθούν στο νέο Σχέδιο Διαχείρισης Δεδομένων. Τα επιλεγμένα σύνολα δεδομένα θα είναι επεξεργάσιμα.", "SELECT-DATASETS-TO-CLONE": "Επιλογή των συνόλων δεδομένων που θα συμπεριληφθούν στο νέο Σχέδιο Διαχείρισης Δεδομένων. Τα επιλεγμένα σύνολα δεδομένα θα είναι επεξεργάσιμα.",
"SELECT-DATASETS-NONE": "Μη διαθέσιμες Περιγραφές Συνόλου Δεδομένων για αυτό το Σχέδιο Διαχείρισης Δεδομένων", "SELECT-DATASETS-NONE": "Μη διαθέσιμες Περιγραφές Συνόλου Δεδομένων για αυτό το Σχέδιο Διαχείρισης Δεδομένων",
"TEXT-INFO": "Datasets are documented following pre-defined templates which set the content of dataset descriptions. In Argos, a DMP can contain as many dataset descriptions as the datasets it documents. Browse ",
"TEXT-INFO-REST": " for a look at datasets described in Argos DMPs",
"LINK-PUBLIC-DATASETS": "Public Dataset Descriptions",
"TEXT-INFO-PAR": "New datasets can be added to existing DMPs at any time and be described with more than one template. Dataset descriptions can also be cloned and re-used in other DMPs as well as be deleted without negatively affecting the DMP as a whole.",
"COLUMNS": { "COLUMNS": {
"NAME": "Τίτλος", "NAME": "Τίτλος",
"REFERNCE": "Αναφορά", "REFERNCE": "Αναφορά",
@ -619,7 +625,8 @@
"GRANT": "Επιχορήγηση", "GRANT": "Επιχορήγηση",
"TEMPLATES-INVOLVED": "Template Περιγραφής Συνόλου Δεδομένων", "TEMPLATES-INVOLVED": "Template Περιγραφής Συνόλου Δεδομένων",
"VERSION": "Έκδοση Σχεδίου Διαχείρισης Δεδομένων" "VERSION": "Έκδοση Σχεδίου Διαχείρισης Δεδομένων"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PUBLIC-LISTING": { "DATASET-PUBLIC-LISTING": {
"TITLE": "Δημοσιευμένες Περιγραφές Συνόλων Δεδομένων", "TITLE": "Δημοσιευμένες Περιγραφές Συνόλων Δεδομένων",
@ -628,7 +635,8 @@
"DMP": "Σχέδιο Διαχείρισης Δεδομένων", "DMP": "Σχέδιο Διαχείρισης Δεδομένων",
"GRANT": "Επιχορήγηση", "GRANT": "Επιχορήγηση",
"TEMPLATES-INVOLVED": "Template Περιγραφής Συνόλου Δεδομένων" "TEMPLATES-INVOLVED": "Template Περιγραφής Συνόλου Δεδομένων"
} },
"EMPTY-LIST": "Nothing here yet."
}, },
"DATASET-PROFILE-LISTING": { "DATASET-PROFILE-LISTING": {
"TITLE": "Templates Περιγραφής Συνόλου Δεδομένων", "TITLE": "Templates Περιγραφής Συνόλου Δεδομένων",