Introduced Facet Search Component On Dataset Public Listing

This commit is contained in:
Ioannis Kalyvas 2018-10-05 09:56:50 +03:00
parent e0c302e67e
commit b8c78e7135
31 changed files with 512 additions and 325 deletions

View File

@ -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

View File

@ -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) -> {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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/;
}
} }

View File

@ -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,9 +23,9 @@ 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: [

View File

@ -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() {
} }
} }

View File

@ -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>

View File

@ -0,0 +1,3 @@
text-center{
text-align: center
}

View File

@ -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;

View File

@ -18,34 +18,34 @@ export class BreadCrumbResolverService {
) { } ) { }
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;
} }
@ -53,31 +53,31 @@ export class BreadCrumbResolverService {
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));
} }
} }

View File

@ -38,11 +38,11 @@ export class DatasetService {
} }
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 });
} }
} }

View File

@ -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>

View File

@ -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;
}
}

View File

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

View File

@ -17,6 +17,9 @@ 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',
@ -33,74 +36,123 @@ export class FacetSearchComponent implements OnInit {
@Output() @Output()
facetCriteriaChange = new EventEmitter(); facetCriteriaChange = new EventEmitter();
ProjectStateType = ProjectStateType;
projects: Observable<ProjectModel[]>
profiles: Observable<DatasetProfileModel[]>
dmpOrganisations: Observable<ExternalSourcesItemModel[]>
@ViewChild("project") selectionList: MatSelectionList
removable = true;
ProjectStateType = ProjectStateType;
projects: Observable<ProjectModel[]>;
profiles: Observable<DatasetProfileModel[]>;
dmpOrganisations: Observable<ExternalSourcesItemModel[]>;
projectSearchControl = new FormControl('');
organisationSearchControl = new FormControl('');
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 },
]);
projectOptions: Observable<ProjectModel[]>;
@ViewChild('project') projectSelectionList: MatSelectionList;
displayProjectStateValue = (option) => option['value'];
displayProjectStateLabel = (option) => option['label'];
displayProjectValue = (option) => option['id'];
displayProjectLabel = (option) => option['label'];
constructor( constructor(
public activatedRoute: ActivatedRoute, public activatedRoute: ActivatedRoute,
public projectService: ProjectService, public projectService: ProjectService,
public languageService: TranslateService,
public datasetProfileService: DatasetService, public datasetProfileService: DatasetService,
public externalSourcesService: ExternalSourcesService public externalSourcesService: ExternalSourcesService
) { ) {
} }
ngOnInit() { ngOnInit() {
this.profiles = this.datasetProfileService.getDatasetProfiles() this.profiles = this.datasetProfileService.getDatasetProfiles();
this.selectionList.selectedOptions = new SelectionModel<MatListOption>(false); this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations('');
this.dmpOrganisations = this.externalSourcesService.searchDMPOrganizations('') this.projectSearchControl.valueChanges.subscribe(x => this.projectSearch(x));
this.organisationSearchControl.valueChanges.subscribe(x => this.dmpOrganisationSearch(x));
} }
public projectStatusChanged(event) { public projectStatusChanged(event) {
this.facetCriteria.projectStatus = event.option.value this.facetCriteria.projectStatus = event.option.value;
if (!event.option.selected) { if (!event.option.selected) {
this.facetCriteria.projectStatus = null; this.facetCriteria.projectStatus = null;
this.projects = Observable.of([]) this.projects = Observable.of([]);
this.facetCriteria.projects = [] this.facetCriteria.projects = [];
} }
if (event.option.selected) { if (event.option.selected) {
let projectCriteria = new ProjectCriteria() const projectCriteria = new ProjectCriteria();
projectCriteria.projectStateType = this.facetCriteria.projectStatus; projectCriteria.projectStateType = this.facetCriteria.projectStatus;
projectCriteria["length"] = 10; projectCriteria['length'] = 10;
let dataTableRequest: RequestItem<ProjectCriteria> = { criteria: projectCriteria }; const dataTableRequest: RequestItem<ProjectCriteria> = { criteria: projectCriteria };
this.projects = this.projectService.get(dataTableRequest); this.projects = this.projectService.get(dataTableRequest);
this.facetCriteria.projects = [] this.facetCriteria.projects = [];
} }
this.facetCriteriaChange.emit(this.facetCriteria); this.facetCriteriaChange.emit(this.facetCriteria);
} }
public projectChanged(event: any) { public projectChanged(event: any) {
let eventValue = event.option.value const eventValue = event.option.value;
if (event.option.selected) this.facetCriteria.projects.push(eventValue); if (event.option.selected) { this.facetCriteria.projects.push(eventValue); }
if (!event.option.selected) { if (!event.option.selected) {
var index = this.facetCriteria.projects.indexOf(eventValue); const index = this.facetCriteria.projects.indexOf(eventValue);
this.facetCriteria.projects.splice(index, 1); this.facetCriteria.projects.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) { public profileChanged(event: any) {
let eventValue = event.option.value const eventValue = event.option.value;
if (event.option.selected) { if (event.option.selected) {
this.facetCriteria.datasetProfile.push(eventValue); this.facetCriteria.datasetProfile.push(eventValue);
} }
if (!event.option.selected) { if (!event.option.selected) {
var index = this.facetCriteria.datasetProfile.indexOf(eventValue); const index = this.facetCriteria.datasetProfile.indexOf(eventValue);
this.facetCriteria.datasetProfile.splice(index, 1); this.facetCriteria.datasetProfile.splice(index, 1);
} }
this.facetCriteriaChange.emit(this.facetCriteria); this.facetCriteriaChange.emit(this.facetCriteria);
} }
public dmpOrganisationChanged(event: any) { public dmpOrganisationChanged(event: any) {
let eventValue = event.option.value const eventValue = event.option.value;
if (event.option.selected) this.facetCriteria.dmpOrganisations.push(eventValue); if (event.option.selected) { this.facetCriteria.dmpOrganisations.push(eventValue); }
if (!event.option.selected) { if (!event.option.selected) {
var index = this.facetCriteria.dmpOrganisations.indexOf(eventValue); const index = this.facetCriteria.dmpOrganisations.indexOf(eventValue);
this.facetCriteria.dmpOrganisations.splice(index, 1); this.facetCriteria.dmpOrganisations.splice(index, 1);
} }
this.facetCriteriaChange.emit(this.facetCriteria); 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);
}
} }

View File

@ -20,21 +20,21 @@ 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;
} }

View File

@ -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>

View File

@ -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{

View File

@ -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>

View File

@ -29,6 +29,7 @@ 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: [
@ -61,13 +62,13 @@ import { FacetSearchComponent } from './components/facets/facet-search.component
MultipleAutoCompleteComponent, MultipleAutoCompleteComponent,
UserDialogComponent, UserDialogComponent,
SearchBarComponent, SearchBarComponent,
FacetSearchComponent FacetSearchComponent,
FacetSearchSectionComponent
], ],
exports: [ exports: [
MaterialModule, MaterialModule,
FlexLayoutModule, FlexLayoutModule,
NavigationComponent, NavigationComponent,
SnackBarNotificationComponent, SnackBarNotificationComponent,
ProjectCriteriaComponent, ProjectCriteriaComponent,
@ -86,7 +87,8 @@ import { FacetSearchComponent } from './components/facets/facet-search.component
SingleAutoCompleteComponent, SingleAutoCompleteComponent,
MultipleAutoCompleteComponent, MultipleAutoCompleteComponent,
UserDialogComponent, UserDialogComponent,
FacetSearchComponent FacetSearchComponent,
FacetSearchSectionComponent
], ],
entryComponents: [ entryComponents: [
UserDialogComponent UserDialogComponent

View File

@ -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

View File

@ -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"
} }
} }
} }

View File

@ -19,7 +19,7 @@
<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>

View File

@ -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']