Skip to content
Snippets Groups Projects
Commit a8a39dfb authored by Tifenn Guillas's avatar Tifenn Guillas
Browse files

Merge branch '19-render-datatable' into 'develop'

Resolve "Gestion render datatable"

Closes #19

See merge request !21
parents f548e5f9 9a1c49a6
No related branches found
No related tags found
2 merge requests!68Develop,!21Resolve "Gestion render datatable"
Pipeline #1299 failed
Showing
with 294 additions and 39 deletions
......@@ -8,27 +8,77 @@
<span *ngIf="!ag.isOpen"><i class="fas fa-chevron-down"></i></span>
</div>
</button>
<div *ngIf="!searchMeta" class="text-center">
<i class="fas fa-circle-notch fa-spin fa-3x"></i>
<span class="sr-only">Loading...</span>
</div>
<div *ngIf="searchMeta">
<div class="table-responsive">
<table class="table table-striped">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th *ngFor="let attribute of searchMeta.attributes_selected" scope="col">{{ attribute.label }}</th>
<th *ngFor="let attribute of searchMeta.attributes_selected" scope="col">
{{ attribute.label }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let datum of searchData">
<td *ngFor="let attribute of searchMeta.attributes_selected" [innerHTML]="datum[attribute.name]"></td>
<td *ngFor="let attribute of searchMeta.attributes_selected">
<div [ngSwitch]="getAttributeRenderer(attribute.name)">
<div *ngSwitchCase="'img'">
<img [src]="getAttributeUriAction(attribute.name, datum[attribute.name])">
</div>
<div *ngSwitchCase="'thumbnail'">
<button class="btn btn-link"
(click)="openModal('thumbnail', attribute.name, datum[attribute.name])">
<img [src]="getAttributeUriAction(attribute.name, datum[attribute.name])"
class="img-fluid">
</button>
</div>
<div *ngSwitchCase="'href'">
<a [href]="getAttributeUriAction(attribute.name, datum[attribute.name])">
{{ datum[attribute.name] }}</a>
</div>
<div *ngSwitchCase="'btn'">
<a [href]="getAttributeUriAction(attribute.name, datum[attribute.name])"
class="btn btn-outline-primary btn-sm">
{{ datum[attribute.name] }}</a>
</div>
<div *ngSwitchCase="'fancybox'">
<button class="btn btn-outline-primary btn-sm"
(click)="openModal('fancybox', attribute.name, datum[attribute.name])">
{{ datum[attribute.name] }}
</button>
</div>
<div *ngSwitchCase="'download'">
<a [href]="getAttributeUriAction(attribute.name, datum[attribute.name])"
class="btn btn-outline-primary btn-sm">
<i class="fa fa-download" aria-hidden="true"></i>
</a>
</div>
<div *ngSwitchDefault>
{{ datum[attribute.name] }}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-3">
<p>Total items {{searchMeta.total_items}}</p>
<p>Total items {{ searchMeta.total_items }}</p>
</div>
<div class="mt-3">
<pagination [totalItems]="searchMeta.total_items" [boundaryLinks]="true" [rotate]="true" [maxSize]="5" (pageChanged)="getSearchData.emit($event.page)"></pagination>
<pagination [totalItems]="searchMeta.total_items" [boundaryLinks]="true" [rotate]="true" [maxSize]="5"
(pageChanged)="getSearchData.emit($event.page)"></pagination>
</div>
</div>
</accordion-group>
</accordion>
<app-modal *ngIf="modalData.isOpen"
[bsModalRef]="bsModalRef"
[type]="modalData.type"
[data]="modalData.data"
(closeEvent)="closeModal($event)">
</app-modal>
\ No newline at end of file
import { Component, Input, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { SearchMeta } from '../store/model';
import { Attribute } from 'src/app/metamodel/model';
interface ModalData {
isOpen: boolean;
type: string;
data: object;
}
@Component({
selector: 'app-datatable',
templateUrl: 'datatable.component.html',
styleUrls: [ 'datatable.component.css' ],
styleUrls: ['datatable.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DatatableComponent {
@Input() datasetName: string;
@Input() datasetAttributeList: Attribute[];
@Input() searchMeta: SearchMeta;
@Input() searchData: any[];
@Output() initSearchMeta: EventEmitter<{}> = new EventEmitter();
@Output() getSearchData: EventEmitter<number> = new EventEmitter();
bsModalRef: BsModalRef;
modalData: ModalData = {
isOpen: false,
type: null,
data: null
};
initDatatable() {
this.initSearchMeta.emit();
this.getSearchData.emit(1);
}
}
\ No newline at end of file
getAttributeRenderer(attributeName: string): string {
const attribute = this.datasetAttributeList.find(a => a.name === attributeName);
return attribute.renderer;
}
getAttributeUriAction(attributeName: string, datum: string): string {
const attribute = this.datasetAttributeList.find(a => a.name === attributeName);
return attribute.uri_action;
}
openModal(type: string, attributeName: string, value: string) {
this.modalData.type = type;
if (type === 'thumbnail') {
this.modalData.data = {
title: value,
srcImage: this.getAttributeUriAction(attributeName, value)
};
} else if (type === 'fancybox') {
this.modalData.data = {
title: value,
idAttribute: value,
};
}
this.modalData.isOpen = true;
}
closeModal(event: null) {
this.modalData.isOpen = false;
this.modalData.type = null;
this.modalData.data = null;
}
}
<p>{{ idAttribute }}</p>
\ No newline at end of file
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-detail',
templateUrl: 'detail.component.html',
styleUrls: ['detail.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DetailComponent {
@Input() title: string;
@Input() idAttribute: number;
}
......@@ -9,6 +9,8 @@ import { SummaryComponent } from './summary.component';
import { criteriaComponents } from './criteria';
import { UrlDisplayComponent } from './url-display.component';
import { DatatableComponent } from './datatable.component';
import { DetailComponent } from './detail.component';
import { ModalComponent } from './modal.component';
export const dummiesComponents = [
ProgressComponent,
......@@ -21,5 +23,7 @@ export const dummiesComponents = [
criteriaComponents,
SummaryComponent,
UrlDisplayComponent,
DatatableComponent
DatatableComponent,
DetailComponent,
ModalComponent
];
.modal-fit {
width: fit-content;
max-width: 95%;
}
\ No newline at end of file
<div bsModal #lgModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="dialog-sizes-name1"
[config]="{ show: true }">
<div class="modal-dialog modal-fit">
<div class="modal-content">
<div class="modal-header">
<h4 id="dialog-sizes-name1" class="modal-title pull-left">{{ data.title }}</h4>
<button type="button" class="close pull-right" (click)="closeModal(lgModal)" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body text-center">
<div [ngSwitch]="type">
<div *ngSwitchCase="'thumbnail'">
<img [src]="data.srcImage" class="img-fluid">
</div>
<div *ngSwitchCase="'fancybox'">
<app-detail
[title]="data.title"
[idAttribute]="data.idAttribute">
</app-detail>
</div>
<div *ngSwitchDefault>
{{ type }} type not supported
</div>
</div>
</div>
</div>
</div>
</div>
\ No newline at end of file
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
@Component({
selector: 'app-modal',
templateUrl: 'modal.component.html',
styleUrls: ['modal.component.css'],
})
export class ModalComponent {
@Input() bsModalRef: BsModalRef;
@Input() type: string;
@Input() data: object;
@Output() closeEvent: EventEmitter<null> = new EventEmitter();
closeModal(modal) {
modal.hide();
this.closeEvent.emit();
}
}
\ No newline at end of file
<accordion>
<accordion-group #ag [isOpen]="true" [panelClass]="'custom-accordion'" class="my-2">
<button class="btn btn-link btn-block clearfix" accordion-heading>
<div class="pull-left float-left">
Direct link to the result (JSON)
&nbsp;
<span *ngIf="ag.isOpen"><i class="fas fa-chevron-up"></i></span>
<span *ngIf="!ag.isOpen"><i class="fas fa-chevron-down"></i></span>
</div>
</button>
<div>
<p>
<a target="_blank" [href]="getUrl()">{{ getUrl() }}</a>
</p>
</div>
</accordion-group>
</accordion>
<accordion-group #ag [isOpen]="true" [panelClass]="'custom-accordion'" class="my-2">
<button class="btn btn-link btn-block clearfix" accordion-heading>
<div class="pull-left float-left">
Direct link to the result (JSON)
&nbsp;
<span *ngIf="ag.isOpen"><i class="fas fa-chevron-up"></i></span>
<span *ngIf="!ag.isOpen"><i class="fas fa-chevron-down"></i></span>
</div>
</button>
<div>
<div *ngIf="isLoading()" class="text-center">
<i class="fas fa-circle-notch fa-spin fa-3x"></i>
<span class="sr-only">Loading...</span>
</div>
<p *ngIf="!isLoading()">
<a target="_blank" [href]="getUrl()">{{ getUrl() }}</a>
</p>
</div>
</accordion-group>
</accordion>
\ No newline at end of file
import { Component, Input, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core';
import { Component, Input, ChangeDetectionStrategy } from '@angular/core';
import { Criterion } from '../store/model';
@Component({
selector: 'app-url-display',
templateUrl: 'url-display.component.html',
styleUrls: [ 'url-display.component.css' ],
styleUrls: ['url-display.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UrlDisplayComponent {
......@@ -14,6 +14,13 @@ export class UrlDisplayComponent {
@Input() criteriaList: Criterion[];
@Input() outputList: number[];
isLoading(): boolean {
if (this.outputList.length > 0) {
return false;
}
return true;
}
getUrl() {
let query = this.apiPath + '/data/' + this.datasetName + '?a=' + this.outputList.join(';');
if (this.criteriaList.length > 0) {
......
<!-- <div class="row mt-4">
<div class="col-12 col-md-8">
<app-url-display
[apiPath]="apiPath"
[datasetName]="datasetName | async"
[criteriaList]="criteriaList | async"
[outputList]="outputList | async">
</app-url-display>
<app-datatable
[datasetAttributeList]="datasetAttributeList | async"
[searchMeta]="searchMeta | async"
[searchData]="searchData | async"
(initSearchMeta)="getSearchMeta()"
(getSearchData)="getSearchData($event)">
</app-datatable>
</div>
<div class="col-12 col-md-4 pt-2">
<app-summary
[datasetName]="datasetName | async"
[currentStep]="currentStep | async"
[datasetList]="datasetList | async"
[criteriaList]="criteriaList | async"
[datasetAttributeList]="datasetAttributeList | async"
[outputList]="outputList | async">
</app-summary>
</div>
</div>
<div class="row mt-5 justify-content-between">
<div class="col">
<a routerLink="/search/output/{{ datasetName | async }}" class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> Previous</a>
</div>
</div> -->
<div>Detail component</div>
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';
import { environment } from '../../../environments/environment';
import { Criterion, SearchMeta } from '../store/model';
import { Dataset, Family, Category, Attribute } from '../../metamodel/model';
import * as searchActions from '../store/search.action';
import * as datasetActions from '../../metamodel/action/dataset.action';
import * as criteriaActions from '../../metamodel/action/criteria.action';
import * as outputActions from '../../metamodel/action/output.action';
import * as fromSearch from '../store/search.reducer';
import * as fromMetamodel from '../../metamodel/reducers';
import * as searchSelector from '../store/search.selector';
import * as metamodelSelector from '../../metamodel/selectors';
interface StoreState {
search: fromSearch.State;
metamodel: fromMetamodel.State;
}
@Component({
selector: 'app-detail-page',
templateUrl: 'detail.component.html',
styleUrls: [ 'detail.component.css' ]
})
export class DetailComponent implements OnInit {
constructor(private route: ActivatedRoute, private store: Store<StoreState>) {
}
ngOnInit() {}
}
......@@ -6,7 +6,9 @@
[criteriaList]="criteriaList | async"
[outputList]="outputList | async">
</app-url-display>
<app-datatable
<app-datatable
[datasetName]="datasetName | async"
[datasetAttributeList]="datasetAttributeList | async"
[searchMeta]="searchMeta | async"
[searchData]="searchData | async"
(initSearchMeta)="getSearchMeta()"
......@@ -26,6 +28,6 @@
</div>
<div class="row mt-5 justify-content-between">
<div class="col">
<a routerLink="/search/output/{{datasetName | async}}" class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> Previous</a>
<a routerLink="/search/output/{{ datasetName | async }}" class="btn btn-outline-secondary"><i class="fas fa-arrow-left"></i> Previous</a>
</div>
</div>
\ No newline at end of file
......@@ -28,7 +28,7 @@ interface StoreState {
})
export class ResultComponent implements OnInit {
public apiPath: string = environment.apiUrl + '/search';
public datasetName: Observable<String>;
public datasetName: Observable<string>;
public currentStep: Observable<string>;
public datasetList: Observable<Dataset[]>;
public datasetAttributeList: Observable<Attribute[]>;
......
......@@ -6,20 +6,24 @@ import { DatasetComponent } from './containers/dataset.component';
import { CriteriaComponent } from './containers/criteria.component';
import { OutputComponent } from './containers/output.component';
import { ResultComponent } from './containers/result.component';
import { DetailComponent } from './containers/detail.component';
const routes: Routes = [
{ path: 'search', component: SearchComponent, children: [
{ path: '', redirectTo: 'dataset', pathMatch: 'full' },
{ path: 'dataset', component: DatasetComponent },
{ path: 'criteria/:dname', component: CriteriaComponent },
{ path: 'output/:dname', component: OutputComponent },
{ path: 'result/:dname', component: ResultComponent }
]}
{
path: 'search', component: SearchComponent, children: [
{ path: '', redirectTo: 'dataset', pathMatch: 'full' },
{ path: 'dataset', component: DatasetComponent },
{ path: 'criteria/:dname', component: CriteriaComponent },
{ path: 'output/:dname', component: OutputComponent },
{ path: 'result/:dname', component: ResultComponent },
{ path: 'detail/:dname/:id', component: DetailComponent }
]
}
];
@NgModule({
imports: [ RouterModule.forChild(routes) ],
exports: [ RouterModule ]
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SearchRoutingModule { }
......@@ -28,5 +32,6 @@ export const routedComponents = [
DatasetComponent,
CriteriaComponent,
OutputComponent,
ResultComponent
ResultComponent,
DetailComponent
];
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment