diff --git a/client/src/app/admin/admin-routing.module.ts b/client/src/app/admin/admin-routing.module.ts index d3aef6a6b6acd59c9bd6da9d15e7d601e3b34eeb..ceec43374f5fe60156ec88ad8cd8eac2e53eea95 100644 --- a/client/src/app/admin/admin-routing.module.ts +++ b/client/src/app/admin/admin-routing.module.ts @@ -15,6 +15,7 @@ import { AdminAuthGuard } from './admin-auth.guard'; import { InstanceListComponent } from './containers/instance/instance-list.component'; import { NewInstanceComponent } from './containers/instance/new-instance.component'; import { EditInstanceComponent } from './containers/instance/edit-instance.component'; +import { DatasetListComponent } from './containers/dataset/dataset-list.component'; import { ConfigureInstanceComponent } from './containers/instance/configure-instance.component'; import { GroupListComponent } from './containers/group/group-list.component'; import { NewGroupComponent } from './containers/group/new-group.component'; @@ -37,13 +38,17 @@ const routes: Routes = [ { path: 'instance-list', component: InstanceListComponent }, { path: 'new-instance', component: NewInstanceComponent }, { path: 'edit-instance/:iname', component: EditInstanceComponent }, - { path: 'configure-instance/:iname', component: ConfigureInstanceComponent }, - { path: 'configure-instance/:iname/group', component: GroupListComponent }, - { path: 'configure-instance/:iname/new-group', component: NewGroupComponent }, - { path: 'configure-instance/:iname/edit-group/:id', component: EditGroupComponent }, - { path: 'configure-instance/:iname/new-dataset', component: NewDatasetComponent }, - { path: 'configure-instance/:iname/edit-dataset/:dname', component: EditDatasetComponent }, - { path: 'configure-instance/:iname/configure-dataset/:dname', component: AttributeListComponent }, + { path: 'configure-instance/:iname', component: ConfigureInstanceComponent, children: + [ + { path: '', component: DatasetListComponent }, + { path: 'group', component: GroupListComponent }, + { path: 'new-group', component: NewGroupComponent }, + { path: 'edit-group/:id', component: EditGroupComponent }, + { path: 'new-dataset', component: NewDatasetComponent }, + { path: 'edit-dataset/:dname', component: EditDatasetComponent }, + { path: 'configure-dataset/:dname', component: AttributeListComponent }, + ] + }, { path: 'survey-list', component: SurveyListComponent }, { path: 'new-survey', component: NewSurveyComponent }, { path: 'edit-survey/:name', component: EditSurveyComponent }, @@ -68,6 +73,7 @@ export const routedComponents = [ NewInstanceComponent, EditInstanceComponent, ConfigureInstanceComponent, + DatasetListComponent, GroupListComponent, NewGroupComponent, EditGroupComponent, diff --git a/client/src/app/admin/admin.component.ts b/client/src/app/admin/admin.component.ts index 93e97de10f1e36607d482147e840a4567f1e5e4c..c66057c76e647be6b2d1d45557aa01eb6aa2fef7 100644 --- a/client/src/app/admin/admin.component.ts +++ b/client/src/app/admin/admin.component.ts @@ -7,13 +7,17 @@ * file that was distributed with this source code. */ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { UserProfile } from 'src/app/auth/user-profile.model'; import * as authActions from 'src/app/auth/auth.actions'; import * as authSelector from 'src/app/auth/auth.selector'; +import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; +import * as databaseActions from 'src/app/metamodel/actions/database.actions'; +import * as selectActions from 'src/app/metamodel/actions/select.actions'; +import * as optionActions from 'src/app/metamodel/actions/select-option.actions'; import { AppConfigService } from 'src/app/app-config.service'; @Component({ @@ -26,9 +30,9 @@ import { AppConfigService } from 'src/app/app-config.service'; * * @implements OnInit */ -export class AdminComponent { +export class AdminComponent implements OnInit { + public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public links = [ - { label: 'Back to portal', icon: 'fas fa-level-up-alt', routerLink: '/portal' }, { label: 'Instances', icon: 'fas fa-object-group', routerLink: 'instance-list' }, { label: 'Surveys', icon: 'fas fa-table', routerLink: 'survey-list'}, { label: 'Databases', icon: 'fas fa-database', routerLink: 'database-list'}, @@ -44,6 +48,14 @@ export class AdminComponent { this.userRoles = store.select(authSelector.selectUserRoles); } + ngOnInit() { + this.favIcon.href = 'favicon.ico'; + Promise.resolve(null).then(() => this.store.dispatch(surveyActions.loadSurveyList())); + Promise.resolve(null).then(() => this.store.dispatch(databaseActions.loadDatabaseList())); + Promise.resolve(null).then(() => this.store.dispatch(selectActions.loadSelectList())); + Promise.resolve(null).then(() => this.store.dispatch(optionActions.loadSelectOptionList())); + } + getBaseHref() { return this.config.baseHref; } diff --git a/client/src/app/admin/components/criteria-family/criteria-family-form.component.html b/client/src/app/admin/components/criteria-family/criteria-family-form.component.html index 9efb6a0cc13b15b3870c4319a07fd39dc0f8a96a..d8b5a066c7d055c812f993aca5f7dd9311a9d62e 100644 --- a/client/src/app/admin/components/criteria-family/criteria-family-form.component.html +++ b/client/src/app/admin/components/criteria-family/criteria-family-form.component.html @@ -7,6 +7,10 @@ <label for="display">Display</label> <input type="number" class="form-control" name="display" formControlName="display"> </div> + <div class="custom-control custom-switch mb-3"> + <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened"> + <label class="custom-control-label" for="opened">Opened</label> + </div> <div class="form-group"> <ng-content></ng-content> </div> diff --git a/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts b/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts index ee12b1eefbb66e74216c31c5339a98e62db63be6..9013e5e8f208926c91e230563e160b181e342acc 100644 --- a/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts +++ b/client/src/app/admin/components/criteria-family/criteria-family-form.component.ts @@ -22,7 +22,8 @@ export class CriteriaFamilyFormComponent { public form = new FormGroup({ label: new FormControl('', [Validators.required]), - display: new FormControl('', [Validators.required]) + display: new FormControl('', [Validators.required]), + opened: new FormControl(true) }); ngOnInit() { diff --git a/client/src/app/admin/components/dataset-family/dataset-family-form.component.html b/client/src/app/admin/components/dataset-family/dataset-family-form.component.html index f55dbbd1e0bd7e7b7acfa83f9e75935bec2feae3..0da5da147f927b7235a573bbb921cde5edc0e086 100644 --- a/client/src/app/admin/components/dataset-family/dataset-family-form.component.html +++ b/client/src/app/admin/components/dataset-family/dataset-family-form.component.html @@ -7,6 +7,10 @@ <label for="display">Display</label> <input type="number" class="form-control" id="display" name="display" formControlName="display"> </div> + <div class="custom-control custom-switch mb-3"> + <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened"> + <label class="custom-control-label" for="opened">Opened</label> + </div> <div class="form-group"> <ng-content></ng-content> </div> diff --git a/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts b/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts index 2d1e8a1de085f2b05e0612f5eadd042f1b486834..c79513ee27d64c79d3d5282ed2190294287bb89c 100644 --- a/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts +++ b/client/src/app/admin/components/dataset-family/dataset-family-form.component.ts @@ -22,7 +22,8 @@ export class DatasetFamilyFormComponent implements OnInit { public form = new FormGroup({ label: new FormControl('', [Validators.required]), - display: new FormControl('', [Validators.required]) + display: new FormControl('', [Validators.required]), + opened: new FormControl(true) }); ngOnInit() { diff --git a/client/src/app/admin/components/instance/design-form-group.component.html b/client/src/app/admin/components/instance/design-form-group.component.html new file mode 100644 index 0000000000000000000000000000000000000000..be9ed62b499b9719d3d299e38ec3f022c400efa8 --- /dev/null +++ b/client/src/app/admin/components/instance/design-form-group.component.html @@ -0,0 +1,16 @@ +<form [formGroup]="form" novalidate> + <accordion-group heading="Design"> + + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="design_color_picker">Color picker</label> + <input class="form-control" type="color" id="design_color_picker" [value]="form.value.design_color" formControlName="design_color"> + </div> + <div class="form-group col-md-6"> + <label for="design_color_input">Color value</label> + <input type="text" class="form-control" id="design_color_input" [value]="form.value.design_color" formControlName="design_color"> + </div> + </div> + + </accordion-group> +</form> diff --git a/client/src/app/admin/components/instance/design-form-group.component.ts b/client/src/app/admin/components/instance/design-form-group.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c84d3c1c0e368851efaa05701fbfee90e03b1f9 --- /dev/null +++ b/client/src/app/admin/components/instance/design-form-group.component.ts @@ -0,0 +1,19 @@ +/** + * 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 } from '@angular/core'; +import { FormGroup } from '@angular/forms'; + +@Component({ + selector: 'app-design-form-group', + templateUrl: 'design-form-group.component.html' +}) +export class DesignFormGroupComponent { + @Input() form: FormGroup; +} diff --git a/client/src/app/admin/components/instance/index.ts b/client/src/app/admin/components/instance/index.ts index 826d3727e78d69a0dba05ba06f159be14301a1ab..47997603644fc0f5c165dc8aad02983b360ae23d 100644 --- a/client/src/app/admin/components/instance/index.ts +++ b/client/src/app/admin/components/instance/index.ts @@ -10,6 +10,7 @@ import { InstanceCardComponent } from './instance-card.component'; import { InstanceButtonsComponent } from './instance-buttons.component'; import { InstanceFormComponent } from './instance-form.component'; +import { DesignFormGroupComponent } from './design-form-group.component'; import { SearchFormGroupComponent } from './search-form-group.component'; import { DocumentationFormGroupComponent } from './documentation-form-group.component'; @@ -17,6 +18,7 @@ export const instanceComponents = [ InstanceCardComponent, InstanceButtonsComponent, InstanceFormComponent, + DesignFormGroupComponent, SearchFormGroupComponent, DocumentationFormGroupComponent ]; diff --git a/client/src/app/admin/components/instance/instance-form.component.html b/client/src/app/admin/components/instance/instance-form.component.html index ee839607e117fd8e3dd4b700b1d5c476de620060..abf027b3ad2fc6e116075cf6d9897837fa4a37bc 100644 --- a/client/src/app/admin/components/instance/instance-form.component.html +++ b/client/src/app/admin/components/instance/instance-form.component.html @@ -14,6 +14,7 @@ <input id="client_url" type="text" class="form-control" id="client_url" name="client_url" formControlName="client_url"> </div> </accordion-group> + <app-design-form-group [form]="designFormGroup"></app-design-form-group> <app-search-form-group [form]="searchFormGroup"></app-search-form-group> <app-documentation-form-group [form]="documentationFormGroup"></app-documentation-form-group> </accordion> diff --git a/client/src/app/admin/components/instance/instance-form.component.ts b/client/src/app/admin/components/instance/instance-form.component.ts index 2514e806be619581ae4688aae927a8f4843e57d2..1463bfa2ef850b440bc79fc8d76c7a515bb94242 100644 --- a/client/src/app/admin/components/instance/instance-form.component.ts +++ b/client/src/app/admin/components/instance/instance-form.component.ts @@ -20,6 +20,10 @@ export class InstanceFormComponent implements OnInit { @Input() instance: Instance; @Output() onSubmit: EventEmitter<Instance> = new EventEmitter(); + public designFormGroup = new FormGroup({ + design_color: new FormControl('', [Validators.required]) + }); + public searchFormGroup = new FormGroup({ search_by_criteria_allowed: new FormControl(true), search_multiple_allowed: new FormControl(false), @@ -35,6 +39,7 @@ export class InstanceFormComponent implements OnInit { label: new FormControl('', [Validators.required]), client_url: new FormControl('', [Validators.required]), config: new FormGroup({ + design: this.designFormGroup, search: this.searchFormGroup, documentation: this.documentationFormGroup }) diff --git a/client/src/app/admin/components/output-family/output-family-form.component.html b/client/src/app/admin/components/output-family/output-family-form.component.html index 9efb6a0cc13b15b3870c4319a07fd39dc0f8a96a..d8b5a066c7d055c812f993aca5f7dd9311a9d62e 100644 --- a/client/src/app/admin/components/output-family/output-family-form.component.html +++ b/client/src/app/admin/components/output-family/output-family-form.component.html @@ -7,6 +7,10 @@ <label for="display">Display</label> <input type="number" class="form-control" name="display" formControlName="display"> </div> + <div class="custom-control custom-switch mb-3"> + <input class="custom-control-input" type="checkbox" id="opened" name="opened" formControlName="opened"> + <label class="custom-control-label" for="opened">Opened</label> + </div> <div class="form-group"> <ng-content></ng-content> </div> diff --git a/client/src/app/admin/components/output-family/output-family-form.component.ts b/client/src/app/admin/components/output-family/output-family-form.component.ts index 1193be901a77b08124305df7364e9bc0c5155771..c36881070df6452534407ace8f0596584491026d 100644 --- a/client/src/app/admin/components/output-family/output-family-form.component.ts +++ b/client/src/app/admin/components/output-family/output-family-form.component.ts @@ -22,7 +22,8 @@ export class OutputFamilyFormComponent { public form = new FormGroup({ label: new FormControl('', [Validators.required]), - display: new FormControl('', [Validators.required]) + display: new FormControl('', [Validators.required]), + opened: new FormControl(true) }); ngOnInit() { diff --git a/client/src/app/admin/containers/attribute/attribute-list.component.ts b/client/src/app/admin/containers/attribute/attribute-list.component.ts index 3031acf79ba02fec240ae38a4593d8e729c93173..801c840dca914638ad832612e41f7188e4f6170a 100644 --- a/client/src/app/admin/containers/attribute/attribute-list.component.ts +++ b/client/src/app/admin/containers/attribute/attribute-list.component.ts @@ -16,7 +16,6 @@ import { Store } from '@ngrx/store'; import { SelectOption, Dataset, Attribute, Column, CriteriaFamily, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; -import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; import * as attributeActions from 'src/app/metamodel/actions/attribute.actions'; import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector'; @@ -26,8 +25,6 @@ import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.ac import * as outputFamilySelector from 'src/app/metamodel/selectors/output-family.selector'; import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions'; import * as outputCategorySelector from 'src/app/metamodel/selectors/output-category.selector'; -import * as selectActions from 'src/app/metamodel/actions/select.actions'; -import * as optionActions from 'src/app/metamodel/actions/select-option.actions'; import * as optionSelector from 'src/app/metamodel/selectors/select-option.selector'; import * as columnActions from 'src/app/metamodel/actions/column.actions'; import * as columnSelector from 'src/app/metamodel/selectors/column.selector'; @@ -98,13 +95,10 @@ export class AttributeListComponent implements OnInit { } ngOnInit() { - this.store.dispatch(datasetActions.loadDatasetList()); - this.store.dispatch(attributeActions.loadAttributeList()); - this.store.dispatch(criteriaFamilyActions.loadCriteriaFamilyList()); - this.store.dispatch(outputFamilyActions.loadOutputFamilyList()); - this.store.dispatch(outputCategoryActions.loadOutputCategoryList()); - this.store.dispatch(selectActions.loadSelectList()); - this.store.dispatch(optionActions.loadSelectOptionList()); + Promise.resolve(null).then(() => this.store.dispatch(attributeActions.loadAttributeList())); + Promise.resolve(null).then(() => this.store.dispatch(criteriaFamilyActions.loadCriteriaFamilyList())); + Promise.resolve(null).then(() => this.store.dispatch(outputFamilyActions.loadOutputFamilyList())); + Promise.resolve(null).then(() => this.store.dispatch(outputCategoryActions.loadOutputCategoryList())); this.tabSelected = this.route.queryParamMap.pipe( map(params => params.get('tab_selected')) ); diff --git a/client/src/app/admin/containers/database/database-list.component.ts b/client/src/app/admin/containers/database/database-list.component.ts index 6963f12b17cb481107ce8103c5093b9f53b3fdbd..f5ad27f645bad411ce9f01a6e870417ca5e969ba 100644 --- a/client/src/app/admin/containers/database/database-list.component.ts +++ b/client/src/app/admin/containers/database/database-list.component.ts @@ -7,13 +7,12 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { Database, Survey } from 'src/app/metamodel/models'; import * as databaseActions from 'src/app/metamodel/actions/database.actions'; -import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; import * as databaseSelector from 'src/app/metamodel/selectors/database.selector'; import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; @@ -21,7 +20,7 @@ import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; selector: 'app-database-list', templateUrl: 'database-list.component.html' }) -export class DatabaseListComponent implements OnInit { +export class DatabaseListComponent { public databaseListIsLoading: Observable<boolean>; public databaseListIsLoaded: Observable<boolean>; public databaseList: Observable<Database[]>; @@ -38,11 +37,6 @@ export class DatabaseListComponent implements OnInit { this.surveyList = store.select(surveySelector.selectAllSurveys); } - ngOnInit() { - this.store.dispatch(databaseActions.loadDatabaseList()); - this.store.dispatch(surveyActions.loadSurveyList()); - } - deleteDatabase(database: Database) { this.store.dispatch(databaseActions.deleteDatabase({ database })); } diff --git a/client/src/app/admin/containers/database/edit-database.component.ts b/client/src/app/admin/containers/database/edit-database.component.ts index cfeb84ad858aa50e7c89a53daa5733fcdd9ec299..f0cbeb07a606bbb98c4a64a1d76ac772b4addc0b 100644 --- a/client/src/app/admin/containers/database/edit-database.component.ts +++ b/client/src/app/admin/containers/database/edit-database.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit} from '@angular/core'; +import { Component} from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -19,7 +19,7 @@ import * as databaseSelector from 'src/app/metamodel/selectors/database.selector selector: 'app-edit-database', templateUrl: 'edit-database.component.html' }) -export class EditDatabaseComponent implements OnInit { +export class EditDatabaseComponent { public databaseListIsLoading: Observable<boolean>; public databaseListIsLoaded: Observable<boolean>; public database: Observable<Database>; @@ -30,10 +30,6 @@ export class EditDatabaseComponent implements OnInit { this.database = store.select(databaseSelector.selectDatabaseByRouteId); } - ngOnInit() { - this.store.dispatch(databaseActions.loadDatabaseList()); - } - editDatabase(database: Database) { this.store.dispatch(databaseActions.editDatabase({ database })); } diff --git a/client/src/app/admin/containers/dataset/dataset-list.component.html b/client/src/app/admin/containers/dataset/dataset-list.component.html new file mode 100644 index 0000000000000000000000000000000000000000..93caa925b0c19e4b32b20429cd46d517d1ad7798 --- /dev/null +++ b/client/src/app/admin/containers/dataset/dataset-list.component.html @@ -0,0 +1,27 @@ +<div class="container-fluid"> + <nav aria-label="breadcrumb"> + <ol class="breadcrumb"> + <li class="breadcrumb-item"><a routerLink="/admin/instance-list">Instances</a></li> + <li class="breadcrumb-item active" aria-current="page">Configure instance {{ (instance | async).label }}</li> + </ol> + </nav> +</div> + +<div class="container"> + <app-spinner *ngIf="(datasetFamilyListIsLoading | async) || (datasetListIsLoading | async)"></app-spinner> + + <ng-container *ngIf="(datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)"> + <app-instance-buttons + (addDatasetFamily)="addDatasetFamily($event)"> + </app-instance-buttons> + + <app-dataset-family-card + *ngFor="let datasetFamily of (datasetFamilyList | async)" + [datasetFamily]="datasetFamily" + [datasetList]="datasetList | async" + (editDatasetFamily)="editDatasetFamily($event)" + (deleteDatasetFamily)="deleteDatasetFamily($event)" + (deleteDataset)="deleteDataset($event)"> + </app-dataset-family-card> + </ng-container> +</div> diff --git a/client/src/app/admin/containers/dataset/dataset-list.component.ts b/client/src/app/admin/containers/dataset/dataset-list.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..862f90f83637895f1c132db92ee8c31890baf31b --- /dev/null +++ b/client/src/app/admin/containers/dataset/dataset-list.component.ts @@ -0,0 +1,59 @@ +/** + * 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 } from '@angular/core'; +import { Observable } from 'rxjs'; +import { Store } from '@ngrx/store'; + +import { Instance, DatasetFamily, Dataset } from 'src/app/metamodel/models'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; +import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; +import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; +import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; +import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; + +@Component({ + selector: 'app-dataset-list', + templateUrl: 'dataset-list.component.html' +}) +export class DatasetListComponent { + public instance: Observable<Instance>; + public datasetFamilyListIsLoading: Observable<boolean>; + public datasetFamilyListIsLoaded: Observable<boolean>; + public datasetFamilyList: Observable<DatasetFamily[]>; + public datasetListIsLoading: Observable<boolean>; + public datasetListIsLoaded: Observable<boolean>; + public datasetList: Observable<Dataset[]>; + + constructor(private store: Store<{ }>) { + this.instance = store.select(instanceSelector.selectInstanceByRouteName); + this.datasetFamilyListIsLoading = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoading); + this.datasetFamilyListIsLoaded = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoaded); + this.datasetFamilyList = store.select(datasetFamilySelector.selectAllDatasetFamilies); + this.datasetListIsLoading = store.select(datasetSelector.selectDatasetListIsLoading); + this.datasetListIsLoaded = store.select(datasetSelector.selectDatasetListIsLoaded); + this.datasetList = store.select(datasetSelector.selectAllDatasets); + } + + addDatasetFamily(datasetFamily: DatasetFamily) { + this.store.dispatch(datasetFamilyActions.addDatasetFamily({ datasetFamily })); + } + + editDatasetFamily(datasetFamily: DatasetFamily) { + this.store.dispatch(datasetFamilyActions.editDatasetFamily({ datasetFamily })); + } + + deleteDatasetFamily(datasetFamily: DatasetFamily) { + this.store.dispatch(datasetFamilyActions.deleteDatasetFamily({ datasetFamily })); + } + + deleteDataset(dataset: Dataset) { + this.store.dispatch(datasetActions.deleteDataset({ dataset })); + } +} diff --git a/client/src/app/admin/containers/dataset/edit-dataset.component.ts b/client/src/app/admin/containers/dataset/edit-dataset.component.ts index b7d126b3314f0810e37bbd5ec4833864eb885f1a..ff37287e413592da229589c438a5a7d58a02a73d 100644 --- a/client/src/app/admin/containers/dataset/edit-dataset.component.ts +++ b/client/src/app/admin/containers/dataset/edit-dataset.component.ts @@ -18,11 +18,9 @@ import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector'; import * as attributeActions from 'src/app/metamodel/actions/attribute.actions'; -import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; import * as tableActions from 'src/app/metamodel/actions/table.actions'; import * as tableSelector from 'src/app/metamodel/selectors/table.selector'; -import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as rootDirectoryActions from 'src/app/metamodel/actions/root-directory.actions'; @@ -78,10 +76,7 @@ export class EditDatasetComponent implements OnInit { } ngOnInit() { - this.store.dispatch(surveyActions.loadSurveyList()); - this.store.dispatch(datasetActions.loadDatasetList()); this.store.dispatch(attributeActions.loadAttributeList()); - this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList()); } loadTableList(idDatabase: number) { diff --git a/client/src/app/admin/containers/dataset/new-dataset.component.ts b/client/src/app/admin/containers/dataset/new-dataset.component.ts index be5ac5bb14bea84db5eb7a4937f364b40c2971b5..3bf1f9f9d848111b204887eb85ddd094c2e8ac5e 100644 --- a/client/src/app/admin/containers/dataset/new-dataset.component.ts +++ b/client/src/app/admin/containers/dataset/new-dataset.component.ts @@ -15,11 +15,9 @@ import { map } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { Survey, DatasetFamily, Dataset, FileInfo } from 'src/app/metamodel/models'; -import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; import * as tableActions from 'src/app/metamodel/actions/table.actions'; import * as tableSelector from 'src/app/metamodel/selectors/table.selector'; -import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; @@ -63,8 +61,6 @@ export class NewDatasetComponent implements OnInit { } ngOnInit() { - this.store.dispatch(surveyActions.loadSurveyList()); - this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList()); this.idDatasetFamily = this.route.queryParamMap.pipe( map(params => +params.get('id_dataset_family')) ); diff --git a/client/src/app/admin/containers/group/edit-group.component.ts b/client/src/app/admin/containers/group/edit-group.component.ts index 9b6c4b9fc0b39da6a8540d698f651887b4a940ad..00df170e623d3cad4f9ade089b41d3c94466a4ea 100644 --- a/client/src/app/admin/containers/group/edit-group.component.ts +++ b/client/src/app/admin/containers/group/edit-group.component.ts @@ -15,14 +15,13 @@ import { Group, Dataset } from 'src/app/metamodel/models'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as groupActions from 'src/app/metamodel/actions/group.actions'; import * as groupSelector from 'src/app/metamodel/selectors/group.selector'; -import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; @Component({ selector: 'app-edit-group', templateUrl: 'edit-group.component.html' }) -export class EditGroupComponent implements OnInit { +export class EditGroupComponent { public instanceName: Observable<string>; public groupListIsLoading: Observable<boolean>; public groupListIsLoaded: Observable<boolean>; @@ -41,11 +40,6 @@ export class EditGroupComponent implements OnInit { this.datasetList = store.select(datasetSelector.selectAllDatasets); } - ngOnInit() { - this.store.dispatch(groupActions.loadGroupList()); - this.store.dispatch(datasetActions.loadDatasetList()); - } - editGroup(group: Group) { this.store.dispatch(groupActions.editGroup({ group })); } diff --git a/client/src/app/admin/containers/group/group-list.component.ts b/client/src/app/admin/containers/group/group-list.component.ts index 5ff76953b4c74784296ea21e505749fd1f70f55d..94a39673d4d5813811681a783b403eb132b4649d 100644 --- a/client/src/app/admin/containers/group/group-list.component.ts +++ b/client/src/app/admin/containers/group/group-list.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -20,7 +20,7 @@ import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector selector: 'app-group-list', templateUrl: 'group-list.component.html' }) -export class GroupListComponent implements OnInit { +export class GroupListComponent { public instanceName: Observable<string>; public groupListIsLoading: Observable<boolean>; public groupListIsLoaded: Observable<boolean>; @@ -33,10 +33,6 @@ export class GroupListComponent implements OnInit { this.groupList = store.select(groupSelector.selectAllGroups); } - ngOnInit() { - this.store.dispatch(groupActions.loadGroupList()); - } - deleteGroup(group: Group) { this.store.dispatch(groupActions.deleteGroup({ group })); } diff --git a/client/src/app/admin/containers/group/new-group.component.ts b/client/src/app/admin/containers/group/new-group.component.ts index 766eb869868e99bde1c0c618d6e97aaae41e0c43..13cb4abda836d17b30905ab042618d559a9404ca 100644 --- a/client/src/app/admin/containers/group/new-group.component.ts +++ b/client/src/app/admin/containers/group/new-group.component.ts @@ -7,21 +7,20 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { Group, Dataset } from 'src/app/metamodel/models'; import * as groupActions from 'src/app/metamodel/actions/group.actions'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; -import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; @Component({ selector: 'app-new-group', templateUrl: 'new-group.component.html' }) -export class NewGroupComponent implements OnInit { +export class NewGroupComponent { public instanceName: Observable<string>; public datasetListIsLoading: Observable<boolean>; public datasetListIsLoaded: Observable<boolean>; @@ -34,10 +33,6 @@ export class NewGroupComponent implements OnInit { this.datasetList = store.select(datasetSelector.selectAllDatasets); } - ngOnInit() { - this.store.dispatch(datasetActions.loadDatasetList()); - } - addNewGroup(group: Group) { this.store.dispatch(groupActions.addGroup({ group })); } diff --git a/client/src/app/admin/containers/instance/configure-instance.component.html b/client/src/app/admin/containers/instance/configure-instance.component.html index 2a3dd82c36f7a36bb417b42293f1eed14d308b72..90c6b64632858139a9e4f4b1c55d0ee1d6e7b740 100644 --- a/client/src/app/admin/containers/instance/configure-instance.component.html +++ b/client/src/app/admin/containers/instance/configure-instance.component.html @@ -1,27 +1 @@ -<div class="container-fluid"> - <nav aria-label="breadcrumb"> - <ol class="breadcrumb"> - <li class="breadcrumb-item"><a routerLink="/admin/instance-list">Instances</a></li> - <li *ngIf="(instanceListIsLoaded | async)" class="breadcrumb-item active" aria-current="page">Configure instance {{ (instance | async).label }}</li> - </ol> - </nav> -</div> - -<div class="container"> - <app-spinner *ngIf="(instanceListIsLoading | async) || (datasetFamilyListIsLoading | async) || (datasetListIsLoading | async)"></app-spinner> - - <ng-container *ngIf="(instanceListIsLoaded | async) && (datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)"> - <app-instance-buttons - (addDatasetFamily)="addDatasetFamily($event)"> - </app-instance-buttons> - - <app-dataset-family-card - *ngFor="let datasetFamily of (datasetFamilyList | async)" - [datasetFamily]="datasetFamily" - [datasetList]="datasetList | async" - (editDatasetFamily)="editDatasetFamily($event)" - (deleteDatasetFamily)="deleteDatasetFamily($event)" - (deleteDataset)="deleteDataset($event)"> - </app-dataset-family-card> - </ng-container> -</div> +<router-outlet></router-outlet> \ No newline at end of file diff --git a/client/src/app/admin/containers/instance/configure-instance.component.ts b/client/src/app/admin/containers/instance/configure-instance.component.ts index c70389dbae55667dfcc1c23baa5a347b84666fef..02664e513d165f3eb5b9ed8a41b1645c8b5f10eb 100644 --- a/client/src/app/admin/containers/instance/configure-instance.component.ts +++ b/client/src/app/admin/containers/instance/configure-instance.component.ts @@ -8,63 +8,22 @@ */ import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; -import { Instance, DatasetFamily, Dataset } from 'src/app/metamodel/models'; -import * as instanceActions from 'src/app/metamodel/actions/instance.actions'; -import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; -import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; -import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; +import * as groupActions from 'src/app/metamodel/actions/group.actions'; @Component({ selector: 'app-configure-instance', - templateUrl: 'configure-instance.component.html' + templateUrl: 'configure-instance.component.html', }) export class ConfigureInstanceComponent implements OnInit { - public instanceListIsLoading: Observable<boolean>; - public instanceListIsLoaded: Observable<boolean>; - public instance: Observable<Instance>; - public datasetFamilyListIsLoading: Observable<boolean>; - public datasetFamilyListIsLoaded: Observable<boolean>; - public datasetFamilyList: Observable<DatasetFamily[]>; - public datasetListIsLoading: Observable<boolean>; - public datasetListIsLoaded: Observable<boolean>; - public datasetList: Observable<Dataset[]>; - - constructor(private store: Store<{ }>) { - this.instanceListIsLoading = store.select(instanceSelector.selectInstanceListIsLoading); - this.instanceListIsLoaded = store.select(instanceSelector.selectInstanceListIsLoaded); - this.instance = store.select(instanceSelector.selectInstanceByRouteName); - this.datasetFamilyListIsLoading = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoading); - this.datasetFamilyListIsLoaded = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoaded); - this.datasetFamilyList = store.select(datasetFamilySelector.selectAllDatasetFamilies); - this.datasetListIsLoading = store.select(datasetSelector.selectDatasetListIsLoading); - this.datasetListIsLoaded = store.select(datasetSelector.selectDatasetListIsLoaded); - this.datasetList = store.select(datasetSelector.selectAllDatasets); - } + constructor(private store: Store<{ }>) { } ngOnInit() { - this.store.dispatch(instanceActions.loadInstanceList()); - this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList()); - this.store.dispatch(datasetActions.loadDatasetList()); - } - - addDatasetFamily(datasetFamily: DatasetFamily) { - this.store.dispatch(datasetFamilyActions.addDatasetFamily({ datasetFamily })); - } - - editDatasetFamily(datasetFamily: DatasetFamily) { - this.store.dispatch(datasetFamilyActions.editDatasetFamily({ datasetFamily })); - } - - deleteDatasetFamily(datasetFamily: DatasetFamily) { - this.store.dispatch(datasetFamilyActions.deleteDatasetFamily({ datasetFamily })); - } - - deleteDataset(dataset: Dataset) { - this.store.dispatch(datasetActions.deleteDataset({ dataset })); + Promise.resolve(null).then(() => this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList())); + Promise.resolve(null).then(() => this.store.dispatch(datasetActions.loadDatasetList())); + Promise.resolve(null).then(() => this.store.dispatch(groupActions.loadGroupList())); } } diff --git a/client/src/app/admin/containers/instance/edit-instance.component.html b/client/src/app/admin/containers/instance/edit-instance.component.html index 9a0c834d18f0c0541617763368ed39bd6cf98513..8db55ccca330f28e87bf795e46e36488f6adeeaa 100644 --- a/client/src/app/admin/containers/instance/edit-instance.component.html +++ b/client/src/app/admin/containers/instance/edit-instance.component.html @@ -2,15 +2,13 @@ <nav aria-label="breadcrumb"> <ol class="breadcrumb"> <li class="breadcrumb-item"><a routerLink="/admin/instance-list">Instances</a></li> - <li *ngIf="instanceListIsLoaded | async" class="breadcrumb-item active" aria-current="page">Edit instance {{ (instance | async).name }}</li> + <li class="breadcrumb-item active" aria-current="page">Edit instance {{ (instance | async).name }}</li> </ol> </nav> </div> <div class="container"> - <app-spinner *ngIf="instanceListIsLoading | async"></app-spinner> - - <div *ngIf="instanceListIsLoaded | async" class="row"> + <div class="row"> <div class="col-12"> <app-instance-form [instance]="instance | async" (onSubmit)="editInstance($event)" #formInstance> <button [disabled]="!formInstance.form.valid || formInstance.form.pristine" type="submit" class="btn btn-primary"> diff --git a/client/src/app/admin/containers/instance/edit-instance.component.ts b/client/src/app/admin/containers/instance/edit-instance.component.ts index 0d0d3cfa358c15c9fc0a4ebfd86882245d5028c6..e26d6aa6da8962e82f56f01b61f1548cf27d7676 100644 --- a/client/src/app/admin/containers/instance/edit-instance.component.ts +++ b/client/src/app/admin/containers/instance/edit-instance.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -20,21 +20,13 @@ import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector selector: 'app-edit-instance', templateUrl: 'edit-instance.component.html' }) -export class EditInstanceComponent implements OnInit { - public instanceListIsLoading: Observable<boolean>; - public instanceListIsLoaded: Observable<boolean>; +export class EditInstanceComponent { public instance: Observable<Instance>; constructor(private store: Store<{ }>) { - this.instanceListIsLoading = store.select(instanceSelector.selectInstanceListIsLoading); - this.instanceListIsLoaded = store.select(instanceSelector.selectInstanceListIsLoaded); this.instance = store.select(instanceSelector.selectInstanceByRouteName); } - ngOnInit() { - this.store.dispatch(instanceActions.loadInstanceList()); - } - editInstance(instance: Instance) { this.store.dispatch(instanceActions.editInstance({ instance })); } diff --git a/client/src/app/admin/containers/instance/instance-list.component.html b/client/src/app/admin/containers/instance/instance-list.component.html index 5b377f65e73fe1ef876a0e67907050da47d8ef0d..307c004ec8272907180898ccea881bf510482c0f 100644 --- a/client/src/app/admin/containers/instance/instance-list.component.html +++ b/client/src/app/admin/containers/instance/instance-list.component.html @@ -7,9 +7,7 @@ </div> <div class="container"> - <app-spinner *ngIf="instanceListIsLoading | async"></app-spinner> - - <div *ngIf="instanceListIsLoaded | async" class="row row-cols-1 row-cols-sm-2 row-cols-md-3"> + <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3"> <div class="col mb-3" *ngFor="let instance of (instanceList | async)"> <app-instance-card [instance]="instance" diff --git a/client/src/app/admin/containers/instance/instance-list.component.ts b/client/src/app/admin/containers/instance/instance-list.component.ts index 19f7b795783fd4a4451bfb499aa10085cfd984f5..74413b97bb50b3be3d12032f3810cee04c2ff9c3 100644 --- a/client/src/app/admin/containers/instance/instance-list.component.ts +++ b/client/src/app/admin/containers/instance/instance-list.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -20,21 +20,13 @@ import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector templateUrl: 'instance-list.component.html', styleUrls: [ 'instance-list.component.scss' ] }) -export class InstanceListComponent implements OnInit { - public instanceListIsLoading: Observable<boolean>; - public instanceListIsLoaded: Observable<boolean>; +export class InstanceListComponent { public instanceList: Observable<Instance[]>; constructor(private store: Store<{ }>) { - this.instanceListIsLoading = store.select(instanceSelector.selectInstanceListIsLoading); - this.instanceListIsLoaded = store.select(instanceSelector.selectInstanceListIsLoaded); this.instanceList = store.select(instanceSelector.selectAllInstances); } - ngOnInit() { - this.store.dispatch(instanceActions.loadInstanceList()); - } - deleteInstance(instance: Instance) { this.store.dispatch(instanceActions.deleteInstance({ instance })); } diff --git a/client/src/app/admin/containers/settings/settings.component.ts b/client/src/app/admin/containers/settings/settings.component.ts index 3e38b5f6198ce2d7bcc66e05ecebd0883079b2d0..6c091610dc6f1759184558c199b3233ccff6957b 100644 --- a/client/src/app/admin/containers/settings/settings.component.ts +++ b/client/src/app/admin/containers/settings/settings.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -22,7 +22,7 @@ import * as optionSelector from 'src/app/metamodel/selectors/select-option.selec selector: 'app-settings', templateUrl: 'settings.component.html' }) -export class SettingsComponent implements OnInit { +export class SettingsComponent { public selectListIsLoading: Observable<boolean>; public selectListIsLoaded: Observable<boolean>; public selectList: Observable<Select[]>; @@ -41,11 +41,6 @@ export class SettingsComponent implements OnInit { this.currentSelect = store.select(selectSelector.getSelectByRouteName); } - ngOnInit() { - this.store.dispatch(selectActions.loadSelectList()); - this.store.dispatch(optionActions.loadSelectOptionList()); - } - addSelect(select: Select) { this.store.dispatch(selectActions.addSelect({ select })); } diff --git a/client/src/app/admin/containers/survey/edit-survey.component.ts b/client/src/app/admin/containers/survey/edit-survey.component.ts index c1642ede80b52fc5b0ba4249656a75bbddf33a57..31728f2e0b1f8dc880185d667c89cbeeaf8b2cfe 100644 --- a/client/src/app/admin/containers/survey/edit-survey.component.ts +++ b/client/src/app/admin/containers/survey/edit-survey.component.ts @@ -13,7 +13,6 @@ import { Store } from '@ngrx/store'; import { Survey, Database } from 'src/app/metamodel/models'; import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; -import * as databaseActions from 'src/app/metamodel/actions/database.actions'; import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; import * as databaseSelector from 'src/app/metamodel/selectors/database.selector'; @@ -21,7 +20,7 @@ import * as databaseSelector from 'src/app/metamodel/selectors/database.selector selector: 'app-edit-survey', templateUrl: 'edit-survey.component.html' }) -export class EditSurveyComponent implements OnInit { +export class EditSurveyComponent { public surveyListIsLoading: Observable<boolean>; public surveyListIsLoaded: Observable<boolean>; public survey: Observable<Survey>; @@ -38,11 +37,6 @@ export class EditSurveyComponent implements OnInit { this.databaseList = this.store.select(databaseSelector.selectAllDatabases); } - ngOnInit() { - this.store.dispatch(surveyActions.loadSurveyList()); - this.store.dispatch(databaseActions.loadDatabaseList()); - } - editSurvey(survey: Survey) { this.store.dispatch(surveyActions.editSurvey({ survey })); } diff --git a/client/src/app/admin/containers/survey/new-survey.component.ts b/client/src/app/admin/containers/survey/new-survey.component.ts index d48092a423d160dc1f01bb242aae25497219a96e..1caeeb29a6fa53925423d533d4002bf4b7377004 100644 --- a/client/src/app/admin/containers/survey/new-survey.component.ts +++ b/client/src/app/admin/containers/survey/new-survey.component.ts @@ -7,20 +7,19 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { Survey, Database } from 'src/app/metamodel/models' import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; -import * as databaseActions from 'src/app/metamodel/actions/database.actions'; import * as databaseSelector from 'src/app/metamodel/selectors/database.selector'; @Component({ selector: 'app-new-survey', templateUrl: 'new-survey.component.html' }) -export class NewSurveyComponent implements OnInit { +export class NewSurveyComponent { public databaseListIsLoading: Observable<boolean>; public databaseListIsLoaded: Observable<boolean>; public databaseList: Observable<Database[]>; @@ -31,10 +30,6 @@ export class NewSurveyComponent implements OnInit { this.databaseList = store.select(databaseSelector.selectAllDatabases); } - ngOnInit() { - this.store.dispatch(databaseActions.loadDatabaseList()); - } - addNewSurvey(survey: Survey) { this.store.dispatch(surveyActions.addSurvey({ survey })); } diff --git a/client/src/app/admin/containers/survey/survey-list.component.ts b/client/src/app/admin/containers/survey/survey-list.component.ts index f805e6e8c3358fb404aa97f992c8c89374cbac3a..3e3fee49108beefcf632d1226ba28f7598a39e51 100644 --- a/client/src/app/admin/containers/survey/survey-list.component.ts +++ b/client/src/app/admin/containers/survey/survey-list.component.ts @@ -7,13 +7,12 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; import { Survey, Database } from 'src/app/metamodel/models'; import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; -import * as databaseActions from 'src/app/metamodel/actions/database.actions'; import * as surveySelector from 'src/app/metamodel/selectors/survey.selector'; import * as databaseSelector from 'src/app/metamodel/selectors/database.selector'; @@ -21,7 +20,7 @@ import * as databaseSelector from 'src/app/metamodel/selectors/database.selector selector: 'app-survey-list', templateUrl: 'survey-list.component.html' }) -export class SurveyListComponent implements OnInit { +export class SurveyListComponent { public surveyListIsLoading: Observable<boolean>; public surveyListIsLoaded: Observable<boolean>; public surveyList: Observable<Survey[]>; @@ -38,11 +37,6 @@ export class SurveyListComponent implements OnInit { this.databaseList = store.select(databaseSelector.selectAllDatabases); } - ngOnInit() { - this.store.dispatch(surveyActions.loadSurveyList()); - this.store.dispatch(databaseActions.loadDatabaseList()); - } - deleteSurvey(survey: Survey) { this.store.dispatch(surveyActions.deleteSurvey({ survey })); } diff --git a/client/src/app/core/containers/app.component.html b/client/src/app/core/containers/app.component.html index 5cc24bf1e51db01c6306d56d52dce845156c5d99..7aed41a286f0dfa4d37cef43b006c02d5d90e005 100644 --- a/client/src/app/core/containers/app.component.html +++ b/client/src/app/core/containers/app.component.html @@ -1,4 +1,8 @@ -<router-outlet></router-outlet> +<div *ngIf="(instanceListIsLoading | async)" class="row justify-content-center mt-5"> + <span class="fas fa-circle-notch fa-spin fa-3x"></span> + <span class="sr-only">Loading...</span> +</div> +<router-outlet *ngIf="(instanceListIsLoaded | async)"></router-outlet> <footer class="footer mt-auto bg-light"> <div class="container my-3"> <div class="row justify-content-center mb-3"> diff --git a/client/src/app/core/containers/app.component.ts b/client/src/app/core/containers/app.component.ts index 7ede1446430a597d5ef318ba39940265e28aa3e0..a13a317e99275634ec5bf57f9d3814f74161e874 100644 --- a/client/src/app/core/containers/app.component.ts +++ b/client/src/app/core/containers/app.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; @@ -16,6 +16,8 @@ import { map } from 'rxjs/operators'; import * as fromAuth from '../../auth/auth.reducer'; import * as authActions from '../../auth/auth.actions'; import * as authSelector from '../../auth/auth.selector'; +import * as instanceActions from 'src/app/metamodel/actions/instance.actions'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import { UserProfile } from '../../auth/user-profile.model'; import { AppConfigService } from '../../app-config.service'; @@ -23,19 +25,27 @@ import { AppConfigService } from '../../app-config.service'; selector: 'app-root', templateUrl: './app.component.html' }) -export class AppComponent { - public anisClientVersion: string = '3.6.0'; +export class AppComponent implements OnInit { + public anisClientVersion: string = '3.7.0'; public year = (new Date()).getFullYear(); + public instanceListIsLoading: Observable<boolean>; + public instanceListIsLoaded: Observable<boolean>; public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; public userRoles: Observable<string[]>; constructor(private store: Store<{ auth: fromAuth.State }>, private config: AppConfigService) { + this.instanceListIsLoading = store.select(instanceSelector.selectInstanceListIsLoading); + this.instanceListIsLoaded = store.select(instanceSelector.selectInstanceListIsLoaded); this.isAuthenticated = store.select(authSelector.selectIsAuthenticated); this.userProfile = store.select(authSelector.selectUserProfile); this.userRoles = store.select(authSelector.selectUserRoles); } + ngOnInit() { + Promise.resolve(null).then(() => this.store.dispatch(instanceActions.loadInstanceList())); + } + authenticationEnabled(): boolean { return this.config.authenticationEnabled; } diff --git a/client/src/app/instance/detail/detail-routing.module.ts b/client/src/app/instance/detail/detail-routing.module.ts deleted file mode 100644 index 8f88b99bb56b2ad21b228b818173bdb623ed7f6d..0000000000000000000000000000000000000000 --- a/client/src/app/instance/detail/detail-routing.module.ts +++ /dev/null @@ -1,28 +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 { Routes, RouterModule } from '@angular/router'; - -import { DetailComponent } from './containers/detail.component'; - -const routes: Routes = [ - { path: '', redirectTo: ':/dname/:id', pathMatch: 'full' }, - { path: ':dname/:id', component: DetailComponent } -]; - -@NgModule({ - imports: [RouterModule.forChild(routes)], - exports: [RouterModule] -}) -export class DetailRoutingModule { } - -export const routedComponents = [ - DetailComponent -]; diff --git a/client/src/app/instance/instance-routing.module.ts b/client/src/app/instance/instance-routing.module.ts index 053f59c53dbca4657b86d991f96f63645148ad67..03c0e21f5b879295d917d7152162fc4e94e73988 100644 --- a/client/src/app/instance/instance-routing.module.ts +++ b/client/src/app/instance/instance-routing.module.ts @@ -17,9 +17,8 @@ const routes: Routes = [ path: ':iname', component: InstanceComponent, children: [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) }, - { path: 'documentation', loadChildren: () => import('./documentation/documentation.module').then(m => m.DocumentationModule) }, { path: 'search', loadChildren: () => import('./search/search.module').then(m => m.SearchModule) }, - { path: 'detail', loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule) } + { path: 'documentation', loadChildren: () => import('./documentation/documentation.module').then(m => m.DocumentationModule) } ] } ]; diff --git a/client/src/app/instance/instance.component.html b/client/src/app/instance/instance.component.html index 61101934f1e33d3d27823eb8998cedcf423d891b..acd9b3df900a6771327d87a05dd6b10e734800fb 100644 --- a/client/src/app/instance/instance.component.html +++ b/client/src/app/instance/instance.component.html @@ -5,6 +5,7 @@ [userProfile]="userProfile | async" [baseHref]="getBaseHref()" [authenticationEnabled]="getAuthenticationEnabled()" + [instance]="instance | async" (login)="login()" (logout)="logout()" (openEditProfile)="openEditProfile()"> diff --git a/client/src/app/instance/instance.component.ts b/client/src/app/instance/instance.component.ts index 214fb769ab385501d5a877f016369ac40eb209f5..b433bd32845d2904c6a6efe0e5c67c60ad4090bb 100644 --- a/client/src/app/instance/instance.component.ts +++ b/client/src/app/instance/instance.component.ts @@ -7,14 +7,18 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; -import { Observable } from 'rxjs'; +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Observable, Subscription } from 'rxjs'; import { Store } from '@ngrx/store'; import { UserProfile } from 'src/app/auth/user-profile.model'; +import { Instance } from 'src/app/metamodel/models'; import * as authActions from 'src/app/auth/auth.actions'; import * as authSelector from 'src/app/auth/auth.selector'; -import * as metamodelActions from './store/actions/metamodel.actions'; +import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; +import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; +import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import { AppConfigService } from 'src/app/app-config.service'; @Component({ @@ -25,26 +29,41 @@ import { AppConfigService } from 'src/app/app-config.service'; * @class * @classdesc Instance container */ -export class InstanceComponent implements OnInit { +export class InstanceComponent implements OnInit, OnDestroy { + public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public links = [ - { label: 'Home', icon: 'fas fa-home', routerLink: 'home' }, - { label: 'Search', icon: 'fas fa-search', routerLink: 'search' }, - { label: 'Search multiple', icon: 'fas fa-search-plus', routerLink: 'search-multiple' }, - { label: 'Documentation', icon: 'fas fa-question', routerLink: 'documentation' }, + { label: 'Home', icon: 'fas fa-home', routerLink: 'home' } ]; + public instance: Observable<Instance>; public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; public userRoles: Observable<string[]>; + public instanceSubscription: Subscription; + constructor(private store: Store<{ }>, private config: AppConfigService) { + this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.isAuthenticated = store.select(authSelector.selectIsAuthenticated); this.userProfile = store.select(authSelector.selectUserProfile); this.userRoles = store.select(authSelector.selectUserRoles); } ngOnInit() { - // Load datasetList, datasetFamilyList, SurveyList - Promise.resolve(null).then(() => this.store.dispatch(metamodelActions.loadInstanceMetamodel())); + Promise.resolve(null).then(() => this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList())); + Promise.resolve(null).then(() => this.store.dispatch(datasetActions.loadDatasetList())); + Promise.resolve(null).then(() => this.store.dispatch(surveyActions.loadSurveyList())); + this.instanceSubscription = this.instance.subscribe(instance => { + if (instance.config.search.search_by_criteria_allowed) { + this.links.push({ label: 'Search', icon: 'fas fa-search', routerLink: 'search' }); + } + if (instance.config.search.search_multiple_allowed) { + this.links.push({ label: 'Search multiple', icon: 'fas fa-search-plus', routerLink: 'search-multiple' }); + } + if (instance.config.documentation.documentation_allowed) { + this.links.push({ label: 'Documentation', icon: 'fas fa-question', routerLink: 'documentation' }); + } + this.favIcon.href = `assets/${instance.name}-favicon.ico`; + }) } getBaseHref() { @@ -66,4 +85,8 @@ export class InstanceComponent implements OnInit { openEditProfile(): void { this.store.dispatch(authActions.openEditProfile()); } + + ngOnDestroy() { + this.instanceSubscription.unsubscribe(); + } } diff --git a/client/src/app/instance/instance.reducer.ts b/client/src/app/instance/instance.reducer.ts index f660ab9ab6c3dd59f99ddf24e047eac5cd2b82a7..76e651beb8b286a870569e434a9c274b4ba1369a 100644 --- a/client/src/app/instance/instance.reducer.ts +++ b/client/src/app/instance/instance.reducer.ts @@ -10,14 +10,12 @@ import { combineReducers, createFeatureSelector } from '@ngrx/store'; import { RouterReducerState } from 'src/app/custom-route-serializer'; -import * as metamodel from './store/reducers/metamodel.reducer'; import * as search from './store/reducers/search.reducer'; import * as samp from './store/reducers/samp.reducer'; import * as coneSearch from './store/reducers/cone-search.reducer'; import * as detail from './store/reducers/detail.reducer'; export interface State { - metamodel: metamodel.State, search: search.State, samp: samp.State, coneSearch: coneSearch.State @@ -25,7 +23,6 @@ export interface State { } const reducers = { - metamodel: metamodel.metamodelReducer, search: search.searchReducer, samp: samp.sampReducer, coneSearch: coneSearch.coneSearchReducer, diff --git a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html index 45c654c3ff635409fc76494de4c80068ec530675..fa9d3aef3286c6ac5d3fb9cdd32279b4c00f2d3b 100644 --- a/client/src/app/instance/search/components/criteria/criteria-tabs.component.html +++ b/client/src/app/instance/search/components/criteria/criteria-tabs.component.html @@ -1,21 +1,6 @@ -<div *ngIf="criteriaFamilyList.length == 1 && (attributeList | attributeListByFamily:criteriaFamilyList[0].id).length > 0"> - <div class="border rounded my-2"> - <p class="border-bottom bg-light text-primary py-4 pl-4">{{ criteriaFamilyList[0].label }}</p> - <div class="px-3"> - <app-criteria-by-family - [attributeList]="attributeList | attributeListByFamily:criteriaFamilyList[0].id" - [criteriaList]="criteriaList" - (addCriterion)="emitAdd($event)" - (deleteCriterion)="emitDelete($event)"> - </app-criteria-by-family> - </div> - </div> -</div> - -<accordion *ngIf="criteriaFamilyList.length > 1" [isAnimated]="true"> +<accordion [isAnimated]="true"> <ng-container *ngFor="let family of criteriaFamilyList"> - <accordion-group #ag *ngIf="(attributeList | attributeListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" - [isOpen]="true" class="my-2"> + <accordion-group #ag *ngIf="(attributeList | attributeListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" [isOpen]="family.opened" class="my-2"> <button class="btn btn-link btn-block clearfix" accordion-heading> <span class="pull-left float-left"> {{ family.label }} diff --git a/client/src/app/instance/search/components/dataset/dataset-card.component.ts b/client/src/app/instance/search/components/dataset/dataset-card.component.ts index ffeb52d4c33d61435f42d1ff21d8b5830f762156..2ca57d970cb2d65383adf42b58744ea296b12868 100644 --- a/client/src/app/instance/search/components/dataset/dataset-card.component.ts +++ b/client/src/app/instance/search/components/dataset/dataset-card.component.ts @@ -30,7 +30,6 @@ export class DatasetCardComponent { constructor(private router: Router) { } selectDataset(datasetName: string) { - this.router.routeReuseStrategy.shouldReuseRoute = () => false; this.router.navigate([`/instance/${this.instanceSelected}/search/dataset/${datasetName}`]); } } diff --git a/client/src/app/instance/search/components/dataset/dataset-tabs.component.html b/client/src/app/instance/search/components/dataset/dataset-tabs.component.html index 08d61aae5a4772c90ef815b17ac4f262ec6e483a..0407fe894237ab475740462f635d1a57adb70ce5 100644 --- a/client/src/app/instance/search/components/dataset/dataset-tabs.component.html +++ b/client/src/app/instance/search/components/dataset/dataset-tabs.component.html @@ -1,26 +1,6 @@ -<div *ngIf="datasetFamilyList.length === 1"> - <div class="border rounded my-2"> - <p *ngIf="(datasetList | datasetListByFamily:datasetFamilyList[0].id).length === 1" class="border-bottom bg-light text-primary py-4 pl-4">Dataset</p> - <p *ngIf="(datasetList | datasetListByFamily:datasetFamilyList[0].id).length > 1" class="border-bottom bg-light text-primary py-4 pl-4">List of datasets</p> - <ul class="p-0"> - <li *ngFor="let dataset of (datasetList | datasetListByFamily:datasetFamilyList[0].id); last as isLast" - class="list-unstyled px-3 pt-3 pb-0"> - <app-dataset-card - [dataset]="dataset" - [survey]="surveyList | surveyByName:dataset.survey_name" - [instanceSelected]="instanceSelected" - [datasetSelected]="datasetSelected"> - </app-dataset-card> - <hr *ngIf="!isLast"> - </li> - </ul> - </div> -</div> - -<accordion *ngIf="datasetFamilyList.length > 1" [isAnimated]="true"> +<accordion [isAnimated]="true"> <ng-container *ngFor="let family of datasetFamilyList"> - <accordion-group #ag *ngIf="(datasetList | datasetListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" - [isOpen]="true" class="my-2"> + <accordion-group #ag *ngIf="(datasetList | datasetListByFamily:family.id).length > 0" [panelClass]="'custom-accordion'" [isOpen]="family.opened" class="my-2"> <button class="btn btn-link btn-block clearfix" accordion-heading> <span class="pull-left float-left"> {{ family.label }} diff --git a/client/src/app/instance/search/components/output/output-by-category.component.html b/client/src/app/instance/search/components/output/output-by-category.component.html index 9774bd950c34cb5a6bf7d6debee9b6faa23fb4e1..7888b9a0acb076a724a631a25a3ef7095f667414 100644 --- a/client/src/app/instance/search/components/output/output-by-category.component.html +++ b/client/src/app/instance/search/components/output/output-by-category.component.html @@ -17,7 +17,7 @@ <div *ngFor="let attribute of getAttributeListSortedByDisplay()"> <div *ngIf="isSelected(attribute.id)"> <button class="btn btn-block text-left py-1 m-0 rounded-0" (click)="toggleSelection(attribute.id)"> - <span class="fas fa-fw fa-check-square theme-color"></span> {{ attribute.form_label }} + <span class="fas fa-fw fa-check-square" [ngStyle]="{ 'color': designColor }"></span> {{ attribute.form_label }} </button> </div> <div *ngIf="!isSelected(attribute.id)"> diff --git a/client/src/app/instance/search/components/output/output-by-category.component.ts b/client/src/app/instance/search/components/output/output-by-category.component.ts index b65113b6bf8ba3fe9b73a17d261bba956c99c434..3cfd66d0ad7da4de3456540fb4f15bf210fad09a 100644 --- a/client/src/app/instance/search/components/output/output-by-category.component.ts +++ b/client/src/app/instance/search/components/output/output-by-category.component.ts @@ -25,6 +25,7 @@ export class OutputByCategoryComponent { @Input() categoryLabel: string; @Input() attributeList: Attribute[]; @Input() outputList: number[]; + @Input() designColor: string; @Input() isAllSelected: boolean; @Input() isAllUnselected: boolean; @Output() change: EventEmitter<number[]> = new EventEmitter(); diff --git a/client/src/app/instance/search/components/output/output-by-family.component.html b/client/src/app/instance/search/components/output/output-by-family.component.html index c281d8698e7e63131e141a846214feaf98995ef4..e4acc92e4ef7ec35c395e3475237bd9f03edd687 100644 --- a/client/src/app/instance/search/components/output/output-by-family.component.html +++ b/client/src/app/instance/search/components/output/output-by-family.component.html @@ -5,6 +5,7 @@ [categoryLabel]="category.label" [attributeList]="getAttributeByCategory(category.id)" [outputList]="outputList" + [designColor]="designColor" [isAllSelected]="getIsAllSelected(category.id)" [isAllUnselected]="getIsAllUnselected(category.id)" (change)="emitChange($event)"> diff --git a/client/src/app/instance/search/components/output/output-by-family.component.ts b/client/src/app/instance/search/components/output/output-by-family.component.ts index 8ef26caf006d04a81acdd4b7231edc31ecb00ef6..23ff1ee0def5dc3eab3841d656115303b1e3f9c5 100644 --- a/client/src/app/instance/search/components/output/output-by-family.component.ts +++ b/client/src/app/instance/search/components/output/output-by-family.component.ts @@ -25,6 +25,7 @@ export class OutputByFamilyComponent { @Input() outputCategoryList: OutputCategory[]; @Input() attributeList: Attribute[]; @Input() outputList: number[]; + @Input() designColor: string; @Output() change: EventEmitter<number[]> = new EventEmitter(); /** diff --git a/client/src/app/instance/search/components/output/output-tabs.component.html b/client/src/app/instance/search/components/output/output-tabs.component.html index d8ca9de4d061a38222c209ede10de79fb8d6a88e..b90fc7bfb85065a187230e8cdb22202d2a304f73 100644 --- a/client/src/app/instance/search/components/output/output-tabs.component.html +++ b/client/src/app/instance/search/components/output/output-tabs.component.html @@ -1,21 +1,5 @@ -<div *ngIf="outputFamilyList.length == 1"> - <div class="border rounded my-2"> - <p class="border-bottom bg-light text-primary py-4 pl-4 mb-0">{{ outputFamilyList[0].label }}</p> - <div class="px-3 pb-3 pt-0"> - <app-output-by-family - [outputFamily]="outputFamilyList[0]" - [attributeList]="attributeList" - [outputCategoryList]="outputCategoryList" - [outputList]="outputList" - (change)="change.emit($event)"> - </app-output-by-family> - </div> - </div> -</div> - -<accordion *ngIf="outputFamilyList.length > 1" [isAnimated]="true"> - <accordion-group #ag *ngFor="let family of outputFamilyList" - [panelClass]="'custom-accordion-output'" class="my-2" [isOpen]="true"> +<accordion [isAnimated]="true"> + <accordion-group #ag *ngFor="let family of outputFamilyList" [panelClass]="'custom-accordion-output'" class="my-2" [isOpen]="family.opened"> <button class="btn btn-link btn-block clearfix" accordion-heading> <span class="pull-left float-left"> {{ family.label }} @@ -29,6 +13,7 @@ [attributeList]="attributeList" [outputCategoryList]="outputCategoryList" [outputList]="outputList" + [designColor]="designColor" (change)="change.emit($event)"> </app-output-by-family> </accordion-group> diff --git a/client/src/app/instance/search/components/output/output-tabs.component.ts b/client/src/app/instance/search/components/output/output-tabs.component.ts index c3ec91115a3e2d3c969bc19cb85dbe415a117d49..6bf1afefdd5168956fdf19f7833a206f92706464 100644 --- a/client/src/app/instance/search/components/output/output-tabs.component.ts +++ b/client/src/app/instance/search/components/output/output-tabs.component.ts @@ -27,6 +27,7 @@ export class OutputTabsComponent { @Input() outputCategoryList: OutputCategory[]; @Input() attributeList: Attribute[]; @Input() outputList: number[]; + @Input() designColor: string; @Output() change: EventEmitter<number[]> = new EventEmitter(); constructor(private toastr: ToastrService) { } diff --git a/client/src/app/instance/search/components/progress-bar.component.html b/client/src/app/instance/search/components/progress-bar.component.html index 4575d0e828006126fa66fc9ef2c97bd458aee00a..b248b98ca39a6d168c490a0d93ee6e375aa01b19 100644 --- a/client/src/app/instance/search/components/progress-bar.component.html +++ b/client/src/app/instance/search/components/progress-bar.component.html @@ -6,58 +6,67 @@ </div> <div class="progress-navigation"> <div class="progress progress-with-circle"> - <div class="progress-bar" role="progressbar" aria-valuenow="1" aria-valuemin="1" aria-valuemax="4" - [ngClass]="getStepClass()"></div> + <div class="progress-bar" + [ngClass]="getStepClass()" + [ngStyle]="{'background-color': instance.config.design.design_color }" + role="progressbar" + aria-valuenow="1" + aria-valuemin="1" + aria-valuemax="4"> + </div> </div> <ul class="nav nav-pills"> <li class="nav-item checked" [ngClass]="{'active': currentStep === 'dataset'}"> - <a class="nav-link" routerLink="/instance/{{ instanceSelected }}/search/dataset/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle"> + <a class="nav-link" [ngStyle]="getNavItemAStyle('dataset', true)" routerLink="/instance/{{ instance.name }}/search/dataset/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('dataset', true)"> <span class="fas fa-book"></span> </div> Dataset </a> </li> <li id="criteriaStep" class="nav-item" [ngClass]="{'active': currentStep === 'criteria', 'checked': criteriaStepChecked}"> - <a *ngIf="datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" - routerLink="/instance/{{ instanceSelected }}/search/criteria/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="datasetSelected" + class="nav-link" + [ngClass]="{'disabled': !datasetSelected}" + [ngStyle]="getNavItemAStyle('criteria', criteriaStepChecked)" + routerLink="/instance/{{ instance.name }}/search/criteria/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('criteria', criteriaStepChecked)"> <span class="fas fa-filter"></span> </div> Criteria </a> - <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" [ngStyle]="getNavItemAStyle('criteria', criteriaStepChecked)" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('criteria', criteriaStepChecked)"> <span class="fas fa-filter"></span> </div> Criteria </a> </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'output', 'checked': outputStepChecked}"> - <a *ngIf="datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" - routerLink="/instance/{{ instanceSelected }}/search/output/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" [ngStyle]="getNavItemAStyle('output', outputStepChecked)" + routerLink="/instance/{{ instance.name }}/search/output/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('output', outputStepChecked)"> <span class="fas fa-eye"></span> </div> Output </a> - <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" [ngStyle]="getNavItemAStyle('output', outputStepChecked)" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('output', outputStepChecked)"> <span class="fas fa-eye"></span> </div> Output </a> </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'result', 'checked': resultStepChecked}"> - <a *ngIf="datasetSelected" class="nav-link" [ngClass]="{'disabled': outputList.length < 1}" - routerLink="/instance/{{ instanceSelected }}/search/result/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="datasetSelected" class="nav-link" [ngClass]="{'disabled': outputList.length < 1}" [ngStyle]="getNavItemAStyle('result', resultStepChecked)" + routerLink="/instance/{{ instance.name }}/search/result/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('result', resultStepChecked)"> <span class="fas fa-table"></span> </div> Result </a> - <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" data-toggle="tab"> - <div class="icon-circle"> + <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" [ngStyle]="getNavItemAStyle('result', resultStepChecked)" data-toggle="tab"> + <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('result', resultStepChecked)"> <span class="fas fa-table"></span> </div> Result diff --git a/client/src/app/instance/search/components/progress-bar.component.scss b/client/src/app/instance/search/components/progress-bar.component.scss index 3537e02786c7efcc15bcf896c97a865bac216b5d..4b28b03c366bfd662ed7f907f98e3138b691dbc8 100644 --- a/client/src/app/instance/search/components/progress-bar.component.scss +++ b/client/src/app/instance/search/components/progress-bar.component.scss @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ - .progress-navigation { +.progress-navigation { position: relative; height: 125px; margin-top: 15px; @@ -25,7 +25,6 @@ -webkit-transition: width .3s ease; -o-transition: width .3s ease; transition: width .3s ease; - background-color: #7AC29A; } .nav-pills { @@ -67,24 +66,12 @@ width: 25%; } -.nav-item.checked .icon-circle { - border-color: #7AC29A; - color: #7AC29A; -} - -.nav-item.checked a { - color: #7AC29A !important; -} - .nav-item.active a { - color: #7AC29A !important; background-color: transparent; } .nav-item.active .icon-circle { color: white !important; - border-color: #7AC29A; - background-color: #7AC29A; } .nav-link.disabled { diff --git a/client/src/app/instance/search/components/progress-bar.component.ts b/client/src/app/instance/search/components/progress-bar.component.ts index c70e73968a36a25064c75487e1d3a4451b861624..de9abad0eaa41190f28662e6515dba35ddff7ae1 100644 --- a/client/src/app/instance/search/components/progress-bar.component.ts +++ b/client/src/app/instance/search/components/progress-bar.component.ts @@ -10,6 +10,7 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; import { SearchQueryParams } from '../../store/models'; +import { Instance } from 'src/app/metamodel/models'; @Component({ selector: 'app-progress-bar', @@ -23,7 +24,7 @@ import { SearchQueryParams } from '../../store/models'; */ export class ProgressBarComponent { @Input() currentStep: string; - @Input() instanceSelected: string; + @Input() instance: Instance; @Input() datasetSelected: string; @Input() criteriaStepChecked: boolean; @Input() outputStepChecked: boolean; @@ -50,4 +51,27 @@ export class ProgressBarComponent { return 'datasetStep'; } } + + getNavItemAStyle(currentStep: string, checked: boolean) { + if (this.currentStep === currentStep || checked) { + return { + 'color': this.instance.config.design.design_color + } + } else { + return null; + } + } + + getNavItemIconCircleStyle(currentStep: string, checked: boolean) { + let style = {}; + if (this.currentStep === currentStep) { + style['border-color'] = this.instance.config.design.design_color; + style['background-color'] = this.instance.config.design.design_color; + } + if (checked) { + style['border-color'] = this.instance.config.design.design_color; + style['color'] = this.instance.config.design.design_color; + } + return style; + } } diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.html b/client/src/app/instance/search/components/result/datatable-tab.component.html index 26dd36d1be6a174d083b150ebb580194511e8e9c..f9f6b3aaa6a57531613c217cf6a1ebf3501bc5be 100644 --- a/client/src/app/instance/search/components/result/datatable-tab.component.html +++ b/client/src/app/instance/search/components/result/datatable-tab.component.html @@ -10,9 +10,10 @@ </button> <app-datatable [dataset]="datasetList | datasetByName:datasetSelected" - [instanceSelected]="instanceSelected" + [instance]="instance" [attributeList]="attributeList" [outputList]="outputList" + [queryParams]="queryParams" [dataLength]="dataLength" [data]="data" [dataIsLoading]="dataIsLoading" diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.ts b/client/src/app/instance/search/components/result/datatable-tab.component.ts index c24e1979d36d8710d5efe016bd9ba69a5e4c35d2..a276dec48ebe3974e8494c21d4cda2602d64794b 100644 --- a/client/src/app/instance/search/components/result/datatable-tab.component.ts +++ b/client/src/app/instance/search/components/result/datatable-tab.component.ts @@ -9,8 +9,8 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; -import { Attribute, Dataset } from 'src/app/metamodel/models'; -import { Pagination } from 'src/app/instance/store/models'; +import { Instance, Attribute, Dataset } from 'src/app/metamodel/models'; +import { Pagination, SearchQueryParams } from 'src/app/instance/store/models'; @Component({ selector: 'app-datatable-tab', @@ -23,10 +23,11 @@ import { Pagination } from 'src/app/instance/store/models'; */ export class DatatableTabComponent { @Input() datasetSelected: string; - @Input() instanceSelected: string; + @Input() instance: Instance; @Input() datasetList: Dataset[]; @Input() attributeList: Attribute[]; @Input() outputList: number[]; + @Input() queryParams: SearchQueryParams; @Input() dataLength: number; @Input() data: any[]; @Input() dataIsLoading: boolean; diff --git a/client/src/app/instance/search/components/result/download.component.html b/client/src/app/instance/search/components/result/download.component.html index 655ee2e2dcccb8332448b08e26a958fc7999c01e..4f9d94496d025ae285d6bd9a7c30ad0e1db42fe8 100644 --- a/client/src/app/instance/search/components/result/download.component.html +++ b/client/src/app/instance/search/components/result/download.component.html @@ -1,8 +1,3 @@ -<div class="jumbotron mb-4 py-4"> - <div class="lead"> - Dataset <span class="bold">{{ getDatasetLabel() }}</span> selected with <span class="bold">{{ dataLength }}</span> objects found. - </div> -</div> <accordion *ngIf="isDownloadActivated()" [isAnimated]="true"> <accordion-group #ag [isOpen]="isDownloadOpened()" [panelClass]="'custom-accordion'" class="my-2"> <button class="btn btn-link btn-block clearfix" accordion-heading> @@ -23,25 +18,25 @@ <p>Download results just here:</p> </div> <div class="col"> - <a *ngIf="getConfigDownloadResultFormat('csv')" [href]="getUrl('csv')" class="btn btn-outline-primary" title="Download results in CSV format"> + <a *ngIf="getConfigDownloadResultFormat('download_csv')" [href]="getUrl('csv')" class="btn btn-outline-primary" title="Download results in CSV format"> <i class="fas fa-file-csv"></i> CSV </a> - <a *ngIf="getConfigDownloadResultFormat('ascii')" [href]="getUrl('ascii')" target="_blank" class="btn btn-outline-primary" title="Download results in ASCII format"> + <a *ngIf="getConfigDownloadResultFormat('download_ascii')" [href]="getUrl('ascii')" target="_blank" class="btn btn-outline-primary" title="Download results in ASCII format"> <i class="fas fa-file"></i> ASCII </a> - <a *ngIf="getConfigDownloadResultFormat('vo')" [href]="getUrl('votable')" target="_blank" class="btn btn-outline-primary" title="Download results in VO format"> + <a *ngIf="getConfigDownloadResultFormat('download_vo')" [href]="getUrl('votable')" target="_blank" class="btn btn-outline-primary" title="Download results in VO format"> <i class="fas fa-file"></i> VOtable </a> - <button *ngIf="getConfigDownloadResultFormat('vo')" [disabled]="!sampRegistered" (click)="broadcastVotable()" class="btn btn-outline-primary" title="Broadcast samp votable"> + <button *ngIf="getConfigDownloadResultFormat('download_vo')" [disabled]="!sampRegistered" (click)="broadcastVotable()" class="btn btn-outline-primary" title="Broadcast samp votable"> <i class="fas fa-broadcast-tower"></i> Broadcast VOtable </button> </div> </div> - <hr *ngIf="getConfigDownloadResultFormat('archive')" class="my-4"> - <div *ngIf="getConfigDownloadResultFormat('archive')" class="row"> + <hr *ngIf="getConfigDownloadResultFormat('download_archive')" class="my-4"> + <div *ngIf="getConfigDownloadResultFormat('download_archive')" class="row"> <div class="col-auto align-self-center"> <p>Download archive files just here:</p> </div> diff --git a/client/src/app/instance/search/components/result/download.component.scss b/client/src/app/instance/search/components/result/download.component.scss deleted file mode 100644 index c83c4f7b435abc15ac65a08d95f4a241e8bea96b..0000000000000000000000000000000000000000 --- a/client/src/app/instance/search/components/result/download.component.scss +++ /dev/null @@ -1,17 +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. - */ - -.bold { - font-weight: 900; -} - -.dl-btn { - height: 80px; - display: inline-block; -} diff --git a/client/src/app/instance/search/components/result/download.component.ts b/client/src/app/instance/search/components/result/download.component.ts index 729dfe595cc1f1e8d5484bf2d91b84311d35ca44..10607d8459b2b922a870567a800cd031fd3d4578 100644 --- a/client/src/app/instance/search/components/result/download.component.ts +++ b/client/src/app/instance/search/components/result/download.component.ts @@ -9,16 +9,14 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { Criterion, criterionToString } from '../../../store/models'; +import { Criterion, ConeSearch, criterionToString } from '../../../store/models'; import { Dataset } from 'src/app/metamodel/models'; import { getHost as host } from 'src/app/shared/utils'; -// import { ConeSearch } from '../../../shared/cone-search/store/model'; import { AppConfigService } from 'src/app/app-config.service'; @Component({ selector: 'app-download', - templateUrl: 'download.component.html', - styleUrls: ['download.component.scss'] + templateUrl: 'download.component.html' }) /** * @class @@ -31,24 +29,13 @@ export class DownloadComponent { @Input() datasetList: Dataset[]; @Input() criteriaList: Criterion[]; @Input() outputList: number[]; + @Input() coneSearch: ConeSearch; @Input() dataLength: number; - //@Input() isConeSearchAdded: boolean; - //@Input() coneSearch: ConeSearch; @Input() sampRegistered: boolean; @Output() broadcast: EventEmitter<string> = new EventEmitter(); constructor(private appConfig: AppConfigService) { } - /** - * Returns dataset label. - * - * @return string - */ - getDatasetLabel(): string { - const dataset = this.datasetList.find(dataset => dataset.name === this.datasetSelected); - return dataset.label; - } - isDownloadActivated(): boolean { const dataset = this.datasetList.find(dataset => dataset.name === this.datasetSelected); return dataset.config.download.download_enabled; @@ -83,9 +70,9 @@ export class DownloadComponent { if (this.criteriaList.length > 0) { query += '&c=' + this.criteriaList.map(criterion => criterionToString(criterion)).join(';'); } - // if (this.isConeSearchAdded) { - // query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; - // } + if (this.coneSearch) { + query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; + } query += '&f=' + format return query; } @@ -95,9 +82,9 @@ export class DownloadComponent { if (this.criteriaList.length > 0) { query += '&c=' + this.criteriaList.map(criterion => criterionToString(criterion)).join(';'); } - // if (this.isConeSearchAdded) { - // query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; - // } + if (this.coneSearch) { + query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; + } return query; } diff --git a/client/src/app/instance/search/components/result/url-display.component.ts b/client/src/app/instance/search/components/result/url-display.component.ts index 1ed461ba64d2d44b402b2cf8eaedf98d59e5024d..d5ef1c03c2dcc7f2a0337edb800f6d40d010a297 100644 --- a/client/src/app/instance/search/components/result/url-display.component.ts +++ b/client/src/app/instance/search/components/result/url-display.component.ts @@ -28,10 +28,9 @@ import { AppConfigService } from 'src/app/app-config.service'; export class UrlDisplayComponent { @Input() datasetSelected: string; @Input() datasetList: Dataset[]; - // @Input() isConeSearchAdded: boolean; - // @Input() coneSearch: ConeSearch; @Input() criteriaList: Criterion[]; @Input() outputList: number[]; + @Input() coneSearch: ConeSearch; constructor(private toastr: ToastrService, private appConfig: AppConfigService) { } @@ -60,9 +59,9 @@ export class UrlDisplayComponent { if (this.criteriaList.length > 0) { query += '&c=' + this.criteriaList.map(criterion => criterionToString(criterion)).join(';'); } - // if (this.isConeSearchAdded) { - // query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; - // } + if (this.coneSearch) { + query += '&cs=' + this.coneSearch.ra + ':' + this.coneSearch.dec + ':' + this.coneSearch.radius; + } return query; } diff --git a/client/src/app/instance/search/containers/dataset.component.ts b/client/src/app/instance/search/containers/dataset.component.ts index bff120abb809e855b406321d5fe87d1c4d2ddd0b..6222da2a0ec1052b5733c0cdf3a839cc374608b2 100644 --- a/client/src/app/instance/search/containers/dataset.component.ts +++ b/client/src/app/instance/search/containers/dataset.component.ts @@ -10,7 +10,7 @@ import { Component} from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable } from 'rxjs'; +import { Observable, Subscription } from 'rxjs'; import { AbstractSearchComponent } from './abstract-search.component'; import { Survey, DatasetFamily } from 'src/app/metamodel/models'; @@ -36,6 +36,8 @@ export class DatasetComponent extends AbstractSearchComponent { public surveyListIsLoaded: Observable<boolean>; public surveyList: Observable<Survey[]>; + public datasetSelectedSubscription: Subscription; + constructor(protected store: Store<{ }>) { super(store); this.isAuthenticated = store.select(authSelector.selectIsAuthenticated); @@ -49,6 +51,16 @@ export class DatasetComponent extends AbstractSearchComponent { ngOnInit() { Promise.resolve(null).then(() => this.store.dispatch(searchActions.changeStep({ step: 'dataset' }))); + this.datasetSelectedSubscription = this.datasetSelected.subscribe(datasetSelected => { + if (datasetSelected) { + Promise.resolve(null).then(() => this.store.dispatch(searchActions.initSearch())); + } + }) super.ngOnInit(); } + + ngOnDestroy() { + this.datasetSelectedSubscription.unsubscribe(); + super.ngOnDestroy(); + } } diff --git a/client/src/app/instance/search/containers/output.component.html b/client/src/app/instance/search/containers/output.component.html index 12d7f60558376fa5c8b4a679cc8fa1a2b4eafce0..db66948c6961e8d968487796e09c4723027f6337 100644 --- a/client/src/app/instance/search/containers/output.component.html +++ b/client/src/app/instance/search/containers/output.component.html @@ -12,6 +12,7 @@ [outputFamilyList]="outputFamilyList | async" [outputCategoryList]="outputCategoryList | async" [outputList]="outputList | async" + [designColor]="(instance | async).config.design.design_color" (change)="updateOutputList($event)"> </app-output-tabs> </div> diff --git a/client/src/app/instance/search/containers/output.component.ts b/client/src/app/instance/search/containers/output.component.ts index 2a8962bc5c4cc6368d2cf1621ffe32a334efa560..16a29fa14700cb69e4aa67e4a780273ba4d2d1c1 100644 --- a/client/src/app/instance/search/containers/output.component.ts +++ b/client/src/app/instance/search/containers/output.component.ts @@ -9,7 +9,12 @@ import { Component } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { Observable } from 'rxjs'; + +import { Instance } from 'src/app/metamodel/models'; import { AbstractSearchComponent } from './abstract-search.component'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as searchActions from '../../store/actions/search.actions'; @Component({ @@ -21,6 +26,13 @@ import * as searchActions from '../../store/actions/search.actions'; * @classdesc Search output container. */ export class OutputComponent extends AbstractSearchComponent { + public instance: Observable<Instance>; + + constructor(protected store: Store<{ }>) { + super(store); + this.instance = store.select(instanceSelector.selectInstanceByRouteName); + } + ngOnInit() { Promise.resolve(null).then(() => this.store.dispatch(searchActions.changeStep({ step: 'output' }))); Promise.resolve(null).then(() => this.store.dispatch(searchActions.checkOutput())); diff --git a/client/src/app/instance/search/containers/result.component.html b/client/src/app/instance/search/containers/result.component.html index 9e4fec28e05e52c08e8baab91789b911b6bbf5f6..d9b4fdbf2a8260fc9d97ecb02df3294d25a04e9f 100644 --- a/client/src/app/instance/search/containers/result.component.html +++ b/client/src/app/instance/search/containers/result.component.html @@ -19,11 +19,18 @@ </div> </div> <ng-container *ngIf="(dataLength | async) > 0"> + <div class="jumbotron mb-4 py-4"> + <div class="lead"> + Dataset <span class="font-weight-bold">{{ (datasetList | async | datasetByName:(datasetSelected | async)).label }}</span> + selected with <span class="font-weight-bold">{{ dataLength | async }}</span> objects found. + </div> + </div> <app-download [datasetSelected]="datasetSelected | async" [datasetList]="datasetList | async" [criteriaList]="criteriaList | async" [outputList]="outputList | async" + [coneSearch]="coneSearch | async" [dataLength]="dataLength | async" [sampRegistered]="sampRegistered | async" (broadcast)="broadcastVotable($event)"> @@ -50,7 +57,8 @@ [datasetSelected]="datasetSelected | async" [datasetList]="datasetList | async" [criteriaList]="criteriaList | async" - [outputList]="outputList | async"> + [outputList]="outputList | async" + [coneSearch]="coneSearch | async"> </app-url-display> <!-- <app-cone-search-plot-tab [datasetName]="datasetName | async" @@ -64,10 +72,11 @@ </app-cone-search-plot-tab> --> <app-datatable-tab [datasetSelected]="datasetSelected | async" - [instanceSelected]="instanceSelected | async" + [instance]="instance | async" [datasetList]="datasetList | async" [attributeList]="attributeList | async" [outputList]="outputList | async" + [queryParams]="queryParams | async" [dataLength]="dataLength | async" [data]="data | async" [dataIsLoading]="dataIsLoading | async" diff --git a/client/src/app/instance/search/containers/result.component.ts b/client/src/app/instance/search/containers/result.component.ts index 1e1c3359b8c7a5fafe764ade7c1c49eef4107a20..82f65348ed3b1cd56878cb116aa9eaae9053fec9 100644 --- a/client/src/app/instance/search/containers/result.component.ts +++ b/client/src/app/instance/search/containers/result.component.ts @@ -14,6 +14,8 @@ import { Observable, Subscription } from 'rxjs'; import { AbstractSearchComponent } from './abstract-search.component'; import { Pagination } from '../../store/models'; +import { Instance } from 'src/app/metamodel/models'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as searchActions from '../../store/actions/search.actions'; import * as searchSelector from '../../store/selectors/search.selector'; import * as sampActions from '../../store/actions/samp.actions'; @@ -31,6 +33,7 @@ import * as sampSelector from '../../store/selectors/samp.selector'; * @implements OnDestroy */ export class ResultComponent extends AbstractSearchComponent { + public instance: Observable<Instance>; public dataLength: Observable<number>; public dataLengthIsLoading: Observable<boolean>; public dataLengthIsLoaded: Observable<boolean>; @@ -44,6 +47,7 @@ export class ResultComponent extends AbstractSearchComponent { constructor(protected store: Store<{ }>) { super(store); + this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.dataLength = this.store.select(searchSelector.selectDataLength); this.dataLengthIsLoading = this.store.select(searchSelector.selectDataLengthIsLoading); this.dataLengthIsLoaded = this.store.select(searchSelector.selectDataLengthIsLoaded); diff --git a/client/src/app/instance/search/search-routing.module.ts b/client/src/app/instance/search/search-routing.module.ts index 6c887b65a4d5a81364fb5d1ad848dafdd4d57126..7d517c99b1441885d1cab6b1a242d5ccdd391db1 100644 --- a/client/src/app/instance/search/search-routing.module.ts +++ b/client/src/app/instance/search/search-routing.module.ts @@ -15,8 +15,10 @@ 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 '../shared-search/detail/containers/detail.component'; const routes: Routes = [ + { path: 'detail/:dname/:id', component: DetailComponent }, { path: '', component: SearchComponent, children: [ { path: '', redirectTo: 'dataset', pathMatch: 'full' }, diff --git a/client/src/app/instance/search/search.component.html b/client/src/app/instance/search/search.component.html index 4ae64be7957f290d83d86b5379f504eaf9b74a0c..a4b16e3bdb1354feee9d04902c3b20af6a7e25c1 100644 --- a/client/src/app/instance/search/search.component.html +++ b/client/src/app/instance/search/search.component.html @@ -1,7 +1,7 @@ <div class="mx-1 mx-sm-5 px-1 px-sm-5"> <app-progress-bar [currentStep]="currentStep | async" - [instanceSelected]="instanceSelected | async" + [instance]="instance | async" [datasetSelected]="datasetSelected | async" [criteriaStepChecked]="criteriaStepChecked | async" [outputStepChecked]="outputStepChecked | async" diff --git a/client/src/app/instance/search/search.component.ts b/client/src/app/instance/search/search.component.ts index 175c4e9bd1d0e714fabdfeff01e4f4491ac3beac..d4e0fa2063ed3ebd044912154697a857bda395c9 100644 --- a/client/src/app/instance/search/search.component.ts +++ b/client/src/app/instance/search/search.component.ts @@ -13,6 +13,7 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { SearchQueryParams } from '../store/models'; +import { Instance } from 'src/app/metamodel/models'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; import * as searchSelector from '../store/selectors/search.selector'; @@ -26,7 +27,7 @@ import * as searchSelector from '../store/selectors/search.selector'; * @classdesc Search container. */ export class SearchComponent { - public instanceSelected: Observable<string>; + public instance: Observable<Instance>; public datasetSelected: Observable<string>; public currentStep: Observable<string>; public criteriaStepChecked: Observable<boolean>; @@ -36,7 +37,7 @@ export class SearchComponent { public outputList: Observable<number[]>; constructor(private store: Store<{ }>) { - this.instanceSelected = store.select(instanceSelector.selectInstanceNameByRoute); + this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.datasetSelected = store.select(datasetSelector.selectDatasetNameByRoute); this.currentStep = store.select(searchSelector.selectCurrentStep); this.criteriaStepChecked = store.select(searchSelector.selectCriteriaStepChecked); diff --git a/client/src/app/instance/shared-search/components/datatable/datatable.component.html b/client/src/app/instance/shared-search/components/datatable/datatable.component.html index 881f79065975906242993d75e2239f945bd4ff4c..7b7ee23a3405f901e1183f30f59c9dbbbfeceefc 100644 --- a/client/src/app/instance/shared-search/components/datatable/datatable.component.html +++ b/client/src/app/instance/shared-search/components/datatable/datatable.component.html @@ -35,7 +35,7 @@ <span class="far fa-square fa-lg text-secondary"></span> </span> <span *ngIf="isSelected(datum)"> - <span class="fas fa-check-square fa-lg theme-color"></span> + <span class="fas fa-check-square fa-lg" [ngStyle]="{ 'color': instance.config.design.design_color }"></span> </span> </button> </td> @@ -45,7 +45,8 @@ <app-detail-renderer [value]="datum[attribute.label]" [datasetName]="dataset.name" - [instanceSelected]="instanceSelected" + [instanceSelected]="instance.name" + [queryParams]="queryParams" [config]="getRendererConfig(attribute)"> </app-detail-renderer> </div> diff --git a/client/src/app/instance/shared-search/components/datatable/datatable.component.ts b/client/src/app/instance/shared-search/components/datatable/datatable.component.ts index 698cf0403bf1ea003acb77f3b9da144bb38132db..1e90851ca9be53f1a232c612002eb5a8ae64981f 100644 --- a/client/src/app/instance/shared-search/components/datatable/datatable.component.ts +++ b/client/src/app/instance/shared-search/components/datatable/datatable.component.ts @@ -9,9 +9,8 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Attribute, Dataset, DetailRendererConfig, DownloadRendererConfig, ImageRendererConfig, LinkRendererConfig, RendererConfig } from 'src/app/metamodel/models'; -import { Pagination, PaginationOrder } from 'src/app/instance/store/models'; - +import { Instance, Attribute, Dataset, DetailRendererConfig, DownloadRendererConfig, ImageRendererConfig, LinkRendererConfig, RendererConfig } from 'src/app/metamodel/models'; +import { Pagination, PaginationOrder, SearchQueryParams } from 'src/app/instance/store/models'; @Component({ selector: 'app-datatable', @@ -26,9 +25,10 @@ import { Pagination, PaginationOrder } from 'src/app/instance/store/models'; */ export class DatatableComponent implements OnInit { @Input() dataset: Dataset; - @Input() instanceSelected: string; + @Input() instance: Instance; @Input() attributeList: Attribute[]; @Input() outputList: number[]; + @Input() queryParams: SearchQueryParams; @Input() dataLength: number; @Input() data: any[]; @Input() dataIsLoading: boolean; diff --git a/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.html b/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.html index 37c9f3133e39d52496faf4585956836050038ccc..bb61c20cb79cb4d03d91803916243d0ace474c9c 100644 --- a/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.html +++ b/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.html @@ -1,4 +1,6 @@ -<a routerLink="/instance/{{ instanceSelected }}/detail/{{ datasetName }}/{{ value }}" [target]="config.blank == true ? '_blank' : '_self'" +<a routerLink="/instance/{{ instanceSelected }}/search/detail/{{ datasetName }}/{{ value }}" + [target]="config.blank == true ? '_blank' : '_self'" + [queryParams]="queryParams" [ngClass]="{'btn btn-outline-primary btn-sm' : config.display == 'text-button'}"> {{ value }} </a> diff --git a/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.ts b/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.ts index d6df4dfd8384e2931696c6807a5a0c97bfdeaefb..8d148a3fa0c9b5cc7d617ab5a7f4992fcaba8ccf 100644 --- a/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.ts +++ b/client/src/app/instance/shared-search/components/datatable/renderer/detail-renderer.component.ts @@ -9,6 +9,7 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; +import { SearchQueryParams } from 'src/app/instance/store/models'; import { DetailRendererConfig } from 'src/app/metamodel/models/renderers/detail-renderer-config.model'; @Component({ @@ -24,5 +25,6 @@ export class DetailRendererComponent { @Input() value: string | number; @Input() datasetName: string; @Input() instanceSelected: string; + @Input() queryParams: SearchQueryParams; @Input() config: DetailRendererConfig; } diff --git a/client/src/app/instance/detail/components/default/default-object.component.html b/client/src/app/instance/shared-search/detail/components/default/default-object.component.html similarity index 100% rename from client/src/app/instance/detail/components/default/default-object.component.html rename to client/src/app/instance/shared-search/detail/components/default/default-object.component.html diff --git a/client/src/app/instance/detail/components/default/default-object.component.ts b/client/src/app/instance/shared-search/detail/components/default/default-object.component.ts similarity index 100% rename from client/src/app/instance/detail/components/default/default-object.component.ts rename to client/src/app/instance/shared-search/detail/components/default/default-object.component.ts diff --git a/client/src/app/instance/detail/components/default/index.ts b/client/src/app/instance/shared-search/detail/components/default/index.ts similarity index 100% rename from client/src/app/instance/detail/components/default/index.ts rename to client/src/app/instance/shared-search/detail/components/default/index.ts diff --git a/client/src/app/instance/detail/components/index.ts b/client/src/app/instance/shared-search/detail/components/index.ts similarity index 100% rename from client/src/app/instance/detail/components/index.ts rename to client/src/app/instance/shared-search/detail/components/index.ts diff --git a/client/src/app/instance/detail/components/object-data.component.html b/client/src/app/instance/shared-search/detail/components/object-data.component.html similarity index 100% rename from client/src/app/instance/detail/components/object-data.component.html rename to client/src/app/instance/shared-search/detail/components/object-data.component.html diff --git a/client/src/app/instance/detail/components/object-data.component.ts b/client/src/app/instance/shared-search/detail/components/object-data.component.ts similarity index 100% rename from client/src/app/instance/detail/components/object-data.component.ts rename to client/src/app/instance/shared-search/detail/components/object-data.component.ts diff --git a/client/src/app/instance/detail/components/spectra/graph/point.ts b/client/src/app/instance/shared-search/detail/components/spectra/graph/point.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/point.ts rename to client/src/app/instance/shared-search/detail/components/spectra/graph/point.ts diff --git a/client/src/app/instance/detail/components/spectra/graph/rays.ts b/client/src/app/instance/shared-search/detail/components/spectra/graph/rays.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/rays.ts rename to client/src/app/instance/shared-search/detail/components/spectra/graph/rays.ts diff --git a/client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.html b/client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.html similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.html rename to client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.html diff --git a/client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.scss b/client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.scss similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.scss rename to client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.scss diff --git a/client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.ts b/client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/spectra-graph.component.ts rename to client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-graph.component.ts diff --git a/client/src/app/instance/detail/components/spectra/graph/spectra-type.ts b/client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-type.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/graph/spectra-type.ts rename to client/src/app/instance/shared-search/detail/components/spectra/graph/spectra-type.ts diff --git a/client/src/app/instance/detail/components/spectra/index.ts b/client/src/app/instance/shared-search/detail/components/spectra/index.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/index.ts rename to client/src/app/instance/shared-search/detail/components/spectra/index.ts diff --git a/client/src/app/instance/detail/components/spectra/spectra-object.component.html b/client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.html similarity index 100% rename from client/src/app/instance/detail/components/spectra/spectra-object.component.html rename to client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.html diff --git a/client/src/app/instance/detail/components/spectra/spectra-object.component.scss b/client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.scss similarity index 100% rename from client/src/app/instance/detail/components/spectra/spectra-object.component.scss rename to client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.scss diff --git a/client/src/app/instance/detail/components/spectra/spectra-object.component.ts b/client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.ts similarity index 100% rename from client/src/app/instance/detail/components/spectra/spectra-object.component.ts rename to client/src/app/instance/shared-search/detail/components/spectra/spectra-object.component.ts diff --git a/client/src/app/instance/detail/containers/detail.component.html b/client/src/app/instance/shared-search/detail/containers/detail.component.html similarity index 100% rename from client/src/app/instance/detail/containers/detail.component.html rename to client/src/app/instance/shared-search/detail/containers/detail.component.html diff --git a/client/src/app/instance/detail/containers/detail.component.ts b/client/src/app/instance/shared-search/detail/containers/detail.component.ts similarity index 90% rename from client/src/app/instance/detail/containers/detail.component.ts rename to client/src/app/instance/shared-search/detail/containers/detail.component.ts index 331290c257df23a6736d98e8f7f702e3ab2da687..8fd9b25bd9c4b9b4dd2a58267bb806fa73bbcd87 100644 --- a/client/src/app/instance/detail/containers/detail.component.ts +++ b/client/src/app/instance/shared-search/detail/containers/detail.component.ts @@ -19,12 +19,10 @@ import * as detailActions from 'src/app/instance/store/actions/detail.actions'; import * as detailSelector from 'src/app/instance/store/selectors/detail.selector'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; import * as searchSelector from 'src/app/instance/store/selectors/search.selector'; -import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.actions'; import * as outputFamilySelector from 'src/app/metamodel/selectors/output-family.selector'; -import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions'; import * as outputCategorySelector from 'src/app/metamodel/selectors/output-category.selector'; -import * as attributeActions from 'src/app/metamodel/actions/attribute.actions'; import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector'; +import * as searchActions from 'src/app/instance/store/actions/search.actions'; /** * Interface for store state. @@ -90,11 +88,10 @@ export class DetailComponent implements OnInit, OnDestroy { ngOnInit() { // Create a micro task that is processed after the current synchronous code // This micro task prevent the expression has changed after view init error - Promise.resolve(null).then(() => this.store.dispatch(attributeActions.loadAttributeList())); - Promise.resolve(null).then(() => this.store.dispatch(outputFamilyActions.loadOutputFamilyList())); - Promise.resolve(null).then(() => this.store.dispatch(outputCategoryActions.loadOutputCategoryList())); + Promise.resolve(null).then(() => this.store.dispatch(searchActions.initSearch())); this.attributeListIsLoadedSubscription = this.attributeListIsLoaded.subscribe(attributeListIsLoaded => { if (attributeListIsLoaded) { + Promise.resolve(null).then(() => this.store.dispatch(searchActions.loadDefaultFormParameters())); Promise.resolve(null).then(() => this.store.dispatch(detailActions.retrieveObject())); } }); diff --git a/client/src/app/instance/detail/detail.module.ts b/client/src/app/instance/shared-search/detail/detail.module.ts similarity index 76% rename from client/src/app/instance/detail/detail.module.ts rename to client/src/app/instance/shared-search/detail/detail.module.ts index fbaaabfa3e090c12c51338d99b4ec7ebd6f32bdc..d9d97c4f5c9ae69ff1a5b6a85b6b71836f2f1767 100644 --- a/client/src/app/instance/detail/detail.module.ts +++ b/client/src/app/instance/shared-search/detail/detail.module.ts @@ -10,16 +10,15 @@ import { NgModule } from '@angular/core'; import { SharedModule } from 'src/app/shared/shared.module'; -import { DetailRoutingModule, routedComponents } from './detail-routing.module'; +import { DetailComponent } from './containers/detail.component'; import { dummiesComponents } from './components'; @NgModule({ imports: [ - SharedModule, - DetailRoutingModule + SharedModule ], declarations: [ - routedComponents, + DetailComponent, dummiesComponents ] }) diff --git a/client/src/app/instance/shared-search/shared-search.module.ts b/client/src/app/instance/shared-search/shared-search.module.ts index 8d66fd662e112bf97b1832d2c6bfd218ffd5451e..061d35abcbd43e1eef08f518ced0d4f14ccc0f52 100644 --- a/client/src/app/instance/shared-search/shared-search.module.ts +++ b/client/src/app/instance/shared-search/shared-search.module.ts @@ -11,12 +11,14 @@ import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { SharedModule } from 'src/app/shared/shared.module'; +import { DetailModule } from './detail/detail.module'; import { sharedComponents } from './components'; import { sharedPipes } from './pipes'; @NgModule({ imports: [ SharedModule, + DetailModule, RouterModule ], declarations: [ @@ -25,6 +27,7 @@ import { sharedPipes } from './pipes'; ], exports: [ sharedComponents, + DetailModule, sharedPipes ] }) diff --git a/client/src/app/instance/store/actions/metamodel.actions.ts b/client/src/app/instance/store/actions/metamodel.actions.ts deleted file mode 100644 index e7e7638b53b2dc3b2d50db79d4c6b445ae27daf3..0000000000000000000000000000000000000000 --- a/client/src/app/instance/store/actions/metamodel.actions.ts +++ /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. - */ - -import { createAction, props } from '@ngrx/store'; - -export const loadInstanceMetamodel = createAction('[Metamodel] Load Instance Metamodel'); -export const changeCurrentInstance = createAction('[Metamodel] Change Current Instance', props<{ currentInstance: string }>()); diff --git a/client/src/app/instance/store/effects/index.ts b/client/src/app/instance/store/effects/index.ts index 29c6402a3c50c5a7138b9d239ae5723e6421e3ec..132bb177b9768dd206195f68ed2d2eef1ca6a8fd 100644 --- a/client/src/app/instance/store/effects/index.ts +++ b/client/src/app/instance/store/effects/index.ts @@ -1,11 +1,9 @@ -import { MetamodelEffects } from './metamodel.effects'; import { SampEffects } from './samp.effects'; import { SearchEffects } from './search.effects'; import { ConeSearchEffects } from './cone-search.effects'; import { DetailEffects } from './detail.effects'; export const instanceEffects = [ - MetamodelEffects, SampEffects, SearchEffects, ConeSearchEffects, diff --git a/client/src/app/instance/store/effects/metamodel.effects.ts b/client/src/app/instance/store/effects/metamodel.effects.ts deleted file mode 100644 index c81b9168c3a7e85105aa45f8743f139dbbcc3529..0000000000000000000000000000000000000000 --- a/client/src/app/instance/store/effects/metamodel.effects.ts +++ /dev/null @@ -1,57 +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 { Injectable } from '@angular/core'; - -import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects'; -import { Store } from '@ngrx/store'; -import { of } from 'rxjs'; -import { mergeMap } from 'rxjs/operators'; - -import * as metamodelActions from '../actions/metamodel.actions'; -import * as metamodelSelector from '../selectors/metamodel.selector'; -import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; -import * as datasetActions from 'src/app/metamodel/actions/dataset.actions'; -import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions'; -import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; - -@Injectable() -export class MetamodelEffects { - loadInstanceMetamodel$ = createEffect(() => - this.actions$.pipe( - ofType(metamodelActions.loadInstanceMetamodel), - concatLatestFrom(() => [ - this.store.select(instanceSelector.selectInstanceNameByRoute), - this.store.select(metamodelSelector.selectCurrentInstance), - this.store.select(metamodelSelector.selectInstanceMetamodelIsLoaded) - ]), - mergeMap(([action, instanceName, currentInstance, instanceMetamodelIsLoaded]) => { - if (instanceName && instanceName !== currentInstance) { - instanceMetamodelIsLoaded = false; - } - - if (!instanceMetamodelIsLoaded) { - return [ - metamodelActions.changeCurrentInstance({ currentInstance: instanceName }), - datasetFamilyActions.loadDatasetFamilyList(), - datasetActions.loadDatasetList(), - surveyActions.loadSurveyList() - ]; - } else { - return of({ type: '[No Action] Load Instance Metamodel' }); - } - }) - ) - ); - - constructor( - private actions$: Actions, - private store: Store<{ }> - ) {} -} diff --git a/client/src/app/instance/store/effects/samp.effects.ts b/client/src/app/instance/store/effects/samp.effects.ts index 68035ebbd9273013ea7181412f5bbe21c772bd3d..f98e2bcb2b70a690e06375e3057d3d9d46adfb26 100644 --- a/client/src/app/instance/store/effects/samp.effects.ts +++ b/client/src/app/instance/store/effects/samp.effects.ts @@ -23,7 +23,7 @@ export class SampEffects { ofType(sampActions.register), mergeMap(() => this.sampService.register() .pipe( - map(() => sampActions.register()), + map(() => sampActions.registerSuccess()), catchError(() => of(sampActions.registerFail())) ) ) diff --git a/client/src/app/instance/store/reducers/metamodel.reducer.ts b/client/src/app/instance/store/reducers/metamodel.reducer.ts deleted file mode 100644 index 6a1733f0d13cc44a468e27b2214beba2ce4fec0b..0000000000000000000000000000000000000000 --- a/client/src/app/instance/store/reducers/metamodel.reducer.ts +++ /dev/null @@ -1,34 +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 { createReducer, on } from '@ngrx/store'; - -import * as metamodelActions from '../actions/metamodel.actions'; - -export interface State { - currentInstance: string; - instanceMetamodelIsLoaded: boolean; -} - -export const initialState: State = { - currentInstance: null, - instanceMetamodelIsLoaded: false -} - -export const metamodelReducer = createReducer( - initialState, - on(metamodelActions.changeCurrentInstance, (state, { currentInstance }) => ({ - ...state, - currentInstance, - instanceMetamodelIsLoaded: true - })) -); - -export const selectCurrentInstance = (state: State) => state.currentInstance; -export const selectInstanceMetamodelIsLoaded = (state: State) => state.instanceMetamodelIsLoaded; diff --git a/client/src/app/instance/store/selectors/metamodel.selector.ts b/client/src/app/instance/store/selectors/metamodel.selector.ts deleted file mode 100644 index 31195a6039dff02158ef4a9052c45d50dffd74cd..0000000000000000000000000000000000000000 --- a/client/src/app/instance/store/selectors/metamodel.selector.ts +++ /dev/null @@ -1,28 +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 { createSelector } from '@ngrx/store'; - -import * as reducer from '../../instance.reducer'; -import * as fromMetamodel from '../reducers/metamodel.reducer'; - -export const selectMetamodelState = createSelector( - reducer.getInstanceState, - (state: reducer.State) => state.metamodel -); - -export const selectCurrentInstance = createSelector( - selectMetamodelState, - fromMetamodel.selectCurrentInstance -); - -export const selectInstanceMetamodelIsLoaded = createSelector( - selectMetamodelState, - fromMetamodel.selectInstanceMetamodelIsLoaded -); diff --git a/client/src/app/metamodel/models/criteria-family.model.ts b/client/src/app/metamodel/models/criteria-family.model.ts index 568bb380173cddeabccd0ec17670af448b7c8db4..aeb7f90aa539d50d73eadad7016bbf1986c4fba1 100644 --- a/client/src/app/metamodel/models/criteria-family.model.ts +++ b/client/src/app/metamodel/models/criteria-family.model.ts @@ -11,4 +11,5 @@ export interface CriteriaFamily { id: number; label: string; display: number; + opened: boolean; } diff --git a/client/src/app/metamodel/models/dataset-family.model.ts b/client/src/app/metamodel/models/dataset-family.model.ts index f9e0f25addcfe908b79188d0a3f990b6f9a4a0fb..391f90392ee3e08741ef0b34ff73ad65cdb81569 100644 --- a/client/src/app/metamodel/models/dataset-family.model.ts +++ b/client/src/app/metamodel/models/dataset-family.model.ts @@ -11,4 +11,5 @@ export interface DatasetFamily { id: number; label: string; display: number; + opened: boolean; } diff --git a/client/src/app/metamodel/models/instance.model.ts b/client/src/app/metamodel/models/instance.model.ts index 716b7ac45030dc43845aa2435a1f7754fe6983ea..006bdc1d3d058f9280a3dff2af46f549d3ce2515 100644 --- a/client/src/app/metamodel/models/instance.model.ts +++ b/client/src/app/metamodel/models/instance.model.ts @@ -12,6 +12,9 @@ export interface Instance { label: string; client_url: string; config: { + design: { + design_color: string + }; search: { search_by_criteria_allowed: boolean; search_multiple_allowed: boolean; diff --git a/client/src/app/metamodel/models/output-family.model.ts b/client/src/app/metamodel/models/output-family.model.ts index a673a0a5f0419aa6b5ed1d68c86ee81a9e7c7fc4..d1d1e076bba1a1bdba4a83c4f48705b8eed3b334 100644 --- a/client/src/app/metamodel/models/output-family.model.ts +++ b/client/src/app/metamodel/models/output-family.model.ts @@ -11,4 +11,5 @@ export interface OutputFamily { id: number; label: string; display: number; + opened: boolean; } diff --git a/client/src/app/portal/containers/portal-home.component.html b/client/src/app/portal/containers/portal-home.component.html index 7fab8209cb2ce3ec74a2982dbfec41e47c310268..5d6bf9146dec27e20d822b19578f7a4d7eb801c9 100644 --- a/client/src/app/portal/containers/portal-home.component.html +++ b/client/src/app/portal/containers/portal-home.component.html @@ -12,12 +12,7 @@ </header> <main role="main" class="container-fluid pb-4"> <div class="container"> - <div *ngIf="instanceListIsLoading | async" class="row justify-content-center mt-5"> - <span class="fas fa-circle-notch fa-spin fa-3x"></span> - <span class="sr-only">Loading...</span> - </div> - - <div *ngIf="instanceListIsLoaded | async" class="row"> + <div class="row"> <app-instance-card *ngFor="let instance of (instanceList | async)" [instance]="instance" diff --git a/client/src/app/portal/containers/portal-home.component.ts b/client/src/app/portal/containers/portal-home.component.ts index 4405a97255d7be0a78375e525c845e425bf657c0..e64f8f617dc3ddf6a1b8acac4b709fb28c527a08 100644 --- a/client/src/app/portal/containers/portal-home.component.ts +++ b/client/src/app/portal/containers/portal-home.component.ts @@ -15,7 +15,6 @@ import { UserProfile } from 'src/app/auth/user-profile.model'; import { Instance } from 'src/app/metamodel/models'; import * as authActions from 'src/app/auth/auth.actions'; import * as authSelector from 'src/app/auth/auth.selector'; -import * as instanceActions from 'src/app/metamodel/actions/instance.actions'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import { AppConfigService } from 'src/app/app-config.service'; @@ -30,14 +29,13 @@ import { AppConfigService } from 'src/app/app-config.service'; * @implements OnInit */ export class PortalHomeComponent implements OnInit, OnDestroy { + public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public links = [ { label: 'Home', icon: 'fas fa-home', routerLink: '/portal' } ]; public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; public userRoles: Observable<string[]>; - public instanceListIsLoading: Observable<boolean>; - public instanceListIsLoaded: Observable<boolean>; public instanceList: Observable<Instance[]>; public userRolesSubscription: Subscription; @@ -46,13 +44,11 @@ export class PortalHomeComponent implements OnInit, OnDestroy { this.isAuthenticated = store.select(authSelector.selectIsAuthenticated); this.userProfile = store.select(authSelector.selectUserProfile); this.userRoles = store.select(authSelector.selectUserRoles); - this.instanceListIsLoading = store.select(instanceSelector.selectInstanceListIsLoading); - this.instanceListIsLoaded = store.select(instanceSelector.selectInstanceListIsLoaded); this.instanceList = store.select(instanceSelector.selectAllInstances); } ngOnInit() { - this.store.dispatch(instanceActions.loadInstanceList()); + this.favIcon.href = 'favicon.ico'; const adminLink = { label: 'Admin', icon: 'fas fa-tools', routerLink: '/admin' }; if (!this.config.authenticationEnabled) { this.links.push(adminLink); diff --git a/client/src/app/shared/components/navbar.component.html b/client/src/app/shared/components/navbar.component.html index 2c8295162061fc29f04bce23a4c0541146b2ee41..14be398008e56c8ba1ee9dcd4dc86ad31579cd08 100644 --- a/client/src/app/shared/components/navbar.component.html +++ b/client/src/app/shared/components/navbar.component.html @@ -1,7 +1,11 @@ <nav class="navbar navbar-light bg-light navbar-expand-md fixed-top border-bottom"> <!-- Logo --> - <a href="{{ baseHref }}" class="navbar-brand"> - <img src="assets/cesam_anis40.png" alt="CeSAM logo" /> + <a *ngIf="!instance" href="{{ baseHref }}" class="navbar-brand"> + <img src="assets/cesam_anis40.png" alt="ANIS logo" /> + </a> + + <a *ngIf="instance" routerLink="/instance/{{ instance.name }}" class="navbar-brand"> + <img src="assets/{{ instance.name }}-logo.png" alt="Instance logo" /> </a> <!-- Right Navigation --> @@ -21,7 +25,7 @@ </button> <span *ngIf="isAuthenticated" id="dropdown-menu" dropdown> <button id="button-basic" dropdownToggle type="button" class="btn btn-light" aria-controls="dropdown-basic"> - <span class="fa-stack theme-color"> + <span class="fa-stack" [ngStyle]="{ color: instance ? instance.config.design.design_color : '#7AC29A' }"> <span class="fas fa-circle fa-2x"></span> <span class="fas fa-user fa-stack-1x fa-inverse"></span> </span> diff --git a/client/src/app/shared/components/navbar.component.ts b/client/src/app/shared/components/navbar.component.ts index 733e55789e7d5b65bea006491b717cfdd758574f..51379dea9a1831eda3124f85f8f8e6a0e5c0c009 100644 --- a/client/src/app/shared/components/navbar.component.ts +++ b/client/src/app/shared/components/navbar.component.ts @@ -9,6 +9,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; +import { Instance } from 'src/app/metamodel/models'; import { UserProfile } from 'src/app/auth/user-profile.model'; @Component({ @@ -23,6 +24,7 @@ export class NavbarComponent { @Input() userProfile: UserProfile = null; @Input() baseHref: string; @Input() authenticationEnabled: boolean; + @Input() instance: Instance; @Output() login: EventEmitter<any> = new EventEmitter(); @Output() logout: EventEmitter<any> = new EventEmitter(); @Output() openEditProfile: EventEmitter<any> = new EventEmitter(); diff --git a/client/src/app/shared/pipes/index.ts b/client/src/app/shared/pipes/index.ts index 85f656d958fead98c129a416d03a08b3fccbc83a..b8263c6a6051a3543d00b84d9b29b2e6a4469823 100644 --- a/client/src/app/shared/pipes/index.ts +++ b/client/src/app/shared/pipes/index.ts @@ -13,6 +13,7 @@ import { SurveyByNamePipe } from './survey-by-name.pipe'; import { OptionListBySelectPipe } from './option-list-by-select.pipe'; import { OutputFamilyById } from './output-family-by-id.pipe'; import { DatasetByNamePipe } from './dataset-by-name.pipe'; +import { InstanceByNamePipe } from './instance-by-name.pipe'; export const sharedPipes = [ DatasetListByFamilyPipe, @@ -20,5 +21,6 @@ export const sharedPipes = [ SurveyByNamePipe, OptionListBySelectPipe, OutputFamilyById, - DatasetByNamePipe + DatasetByNamePipe, + InstanceByNamePipe ]; diff --git a/client/src/app/shared/pipes/instance-by-name.pipe.ts b/client/src/app/shared/pipes/instance-by-name.pipe.ts new file mode 100644 index 0000000000000000000000000000000000000000..ffb56e0da45a96079c17000b3bc33fad332f82a1 --- /dev/null +++ b/client/src/app/shared/pipes/instance-by-name.pipe.ts @@ -0,0 +1,19 @@ +/** + * 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 { Pipe, PipeTransform } from '@angular/core'; + +import { Instance } from 'src/app/metamodel/models'; + +@Pipe({name: 'instanceByName'}) +export class InstanceByNamePipe implements PipeTransform { + transform(instanceList: Instance[], instanceName: string): Instance { + return instanceList.find(instance => instance.name === instanceName); + } +} diff --git a/client/src/assets/default-favicon.ico b/client/src/assets/default-favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..fe0301e8a2cfb923d40a6d1af50ec1280db6948c Binary files /dev/null and b/client/src/assets/default-favicon.ico differ diff --git a/client/src/assets/default-logo.png b/client/src/assets/default-logo.png new file mode 100755 index 0000000000000000000000000000000000000000..30da450f9e6bcb232ed986468d30fed44dfc0ce3 Binary files /dev/null and b/client/src/assets/default-logo.png differ diff --git a/client/src/assets/sdb-favicon.ico b/client/src/assets/sdb-favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3c5447241705f2c51891bbe67789c6d11382d760 Binary files /dev/null and b/client/src/assets/sdb-favicon.ico differ diff --git a/client/src/assets/sdb-logo.png b/client/src/assets/sdb-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2ec3dc9dc91622daa10cdac0c401de9c4f4de53f Binary files /dev/null and b/client/src/assets/sdb-logo.png differ diff --git a/client/src/index.html b/client/src/index.html index a0167da6dcb624806b494ce0469b89e84a7ab238..82bcb25eaef1535bfdf72649fd25b94976825b6e 100644 --- a/client/src/index.html +++ b/client/src/index.html @@ -5,7 +5,7 @@ <title>Anis - Client</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> - <link rel="icon" type="image/x-icon" href="favicon.ico"> + <link rel="icon" id="favicon" type="image/x-icon" href="favicon.ico"> </head> <body class="h-100"> <app-root class="d-flex flex-column h-100"></app-root> diff --git a/client/src/styles.scss b/client/src/styles.scss index 388dc72eda0e8cd56595c80bfcc8c8b5650ec62e..db95f8b3e83d57b52cc97d8b8c0f4bb9a6f0a8b4 100644 --- a/client/src/styles.scss +++ b/client/src/styles.scss @@ -40,11 +40,6 @@ @import '~ngx-bootstrap/datepicker/bs-datepicker.css'; /* Global styles */ - -.theme-color { - color: #7AC29A; -} - main { margin-top: 100px; } @@ -85,7 +80,6 @@ input.ng-invalid, select.ng-invalid, ng-select.ng-invalid div.ng-select-containe } /* Utilities */ - .pointer { cursor: pointer; } diff --git a/conf-dev/create-db.sh b/conf-dev/create-db.sh index 692077d4a2f12f146d6a77495e522d2aa20e6c53..464504e5a199237a333cf52dd96c6e720fd1ffbd 100644 --- a/conf-dev/create-db.sh +++ b/conf-dev/create-db.sh @@ -59,7 +59,7 @@ curl -d '{"label":"Spectra graph","value":"spectra_graph","display":20,"select_n curl -d '{"label":"Test","dbname":"anis_test","dbtype":"pdo_pgsql","dbhost":"db","dbport":5432,"dblogin":"anis","dbpassword":"anis"}' --header 'Content-Type: application/json' -X POST http://localhost/database # Add default instance -curl -d '{"name":"default","label":"Default instance","client_url":"http://localhost:4200","config":{"search":{"search_by_criteria_allowed":true,"search_multiple_allowed":false,"search_multiple_all_datasets_selected":false},"documentation":{"documentation_allowed":false}}}' --header 'Content-Type: application/json' -X POST http://localhost/instance +curl -d '{"name":"default","label":"Default instance","client_url":"http://localhost:4200","config":{"design":{"design_color":"#7AC29A"},"search":{"search_by_criteria_allowed":true,"search_multiple_allowed":false,"search_multiple_all_datasets_selected":false},"documentation":{"documentation_allowed":false}}}' --header 'Content-Type: application/json' -X POST http://localhost/instance # Add ANIS, SVOM and IRIS surveys curl -d '{"name":"anis_survey","label":"ANIS survey","description":"Survey used for testing","link":"https://anis.lam.fr","manager":"F. Agneray","id_database":1}' --header 'Content-Type: application/json' -X POST http://localhost/survey @@ -67,9 +67,9 @@ curl -d '{"name":"svom","label":"SVOM","description":"Survey used for testing"," curl -d '{"name":"iris","label":"IRiS","description":"Survey used for testing","link":"http://iris.lam.fr","manager":"S. Basa","id_database":1}' --header 'Content-Type: application/json' -X POST http://localhost/survey # Add dataset families -curl -d '{"label":"Default dataset family","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family -curl -d '{"label":"SVOM dataset family","display":20}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family -curl -d '{"label":"IRiS dataset family","display":30}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family +curl -d '{"label":"Default dataset family","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family +curl -d '{"label":"SVOM dataset family","display":20,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family +curl -d '{"label":"IRiS dataset family","display":30,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family # Add datasets curl -d '{"name":"vipers_dr2_w1","table_ref":"aspic_vipers_dr2_w1","label":"VIPERS-W1 (DR2)","description":"VIPERS W1 dataset","display":10,"data_path":"\/ASPIC\/VIPERS_DR2","config":{"images":[],"cone_search":{"cone_search_enabled":false,"cone_search_opened":true,"cone_search_column_ra":null,"cone_search_column_dec":null,"cone_search_plot_enabled":false,"cone_search_sdss_enabled":true,"cone_search_sdss_display":10,"cone_search_background":[]},"download":{"download_enabled":true,"download_opened":false,"download_csv":true,"download_ascii":true,"download_vo":false,"download_archive":true},"summary":{"summary_enabled":true,"summary_opened":false},"server_link":{"server_link_enabled":false,"server_link_opened":false},"samp":{"samp_enabled":false,"samp_opened":false},"datatable":{"datatable_enabled":true,"datatable_opened":false,"datatable_selectable_rows":false}},"public":true,"survey_name":"anis_survey"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset-family/1/dataset @@ -78,8 +78,8 @@ curl -d '{"name":"observations","table_ref":"v_observation","label":"IRiS obs"," curl -d '{"name":"vvds_f02_udeep","table_ref":"aspic_vvds_f02_udeep","label":"VVDS2h Ultra Deep","description":"VVDS2h Ultra Deep","display":20,"data_path":"","config":{"images":[],"cone_search":{"cone_search_enabled":false,"cone_search_opened":true,"cone_search_column_ra":null,"cone_search_column_dec":null,"cone_search_plot_enabled":false,"cone_search_sdss_enabled":true,"cone_search_sdss_display":10,"cone_search_background":[]},"download":{"download_enabled":true,"download_opened":false,"download_csv":true,"download_ascii":true,"download_vo":false,"download_archive":true},"summary":{"summary_enabled":true,"summary_opened":false},"server_link":{"server_link_enabled":false,"server_link_opened":false},"samp":{"samp_enabled":false,"samp_opened":false},"datatable":{"datatable_enabled":true,"datatable_opened":false,"datatable_selectable_rows":false}},"public":true,"survey_name":"anis_survey"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset-family/1/dataset # Add vipers_dr2_w1 attributes -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/criteria-family -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/output-family +curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/criteria-family +curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/output-family curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/1/output-category curl -d '{"id":1,"name":"num","label":"num","form_label":"num","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":"field","type":"decimal","operator":"eq","min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"detail","renderer_config":{"display":"text","blank":true},"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":true,"renderer_detail":null,"renderer_detail_config":null,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute @@ -99,8 +99,8 @@ curl -d '{"id":57,"name":"spec1dnoise","label":"spec1dnoise","form_label":"spec1 curl -d '{"id":58,"name":"spec1dsky","label":"spec1dsky","form_label":"spec1dsky","description":null,"output_display":580,"criteria_display":580,"search_flag":null,"search_type":null,"type":"text","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"display_detail":580,"selected":true,"order_by":false,"order_display":580,"detail":true,"renderer_detail":null,"renderer_detail_config":null,"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}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute # Add sp_cards attributes -curl -d '{"label":"Card","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/criteria-family -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/output-family +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 curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/2/output-category curl -d '{"id":1,"name":"acronym","label":"acronym","form_label":"Product Acronym","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":"select","type":"string","operator":"eq","min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"options":[{"label":"LAMTEST","value":"LAMTEST","display":10},{"label":"LAMTEST_DC1","value":"LAMTEST_DC1","display":20},{"label":"MXT-EVT-CAL","value":"MXT-EVT-CAL","display":30}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":2,"id_output_category":2}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute @@ -114,8 +114,8 @@ curl -d '{"id":8,"name":"search_kw","label":"search_kw","form_label":"KWs search curl -d '{"id":9,"name":"json_schema_uploaded","label":"json_schema_uploaded","form_label":"json_schema_uploaded","description":null,"output_display":90,"criteria_display":90,"search_flag":null,"search_type":null,"type":"json","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"display_detail":90,"selected":true,"order_by":false,"order_display":90,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"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":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute # Add observations attributes -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/criteria-family -curl -d '{"label":"Default parameters","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/output-family +curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/criteria-family +curl -d '{"label":"Default parameters","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/output-family curl -d '{"label":"Astrometry","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/3/output-category curl -d '{"label":"Observation","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/3/output-category @@ -130,8 +130,8 @@ curl -d '{"id":8,"name":"fits_file","label":"fits_file","form_label":"fits_file" curl -d '{"id":9,"name":"fits_png","label":"fits_png","form_label":"fits_png","description":null,"output_display":90,"criteria_display":90,"search_flag":null,"search_type":null,"type":"string","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"image","renderer_config":{"type":"fits","display":"modal","width":"50","height":"50"},"display_detail":90,"selected":true,"order_by":false,"order_display":90,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"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}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute # Add vvds_f02_udeep attributes -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/criteria-family -curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/output-family +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 curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/4/output-category curl -d '{"id":1,"name":"vvds_ident","label":"vvds_ident","form_label":"vvds_ident","description":null,"output_display":10,"criteria_display":10,"search_flag":"ID","search_type":null,"type":"decimal","operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"display_detail":10,"selected":true,"order_by":false,"order_display":10,"detail":false,"renderer_detail":null,"renderer_detail_config":null,"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":5}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute diff --git a/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php b/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php index 5b8e0972de7ecbab90fee3d1b7d269d2f45bc8ee..91114f9e5a4685514555781c1cb694a899bb0c6c 100644 --- a/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php +++ b/server/doctrine-proxy/__CG__AppEntityCriteriaFamily.php @@ -66,10 +66,10 @@ class CriteriaFamily extends \App\Entity\CriteriaFamily implements \Doctrine\ORM public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'id', 'label', 'display', 'dataset']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset']; } - return ['__isInitialized__', 'id', 'label', 'display', 'dataset']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset']; } /** @@ -235,6 +235,28 @@ class CriteriaFamily extends \App\Entity\CriteriaFamily implements \Doctrine\ORM return parent::setDisplay($display); } + /** + * {@inheritDoc} + */ + public function getOpened() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []); + + return parent::getOpened(); + } + + /** + * {@inheritDoc} + */ + public function setOpened($opened) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]); + + return parent::setOpened($opened); + } + /** * {@inheritDoc} */ diff --git a/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php b/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php index 0adf9739fc645ed4e6fd2806935e7181826e8f17..f86a2a919859acdc727ad38ebab8c9ffcea322a0 100644 --- a/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php +++ b/server/doctrine-proxy/__CG__AppEntityDatasetFamily.php @@ -66,10 +66,10 @@ class DatasetFamily extends \App\Entity\DatasetFamily implements \Doctrine\ORM\P public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'id', 'label', 'display', 'instance', 'datasets']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'instance', 'datasets']; } - return ['__isInitialized__', 'id', 'label', 'display', 'instance', 'datasets']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'instance', 'datasets']; } /** @@ -235,6 +235,28 @@ class DatasetFamily extends \App\Entity\DatasetFamily implements \Doctrine\ORM\P return parent::setDisplay($display); } + /** + * {@inheritDoc} + */ + public function getOpened() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []); + + return parent::getOpened(); + } + + /** + * {@inheritDoc} + */ + public function setOpened($opened) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]); + + return parent::setOpened($opened); + } + /** * {@inheritDoc} */ diff --git a/server/doctrine-proxy/__CG__AppEntityOutputFamily.php b/server/doctrine-proxy/__CG__AppEntityOutputFamily.php index 2b372a634fdbf3cea0f38e99569b0abbb15c525e..6f3aedeb8794fdffc104b41d00bc3e6e2013f679 100644 --- a/server/doctrine-proxy/__CG__AppEntityOutputFamily.php +++ b/server/doctrine-proxy/__CG__AppEntityOutputFamily.php @@ -66,10 +66,10 @@ class OutputFamily extends \App\Entity\OutputFamily implements \Doctrine\ORM\Pro public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'id', 'label', 'display', 'dataset']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset']; } - return ['__isInitialized__', 'id', 'label', 'display', 'dataset']; + return ['__isInitialized__', 'id', 'label', 'display', 'opened', 'dataset']; } /** @@ -235,6 +235,28 @@ class OutputFamily extends \App\Entity\OutputFamily implements \Doctrine\ORM\Pro return parent::getDisplay(); } + /** + * {@inheritDoc} + */ + public function getOpened() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOpened', []); + + return parent::getOpened(); + } + + /** + * {@inheritDoc} + */ + public function setOpened($opened) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOpened', [$opened]); + + return parent::setOpened($opened); + } + /** * {@inheritDoc} */ diff --git a/server/src/Action/CriteriaFamilyAction.php b/server/src/Action/CriteriaFamilyAction.php index 74489ad88dfa2291b80d1dc110c7533f08e102a9..2f4a4bbd4872d805ea682a3add2aeec143670c9b 100644 --- a/server/src/Action/CriteriaFamilyAction.php +++ b/server/src/Action/CriteriaFamilyAction.php @@ -59,7 +59,7 @@ final class CriteriaFamilyAction extends AbstractAction if ($request->getMethod() === PUT) { $parsedBody = $request->getParsedBody(); - $fields = array('label', 'display'); + $fields = array('label', 'display', 'opened'); foreach ($fields as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( @@ -96,6 +96,7 @@ final class CriteriaFamilyAction extends AbstractAction { $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->flush(); } } diff --git a/server/src/Action/CriteriaFamilyListAction.php b/server/src/Action/CriteriaFamilyListAction.php index cd4a2afa83d0b95d60aff208bb6ed9b02194c425..cb05722614036fd45d5109c47016f306e3c5622e 100644 --- a/server/src/Action/CriteriaFamilyListAction.php +++ b/server/src/Action/CriteriaFamilyListAction.php @@ -63,7 +63,7 @@ final class CriteriaFamilyListAction extends AbstractAction $parsedBody = $request->getParsedBody(); // To work this action needs information - foreach (array('label', 'display') as $a) { + foreach (array('label', 'display', 'opened') as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( $request, @@ -94,6 +94,7 @@ final class CriteriaFamilyListAction extends AbstractAction $family = new CriteriaFamily($dataset); $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->persist($family); $this->em->flush(); diff --git a/server/src/Action/DatasetFamilyAction.php b/server/src/Action/DatasetFamilyAction.php index 5d78b77b3b5564dfdc37d6600d3934e2fe5349f2..774ba164e37915038045a202bef9257e0add99c6 100644 --- a/server/src/Action/DatasetFamilyAction.php +++ b/server/src/Action/DatasetFamilyAction.php @@ -59,7 +59,7 @@ final class DatasetFamilyAction extends AbstractAction if ($request->getMethod() === PUT) { $parsedBody = $request->getParsedBody(); - $fields = array('label', 'display'); + $fields = array('label', 'display', 'opened'); foreach ($fields as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( @@ -96,6 +96,7 @@ final class DatasetFamilyAction extends AbstractAction { $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->flush(); } } diff --git a/server/src/Action/DatasetFamilyListAction.php b/server/src/Action/DatasetFamilyListAction.php index 408c1efd60d2d2a9d8e6e979c2829448f631b4e2..628d56267b2c45f7a55714de77f8a436dbfcf9b4 100644 --- a/server/src/Action/DatasetFamilyListAction.php +++ b/server/src/Action/DatasetFamilyListAction.php @@ -60,7 +60,7 @@ final class DatasetFamilyListAction extends AbstractAction $parsedBody = $request->getParsedBody(); // To work this action needs information - foreach (array('label', 'display') as $a) { + foreach (array('label', 'display', 'opened') as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( $request, @@ -91,6 +91,7 @@ final class DatasetFamilyListAction extends AbstractAction $family = new DatasetFamily($instance); $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->persist($family); $this->em->flush(); diff --git a/server/src/Action/OutputFamilyAction.php b/server/src/Action/OutputFamilyAction.php index a13c399d0e23550d1cc552071f02212637f65f8e..fc0b92b41975b9c64083b2a9786e567c898b4555 100644 --- a/server/src/Action/OutputFamilyAction.php +++ b/server/src/Action/OutputFamilyAction.php @@ -59,7 +59,7 @@ final class OutputFamilyAction extends AbstractAction if ($request->getMethod() === PUT) { $parsedBody = $request->getParsedBody(); - $fields = array('label', 'display'); + $fields = array('label', 'display', 'opened'); foreach ($fields as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( @@ -96,6 +96,7 @@ final class OutputFamilyAction extends AbstractAction { $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->flush(); } } diff --git a/server/src/Action/OutputFamilyListAction.php b/server/src/Action/OutputFamilyListAction.php index ce4b642619a497effdc9b698187b23d2706a87e4..6e112af0811b436d38b7d5243c295c451150d9f4 100644 --- a/server/src/Action/OutputFamilyListAction.php +++ b/server/src/Action/OutputFamilyListAction.php @@ -63,7 +63,7 @@ final class OutputFamilyListAction extends AbstractAction $parsedBody = $request->getParsedBody(); // To work this action needs information - foreach (array('label', 'display') as $a) { + foreach (array('label', 'display', 'opened') as $a) { if ($this->isEmptyField($a, $parsedBody)) { throw new HttpBadRequestException( $request, @@ -92,6 +92,7 @@ final class OutputFamilyListAction extends AbstractAction $family = new OutputFamily($dataset); $family->setLabel($parsedBody['label']); $family->setDisplay($parsedBody['display']); + $family->setOpened($parsedBody['opened']); $this->em->persist($family); $this->em->flush(); diff --git a/server/src/Entity/CriteriaFamily.php b/server/src/Entity/CriteriaFamily.php index 91e661224adff6142561700cc690da5e4782b2b5..b238afd04f2db80cfd8024c22715c8a4780d136e 100644 --- a/server/src/Entity/CriteriaFamily.php +++ b/server/src/Entity/CriteriaFamily.php @@ -44,6 +44,13 @@ class CriteriaFamily implements \JsonSerializable */ protected $display; + /** + * @var bool + * + * @Column(type="boolean", nullable=false) + */ + protected $opened; + /** * @var Dataset * @@ -82,12 +89,23 @@ class CriteriaFamily implements \JsonSerializable $this->display = $display; } + public function getOpened() + { + return $this->opened; + } + + public function setOpened($opened) + { + $this->opened = $opened; + } + public function jsonSerialize() { return [ 'id' => $this->getId(), 'label' => $this->getLabel(), - 'display' => $this->getDisplay() + 'display' => $this->getDisplay(), + 'opened' => $this->getOpened() ]; } } diff --git a/server/src/Entity/DatasetFamily.php b/server/src/Entity/DatasetFamily.php index df0b25ae7747ff8e131dc7da23467fa19f4b4c18..4a53a1325a22f4df96e8fbbd826f36b4190c0e17 100644 --- a/server/src/Entity/DatasetFamily.php +++ b/server/src/Entity/DatasetFamily.php @@ -44,6 +44,13 @@ class DatasetFamily implements \JsonSerializable */ protected $display; + /** + * @var bool + * + * @Column(type="boolean", nullable=false) + */ + protected $opened; + /** * @var Instance * @@ -89,6 +96,16 @@ class DatasetFamily implements \JsonSerializable $this->display = $display; } + public function getOpened() + { + return $this->opened; + } + + public function setOpened($opened) + { + $this->opened = $opened; + } + public function getInstance() { return $this->instance; @@ -104,7 +121,8 @@ class DatasetFamily implements \JsonSerializable return [ 'id' => $this->getId(), 'label' => $this->getLabel(), - 'display' => $this->getDisplay() + 'display' => $this->getDisplay(), + 'opened' => $this->getOpened() ]; } } diff --git a/server/src/Entity/OutputFamily.php b/server/src/Entity/OutputFamily.php index 278954ead0009dc0dab91af0af14241c3d877559..1e10fd6b142876e49122142c5e6fc4bd9a0aa043 100644 --- a/server/src/Entity/OutputFamily.php +++ b/server/src/Entity/OutputFamily.php @@ -44,6 +44,13 @@ class OutputFamily implements \JsonSerializable */ protected $display; + /** + * @var bool + * + * @Column(type="boolean", nullable=false) + */ + protected $opened; + /** * @var Dataset * @@ -82,12 +89,23 @@ class OutputFamily implements \JsonSerializable return $this->display; } + public function getOpened() + { + return $this->opened; + } + + public function setOpened($opened) + { + $this->opened = $opened; + } + public function jsonSerialize() { return [ 'id' => $this->getId(), 'label' => $this->getLabel(), - 'display' => $this->getDisplay() + 'display' => $this->getDisplay(), + 'opened' => $this->getOpened() ]; } } diff --git a/server/tests/Action/CriteriaFamilyActionTest.php b/server/tests/Action/CriteriaFamilyActionTest.php index 5b9e3fd12ee72d14dbc560b0fcbdb5ed9d8cdedb..51e6fd73cddc6ded6d43103fea4ba68b3317aff7 100644 --- a/server/tests/Action/CriteriaFamilyActionTest.php +++ b/server/tests/Action/CriteriaFamilyActionTest.php @@ -77,7 +77,8 @@ final class CriteriaFamilyActionTest extends TestCase $fields = array( 'label' => 'Modfied family', - 'display' => 20 + 'display' => 20, + 'opened' => true ); $request = $this->getRequest('PUT')->withParsedBody($fields); diff --git a/server/tests/Action/CriteriaFamilyListActionTest.php b/server/tests/Action/CriteriaFamilyListActionTest.php index 9eab6362ec81043ab644c1538a5bda9fc158f54c..b0cd8314ae01916c71f176fa81085c4092d6626e 100644 --- a/server/tests/Action/CriteriaFamilyListActionTest.php +++ b/server/tests/Action/CriteriaFamilyListActionTest.php @@ -85,7 +85,8 @@ final class CriteriaFamilyListActionTest extends TestCase $fields = array( 'label' => 'Default criteria family', - 'display' => 10 + 'display' => 10, + 'opened' => true ); $request = $this->getRequest('POST')->withParsedBody($fields); $response = ($this->action)($request, new Response(), array('name' => 'obs_cat')); diff --git a/server/tests/Action/DatasetFamilyActionTest.php b/server/tests/Action/DatasetFamilyActionTest.php index f2b162c0abb2d05f5f0b61380e7664532077115d..429e434578e8462597e2116405fa8718c039c991 100644 --- a/server/tests/Action/DatasetFamilyActionTest.php +++ b/server/tests/Action/DatasetFamilyActionTest.php @@ -77,7 +77,8 @@ final class DatasetFamilyActionTest extends TestCase $fields = array( 'label' => 'Modfied family', - 'display' => 20 + 'display' => 20, + 'opened' => true ); $request = $this->getRequest('PUT')->withParsedBody($fields); ($this->action)($request, new Response(), array('id' => 1)); diff --git a/server/tests/Action/DatasetFamilyListActionTest.php b/server/tests/Action/DatasetFamilyListActionTest.php index f184e3b21cc208b02669ac7c34e1eea1f1a79bfa..cfbcb25aa71b90dd44726c27d06bb2f9524b6795 100644 --- a/server/tests/Action/DatasetFamilyListActionTest.php +++ b/server/tests/Action/DatasetFamilyListActionTest.php @@ -84,7 +84,8 @@ final class DatasetFamilyListActionTest extends TestCase $fields = array( 'label' => 'Default family', - 'display' => 10 + 'display' => 10, + 'opened' => true ); $request = $this->getRequest('POST')->withParsedBody($fields); diff --git a/server/tests/Action/OutputFamilyActionTest.php b/server/tests/Action/OutputFamilyActionTest.php index 73c391b17662c098416fe98c312f38191f4a74b5..948c359cda3774386f0b1d0fc294023582744e74 100644 --- a/server/tests/Action/OutputFamilyActionTest.php +++ b/server/tests/Action/OutputFamilyActionTest.php @@ -77,7 +77,8 @@ final class OutputFamilyActionTest extends TestCase $fields = array( 'label' => 'Modfied family', - 'display' => 20 + 'display' => 20, + 'opened' => true ); $request = $this->getRequest('PUT')->withParsedBody($fields); diff --git a/server/tests/Action/OutputFamilyListActionTest.php b/server/tests/Action/OutputFamilyListActionTest.php index 9f5953d7b52644fd5e0af761dd44ea21145137e8..f094c9c22366520a9ace48a7fd247a88ce09898c 100644 --- a/server/tests/Action/OutputFamilyListActionTest.php +++ b/server/tests/Action/OutputFamilyListActionTest.php @@ -85,7 +85,8 @@ final class OutputFamilyListActionTest extends TestCase $fields = array( 'label' => 'Default output family', - 'display' => 10 + 'display' => 10, + 'opened' => true ); $request = $this->getRequest('POST')->withParsedBody($fields);