Introduced Facet Search Component On Dataset Public Listing

dmp-editor
Ioannis Kalyvas 6 years ago
parent e0c302e67e
commit b8c78e7135

@ -20,6 +20,8 @@ public class DatasetPublicTableRequest extends TableQuery<DatasetPublicCriteria,
query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("dmp").get("version"), query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("dmp").get("version"),
query.<String>subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.equal(externalRoot.get("dmp").get("groupId"), nestedRoot.get("dmp").get("groupId")), query.<String>subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.equal(externalRoot.get("dmp").get("groupId"), nestedRoot.get("dmp").get("groupId")),
Arrays.asList(new SelectionField(FieldSelectionType.COMPOSITE_FIELD, "dmp:version")), String.class))); Arrays.asList(new SelectionField(FieldSelectionType.COMPOSITE_FIELD, "dmp:version")), String.class)));
if (this.getCriteria().getLike() != null && !this.getCriteria().getLike().isEmpty())
query.where((builder, root) -> builder.like(root.get("label"), "%" + this.getCriteria().getLike() + "%"));
if (this.getCriteria().projects != null && !this.getCriteria().projects.isEmpty()) if (this.getCriteria().projects != null && !this.getCriteria().projects.isEmpty())
query.where(((builder, root) -> root.get("dmp").get("project").get("id").in(this.getCriteria().projects))); query.where(((builder, root) -> root.get("dmp").get("project").get("id").in(this.getCriteria().projects)));
if (this.getCriteria().projectStatus != null) query if (this.getCriteria().projectStatus != null) query

@ -80,8 +80,7 @@ public class DatasetManager {
public DataTableData<DatasetListingModel> getPaged(ApiContext apiContext, DatasetPublicTableRequest datasetTableRequest, Principal principal) throws Exception { public DataTableData<DatasetListingModel> getPaged(ApiContext apiContext, DatasetPublicTableRequest datasetTableRequest, Principal principal) throws Exception {
datasetTableRequest.setQuery(apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetListingModel.class))); datasetTableRequest.setQuery(apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetListingModel.class)));
QueryableList<eu.eudat.data.entities.Dataset> pagedItems = PaginationManager.applyPaging(datasetTableRequest.applyCriteria(), datasetTableRequest); QueryableList<eu.eudat.data.entities.Dataset> pagedItems = PaginationManager.applyPaging(datasetTableRequest.applyCriteria(), datasetTableRequest);
DataTableData<DatasetListingModel> dataTable = new DataTableData<DatasetListingModel>(); DataTableData<DatasetListingModel> dataTable = new DataTableData<>();
CompletableFuture<List<DatasetListingModel>> itemsFuture = pagedItems. CompletableFuture<List<DatasetListingModel>> itemsFuture = pagedItems.
selectAsync(item -> new DatasetListingModel().fromDataModel(item)).whenComplete((resultList, throwable) -> { selectAsync(item -> new DatasetListingModel().fromDataModel(item)).whenComplete((resultList, throwable) -> {

@ -3,7 +3,8 @@
#eu.eudat.logic.security.portmapping.https = 7444 #eu.eudat.logic.security.portmapping.https = 7444
########################/Security######################################## ########################/Security########################################
server.port=8080 server.port=8080
server.tomcat.max-threads = 1000 server.tomcat.max-threads = 20
server.tomcat.max-connections = 10000
logging.file=/logs/spring-boot-logging.log logging.file=/logs/spring-boot-logging.log
##########################Persistence########################################## ##########################Persistence##########################################
database.driver-class-name=org.postgresql.Driver database.driver-class-name=org.postgresql.Driver

@ -3,8 +3,8 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
indent_style = space indent_style = tab
indent_size = 2 indent_size = 4
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true

@ -2,6 +2,7 @@ FROM johnpapa/angular-cli as angular
WORKDIR /app WORKDIR /app
COPY package.json /app/ COPY package.json /app/
RUN npm cache clear --force && npm install RUN npm cache clear --force && npm install
COPY ./ /app/ COPY ./ /app/
ARG env=dev ARG env=dev
ARG aot=--no-aot ARG aot=--no-aot

@ -9,4 +9,8 @@ server {
location /material/ { location /material/ {
alias /usr/share/nginx/static/; alias /usr/share/nginx/static/;
} }
location /.well-known/ {
alias /usr/share/nginx/wwwcert/;
}
} }

@ -1,9 +1,9 @@
import { NgModule } from "@angular/core"; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DatasetProfileRoutes } from "./dataset-profile.router"; import { DatasetProfileRoutes } from './dataset-profile.router';
import { RouterModule } from "@angular/router"; import { RouterModule } from '@angular/router';
import { FormComponent } from './form/form.component'; import { FormComponent } from './form/form.component';
//import { GroupFieldFormComponent } from './groupfield-form/groupfield-form.component'; //import { GroupFieldFormComponent } from './groupfield-form/groupfield-form.component';
@ -12,7 +12,7 @@ import { SectionFormComponent } from './section-form/section-form.component';
import { PageFormComponent } from './page-form/page-component'; import { PageFormComponent } from './page-form/page-component';
import { CompositeFieldFormComponent } from './compositefield-form/compositefield-form.component'; import { CompositeFieldFormComponent } from './compositefield-form/compositefield-form.component';
import { FieldFormComponent } from './field-form/field-form.component'; import { FieldFormComponent } from './field-form/field-form.component';
import { HttpClientModule, HttpClient } from "@angular/common/http"; import { HttpClientModule, HttpClient } from '@angular/common/http';
import { CheckBoxComponent } from '../shared/componentsAdmin/checkbox/checkbox-component'; import { CheckBoxComponent } from '../shared/componentsAdmin/checkbox/checkbox-component';
import { FreeTextData } from '../models/DataField/FreeTextData'; import { FreeTextData } from '../models/DataField/FreeTextData';
@ -23,63 +23,63 @@ import { RadioBoxComponent } from '../shared/componentsAdmin/radiobox/radiobox-c
import { WordlistComponent } from '../shared/componentsAdmin/wordlist/wordlist-component'; import { WordlistComponent } from '../shared/componentsAdmin/wordlist/wordlist-component';
import { AutocompleteComponent } from '../shared/componentsAdmin/autocomplete/autocomplete-component'; import { AutocompleteComponent } from '../shared/componentsAdmin/autocomplete/autocomplete-component';
import { ComboboxComponent } from '../shared/componentsAdmin/combobox/combobox-component'; import { ComboboxComponent } from '../shared/componentsAdmin/combobox/combobox-component';
import { SharedModule } from "../shared/shared.module"; import { SharedModule } from '../shared/shared.module';
import { DatasetProfilePreviewerComponent } from "./previewer/dataset-profile-previewer.component"; import { DatasetProfilePreviewerComponent } from './previewer/dataset-profile-previewer.component';
import { DynamicFormModule } from "../form/dynamic-form.module"; import { DynamicFormModule } from '../form/dynamic-form.module';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
FormsModule, FormsModule,
HttpClientModule, HttpClientModule,
ReactiveFormsModule, ReactiveFormsModule,
RouterModule, RouterModule,
SharedModule, SharedModule,
DynamicFormModule, DynamicFormModule,
RouterModule.forChild(DatasetProfileRoutes) RouterModule.forChild(DatasetProfileRoutes)
], ],
declarations: [ declarations: [
FormComponent, FormComponent,
//GroupFieldFormComponent, //GroupFieldFormComponent,
RuleFormComponent, RuleFormComponent,
SectionFormComponent, SectionFormComponent,
PageFormComponent, PageFormComponent,
CompositeFieldFormComponent, CompositeFieldFormComponent,
FieldFormComponent, FieldFormComponent,
TextAreaComponent, TextAreaComponent,
CheckBoxComponent, CheckBoxComponent,
BooleanDecisionComponent, BooleanDecisionComponent,
FreeTextComponent, FreeTextComponent,
ComboboxComponent, ComboboxComponent,
AutocompleteComponent, AutocompleteComponent,
WordlistComponent, WordlistComponent,
RadioBoxComponent, RadioBoxComponent,
DatasetProfilePreviewerComponent DatasetProfilePreviewerComponent
], ],
exports: [ exports: [
FormComponent, FormComponent,
//GroupFieldFormComponent, //GroupFieldFormComponent,
RuleFormComponent, RuleFormComponent,
SectionFormComponent, SectionFormComponent,
PageFormComponent, PageFormComponent,
CompositeFieldFormComponent, CompositeFieldFormComponent,
FieldFormComponent, FieldFormComponent,
TextAreaComponent, TextAreaComponent,
CheckBoxComponent, CheckBoxComponent,
BooleanDecisionComponent, BooleanDecisionComponent,
FreeTextComponent, FreeTextComponent,
ComboboxComponent, ComboboxComponent,
AutocompleteComponent, AutocompleteComponent,
WordlistComponent, WordlistComponent,
RadioBoxComponent RadioBoxComponent
], ],
providers: [ providers: [
], ],
entryComponents: [ entryComponents: [
DatasetProfilePreviewerComponent DatasetProfilePreviewerComponent
] ]
}) })

@ -2,13 +2,13 @@ import { RouterModule, Routes } from '@angular/router';
import { FormComponent } from 'app/dataset-profile-form/form/form.component'; import { FormComponent } from 'app/dataset-profile-form/form/form.component';
export const DatasetProfileRoutes: Routes = [ export const DatasetProfileRoutes: Routes = [
{ {
path: ':id', path: ':id',
component: FormComponent component: FormComponent
}, },
{ {
path: '', path: '',
component: FormComponent component: FormComponent
} }
]; ];

@ -1,18 +1,17 @@
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms' import { FormGroup } from '@angular/forms';
import { Rule } from 'app/models/datasetProfileAdmin/Rule'
@Component({ @Component({
selector: 'rule-form', selector: 'app-rule-form',
templateUrl: './rule.component.html', templateUrl: './rule.component.html',
styleUrls: ['./rule.component.scss'] styleUrls: ['./rule.component.scss']
}) })
export class RuleFormComponent { export class RuleFormComponent {
@Input() form: FormGroup; @Input() form: FormGroup;
@Input() dataModel: FormGroup; @Input() dataModel: FormGroup;
TargetValidation(){ TargetValidation() {
} }
} }

@ -1,15 +1,13 @@
<div class="container"> <div class="container ">
<h3 class="text-center">{{'DATASET-PUBLIC-LISTING.TITLE' | translate}} {{titlePrefix}}</h3>
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<app-facet (facetCriteriaChange)="onCriteriaChange($event)"> <app-facet (facetCriteriaChange)="onCriteriaChange($event)">
</app-facet> </app-facet>
</div> </div>
<div class="col-md-10"> <div class="col-md-9">
<div> <div>
<h3>{{'DATASET-PUBLIC-LISTING.TITLE' | translate}} {{titlePrefix}}</h3>
<app-datasets-criteria-component [isPublic]='true'></app-datasets-criteria-component> <app-datasets-criteria-component [isPublic]='true'></app-datasets-criteria-component>
<mat-card class="mat-card"> <mat-card class="mat-card">
<mat-card-header> <mat-card-header>

@ -2,7 +2,7 @@ import { BaseErrorModel } from '../error/BaseErrorModel';
import { BackendErrorValidator } from '../../utilities/validators/BackendErrorValidator'; import { BackendErrorValidator } from '../../utilities/validators/BackendErrorValidator';
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ValidationContext } from '../../utilities/validators/ValidationContext'; import { ValidationContext } from '../../utilities/validators/ValidationContext';
import { Serializable } from "../Serializable"; import { Serializable } from '../Serializable';
export class DatasetProfileModel implements Serializable<DatasetProfileModel> { export class DatasetProfileModel implements Serializable<DatasetProfileModel> {
public id: String; public id: String;
@ -29,4 +29,4 @@ export class DatasetProfileModel implements Serializable<DatasetProfileModel> {
//baseContext.validation.push({ key: 'id', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'id')] }); //baseContext.validation.push({ key: 'id', validators: [Validators.required, BackendErrorValidator(this.errorModel, 'id')] });
return baseContext; return baseContext;
} }
} }

@ -2,4 +2,4 @@ export interface ExternalSourcesItemModel {
id: String; id: String;
name: String; name: String;
description: String; description: String;
} }

@ -13,71 +13,71 @@ export class BreadCrumbResolverService {
private parentComponents = []; private parentComponents = [];
private breadCrumbs: Observable<BreadcrumbItem[]> = Observable.of([]); private breadCrumbs: Observable<BreadcrumbItem[]> = Observable.of([]);
constructor( constructor(
private router: Router, private router: Router,
private zone: NgZone private zone: NgZone
) { } ) { }
public push(component: any) { public push(component: any) {
let existingComponentIndex = this.activeComponents.map(x => x.constructor.name).indexOf(component.constructor.name); const existingComponentIndex = this.activeComponents.map(x => x.constructor.name).indexOf(component.constructor.name);
if (existingComponentIndex !== -1) this.activeComponents.splice(existingComponentIndex, 1) if (existingComponentIndex !== -1) { this.activeComponents.splice(existingComponentIndex, 1); }
this.activeComponents.push(component); this.activeComponents.push(component);
} }
public clear() { public clear() {
this.activeComponents.length = 0; this.activeComponents.length = 0;
this.breadCrumbs = Observable.of([]) this.breadCrumbs = Observable.of([]);
} }
public resolve(activatedRoute: ActivatedRoute): Observable<BreadcrumbItem[]> { public resolve(activatedRoute: ActivatedRoute): Observable<BreadcrumbItem[]> {
this.breadCrumbs = Observable.of([]) this.breadCrumbs = Observable.of([]);
let routeComponents = this.getComponentsFromRoute(activatedRoute, []); const routeComponents = this.getComponentsFromRoute(activatedRoute, []);
this.activeComponents.filter(x => routeComponents.indexOf(x.constructor.name) !== -1).forEach(x => { this.activeComponents.filter(x => routeComponents.indexOf(x.constructor.name) !== -1).forEach(x => {
if (x.hasOwnProperty('breadCrumbs')) { if (x.hasOwnProperty('breadCrumbs')) {
let componentItems = this.resolveDependentComponents((<IBreadCrumbComponent>x).breadCrumbs, []); const componentItems = this.resolveDependentComponents((<IBreadCrumbComponent>x).breadCrumbs, []);
this.breadCrumbs = Observable.of(componentItems); this.breadCrumbs = Observable.of(componentItems);
} }
}) });
return this.breadCrumbs; return this.breadCrumbs;
} }
private getComponentsFromRoute(activatedRoute: ActivatedRoute, routeComponents: any[]): any[] { private getComponentsFromRoute(activatedRoute: ActivatedRoute, routeComponents: any[]): any[] {
activatedRoute.children.forEach(x => { activatedRoute.children.forEach(x => {
if (x.children.length > 0) this.getComponentsFromRoute(x.children[0], routeComponents); if (x.children.length > 0) { this.getComponentsFromRoute(x.children[0], routeComponents); }
if (x.component) routeComponents.push(x.component['name']) if (x.component) { routeComponents.push(x.component['name']); }
}) });
if (activatedRoute.component) routeComponents.push(activatedRoute.component['name']) if (activatedRoute.component) { routeComponents.push(activatedRoute.component['name']); }
return routeComponents; return routeComponents;
} }
resolveDependentComponents(items: Observable<BreadcrumbItem[]>, components: any[]): any[] { resolveDependentComponents(items: Observable<BreadcrumbItem[]>, components: any[]): any[] {
items.subscribe(breadCrumbs => { items.subscribe(breadCrumbs => {
breadCrumbs.forEach(async item => { breadCrumbs.forEach(async item => {
let parentComponent = item.parentComponentName ? this.findComponent(item.parentComponentName) : null const parentComponent = item.parentComponentName ? this.findComponent(item.parentComponentName) : null;
if (parentComponent && parentComponent.hasOwnProperty('breadCrumbs')) { if (parentComponent && parentComponent.hasOwnProperty('breadCrumbs')) {
components = this.pushToStart(components, this.resolveDependentComponents((<IBreadCrumbComponent>parentComponent).breadCrumbs, components)) components = this.pushToStart(components, this.resolveDependentComponents((<IBreadCrumbComponent>parentComponent).breadCrumbs, components));
} else if (item.notFoundResolver) { } else if (item.notFoundResolver) {
components = this.pushToStart(components, item.notFoundResolver) components = this.pushToStart(components, item.notFoundResolver);
//components = this.pushToStart(components, [unresolvedComponentItems]) //components = this.pushToStart(components, [unresolvedComponentItems])
} }
}) });
components = this.pushToEnd(components, breadCrumbs); components = this.pushToEnd(components, breadCrumbs);
}) });
return components return components;
} }
private findComponent(componentName: string): any { private findComponent(componentName: string): any {
for (let i = 0; i < this.activeComponents.length; i++) { for (let i = 0; i < this.activeComponents.length; i++) {
if (this.activeComponents[i].constructor.name === componentName) return this.activeComponents[i]; if (this.activeComponents[i].constructor.name === componentName) { return this.activeComponents[i]; }
} }
return null return null;
} }
pushToStart(first: any[], second: any[]) { pushToStart(first: any[], second: any[]) {
return [].concat(second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) == -1), first); return [].concat(second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1), first);
} }
pushToEnd(first: any[], second: any[]) { pushToEnd(first: any[], second: any[]) {
return [].concat(first, second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) == -1)); return [].concat(first, second.filter(x => first.map(firstX => firstX.label).indexOf(x.label) === -1));
} }
} }

@ -22,27 +22,27 @@ export class DatasetService {
constructor(private http: BaseHttpService) { constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'datasets/'; this.actionUrl = HostConfiguration.Server + 'datasets/';
this.headers = new HttpHeaders(); this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json'); this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json'); this.headers = this.headers.set('Accept', 'application/json');
} }
getPaged(dataTableRequest: DataTableRequest<DatasetCriteria>): Observable<DataTableData<DatasetListingModel>> { getPaged(dataTableRequest: DataTableRequest<DatasetCriteria>): Observable<DataTableData<DatasetListingModel>> {
return this.http.post<DataTableData<DatasetListingModel>>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers }); return this.http.post<DataTableData<DatasetListingModel>>(this.actionUrl + 'getPaged', dataTableRequest, { headers: this.headers });
} }
getPublicPaged(dataTableRequest: DataTableRequest<FacetSearchCriteriaModel>): Observable<DataTableData<DatasetListingModel>> { getPublicPaged(dataTableRequest: DataTableRequest<FacetSearchCriteriaModel>): Observable<DataTableData<DatasetListingModel>> {
return this.http.post<DataTableData<DatasetListingModel>>(this.actionUrl + 'public/paged', dataTableRequest, { headers: this.headers }); return this.http.post<DataTableData<DatasetListingModel>>(this.actionUrl + 'public/paged', dataTableRequest, { headers: this.headers });
} }
makeDatasetPublic(id: String) { makeDatasetPublic(id: String) {
return this.http.get(this.actionUrl + 'makepublic/' + id, { headers: this.headers }) return this.http.get(this.actionUrl + 'makepublic/' + id, { headers: this.headers });
} }
getDatasetProfiles(): Observable<DatasetProfileModel[]> { getDatasetProfiles(): Observable<DatasetProfileModel[]> {
return this.http.get<DatasetProfileModel[]>(HostConfiguration.Server + 'datasetprofiles/getAll', { headers: this.headers }) return this.http.get<DatasetProfileModel[]>(HostConfiguration.Server + 'datasetprofiles/getAll', { headers: this.headers });
} }
} }

@ -0,0 +1,15 @@
<div *ngIf="searchEnabled">
<mat-form-field>
<input type="text" placeholder="{{ 'FACET-SEARCH.FILTER' | translate }}" matInput [formControl]="optionSearchControl">
</mat-form-field>
</div>
<mat-chip-list>
<mat-chip [removable]="removable" (removed)="removeOption(option)" *ngFor="let option of selectedOptions">{{ option }}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
<mat-selection-list #optionsList (selectionChange)="selectionChanged($event)">
<mat-list-option *ngFor="let option of (options | async) | slice:0:10" [value]="displayValue(option)" [selected]="isOptionSelected(option)">
<p>{{ displayLabel(option) }}</p>
</mat-list-option>
</mat-selection-list>

@ -0,0 +1,71 @@
import { Component, ViewEncapsulation, OnInit, Input, Output, ViewChild, EventEmitter } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { FormControl } from '@angular/forms';
import { MatSelectionList } from '@angular/material';
@Component({
selector: 'app-facet-section-component',
templateUrl: './facet-search-section.component.html',
styleUrls: ['./facet-search-section.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class FacetSearchSectionComponent implements OnInit {
@Input()
searchEnabled = false;
@Input()
filterOptions: (value) => Observable<any[]>;
@Input()
options: Observable<any[]> = Observable.of([]);
@Input()
displayTitleFunc: (value) => string;
@Input()
displayValueFunc: (value) => string;
@Output()
selectedChanged = new EventEmitter();
@Output()
optionRemoved = new EventEmitter();
optionSearchControl = new FormControl('');
private selectedOptions: any[] = [];
@ViewChild('optionsList') selectionList: MatSelectionList;
ngOnInit(): void {
this.optionSearchControl.valueChanges.subscribe(x => { if (this.filterOptions) { this.options = this.filterOptions(x); } });
}
public selectionChanged(event: any) {
this.selectedChanged.emit(event);
}
public removeOption(project) {
const list = this.selectionList.selectedOptions.selected.map(x => x.value);
const indexOfProject = list.indexOf(project);
if (this.selectionList.selectedOptions.selected[indexOfProject]) {
this.selectionList.selectedOptions.selected[indexOfProject].selected = false;
this.selectionList.selectedOptions.selected.splice(indexOfProject, 1);
}
this.optionRemoved.emit(project);
}
public isOptionSelected(value) {
return this.selectedOptions.indexOf(value) !== -1;
}
displayLabel(value) {
return this.displayTitleFunc ? this.displayTitleFunc(value) : value;
}
displayValue(value) {
return this.displayValueFunc ? this.displayValueFunc(value) : value;
}
}

@ -1,35 +1,70 @@
<div> <mat-accordion>
<mat-selection-list #project role="listbox" (selectionChange)="projectStatusChanged($event)"> <mat-expansion-panel>
<h3 matSubheader>{{ 'FACET-SEARCH.PROJECT-STATUS.TITLE' | translate }}</h3> <mat-expansion-panel-header>
<mat-list-option [value]="ProjectStateType.Finished"> <mat-panel-title>
{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE' | translate }} {{ 'FACET-SEARCH.PROJECT-STATUS.TITLE' | translate }}
</mat-list-option> </mat-panel-title>
<mat-list-option [value]="ProjectStateType.OnGoing"> </mat-expansion-panel-header>
{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE' | translate }} <mat-selection-list #projectState role="listbox" (selectionChange)="projectStatusChanged($event)">
</mat-list-option> <mat-list-option [value]="ProjectStateType.Finished">
</mat-selection-list> <p>{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE' | translate }}</p>
<mat-divider></mat-divider> </mat-list-option>
<mat-selection-list *ngIf="this.facetCriteria.projectStatus == ProjectStateType.OnGoing || this.facetCriteria.projectStatus == ProjectStateType.Finished" <mat-list-option [value]="ProjectStateType.OnGoing">
(selectionChange)="projectChanged($event)"> <p>{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE' | translate }}</p>
<h3 matSubheader>{{ 'FACET-SEARCH.PROJECT.TITLE' | translate }}</h3> </mat-list-option>
<mat-list-option *ngFor="let project of (projects | async) | slice:0:10" [value]="project.id"> </mat-selection-list>
{{ project.label }} </mat-expansion-panel>
</mat-list-option> <mat-expansion-panel *ngIf="this.facetCriteria.projectStatus == ProjectStateType.OnGoing || this.facetCriteria.projectStatus == ProjectStateType.Finished">
</mat-selection-list> <mat-expansion-panel-header>
<mat-divider></mat-divider> <mat-panel-title>
<mat-selection-list {{ 'FACET-SEARCH.PROJECT.TITLE' | translate }}
(selectionChange)="profileChanged($event)"> </mat-panel-title>
<h3 matSubheader>{{ 'FACET-SEARCH.PROFILES.TITLE' | translate }}</h3> </mat-expansion-panel-header>
<mat-list-option *ngFor="let profile of (profiles | async) | slice:0:10" [value]="profile.id"> <div>
{{ profile.label }} <mat-form-field>
</mat-list-option> <input type="text" placeholder="{{ 'FACET-SEARCH.PROJECT.FILTER' | translate }}" matInput [formControl]="projectSearchControl">
</mat-selection-list> </mat-form-field>
<mat-divider></mat-divider> </div>
<mat-selection-list <mat-chip-list>
(selectionChange)="dmpOrganisationChanged($event)"> <mat-chip [removable]="removable" (removed)="removeProject(project)" *ngFor="let project of facetCriteria.projects">{{
<h3 matSubheader>{{ 'FACET-SEARCH.DMP-ORGANISATIONS.TITLE' | translate }}</h3> project }}
<mat-list-option *ngFor="let dmpOrganisation of (dmpOrganisations | async) | slice:0:10" [value]="dmpOrganisation.id"> <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
{{ dmpOrganisation.name }} </mat-chip>
</mat-list-option> </mat-chip-list>
</mat-selection-list> <mat-selection-list #project (selectionChange)="projectChanged($event)">
</div> <mat-list-option *ngFor="let project of (projects | async) | slice:0:10" [value]="project.id" [selected]="projectIsSelected(project.id)">
<p>{{ project.label }}</p>
</mat-list-option>
</mat-selection-list>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{ 'FACET-SEARCH.PROFILES.TITLE' | translate }}
</mat-panel-title>
</mat-expansion-panel-header>
<mat-selection-list (selectionChange)="profileChanged($event)">
<mat-list-option *ngFor="let profile of (profiles | async) | slice:0:10" [value]="profile.id">
<p>{{ profile.label }}</p>
</mat-list-option>
</mat-selection-list>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
{{ 'FACET-SEARCH.DMP-ORGANISATIONS.TITLE' | translate }}
</mat-panel-title>
</mat-expansion-panel-header>
<div>
<mat-form-field>
<input type="text" placeholder="{{ 'FACET-SEARCH.DMP-ORGANISATIONS.FILTER' | translate }}" matInput
[formControl]="organisationSearchControl">
</mat-form-field>
</div>
<mat-selection-list (selectionChange)="dmpOrganisationChanged($event)">
<mat-list-option *ngFor="let dmpOrganisation of (dmpOrganisations | async) | slice:0:10" [value]="dmpOrganisation.id">
<p>{{ dmpOrganisation.name }}</p>
</mat-list-option>
</mat-selection-list>
</mat-expansion-panel>
</mat-accordion>

@ -17,90 +17,142 @@ import { DatasetProfileModel } from '../../../models/datasetprofile/DatasetProfi
import { RequestItem } from '../../../models/criteria/RequestItem'; import { RequestItem } from '../../../models/criteria/RequestItem';
import { ExternalSourcesService } from '../../../services/external-sources/external-sources.service'; import { ExternalSourcesService } from '../../../services/external-sources/external-sources.service';
import { ExternalSourcesItemModel } from '../../../models/external-sources/ExternalSourcesItemModel'; import { ExternalSourcesItemModel } from '../../../models/external-sources/ExternalSourcesItemModel';
import { FormControl } from '@angular/forms';
import { LanguageService } from '../../../services/language/language.service';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'app-facet', selector: 'app-facet',
templateUrl: './facet-search.component.html', templateUrl: './facet-search.component.html',
styleUrls: ['./facet-search.component.scss'], styleUrls: ['./facet-search.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
providers: [ProjectService] providers: [ProjectService]
}) })
export class FacetSearchComponent implements OnInit { export class FacetSearchComponent implements OnInit {
@Input() @Input()
facetCriteria = new FacetSearchCriteriaModel(); facetCriteria = new FacetSearchCriteriaModel();
@Output() @Output()
facetCriteriaChange = new EventEmitter(); facetCriteriaChange = new EventEmitter();
ProjectStateType = ProjectStateType;
projects: Observable<ProjectModel[]>
profiles: Observable<DatasetProfileModel[]>
dmpOrganisations: Observable<ExternalSourcesItemModel[]> removable = true;
ProjectStateType = ProjectStateType;
@ViewChild("project") selectionList: MatSelectionList projects: Observable<ProjectModel[]>;
profiles: Observable<DatasetProfileModel[]>;
constructor( dmpOrganisations: Observable<ExternalSourcesItemModel[]>;
public activatedRoute: ActivatedRoute, projectSearchControl = new FormControl('');
public projectService: ProjectService, organisationSearchControl = new FormControl('');
public datasetProfileService: DatasetService,
public externalSourcesService: ExternalSourcesService projectStateOptions = Observable.of(
) { [
} { label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE'), value: ProjectStateType.Finished },
{ label: this.languageService.instant('FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE'), value: ProjectStateType.OnGoing },
ngOnInit() { ]);
this.profiles = this.datasetProfileService.getDatasetProfiles() projectOptions: Observable<ProjectModel[]>;
this.selectionList.selectedOptions = new SelectionModel<MatListOption>(false);
this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations('') @ViewChild('project') projectSelectionList: MatSelectionList;
}
displayProjectStateValue = (option) => option['value'];
public projectStatusChanged(event) { displayProjectStateLabel = (option) => option['label'];
this.facetCriteria.projectStatus = event.option.value
if (!event.option.selected) { displayProjectValue = (option) => option['id'];
this.facetCriteria.projectStatus = null; displayProjectLabel = (option) => option['label'];
this.projects = Observable.of([])
this.facetCriteria.projects = [] constructor(
} public activatedRoute: ActivatedRoute,
if (event.option.selected) { public projectService: ProjectService,
let projectCriteria = new ProjectCriteria() public languageService: TranslateService,
projectCriteria.projectStateType = this.facetCriteria.projectStatus; public datasetProfileService: DatasetService,
projectCriteria["length"] = 10; public externalSourcesService: ExternalSourcesService
let dataTableRequest: RequestItem<ProjectCriteria> = { criteria: projectCriteria }; ) {
this.projects = this.projectService.get(dataTableRequest); }
this.facetCriteria.projects = []
} ngOnInit() {
this.facetCriteriaChange.emit(this.facetCriteria); this.profiles = this.datasetProfileService.getDatasetProfiles();
} this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations('');
this.projectSearchControl.valueChanges.subscribe(x => this.projectSearch(x));
public projectChanged(event: any) { this.organisationSearchControl.valueChanges.subscribe(x => this.dmpOrganisationSearch(x));
let eventValue = event.option.value }
if (event.option.selected) this.facetCriteria.projects.push(eventValue);
if (!event.option.selected) { public projectStatusChanged(event) {
var index = this.facetCriteria.projects.indexOf(eventValue); this.facetCriteria.projectStatus = event.option.value;
this.facetCriteria.projects.splice(index, 1); if (!event.option.selected) {
} this.facetCriteria.projectStatus = null;
this.facetCriteriaChange.emit(this.facetCriteria); this.projects = Observable.of([]);
} this.facetCriteria.projects = [];
}
public profileChanged(event: any) { if (event.option.selected) {
let eventValue = event.option.value const projectCriteria = new ProjectCriteria();
if (event.option.selected) { projectCriteria.projectStateType = this.facetCriteria.projectStatus;
this.facetCriteria.datasetProfile.push(eventValue); projectCriteria['length'] = 10;
} const dataTableRequest: RequestItem<ProjectCriteria> = { criteria: projectCriteria };
if (!event.option.selected) { this.projects = this.projectService.get(dataTableRequest);
var index = this.facetCriteria.datasetProfile.indexOf(eventValue); this.facetCriteria.projects = [];
this.facetCriteria.datasetProfile.splice(index, 1); }
} this.facetCriteriaChange.emit(this.facetCriteria);
this.facetCriteriaChange.emit(this.facetCriteria); }
}
public projectChanged(event: any) {
public dmpOrganisationChanged(event: any) { const eventValue = event.option.value;
let eventValue = event.option.value if (event.option.selected) { this.facetCriteria.projects.push(eventValue); }
if (event.option.selected) this.facetCriteria.dmpOrganisations.push(eventValue); if (!event.option.selected) {
if (!event.option.selected) { const index = this.facetCriteria.projects.indexOf(eventValue);
var index = this.facetCriteria.dmpOrganisations.indexOf(eventValue); this.facetCriteria.projects.splice(index, 1);
this.facetCriteria.dmpOrganisations.splice(index, 1); }
} this.facetCriteriaChange.emit(this.facetCriteria);
this.facetCriteriaChange.emit(this.facetCriteria); }
}
removeProject(project) {
const list = this.projectSelectionList.selectedOptions.selected.map(x => x.value);
const indexOfProject = list.indexOf(project);
if (this.projectSelectionList.selectedOptions.selected[indexOfProject]) {
this.projectSelectionList.selectedOptions.selected[indexOfProject].selected = false;
this.projectSelectionList.selectedOptions.selected.splice(indexOfProject, 1);
}
this.facetCriteria.projects.splice(this.facetCriteria.projects.indexOf(project), 1);
this.facetCriteriaChange.emit(this.facetCriteria);
}
public profileChanged(event: any) {
const eventValue = event.option.value;
if (event.option.selected) {
this.facetCriteria.datasetProfile.push(eventValue);
}
if (!event.option.selected) {
const index = this.facetCriteria.datasetProfile.indexOf(eventValue);
this.facetCriteria.datasetProfile.splice(index, 1);
}
this.facetCriteriaChange.emit(this.facetCriteria);
}
public dmpOrganisationChanged(event: any) {
const eventValue = event.option.value;
if (event.option.selected) { this.facetCriteria.dmpOrganisations.push(eventValue); }
if (!event.option.selected) {
const index = this.facetCriteria.dmpOrganisations.indexOf(eventValue);
this.facetCriteria.dmpOrganisations.splice(index, 1);
}
this.facetCriteriaChange.emit(this.facetCriteria);
}
public projectIsSelected(value: string) {
return this.facetCriteria.projects.indexOf(value) !== -1;
}
public projectSearch(value: string): Observable<ProjectModel[]> {
const projectCriteria = new ProjectCriteria();
projectCriteria.projectStateType = this.facetCriteria.projectStatus;
projectCriteria['length'] = 10;
projectCriteria.like = value;
const dataTableRequest: RequestItem<ProjectCriteria> = { criteria: projectCriteria };
return this.projectService.get(dataTableRequest);
}
public dmpOrganisationSearch(value: string) {
this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations(value);
}
} }

@ -20,22 +20,22 @@ export class FigurecardComponent implements OnInit {
@Input() buttonTitle: string; @Input() buttonTitle: string;
@Input() buttonRedirectLink: string; @Input() buttonRedirectLink: string;
constructor(private router: Router,private authService: AuthService) { } constructor(private router: Router, private authService: AuthService) { }
ngOnInit() { ngOnInit() {
} }
navigateToUrl() { navigateToUrl() {
if(!this.isAuthenticated()) return; if (!this.isAuthenticated()) { return; }
this.router.navigate([this.routelLink]); this.router.navigate([this.routelLink]);
} }
createNew(){ createNew() {
this.router.navigate([this.buttonRedirectLink]); this.router.navigate([this.buttonRedirectLink]);
} }
isAuthenticated(){ isAuthenticated() {
return this.authService.current() != null; return this.authService.current() != null;
} }
} }

@ -1,6 +1,6 @@
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<a class="app-logo" routerLink="/"> <a class="app-logo" routerLink="/">
<img [src]="'/assets/images/openDmps.png'" alt="openDMPS"> <img [src]="'/assets/images/OpenDMP.png'" alt="openDMP">
</a> </a>
<div *ngIf="isAuthenticated()"> <div *ngIf="isAuthenticated()">
<a mat-button class="navbar-button" routerLink="/projects">{{this.languageResolver.getBy('navbar') | translate}}</a> <a mat-button class="navbar-button" routerLink="/projects">{{this.languageResolver.getBy('navbar') | translate}}</a>

@ -33,9 +33,11 @@
font-size: 14px; font-size: 14px;
} }
.logo { .app-logo {
width: 38px; height: 60px;
height: 38px; img{
height: inherit;
}
} }
.user-profile{ .user-profile{

@ -14,7 +14,7 @@
</div> </div>
<div mat-dialog-actions> <div mat-dialog-actions>
<div layout="row" class="full-width text-right" align="end"> <div class="full-width">
{{'USER-DIALOG.EXIT' | translate}} {{'USER-DIALOG.EXIT' | translate}}
<button mat-icon-button (click)="logout()"> <button mat-icon-button (click)="logout()">
<mat-icon>exit_to_app</mat-icon> <mat-icon>exit_to_app</mat-icon>

@ -29,68 +29,70 @@ import { TimezoneInfoDisplayPipe } from '../utilities/culture/pipes/TimezoneInfo
import { CultureService } from '../utilities/culture/culture-service'; import { CultureService } from '../utilities/culture/culture-service';
import { MAT_DATE_LOCALE } from '@angular/material'; import { MAT_DATE_LOCALE } from '@angular/material';
import { FacetSearchComponent } from './components/facets/facet-search.component'; import { FacetSearchComponent } from './components/facets/facet-search.component';
import { FacetSearchSectionComponent } from './components/facets/facet-search-component/facet-search-section.component';
@NgModule({ @NgModule({
imports: [ imports: [
CommonModule, CommonModule,
RouterModule, RouterModule,
MaterialModule, MaterialModule,
FlexLayoutModule, FlexLayoutModule,
TranslateModule, TranslateModule,
FormsModule, FormsModule,
ReactiveFormsModule ReactiveFormsModule
], ],
declarations: [ declarations: [
NavigationComponent, NavigationComponent,
SnackBarNotificationComponent, SnackBarNotificationComponent,
ProjectCriteriaComponent, ProjectCriteriaComponent,
DatasetCriteriaComponent, DatasetCriteriaComponent,
DataManagementPlanCriteriaComponent, DataManagementPlanCriteriaComponent,
DataManagementPlanProfileCriteriaComponent, DataManagementPlanProfileCriteriaComponent,
FigurecardComponent, FigurecardComponent,
BaseCriteriaComponent, BaseCriteriaComponent,
FileUploaderComponent, FileUploaderComponent,
UrlListingComponent, UrlListingComponent,
NgForLimitPipe, NgForLimitPipe,
AutoCompleteComponent, AutoCompleteComponent,
ExternalItemListingComponent, ExternalItemListingComponent,
ExternalItemComponent, ExternalItemComponent,
BreadcrumbComponent, BreadcrumbComponent,
SingleAutoCompleteComponent, SingleAutoCompleteComponent,
MultipleAutoCompleteComponent, MultipleAutoCompleteComponent,
UserDialogComponent, UserDialogComponent,
SearchBarComponent, SearchBarComponent,
FacetSearchComponent FacetSearchComponent,
], FacetSearchSectionComponent
],
exports: [ exports: [
MaterialModule, MaterialModule,
FlexLayoutModule, FlexLayoutModule,
NavigationComponent,
NavigationComponent, SnackBarNotificationComponent,
SnackBarNotificationComponent, ProjectCriteriaComponent,
ProjectCriteriaComponent, DatasetCriteriaComponent,
DatasetCriteriaComponent, DataManagementPlanProfileCriteriaComponent,
DataManagementPlanProfileCriteriaComponent, DataManagementPlanCriteriaComponent,
DataManagementPlanCriteriaComponent, FigurecardComponent,
FigurecardComponent, BaseCriteriaComponent,
BaseCriteriaComponent, FileUploaderComponent,
FileUploaderComponent, UrlListingComponent,
UrlListingComponent, NgForLimitPipe,
NgForLimitPipe, AutoCompleteComponent,
AutoCompleteComponent, ExternalItemListingComponent,
ExternalItemListingComponent, ExternalItemComponent,
ExternalItemComponent, BreadcrumbComponent,
BreadcrumbComponent, SingleAutoCompleteComponent,
SingleAutoCompleteComponent, MultipleAutoCompleteComponent,
MultipleAutoCompleteComponent, UserDialogComponent,
UserDialogComponent, FacetSearchComponent,
FacetSearchComponent FacetSearchSectionComponent
], ],
entryComponents: [ entryComponents: [
UserDialogComponent UserDialogComponent
], ],
}) })

@ -44,7 +44,7 @@
<button mat-button (click)="nativeLogin()">LOGIN</button> <button mat-button (click)="nativeLogin()">LOGIN</button>
</div> </div>
</div> </div>
<p>You dont need to have a registered account for OpenDMPs</p> <p>You dont need to have a registered account for OpenDMP</p>
</div> </div>
</div> </div>
</div> </div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

@ -29,7 +29,7 @@
} }
}, },
"NAV-BAR": { "NAV-BAR": {
"TITLE": "OpenDMPS", "TITLE": "OpenDMP",
"PROJECTS": "Projects", "PROJECTS": "Projects",
"DMPS": "DMPs", "DMPS": "DMPs",
"DATASETS": "Datasets", "DATASETS": "Datasets",
@ -316,7 +316,7 @@
}, },
"HOMEPAGE": { "HOMEPAGE": {
"OPEN-DMPS": { "OPEN-DMPS": {
"STATS": "OpenDMPS DashBoard" "STATS": "OpenDMP DashBoard"
}, },
"MY-DMPS": { "MY-DMPS": {
"STATS": "My DashBoard" "STATS": "My DashBoard"
@ -388,13 +388,15 @@
} }
}, },
"PROJECT": { "PROJECT": {
"TITLE": "Project" "TITLE": "Project",
"FILTER": "Filter Projects"
}, },
"PROFILES": { "PROFILES": {
"TITLE": "Dataset specification" "TITLE": "Dataset specification"
}, },
"DMP-ORGANISATIONS": { "DMP-ORGANISATIONS": {
"TITLE": "DMP Organisations" "TITLE": "DMP Organisations",
"FILTER": "Filter Organisations"
} }
} }
} }

@ -19,11 +19,11 @@
<nav> <nav>
<div class="nav-wrapper blue darken-3"> <div class="nav-wrapper blue darken-3">
<a href="http://opendmp.eu" class="brand-logo" style="margin-top: 20px;"> <a href="http://opendmp.eu" class="brand-logo" style="margin-top: 20px;">
<img src="/material/openDmps.png" alt="openDMPS"> <img src="/material/OpenDMP.png" alt="openDMP">
</a> </a>
helllooooooooooooooooo helllooooooooooooooooo
</div> </div>
</nav> </nav>
</body> </body>
</html> </html>

@ -41,6 +41,7 @@ services:
container_name: dmp-frontend container_name: dmp-frontend
volumes: volumes:
- ./static:/usr/share/nginx/static - ./static:/usr/share/nginx/static
- /srv/docker/wwwcert:/usr/share/nginx/wwwcert
ports: ['0.0.0.0:80:80'] ports: ['0.0.0.0:80:80']
networks: ['stack'] networks: ['stack']

Loading…
Cancel
Save