From 1a6504bfb0c7535005c35480d4cfc761ad7eb66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr> Date: Wed, 6 Jul 2022 21:50:14 +0200 Subject: [PATCH] Refactor detail page => WIP 2 --- .../detail/default-object.component.html | 11 --- .../detail/default-object.component.spec.ts | 34 ------- .../detail/default-object.component.ts | 29 ------ .../search/components/detail/index.ts | 9 -- .../detail/object-data.component.html | 58 ----------- .../detail/object-data.component.spec.ts | 49 ---------- .../detail/object-data.component.ts | 86 ----------------- .../search/components/detail/spectra/index.ts | 7 -- .../spectra/spectra-object.component.html | 35 ------- .../spectra/spectra-object.component.scss | 13 --- .../spectra/spectra-object.component.spec.ts | 52 ---------- .../spectra/spectra-object.component.ts | 82 ---------------- .../app/instance/search/components/index.ts | 4 +- .../components/detail-content.component.html | 6 +- .../components/detail-content.component.ts | 18 +++- .../detail/containers/detail.component.html | 1 + .../instance/search/detail/detail.module.ts | 12 ++- .../dynamic-content/components/index.ts | 14 --- .../display-object.component.html | 0 .../display-object.component.ts | 5 +- .../display-ra-dec.component.html | 11 +++ .../display-ra-dec.component.ts | 36 +++++++ .../display-spectra.component.html | 1 + .../display-spectra.component.ts | 47 +++++++++ .../dynamic-components/index.ts | 12 ++- .../spectra-graph}/point.ts | 0 .../dynamic-components/spectra-graph}/rays.ts | 0 .../spectra-graph.component.html | 0 .../spectra-graph.component.scss | 0 .../spectra-graph}/spectra-graph.component.ts | 0 .../spectra-graph}/spectra-type.ts | 0 .../dynamic-content/dynamic-content.module.ts | 53 ---------- .../search/detail/dynamic-content/index.ts | 14 +++ .../detail/dynamic-content/parsers/index.ts | 4 +- .../instance/store/effects/detail.effects.ts | 4 +- .../instance/store/services/detail.service.ts | 4 +- .../components/datatable.component.html | 0 .../components/datatable.component.ts | 0 .../app/instance/webpage/components/index.ts | 4 +- .../components/webpage-content.component.html | 2 +- .../components/webpage-content.component.ts | 14 ++- .../dynamic-content/components/index.ts | 14 --- .../dynamic-router-link.component.html | 18 ---- .../dynamic-router-link.component.scss | 3 - .../dynamic-router-link.component.ts | 18 ---- .../dynamic-components/index.ts | 4 +- .../dynamic-content/dynamic-content.module.ts | 53 ---------- .../instance/webpage/dynamic-content/index.ts | 14 +++ .../parsers/dynamic-router-link-parser.ts | 96 ------------------- .../webpage/dynamic-content/parsers/index.ts | 4 +- .../app/instance/webpage/webpage.module.ts | 12 ++- .../dynamic-router-link.component.html | 0 .../dynamic-router-link.component.scss | 0 .../dynamic-router-link.component.ts | 0 .../dynamic-components/index.ts | 5 + .../src/app/shared/dynamic-content/index.ts | 14 +++ .../parsers/dynamic-router-link-parser.ts | 2 +- .../shared/dynamic-content/parsers/index.ts | 5 + client/src/app/shared/shared.module.ts | 18 +++- conf-dev/create-db.sh | 8 +- 60 files changed, 244 insertions(+), 775 deletions(-) delete mode 100644 client/src/app/instance/search/components/detail/default-object.component.html delete mode 100644 client/src/app/instance/search/components/detail/default-object.component.spec.ts delete mode 100644 client/src/app/instance/search/components/detail/default-object.component.ts delete mode 100644 client/src/app/instance/search/components/detail/index.ts delete mode 100644 client/src/app/instance/search/components/detail/object-data.component.html delete mode 100644 client/src/app/instance/search/components/detail/object-data.component.spec.ts delete mode 100644 client/src/app/instance/search/components/detail/object-data.component.ts delete mode 100644 client/src/app/instance/search/components/detail/spectra/index.ts delete mode 100644 client/src/app/instance/search/components/detail/spectra/spectra-object.component.html delete mode 100644 client/src/app/instance/search/components/detail/spectra/spectra-object.component.scss delete mode 100644 client/src/app/instance/search/components/detail/spectra/spectra-object.component.spec.ts delete mode 100644 client/src/app/instance/search/components/detail/spectra/spectra-object.component.ts delete mode 100644 client/src/app/instance/search/detail/dynamic-content/components/index.ts rename client/src/app/instance/search/detail/dynamic-content/{components => dynamic-components}/display-object.component.html (100%) rename client/src/app/instance/search/detail/dynamic-content/{components => dynamic-components}/display-object.component.ts (85%) create mode 100644 client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html create mode 100644 client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.ts create mode 100644 client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html create mode 100644 client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.ts rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/point.ts (100%) rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/rays.ts (100%) rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/spectra-graph.component.html (100%) rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/spectra-graph.component.scss (100%) rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/spectra-graph.component.ts (100%) rename client/src/app/instance/search/{components/detail/spectra/graph => detail/dynamic-content/dynamic-components/spectra-graph}/spectra-type.ts (100%) delete mode 100644 client/src/app/instance/search/detail/dynamic-content/dynamic-content.module.ts create mode 100644 client/src/app/instance/search/detail/dynamic-content/index.ts rename client/src/app/instance/webpage/{dynamic-content => }/components/datatable.component.html (100%) rename client/src/app/instance/webpage/{dynamic-content => }/components/datatable.component.ts (100%) delete mode 100644 client/src/app/instance/webpage/dynamic-content/components/index.ts delete mode 100644 client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.html delete mode 100644 client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.scss delete mode 100644 client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.ts delete mode 100644 client/src/app/instance/webpage/dynamic-content/dynamic-content.module.ts create mode 100644 client/src/app/instance/webpage/dynamic-content/index.ts delete mode 100644 client/src/app/instance/webpage/dynamic-content/parsers/dynamic-router-link-parser.ts rename client/src/app/{instance/search/detail => shared}/dynamic-content/dynamic-components/dynamic-router-link.component.html (100%) rename client/src/app/{instance/search/detail => shared}/dynamic-content/dynamic-components/dynamic-router-link.component.scss (100%) rename client/src/app/{instance/search/detail => shared}/dynamic-content/dynamic-components/dynamic-router-link.component.ts (100%) create mode 100644 client/src/app/shared/dynamic-content/dynamic-components/index.ts create mode 100644 client/src/app/shared/dynamic-content/index.ts rename client/src/app/{instance/search/detail => shared}/dynamic-content/parsers/dynamic-router-link-parser.ts (99%) create mode 100644 client/src/app/shared/dynamic-content/parsers/index.ts diff --git a/client/src/app/instance/search/components/detail/default-object.component.html b/client/src/app/instance/search/components/detail/default-object.component.html deleted file mode 100644 index bc6843ae..00000000 --- a/client/src/app/instance/search/components/detail/default-object.component.html +++ /dev/null @@ -1,11 +0,0 @@ -<div class="row justify-content-center"> - <div class="col col-lg-10 col-xl-8 mt-4"> - <app-object-data - [datasetSelected]="datasetSelected" - [outputFamilyList]="outputFamilyList" - [outputCategoryList]="outputCategoryList" - [attributeList]="attributeList" - [object]="object"> - </app-object-data> - </div> -</div> diff --git a/client/src/app/instance/search/components/detail/default-object.component.spec.ts b/client/src/app/instance/search/components/detail/default-object.component.spec.ts deleted file mode 100644 index 24698efe..00000000 --- a/client/src/app/instance/search/components/detail/default-object.component.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { Component, Input } from '@angular/core'; - -import { DefaultObjectComponent } from './default-object.component'; -import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; - -describe('[Instance][Search][Component][Detail][Default] DefaultObjectComponent', () => { - @Component({ selector: 'app-object-data', template: '' }) - class ObjectDataStubComponent { - @Input() datasetSelected: string; - @Input() outputFamilyList: OutputFamily[]; - @Input() outputCategoryList: OutputCategory[]; - @Input() attributeList: Attribute[]; - @Input() object: any; - } - - let component: DefaultObjectComponent; - let fixture: ComponentFixture<DefaultObjectComponent>; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ - DefaultObjectComponent, - ObjectDataStubComponent - ] - }); - fixture = TestBed.createComponent(DefaultObjectComponent); - component = fixture.componentInstance; - })); - - it('should create the component', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/client/src/app/instance/search/components/detail/default-object.component.ts b/client/src/app/instance/search/components/detail/default-object.component.ts deleted file mode 100644 index b690b814..00000000 --- a/client/src/app/instance/search/components/detail/default-object.component.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; - -import { Attribute, OutputFamily, OutputCategory } from 'src/app/metamodel/models'; - -/** - * @class - * @classdesc Detail default object component. - */ -@Component({ - selector: 'app-default-object', - templateUrl: 'default-object.component.html', - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class DefaultObjectComponent { - @Input() datasetSelected: string; - @Input() outputFamilyList: OutputFamily[]; - @Input() outputCategoryList: OutputCategory[]; - @Input() attributeList: Attribute[]; - @Input() object: any; -} diff --git a/client/src/app/instance/search/components/detail/index.ts b/client/src/app/instance/search/components/detail/index.ts deleted file mode 100644 index 86a0c1e9..00000000 --- a/client/src/app/instance/search/components/detail/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ObjectDataComponent } from './object-data.component'; -import { DefaultObjectComponent } from './default-object.component'; -import { spectraComponents } from './spectra'; - -export const detailsComponents = [ - ObjectDataComponent, - DefaultObjectComponent, - spectraComponents -]; diff --git a/client/src/app/instance/search/components/detail/object-data.component.html b/client/src/app/instance/search/components/detail/object-data.component.html deleted file mode 100644 index e9411be0..00000000 --- a/client/src/app/instance/search/components/detail/object-data.component.html +++ /dev/null @@ -1,58 +0,0 @@ -<div *ngIf="getAttributeRa() && getAttributeDec()" class="row"> - <div class="col-12"> - <table class="table mb-1" aria-describedby="Object coordinates"> - <tr> - <th scope="col">Alpha</th> - <th scope="col">Delta</th> - <th scope="col" class="text-center" rowspan="2"><img src="assets/cesam_anis80.png" alt="CeSAM logo" /></th> - </tr> - <tr> - <td>{{ object[getAttributeRa().label] }}</td> - <td>{{ object[getAttributeDec().label] }}</td> - </tr> - </table> - <hr class="mt-0 mb-4"> - </div> -</div> - -<!-- Accordion families --> -<accordion [isAnimated]="true"> - <accordion-group *ngFor="let family of outputFamilyList" #ag [isOpen]="true" class="pl-2"> - <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> - <span class="pull-left float-left text-primary"> - {{ family.label }} - - <span *ngIf="ag.isOpen"> - <span class="fas fa-chevron-up"></span> - </span> - <span *ngIf="!ag.isOpen"> - <span class="fas fa-chevron-down"></span> - </span> - </span> - </button> - - <!-- Accordion categories --> - <accordion [isAnimated]="true"> - <accordion-group *ngFor="let category of getCategoryByFamily(family.id)" #ag [isOpen]="true" class="pl-4"> - <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> - <span class="pull-left float-left text-primary"> - {{ category.label }} - - <span *ngIf="ag.isOpen"> - <span class="fas fa-chevron-up"></span> - </span> - <span *ngIf="!ag.isOpen"> - <span class="fas fa-chevron-down"></span> - </span> - </span> - </button> - - <!-- Output list --> - <div *ngFor="let attribute of getAttributesVisibleByCategory(category.id)" class="row pb-2"> - <div class="col-5 font-weight-bold">{{ attribute.form_label }}</div> - <div class="col">{{ object[attribute.label] }}</div> - </div> - </accordion-group> - </accordion> - </accordion-group> -</accordion> diff --git a/client/src/app/instance/search/components/detail/object-data.component.spec.ts b/client/src/app/instance/search/components/detail/object-data.component.spec.ts deleted file mode 100644 index cdc9ba29..00000000 --- a/client/src/app/instance/search/components/detail/object-data.component.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; - -import { AccordionModule } from 'ngx-bootstrap/accordion'; - -import { ObjectDataComponent } from './object-data.component'; -import { AppConfigService } from '../../../../app-config.service'; -import { ATTRIBUTE_LIST, CATEGORY_LIST } from '../../../../../test-data'; - -describe('[Instance][Search][Component][Detail] ObjectDataComponent', () => { - let component: ObjectDataComponent; - let fixture: ComponentFixture<ObjectDataComponent>; - let appConfigServiceStub = new AppConfigService(); - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [ObjectDataComponent], - imports: [AccordionModule.forRoot()], - providers: [{ provide: AppConfigService, useValue: appConfigServiceStub }] - }); - fixture = TestBed.createComponent(ObjectDataComponent); - component = fixture.componentInstance; - })); - - it('should create the component', () => { - expect(component).toBeTruthy(); - }); - - it('#getCategoryByFamily() should return categories for the given family', () => { - component.outputCategoryList = CATEGORY_LIST; - expect(component.getCategoryByFamily(1).length).toEqual(2); - }); - - it('#getAttributesVisibleByCategory() should return visible attributes for the given category', () => { - component.attributeList = ATTRIBUTE_LIST; - expect(component.getAttributesVisibleByCategory(1).length).toEqual(1); - expect(component.getAttributesVisibleByCategory(1)[0].id).toEqual(2); - }); - - it('#getAttributesVisible() should return visible attributes', () => { - component.attributeList = ATTRIBUTE_LIST; - expect(component.getAttributesVisible().length).toEqual(2); - }); - - it('#getDownloadHref() should return URL', () => { - appConfigServiceStub.apiUrl = 'http://test.com'; - component.datasetSelected = 'myDataset'; - expect(component.getDownloadHref('myAttributeLabel')).toEqual('http://test.com/download-file/myDataset/myAttributeLabel'); - }); -}); diff --git a/client/src/app/instance/search/components/detail/object-data.component.ts b/client/src/app/instance/search/components/detail/object-data.component.ts deleted file mode 100644 index 34068a6f..00000000 --- a/client/src/app/instance/search/components/detail/object-data.component.ts +++ /dev/null @@ -1,86 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; - -import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; -import { getHost } from 'src/app/shared/utils'; -import { AppConfigService } from 'src/app/app-config.service'; - -/** - * @class - * @classdesc Detail object data component. - */ -@Component({ - selector: 'app-object-data', - templateUrl: 'object-data.component.html', - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class ObjectDataComponent { - @Input() datasetSelected: string; - @Input() outputFamilyList: OutputFamily[]; - @Input() outputCategoryList: OutputCategory[]; - @Input() attributeList: Attribute[]; - @Input() object: any; - - constructor(private appConfig: AppConfigService) { } - - /** - * Returns category list for the given output family ID. - * - * @param {number} idFamily - The output family ID. - * - * @return OutputCategory[] - */ - getCategoryByFamily(idFamily: number): OutputCategory[] { - return this.outputCategoryList - .filter(category => category.id_output_family === idFamily); - } - - /** - * Returns attribute list for the given output category ID that are visible in detail page. - * - * @param {number} idCategory - The output category ID. - * - * @return Attribute[] - */ - getAttributesVisibleByCategory(idCategory: number): Attribute[] { - return this.attributeList - .filter(a => a.id_detail_output_category) - .filter(a => a.id_output_category === idCategory); - } - - /** - * Returns attribute list that are visible in detail page. - * - * @return Attribute[] - */ - getAttributesVisible(): Attribute[] { - return this.attributeList.filter(a => a.id_detail_output_category); - } - - /** - * Returns URL where download object. - * - * @param {string} attributeLabel - The attribute label. - * - * @return string - */ - getDownloadHref(attributeLabel: string): string { - return `${getHost(this.appConfig.apiUrl)}/download-file/${this.datasetSelected}/${attributeLabel}`; - } - - getAttributeRa() { - return this.attributeList[2]; - } - - getAttributeDec() { - return this.attributeList[3]; - } -} diff --git a/client/src/app/instance/search/components/detail/spectra/index.ts b/client/src/app/instance/search/components/detail/spectra/index.ts deleted file mode 100644 index 77b5e039..00000000 --- a/client/src/app/instance/search/components/detail/spectra/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { SpectraObjectComponent } from "./spectra-object.component"; -import { SpectraGraphComponent } from "./graph/spectra-graph.component"; - -export const spectraComponents = [ - SpectraObjectComponent, - SpectraGraphComponent -]; diff --git a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.html b/client/src/app/instance/search/components/detail/spectra/spectra-object.component.html deleted file mode 100644 index 8e1360dc..00000000 --- a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.html +++ /dev/null @@ -1,35 +0,0 @@ -<div class="row"> - <div *ngIf="getAttributeSpectraGraph()" class="col col-md-8 col-sm-12"> - <div *ngIf="spectraIsLoading" id="div-spinner" class="text-center"> - <span class="fas fa-circle-notch fa-spin fa-3x"></span> - <span class="sr-only">Loading...</span> - </div> - <app-spectra-graph *ngIf="spectraIsLoaded" [z]="getZ()" [spectraCSV]="spectraCSV"></app-spectra-graph> - </div> - - <div [ngClass]="{'col-md-4 col-sm-12': getAttributeSpectraGraph()}" class="col mt-4"> - <div *ngIf="getSpectra()" class="jumbotron row mb-3 p-4"> - <div class="col-auto align-self-center"> - <p>Download:</p> - </div> - <div class="w-100 d-block d-xl-none"></div> - <div class="col"> - <div class="row justify-content-center"> - <div class="col-auto"> - <a [href]="getSpectra()" class="btn btn-lg btn-block dl-btn"> - Download SPECTRA archive - </a> - </div> - </div> - </div> - </div> - - <app-object-data - [datasetSelected]="datasetSelected" - [outputFamilyList]="outputFamilyList" - [outputCategoryList]="outputCategoryList" - [attributeList]="attributeList" - [object]="object"> - </app-object-data> - </div> -</div> diff --git a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.scss b/client/src/app/instance/search/components/detail/spectra/spectra-object.component.scss deleted file mode 100644 index 260a2036..00000000 --- a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.scss +++ /dev/null @@ -1,13 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -.dl-btn { - height: 80px; - display: inline-block; -} diff --git a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.spec.ts b/client/src/app/instance/search/components/detail/spectra/spectra-object.component.spec.ts deleted file mode 100644 index 890caacf..00000000 --- a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { Component, Input } from '@angular/core'; - -import { SpectraObjectComponent } from './spectra-object.component'; -import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; -import { AppConfigService } from 'src/app/app-config.service'; -import { ATTRIBUTE_LIST, OBJECT_DETAIL } from 'src/test-data'; - -describe('[Instance][Search][Component][Detail][Spectra] SpectraObjectComponent', () => { - @Component({ selector: 'app-spectra-graph', template: '' }) - class SpectraGraphStubComponent { - @Input() z: number; - @Input() spectraCSV: string; - } - - @Component({ selector: 'app-object-data', template: '' }) - class ObjectDataStubComponent { - @Input() datasetSelected: string; - @Input() outputFamilyList: OutputFamily[]; - @Input() outputCategoryList: OutputCategory[]; - @Input() attributeList: Attribute[]; - @Input() object: any; - } - - let component: SpectraObjectComponent; - let fixture: ComponentFixture<SpectraObjectComponent>; - let appConfigServiceStub = new AppConfigService(); - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [ - SpectraObjectComponent, - SpectraGraphStubComponent, - ObjectDataStubComponent - ], - providers: [{ provide: AppConfigService, useValue: appConfigServiceStub }] - }); - fixture = TestBed.createComponent(SpectraObjectComponent); - component = fixture.componentInstance; - }); - - it('should create the component', () => { - expect(component).toBeTruthy(); - }); - - it('#ngOnInit() should emit getSpectraCSV event if an attribute have spectra_graph renderer_detail', () => { - component.attributeList = ATTRIBUTE_LIST; - component.object = OBJECT_DETAIL; - component.getSpectraCSV.subscribe((event: string) => expect(event).toEqual('spec1d')); - component.ngOnInit(); - }); -}); diff --git a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.ts b/client/src/app/instance/search/components/detail/spectra/spectra-object.component.ts deleted file mode 100644 index aa64933c..00000000 --- a/client/src/app/instance/search/components/detail/spectra/spectra-object.component.ts +++ /dev/null @@ -1,82 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { Component, Input, ChangeDetectionStrategy, Output, EventEmitter, OnInit } from '@angular/core'; - -import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; -import { getHost } from 'src/app/shared/utils'; -import { AppConfigService } from 'src/app/app-config.service'; - -/** - * @class - * @classdesc Detail spectra object component. - * - * @implements OnInit - */ -@Component({ - selector: 'app-spectra-object', - templateUrl: 'spectra-object.component.html', - styleUrls: ['spectra-object.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush -}) -export class SpectraObjectComponent implements OnInit { - @Input() datasetSelected: string; - @Input() outputFamilyList: OutputFamily[]; - @Input() outputCategoryList: OutputCategory[]; - @Input() attributeList: Attribute[]; - @Input() object: any; - @Input() spectraIsLoading: boolean; - @Input() spectraIsLoaded: boolean; - @Input() spectraCSV: string; - @Output() getSpectraCSV: EventEmitter<string> = new EventEmitter(); - - constructor(private appConfig: AppConfigService) { } - - ngOnInit(): void { - const attributeSpectraGraph = this.getAttributeSpectraGraph(); - if (attributeSpectraGraph) { - Promise.resolve(null).then(() => this.getSpectraCSV.emit(this.object[attributeSpectraGraph.label])); - } - } - - /** - * Returns spectra file URL. - * - * @return string - */ - getSpectra(): string { - const spectraAttribute = this.attributeList[0]; - return `${getHost(this.appConfig.apiUrl)}/download-file/${this.datasetSelected}/${this.object[spectraAttribute.label]}`; - } - - /** - * Returns detail rendered spectra graph attribute. - * - * @return Attribute - */ - getAttributeSpectraGraph(): Attribute { - return this.attributeList[1]; - } - - /** - * Returns Z. - * - * @return number - */ - getZ(): number { - return 0; - // const spectraGraphRendererConfig = this.getAttributeSpectraGraph().renderer_detail_config as SpectraGraphRendererConfig; - // if (spectraGraphRendererConfig.z) { - // const attributeZ = this.attributeList.find(attribute => attribute.id === spectraGraphRendererConfig.z); - // return +this.object[attributeZ.label]; - // } else { - // return 0; - // } - } -} diff --git a/client/src/app/instance/search/components/index.ts b/client/src/app/instance/search/components/index.ts index f4057d78..9a0df624 100644 --- a/client/src/app/instance/search/components/index.ts +++ b/client/src/app/instance/search/components/index.ts @@ -4,7 +4,6 @@ import { datasetComponents } from './dataset'; import { criteriaComponents } from './criteria'; import { outputComponents } from './output'; import { resultComponents } from './result'; -import { detailsComponents } from './detail'; export const dummiesComponents = [ ProgressBarComponent, @@ -12,6 +11,5 @@ export const dummiesComponents = [ datasetComponents, criteriaComponents, outputComponents, - resultComponents, - detailsComponents + resultComponents ]; \ No newline at end of file diff --git a/client/src/app/instance/search/detail/components/detail-content.component.html b/client/src/app/instance/search/detail/components/detail-content.component.html index daab406d..b0961d8f 100644 --- a/client/src/app/instance/search/detail/components/detail-content.component.html +++ b/client/src/app/instance/search/detail/components/detail-content.component.html @@ -1 +1,5 @@ -<ngx-dynamic-hooks [content]="detailConfig.content" [context]="getContext()"></ngx-dynamic-hooks> \ No newline at end of file +<ngx-dynamic-hooks + [content]="detailConfig.content" + [parsers]="getParsers()" + [context]="getContext()"> +</ngx-dynamic-hooks> diff --git a/client/src/app/instance/search/detail/components/detail-content.component.ts b/client/src/app/instance/search/detail/components/detail-content.component.ts index 4e1adf83..ca7dfd60 100644 --- a/client/src/app/instance/search/detail/components/detail-content.component.ts +++ b/client/src/app/instance/search/detail/components/detail-content.component.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ -import { Component, Input } from '@angular/core'; +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; -import { DetailConfig, Attribute, OutputFamily, OutputCategory} from 'src/app/metamodel/models'; +import { DetailConfig, Dataset, Attribute, OutputFamily, OutputCategory } from 'src/app/metamodel/models'; +import { globalParsers } from 'src/app/shared/dynamic-content'; +import { componentParsers } from '../dynamic-content'; /** * @class @@ -17,18 +19,28 @@ import { DetailConfig, Attribute, OutputFamily, OutputCategory} from 'src/app/me */ @Component({ selector: 'app-detail-content', - templateUrl: 'detail-content.component.html' + templateUrl: 'detail-content.component.html', + changeDetection: ChangeDetectionStrategy.OnPush }) export class DetailContentComponent { @Input() detailConfig: DetailConfig; @Input() object: any; + @Input() datasetName: string; @Input() attributeList: Attribute[]; @Input() outputFamilyList: OutputFamily[]; @Input() outputCategoryList: OutputCategory[]; + getParsers() { + return [ + ...globalParsers, + ...componentParsers + ]; + } + getContext() { return { object: this.object, + datasetName: this.datasetName, attributeList: this.attributeList, outputFamilyList: this.outputFamilyList, outputCategoryList: this.outputCategoryList diff --git a/client/src/app/instance/search/detail/containers/detail.component.html b/client/src/app/instance/search/detail/containers/detail.component.html index 9fc60ad4..22aab0c4 100644 --- a/client/src/app/instance/search/detail/containers/detail.component.html +++ b/client/src/app/instance/search/detail/containers/detail.component.html @@ -20,6 +20,7 @@ <app-detail-content [detailConfig]="detailConfig | async" [object]="object | async" + [datasetName]="datasetSelected | async" [attributeList]="attributeList | async" [outputFamilyList]="outputFamilyList | async" [outputCategoryList]="outputCategoryList | async"> diff --git a/client/src/app/instance/search/detail/detail.module.ts b/client/src/app/instance/search/detail/detail.module.ts index a23e0508..f272f917 100644 --- a/client/src/app/instance/search/detail/detail.module.ts +++ b/client/src/app/instance/search/detail/detail.module.ts @@ -10,9 +10,9 @@ import { NgModule } from '@angular/core'; import { SharedModule } from 'src/app/shared/shared.module'; -import { DynamicContentModule } from './dynamic-content/dynamic-content.module'; import { DetailRoutingModule, routedComponents } from './detail-routing.module'; import { dummiesComponents } from './components'; +import { hookParsers, dynamicComponents } from './dynamic-content'; /** * @class @@ -21,12 +21,18 @@ import { dummiesComponents } from './components'; @NgModule({ imports: [ SharedModule, - DynamicContentModule, DetailRoutingModule ], declarations: [ routedComponents, - dummiesComponents + dummiesComponents, + dynamicComponents + ], + entryComponents: [ + dynamicComponents + ], + providers: [ + hookParsers ] }) export class DetailModule { } diff --git a/client/src/app/instance/search/detail/dynamic-content/components/index.ts b/client/src/app/instance/search/detail/dynamic-content/components/index.ts deleted file mode 100644 index ff4f0ea4..00000000 --- a/client/src/app/instance/search/detail/dynamic-content/components/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { DisplayObjectComponent } from './display-object.component'; - -export const dummiesComponents = [ - DisplayObjectComponent -]; diff --git a/client/src/app/instance/search/detail/dynamic-content/components/display-object.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html similarity index 100% rename from client/src/app/instance/search/detail/dynamic-content/components/display-object.component.html rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html diff --git a/client/src/app/instance/search/detail/dynamic-content/components/display-object.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts similarity index 85% rename from client/src/app/instance/search/detail/dynamic-content/components/display-object.component.ts rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts index c290ab7e..1c029c11 100644 --- a/client/src/app/instance/search/detail/dynamic-content/components/display-object.component.ts +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, Input } from '@angular/core'; +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; @@ -17,7 +17,8 @@ import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/model */ @Component({ selector: 'app-display-object', - templateUrl: 'display-object.component.html' + templateUrl: 'display-object.component.html', + changeDetection: ChangeDetectionStrategy.OnPush }) export class DisplayObjectComponent { @Input() object: any; diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html new file mode 100644 index 00000000..b779cc47 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html @@ -0,0 +1,11 @@ +<table class="table mb-1" aria-describedby="Object coordinates"> + <tr> + <th scope="col">Alpha</th> + <th scope="col">Delta</th> + <th scope="col" class="text-center" rowspan="2"><img src="assets/cesam_anis80.png" alt="CeSAM logo" /></th> + </tr> + <tr> + <td>{{ object[getAttributeRa().label] }}</td> + <td>{{ object[getAttributeDec().label] }}</td> + </tr> +</table> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.ts new file mode 100644 index 00000000..4715be9b --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.ts @@ -0,0 +1,36 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; + +import { Attribute } from 'src/app/metamodel/models'; + +/** + * @class + * @classdesc Display object component. + */ +@Component({ + selector: 'app-display-ra-dec', + templateUrl: 'display-ra-dec.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplayRaDecComponent { + @Input() object: any; + @Input() attributeList: Attribute[]; + @Input() attributeRaId: number; + @Input() attributeDecId: number; + + getAttributeRa() { + return this.attributeList.find(attribute => attribute.id === this.attributeRaId); + } + + getAttributeDec() { + return this.attributeList.find(attribute => attribute.id === this.attributeDecId); + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html new file mode 100644 index 00000000..f908a1e0 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html @@ -0,0 +1 @@ +<app-spectra-graph *ngIf="spectraCSV | async as data" [z]="getZ()" [spectraCSV]="data"></app-spectra-graph> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.ts new file mode 100644 index 00000000..fcf7ffed --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.ts @@ -0,0 +1,47 @@ +/** + * This file is part of Anis Client. + * + * @copyright Laboratoire d'Astrophysique de Marseille / CNRS + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { Observable } from 'rxjs'; + +import { Attribute } from 'src/app/metamodel/models'; +import { AppConfigService } from 'src/app/app-config.service'; + +/** + * @class + * @classdesc Display spectra component. + */ +@Component({ + selector: 'app-display-spectra', + templateUrl: 'display-spectra.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplaySpectraComponent { + @Input() object: any; + @Input() datasetName: string; + @Input() attributeList: Attribute[]; + @Input() attributeSpectraId: number; + @Input() attributeZId: number; + + spectraCSV: Observable<string>; + + constructor(private http: HttpClient, private config: AppConfigService) { } + + ngOnInit() { + const spectraFile = this.object[this.attributeList.find(attribute => attribute.id === this.attributeSpectraId).label]; + this.spectraCSV = this.http.get(`${this.config.servicesUrl}/spectra-to-csv/${this.datasetName}?filename=${spectraFile}`, { responseType: 'text' }); + } + + getZ() { + const z = this.object[this.attributeList.find(attribute => attribute.id === this.attributeZId).label]; + return +z; + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts index 0a6b8f24..8c84be9b 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts @@ -1,5 +1,11 @@ -import { DynamicRouterLinkComponent } from './dynamic-router-link.component'; +import { DisplayObjectComponent } from './display-object.component'; +import { DisplayRaDecComponent } from './display-ra-dec.component'; +import { DisplaySpectraComponent } from './display-spectra.component'; +import { SpectraGraphComponent } from './spectra-graph/spectra-graph.component'; -export const DynamicComponents = [ - DynamicRouterLinkComponent +export const dynamicComponents = [ + DisplayObjectComponent, + DisplayRaDecComponent, + DisplaySpectraComponent, + SpectraGraphComponent ]; diff --git a/client/src/app/instance/search/components/detail/spectra/graph/point.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/point.ts similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/point.ts rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/point.ts diff --git a/client/src/app/instance/search/components/detail/spectra/graph/rays.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/rays.ts similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/rays.ts rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/rays.ts diff --git a/client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.html similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.html rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.html diff --git a/client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.scss b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.scss similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.scss rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.scss diff --git a/client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.ts similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/spectra-graph.component.ts rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-graph.component.ts diff --git a/client/src/app/instance/search/components/detail/spectra/graph/spectra-type.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-type.ts similarity index 100% rename from client/src/app/instance/search/components/detail/spectra/graph/spectra-type.ts rename to client/src/app/instance/search/detail/dynamic-content/dynamic-components/spectra-graph/spectra-type.ts diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-content.module.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-content.module.ts deleted file mode 100644 index 8f4f2781..00000000 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-content.module.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { DynamicHooksModule, HookParserEntry } from 'ngx-dynamic-hooks'; - -import { SharedModule } from 'src/app/shared/shared.module'; -import { hookParsers } from './parsers'; -import { DynamicComponents } from './dynamic-components'; -import { dummiesComponents } from './components'; - -export const componentParsers: Array<HookParserEntry> = [ - ...hookParsers, - ...DynamicComponents.map(component => { - return { component }; - }) -]; - -/** - * @class - * @classdesc Dynamic content module. - */ -@NgModule({ - imports: [ - SharedModule, - RouterModule, - DynamicHooksModule.forRoot({ - globalParsers: componentParsers - }), - ], - exports: [ - DynamicHooksModule - ], - providers: [ - hookParsers - ], - declarations: [ - DynamicComponents, - dummiesComponents - ], - entryComponents: [ - DynamicComponents - ] -}) -export class DynamicContentModule { } diff --git a/client/src/app/instance/search/detail/dynamic-content/index.ts b/client/src/app/instance/search/detail/dynamic-content/index.ts new file mode 100644 index 00000000..a8a58f22 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/index.ts @@ -0,0 +1,14 @@ +import { HookParserEntry } from 'ngx-dynamic-hooks'; + +import { hookParsers } from './parsers'; +import { dynamicComponents } from './dynamic-components'; + +export const componentParsers: Array<HookParserEntry> = [ + ...hookParsers, + ...dynamicComponents.map(component => { + return { component }; + }) +]; + +export { hookParsers } from './parsers'; +export { dynamicComponents } from './dynamic-components'; diff --git a/client/src/app/instance/search/detail/dynamic-content/parsers/index.ts b/client/src/app/instance/search/detail/dynamic-content/parsers/index.ts index bac0c8f9..552c5a60 100644 --- a/client/src/app/instance/search/detail/dynamic-content/parsers/index.ts +++ b/client/src/app/instance/search/detail/dynamic-content/parsers/index.ts @@ -1,5 +1,3 @@ -import { DynamicRouterLinkParser } from './dynamic-router-link-parser'; - export const hookParsers = [ - DynamicRouterLinkParser + ]; diff --git a/client/src/app/instance/store/effects/detail.effects.ts b/client/src/app/instance/store/effects/detail.effects.ts index ce166cfa..b032e8c8 100644 --- a/client/src/app/instance/store/effects/detail.effects.ts +++ b/client/src/app/instance/store/effects/detail.effects.ts @@ -27,7 +27,6 @@ import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; */ @Injectable() export class DetailEffects { - /** * Calls actions to retrieve object. */ @@ -42,8 +41,7 @@ export class DetailEffects { mergeMap(([, datasetName, attributeList, id]) => this.detailService.retrieveObject( datasetName, attributeList.find(attribute => attribute.order_by).id, - id, - attributeList.filter(attribute => attribute.id_detail_output_category).map(attribute => attribute.id) + id ).pipe( map(object => detailActions.retrieveObjectSuccess({ object: object[0] })), catchError(() => of(detailActions.retrieveObjectFail())) diff --git a/client/src/app/instance/store/services/detail.service.ts b/client/src/app/instance/store/services/detail.service.ts index e9b644aa..eee2a624 100644 --- a/client/src/app/instance/store/services/detail.service.ts +++ b/client/src/app/instance/store/services/detail.service.ts @@ -32,8 +32,8 @@ export class DetailService { * * @return Observable<any[]> */ - retrieveObject(dname: string, criterionId: number, objectSelected: string, outputList: number[]): Observable<any[]> { - const query = `${dname}?c=${criterionId}::eq::${objectSelected}&a=${outputList.join(';')}`; + retrieveObject(dname: string, criterionId: number, objectSelected: string): Observable<any[]> { + const query = `${dname}?c=${criterionId}::eq::${objectSelected}&a=all`; return this.http.get<any[]>(`${this.config.apiUrl}/search/${query}`); } diff --git a/client/src/app/instance/webpage/dynamic-content/components/datatable.component.html b/client/src/app/instance/webpage/components/datatable.component.html similarity index 100% rename from client/src/app/instance/webpage/dynamic-content/components/datatable.component.html rename to client/src/app/instance/webpage/components/datatable.component.html diff --git a/client/src/app/instance/webpage/dynamic-content/components/datatable.component.ts b/client/src/app/instance/webpage/components/datatable.component.ts similarity index 100% rename from client/src/app/instance/webpage/dynamic-content/components/datatable.component.ts rename to client/src/app/instance/webpage/components/datatable.component.ts diff --git a/client/src/app/instance/webpage/components/index.ts b/client/src/app/instance/webpage/components/index.ts index 28c122e3..cdbd8374 100644 --- a/client/src/app/instance/webpage/components/index.ts +++ b/client/src/app/instance/webpage/components/index.ts @@ -1,5 +1,7 @@ import { WebpageComponent } from './webpage-content.component'; +import { DatatableComponent } from './datatable.component'; export const dummiesComponents = [ - WebpageComponent + WebpageComponent, + DatatableComponent ]; diff --git a/client/src/app/instance/webpage/components/webpage-content.component.html b/client/src/app/instance/webpage/components/webpage-content.component.html index 99c5e9a4..5fff195d 100644 --- a/client/src/app/instance/webpage/components/webpage-content.component.html +++ b/client/src/app/instance/webpage/components/webpage-content.component.html @@ -1 +1 @@ -<ngx-dynamic-hooks [content]="webpage.content"></ngx-dynamic-hooks> \ No newline at end of file +<ngx-dynamic-hooks [content]="webpage.content" [parsers]="getParsers()"></ngx-dynamic-hooks> \ No newline at end of file diff --git a/client/src/app/instance/webpage/components/webpage-content.component.ts b/client/src/app/instance/webpage/components/webpage-content.component.ts index a8bfd9bb..7559b9c5 100644 --- a/client/src/app/instance/webpage/components/webpage-content.component.ts +++ b/client/src/app/instance/webpage/components/webpage-content.component.ts @@ -7,9 +7,11 @@ * file that was distributed with this source code. */ -import { Component, Input } from '@angular/core'; +import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; import { Webpage } from 'src/app/metamodel/models'; +import { globalParsers } from 'src/app/shared/dynamic-content'; +import { componentParsers } from '../dynamic-content'; /** * @class @@ -17,8 +19,16 @@ import { Webpage } from 'src/app/metamodel/models'; */ @Component({ selector: 'app-webpage-content', - templateUrl: 'webpage-content.component.html' + templateUrl: 'webpage-content.component.html', + changeDetection: ChangeDetectionStrategy.OnPush }) export class WebpageComponent { @Input() webpage: Webpage; + + getParsers() { + return [ + ...globalParsers, + ...componentParsers + ]; + } } diff --git a/client/src/app/instance/webpage/dynamic-content/components/index.ts b/client/src/app/instance/webpage/dynamic-content/components/index.ts deleted file mode 100644 index b3594ebb..00000000 --- a/client/src/app/instance/webpage/dynamic-content/components/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { DatatableComponent } from './datatable.component'; - -export const dummiesComponents = [ - DatatableComponent -]; diff --git a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.html b/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.html deleted file mode 100644 index 2f43ac7e..00000000 --- a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.html +++ /dev/null @@ -1,18 +0,0 @@ -<a *ngIf="isExternalLink()" - [href]="link" - [ngClass]="css" - [target]="target ? target : '_self'" -> - <ng-container *ngTemplateOutlet="contentTpl"></ng-container> -</a> - -<a *ngIf="!isExternalLink()" - [routerLink]="link" - [queryParams]="queryParams ? queryParams : {}" - [fragment]="anchorFragment ? anchorFragment : null" - [ngClass]="css" -> - <ng-container *ngTemplateOutlet="contentTpl"></ng-container> -</a> - -<ng-template #contentTpl><ng-content></ng-content></ng-template> diff --git a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.scss b/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.scss deleted file mode 100644 index 1f0440ee..00000000 --- a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -:host { - display: inline; -} \ No newline at end of file diff --git a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.ts b/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.ts deleted file mode 100644 index d0e20e09..00000000 --- a/client/src/app/instance/webpage/dynamic-content/dynamic-components/dynamic-router-link.component.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Component, Input } from '@angular/core'; - -@Component({ - selector: 'app-dynamic-router-link', - templateUrl: 'dynamic-router-link.component.html', - styleUrls: [ 'dynamic-router-link.component.scss' ] -}) -export class DynamicRouterLinkComponent { - @Input() link: string; - @Input() queryParams: {[key: string]: any}; - @Input() anchorFragment: string; - @Input() css: string; - @Input() target: string; - - isExternalLink() { - return this.link.startsWith('http'); - } -} diff --git a/client/src/app/instance/webpage/dynamic-content/dynamic-components/index.ts b/client/src/app/instance/webpage/dynamic-content/dynamic-components/index.ts index 81f64b14..36671afc 100644 --- a/client/src/app/instance/webpage/dynamic-content/dynamic-components/index.ts +++ b/client/src/app/instance/webpage/dynamic-content/dynamic-components/index.ts @@ -1,7 +1,5 @@ -import { DynamicRouterLinkComponent } from './dynamic-router-link.component'; import { DatasetSampleComponent } from './dataset-sample.component'; -export const DynamicComponents = [ - DynamicRouterLinkComponent, +export const dynamicComponents = [ DatasetSampleComponent ]; diff --git a/client/src/app/instance/webpage/dynamic-content/dynamic-content.module.ts b/client/src/app/instance/webpage/dynamic-content/dynamic-content.module.ts deleted file mode 100644 index 8f4f2781..00000000 --- a/client/src/app/instance/webpage/dynamic-content/dynamic-content.module.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * This file is part of Anis Client. - * - * @copyright Laboratoire d'Astrophysique de Marseille / CNRS - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -import { NgModule } from '@angular/core'; -import { RouterModule } from '@angular/router'; - -import { DynamicHooksModule, HookParserEntry } from 'ngx-dynamic-hooks'; - -import { SharedModule } from 'src/app/shared/shared.module'; -import { hookParsers } from './parsers'; -import { DynamicComponents } from './dynamic-components'; -import { dummiesComponents } from './components'; - -export const componentParsers: Array<HookParserEntry> = [ - ...hookParsers, - ...DynamicComponents.map(component => { - return { component }; - }) -]; - -/** - * @class - * @classdesc Dynamic content module. - */ -@NgModule({ - imports: [ - SharedModule, - RouterModule, - DynamicHooksModule.forRoot({ - globalParsers: componentParsers - }), - ], - exports: [ - DynamicHooksModule - ], - providers: [ - hookParsers - ], - declarations: [ - DynamicComponents, - dummiesComponents - ], - entryComponents: [ - DynamicComponents - ] -}) -export class DynamicContentModule { } diff --git a/client/src/app/instance/webpage/dynamic-content/index.ts b/client/src/app/instance/webpage/dynamic-content/index.ts new file mode 100644 index 00000000..a8a58f22 --- /dev/null +++ b/client/src/app/instance/webpage/dynamic-content/index.ts @@ -0,0 +1,14 @@ +import { HookParserEntry } from 'ngx-dynamic-hooks'; + +import { hookParsers } from './parsers'; +import { dynamicComponents } from './dynamic-components'; + +export const componentParsers: Array<HookParserEntry> = [ + ...hookParsers, + ...dynamicComponents.map(component => { + return { component }; + }) +]; + +export { hookParsers } from './parsers'; +export { dynamicComponents } from './dynamic-components'; diff --git a/client/src/app/instance/webpage/dynamic-content/parsers/dynamic-router-link-parser.ts b/client/src/app/instance/webpage/dynamic-content/parsers/dynamic-router-link-parser.ts deleted file mode 100644 index cb543c79..00000000 --- a/client/src/app/instance/webpage/dynamic-content/parsers/dynamic-router-link-parser.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Injectable } from '@angular/core'; -import { HookParser, HookPosition, HookValue, HookComponentData, HookBindings, HookFinder } from 'ngx-dynamic-hooks'; - -import { DynamicRouterLinkComponent } from '../dynamic-components/dynamic-router-link.component'; - -@Injectable() -export class DynamicRouterLinkParser implements HookParser { - linkOpeningTagRegex: RegExp; - linkClosingTagRegex: RegExp; - hrefAttrRegex: RegExp; - classAttrRegex: RegExp; - targetAttrRegex: RegExp; - - constructor(private hookFinder: HookFinder) { - const hrefAttr = '\\s+href\=\\"([^\\"]*?)\\"'; - const anyOtherAttr = '\\s+[a-zA-Z]+\\=\\"[^\\"]*?\\"'; - const linkOpeningTag = '\\<a(?:' + anyOtherAttr + ')*?' + hrefAttr + '(?:' + anyOtherAttr + ')*?\\>'; - - // Transform into proper regex objects and save for later - this.linkOpeningTagRegex = new RegExp(linkOpeningTag, 'gim'); - this.linkClosingTagRegex = new RegExp('<\\/a>', 'gim'); - this.hrefAttrRegex = new RegExp(hrefAttr, 'im'); - this.classAttrRegex = new RegExp('\\s+class\=\\"([^\\"]*?)\\"', 'im'); - this.targetAttrRegex = new RegExp('\\s+target\=\\"([^\\"]*?)\\"', 'im') - } - - public findHooks(content: string, context: any): Array<HookPosition> { - // With the regexes we prepared, we can simply use findEnclosingHooks() to retrieve - // the HookPositions of all internal <a>-elements from the content string - return this.hookFinder.findEnclosingHooks(content, this.linkOpeningTagRegex, this.linkClosingTagRegex); - } - - public loadComponent(hookId: number, hookValue: HookValue, context: any, childNodes: Array<Element>): HookComponentData { - // Simply return the component class here - return { - component: DynamicRouterLinkComponent - }; - } - - public getBindings(hookId: number, hookValue: HookValue, context: any): HookBindings { - // We can reuse the hrefAttrRegex here as its first capture group is the relative part of the url, - // e.g. '/jedi/windu' from 'https://www.mysite.com/jedi/windu', which is what we need - const hrefAttrMatch = hookValue.openingTag.match(this.hrefAttrRegex); - let link = hrefAttrMatch[1]; - - // The relative part of the link may still contain the query string and the - // anchor fragment, so we need to split it up accordingly - const anchorFragmentSplit = link.split('#'); - link = anchorFragmentSplit[0]; - const anchorFragment = anchorFragmentSplit.length > 1 ? anchorFragmentSplit[1] : null; - - const queryParamsSplit = link.split('?'); - link = queryParamsSplit[0]; - const queryParams = queryParamsSplit.length > 1 ? this.parseQueryString(queryParamsSplit[1]) : {}; - - // Select css part - let css = null; - const classAttrMatch = hookValue.openingTag.match(this.classAttrRegex); - if (classAttrMatch) { - css = classAttrMatch[1]; - } - - // Select target part - let target = null; - const targetAttrMatch = hookValue.openingTag.match(this.targetAttrRegex); - if (targetAttrMatch) { - target = targetAttrMatch[1]; - } - - // Give all of these to our DynamicRouterLinkComponent as inputs and we're done! - return { - inputs: { - link, - queryParams: queryParams, - anchorFragment: anchorFragment, - css, - target - } - }; - } - - /** - * A helper function that transforms a query string into a QueryParams object - * Approach by Wolfgang Kuehn @ https://stackoverflow.com/a/8649003/3099523 - * - * @param queryParamString - The queryString to parse - */ - private parseQueryString(queryParamString: string): {[key: string]: any} { - return JSON.parse('{"' + - decodeURI(queryParamString) - .replace(/"/g, '\\"') - .replace(/&/g, '","') - .replace(/=/g, '":"') + - '"}'); - } -} diff --git a/client/src/app/instance/webpage/dynamic-content/parsers/index.ts b/client/src/app/instance/webpage/dynamic-content/parsers/index.ts index bac0c8f9..552c5a60 100644 --- a/client/src/app/instance/webpage/dynamic-content/parsers/index.ts +++ b/client/src/app/instance/webpage/dynamic-content/parsers/index.ts @@ -1,5 +1,3 @@ -import { DynamicRouterLinkParser } from './dynamic-router-link-parser'; - export const hookParsers = [ - DynamicRouterLinkParser + ]; diff --git a/client/src/app/instance/webpage/webpage.module.ts b/client/src/app/instance/webpage/webpage.module.ts index e88ace7b..86a7baca 100644 --- a/client/src/app/instance/webpage/webpage.module.ts +++ b/client/src/app/instance/webpage/webpage.module.ts @@ -10,9 +10,9 @@ import { NgModule } from '@angular/core'; import { SharedModule } from 'src/app/shared/shared.module'; -import { DynamicContentModule } from './dynamic-content/dynamic-content.module'; import { WebpageRoutingModule, routedComponents } from './webpage-routing.module'; import { dummiesComponents } from './components'; +import { hookParsers, dynamicComponents } from './dynamic-content'; /** * @class @@ -21,12 +21,18 @@ import { dummiesComponents } from './components'; @NgModule({ imports: [ SharedModule, - DynamicContentModule, WebpageRoutingModule, ], declarations: [ routedComponents, - dummiesComponents + dummiesComponents, + dynamicComponents + ], + entryComponents: [ + dynamicComponents + ], + providers: [ + hookParsers ] }) export class WebpageModule { } diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.html b/client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.html similarity index 100% rename from client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.html rename to client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.html diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.scss b/client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.scss similarity index 100% rename from client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.scss rename to client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.scss diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.ts b/client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.ts similarity index 100% rename from client/src/app/instance/search/detail/dynamic-content/dynamic-components/dynamic-router-link.component.ts rename to client/src/app/shared/dynamic-content/dynamic-components/dynamic-router-link.component.ts diff --git a/client/src/app/shared/dynamic-content/dynamic-components/index.ts b/client/src/app/shared/dynamic-content/dynamic-components/index.ts new file mode 100644 index 00000000..376e8a42 --- /dev/null +++ b/client/src/app/shared/dynamic-content/dynamic-components/index.ts @@ -0,0 +1,5 @@ +import { DynamicRouterLinkComponent } from './dynamic-router-link.component'; + +export const dynamicComponents = [ + DynamicRouterLinkComponent +]; diff --git a/client/src/app/shared/dynamic-content/index.ts b/client/src/app/shared/dynamic-content/index.ts new file mode 100644 index 00000000..98122e3a --- /dev/null +++ b/client/src/app/shared/dynamic-content/index.ts @@ -0,0 +1,14 @@ +import { HookParserEntry } from 'ngx-dynamic-hooks'; + +import { hookParsers } from './parsers'; +import { dynamicComponents } from './dynamic-components'; + +export const globalParsers: Array<HookParserEntry> = [ + ...hookParsers, + ...dynamicComponents.map(component => { + return { component }; + }) +]; + +export { hookParsers } from './parsers'; +export { dynamicComponents } from './dynamic-components'; diff --git a/client/src/app/instance/search/detail/dynamic-content/parsers/dynamic-router-link-parser.ts b/client/src/app/shared/dynamic-content/parsers/dynamic-router-link-parser.ts similarity index 99% rename from client/src/app/instance/search/detail/dynamic-content/parsers/dynamic-router-link-parser.ts rename to client/src/app/shared/dynamic-content/parsers/dynamic-router-link-parser.ts index cb543c79..01b5fa6e 100644 --- a/client/src/app/instance/search/detail/dynamic-content/parsers/dynamic-router-link-parser.ts +++ b/client/src/app/shared/dynamic-content/parsers/dynamic-router-link-parser.ts @@ -21,7 +21,7 @@ export class DynamicRouterLinkParser implements HookParser { this.linkClosingTagRegex = new RegExp('<\\/a>', 'gim'); this.hrefAttrRegex = new RegExp(hrefAttr, 'im'); this.classAttrRegex = new RegExp('\\s+class\=\\"([^\\"]*?)\\"', 'im'); - this.targetAttrRegex = new RegExp('\\s+target\=\\"([^\\"]*?)\\"', 'im') + this.targetAttrRegex = new RegExp('\\s+target\=\\"([^\\"]*?)\\"', 'im'); } public findHooks(content: string, context: any): Array<HookPosition> { diff --git a/client/src/app/shared/dynamic-content/parsers/index.ts b/client/src/app/shared/dynamic-content/parsers/index.ts new file mode 100644 index 00000000..bac0c8f9 --- /dev/null +++ b/client/src/app/shared/dynamic-content/parsers/index.ts @@ -0,0 +1,5 @@ +import { DynamicRouterLinkParser } from './dynamic-router-link-parser'; + +export const hookParsers = [ + DynamicRouterLinkParser +]; diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index 5455daca..750a89c0 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -23,9 +23,11 @@ import { PaginationModule } from 'ngx-bootstrap/pagination'; import { ProgressbarModule } from 'ngx-bootstrap/progressbar'; import { NgSelectModule } from '@ng-select/ng-select'; import { NgxJsonViewerModule } from 'ngx-json-viewer'; +import { DynamicHooksModule } from 'ngx-dynamic-hooks'; import { sharedComponents } from './components'; import { sharedPipes } from './pipes'; +import { hookParsers, dynamicComponents } from './dynamic-content'; /** * @class @@ -34,7 +36,14 @@ import { sharedPipes } from './pipes'; @NgModule({ declarations: [ sharedComponents, - sharedPipes + sharedPipes, + dynamicComponents + ], + entryComponents: [ + dynamicComponents + ], + providers: [ + hookParsers ], imports: [ CommonModule, @@ -51,7 +60,8 @@ import { sharedPipes } from './pipes'; PaginationModule.forRoot(), ProgressbarModule.forRoot(), NgSelectModule, - NgxJsonViewerModule + NgxJsonViewerModule, + DynamicHooksModule.forRoot({}), ], exports: [ CommonModule, @@ -68,8 +78,10 @@ import { sharedPipes } from './pipes'; ProgressbarModule, NgSelectModule, NgxJsonViewerModule, + DynamicHooksModule, sharedComponents, - sharedPipes + sharedPipes, + dynamicComponents ] }) export class SharedModule { } diff --git a/conf-dev/create-db.sh b/conf-dev/create-db.sh index 5118a6a2..04733542 100644 --- a/conf-dev/create-db.sh +++ b/conf-dev/create-db.sh @@ -43,6 +43,9 @@ curl -d '{"id":56,"name":"spec1d","label":"spec1d","form_label":"spec1d","descri curl -d '{"id":57,"name":"spec1dnoise","label":"spec1dnoise","form_label":"spec1dnoise","description":null,"primary_key":false,"output_display":570,"criteria_display":570,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":570,"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute curl -d '{"id":58,"name":"spec1dsky","label":"spec1dsky","form_label":"spec1dsky","description":null,"primary_key":false,"output_display":580,"criteria_display":580,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":580,"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +# Add vipers_dr2_w1 detail config +curl -d '{"enabled":true,"content":"<div class=\"row\">\n <div class=\"col col-md-8 col-sm-12\">\n <app-display-spectra\n [object]=\"context.object\"\n [datasetName]=\"context.datasetName\"\n [attributeList]=\"context.attributeList\"\n [attributeSpectraId]=\"56\"\n [attributeZId]=\"8\">\n </app-display-spectra>\n </div>\n <div class=\"col col-md-4 col-sm-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n <app-display-object \n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [outputFamilyList]=\"context.outputFamilyList\"\n [outputCategoryList]=\"context.outputCategoryList\">\n </app-display-object>\n </div>\n</div>"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/detail-config + # Add sp_cards attributes curl -d '{"label":"Card","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/criteria-family curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/output-family @@ -74,6 +77,9 @@ curl -d '{"id":7,"name":"object_name","label":"object_name","form_label":"Object curl -d '{"id":8,"name":"fits_file","label":"fits_file","form_label":"fits_file","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":80,"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute curl -d '{"id":9,"name":"fits_png","label":"fits_png","form_label":"fits_png","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"image","renderer_config":{"type":"fits","display":"modal","width":"50","height":"50"},"detail_display":90,"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +# Add observations detail config +curl -d '{"enabled":true,"content":"<div class=\"row justify-content-center\">\n <div class=\"col col-lg-10 col-xl-8 mt-4\">\n <div class=\"row\">\n <div class=\"col-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n </div>\n </div>\n\n <app-display-object \n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [outputFamilyList]=\"context.outputFamilyList\"\n [outputCategoryList]=\"context.outputCategoryList\">\n </app-display-object>\n </div>\n</div>"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/detail-config + # Add vvds_f02_udeep attributes curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/criteria-family curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/output-family @@ -112,4 +118,4 @@ curl -d '{"id":15,"name":"src_id","label":"src_id","form_label":"SRC ID","descri # Add webpages curl -d '{"label":"Default","icon":null,"display":10}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/webpage-family -curl -d '{"label":"Home","icon":"fas fa-home","display":10,"title":"Home","content":"<div class=\"row align-items-center jumbotron\"><div class=\"col-6 col-md-4 order-md-2 mx-auto text-center\"><img class=\"img-fluid mb-3 mb-md-0\" src=\"http://localhost:8080/instance/default/file-explorer/home_component_logo.png\" alt=\"Instance logo\"></div><div class=\"col-md-8 order-md-1 text-justify pr-md-5\"><h2 class=\"mb-3\">Welcome to the ANIS default instance</h2><p class=\"lead\">This service provides several sub-services to interact with the database.<br>Here is a brief presentation of these sub-services:</p><ul class=\"lead\"><li><a href=\"https://drf-gitlab.cea.fr/svom/sdb/api-import/-/wikis/home\">/import/</a> => This sub-service allows you to import data L0, L1 or SR3/SR4</li><li>/export-rest => => This sub-service allows you to request and export data from the database in json format with a specific URL. To build this URL you could <a class=\"btn btn-warning\" href=\"../../search\">Go to search form</a></li></ul></div></div>"}' --header 'Content-Type: application/json' -X POST http://localhost/webpage-family/1/webpage +curl -d '{"label":"Home","icon":"fas fa-home","display":10,"title":"Home","content":"<div class=\"row align-items-center jumbotron\">\n <div class=\"col-6 col-md-4 order-md-2 mx-auto text-center\">\n <img class=\"img-fluid mb-3 mb-md-0\" src=\"http://localhost:8080/instance/default/file-explorer/home_component_logo.png\" alt=\"Instance logo\">\n </div>\n <div class=\"col-md-8 order-md-1 text-justify pr-md-5\">\n <h2 class=\"mb-3\">Welcome to the ANIS default instance</h2>\n <p class=\"lead\">\n This service provides several sub-services to interact with the database.<br>\n Here is a brief presentation of these sub-services:\n </p>\n <ul class=\"lead\">\n <li>\n <a href=\"https://drf-gitlab.cea.fr/svom/sdb/api-import/-/wikis/home\">\n /import/\n </a> => This sub-service allows you to import data L0, L1 or SR3/SR4\n </li>\n <li>\n /export-rest => => This sub-service allows you to request and export data \n from the database in json format with a specific URL. To build this URL you could \n <a class=\"btn btn-warning\" href=\"../../search\">\n Go to search form\n </a>\n </li>\n </ul>\n </div>\n</div>\n<app-dataset-sample\n [datasetName]=\"'\''observations'\''\"\n [sortingColumn]=\"1\"\n [sortingDirection]=\"'\''d'\''\"\n [nbItems]=\"5\">\n</app-dataset-sample>"}' --header 'Content-Type: application/json' -X POST http://localhost/webpage-family/1/webpage -- GitLab