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.<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)));
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())
query.where(((builder, root) -> root.get("dmp").get("project").get("id").in(this.getCriteria().projects)));
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 {
datasetTableRequest.setQuery(apiContext.getOperationsContext().getDatabaseRepository().getDatasetDao().asQueryable().withHint(HintedModelFactory.getHint(DatasetListingModel.class)));
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.
selectAsync(item -> new DatasetListingModel().fromDataModel(item)).whenComplete((resultList, throwable) -> {

View File

@ -3,7 +3,8 @@
#eu.eudat.logic.security.portmapping.https = 7444
########################/Security########################################
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
##########################Persistence##########################################
database.driver-class-name=org.postgresql.Driver

View File

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

View File

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

View File

@ -9,4 +9,8 @@ server {
location /material/ {
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 { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { DatasetProfileRoutes } from "./dataset-profile.router";
import { RouterModule } from "@angular/router";
import { DatasetProfileRoutes } from './dataset-profile.router';
import { RouterModule } from '@angular/router';
import { FormComponent } from './form/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 { CompositeFieldFormComponent } from './compositefield-form/compositefield-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 { 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 { AutocompleteComponent } from '../shared/componentsAdmin/autocomplete/autocomplete-component';
import { ComboboxComponent } from '../shared/componentsAdmin/combobox/combobox-component';
import { SharedModule } from "../shared/shared.module";
import { DatasetProfilePreviewerComponent } from "./previewer/dataset-profile-previewer.component";
import { DynamicFormModule } from "../form/dynamic-form.module";
import { SharedModule } from '../shared/shared.module';
import { DatasetProfilePreviewerComponent } from './previewer/dataset-profile-previewer.component';
import { DynamicFormModule } from '../form/dynamic-form.module';
@NgModule({
imports: [
CommonModule,
FormsModule,
HttpClientModule,
ReactiveFormsModule,
RouterModule,
SharedModule,
DynamicFormModule,
RouterModule.forChild(DatasetProfileRoutes)
],
imports: [
CommonModule,
FormsModule,
HttpClientModule,
ReactiveFormsModule,
RouterModule,
SharedModule,
DynamicFormModule,
RouterModule.forChild(DatasetProfileRoutes)
],
declarations: [
FormComponent,
//GroupFieldFormComponent,
RuleFormComponent,
SectionFormComponent,
PageFormComponent,
CompositeFieldFormComponent,
FieldFormComponent,
TextAreaComponent,
CheckBoxComponent,
BooleanDecisionComponent,
FreeTextComponent,
ComboboxComponent,
AutocompleteComponent,
WordlistComponent,
RadioBoxComponent,
DatasetProfilePreviewerComponent
],
declarations: [
FormComponent,
//GroupFieldFormComponent,
RuleFormComponent,
SectionFormComponent,
PageFormComponent,
CompositeFieldFormComponent,
FieldFormComponent,
TextAreaComponent,
CheckBoxComponent,
BooleanDecisionComponent,
FreeTextComponent,
ComboboxComponent,
AutocompleteComponent,
WordlistComponent,
RadioBoxComponent,
DatasetProfilePreviewerComponent
],
exports: [
FormComponent,
//GroupFieldFormComponent,
RuleFormComponent,
SectionFormComponent,
PageFormComponent,
CompositeFieldFormComponent,
FieldFormComponent,
TextAreaComponent,
CheckBoxComponent,
BooleanDecisionComponent,
FreeTextComponent,
ComboboxComponent,
AutocompleteComponent,
WordlistComponent,
RadioBoxComponent
],
providers: [
],
entryComponents: [
DatasetProfilePreviewerComponent
]
exports: [
FormComponent,
//GroupFieldFormComponent,
RuleFormComponent,
SectionFormComponent,
PageFormComponent,
CompositeFieldFormComponent,
FieldFormComponent,
TextAreaComponent,
CheckBoxComponent,
BooleanDecisionComponent,
FreeTextComponent,
ComboboxComponent,
AutocompleteComponent,
WordlistComponent,
RadioBoxComponent
],
providers: [
],
entryComponents: [
DatasetProfilePreviewerComponent
]
})

View File

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

View File

@ -1,18 +1,17 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup } from '@angular/forms'
import { Rule } from 'app/models/datasetProfileAdmin/Rule'
import { Component, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'rule-form',
templateUrl: './rule.component.html',
styleUrls: ['./rule.component.scss']
selector: 'app-rule-form',
templateUrl: './rule.component.html',
styleUrls: ['./rule.component.scss']
})
export class RuleFormComponent {
@Input() form: FormGroup;
@Input() dataModel: FormGroup;
@Input() form: 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="col-md-2">
<div class="col-md-3">
<app-facet (facetCriteriaChange)="onCriteriaChange($event)">
</app-facet>
</div>
<div class="col-md-10">
<div class="col-md-9">
<div>
<h3>{{'DATASET-PUBLIC-LISTING.TITLE' | translate}} {{titlePrefix}}</h3>
<app-datasets-criteria-component [isPublic]='true'></app-datasets-criteria-component>
<mat-card class="mat-card">
<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 { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ValidationContext } from '../../utilities/validators/ValidationContext';
import { Serializable } from "../Serializable";
import { Serializable } from '../Serializable';
export class DatasetProfileModel implements Serializable<DatasetProfileModel> {
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')] });
return baseContext;
}
}
}

View File

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

View File

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

@ -22,27 +22,27 @@ export class DatasetService {
constructor(private http: BaseHttpService) {
this.actionUrl = HostConfiguration.Server + 'datasets/';
this.actionUrl = HostConfiguration.Server + 'datasets/';
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
this.headers = new HttpHeaders();
this.headers = this.headers.set('Content-Type', 'application/json');
this.headers = this.headers.set('Accept', 'application/json');
}
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>> {
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) {
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[]> {
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-selection-list #project role="listbox" (selectionChange)="projectStatusChanged($event)">
<h3 matSubheader>{{ 'FACET-SEARCH.PROJECT-STATUS.TITLE' | translate }}</h3>
<mat-list-option [value]="ProjectStateType.Finished">
{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE' | translate }}
</mat-list-option>
<mat-list-option [value]="ProjectStateType.OnGoing">
{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE' | translate }}
</mat-list-option>
</mat-selection-list>
<mat-divider></mat-divider>
<mat-selection-list *ngIf="this.facetCriteria.projectStatus == ProjectStateType.OnGoing || this.facetCriteria.projectStatus == ProjectStateType.Finished"
(selectionChange)="projectChanged($event)">
<h3 matSubheader>{{ 'FACET-SEARCH.PROJECT.TITLE' | translate }}</h3>
<mat-list-option *ngFor="let project of (projects | async) | slice:0:10" [value]="project.id">
{{ project.label }}
</mat-list-option>
</mat-selection-list>
<mat-divider></mat-divider>
<mat-selection-list
(selectionChange)="profileChanged($event)">
<h3 matSubheader>{{ 'FACET-SEARCH.PROFILES.TITLE' | translate }}</h3>
<mat-list-option *ngFor="let profile of (profiles | async) | slice:0:10" [value]="profile.id">
{{ profile.label }}
</mat-list-option>
</mat-selection-list>
<mat-divider></mat-divider>
<mat-selection-list
(selectionChange)="dmpOrganisationChanged($event)">
<h3 matSubheader>{{ 'FACET-SEARCH.DMP-ORGANISATIONS.TITLE' | translate }}</h3>
<mat-list-option *ngFor="let dmpOrganisation of (dmpOrganisations | async) | slice:0:10" [value]="dmpOrganisation.id">
{{ dmpOrganisation.name }}
</mat-list-option>
</mat-selection-list>
</div>
<mat-accordion>
<mat-expansion-panel>
<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">
<p>{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.INACTIVE' | translate }}</p>
</mat-list-option>
<mat-list-option [value]="ProjectStateType.OnGoing">
<p>{{ 'FACET-SEARCH.PROJECT-STATUS.OPTIONS.ACTIVE' | translate }}</p>
</mat-list-option>
</mat-selection-list>
</mat-expansion-panel>
<mat-expansion-panel *ngIf="this.facetCriteria.projectStatus == ProjectStateType.OnGoing || this.facetCriteria.projectStatus == ProjectStateType.Finished">
<mat-expansion-panel-header>
<mat-panel-title>
{{ 'FACET-SEARCH.PROJECT.TITLE' | translate }}
</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-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>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -44,7 +44,7 @@
<button mat-button (click)="nativeLogin()">LOGIN</button>
</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>

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

View File

@ -19,11 +19,11 @@
<nav>
<div class="nav-wrapper blue darken-3">
<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>
helllooooooooooooooooo
</div>
</nav>
</body>
</html>
</html>

View File

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