diff --git a/client/src/app/admin/admin.component.html b/client/src/app/admin/admin.component.html index 5c884c3b52f4a5225b2b6596965fb0ac8845b72c..d89e40d276b3a1a09da13739e70ccd4b9fdcacab 100644 --- a/client/src/app/admin/admin.component.html +++ b/client/src/app/admin/admin.component.html @@ -1,13 +1,16 @@ -<header> - <app-admin-navbar - [isAuthenticated]="isAuthenticated | async" - [userProfile]="userProfile | async" - [authenticationEnabled]="getAuthenticationEnabled()" - (login)="login()" - (logout)="logout()" - (openEditProfile)="openEditProfile()"> - </app-admin-navbar> -</header> -<main role="main" class="container-fluid pb-4"> - <router-outlet></router-outlet> -</main> +<div class="d-flex flex-column h-100"> + <header> + <app-admin-navbar + [isAuthenticated]="isAuthenticated | async" + [userProfile]="userProfile | async" + [authenticationEnabled]="getAuthenticationEnabled()" + (login)="login()" + (logout)="logout()" + (openEditProfile)="openEditProfile()"> + </app-admin-navbar> + </header> + <main role="main" class="container-fluid pb-4"> + <router-outlet></router-outlet> + </main> + <app-footer class="footer mt-auto"></app-footer> +</div> diff --git a/client/src/app/admin/instance/components/footer-logo-form.component.html b/client/src/app/admin/instance/components/footer-logo-form.component.html new file mode 100644 index 0000000000000000000000000000000000000000..bdf494d65f0cbf9e0f80d9e7a440d98978c6f807 --- /dev/null +++ b/client/src/app/admin/instance/components/footer-logo-form.component.html @@ -0,0 +1,9 @@ +<form [formGroup]="form" novalidate> + <div class="values"> + <input type="text" class="form-control" name="href" placeholder="Href" formControlName="href"> + <input type="text" class="form-control" name="title" placeholder="title" formControlName="title"> + <input type="text" class="form-control" name="file" placeholder="File" formControlName="file"> + <input type="number" class="form-control" name="display" placeholder="Display" formControlName="display"> + <ng-content></ng-content> + </div> +</form> diff --git a/client/src/app/admin/instance/components/footer-logo-form.component.scss b/client/src/app/admin/instance/components/footer-logo-form.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..3cb1593cb2a5dcc37d49dce2930ae49158e09b2f --- /dev/null +++ b/client/src/app/admin/instance/components/footer-logo-form.component.scss @@ -0,0 +1,4 @@ +.values input { + display: inline-block; + width: 22%; +} diff --git a/client/src/app/admin/instance/components/footer-logo-form.component.ts b/client/src/app/admin/instance/components/footer-logo-form.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..13b8730e77121ebf9732570b6241f8a5d5f3d9b7 --- /dev/null +++ b/client/src/app/admin/instance/components/footer-logo-form.component.ts @@ -0,0 +1,13 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; + +import { UntypedFormGroup } from '@angular/forms'; + +@Component({ + selector: 'app-footer-logo-form', + templateUrl: 'footer-logo-form.component.html', + styleUrls: [ 'footer-logo-form.component.scss' ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FooterLogoFormComponent { + @Input() form: UntypedFormGroup; +} diff --git a/client/src/app/admin/instance/components/footer-logos-list.component.html b/client/src/app/admin/instance/components/footer-logos-list.component.html new file mode 100644 index 0000000000000000000000000000000000000000..672f6aa31e62e82573fb8cdaf93905354e57a23a --- /dev/null +++ b/client/src/app/admin/instance/components/footer-logos-list.component.html @@ -0,0 +1,11 @@ +<app-footer-logo-form *ngFor="let logo of form.controls; index as i" [form]="getLogoFormGroup(logo)"> + <button (click)="removeLogo(i)" class="btn btn-default"> + <span class="fas fa-trash-alt"></span> + </button> +</app-footer-logo-form> + +<app-footer-logo-form [form]="newLogoFormGroup" #f> + <button (click)="addLogo()" [disabled]="!f.form.valid || f.form.pristine" class="btn btn-default"> + <span class="fas fa-plus"></span> + </button> +</app-footer-logo-form> diff --git a/client/src/app/admin/instance/components/footer-logos-list.component.ts b/client/src/app/admin/instance/components/footer-logos-list.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa048c866de2c9cc72265d866ba66efd126e9adc --- /dev/null +++ b/client/src/app/admin/instance/components/footer-logos-list.component.ts @@ -0,0 +1,51 @@ +import { Component, ChangeDetectionStrategy, OnInit, Input } from '@angular/core'; +import { UntypedFormArray, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; + +import { Logo } from 'src/app/metamodel/models'; + +@Component({ + selector: 'app-footer-logos-list', + templateUrl: 'footer-logos-list.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FooterLogosListComponent implements OnInit { + @Input() form: UntypedFormArray; + @Input() logoList: Logo[]; + + newLogoFormGroup: UntypedFormGroup; + + ngOnInit() { + if (this.form.controls.length < 1 && this.logoList && this.logoList.length > 0) { + for (const logo of this.logoList) { + const logoForm = this.buildFormGroup(); + logoForm.patchValue(logo); + this.form.push(logoForm); + } + } + this.newLogoFormGroup = this.buildFormGroup(); + } + + buildFormGroup() { + return new UntypedFormGroup({ + href: new UntypedFormControl('', [Validators.required]), + title: new UntypedFormControl('', [Validators.required]), + file: new UntypedFormControl('', [Validators.required]), + display: new UntypedFormControl('', [Validators.required]) + }); + } + + getLogoFormGroup(logo) { + return logo as UntypedFormGroup; + } + + addLogo() { + this.form.push(this.newLogoFormGroup); + this.newLogoFormGroup = this.buildFormGroup(); + this.form.markAsDirty(); + } + + removeLogo(index: number) { + this.form.removeAt(index); + this.form.markAsDirty(); + } +} diff --git a/client/src/app/admin/instance/components/index.ts b/client/src/app/admin/instance/components/index.ts index 1927331f8ed08d985f937a214193e830e0ac2221..d2ae1f97a4b0ae2f1bd028c198d58357680cf8f7 100644 --- a/client/src/app/admin/instance/components/index.ts +++ b/client/src/app/admin/instance/components/index.ts @@ -9,12 +9,16 @@ import { InstanceCardComponent } from './instance-card.component'; import { InstanceFormComponent } from './instance-form.component'; +import { FooterLogoFormComponent } from './footer-logo-form.component'; +import { FooterLogosListComponent } from './footer-logos-list.component'; import { InstanceGroupTableComponent } from './instance-group-table.component'; import { InstanceGroupFormComponent } from './instance-group-form.component'; export const dummiesComponents = [ InstanceCardComponent, InstanceFormComponent, + FooterLogoFormComponent, + FooterLogosListComponent, InstanceGroupTableComponent, InstanceGroupFormComponent ]; diff --git a/client/src/app/admin/instance/components/instance-form.component.html b/client/src/app/admin/instance/components/instance-form.component.html index 39aa735896255b86550e62c829b9de01e08990b5..b12f451f7f3f83e92a9045aba213e308367a9559 100644 --- a/client/src/app/admin/instance/components/instance-form.component.html +++ b/client/src/app/admin/instance/components/instance-form.component.html @@ -73,12 +73,12 @@ </app-path-select-form-control> <div class="form-row"> <div class="form-group col-md-6"> - <label for="design_color_picker">Instance color (picker)</label> - <input class="form-control" type="color" id="design_color_picker" [value]="form.value.design_color" formControlName="design_color"> + <label for="portal_color_picker">Instance portal color (picker)</label> + <input class="form-control" type="color" id="portal_color_picker" [value]="form.value.portal_color" formControlName="portal_color"> </div> <div class="form-group col-md-6"> - <label for="design_color_input">Instance color (value)</label> - <input type="text" class="form-control" id="design_color_input" [value]="form.value.design_color" formControlName="design_color"> + <label for="portal_color_input">Instance portal color (value)</label> + <input type="text" class="form-control" id="portal_color_input" [value]="form.value.portal_color" formControlName="portal_color"> </div> </div> <div class="form-row"> @@ -91,6 +91,40 @@ <input type="text" class="form-control" id="design_background_color_input" [value]="form.value.design_background_color" formControlName="design_background_color"> </div> </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="design_text_color_picker">Instance text color (picker)</label> + <input class="form-control" type="color" id="design_text_color_picker" [value]="form.value.design_text_color" formControlName="design_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="design_text_color_input">Instance text color (value)</label> + <input type="text" class="form-control" id="design_text_color_input" [value]="form.value.design_text_color" formControlName="design_text_color"> + </div> + </div> + <div class="form-group"> + <label for="design_font_family">Instance font family</label> + <input type="text" class="form-control" id="design_font_family" name="design_font_family" formControlName="design_font_family"> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="design_link_color_picker">Instance link color (picker)</label> + <input class="form-control" type="color" id="design_link_color_picker" [value]="form.value.design_link_color" formControlName="design_link_color"> + </div> + <div class="form-group col-md-6"> + <label for="design_link_color_input">Instance link color (value)</label> + <input type="text" class="form-control" id="design_link_color_input" [value]="form.value.design_link_color" formControlName="design_link_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="design_link_hover_color_picker">Instance link hover color (picker)</label> + <input class="form-control" type="color" id="design_link_hover_color_picker" [value]="form.value.design_link_hover_color" formControlName="design_link_hover_color"> + </div> + <div class="form-group col-md-6"> + <label for="design_link_hover_color_input">Instance link hover color (value)</label> + <input type="text" class="form-control" id="design_link_hover_color_input" [value]="form.value.design_link_hover_color" formControlName="design_link_hover_color"> + </div> + </div> <app-path-select-form-control [form]="form" [disabled]="isFilesPathEmpty()" @@ -115,6 +149,10 @@ [selectType]="'file'" (loadDirectory)="onChangeFileSelect($event)"> </app-path-select-form-control> + <div class="form-group"> + <label for="design_logo_href">Logo href</label> + <input type="text" class="form-control" id="design_logo_href" name="design_logo_href" formControlName="design_logo_href"> + </div> <div class="form-row"> <div class="form-group col-md-6"> <label for="navbar_background_color_picker">Navbar background color (picker)</label> @@ -145,6 +183,30 @@ <input type="text" class="form-control" id="navbar_color_href_input" [value]="form.value.navbar_color_href" formControlName="navbar_color_href"> </div> </div> + <div class="form-group"> + <label for="navbar_font_family">Navbar font family</label> + <input type="text" class="form-control" id="navbar_font_family" name="navbar_font_family" formControlName="navbar_font_family"> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="navbar_sign_in_btn_color_picker">Navbar sign in btn color (picker)</label> + <input class="form-control" type="color" id="navbar_sign_in_btn_color_picker" [value]="form.value.navbar_sign_in_btn_color" formControlName="navbar_sign_in_btn_color"> + </div> + <div class="form-group col-md-6"> + <label for="navbar_sign_in_btn_color_input">Navbar sign in btn color (value)</label> + <input type="text" class="form-control" id="navbar_sign_in_btn_color_input" [value]="form.value.navbar_sign_in_btn_color" formControlName="navbar_sign_in_btn_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="navbar_user_btn_color_picker">Navbar user btn color (picker)</label> + <input class="form-control" type="color" id="navbar_user_btn_color_picker" [value]="form.value.navbar_user_btn_color" formControlName="navbar_user_btn_color"> + </div> + <div class="form-group col-md-6"> + <label for="navbar_user_btn_color_input">Navbar user btn color (value)</label> + <input type="text" class="form-control" id="navbar_user_btn_color_input" [value]="form.value.navbar_user_btn_color" formControlName="navbar_user_btn_color"> + </div> + </div> <div class="custom-control custom-switch mb-2"> <input class="custom-control-input" type="checkbox" id="back_to_portal" name="back_to_portal" formControlName="back_to_portal"> <label class="custom-control-label" for="back_to_portal">Back to portal</label> @@ -185,8 +247,187 @@ <input type="text" class="form-control" id="footer_text_color_input" [value]="form.value.footer_text_color" formControlName="footer_text_color"> </div> </div> + <div class="form-group"> + <label for="footer_logos">Footer logos</label> + <app-footer-logos-list + [form]="footerLogosFormArray" + [logoList]="getFooterLogoListByDisplay()"> + </app-footer-logos-list> + </div> + </accordion-group> + <accordion-group heading="[Search] Design progress bar" [isOpen]="false"> + <div class="form-group"> + <label for="progress_bar_title">Progress bar title</label> + <input type="text" class="form-control" id="progress_bar_title" formControlName="progress_bar_title"> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_title_color_picker">Progress bar title color (picker)</label> + <input class="form-control" type="color" id="progress_bar_title_color_picker" [value]="form.value.progress_bar_title_color" formControlName="progress_bar_title_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_title_color_input">Progress bar title color (value)</label> + <input type="text" class="form-control" id="progress_bar_title_color_input" [value]="form.value.progress_bar_title_color" formControlName="progress_bar_title_color"> + </div> + </div> + <div class="form-group"> + <label for="progress_bar_subtitle">Progress bar subtitle</label> + <input type="text" class="form-control" id="progress_bar_subtitle" formControlName="progress_bar_subtitle"> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_subtitle_color_picker">Progress bar subtitle color (picker)</label> + <input class="form-control" type="color" id="progress_bar_subtitle_color_picker" [value]="form.value.progress_bar_subtitle_color" formControlName="progress_bar_subtitle_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_subtitle_color_input">Progress bar title color (value)</label> + <input type="text" class="form-control" id="progress_bar_subtitle_color_input" [value]="form.value.progress_bar_subtitle_color" formControlName="progress_bar_subtitle_color"> + </div> + </div> + <div class="form-group"> + <label for="progress_bar_step_dataset_title">Progress bar step dataset title</label> + <input type="text" class="form-control" id="progress_bar_step_dataset_title" formControlName="progress_bar_step_dataset_title"> + </div> + <div class="form-group"> + <label for="progress_bar_step_criteria_title">Progress bar step criteria title</label> + <input type="text" class="form-control" id="progress_bar_step_criteria_title" formControlName="progress_bar_step_criteria_title"> + </div> + <div class="form-group"> + <label for="progress_bar_step_output_title">Progress bar step output title</label> + <input type="text" class="form-control" id="progress_bar_step_output_title" formControlName="progress_bar_step_output_title"> + </div> + <div class="form-group"> + <label for="progress_bar_step_result_title">Progress bar step result title</label> + <input type="text" class="form-control" id="progress_bar_step_result_title" formControlName="progress_bar_step_result_title"> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_color_picker">Progress bar color (picker)</label> + <input class="form-control" type="color" id="progress_bar_color_picker" [value]="form.value.progress_bar_color" formControlName="progress_bar_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_color_input">Progress bar color (value)</label> + <input type="text" class="form-control" id="progress_bar_color_input" [value]="form.value.progress_bar_color" formControlName="progress_bar_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_active_color_picker">Progress bar active color (picker)</label> + <input class="form-control" type="color" id="progress_bar_active_color_picker" [value]="form.value.progress_bar_active_color" formControlName="progress_bar_active_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_active_color_input">Progress bar active color (value)</label> + <input type="text" class="form-control" id="progress_bar_active_color_input" [value]="form.value.progress_bar_active_color" formControlName="progress_bar_active_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_color_picker">Progress bar circle color (picker)</label> + <input class="form-control" type="color" id="progress_bar_circle_color_picker" [value]="form.value.progress_bar_circle_color" formControlName="progress_bar_circle_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_color_input">Progress bar cirlce color (value)</label> + <input type="text" class="form-control" id="progress_bar_circle_color_input" [value]="form.value.progress_bar_circle_color" formControlName="progress_bar_circle_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_icon_color_picker">Progress bar icon circle color (picker)</label> + <input class="form-control" type="color" id="progress_bar_circle_icon_color_picker" [value]="form.value.progress_bar_circle_icon_color" formControlName="progress_bar_circle_icon_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_icon_color_input">Progress bar icon cirlce color (value)</label> + <input type="text" class="form-control" id="progress_bar_circle_icon_color_input" [value]="form.value.progress_bar_circle_icon_color" formControlName="progress_bar_circle_icon_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_icon_active_color_picker">Progress bar icon circle active color (picker)</label> + <input class="form-control" type="color" id="progress_bar_circle_icon_active_color_picker" [value]="form.value.progress_bar_circle_icon_active_color" formControlName="progress_bar_circle_icon_active_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_circle_icon_active_color_input">Progress bar icon cirlce active color (value)</label> + <input type="text" class="form-control" id="progress_bar_circle_icon_active_color" [value]="form.value.progress_bar_circle_icon_active_color" formControlName="progress_bar_circle_icon_active_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="progress_bar_text_color_picker">Progress bar text color (picker)</label> + <input class="form-control" type="color" id="progress_bar_text_color_picker" [value]="form.value.progress_bar_text_color" formControlName="progress_bar_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="progress_bar_text_color_input">Progress bar text color (value)</label> + <input type="text" class="form-control" id="progress_bar_text_color_input" [value]="form.value.progress_bar_text_color" formControlName="progress_bar_text_color"> + </div> + </div> + <div class="custom-control custom-switch mb-2"> + <input class="custom-control-input" type="checkbox" id="progress_bar_text_bold" name="progress_bar_text_bold" formControlName="progress_bar_text_bold"> + <label class="custom-control-label" for="progress_bar_text_bold">Progress bar text bold</label> + </div> + </accordion-group> + <accordion-group heading="[Search] Next/Back buttons" [isOpen]="false"> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_next_btn_color_picker">Search next btn color (picker)</label> + <input class="form-control" type="color" id="search_next_btn_color_picker" [value]="form.value.search_next_btn_color" formControlName="search_next_btn_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_next_btn_color_input">Search next btn color (value)</label> + <input type="text" class="form-control" id="search_next_btn_color_input" [value]="form.value.search_next_btn_color" formControlName="search_next_btn_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_next_btn_hover_color_picker">Search next btn hover color (picker)</label> + <input class="form-control" type="color" id="search_next_btn_hover_color_picker" [value]="form.value.search_next_btn_hover_color" formControlName="search_next_btn_hover_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_next_btn_hover_color_input">Search next btn hover color (value)</label> + <input type="text" class="form-control" id="search_next_btn_hover_color_input" [value]="form.value.search_next_btn_hover_color" formControlName="search_next_btn_hover_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_next_btn_hover_text_color_picker">Search next btn hover text color (picker)</label> + <input class="form-control" type="color" id="search_next_btn_hover_text_color_picker" [value]="form.value.search_next_btn_hover_text_color" formControlName="search_next_btn_hover_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_next_btn_hover_text_color_input">Search next btn hover text color (value)</label> + <input type="text" class="form-control" id="search_next_btn_hover_text_color_input" [value]="form.value.search_next_btn_hover_text_color" formControlName="search_next_btn_hover_text_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_back_btn_color_picker">Search back btn color (picker)</label> + <input class="form-control" type="color" id="search_back_btn_color_picker" [value]="form.value.search_back_btn_color" formControlName="search_back_btn_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_back_btn_color_input">Search back btn color (value)</label> + <input type="text" class="form-control" id="search_back_btn_color_input" [value]="form.value.search_back_btn_color" formControlName="search_back_btn_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_back_btn_hover_color_picker">Search back btn hover color (picker)</label> + <input class="form-control" type="color" id="search_back_btn_hover_color_picker" [value]="form.value.search_back_btn_hover_color" formControlName="search_back_btn_hover_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_back_btn_hover_color_input">Search back btn hover color (value)</label> + <input type="text" class="form-control" id="search_back_btn_hover_color_input" [value]="form.value.search_back_btn_hover_color" formControlName="search_back_btn_hover_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="search_back_btn_hover_text_color_picker">Search back btn hover text color (picker)</label> + <input class="form-control" type="color" id="search_back_btn_hover_text_color_picker" [value]="form.value.search_back_btn_hover_text_color" formControlName="search_back_btn_hover_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="search_back_btn_hover_text_color_input">Search back btn text color (value)</label> + <input type="text" class="form-control" id="search_back_btn_hover_text_color_input" [value]="form.value.search_back_btn_hover_text_color" formControlName="search_back_btn_hover_text_color"> + </div> + </div> </accordion-group> - <accordion-group heading="Design family" [isOpen]="false"> + <accordion-group heading="[Search] Design family" [isOpen]="false"> <div class="form-row"> <div class="form-group col-md-6"> <label for="family_border_color_picker">Family border color (picker)</label> @@ -233,162 +474,216 @@ </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="family_color_picker">Family color (picker)</label> - <input class="form-control" type="color" id="family_color_picker" [value]="form.value.family_color" formControlName="family_color"> + <label for="family_text_color_picker">Family text color (picker)</label> + <input class="form-control" type="color" id="family_text_color_picker" [value]="form.value.family_text_color" formControlName="family_text_color"> </div> <div class="form-group col-md-6"> - <label for="family_color_input">Family color (value)</label> - <input type="text" class="form-control" id="family_color_input" [value]="form.value.family_color" formControlName="family_color"> + <label for="family_text_color_input">Family text color (value)</label> + <input type="text" class="form-control" id="family_text_color_input" [value]="form.value.family_text_color" formControlName="family_text_color"> </div> </div> </accordion-group> - <accordion-group heading="Design progress bar" [isOpen]="false"> - <div class="form-group"> - <label for="progress_bar_title">Progress bar title</label> - <input type="text" class="form-control" id="progress_bar_title" formControlName="progress_bar_title"> + <accordion-group heading="[Search] Design dataset selection" [isOpen]="false"> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="dataset_select_btn_color_picker">Dataset select btn color (picker)</label> + <input class="form-control" type="color" id="dataset_select_btn_color_picker" [value]="form.value.dataset_select_btn_color" formControlName="dataset_select_btn_color"> + </div> + <div class="form-group col-md-6"> + <label for="dataset_select_btn_color_input">Dataset select btn color (value)</label> + <input type="text" class="form-control" id="dataset_select_btn_color_input" [value]="form.value.dataset_select_btn_color" formControlName="dataset_select_btn_color"> + </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_title_color_picker">Progress bar title color (picker)</label> - <input class="form-control" type="color" id="progress_bar_title_color_picker" [value]="form.value.progress_bar_title_color" formControlName="progress_bar_title_color"> + <label for="dataset_select_btn_hover_color_picker">Dataset select btn hover color (picker)</label> + <input class="form-control" type="color" id="dataset_select_btn_hover_color_picker" [value]="form.value.dataset_select_btn_hover_color" formControlName="dataset_select_btn_hover_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_title_color_input">Progress bar title color (value)</label> - <input type="text" class="form-control" id="progress_bar_title_color_input" [value]="form.value.progress_bar_title_color" formControlName="progress_bar_title_color"> + <label for="dataset_select_btn_hover_color_input">Dataset select btn hover color (value)</label> + <input type="text" class="form-control" id="dataset_select_btn_hover_color_input" [value]="form.value.dataset_select_btn_hover_color" formControlName="dataset_select_btn_hover_color"> </div> </div> - <div class="form-group"> - <label for="progress_bar_subtitle">Progress bar subtitle</label> - <input type="text" class="form-control" id="progress_bar_subtitle" formControlName="progress_bar_subtitle"> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="dataset_select_btn_hover_text_color_picker">Dataset select btn hover text color (picker)</label> + <input class="form-control" type="color" id="dataset_select_btn_hover_text_color_picker" [value]="form.value.dataset_select_btn_hover_text_color" formControlName="dataset_select_btn_hover_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="dataset_select_btn_hover_text_color_input">Dataset select btn hover text color (value)</label> + <input type="text" class="form-control" id="dataset_select_btn_hover_text_color_input" [value]="form.value.dataset_select_btn_hover_text_color" formControlName="dataset_select_btn_hover_text_color"> + </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_subtitle_color_picker">Progress bar subtitle color (picker)</label> - <input class="form-control" type="color" id="progress_bar_subtitle_color_picker" [value]="form.value.progress_bar_subtitle_color" formControlName="progress_bar_subtitle_color"> + <label for="dataset_selected_icon_color_picker">Dataset selected icon color (picker)</label> + <input class="form-control" type="color" id="dataset_selected_icon_color_picker" [value]="form.value.dataset_selected_icon_color" formControlName="dataset_selected_icon_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_subtitle_color_input">Progress bar title color (value)</label> - <input type="text" class="form-control" id="progress_bar_subtitle_color_input" [value]="form.value.progress_bar_subtitle_color" formControlName="progress_bar_subtitle_color"> + <label for="dataset_selected_icon_color_input">Dataset selected icon color (value)</label> + <input type="text" class="form-control" id="dataset_selected_icon_color_input" [value]="form.value.dataset_selected_icon_color" formControlName="dataset_selected_icon_color"> </div> </div> + </accordion-group> + <accordion-group heading="[Search] Design search info" [isOpen]="false"> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_color_picker">Progress bar color (picker)</label> - <input class="form-control" type="color" id="progress_bar_color_picker" [value]="form.value.progress_bar_color" formControlName="progress_bar_color"> + <label for="search_info_background_color_picker">Search info background color (picker)</label> + <input class="form-control" type="color" id="search_info_background_color_picker" [value]="form.value.search_info_background_color" formControlName="search_info_background_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_color_input">Progress bar color (value)</label> - <input type="text" class="form-control" id="progress_bar_color_input" [value]="form.value.progress_bar_color" formControlName="progress_bar_color"> + <label for="search_info_background_color_input">Search info background color (value)</label> + <input type="text" class="form-control" id="search_info_background_color_input" [value]="form.value.search_info_background_color" formControlName="search_info_background_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_active_color_picker">Progress bar active color (picker)</label> - <input class="form-control" type="color" id="progress_bar_active_color_picker" [value]="form.value.progress_bar_active_color" formControlName="progress_bar_active_color"> + <label for="search_info_text_color_picker">Search info text color (picker)</label> + <input class="form-control" type="color" id="search_info_text_color_picker" [value]="form.value.search_info_text_color" formControlName="search_info_text_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_active_color_input">Progress bar active color (value)</label> - <input type="text" class="form-control" id="progress_bar_active_color_input" [value]="form.value.progress_bar_active_color" formControlName="progress_bar_active_color"> + <label for="search_info_text_color_input">Search info text color (value)</label> + <input type="text" class="form-control" id="search_info_text_color_input" [value]="form.value.search_info_text_color" formControlName="search_info_text_color"> </div> </div> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" id="search_info_help_enabled" name="search_info_help_enabled" formControlName="search_info_help_enabled"> + <label class="custom-control-label" for="search_info_help_enabled">Search info help enabled</label> + </div> + </accordion-group> + <accordion-group heading="[Search] Design search criteria" [isOpen]="false"> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_circle_color_picker">Progress bar circle color (picker)</label> - <input class="form-control" type="color" id="progress_bar_circle_color_picker" [value]="form.value.progress_bar_circle_color" formControlName="progress_bar_circle_color"> + <label for="search_criterion_background_color_picker">Search criterion background color (picker)</label> + <input class="form-control" type="color" id="search_criterion_background_color_picker" [value]="form.value.search_criterion_background_color" formControlName="search_criterion_background_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_circle_color_input">Progress bar cirlce color (value)</label> - <input type="text" class="form-control" id="progress_bar_circle_color_input" [value]="form.value.progress_bar_circle_color" formControlName="progress_bar_circle_color"> + <label for="search_criterion_background_color_input">Search criterion background color (value)</label> + <input type="text" class="form-control" id="search_criterion_background_color_input" [value]="form.value.search_criterion_background_color" formControlName="search_criterion_background_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_circle_icon_color_picker">Progress bar icon circle color (picker)</label> - <input class="form-control" type="color" id="progress_bar_circle_icon_color_picker" [value]="form.value.progress_bar_circle_icon_color" formControlName="progress_bar_circle_icon_color"> + <label for="search_criterion_text_color_picker">Search criterion text color (picker)</label> + <input class="form-control" type="color" id="search_criterion_text_color_picker" [value]="form.value.search_criterion_text_color" formControlName="search_criterion_text_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_circle_icon_color_input">Progress bar icon cirlce color (value)</label> - <input type="text" class="form-control" id="progress_bar_circle_icon_color_input" [value]="form.value.progress_bar_circle_icon_color" formControlName="progress_bar_circle_icon_color"> + <label for="search_criterion_text_color_input">Search criterion text color (value)</label> + <input type="text" class="form-control" id="search_criterion_text_color_input" [value]="form.value.search_criterion_text_color" formControlName="search_criterion_text_color"> </div> </div> + </accordion-group> + <accordion-group heading="[Search] Design output columns" [isOpen]="false"> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_circle_icon_active_color_picker">Progress bar icon circle active color (picker)</label> - <input class="form-control" type="color" id="progress_bar_circle_icon_active_color_picker" [value]="form.value.progress_bar_circle_icon_active_color" formControlName="progress_bar_circle_icon_active_color"> + <label for="output_columns_selected_color_picker">Output columns selected color (picker)</label> + <input class="form-control" type="color" id="output_columns_selected_color_picker" [value]="form.value.output_columns_selected_color" formControlName="output_columns_selected_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_circle_icon_active_color_input">Progress bar icon cirlce active color (value)</label> - <input type="text" class="form-control" id="progress_bar_circle_icon_active_color" [value]="form.value.progress_bar_circle_icon_active_color" formControlName="progress_bar_circle_icon_active_color"> + <label for="output_columns_selected_color_input">Output columns selected color (value)</label> + <input type="text" class="form-control" id="output_columns_selected_color_input" [value]="form.value.output_columns_selected_color" formControlName="output_columns_selected_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="progress_bar_text_color_picker">Progress bar text color (picker)</label> - <input class="form-control" type="color" id="progress_bar_text_color_picker" [value]="form.value.progress_bar_text_color" formControlName="progress_bar_text_color"> + <label for="output_columns_select_all_btn_color_picker">Output columns select all btn color (picker)</label> + <input class="form-control" type="color" id="output_columns_select_all_btn_color_picker" [value]="form.value.output_columns_select_all_btn_color" formControlName="output_columns_select_all_btn_color"> </div> <div class="form-group col-md-6"> - <label for="progress_bar_text_color_input">Progress bar text color (value)</label> - <input type="text" class="form-control" id="progress_bar_text_color_input" [value]="form.value.progress_bar_text_color" formControlName="progress_bar_text_color"> + <label for="output_columns_select_all_btn_color_input">Output columns select all btn color (value)</label> + <input type="text" class="form-control" id="output_columns_select_all_btn_color_input" [value]="form.value.output_columns_select_all_btn_color" formControlName="output_columns_select_all_btn_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="output_columns_select_all_btn_hover_color_picker">Output columns select all btn hover color (picker)</label> + <input class="form-control" type="color" id="output_columns_select_all_btn_hover_color_picker" [value]="form.value.output_columns_select_all_btn_hover_color" formControlName="output_columns_select_all_btn_hover_color"> + </div> + <div class="form-group col-md-6"> + <label for="output_columns_select_all_btn_hover_color_input">Output columns select all btn hover color (value)</label> + <input type="text" class="form-control" id="output_columns_select_all_btn_hover_color_input" [value]="form.value.output_columns_select_all_btn_hover_color" formControlName="output_columns_select_all_btn_hover_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="output_columns_select_all_btn_hover_text_color_picker">Output columns select all btn hover text color (picker)</label> + <input class="form-control" type="color" id="output_columns_select_all_btn_hover_text_color_picker" [value]="form.value.output_columns_select_all_btn_hover_text_color" formControlName="output_columns_select_all_btn_hover_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="output_columns_select_all_btn_hover_text_color_input">Output columns select all btn hover text color (value)</label> + <input type="text" class="form-control" id="output_columns_select_all_btn_hover_text_color_input" [value]="form.value.output_columns_select_all_btn_hover_text_color" formControlName="output_columns_select_all_btn_hover_text_color"> </div> </div> </accordion-group> - <accordion-group heading="Design result header" [isOpen]="false"> + <accordion-group heading="[Search] Design result datatable" [isOpen]="false"> <div class="form-row"> <div class="form-group col-md-6"> - <label for="result_header_background_color_picker">Result header background color (picker)</label> - <input class="form-control" type="color" id="result_header_background_color_picker" [value]="form.value.result_header_background_color" formControlName="result_header_background_color"> + <label for="result_download_btn_color_picker">Result download btn color (picker)</label> + <input class="form-control" type="color" id="result_download_btn_color_picker" [value]="form.value.result_download_btn_color" formControlName="result_download_btn_color"> </div> <div class="form-group col-md-6"> - <label for="result_header_background_color_input">Result header background color (value)</label> - <input type="text" class="form-control" id="result_header_background_color_input" [value]="form.value.result_header_background_color" formControlName="result_header_background_color"> + <label for="result_download_btn_color_input">Result download btn color (value)</label> + <input type="text" class="form-control" id="result_download_btn_color_input" [value]="form.value.result_download_btn_color" formControlName="result_download_btn_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="result_header_text_color_picker">Result header text color (picker)</label> - <input class="form-control" type="color" id="result_header_text_color_picker" [value]="form.value.result_header_text_color" formControlName="result_header_text_color"> + <label for="result_download_btn_hover_color_picker">Result download btn hover color (picker)</label> + <input class="form-control" type="color" id="result_download_btn_hover_color_picker" [value]="form.value.result_download_btn_hover_color" formControlName="result_download_btn_hover_color"> </div> <div class="form-group col-md-6"> - <label for="result_header_text_color_input">Result header text color (value)</label> - <input type="text" class="form-control" id="result_header_text_color_input" [value]="form.value.result_header_text_color" formControlName="result_header_text_color"> + <label for="result_download_btn_hover_color_input">Result download btn hover color (value)</label> + <input type="text" class="form-control" id="result_download_btn_hover_color_input" [value]="form.value.result_download_btn_hover_color" formControlName="result_download_btn_hover_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="result_header_btn_color_picker">Result header btn color (picker)</label> - <input class="form-control" type="color" id="result_header_btn_color_picker" [value]="form.value.result_header_btn_color" formControlName="result_header_btn_color"> + <label for="result_download_btn_text_color_picker">Result download btn text color (picker)</label> + <input class="form-control" type="color" id="result_download_btn_text_color_picker" [value]="form.value.result_download_btn_text_color" formControlName="result_download_btn_text_color"> </div> <div class="form-group col-md-6"> - <label for="result_header_btn_color_input">Result header btn color (value)</label> - <input type="text" class="form-control" id="result_header_btn_color_input" [value]="form.value.result_header_btn_color" formControlName="result_header_btn_color"> + <label for="result_download_btn_text_color_input">Result download btn text color (value)</label> + <input type="text" class="form-control" id="result_download_btn_text_color_input" [value]="form.value.result_download_btn_text_color" formControlName="result_download_btn_text_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="result_header_btn_hover_color_picker">Result header btn hover color (picker)</label> - <input class="form-control" type="color" id="result_header_btn_hover_color_picker" [value]="form.value.result_header_btn_hover_color" formControlName="result_header_btn_hover_color"> + <label for="result_datatable_actions_btn_color_picker">Result datatable actions btn color (picker)</label> + <input class="form-control" type="color" id="result_datatable_actions_btn_color_picker" [value]="form.value.result_datatable_actions_btn_color" formControlName="result_datatable_actions_btn_color"> </div> <div class="form-group col-md-6"> - <label for="result_header_btn_hover_color_input">Result header btn hover color (value)</label> - <input type="text" class="form-control" id="result_header_btn_hover_color_input" [value]="form.value.result_header_btn_hover_color" formControlName="result_header_btn_hover_color"> + <label for="result_datatable_actions_btn_color_input">Result datatable actions btn color (value)</label> + <input type="text" class="form-control" id="result_datatable_actions_btn_color_input" [value]="form.value.result_datatable_actions_btn_color" formControlName="result_datatable_actions_btn_color"> </div> </div> <div class="form-row"> <div class="form-group col-md-6"> - <label for="result_header_btn_text_color_picker">Result header btn text color (picker)</label> - <input class="form-control" type="color" id="result_header_btn_text_color_picker" [value]="form.value.result_header_btn_text_color" formControlName="result_header_btn_text_color"> + <label for="result_datatable_actions_btn_hover_color_picker">Result datatable actions btn hover color (picker)</label> + <input class="form-control" type="color" id="result_datatable_actions_btn_hover_color_picker" [value]="form.value.result_datatable_actions_btn_hover_color" formControlName="result_datatable_actions_btn_hover_color"> </div> <div class="form-group col-md-6"> - <label for="result_header_btn_text_color_input">Result header btn text color (value)</label> - <input type="text" class="form-control" id="result_header_btn_text_color_input" [value]="form.value.result_header_btn_text_color" formControlName="result_header_btn_text_color"> + <label for="result_datatable_actions_btn_hover_color_input">Result datatable actions btn hover color (value)</label> + <input type="text" class="form-control" id="result_datatable_actions_btn_hover_color_input" [value]="form.value.result_datatable_actions_btn_hover_color" formControlName="result_datatable_actions_btn_hover_color"> + </div> + </div> + <div class="form-row"> + <div class="form-group col-md-6"> + <label for="result_datatable_actions_btn_text_color_picker">Result datatable actions btn text color (picker)</label> + <input class="form-control" type="color" id="result_datatable_actions_btn_text_color_picker" [value]="form.value.result_datatable_actions_btn_text_color" formControlName="result_datatable_actions_btn_text_color"> + </div> + <div class="form-group col-md-6"> + <label for="result_datatable_actions_btn_text_color_input">Result datatable actions btn text color (value)</label> + <input type="text" class="form-control" id="result_datatable_actions_btn_text_color_input" [value]="form.value.result_datatable_actions_btn_text_color" formControlName="result_datatable_actions_btn_text_color"> </div> </div> - </accordion-group> - <accordion-group heading="Design result datatable" [isOpen]="false"> <div class="custom-control custom-switch mb-2"> <input class="custom-control-input" type="checkbox" id="result_datatable_bordered" name="result_datatable_bordered" formControlName="result_datatable_bordered"> <label class="custom-control-label" for="result_datatable_bordered">Result datatable bordered</label> </div> + <div class="custom-control custom-switch mb-2"> + <input class="custom-control-input" type="checkbox" id="result_datatable_bordered_radius" name="result_datatable_bordered_radius" formControlName="result_datatable_bordered_radius"> + <label class="custom-control-label" for="result_datatable_bordered_radius">Result datatable bordered radius</label> + </div> <div class="form-row"> <div class="form-group col-md-6"> <label for="result_datatable_border_color_picker">Result datatable border color (picker)</label> diff --git a/client/src/app/admin/instance/components/instance-form.component.ts b/client/src/app/admin/instance/components/instance-form.component.ts index 4d8ee67ce0e05b2e1c95e374ff6bc3497a5db9de..c16e9ae576c064ef270b8bf81d4513481f148011 100644 --- a/client/src/app/admin/instance/components/instance-form.component.ts +++ b/client/src/app/admin/instance/components/instance-form.component.ts @@ -7,15 +7,16 @@ * file that was distributed with this source code. */ -import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core'; -import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms'; +import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { UntypedFormGroup, UntypedFormArray, UntypedFormControl, Validators } from '@angular/forms'; import { Instance } from 'src/app/metamodel/models'; import { FileInfo } from 'src/app/admin/store/models'; @Component({ selector: 'app-instance-form', - templateUrl: 'instance-form.component.html' + templateUrl: 'instance-form.component.html', + changeDetection: ChangeDetectionStrategy.OnPush }) export class InstanceFormComponent implements OnInit { @Input() instance: Instance; @@ -25,6 +26,8 @@ export class InstanceFormComponent implements OnInit { @Output() loadRootDirectory: EventEmitter<string> = new EventEmitter(); @Output() onSubmit: EventEmitter<Instance> = new EventEmitter(); + footerLogosFormArray = new UntypedFormArray([]); + public form = new UntypedFormGroup({ name: new UntypedFormControl('', [Validators.required]), label: new UntypedFormControl('', [Validators.required]), @@ -37,38 +40,73 @@ export class InstanceFormComponent implements OnInit { files_path: new UntypedFormControl(''), public: new UntypedFormControl(true, [Validators.required]), portal_logo: new UntypedFormControl(''), - design_color: new UntypedFormControl('#7AC29A', [Validators.required]), + portal_color: new UntypedFormControl('#7AC29A', [Validators.required]), design_background_color: new UntypedFormControl('#FFFFFF', [Validators.required]), + design_text_color: new UntypedFormControl('#212529'), + design_font_family: new UntypedFormControl('Roboto, sans-serif'), + design_link_color: new UntypedFormControl('#007BFF'), + design_link_hover_color: new UntypedFormControl('#0056B3'), design_logo: new UntypedFormControl(''), + design_logo_href: new UntypedFormControl(null), design_favicon: new UntypedFormControl(''), navbar_background_color: new UntypedFormControl('#F8F9FA'), navbar_border_bottom_color: new UntypedFormControl('#DEE2E6'), navbar_color_href: new UntypedFormControl('#000000'), + navbar_font_family: new UntypedFormControl('auto'), + navbar_sign_in_btn_color: new UntypedFormControl('#28A745'), + navbar_user_btn_color: new UntypedFormControl('#7AC29A'), footer_background_color: new UntypedFormControl('#F8F9FA'), footer_border_top_color: new UntypedFormControl('#DEE2E6'), footer_text_color: new UntypedFormControl('#000000'), + footer_logos: this.footerLogosFormArray, family_border_color: new UntypedFormControl('#DFDFDF'), family_header_background_color: new UntypedFormControl('#F7F7F7'), family_title_color: new UntypedFormControl('#007BFF'), family_title_bold: new UntypedFormControl(false), family_background_color: new UntypedFormControl('#FFFFFF'), - family_color: new UntypedFormControl('#212529'), + family_text_color: new UntypedFormControl('#212529'), progress_bar_title: new UntypedFormControl('Dataset search'), progress_bar_title_color: new UntypedFormControl('#000000'), progress_bar_subtitle: new UntypedFormControl('Select a dataset, add criteria, select output columns and display the result.'), progress_bar_subtitle_color: new UntypedFormControl('#6C757D'), + progress_bar_step_dataset_title: new UntypedFormControl('Dataset selection'), + progress_bar_step_criteria_title: new UntypedFormControl('Search criteria'), + progress_bar_step_output_title: new UntypedFormControl('Output columns'), + progress_bar_step_result_title: new UntypedFormControl('Result table'), progress_bar_color: new UntypedFormControl('#E9ECEF'), progress_bar_active_color: new UntypedFormControl('#7AC29A'), progress_bar_circle_color: new UntypedFormControl('#FFFFFF'), progress_bar_circle_icon_color: new UntypedFormControl('#CCCCCC'), progress_bar_circle_icon_active_color: new UntypedFormControl('#FFFFFF'), progress_bar_text_color: new UntypedFormControl('#91B2BF'), - result_header_background_color: new UntypedFormControl('#E9ECEF'), - result_header_text_color: new UntypedFormControl('#000000'), - result_header_btn_color: new UntypedFormControl('#007BFF'), - result_header_btn_hover_color: new UntypedFormControl('#0069D9'), - result_header_btn_text_color: new UntypedFormControl('#FFFFFF'), + progress_bar_text_bold: new UntypedFormControl(false), + search_next_btn_color: new UntypedFormControl('#007BFF'), + search_next_btn_hover_color: new UntypedFormControl('#007BFF'), + search_next_btn_hover_text_color: new UntypedFormControl('#FFFFFF'), + search_back_btn_color: new UntypedFormControl('#6C757D'), + search_back_btn_hover_color: new UntypedFormControl('#6C757D'), + search_back_btn_hover_text_color: new UntypedFormControl('#FFFFFF'), + search_info_background_color: new UntypedFormControl('#E9ECEF'), + search_info_text_color: new UntypedFormControl('#000000'), + search_info_help_enabled: new UntypedFormControl(true), + dataset_select_btn_color: new UntypedFormControl('#6C757D'), + dataset_select_btn_hover_color: new UntypedFormControl('#6C757D'), + dataset_select_btn_hover_text_color: new UntypedFormControl('#FFFFFF'), + dataset_selected_icon_color: new UntypedFormControl('#28A745'), + search_criterion_background_color: new UntypedFormControl('#7AC29A'), + search_criterion_text_color: new UntypedFormControl('#000000'), + output_columns_selected_color: new UntypedFormControl('#7AC29A'), + output_columns_select_all_btn_color: new UntypedFormControl('#6C757D'), + output_columns_select_all_btn_hover_color: new UntypedFormControl('#6C757D'), + output_columns_select_all_btn_hover_text_color: new UntypedFormControl('#FFFFFF'), + result_download_btn_color: new UntypedFormControl('#007BFF'), + result_download_btn_hover_color: new UntypedFormControl('#0069D9'), + result_download_btn_text_color: new UntypedFormControl('#FFFFFF'), + result_datatable_actions_btn_color: new UntypedFormControl('#007BFF'), + result_datatable_actions_btn_hover_color: new UntypedFormControl('#0069D9'), + result_datatable_actions_btn_text_color: new UntypedFormControl('#FFFFFF'), result_datatable_bordered: new UntypedFormControl(true), + result_datatable_bordered_radius: new UntypedFormControl(false), result_datatable_border_color: new UntypedFormControl('#DEE2E6'), result_datatable_header_background_color: new UntypedFormControl('#FFFFFF'), result_datatable_header_text_color: new UntypedFormControl('#000000'), @@ -155,12 +193,21 @@ export class InstanceFormComponent implements OnInit { } } + getFooterLogoListByDisplay() { + if (this.instance && this.instance.footer_logos) { + return [...this.instance.footer_logos].sort((a, b) => a.display - b.display); + } else { + return []; + } + } + submit() { if (this.instance) { this.onSubmit.emit({ ...this.instance, ...this.form.getRawValue() }); + this.form.markAsPristine(); } else { this.onSubmit.emit(this.form.getRawValue()); } diff --git a/client/src/app/admin/instance/dataset-group/components/dataset-group-form.component.spec.ts b/client/src/app/admin/instance/dataset-group/components/dataset-group-form.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..8305502f044a69afabbf04d609afd16b3a50dced --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/components/dataset-group-form.component.spec.ts @@ -0,0 +1,107 @@ +/** + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { Dataset, DatasetGroup } from 'src/app/metamodel/models'; +import { DatasetGroupFormComponent } from './dataset-group-form.component'; + +describe('[admin][instance][dataset-group][components] DatasetGroupFormComponent', () => { + let component: DatasetGroupFormComponent; + let fixture: ComponentFixture<DatasetGroupFormComponent>; + let store: MockStore; + let spy; + let datasetGroup: DatasetGroup = { datasets: [], id: 1, instance_name: 'test', role: '' }; + let dataset: Dataset = { + cone_search_config_id: 1, + data_path: '', + datatable_enabled: false, + datatable_selectable_rows: true, + description: '', + display: 10, + download_ascii: true, + download_csv: false, + download_json: false, + download_vo: false, + full_data_path: '', + id_database: 10, + id_dataset_family: 1, + label: '', + name: '', + public: true, + server_link_enabled: false, + table_ref: '' + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DatasetGroupFormComponent, + ], + imports: [ + BrowserAnimationsModule, + ], + providers: [ + provideMockStore({}) + ] + }); + fixture = TestBed.createComponent(DatasetGroupFormComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + + component.datasetList = []; + component.datasetGroup = datasetGroup; + spy = jest.spyOn(component.onSubmit, 'emit'); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('submit() should emit datasetgroup, form.value and datasets', () => { + component.submit(); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith({ ...datasetGroup, ...component.form.value, datasets: component.groupDatasets }) + }); + + it('submit() should emit form.value and datasets', () => { + component.datasetGroup = null; + component.submit(); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith({ ...component.form.value, datasets: component.groupDatasets }) + }); + + it('getAvailableDatasets() should return an array with 2 elements', () => { + component.datasetList = [{ ...dataset, name: 'test1' }, { ...dataset, name: 'test2' }, { ...dataset, name: 'test1' }]; + component.groupDatasets = ['test2']; + let result = component.getAvailableDatasets(); + expect(result.length).toEqual(2); + }); + + it('addDatasets(selectElement) should add the dataset in groupDataSets array', () => { + let selectElement = { options: [{ selected: true, value: { ...dataset, name: 'test' } }] }; + component.groupDatasets = []; + expect(component.groupDatasets.length).toEqual(0) + component.addDatasets(selectElement); + expect(component.groupDatasets.length).toEqual(1); + expect(component.groupDatasets[0]).toEqual(selectElement.options[0].value) + }); + + it('removeDatasets(selectElement) should remove the dataset from groupDataSets', () => { + let selectElement = { options: [{ selected: true, value: dataset }] }; + component.groupDatasets = [dataset]; + expect(component.groupDatasets.length).toEqual(1); + component.removeDatasets(selectElement) + expect(component.groupDatasets.length).toEqual(0); + }); +}) diff --git a/client/src/app/admin/instance/dataset-group/components/dataset-group-table.component.spec.ts b/client/src/app/admin/instance/dataset-group/components/dataset-group-table.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..cd6c22a6317896517230a3586464aff7350a0a80 --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/components/dataset-group-table.component.spec.ts @@ -0,0 +1,43 @@ +/** + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { DatasetGroupTableComponent } from './dataset-group-table.component'; + +describe('[admin][instance][dataset-group][components] DatasetGroupTableComponent', () => { + let component: DatasetGroupTableComponent; + let fixture: ComponentFixture<DatasetGroupTableComponent>; + let store: MockStore; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DatasetGroupTableComponent, + ], + imports: [ + BrowserAnimationsModule, + ], + providers: [ + provideMockStore({}) + ] + }); + fixture = TestBed.createComponent(DatasetGroupTableComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); +}) diff --git a/client/src/app/admin/instance/dataset-group/components/index.spec.ts b/client/src/app/admin/instance/dataset-group/components/index.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..5ebd1117453bcdfde72534ef18e494c569eb749e --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/components/index.spec.ts @@ -0,0 +1,17 @@ +/** + * 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 { dummiesComponents } from './index'; + +describe('[[admin][instance][webpage][components]index', () => { + it('Test index components', () => { + expect(dummiesComponents.length).toEqual(2); + }); +}); + \ No newline at end of file diff --git a/client/src/app/admin/instance/dataset-group/containers/dataset-group-list.component.spec.ts b/client/src/app/admin/instance/dataset-group/containers/dataset-group-list.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..246d87b0852f21dc56e7039186ef608d06b5026d --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/containers/dataset-group-list.component.spec.ts @@ -0,0 +1,64 @@ +/** + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; + +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { DatasetGroup } from 'src/app/metamodel/models'; +import { DatasetGroupListComponent } from './dataset-group-list.component'; +import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions'; + +@Component({ + template: '' +}) +class DummyComponent { } + +describe('[admin][instance][dataset-group][containers] DatasetGroupListComponent', () => { + let component: DatasetGroupListComponent; + let fixture: ComponentFixture<DatasetGroupListComponent>; + let store: MockStore; + let spy; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DatasetGroupListComponent, + ], + imports: [ + BrowserAnimationsModule, + RouterTestingModule.withRoutes([ + { path: 'test', component: DummyComponent } + ]) + ], + providers: [ + provideMockStore({}) + ] + }); + fixture = TestBed.createComponent(DatasetGroupListComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('deleteDatasetGroup(datasetGroup: DatasetGroup) should dispatch deleteDatasetGroup action', () => { + let datasetGroup: DatasetGroup = { datasets: [], id: 1, instance_name: 'test', role: 'test' }; + spy = jest.spyOn(store, 'dispatch'); + component.deleteDatasetGroup(datasetGroup); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(datasetGroupActions.deleteDatasetGroup({ datasetGroup })) + }); +}) diff --git a/client/src/app/admin/instance/dataset-group/containers/edit-dataset-group.component.spec.ts b/client/src/app/admin/instance/dataset-group/containers/edit-dataset-group.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e3996b353b4e121710f51a6a39fcd17c5629a659 --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/containers/edit-dataset-group.component.spec.ts @@ -0,0 +1,54 @@ +/** + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; + +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { DatasetGroup } from 'src/app/metamodel/models'; +import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions'; +import { EditDatasetGroupComponent } from './edit-dataset-group.component'; + +describe('[admin][instance][dataset-group][containers] EditDatasetGroupComponent', () => { + let component: EditDatasetGroupComponent; + let fixture: ComponentFixture<EditDatasetGroupComponent>; + let store: MockStore; + let spy; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + EditDatasetGroupComponent, + ], + imports: [ + BrowserAnimationsModule, + ], + providers: [ + provideMockStore({}) + ] + }); + fixture = TestBed.createComponent(EditDatasetGroupComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('deleteDatasetGroup(datasetGroup: DatasetGroup) should dispatch deleteDatasetGroup action', () => { + let datasetGroup: DatasetGroup = { datasets: [], id: 1, instance_name: 'test', role: 'test' }; + spy = jest.spyOn(store, 'dispatch'); + component.editDatasetGroup(datasetGroup); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(datasetGroupActions.editDatasetGroup({ datasetGroup })) + }); +}) diff --git a/client/src/app/admin/instance/dataset-group/containers/new-dataset-group.component.spec.ts b/client/src/app/admin/instance/dataset-group/containers/new-dataset-group.component.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..e49329529bd15dd1ebd1d3f858ec4efaeedaf43e --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/containers/new-dataset-group.component.spec.ts @@ -0,0 +1,62 @@ +/** + * 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 { ComponentFixture, TestBed } from '@angular/core/testing'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; +import { DatasetGroup } from 'src/app/metamodel/models'; +import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions'; +import { NewDatasetGroupComponent } from './new-dataset-group.component'; +import { Component } from '@angular/core'; +import { RouterTestingModule } from '@angular/router/testing'; + +@Component({ + template: '' +}) +class DummyComponent { } + +describe('[admin][instance][dataset-group][containers] NewDatasetGroupComponent', () => { + let component: NewDatasetGroupComponent; + let fixture: ComponentFixture<NewDatasetGroupComponent>; + let store: MockStore; + let spy; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + NewDatasetGroupComponent, + ], + imports: [ + BrowserAnimationsModule, + RouterTestingModule.withRoutes([ + { path: 'test', component: DummyComponent } + ]) + ], + providers: [ + provideMockStore({}) + ] + }); + fixture = TestBed.createComponent(NewDatasetGroupComponent); + component = fixture.componentInstance; + store = TestBed.inject(MockStore); + fixture.detectChanges(); + }); + + it('should create the component', () => { + expect(component).toBeTruthy(); + }); + + it('deleteDatasetGroup(datasetGroup: DatasetGroup) should dispatch deleteDatasetGroup action', () => { + let datasetGroup: DatasetGroup = { datasets: [], id: 1, instance_name: 'test', role: 'test' }; + spy = jest.spyOn(store, 'dispatch'); + component.addNewDatasetGroup(datasetGroup); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(datasetGroupActions.addDatasetGroup({ datasetGroup })) + }); +}) diff --git a/client/src/app/admin/instance/dataset-group/dataset-group-title.resolver.spec.ts b/client/src/app/admin/instance/dataset-group/dataset-group-title.resolver.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..26b8ff83e8504037a07da23b8241014222030813 --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/dataset-group-title.resolver.spec.ts @@ -0,0 +1,62 @@ +/** + * 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 { TestBed } from '@angular/core/testing'; +import { ActivatedRouteSnapshot } from '@angular/router'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { cold } from 'jasmine-marbles'; + +import { DatasetGroupTitleResolver } from './dataset-group-title.resolver'; +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; +import { Instance } from 'src/app/metamodel/models'; + +describe('[admin][instance][dataset-group] DatasetGroupTitleResolver', () => { + let datasetGroupTitleResolver: DatasetGroupTitleResolver; + let store: MockStore; + let mockInstanceSelectorSelectInstanceByRouteName; + let instance: Instance; + let component; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [], + providers: [ + DatasetGroupTitleResolver, + provideMockStore({}), + ] + }) + instance = { ...instance, label: 'test_label', } + store = TestBed.inject(MockStore); + datasetGroupTitleResolver = TestBed.inject(DatasetGroupTitleResolver); + mockInstanceSelectorSelectInstanceByRouteName = store.overrideSelector(instanceSelector.selectInstanceByRouteName, instance); + }); + + it('should be created', () => { + expect(datasetGroupTitleResolver).toBeTruthy(); + }); + + it('resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) should return test_label - Dataset-groups list ', () => { + const expected = cold('a', { a: instance.label + ' - Dataset-groups list' }); + let route: ActivatedRouteSnapshot; + component = { name: 'DatasetGroupListComponent' } + route = { ...route, component: component, children: [], root: null, parent: null, firstChild: null, pathFromRoot: null, paramMap: null, queryParamMap: null }; + let result = datasetGroupTitleResolver.resolve(route, null); + expect(result).toBeObservable(expected); + }); + + it('resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) should return test_label - New dataset-group ', () => { + const expected = cold('a', { a: instance.label + ' - New dataset-group' }); + let route: ActivatedRouteSnapshot; + component = { name: 'TestComponent' } + route = { ...route, component: component, children: [], root: null, parent: null, firstChild: null, pathFromRoot: null, paramMap: null, queryParamMap: null }; + let result = datasetGroupTitleResolver.resolve(route, null); + expect(result).toBeObservable(expected); + }); +}); diff --git a/client/src/app/admin/instance/dataset-group/dataset-group.module.spec.ts b/client/src/app/admin/instance/dataset-group/dataset-group.module.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..892bdc741e1ffc471402aba79818100a06bdd676 --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/dataset-group.module.spec.ts @@ -0,0 +1,16 @@ +/** + * 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 { DatasetGroupModule } from './dataset-group.module'; + +describe('[admin][instance][dataset-group]DatasetGroupModule', () => { + it('Test DatasetGroupModule module', () => { + expect(DatasetGroupModule.name).toEqual('DatasetGroupModule'); + }); +}); diff --git a/client/src/app/admin/instance/dataset-group/edit-dataset-group-title.resolver.spec.ts b/client/src/app/admin/instance/dataset-group/edit-dataset-group-title.resolver.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3cb3eeae7982d6eb5c9937416c881e8b9aa1c75 --- /dev/null +++ b/client/src/app/admin/instance/dataset-group/edit-dataset-group-title.resolver.spec.ts @@ -0,0 +1,67 @@ +/** + * 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 { TestBed } from '@angular/core/testing'; +import { MockStore, provideMockStore } from '@ngrx/store/testing'; + +import { cold, hot } from 'jasmine-marbles'; + +import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; +import { DatasetGroup, Instance } from 'src/app/metamodel/models'; +import { EditDatasetGroupTitleResolver } from './edit-dataset-group-title.resolver'; +import * as datasetGroupSelector from 'src/app/metamodel/selectors/dataset-group.selector'; + +describe('[admin][instance][dataset-group] DatasetGroupTitleResolver', () => { + let editDatasetGroupTitleResolver: EditDatasetGroupTitleResolver; + let store: MockStore; + let mockDatasetGroupSelectorGroupListIsLoaded; + let mockInstanceSelectorInstanceByRouteName; + let mockDatasetGroupSelectorDatasetGroupByRouteId; + let instance: Instance; + let datasetGroup: DatasetGroup; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [], + providers: [ + EditDatasetGroupTitleResolver, + provideMockStore({}), + ] + }) + instance = { ...instance, label: 'instance_test_label' } + + store = TestBed.inject(MockStore); + datasetGroup = { datasets: [], id: 1, instance_name: 'test', role: 'test' }; + + editDatasetGroupTitleResolver = TestBed.inject(EditDatasetGroupTitleResolver); + mockDatasetGroupSelectorDatasetGroupByRouteId = store.overrideSelector(datasetGroupSelector.selectDatasetGroupByRouteId, datasetGroup); + mockDatasetGroupSelectorGroupListIsLoaded = store.overrideSelector(datasetGroupSelector.selectDatasetGroupListIsLoaded, false); + mockInstanceSelectorInstanceByRouteName = store.overrideSelector(instanceSelector.selectInstanceByRouteName, instance); + }); + + it('should be created', () => { + expect(editDatasetGroupTitleResolver).toBeTruthy(); + }); + + it('shoud dispatch datasetGroupActions.loadDatasetGroupList() action and return datasetGroupListIsLoaded', () => { + const expected = cold('a', { a: [] }); + let spy = jest.spyOn(store, 'dispatch'); + let result = hot('a', { a: editDatasetGroupTitleResolver.resolve(null, null) }); + + expect(result).toBeObservable(expected); + expect(spy).toHaveBeenCalledTimes(1); + }); + + it('should return test - Edit dataset-group test', () => { + mockDatasetGroupSelectorGroupListIsLoaded = store.overrideSelector(datasetGroupSelector.selectDatasetGroupListIsLoaded, true); + let result = editDatasetGroupTitleResolver.resolve(null, null); + const expected = cold('a', { a: instance.label + " - Edit dataset-group " + datasetGroup.role }); + expect(result).toBeObservable(expected); + }); +}); diff --git a/client/src/app/admin/instance/dataset/components/add-attribute.component.ts b/client/src/app/admin/instance/dataset/components/add-attribute.component.ts index c1f4241c0dd4a8f7130aa5dd27166ab2fa35a3a2..833092753a92184d7f7ac8886448f1010cabc238 100644 --- a/client/src/app/admin/instance/dataset/components/add-attribute.component.ts +++ b/client/src/app/admin/instance/dataset/components/add-attribute.component.ts @@ -70,6 +70,8 @@ export class AddAttributeComponent { order_by: true, archive: false, detail_display: id * 10, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/admin/instance/dataset/components/attribute/criteria/option-form.component.ts b/client/src/app/admin/instance/dataset/components/attribute/criteria/option-form.component.ts index f35a1803d6e48ba813ea83a30aae77b259e6de4b..ad45bb972b25cebe532052fdc934a2a5699d0610 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/criteria/option-form.component.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/criteria/option-form.component.ts @@ -8,6 +8,7 @@ */ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; + import { UntypedFormGroup } from '@angular/forms'; @Component({ diff --git a/client/src/app/admin/instance/dataset/components/attribute/criteria/tr-criteria.component.ts b/client/src/app/admin/instance/dataset/components/attribute/criteria/tr-criteria.component.ts index 3127807b6497a225d93d91f73190505088a5c3c2..6af3661858c28e1a772ceddf45d373e475cb85c1 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/criteria/tr-criteria.component.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/criteria/tr-criteria.component.ts @@ -30,9 +30,8 @@ export class TrCriteriaComponent implements OnInit { @Output() loadAttributeDistinctList: EventEmitter<{}> = new EventEmitter(); searchTypeList = searchTypeList; - - optionsFormArray = new UntypedFormArray([]); operatorList = searchTypeOperators; + optionsFormArray = new UntypedFormArray([]); public form = new UntypedFormGroup({ name: new UntypedFormControl({ value: '', disabled: true }), diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/index.ts b/client/src/app/admin/instance/dataset/components/attribute/detail/index.ts index d1581ea5b138546e26d7eba21a7cd6d624ce1612..4db9273e1ec22368184b553c46b2f8f4a5433a02 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/detail/index.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/index.ts @@ -9,8 +9,10 @@ import { TableDetailComponent } from './table-detail.component'; import { TrDetailComponent } from './tr-detail.component'; +import { detailRenderers } from './renderers'; export const detailComponents = [ TableDetailComponent, - TrDetailComponent + TrDetailComponent, + detailRenderers ]; diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/detail-renderer-form-factory.ts b/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/detail-renderer-form-factory.ts new file mode 100644 index 0000000000000000000000000000000000000000..cc525170b3d37e70cf5d723962fd23e3aba0ab48 --- /dev/null +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/detail-renderer-form-factory.ts @@ -0,0 +1,23 @@ +/** + * 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 { SharedRendererFormFactory } from '../../shared-renderers'; + +export abstract class DetailRendererFormFactory { + static create(renderer: string) { + const sharedRendererForm = SharedRendererFormFactory.create(renderer); + + let detailRendererForm = null; + switch (renderer) { + + } + + return (detailRendererForm) ? detailRendererForm : sharedRendererForm; + } +} diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/index.ts b/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..142c4beb9c65621cab477956bc8448c196eacd5a --- /dev/null +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/renderers/index.ts @@ -0,0 +1,20 @@ +/** + * 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 { sharedRendererList } from '../../shared-renderers'; + +export const detailRenderers = [ + +]; + +export * from './detail-renderer-form-factory'; + +export const detailRendererList = [ + ...sharedRendererList +]; diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/table-detail.component.html b/client/src/app/admin/instance/dataset/components/attribute/detail/table-detail.component.html index 64784d8fd030fff24798a7e7f775decaf7c87231..356a1c56ecc2e22c05891293fd2c6aab282e2ae8 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/detail/table-detail.component.html +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/table-detail.component.html @@ -5,6 +5,8 @@ <th scope="col" style="min-width:150px">Name</th> <th scope="col" style="min-width:150px">Output family / category</th> <th scope="col" style="min-width:100px;width:100px;">Display</th> + <th scope="col" style="min-width:150px">Renderer</th> + <th scope="col" style="min-width:200px">Renderer config</th> <th scope="col" style="width:50px">Save</th> </tr> </thead> diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.html b/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.html index 60b2752e0eeae20048b48b99af9d11a9675844b3..955e39d7dd68d8178e5f9f0ee2879231f89fb5d1 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.html +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.html @@ -13,6 +13,20 @@ <td> <input *ngIf="form.controls.id_detail_output_category.value" type="number" class="form-control" name="detail_display" formControlName="detail_display"> </td> + <td> + <select *ngIf="form.controls.id_detail_output_category.value" class="form-control" name="detail_renderer" (change)="detailRendererOnChange()" formControlName="detail_renderer"> + <option></option> + <option *ngFor="let renderer of detailRendererList" [ngValue]="renderer.value">{{ renderer.label }} + </option> + </select> + </td> + <td> + <ng-container *ngIf="form.controls.detail_renderer.value" [ngSwitch]="form.controls.detail_renderer.value"> + <app-link-renderer *ngSwitchCase="'link'" [id]="attribute.id" [form]="getDetailRendererConfigForm()"></app-link-renderer> + <app-download-renderer *ngSwitchCase="'download'" [id]="attribute.id" [form]="getDetailRendererConfigForm()"></app-download-renderer> + <app-image-renderer *ngSwitchCase="'image'" [id]="attribute.id" [form]="getDetailRendererConfigForm()"></app-image-renderer> + </ng-container> + </td> <td class="text-center align-middle"> <button (click)="submit()" [disabled]="form.invalid || form.pristine" class="btn btn-outline-primary"> <span class="fas fa-save"></span> diff --git a/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.ts b/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.ts index 8495e39267704a7fe66e3070a52f3a082b1835eb..8bf45ffeca998b3cfb08f0308742dfb6f61fab5e 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/detail/tr-detail.component.ts @@ -11,6 +11,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, OnInit import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; +import { DetailRendererFormFactory, detailRendererList } from './renderers'; @Component({ selector: '[detail]', @@ -24,18 +25,38 @@ export class TrDetailComponent implements OnInit { @Input() outputFamilyList: OutputFamily[]; @Output() save: EventEmitter<Attribute> = new EventEmitter(); + detailRendererList = detailRendererList; + public form = new UntypedFormGroup({ name: new UntypedFormControl({ value: '', disabled: true }), id_detail_output_category: new UntypedFormControl(), - detail_display: new UntypedFormControl() + detail_display: new UntypedFormControl(), + detail_renderer: new UntypedFormControl(null) }); ngOnInit() { if (this.attribute) { + const detailRendererConfigForm = DetailRendererFormFactory.create(this.attribute.detail_renderer); + this.form.addControl('detail_renderer_config', new UntypedFormGroup(detailRendererConfigForm)); this.form.patchValue(this.attribute); } } + getDetailRendererConfigForm() { + return this.form.controls['detail_renderer_config'] as UntypedFormGroup; + } + + detailRendererOnChange() { + if (this.form.controls.detail_renderer.value === '') { + this.form.controls.detail_renderer.setValue(null); + this.form.setControl('detail_renderer_config', new UntypedFormGroup({})); + } else { + this.form.setControl('detail_renderer_config', new UntypedFormGroup( + DetailRendererFormFactory.create(this.form.controls.detail_renderer.value) + )); + } + } + detailOutputCategoryOnChange(): void { if (this.form.controls.id_detail_output_category.value === '') { this.form.controls.id_detail_output_category.setValue(null); diff --git a/client/src/app/admin/instance/dataset/components/attribute/index.ts b/client/src/app/admin/instance/dataset/components/attribute/index.ts index 92a8597ae2e17287848ba705eac7dbf72377aeb9..e6eee592357993b86f17de9fb3c3213df4faaf2f 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/index.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/index.ts @@ -13,6 +13,7 @@ import { outputComponents } from './output'; import { resultComponents } from './result'; import { detailComponents } from './detail'; import { voComponents } from './vo'; +import { sharedRenderers } from './shared-renderers'; export const attributeComponents = [ generalComponents, @@ -20,5 +21,6 @@ export const attributeComponents = [ outputComponents, resultComponents, detailComponents, - voComponents + voComponents, + sharedRenderers ]; diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/index.ts b/client/src/app/admin/instance/dataset/components/attribute/result/renderers/index.ts index 4e147f8613cb1083440e171f1a9b3abe1719cd8a..ead160cabbfb162eaf6be271a42d8d33d8de2d78 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/index.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/result/renderers/index.ts @@ -8,23 +8,15 @@ */ import { DetailLinkRendererComponent } from './detail-link-renderer.component'; -import { DownloadRendererComponent } from './download-renderer.component'; -import { ImageRendererComponent } from './image-renderer.component'; -import { LinkRendererComponent } from './link-renderer.component'; +import { sharedRendererList } from '../../shared-renderers'; export const renderers = [ - DetailLinkRendererComponent, - DownloadRendererComponent, - ImageRendererComponent, - LinkRendererComponent + DetailLinkRendererComponent ]; export * from './renderer-form-factory'; export const rendererList = [ - { label: 'Link detail page', value: 'detail-link', display: 10 }, - { label: 'Download file', value: 'download', display: 20 }, - { label: 'Link (file, web page...)', value: 'link', display: 30 }, - { label: 'Display image (png, jpg...)', value: 'image', display: 40 }, - { label: 'Display json', value: 'json', display: 50 } + ...sharedRendererList, + { label: 'Link detail page', value: 'detail-link', display: 10 } ]; diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/renderer-form-factory.ts b/client/src/app/admin/instance/dataset/components/attribute/result/renderers/renderer-form-factory.ts index bcaeeb71c116add07d1721053780c98164d25383..f31123afce1b99b2b96683bd1ad47faaacf3c6f6 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/renderer-form-factory.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/result/renderers/renderer-form-factory.ts @@ -7,38 +7,23 @@ * file that was distributed with this source code. */ -import { UntypedFormControl } from "@angular/forms"; +import { UntypedFormControl } from '@angular/forms'; + +import { SharedRendererFormFactory } from '../../shared-renderers'; export abstract class RendererFormFactory { static create(renderer: string) { + const sharedRendererForm = SharedRendererFormFactory.create(renderer); + + let rendererForm = null; switch (renderer) { case 'detail-link': - return { + rendererForm = { display: new UntypedFormControl('text') }; - case 'link': - return { - href: new UntypedFormControl('$value'), - display: new UntypedFormControl('text'), - text: new UntypedFormControl('$value'), - icon: new UntypedFormControl('fas fa-link'), - blank: new UntypedFormControl(true) - }; - case 'download': - return { - display: new UntypedFormControl('icon-button'), - text: new UntypedFormControl('DOWNLOAD'), - icon: new UntypedFormControl('fas fa-download') - }; - case 'image': - return { - type: new UntypedFormControl('fits'), - display: new UntypedFormControl('modal'), - width: new UntypedFormControl(''), - height: new UntypedFormControl('') - }; - default: - return {}; + break; } + + return (rendererForm) ? rendererForm : sharedRendererForm; } } diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/tr-result.component.ts b/client/src/app/admin/instance/dataset/components/attribute/result/tr-result.component.ts index 2b9f4d4c3ebd58ef19ce595a51b1878346a4596a..fdb5abafe60c8e8380328860941ce4b304b4c963 100644 --- a/client/src/app/admin/instance/dataset/components/attribute/result/tr-result.component.ts +++ b/client/src/app/admin/instance/dataset/components/attribute/result/tr-result.component.ts @@ -13,7 +13,6 @@ import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { Attribute } from 'src/app/metamodel/models'; import { RendererFormFactory, rendererList } from './renderers'; - @Component({ selector: '[result]', templateUrl: 'tr-result.component.html', diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/download-renderer.component.html b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/download-renderer.component.html similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/download-renderer.component.html rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/download-renderer.component.html diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/download-renderer.component.ts b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/download-renderer.component.ts similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/download-renderer.component.ts rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/download-renderer.component.ts diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/image-renderer.component.html b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/image-renderer.component.html similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/image-renderer.component.html rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/image-renderer.component.html diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/image-renderer.component.ts b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/image-renderer.component.ts similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/image-renderer.component.ts rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/image-renderer.component.ts diff --git a/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/index.ts b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..98826d5ef7c99d43f499533c3bab47671c8c76b0 --- /dev/null +++ b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/index.ts @@ -0,0 +1,18 @@ +import { DownloadRendererComponent } from './download-renderer.component'; +import { ImageRendererComponent } from './image-renderer.component'; +import { LinkRendererComponent } from './link-renderer.component'; + +export const sharedRenderers = [ + DownloadRendererComponent, + ImageRendererComponent, + LinkRendererComponent +]; + +export * from './shared-renderer-form-factory'; + +export const sharedRendererList = [ + { label: 'Download file', value: 'download', display: 20 }, + { label: 'Link (file, web page...)', value: 'link', display: 30 }, + { label: 'Display image (png, jpg...)', value: 'image', display: 40 }, + { label: 'Display json', value: 'json', display: 50 } +]; diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/link-renderer.component.html b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/link-renderer.component.html similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/link-renderer.component.html rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/link-renderer.component.html diff --git a/client/src/app/admin/instance/dataset/components/attribute/result/renderers/link-renderer.component.ts b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/link-renderer.component.ts similarity index 100% rename from client/src/app/admin/instance/dataset/components/attribute/result/renderers/link-renderer.component.ts rename to client/src/app/admin/instance/dataset/components/attribute/shared-renderers/link-renderer.component.ts diff --git a/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/shared-renderer-form-factory.ts b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/shared-renderer-form-factory.ts new file mode 100644 index 0000000000000000000000000000000000000000..a87d1b9dc94f9b84f3e44bcad136319312d012bf --- /dev/null +++ b/client/src/app/admin/instance/dataset/components/attribute/shared-renderers/shared-renderer-form-factory.ts @@ -0,0 +1,40 @@ +/** + * 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 { UntypedFormControl } from "@angular/forms"; + +export abstract class SharedRendererFormFactory { + static create(renderer: string) { + switch (renderer) { + case 'link': + return { + href: new UntypedFormControl('$value'), + display: new UntypedFormControl('text'), + text: new UntypedFormControl('$value'), + icon: new UntypedFormControl('fas fa-link'), + blank: new UntypedFormControl(true) + }; + case 'download': + return { + display: new UntypedFormControl('icon-button'), + text: new UntypedFormControl('DOWNLOAD'), + icon: new UntypedFormControl('fas fa-download') + }; + case 'image': + return { + type: new UntypedFormControl('fits'), + display: new UntypedFormControl('modal'), + width: new UntypedFormControl(''), + height: new UntypedFormControl('') + }; + default: + return {}; + } + } +} diff --git a/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.html b/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.html index ca1a671ed43e3e3b7f1edbcc97fa36d7db6cc377..f75a949f8a9bcb0e0e5f06cff9ffde57c56d8b33 100644 --- a/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.html +++ b/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.html @@ -23,6 +23,34 @@ </div> </div> </div> + <div class="custom-control custom-switch"> + <input class="custom-control-input" type="checkbox" id="resolver_enabled" name="resolver_enabled" formControlName="resolver_enabled"> + <label class="custom-control-label" for="resolver_enabled">Resolver enabled</label> + </div> + <div class="form-group"> + <div class="form-row"> + <div class="col-md-6"> + <label for="default_ra">Default RA</label> + <input type="number" class="form-control" id="default_ra" name="default_ra" formControlName="default_ra"> + </div> + <div class="col-md-6"> + <label for="default_dec">Default DEC</label> + <input type="number" class="form-control" id="default_dec" name="default_dec" formControlName="default_dec"> + </div> + </div> + </div> + <div class="form-group"> + <label for="default_radius">Default radius</label> + <input type="number" class="form-control" id="default_radius" name="default_radius" formControlName="default_radius"> + </div> + <div class="form-group"> + <label for="default_ra_dec_unit">Default Ra & Dec unit</label> + <select class="form-control" id="default_ra_dec_unit" name="default_ra_dec_unit" formControlName="default_ra_dec_unit"> + <option></option> + <option value="degree">Degree</option> + <option value="hms">HMS</option> + </select> + </div> <div class="custom-control custom-switch"> <input class="custom-control-input" type="checkbox" id="plot_enabled" name="plot_enabled" formControlName="plot_enabled"> <label class="custom-control-label" for="plot_enabled">Plot enabled</label> diff --git a/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.ts b/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.ts index 3a2ff5a3059c44ff9ae31390001d6a86a7176233..d42ca6195606536b3eab8629c1809ce4b612a08a 100644 --- a/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.ts +++ b/client/src/app/admin/instance/dataset/components/cone-search-config/cone-search-config-form.component.ts @@ -27,7 +27,12 @@ export class ConeSearchConfigFormComponent implements OnInit { opened: new UntypedFormControl({value: false, disabled: true}), column_ra: new UntypedFormControl({value: false, disabled: true}), column_dec: new UntypedFormControl({value: false, disabled: true}), - plot_enabled: new UntypedFormControl(false), + resolver_enabled: new UntypedFormControl({value: false, disabled: true}), + default_ra: new UntypedFormControl({value: null, disabled: true}), + default_dec: new UntypedFormControl({value: null, disabled: true}), + default_radius: new UntypedFormControl({value: 2.0, disabled: true}), + default_ra_dec_unit: new UntypedFormControl({value: 'degree', disabled: true}), + plot_enabled: new UntypedFormControl({value: false, disabled: true}) }); ngOnInit() { @@ -40,12 +45,22 @@ export class ConeSearchConfigFormComponent implements OnInit { this.form.controls.opened.enable(); this.form.controls.column_ra.enable(); this.form.controls.column_dec.enable(); + this.form.controls.resolver_enabled.enable(); + this.form.controls.default_ra.enable(); + this.form.controls.default_dec.enable(); + this.form.controls.default_radius.enable(); + this.form.controls.default_ra_dec_unit.enable(); this.form.controls.plot_enabled.enable(); } else { this.form.controls.opened.setValue(false); this.form.controls.opened.disable(); this.form.controls.column_ra.disable(); this.form.controls.column_dec.disable(); + this.form.controls.resolver_enabled.disable(); + this.form.controls.default_ra.disable(); + this.form.controls.default_dec.disable(); + this.form.controls.default_radius.disable(); + this.form.controls.default_ra_dec_unit.disable(); this.form.controls.plot_enabled.disable(); } } diff --git a/client/src/app/admin/instance/dataset/components/output-category/output-category-list.component.html b/client/src/app/admin/instance/dataset/components/output-category/output-category-list.component.html index 7f8fde329325f0c4a4309c105b617a3618123622..4d52dff6bcfc39455620a9f0843431f6c6fc160c 100644 --- a/client/src/app/admin/instance/dataset/components/output-category/output-category-list.component.html +++ b/client/src/app/admin/instance/dataset/components/output-category/output-category-list.component.html @@ -7,6 +7,7 @@ <table class="table table-striped" aria-describedby="Output category list"> <thead> <tr> + <th scope="col">Id</th> <th scope="col">Label</th> <th scope="col">Display</th> <th scope="col">Output family</th> @@ -15,6 +16,7 @@ </thead> <tbody> <tr *ngFor="let outputCategory of outputCategoryList"> + <td class="align-middle">{{ outputCategory.id }}</td> <td class="align-middle">{{ outputCategory.label }}</td> <td class="align-middle">{{ outputCategory.display }}</td> <td class="align-middle">{{ (outputFamilyList | outputFamilyById:outputCategory.id_output_family).label }}</td> diff --git a/client/src/app/admin/instance/dataset/components/output-family/output-family-list.component.html b/client/src/app/admin/instance/dataset/components/output-family/output-family-list.component.html index 47a0dd0277e618c0ebfd013270ceb28ee321aead..2443323c36e907d23576d09dadb503025ff0beb2 100644 --- a/client/src/app/admin/instance/dataset/components/output-family/output-family-list.component.html +++ b/client/src/app/admin/instance/dataset/components/output-family/output-family-list.component.html @@ -4,6 +4,7 @@ <table class="table table-striped" aria-describedby="Output family list"> <thead> <tr> + <th scope="col">Id</th> <th scope="col">Label</th> <th scope="col">Display</th> <th scope="col">Actions</th> @@ -11,6 +12,7 @@ </thead> <tbody> <tr *ngFor="let outputFamily of outputFamilyList"> + <td class="align-middle">{{ outputFamily.id }}</td> <td class="align-middle">{{ outputFamily.label }}</td> <td class="align-middle">{{ outputFamily.display }}</td> <td class="align-middle"> diff --git a/client/src/app/core/containers/app.component.html b/client/src/app/core/containers/app.component.html index 3cd4c5e07197c521203f6f6075784371d82cf6b3..20c3962160f9c12aa7d642ea6c742471b87b8660 100644 --- a/client/src/app/core/containers/app.component.html +++ b/client/src/app/core/containers/app.component.html @@ -3,43 +3,3 @@ <span class="sr-only">Loading...</span> </div> <router-outlet *ngIf="(instanceListIsLoaded | async) && (instanceGroupListIsLoaded | async)"></router-outlet> -<footer class="footer mt-auto"> - <div class="container my-3"> - <div class="row justify-content-center font-weight-bold mb-1"> - © ANIS 2014 - {{ year }} - </div> - <div class="row justify-content-center font-weight-bold mb-4"> - Currently based on ANIS v{{ anisClientVersion }}. - </div> - <div class="row justify-content-center font-weight-bold mb-4"> - Code licensed CeCILL. - </div> - <div class="row justify-content-around"> - <div class="col mb-3 text-center"> - <a href="http://cesam.lam.fr" title="Centre de données Astrophysique de Marseille"> - <img class="img-fluid" src="assets/logo_cesam_s.png" alt="CeSAM" /> - </a> - </div> - <div class="col text-center"> - <a href="http://lam.fr" title="Laboratoire d'Astrophysique de Marseille"> - <img class="img-fluid" src="assets/logo_lam_s.png" alt="LAM" /> - </a> - </div> - <div class="col text-center"> - <a href="http://www.univ-amu.fr" title="Aix*Marseille Université"> - <img class="img-fluid" src="assets/logo_amu_s.png" alt="AMU" /> - </a> - </div> - <div class="col text-center"> - <a href="http://www.insu.cnrs.fr" title="Institut National des Sciences de l'Univers"> - <img class="img-fluid" src="assets/logo_insu_s.png" alt="INSU" /> - </a> - </div> - <div class="col text-center"> - <a href="http://anis.lam.fr" title="AstroNomical Information System"> - <img class="img-fluid" src="assets/cesam_anis40.png" alt="ANIS" /> - </a> - </div> - </div> - </div> -</footer> diff --git a/client/src/app/core/containers/app.component.ts b/client/src/app/core/containers/app.component.ts index bdeae085da022d8650343978b8832335358c2aa9..d7eb360fecb7c501b0f51195033987dd92f11057 100644 --- a/client/src/app/core/containers/app.component.ts +++ b/client/src/app/core/containers/app.component.ts @@ -28,8 +28,6 @@ import { AppConfigService } from 'src/app/app-config.service'; templateUrl: './app.component.html' }) export class AppComponent implements OnInit { - public anisClientVersion: string = '3.7.0'; - public year: number = (new Date()).getFullYear(); public instanceListIsLoading: Observable<boolean>; public instanceListIsLoaded: Observable<boolean>; public instanceGroupListIsLoading: Observable<boolean>; diff --git a/client/src/app/instance/components/index.ts b/client/src/app/instance/components/index.ts index 74d75b58fafa3e513a25c4bc99b1a732210378b8..838f0f1507340ef8ffd1ec1c9245edddcdc02b85 100644 --- a/client/src/app/instance/components/index.ts +++ b/client/src/app/instance/components/index.ts @@ -8,11 +8,13 @@ */ import { InstanceNavbarComponent } from './instance-navbar.component'; +import { InstanceFooterComponent } from './instance-footer.component'; import { WebpageFamilyNavComponent } from './webpage-family-nav.component'; import { WebpageFamilyNavMobileComponent } from './webpage-family-nav-mobile.component'; export const dummiesComponents = [ InstanceNavbarComponent, + InstanceFooterComponent, WebpageFamilyNavComponent, WebpageFamilyNavMobileComponent ]; diff --git a/client/src/app/instance/components/instance-footer.component.html b/client/src/app/instance/components/instance-footer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4bf4243154b32f2153f93201f5f6fb145335a386 --- /dev/null +++ b/client/src/app/instance/components/instance-footer.component.html @@ -0,0 +1,21 @@ +<footer> + <div class="container my-3"> + <div class="row justify-content-center font-weight-bold mb-1"> + © ANIS 2014 - {{ year }} + </div> + <div class="row justify-content-center font-weight-bold mb-4"> + Currently based on ANIS v{{ anisClientVersion }}. + </div> + <div class="row justify-content-center font-weight-bold mb-4"> + Code licensed CeCILL. + </div> + <div class="row justify-content-around"> + <div *ngFor="let logo of instance.footer_logos" class="col mb-3 text-center"> + <a [href]="logo.href" [title]="logo.title"> + <img *ngIf="instance.public" class="img-fluid" [src]="getLogoHref(logo)" alt="Not found" /> + <img *ngIf="!instance.public" class="img-fluid" [src]="getLogoHref(logo) | authImage | async" alt="Not found" /> + </a> + </div> + </div> + </div> +</footer> \ No newline at end of file diff --git a/client/src/app/instance/components/instance-footer.component.ts b/client/src/app/instance/components/instance-footer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..5d6b156ef8ecb43567563ab4d877973597a43573 --- /dev/null +++ b/client/src/app/instance/components/instance-footer.component.ts @@ -0,0 +1,25 @@ +import { Component, ChangeDetectionStrategy, Input } from '@angular/core'; + +import { Instance, Logo } from 'src/app/metamodel/models'; + +@Component({ + selector: 'app-instance-footer', + templateUrl: 'instance-footer.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class InstanceFooterComponent { + @Input() instance: Instance; + @Input() apiUrl: string; + + public anisClientVersion: string = '3.7.0'; + public year: number = (new Date()).getFullYear(); + + /** + * Returns logo href. + * + * @return string + */ + getLogoHref(logo: Logo): string { + return `${this.apiUrl}/instance/${this.instance.name}/file-explorer${logo.file}`; + } +} diff --git a/client/src/app/instance/components/instance-navbar.component.html b/client/src/app/instance/components/instance-navbar.component.html index 83867b70be23460d49cfc1b8e5f59f4e131effd2..41d9a79b21f5a92f330decac96093e0dd0f511ac 100644 --- a/client/src/app/instance/components/instance-navbar.component.html +++ b/client/src/app/instance/components/instance-navbar.component.html @@ -1,8 +1,12 @@ <nav class="navbar-instance navbar navbar-expand-md fixed-top"> <!-- Logo --> - <a [routerLink]="getInstanceBaseHref()" class="navbar-brand"> - <img *ngIf="instance.public" [src]="getLogoHref()" alt="Instance logo" /> - <img *ngIf="!instance.public" [src]="getLogoHref() | authImage | async" alt="Instance logo" /> + <a *ngIf="!instance.design_logo_href" [routerLink]="getLogoHref()" class="navbar-brand"> + <img *ngIf="instance.public" [src]="getLogoURL()" alt="Instance logo" /> + <img *ngIf="!instance.public" [src]="getLogoURL() | authImage | async" alt="Instance logo" /> + </a> + <a *ngIf="instance.design_logo_href" [href]="getLogoHref()" class="navbar-brand"> + <img *ngIf="instance.public" [src]="getLogoURL()" alt="Instance logo" /> + <img *ngIf="!instance.public" [src]="getLogoURL() | authImage | async" alt="Instance logo" /> </a> <!-- Navigation --> @@ -51,8 +55,8 @@ Sign In / Register </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" [ngStyle]="{ color: instance.design_color }"> + <button id="button-user" dropdownToggle type="button" class="btn btn-light" aria-controls="dropdown-basic"> + <span class="fa-stack"> <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/instance/components/instance-navbar.component.ts b/client/src/app/instance/components/instance-navbar.component.ts index 06696f9f0926fd74394e3a27446ce389ffd6225c..3b5b005c16c82fcb09f8fdc2e5a5a0d6138f29d7 100644 --- a/client/src/app/instance/components/instance-navbar.component.ts +++ b/client/src/app/instance/components/instance-navbar.component.ts @@ -44,17 +44,25 @@ export class InstanceNavbarComponent { } /** - * Returns logo href. + * Returns logo URL. * * @return string */ - getLogoHref(): string { + getLogoURL(): string { if (this.instance.design_logo) { return `${this.apiUrl}/instance/${this.instance.name}/file-explorer${this.instance.design_logo}`; } return 'assets/cesam_anis40.png'; } + getLogoHref(): string { + if (this.instance.design_logo_href) { + return this.instance.design_logo_href; + } else { + return this.getInstanceBaseHref(); + } + } + getInstanceBaseHref() { if (this.firstWebpage) { return `/instance/${this.instance.name}/webpage/${this.firstWebpage.name}`; diff --git a/client/src/app/instance/search/components/cone-search-parameters.component.html b/client/src/app/instance/cone-search/components/cone-search-parameters.component.html similarity index 63% rename from client/src/app/instance/search/components/cone-search-parameters.component.html rename to client/src/app/instance/cone-search/components/cone-search-parameters.component.html index 9e6531b91c3d791a31453ca9c0638d9e52fc14b8..b20a3359a381b886d1c67795edcc67e844690ff1 100644 --- a/client/src/app/instance/search/components/cone-search-parameters.component.html +++ b/client/src/app/instance/cone-search/components/cone-search-parameters.component.html @@ -1,4 +1,4 @@ -<div class="search_criterium" [ngStyle]="{'background-color': backgroundColor }"> +<div class="search_criterium"> <strong>Cone search</strong>: ra = {{coneSearch.ra}} deg, dec = {{coneSearch.dec}} deg, radius = {{ coneSearch.radius}} arcsec. </div> diff --git a/client/src/app/instance/cone-search/components/cone-search-parameters.component.scss b/client/src/app/instance/cone-search/components/cone-search-parameters.component.scss new file mode 100644 index 0000000000000000000000000000000000000000..fe64ac25e2c2f05e575cb839869354fa271b7981 --- /dev/null +++ b/client/src/app/instance/cone-search/components/cone-search-parameters.component.scss @@ -0,0 +1,8 @@ +.search_criterium { + float: left; + border-radius: 5px; + padding: .1em .5em; + margin: .2em; + font-weight: bold; + font-size: 16px; +} diff --git a/client/src/app/instance/search/components/cone-search-parameters.component.ts b/client/src/app/instance/cone-search/components/cone-search-parameters.component.ts similarity index 85% rename from client/src/app/instance/search/components/cone-search-parameters.component.ts rename to client/src/app/instance/cone-search/components/cone-search-parameters.component.ts index 8da0e7a1a4323a57732423dad8a496cc302c8894..305f8fe39d2a5af382c3ab29c7a4521a1778227b 100644 --- a/client/src/app/instance/search/components/cone-search-parameters.component.ts +++ b/client/src/app/instance/cone-search/components/cone-search-parameters.component.ts @@ -13,9 +13,8 @@ import { ConeSearch } from "src/app/instance/store/models"; @Component({ selector: 'app-cone-search-parameters', templateUrl: 'cone-search-parameters.component.html', - styleUrls: ['criteria-list-parameters.component.scss'] + styleUrls: ['cone-search-parameters.component.scss'] }) export class ConeSearchParametersComponent { @Input() coneSearch: ConeSearch; - @Input() backgroundColor: string; } diff --git a/client/src/app/instance/cone-search/components/cone-search.component.html b/client/src/app/instance/cone-search/components/cone-search.component.html index 6e676e971e10e1ebf73318e490770eb147abdae1..c2e0feb841ffc6b4c17bbb2ad65917466cf1c185 100644 --- a/client/src/app/instance/cone-search/components/cone-search.component.html +++ b/client/src/app/instance/cone-search/components/cone-search.component.html @@ -1,8 +1,7 @@ -<div class="row pb-4"> +<div class="row pb-4" *ngIf="resolverEnabled"> <div class="col"> <app-resolver [coneSearch]="coneSearch" - [resolver]="resolver" [resolverIsLoading]="resolverIsLoading" [resolverIsLoaded]="resolverIsLoaded" (retrieveCoordinates)="retrieveCoordinates.emit($event)"> @@ -11,16 +10,16 @@ </div> <div class="row"> <div class="col pb-4"> - <app-ra [form]="form" [unit]="unit" [resolver]="resolver"> + <app-ra [form]="form" [unit]="unit" [coneSearch]="coneSearch"> </app-ra> </div> <div class="col-auto p-0 align-self-center"> - <button class="btn btn-outline-secondary" [disabled]="coneSearch" (click)="unit === 'degree' ? unit = 'hms' : unit = 'degree'" title="Change unit"> + <button class="btn btn-outline-secondary" (click)="unit === 'degree' ? unit = 'hms' : unit = 'degree'" title="Change unit"> <span class="fas fa-sync-alt"></span> </button> </div> <div class="col"> - <app-dec [form]="form" [unit]="unit" [resolver]="resolver"> + <app-dec [form]="form" [unit]="unit" [coneSearch]="coneSearch"> </app-dec> </div> <div class="col-12"> diff --git a/client/src/app/instance/cone-search/components/cone-search.component.spec.ts b/client/src/app/instance/cone-search/components/cone-search.component.spec.ts index d7a2d24a5d3bf1f4553fd1326125e1ba4f6bde5b..5a83f53ed02ea8277eac2497186c0fbe8e8e483d 100644 --- a/client/src/app/instance/cone-search/components/cone-search.component.spec.ts +++ b/client/src/app/instance/cone-search/components/cone-search.component.spec.ts @@ -12,24 +12,22 @@ import { Component, Input, ViewChild } from '@angular/core'; import { FormGroup, ReactiveFormsModule } from '@angular/forms'; import { ConeSearchComponent } from './cone-search.component'; -import { ConeSearch, Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; describe('[Instance][ConeSearch][Components] ConeSearchComponent', () => { @Component({ selector: `app-host`, template: ` <app-cone-search - [coneSearch]="coneSearch" - [resolver]="resolver" - [resolverIsLoading]="resolverIsLoading" - [resolverIsLoaded]="resolverIsLoaded"> + [coneSearch]="coneSearch" + [resolverIsLoading]="resolverIsLoading" + [resolverIsLoaded]="resolverIsLoaded"> </app-cone-search>` }) class TestHostComponent { @ViewChild(ConeSearchComponent, { static: false }) public testedComponent: ConeSearchComponent; public coneSearch: ConeSearch = undefined; - public resolver: Resolver = undefined; public resolverIsLoading: boolean = false; public resolverIsLoaded: boolean = false; } @@ -37,7 +35,6 @@ describe('[Instance][ConeSearch][Components] ConeSearchComponent', () => { @Component({ selector: 'app-resolver', template: '' }) class ResolverStubComponent { @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; } @@ -46,14 +43,12 @@ describe('[Instance][ConeSearch][Components] ConeSearchComponent', () => { class RaStubComponent { @Input() form: FormGroup; @Input() unit: string; - @Input() resolver: Resolver; } @Component({ selector: 'app-dec', template: '' }) class DecStubComponent { @Input() form: FormGroup; @Input() unit: string; - @Input() resolver: Resolver; } @Component({ selector: 'app-radius', template: '' }) @@ -89,9 +84,8 @@ describe('[Instance][ConeSearch][Components] ConeSearchComponent', () => { it('should call ngOnChanges and apply changes', () => { const spy = jest.spyOn(testedComponent, 'ngOnChanges'); - testHostComponent.resolver = { name: 'myObject', ra: 1, dec: 2 }; testHostFixture.detectChanges(); - expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledTimes(0); expect(testedComponent.unit).toEqual('degree'); expect(testedComponent.form.controls.ra.enabled).toBeTruthy(); expect(testedComponent.form.controls.dec.enabled).toBeTruthy(); @@ -99,16 +93,15 @@ describe('[Instance][ConeSearch][Components] ConeSearchComponent', () => { testHostComponent.coneSearch = { ra: 1, dec: 2, radius: 3 }; testHostFixture.detectChanges(); - expect(spy).toHaveBeenCalledTimes(2); - expect(testedComponent.form.controls.ra.value).toEqual(1); - expect(testedComponent.form.controls.dec.value).toEqual(2); + expect(spy).toHaveBeenCalledTimes(1); + expect(testedComponent.form.controls.ra.value).toEqual(null); + expect(testedComponent.form.controls.dec.value).toEqual(null); expect(testedComponent.form.controls.radius.value).toEqual(3); - expect(testedComponent.form.disabled).toBeTruthy(); testHostComponent.coneSearch = undefined; testedComponent.unit = 'hms'; testHostFixture.detectChanges(); - expect(spy).toHaveBeenCalledTimes(3); + expect(spy).toHaveBeenCalledTimes(2); expect(testedComponent.form.controls.ra_hms.enabled).toBeTruthy(); expect(testedComponent.form.controls.dec_dms.enabled).toBeTruthy(); }); diff --git a/client/src/app/instance/cone-search/components/cone-search.component.ts b/client/src/app/instance/cone-search/components/cone-search.component.ts index 227f1249c241a44a8791f6faabde9396f9b02add..4c5783e0608b7c1fd193c8f543af1856be0e400c 100644 --- a/client/src/app/instance/cone-search/components/cone-search.component.ts +++ b/client/src/app/instance/cone-search/components/cone-search.component.ts @@ -7,12 +7,12 @@ * file that was distributed with this source code. */ -import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core'; +import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, OnInit, OnDestroy } from '@angular/core'; import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms'; -import { Subscription } from 'rxjs'; +import { debounceTime, Subscription } from 'rxjs'; -import { ConeSearch, Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; import { nanValidator, rangeValidator } from '../validators'; /** @@ -27,44 +27,54 @@ import { nanValidator, rangeValidator } from '../validators'; }) export class ConeSearchComponent implements OnChanges, OnInit, OnDestroy { @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; + @Input() defaultRadius: number; + @Input() defaultRaDecUnit: string; + @Input() resolverEnabled: boolean; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter(); + @Output() emitAdd: EventEmitter<{}> = new EventEmitter<{}>(); private formValueChangesSubscription: Subscription; public form = new UntypedFormGroup({ - ra: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 360, 'RA')]), + ra: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 360, 'RA')]), ra_hms: new UntypedFormGroup({ - h: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 24, 'Hours')]), - m: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]), - s: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) + h: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 24, 'Hours')]), + m: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]), + s: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) }), - dec: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'DEC')]), + dec: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(-90, 90, 'DEC')]), dec_dms: new UntypedFormGroup({ - d: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(-90, 90, 'Degree')]), - m: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]), - s: new UntypedFormControl('', [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) + d: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(-90, 90, 'Degree')]), + m: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 60, 'Minutes')]), + s: new UntypedFormControl(null, [Validators.required, nanValidator, rangeValidator(0, 60, 'Seconds')]) }), radius: new UntypedFormControl(2, [Validators.required, rangeValidator(0, 150, 'Radius')]) }); public unit = 'degree'; - constructor(private cd: ChangeDetectorRef) {} - ngOnInit() { - this.formValueChangesSubscription = this.form.valueChanges.subscribe(() => { - this.cd.markForCheck(); + this.formValueChangesSubscription = this.form.valueChanges.pipe( + debounceTime(300), + ) + .subscribe(() => { + if (this.form.valid) { + this.emitAdd.emit(); + } }); - } - ngOnChanges(changes: SimpleChanges): void { - if (changes.resolver && changes.resolver.currentValue) { - this.unit = 'degree'; + if (!this.coneSearch && this.defaultRadius) { + this.form.controls.radius.setValue(this.defaultRadius); } + if (this.defaultRaDecUnit) { + this.unit = this.defaultRaDecUnit; + } + } + + ngOnChanges(changes: SimpleChanges): void { if (changes.coneSearch && !changes.coneSearch.currentValue) { if (this.unit == 'degree') { this.form.controls.ra.enable(); @@ -74,11 +84,13 @@ export class ConeSearchComponent implements OnChanges, OnInit, OnDestroy { this.form.controls.ra_hms.enable(); this.form.controls.dec_dms.enable(); } + this.form.reset(); + this.form.controls.radius.setValue(2); } if (changes.coneSearch && changes.coneSearch.currentValue) { - this.form.patchValue(this.coneSearch); - this.form.disable(); + const radius = changes.coneSearch.currentValue.radius; + this.form.controls.radius.setValue(radius); } } diff --git a/client/src/app/instance/cone-search/components/dec.component.spec.ts b/client/src/app/instance/cone-search/components/dec.component.spec.ts index ddc5a64bb830c6fe022afcdeb2834fe545ecabe1..895af94e9ca8a2e32352412a57e2b38660819ded 100644 --- a/client/src/app/instance/cone-search/components/dec.component.spec.ts +++ b/client/src/app/instance/cone-search/components/dec.component.spec.ts @@ -14,7 +14,6 @@ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angula import { of } from 'rxjs'; import { DecComponent } from './dec.component'; -import { Resolver } from 'src/app/instance/store/models'; import { nanValidator, rangeValidator } from '../validators'; describe('[Instance][ConeSearch][Components] DecComponent', () => { @@ -41,7 +40,6 @@ describe('[Instance][ConeSearch][Components] DecComponent', () => { public testedComponent: DecComponent; public form: FormGroup = form; public unit: string = 'degree'; - public resolver: Resolver = undefined; } let testHostComponent: TestHostComponent; @@ -92,10 +90,9 @@ describe('[Instance][ConeSearch][Components] DecComponent', () => { expect(spy).toHaveBeenCalledTimes(2); expect(testedComponent.form.controls.dec_dms.disabled).toBeTruthy(); expect(testedComponent.form.controls.dec.enabled).toBeTruthy(); - testHostComponent.resolver = { ra: 1, dec: 2, name: 'myObject' }; testHostFixture.detectChanges(); - expect(spy).toHaveBeenCalledTimes(3); - expect(testedComponent.form.controls.dec.value).toEqual(2); + expect(spy).toHaveBeenCalledTimes(2); + expect(testedComponent.form.controls.dec.value).toEqual(32.87); }); it('#getDecDmsForm() should return DEC DMS form control', () => { diff --git a/client/src/app/instance/cone-search/components/dec.component.ts b/client/src/app/instance/cone-search/components/dec.component.ts index a9d1dc0872979302fd9d366cec5b127308163f1b..c6f3a72aab7a69a9aa9f01f5cffd7b9be48cfea0 100644 --- a/client/src/app/instance/cone-search/components/dec.component.ts +++ b/client/src/app/instance/cone-search/components/dec.component.ts @@ -13,7 +13,7 @@ import { UntypedFormGroup } from '@angular/forms'; import { Subscription } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; -import { Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; /** * @class @@ -32,13 +32,18 @@ import { Resolver } from 'src/app/instance/store/models'; export class DecComponent implements OnInit, OnDestroy, OnChanges { @Input() form: UntypedFormGroup; @Input() unit: string; - @Input() resolver: Resolver; + @Input() coneSearch: ConeSearch; public decControlSubscription: Subscription public decDmsSubscription: Subscription; ngOnInit(): void { - this.form.controls.dec_dms.disable(); + if (this.unit === 'degree') { + this.form.controls.dec_dms.disable(); + } else { + this.form.controls.dec.disable(); + } + this.decControlSubscription = this.form.controls.dec.valueChanges.pipe(debounceTime(250)) .subscribe(deg => this.deg2DMS(deg)); } @@ -61,8 +66,10 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { } } - if (changes.resolver && changes.resolver.currentValue) { - this.form.controls.dec.setValue(changes.resolver.currentValue.dec); + if (changes.coneSearch && changes.coneSearch.currentValue) { + const dec = changes.coneSearch.currentValue.dec; + this.form.controls.dec.setValue(changes.coneSearch.currentValue.dec); + this.deg2DMS(dec); } } @@ -81,15 +88,17 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { * @param {number} deg - The degree value. */ deg2DMS(deg: number): void { - const hh = Math.trunc(deg); - let tmp = (Math.abs(deg - hh)) * 60; - const mm = Math.trunc(tmp); - tmp = (tmp - mm) * 60; - const ss = tmp.toFixed(2); - const decDmsForm = this.getDecDmsForm(); - decDmsForm.controls.d.setValue(hh); - decDmsForm.controls.m.setValue(mm); - decDmsForm.controls.s.setValue(ss); + if (deg !== null) { + const hh = Math.trunc(deg); + let tmp = (Math.abs(deg - hh)) * 60; + const mm = Math.trunc(tmp); + tmp = (tmp - mm) * 60; + const ss = tmp.toFixed(2); + const decDmsForm = this.getDecDmsForm(); + decDmsForm.controls.d.setValue(hh); + decDmsForm.controls.m.setValue(mm); + decDmsForm.controls.s.setValue(ss); + } } /** @@ -98,12 +107,14 @@ export class DecComponent implements OnInit, OnDestroy, OnChanges { * @param {d: number, m: number, s: number} dms - Coordinates in DMS. */ DMS2Deg(dms: {d: number, m: number, s: number }): void { - const tmp = ((dms.s / 60) + dms.m) / 60; - let deg = tmp + Math.abs(dms.d); - if (dms.d < 0) { - deg = -deg; + if (dms !== null) { + const tmp = ((dms.s / 60) + dms.m) / 60; + let deg = tmp + Math.abs(dms.d); + if (dms.d < 0) { + deg = -deg; + } + this.form.controls.dec.setValue(deg); } - this.form.controls.dec.setValue(deg); } ngOnDestroy(): void { diff --git a/client/src/app/instance/cone-search/components/index.ts b/client/src/app/instance/cone-search/components/index.ts index cce5e9fa772723ef602c144a17db4d759ef6d546..bf278389cb5efc69d73275865387362a2c78c3d6 100644 --- a/client/src/app/instance/cone-search/components/index.ts +++ b/client/src/app/instance/cone-search/components/index.ts @@ -12,11 +12,13 @@ import { ResolverComponent } from './resolver.component'; import { RaComponent } from './ra.component'; import { DecComponent } from './dec.component'; import { RadiusComponent } from './radius.component'; +import { ConeSearchParametersComponent } from './cone-search-parameters.component'; export const coneSearchComponents = [ ConeSearchComponent, ResolverComponent, RaComponent, DecComponent, - RadiusComponent + RadiusComponent, + ConeSearchParametersComponent ]; diff --git a/client/src/app/instance/cone-search/components/ra.component.spec.ts b/client/src/app/instance/cone-search/components/ra.component.spec.ts index 1ecb7b1631f6cc3c52f34fc92bd4cd3e395a8bda..044647cd2b86f501bc40b4714ec772913bda79ee 100644 --- a/client/src/app/instance/cone-search/components/ra.component.spec.ts +++ b/client/src/app/instance/cone-search/components/ra.component.spec.ts @@ -14,7 +14,6 @@ import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angula import { of } from 'rxjs'; import { RaComponent } from './ra.component'; -import { Resolver } from 'src/app/instance/store/models'; import { nanValidator, rangeValidator } from '../validators'; describe('[Instance][ConeSearch][Components] RaComponent', () => { @@ -41,7 +40,6 @@ describe('[Instance][ConeSearch][Components] RaComponent', () => { public testedComponent: RaComponent; public form: FormGroup = form; public unit: string = 'degree'; - public resolver: Resolver = undefined; } let testHostComponent: TestHostComponent; @@ -92,10 +90,9 @@ describe('[Instance][ConeSearch][Components] RaComponent', () => { expect(spy).toHaveBeenCalledTimes(2); expect(testedComponent.form.controls.ra_hms.disabled).toBeTruthy(); expect(testedComponent.form.controls.ra.enabled).toBeTruthy(); - testHostComponent.resolver = { ra: 1, dec: 2, name: 'myObject' }; testHostFixture.detectChanges(); - expect(spy).toHaveBeenCalledTimes(3); - expect(testedComponent.form.controls.ra.value).toEqual(1); + expect(spy).toHaveBeenCalledTimes(2); + expect(testedComponent.form.controls.ra.value).toEqual(78.2); }); it('#getRaHmsForm() should return RA HMS form control', () => { diff --git a/client/src/app/instance/cone-search/components/ra.component.ts b/client/src/app/instance/cone-search/components/ra.component.ts index 82932a8d2352607cd60a6240bba5e55b90a6095c..3dec1ea4b7081eaedba34f6fff5e96214f2a0c45 100644 --- a/client/src/app/instance/cone-search/components/ra.component.ts +++ b/client/src/app/instance/cone-search/components/ra.component.ts @@ -13,7 +13,7 @@ import { UntypedFormGroup } from '@angular/forms'; import { Subscription } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; -import { Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; /** * @class @@ -32,13 +32,18 @@ import { Resolver } from 'src/app/instance/store/models'; export class RaComponent implements OnInit, OnDestroy, OnChanges { @Input() form: UntypedFormGroup; @Input() unit: string; - @Input() resolver: Resolver; + @Input() coneSearch: ConeSearch; public raControlSubscription: Subscription; public raHmsFormSubscription: Subscription; ngOnInit(): void { - this.form.controls.ra_hms.disable(); + if (this.unit === 'degree') { + this.form.controls.ra_hms.disable(); + } else { + this.form.controls.ra.disable(); + } + this.raControlSubscription = this.form.controls.ra.valueChanges.pipe(debounceTime(250)) .subscribe(deg => this.deg2HMS(deg)); } @@ -61,8 +66,10 @@ export class RaComponent implements OnInit, OnDestroy, OnChanges { } } - if (changes.resolver && changes.resolver.currentValue) { - this.form.controls.ra.setValue(changes.resolver.currentValue.ra); + if (changes.coneSearch && changes.coneSearch.currentValue) { + const ra = changes.coneSearch.currentValue.ra; + this.form.controls.ra.setValue(changes.coneSearch.currentValue.ra); + this.deg2HMS(ra); } } @@ -81,16 +88,18 @@ export class RaComponent implements OnInit, OnDestroy, OnChanges { * @param {number} deg - The degree value. */ deg2HMS(deg: number): void { - let tmp = deg / 15; - const hh = Math.trunc(tmp); - tmp = (tmp - hh) * 60; - const mm = Math.trunc(tmp); - tmp = (tmp - mm) * 60; - const ss = +tmp.toFixed(2); - const raHmsForm = this.getRaHmsForm(); - raHmsForm.controls.h.setValue(hh); - raHmsForm.controls.m.setValue(mm); - raHmsForm.controls.s.setValue(ss); + if (deg !== null) { + let tmp = deg / 15; + const hh = Math.trunc(tmp); + tmp = (tmp - hh) * 60; + const mm = Math.trunc(tmp); + tmp = (tmp - mm) * 60; + const ss = +tmp.toFixed(2); + const raHmsForm = this.getRaHmsForm(); + raHmsForm.controls.h.setValue(hh); + raHmsForm.controls.m.setValue(mm); + raHmsForm.controls.s.setValue(ss); + } } /** @@ -99,8 +108,10 @@ export class RaComponent implements OnInit, OnDestroy, OnChanges { * @param {h: number, m: number, s: number} hms - Coordinates in HMS. */ HMS2Deg(hms: { h: number, m: number, s: number }): void { - const deg = +(((((hms.s / 60) + hms.m) / 60) + hms.h) * 15).toFixed(8); - this.form.controls.ra.setValue(deg); + if (hms !== null) { + const deg = +(((((hms.s / 60) + hms.m) / 60) + hms.h) * 15).toFixed(8); + this.form.controls.ra.setValue(deg); + } } ngOnDestroy(): void { diff --git a/client/src/app/instance/cone-search/components/resolver.component.spec.ts b/client/src/app/instance/cone-search/components/resolver.component.spec.ts index e0f31351751ec612401feb8445284c52493497e2..d8d2ae6f5b46608d742d9bfae11733ab0fbe377d 100644 --- a/client/src/app/instance/cone-search/components/resolver.component.spec.ts +++ b/client/src/app/instance/cone-search/components/resolver.component.spec.ts @@ -12,7 +12,7 @@ import { Component, ViewChild } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { ResolverComponent } from './resolver.component'; -import { ConeSearch, Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; describe('[Instance][ConeSearch][Components] ResolverComponent', () => { @Component({ @@ -20,7 +20,6 @@ describe('[Instance][ConeSearch][Components] ResolverComponent', () => { template: ` <app-resolver [coneSearch]="coneSearch" - [resolver]="resolver" [resolverIsLoading]="resolverIsLoading" [resolverIsLoaded]="resolverIsLoaded"> </app-resolver>` @@ -29,7 +28,6 @@ describe('[Instance][ConeSearch][Components] ResolverComponent', () => { @ViewChild(ResolverComponent, { static: false }) public testedComponent: ResolverComponent; public coneSearch: ConeSearch = undefined; - public resolver: Resolver = undefined; public resolverIsLoading: boolean = false; public resolverIsLoaded: boolean = false; } @@ -56,24 +54,6 @@ describe('[Instance][ConeSearch][Components] ResolverComponent', () => { expect(testedComponent).toBeTruthy(); }); - it('#ngOnInit() should disable form if cone search already defined', () => { - expect(testedComponent.form.enabled).toBeTruthy(); - testedComponent.coneSearch = { ra: 1, dec: 2, radius: 3 }; - testedComponent.ngOnInit(); - expect(testedComponent.form.disabled).toBeTruthy(); - }); - - it('should call ngOnChanges and apply changes', () => { - const spy = jest.spyOn(testedComponent, 'ngOnChanges'); - testHostComponent.coneSearch = null; - testHostFixture.detectChanges(); - expect(testedComponent.form.enabled).toBeTruthy(); - testHostComponent.coneSearch = { ra: 1, dec: 2, radius: 3 }; - testHostFixture.detectChanges(); - expect(testedComponent.form.disabled).toBeTruthy(); - expect(spy).toHaveBeenCalledTimes(2); - }); - it('#submit() should raise retrieveCoordinates event', () => { testedComponent.form.controls.name.setValue('myObjectName'); const spy = jest.spyOn(testedComponent.retrieveCoordinates, 'emit'); diff --git a/client/src/app/instance/cone-search/components/resolver.component.ts b/client/src/app/instance/cone-search/components/resolver.component.ts index f04bf6fb3c2d869e39c8a76a829e5c83a475a9b6..77dc17c294f0e5e81aafd34b6fc16d731f71e7ca 100644 --- a/client/src/app/instance/cone-search/components/resolver.component.ts +++ b/client/src/app/instance/cone-search/components/resolver.component.ts @@ -7,10 +7,10 @@ * file that was distributed with this source code. */ -import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, OnInit, OnChanges, SimpleChanges } from '@angular/core'; +import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms'; -import { ConeSearch, Resolver } from 'src/app/instance/store/models'; +import { ConeSearch } from 'src/app/instance/store/models'; /** * @class @@ -21,9 +21,8 @@ import { ConeSearch, Resolver } from 'src/app/instance/store/models'; templateUrl: 'resolver.component.html', changeDetection: ChangeDetectionStrategy.OnPush }) -export class ResolverComponent implements OnInit, OnChanges { +export class ResolverComponent { @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter(); @@ -32,22 +31,6 @@ export class ResolverComponent implements OnInit, OnChanges { name: new UntypedFormControl('', [Validators.required]) }); - ngOnInit(): void { - if (this.coneSearch) { - this.form.disable(); - } - } - - ngOnChanges(changes: SimpleChanges): void { - if (changes.coneSearch && !changes.coneSearch.currentValue) { - this.form.enable(); - } - - if (changes.coneSearch && changes.coneSearch.currentValue) { - this.form.disable(); - } - } - /** * Emits event to retrieve coordinates. * @@ -55,5 +38,6 @@ export class ResolverComponent implements OnInit, OnChanges { */ submit(): void { this.retrieveCoordinates.emit(this.form.controls.name.value); + this.form.controls.name.setValue(''); } } diff --git a/client/src/app/instance/instance-style.service.ts b/client/src/app/instance/instance-style.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..037d0fbf2963fdec5d092985208609046eda3382 --- /dev/null +++ b/client/src/app/instance/instance-style.service.ts @@ -0,0 +1,246 @@ +import { Injectable } from '@angular/core'; + +import { Instance } from 'src/app/metamodel/models'; +import { StyleService } from 'src/app/shared/services/style.service'; + +@Injectable({ + providedIn: 'root' +}) +export class InstanceStyleService { + constructor(private style: StyleService) { } + + public applyInstanceStyle(instance: Instance) { + this.generalStyle(instance); + this.navbarStyle(instance); + this.footerStyle(instance); + this.searchProgressBarStyle(instance); + this.searchNextBackButtonsStyle(instance); + this.searchFamilyStyle(instance); + this.searchInfoStyle(instance); + this.searchDatasetSelectionStyle(instance); + this.searchCriteriaStyle(instance); + this.searchOutputColumnsStyle(instance); + this.searchResultTable(instance); + } + + private generalStyle(instance: Instance) { + this.style.setStyles('.instance-main', { + 'background-color': instance.design_background_color, + 'color': instance.design_text_color, + 'font-family': instance.design_font_family + }); + this.style.setStyle('.instance-main a', 'color', instance.design_link_color); + this.style.setStyle('.instance-main a:hover', 'color', instance.design_link_hover_color); + this.style.setStyle('.instance-main a.btn', 'color', '#212529'); + } + + private navbarStyle(instance: Instance) { + this.style.setStyles('.navbar-instance', { + 'background-color': instance.navbar_background_color, + 'border-bottom': `1px solid ${instance.navbar_border_bottom_color}`, + 'font-family': instance.navbar_font_family + }); + this.style.setStyle('.navbar-instance a', 'color', instance.navbar_color_href); + this.style.setStyle('.navbar-instance a:hover', 'color', instance.navbar_color_href); + this.style.setStyle('.navbar-instance a.active', 'font-weight', 'bold'); + this.style.setStyles('.navbar-instance #button-sign-in', { + 'color': instance.navbar_sign_in_btn_color, + 'border-color': instance.navbar_sign_in_btn_color + }); + this.style.setStyles('.navbar-instance #button-sign-in:hover', { + 'background-color': instance.navbar_background_color + }); + this.style.setStyles('.navbar-instance #button-basic', { + 'background-color': instance.navbar_background_color, + 'border': 'none' + }); + this.style.setStyle('.navbar-instance #button-user', 'color', instance.navbar_user_btn_color); + } + + private footerStyle(instance: Instance) { + this.style.setStyles('.footer', { + 'background-color': instance.footer_background_color, + 'border-top': `1px solid ${instance.footer_border_top_color}`, + 'color': instance.footer_text_color, + }); + } + + private searchProgressBarStyle(instance: Instance) { + this.style.setStyle('.progress-bar-title', 'color', instance.progress_bar_title_color); + this.style.setStyle('.progress-bar-subtitle', 'color', instance.progress_bar_subtitle_color); + this.style.setStyle('.progress-navigation .progress.progress-with-circle', 'background-color', instance.progress_bar_color); + this.style.setStyle('.progress-navigation .progress.progress-with-circle .progress-bar', 'background-color', instance.progress_bar_active_color); + const progressTitleBold = (instance.progress_bar_text_bold) ? 'bold' : 'normal'; + this.style.setStyles('.progress-navigation .nav-link, .progress-navigation .nav-link.disabled', { + 'color': instance.progress_bar_text_color, + 'font-weight': progressTitleBold + }); + this.style.setStyle('.progress-navigation .nav-link:hover', 'color', instance.progress_bar_text_color); + this.style.setStyle('.progress-navigation .nav-item.checked .nav-link, .progress-navigation.nav-item.active .nav-link', 'color', instance.progress_bar_active_color); + this.style.setStyles('.progress-navigation .nav-item .icon-circle', { + 'border-color': instance.progress_bar_color, + 'background-color': instance.progress_bar_circle_color, + 'color': instance.progress_bar_circle_icon_color + }); + this.style.setStyles('.progress-navigation .nav-item.checked .icon-circle', { + 'background-color': instance.progress_bar_circle_color, + 'border-color': instance.progress_bar_active_color, + 'color': instance.progress_bar_active_color + }); + this.style.setStyles('.progress-navigation .nav-item.active .icon-circle', { + 'border-color': instance.progress_bar_active_color, + 'background-color': instance.progress_bar_active_color, + 'color': instance.progress_bar_circle_icon_active_color + }); + } + + private searchNextBackButtonsStyle(instance: Instance) { + // Next button + this.style.setStyles('.search-next.btn.btn-outline-primary', { + 'color': instance.search_next_btn_color, + 'border-color': instance.search_next_btn_color + }); + this.style.setStyles('.search-next:hover.btn.btn-outline-primary', { + 'color': instance.search_next_btn_hover_text_color, + 'background-color': instance.search_next_btn_hover_color, + 'border-color': instance.search_next_btn_hover_color + }); + + // Back button + this.style.setStyles('.search-back.btn.btn-outline-secondary', { + 'color': instance.search_back_btn_color, + 'border-color': instance.search_back_btn_color + }); + this.style.setStyles('.search-back:hover.btn.btn-outline-secondary', { + 'color': instance.search_back_btn_hover_text_color, + 'background-color': instance.search_back_btn_hover_color, + 'border-color': instance.search_back_btn_hover_color + }); + } + + private searchFamilyStyle(instance: Instance) { + this.style.setStyle('.panel.card.custom-accordion', 'border-color', instance.family_border_color); + this.style.setStyle('.panel.card.custom-accordion .card-header', 'border-bottom-color', instance.family_border_color); + this.style.setStyle('.custom-accordion .panel-heading', 'background-color', instance.family_header_background_color); + this.style.setStyle('.custom-accordion .panel-heading .btn-link', 'color', instance.family_title_color); + const familyTitleBold = (instance.family_title_bold) ? 'bold' : 'normal'; + this.style.setStyle('.custom-accordion .panel-heading .btn-link', 'font-weight', familyTitleBold); + this.style.setStyles('.custom-accordion .panel-body', { + 'color': instance.family_text_color, + 'background-color': `${instance.family_background_color}` + }); + this.style.setStyle('.custom-accordion .panel-body .card', 'background-color', instance.family_background_color); + } + + private searchInfoStyle(instance: Instance) { + this.style.setStyles('.search-info.jumbotron', { + 'background-color': instance.search_info_background_color, + 'color': instance.search_info_text_color + }); + this.style.setStyle('.search-info .btn.btn-outline-primary', 'color', '#007BFF'); + this.style.setStyle('.search-info .btn.btn-outline-primary:hover', 'color', '#FFFFFF'); + } + + private searchDatasetSelectionStyle(instance: Instance) { + this.style.setStyles('.dataset-select-btn.btn.btn-outline-secondary', { + 'color': instance.dataset_select_btn_color, + 'border-color': instance.dataset_select_btn_color + }); + this.style.setStyles('.dataset-select-btn:hover.btn.btn-outline-secondary', { + 'color': instance.dataset_select_btn_hover_text_color, + 'background-color': instance.dataset_select_btn_hover_color, + 'border-color': instance.dataset_select_btn_hover_color + }); + this.style.setStyle('.search-dataset-selected', 'color', instance.dataset_selected_icon_color); + } + + private searchCriteriaStyle(instance: Instance) { + this.style.setStyles('.search_criterium', { + 'background-color': instance.search_criterion_background_color, + 'color': instance.search_criterion_text_color + }); + } + + private searchOutputColumnsStyle(instance: Instance) { + this.style.setStyle('.output_columns_selected', 'color', instance.output_columns_selected_color); + + this.style.setStyles('.select-all.btn.btn-outline-secondary', { + 'color': instance.output_columns_select_all_btn_color, + 'border-color': instance.output_columns_select_all_btn_color + }); + this.style.setStyles('.select-all:not([disabled]):hover.btn.btn-outline-secondary', { + 'color': instance.output_columns_select_all_btn_hover_text_color, + 'background-color': instance.output_columns_select_all_btn_hover_color, + 'border-color': instance.output_columns_select_all_btn_hover_color + }); + } + + private searchResultTable(instance: Instance) { + // Result header (download + SAMP) + this.style.setStyles('.search-info .btn.btn-primary', { + 'background-color': instance.result_download_btn_color, + 'border-color': instance.result_download_btn_color, + 'color': instance.result_download_btn_text_color + }); + this.style.setStyles('.search-info .btn.btn-primary:hover', { + 'background-color': instance.result_download_btn_hover_color, + 'border-color': instance.result_download_btn_hover_color, + 'color': instance.result_download_btn_text_color + }); + + // Datatable button actions + this.style.setStyles('.btn-datatable-actions.btn.btn-primary.dropdown-toggle', { + 'color': instance.result_datatable_actions_btn_text_color, + 'background-color': instance.result_datatable_actions_btn_color, + 'border-color': instance.result_datatable_actions_btn_color + }); + this.style.setStyles('.btn-datatable-actions:not([disabled]):hover.btn.btn-primary', { + 'background-color': instance.result_datatable_actions_btn_hover_color, + 'border-color': instance.result_datatable_actions_btn_hover_color, + }); + this.style.setStyles('.btn-datatable-actions:not([disabled]):focus.btn.btn-primary', { + 'box-shadow': 'none' + }); + + // Datatable + if (instance.result_datatable_bordered) { + this.style.setStyle('#datatable.table-bordered th, #datatable.table-bordered td', 'border', `1px solid ${instance.result_datatable_border_color}`); + this.style.setStyle('#datatable.table-bordered thead th', 'border-bottom', `2px solid ${instance.result_datatable_border_color}`); + if (instance.result_datatable_bordered_radius) { + this.style.setStyles('.datatable-responsive.table-responsive', { + 'border-top-left-radius': '0.3rem', + 'border-top-right-radius': '0.3rem', + }); + } + } else { + this.style.setStyle('#datatable.table th, #datatable.table td', 'border-top', `1px solid ${instance.result_datatable_border_color}`); + this.style.setStyle('#datatable.table thead th', 'border-bottom', `2px solid ${instance.result_datatable_border_color}`); + } + this.style.setStyles('#datatable.table thead tr', { + 'background-color': instance.result_datatable_header_background_color, + 'color': instance.result_datatable_header_text_color + }); + this.style.setStyles('#datatable.table thead tr .column-sorted', { + 'color': instance.result_datatable_sorted_active_color, + 'background-color': instance.result_datatable_header_background_color + }); + this.style.setStyle('#datatable.table thead tr .click-to-sort .unsorted', 'color', instance.result_datatable_sorted_color); + this.style.setStyles('#datatable.table thead tr .click-to-sort .on-hover', { + 'color': instance.result_datatable_sorted_color, + 'background-color': instance.result_datatable_header_background_color + }); + this.style.setStyles('#datatable.table tbody tr', { + 'background-color': instance.result_datatable_rows_background_color, + 'color': instance.result_datatable_rows_text_color + }); + this.style.setStyle('#datatable.table tbody tr.datum-selected-in-plot', 'background-color', instance.result_datatable_rows_selected_color); + this.style.setStyle('#datatable.table tbody tr .checked', 'color', instance.result_datatable_rows_selected_color); + this.style.setStyle('#datatable.table a, .detail a.btn', 'color', instance.result_datatable_link_color); + this.style.setStyle('#datatable.table a, .detail a', 'text-decoration', 'none'); + this.style.setStyle('#datatable.table a.btn-outline-primary, .detail a.btn-outline-primary', 'border-color', instance.result_datatable_link_color); + this.style.setStyle('#datatable.table a:hover, .detail a:hover', 'color', instance.result_datatable_link_hover_color); + this.style.setStyle('#datatable.table a.btn-outline-primary:hover, .detail a.btn-outline-primary:hover', 'color', instance.result_datatable_link_hover_color); + this.style.setStyle('#datatable.table a.btn-outline-primary:hover, .detail a.btn-outline-primary:hover', 'background-color', instance.result_datatable_rows_background_color); + this.style.setStyle('#datatable.table a.btn-outline-primary:hover, .detail a.btn-outline-primary:hover', 'border-color', instance.result_datatable_link_hover_color); + } +} diff --git a/client/src/app/instance/instance.component.html b/client/src/app/instance/instance.component.html index 200ce1c7dd6dc5df008c3ec8bc9481e4d48b289c..2f7c5f4cc33ea5ebcdc6da1b7f711d3452da0dd2 100644 --- a/client/src/app/instance/instance.component.html +++ b/client/src/app/instance/instance.component.html @@ -1,4 +1,4 @@ -<ng-container> +<div class="d-flex flex-column h-100"> <header> <app-instance-navbar [isAuthenticated]="isAuthenticated | async" @@ -16,7 +16,11 @@ (openEditProfile)="openEditProfile()"> </app-instance-navbar> </header> - <main role="main" class="container-fluid pb-4"> + <main role="main" class="container-fluid pb-4 instance-main"> <router-outlet></router-outlet> </main> -</ng-container> + <app-instance-footer class="footer mt-auto" + [instance]="instance | async" + [apiUrl]="getApiUrl()"> + </app-instance-footer> +</div> diff --git a/client/src/app/instance/instance.component.spec.ts b/client/src/app/instance/instance.component.spec.ts index df5f0ff3cc0f85b5b1e17675053ceafc6852466e..f5313afe7fb61567c75b415a71b26f36c65a0373 100644 --- a/client/src/app/instance/instance.component.spec.ts +++ b/client/src/app/instance/instance.component.spec.ts @@ -86,38 +86,73 @@ describe('[Instance] InstanceComponent', () => { files_path: 'files', public: true, portal_logo: 'logo.png', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: '/path/to/logo', + design_logo_href: null, design_favicon: '/path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', + footer_logos: null, family_border_color: '#DFDFDF', family_header_background_color: '#F7F7F7', family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', diff --git a/client/src/app/instance/instance.component.ts b/client/src/app/instance/instance.component.ts index 90b9a5f6d50eb5d7799ac63f1c6f98bc0d5ae583..80d919916a6ef012d736f405f560f83dd357278a 100644 --- a/client/src/app/instance/instance.component.ts +++ b/client/src/app/instance/instance.component.ts @@ -27,7 +27,7 @@ import * as webpageFamilySelector from 'src/app/metamodel/selectors/webpage-fami import * as webpageActions from 'src/app/metamodel/actions/webpage.actions'; import * as webpageSelector from 'src/app/metamodel/selectors/webpage.selector'; import { AppConfigService } from 'src/app/app-config.service'; -import { StyleService } from 'src/app/shared/services/style.service'; +import { InstanceStyleService } from './instance-style.service'; /** * @class @@ -42,7 +42,6 @@ import { StyleService } from 'src/app/shared/services/style.service'; }) export class InstanceComponent implements OnInit, OnDestroy { public favIcon: HTMLLinkElement = document.querySelector('#favicon'); - public body: HTMLBodyElement = document.querySelector('body'); public instance: Observable<Instance>; public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; @@ -63,7 +62,7 @@ export class InstanceComponent implements OnInit, OnDestroy { private http: HttpClient, private route: ActivatedRoute, private router: Router, - private style: StyleService + private style: InstanceStyleService ) { this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.isAuthenticated = store.select(authSelector.selectIsAuthenticated); @@ -91,67 +90,8 @@ export class InstanceComponent implements OnInit, OnDestroy { if (instance.design_favicon !== '') { this.setFaviconHref(instance); } - this.body.style.backgroundColor = instance.design_background_color; if(document.styleSheets.length > 0) { - this.style.setStyles('.navbar-instance', { - 'background-color': instance.navbar_background_color, - 'border-bottom': `1px solid ${instance.navbar_border_bottom_color}` - }); - this.style.setStyle('.navbar-instance a', 'color', instance.navbar_color_href); - this.style.setStyle('.navbar-instance a:hover', 'color', instance.navbar_color_href); - this.style.setStyle('.navbar-instance a.active', 'font-weight', 'bold'); - this.style.setStyles('.navbar-instance #button-basic', { - 'background-color': instance.navbar_background_color, - 'border': 'none' - }); - - this.style.setStyles('.footer', { - 'background-color': instance.footer_background_color, - 'border-top': `1px solid ${instance.footer_border_top_color}`, - 'color': instance.footer_text_color, - }); - - this.style.setStyle('.panel.card.custom-accordion', 'border-color', instance.family_border_color); - this.style.setStyle('.custom-accordion .panel-heading', 'background-color', instance.family_header_background_color); - this.style.setStyle('.custom-accordion .panel-heading .btn-link', 'color', instance.family_title_color); - const familyTitleBold = (instance.family_title_bold) ? 'bold' : 'normal'; - this.style.setStyle('.custom-accordion .panel-heading .btn-link', 'font-weight', familyTitleBold); - this.style.setStyles('.custom-accordion .panel-body', { - 'color': instance.family_color, - 'background-color': `${instance.family_background_color}` - }); - this.style.setStyle('.custom-accordion .panel-body .card', 'background-color', instance.family_background_color); - - this.style.setStyles('.anis-result-header.jumbotron', { - 'background-color': instance.result_header_background_color, - 'color': instance.result_header_text_color - }); - this.style.setStyles('.anis-result-header .btn-primary', { - 'background-color': instance.result_header_btn_color, - 'border-color': instance.result_header_btn_color, - 'color': instance.result_header_btn_text_color - }); - this.style.setStyles('.anis-result-header .btn-primary:hover', { - 'background-color': instance.result_header_btn_hover_color, - 'border-color': instance.result_header_btn_hover_color, - 'color': instance.result_header_btn_text_color - }); - - if (instance.result_datatable_bordered) { - this.style.setStyle('#datatable.table-bordered th, #datatable.table-bordered td', 'border', `1px solid ${instance.result_datatable_border_color}`); - this.style.setStyle('#datatable.table-bordered thead th', 'border-bottom', `2px solid ${instance.result_datatable_border_color}`); - } else { - this.style.setStyle('#datatable.table th, #datatable.table td', 'border-top', `1px solid ${instance.result_datatable_border_color}`); - this.style.setStyle('#datatable.table thead th', 'border-bottom', `2px solid ${instance.result_datatable_border_color}`); - } - - this.style.setStyle('#datatable.table a', 'color', instance.result_datatable_link_color); - this.style.setStyle('#datatable.table a', 'text-decoration', 'none'); - this.style.setStyle('#datatable.table a.btn-outline-primary', 'border-color', instance.result_datatable_link_color); - this.style.setStyle('#datatable.table a:hover', 'color', instance.result_datatable_link_hover_color); - this.style.setStyle('#datatable.table a.btn-outline-primary:hover', 'color', instance.result_datatable_link_hover_color); - this.style.setStyle('#datatable.table a.btn-outline-primary:hover', 'background-color', instance.result_datatable_rows_background_color); - this.style.setStyle('#datatable.table a.btn-outline-primary:hover', 'border-color', instance.result_datatable_link_hover_color); + this.style.applyInstanceStyle(instance); } } }); diff --git a/client/src/app/instance/instance.module.ts b/client/src/app/instance/instance.module.ts index a0f28693cc50fe455be948c517f5dae9883f114f..f3a96e2ccae6e5031964e7d2c72e68de6a051578 100644 --- a/client/src/app/instance/instance.module.ts +++ b/client/src/app/instance/instance.module.ts @@ -18,6 +18,7 @@ import { dummiesComponents } from './components'; import { instanceReducer } from './instance.reducer'; import { instanceEffects } from './store/effects'; import { instanceServices } from './store/services'; +import { InstanceStyleService } from './instance-style.service'; /** * @class @@ -35,7 +36,8 @@ import { instanceServices } from './store/services'; dummiesComponents ], providers: [ - instanceServices + instanceServices, + InstanceStyleService ] }) export class InstanceModule { } diff --git a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.html b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.html index b63ad383bfde5b8f6ac45cadd5d5214c2940fb4c..bfbcdfc0c8880b0893552a81ffcb894f29202ff1 100644 --- a/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.html +++ b/client/src/app/instance/search-multiple/components/datasets/datasets-by-family.component.html @@ -17,7 +17,7 @@ <div *ngFor="let dataset of datasetList"> <div *ngIf="isSelected(dataset.name)"> <button class="btn btn-block text-left py-1 m-0 rounded-0" (click)="toggleSelection(dataset.name)"> - <span class="fas fa-fw fa-check-square theme-color"></span> + <span class="fas fa-fw fa-check-square output_columns_selected"></span> {{ dataset.label }} <span [tooltip]="datasetInfo" placement="right" containerClass="custom-tooltip right-tooltip"> <span class="far fa-question-circle fa-xs"></span> diff --git a/client/src/app/instance/search-multiple/components/index.ts b/client/src/app/instance/search-multiple/components/index.ts index f96bfa83836d525bd1d0d20a35c99aacd4fce382..5a6caee576bb9769a209621ade80b44e2fd2cab6 100644 --- a/client/src/app/instance/search-multiple/components/index.ts +++ b/client/src/app/instance/search-multiple/components/index.ts @@ -1,9 +1,11 @@ import { ProgressBarMultipleComponent } from './progress-bar-multiple.component'; +import { positionComponents } from './position'; import { datasetsComponents } from './datasets'; import { resultComponents } from './result'; export const dummiesComponents = [ ProgressBarMultipleComponent, + positionComponents, datasetsComponents, resultComponents ]; diff --git a/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.html b/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.html new file mode 100644 index 0000000000000000000000000000000000000000..325a6577fbc8889eea057aff8465ba5d8b3d1a65 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.html @@ -0,0 +1,34 @@ +<accordion [isAnimated]="true"> + <accordion-group #ag [panelClass]="'custom-accordion'" [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix" accordion-heading> + <span class="pull-left float-left"> + Cone search + + <span *ngIf="ag.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!ag.isOpen"> + <span class="fas fa-chevron-down"></span> + </span> + </span> + </button> + <div class="row"> + <div class="col"> + <app-cone-search + [coneSearch]="coneSearch" + [resolverEnabled]="true" + [resolverIsLoading]="resolverIsLoading" + [resolverIsLoaded]="resolverIsLoaded" + (retrieveCoordinates)="retrieveCoordinates.emit($event)" + (emitAdd)="emitAdd(cs.getConeSearch())" + #cs> + </app-cone-search> + </div> + <div class="col-2 text-center align-self-end"> + <button class="btn btn-outline-danger" *ngIf="coneSearch" (click)="deleteConeSearch.emit()"> + <span class="fa fa-times fa-fw"></span> + </button> + </div> + </div> + </accordion-group> +</accordion> diff --git a/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.ts b/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..cb656bea3c4cc3f2f6be0b9b6f4da37eb940ccca --- /dev/null +++ b/client/src/app/instance/search-multiple/components/position/cone-search-panel.component.ts @@ -0,0 +1,41 @@ +/** + * 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, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core'; + +import { ConeSearch, coneSearchToString } from 'src/app/instance/store/models'; + +@Component({ + selector: 'app-cone-search-panel', + templateUrl: 'cone-search-panel.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ConeSearchPanelComponent { + @Input() coneSearch: ConeSearch; + @Input() resolverIsLoading: boolean; + @Input() resolverIsLoaded: boolean; + @Output() addConeSearch: EventEmitter<ConeSearch> = new EventEmitter(); + @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter(); + @Output() deleteConeSearch: EventEmitter<{ }> = new EventEmitter(); + @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter(); + + /** + * Emits event to add or update cone-search. + * + * @fires EventEmitter<ConeSearch> + */ + emitAdd(newConeSearch: ConeSearch): void { + if (!this.coneSearch) { + this.addConeSearch.emit(newConeSearch); + } + if (this.coneSearch && coneSearchToString(this.coneSearch) !== coneSearchToString(newConeSearch)) { + this.updateConeSearch.emit(newConeSearch); + } + } +} diff --git a/client/src/app/instance/search-multiple/components/position/index.ts b/client/src/app/instance/search-multiple/components/position/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..1e564451631358fa0647bc5adb8ca0dfcb557fc9 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/position/index.ts @@ -0,0 +1,7 @@ +import { ParametersPanelComponent } from './parameters-panel.component'; +import { ConeSearchPanelComponent } from './cone-search-panel.component'; + +export const positionComponents = [ + ParametersPanelComponent, + ConeSearchPanelComponent +]; diff --git a/client/src/app/instance/search-multiple/components/position/parameters-panel.component.html b/client/src/app/instance/search-multiple/components/position/parameters-panel.component.html new file mode 100644 index 0000000000000000000000000000000000000000..aeb9d25b7a19ecbc222acff0dc06d76a08802224 --- /dev/null +++ b/client/src/app/instance/search-multiple/components/position/parameters-panel.component.html @@ -0,0 +1,19 @@ +<div *ngIf="coneSearch" class="search-info jumbotron row mx-0 mb-4 py-4 sticky-top search_criteria_list"> + <div class="col"> + <div class="row mb-2"> + <div class="lead"> + <div class="row"> + <div class="col ml-2"> + <span class="font-weight-bold">Cone-search position</span> + </div> + </div> + <div class="row"> + <div class="col"> + <app-cone-search-parameters [coneSearch]="coneSearch"> + </app-cone-search-parameters> + </div> + </div> + </div> + </div> + </div> +</div> diff --git a/client/src/app/instance/search-multiple/components/position/parameters-panel.component.ts b/client/src/app/instance/search-multiple/components/position/parameters-panel.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..78abdb93380f63102a5c35c7d89f8980106a25ff --- /dev/null +++ b/client/src/app/instance/search-multiple/components/position/parameters-panel.component.ts @@ -0,0 +1,23 @@ +/** + * 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, ChangeDetectionStrategy, Input } from '@angular/core'; + +import { ConeSearch } from 'src/app/instance/store/models'; +import { Dataset } from 'src/app/metamodel/models'; + +@Component({ + selector: 'app-parameters-panel', + templateUrl: 'parameters-panel.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class ParametersPanelComponent { + @Input() coneSearch: ConeSearch; + @Input() dataset: Dataset; +} diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html index 54904e5ecb171fded00a42d506b5e104c8e5d2da..feba9bcfac34f6f726f52db5fc4cce1758d9ca91 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.html @@ -1,54 +1,33 @@ <div class="row text-center"> <div class="col"> - <h1>Search around a position in multiple datasets</h1> - <p class="text-muted">Fill RA & DEC position, select datasets and display the result.</p> + <h1 class="progress-bar-title">Search around a position in multiple datasets</h1> + <p class="progress-bar-subtitle">Fill RA & DEC position, select datasets and display the result.</p> </div> </div> <div class="progress-navigation"> <div class="progress progress-with-circle"> - <div class="progress-bar" - [ngClass]="getStepClass()" - [ngStyle]="{'background-color': instance.design_color }" - role="progressbar" - aria-valuenow="1" - aria-valuemin="1" - aria-valuemax="4"> - </div> + <div class="progress-bar" [ngClass]="getStepClass()" role="progressbar"></div> </div> <ul class="nav nav-pills"> <li class="nav-item checked" [ngClass]="{'active': currentStep === 'position'}"> - <a class="nav-link" [ngStyle]="getNavItemAStyle('position', true)" routerLink="/instance/{{ instance.name }}/search-multiple/position" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('position', true)"> + <a class="nav-link" routerLink="/instance/{{ instance.name }}/search-multiple/position" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-drafting-compass"></span> </div> Position </a> </li> - <li class="nav-item" [ngClass]="{'active': currentStep === 'datasets', 'checked': datasetsStepChecked}"> - <a *ngIf="coneSearch" class="nav-link" [ngStyle]="getNavItemAStyle('datasets', datasetsStepChecked)" routerLink="/instance/{{ instance.name }}/search-multiple/datasets" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('datasets', datasetsStepChecked)"> - <span class="fas fa-book"></span> - </div> - Datasets - </a> - <a *ngIf="!coneSearch" class="nav-link disabled" [ngStyle]="getNavItemAStyle('datasets', datasetsStepChecked)" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('datasets', datasetsStepChecked)"> + <a class="nav-link" [ngClass]="{'disabled': !coneSearch}" routerLink="/instance/{{ instance.name }}/search-multiple/datasets" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-book"></span> </div> Datasets </a> </li> - <li class="nav-item" [ngClass]="{'active': currentStep === 'result', 'checked': resultStepChecked}"> - <a *ngIf="coneSearch && selectedDatasets.length > 0" class="nav-link" [ngStyle]="getNavItemAStyle('result', resultStepChecked)" routerLink="/instance/{{ instance.name }}/search-multiple/result" [queryParams]="queryParams" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('result', resultStepChecked)"> - <span class="fas fa-table"></span> - </div> - Result - </a> - <a *ngIf="!coneSearch || selectedDatasets.length < 1" class="nav-link disabled" [ngStyle]="getNavItemAStyle('result', resultStepChecked)" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('result', resultStepChecked)"> + <a class="nav-link" [ngClass]="{'disabled': !coneSearch || selectedDatasets.length < 1}" routerLink="/instance/{{ instance.name }}/search-multiple/result" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-table"></span> </div> Result diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.scss b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.scss index 0cf6548626fcaec4468e60ae9b438a7349060294..f1fde753c55b9474337e3eaf4fabaeac14e284a7 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.scss +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.scss @@ -7,85 +7,10 @@ * file that was distributed with this source code. */ -.progress-navigation { - position: relative; - height: 125px; - margin-top: 15px; -} - -.progress-with-circle { - position: relative; - top: 40px; - z-index: 50; - height: 4px; -} - -.progress-bar { - box-shadow: none; - -webkit-transition: width .3s ease; - -o-transition: width .3s ease; - transition: width .3s ease; -} - -.nav-pills { - background-color: #F3F2EE; - position: absolute; - width: 100%; - height: 4px; - top: 40px; - text-align: center; -} - -.nav-pills li a { - padding: 0; - max-width: 78px; - margin: 0 auto; - color: rgba(0, 0, 0, 0.2); - border-radius: 50%; - position: relative; - top: -32px; - z-index: 100; -} - -.icon-circle { - font-size: 20px; - border: 3px solid #E9ECEF; - text-align: center; - border-radius: 50%; - color: rgba(0, 0, 0, 0.2); - font-weight: 600; - width: 70px; - height: 70px; - background-color: #FFFFFF; - margin: 0 auto; - position: relative; - top: -2px; -} - .nav-item { width: 33%; } -.nav-item.active a { - background-color: transparent; -} - -.nav-item.active .icon-circle { - color: white !important; -} - -.nav-link.disabled { - cursor: not-allowed; -} - -.icon-circle svg { - position: absolute; - z-index: 1; - left: 22px; - right: 0; - top: 23px; -} - .positionStep { width: 15%; } @@ -97,11 +22,3 @@ .resultStep { width: 100%; } - -.btn-clear-form span { - display: none; -} - -.btn-clear-form:hover span { - display: inline; -} diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts index a86e34f952555f07fd597b550583aadb210a5313..23e4b5e67237b8f84f103d61b079ec2ec8338605 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.spec.ts @@ -2,7 +2,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { ProgressBarMultipleComponent } from './progress-bar-multiple.component'; -import { INSTANCE } from '../../../../test-data'; describe('[Instance][SearchMultiple][Component] ProgressBarMultipleComponent', () => { let component: ProgressBarMultipleComponent; @@ -34,21 +33,4 @@ describe('[Instance][SearchMultiple][Component] ProgressBarMultipleComponent', ( style = component.getStepClass(); expect(style).toBe('resultStep'); }); - - it('#getNavItemAStyle() should return correct style for navigation link', () => { - component.currentStep = 'step'; - component.instance = INSTANCE; - expect(component.getNavItemAStyle('', false)).toBeNull(); - expect(component.getNavItemAStyle('step', true)).toEqual({ color: 'green' }); - }); - - it('#getNavItemIconCircleStyle() should return correct style for icon circle', () => { - component.currentStep = 'step'; - component.instance = INSTANCE; - expect(component.getNavItemIconCircleStyle('', false)).toEqual({ }); - const expectedWithStep = { 'border-color': 'green', 'background-color': 'green' }; - expect(component.getNavItemIconCircleStyle('step', false)).toEqual(expectedWithStep); - const expectedWithChecked = { 'border-color': 'green', 'color': 'green' }; - expect(component.getNavItemIconCircleStyle('', true)).toEqual(expectedWithChecked); - }); }); diff --git a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts index 9a09a721236ea1f314b9958270f1b9b9690b77e7..85d4c12a15ac043bd636581ac4abc7b6bb31332e 100644 --- a/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts +++ b/client/src/app/instance/search-multiple/components/progress-bar-multiple.component.ts @@ -19,13 +19,12 @@ import { ConeSearch, SearchMultipleQueryParams } from 'src/app/instance/store/mo @Component({ selector: 'app-progress-bar-multiple', templateUrl: 'progress-bar-multiple.component.html', - styleUrls: ['progress-bar-multiple.component.scss'], + styleUrls: [ '../../search/components/progress-bar.component.scss', 'progress-bar-multiple.component.scss' ], changeDetection: ChangeDetectionStrategy.OnPush }) export class ProgressBarMultipleComponent { @Input() instance: Instance; @Input() currentStep: string; - @Input() positionStepChecked: boolean; @Input() datasetsStepChecked: boolean; @Input() resultStepChecked: boolean; @Input() coneSearch: ConeSearch; @@ -49,40 +48,4 @@ export class ProgressBarMultipleComponent { return 'positionStep'; } } - - /** - * Returns navigation link style. - * - * @param {string} currentStep - The current step. - * @param {boolean} checked - The checked status of current step. - * - * @return { color: string } | null - */ - getNavItemAStyle(currentStep: string, checked: boolean): { color: string } | null { - if (this.currentStep === currentStep || checked) { - return { 'color': this.instance.design_color } - } - return null; - } - - /** - * Returns navigation icon circle style. - * - * @param {string} currentStep - The current step. - * @param {boolean} checked - The checked status of current step. - * - * @return any - */ - getNavItemIconCircleStyle(currentStep: string, checked: boolean): any { - let style = {}; - if (this.currentStep === currentStep) { - style['border-color'] = this.instance.design_color; - style['background-color'] = this.instance.design_color; - } - if (checked) { - style['border-color'] = this.instance.design_color; - style['color'] = this.instance.design_color; - } - return style; - } } diff --git a/client/src/app/instance/search-multiple/components/result/overview.component.html b/client/src/app/instance/search-multiple/components/result/overview.component.html index 91b90040c64e0fa910f1e502ff2d7c33d34a5be1..585de9931e37a0da161d8959e7cd889c6715d7d6 100644 --- a/client/src/app/instance/search-multiple/components/result/overview.component.html +++ b/client/src/app/instance/search-multiple/components/result/overview.component.html @@ -32,11 +32,10 @@ <div *ngIf="getTotalObject() > 0"> <div class="lead"> - Found <span class="font-weight-bold">{{ getTotalObject() }}</span> <span *ngIf="getTotalObject() > 1; else object"> objects</span> <ng-template #object> object</ng-template> - in + found in <span class="font-weight-bold">{{ getTotalDatasets() }}</span> <span *ngIf="getTotalDatasets() > 1; else dataset"> datasets</span> <ng-template #dataset> dataset</ng-template>. diff --git a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts index 69b64e6f6f803b12951d53d835f5593d15e3ea8f..5bece9d1f56e186d2ed2ca53dd3d679d34f3eda1 100644 --- a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts +++ b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.spec.ts @@ -5,7 +5,6 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { of } from 'rxjs'; import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component'; -import * as searchActions from '../../store/actions/search.actions'; import * as searchMultipleActions from '../../store/actions/search-multiple.actions'; describe('[Instance][SearchMultiple][Container] AbstractSearchComponent', () => { @@ -17,10 +16,6 @@ describe('[Instance][SearchMultiple][Container] AbstractSearchComponent', () => ngOnInit() { super.ngOnInit(); } - - ngOnDestroy() { - super.ngOnDestroy(); - } } let component: MyFakeComponent; @@ -51,11 +46,4 @@ describe('[Instance][SearchMultiple][Container] AbstractSearchComponent', () => done(); }); }); - - it('#ngOnDestroy() should unsubscribe from datasetListSubscription', () => { - component.datasetListSubscription = of().subscribe(); - const spy = jest.spyOn(component.datasetListSubscription, 'unsubscribe'); - component.ngOnDestroy(); - expect(spy).toHaveBeenCalledTimes(1); - }); }); diff --git a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts index 9636c26a182b8dda539f9f069a5c25344680312e..9a8557be38130f6803bc390f4c4c35a4c9042fbe 100644 --- a/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts +++ b/client/src/app/instance/search-multiple/containers/abstract-search-multiple.component.ts @@ -3,7 +3,7 @@ import { Directive, OnDestroy, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; -import { Dataset, DatasetFamily } from 'src/app/metamodel/models'; +import { Instance, Dataset, DatasetFamily } from 'src/app/metamodel/models'; import { ConeSearch, SearchMultipleQueryParams } from '../../store/models'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector'; @@ -21,9 +21,9 @@ import * as coneSearchSelector from 'src/app/instance/store/selectors/cone-searc * @implements OnDestroy */ @Directive() -export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestroy { +export abstract class AbstractSearchMultipleComponent implements OnInit { public pristine: Observable<boolean>; - public instanceSelected: Observable<string>; + public instance: Observable<Instance>; public datasetFamilyListIsLoading: Observable<boolean>; public datasetFamilyListIsLoaded: Observable<boolean>; public datasetFamilyList: Observable<DatasetFamily[]>; @@ -34,11 +34,10 @@ export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestr public selectedDatasets: Observable<string[]>; public coneSearch: Observable<ConeSearch>; public queryParams: Observable<SearchMultipleQueryParams>; - public datasetListSubscription: Subscription; constructor(protected store: Store<{ }>) { this.pristine = this.store.select(searchMultipleSelector.selectPristine); - this.instanceSelected = this.store.select(instanceSelector.selectInstanceNameByRoute); + this.instance = this.store.select(instanceSelector.selectInstanceByRouteName); this.datasetFamilyListIsLoading = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoading); this.datasetFamilyListIsLoaded = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoaded); this.datasetFamilyList = store.select(datasetFamilySelector.selectAllDatasetFamilies); @@ -52,16 +51,8 @@ export abstract class AbstractSearchMultipleComponent implements OnInit, OnDestr } ngOnInit(): void { - this.datasetListSubscription = this.datasetListIsLoaded.subscribe(datasetListIsLoaded => { - if (datasetListIsLoaded) { - // 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(searchMultipleActions.initSearch())); - } - }) - } - - ngOnDestroy(): void { - if (this.datasetListSubscription) this.datasetListSubscription.unsubscribe(); + // 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(searchMultipleActions.initSearch())); } } diff --git a/client/src/app/instance/search-multiple/containers/datasets.component.html b/client/src/app/instance/search-multiple/containers/datasets.component.html index 5852145ab4bee6d555c60a46f0b84f6eb06f553c..d8ce39082a3b5e8a89af853688d2627cd0e1feed 100644 --- a/client/src/app/instance/search-multiple/containers/datasets.component.html +++ b/client/src/app/instance/search-multiple/containers/datasets.component.html @@ -1,32 +1,35 @@ <app-spinner *ngIf="(datasetFamilyListIsLoading | async) || (datasetListIsLoading | async)"> </app-spinner> -<div *ngIf="(datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)" class="row mt-4"> - <div class="col-12"> - <div class="border rounded my-2"> - <p class="border-bottom bg-light text-primary mb-0 py-4 pl-4">Datasets</p> - <div class="px-3"> - <app-dataset-list - [datasetFamilyList]="datasetFamilyList | async" - [datasetList]="datasetList | async" - [selectedDatasets]="selectedDatasets | async" - (updateSelectedDatasets)="updateSelectedDatasets($event)"> - </app-dataset-list> - </div> - </div> - </div> -</div> +<accordion *ngIf="(datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)" [isAnimated]="true"> + <accordion-group #ag [panelClass]="'custom-accordion'" class="my-2" [isOpen]="true"> + <button class="btn btn-link btn-block clearfix" accordion-heading> + <span class="pull-left float-left"> + Datasets + + <span *ngIf="ag.isOpen"><span class="fas fa-chevron-up"></span></span> + <span *ngIf="!ag.isOpen"><span class="fas fa-chevron-down"></span></span> + </span> + </button> + <app-dataset-list + [datasetFamilyList]="datasetFamilyList | async" + [datasetList]="datasetList | async" + [selectedDatasets]="selectedDatasets | async" + (updateSelectedDatasets)="updateSelectedDatasets($event)"> + </app-dataset-list> + </accordion-group> +</accordion> <div class="row mt-5 justify-content-between"> <div class="col"> - <a routerLink="/instance/{{ instanceSelected | async }}/search-multiple/position" [queryParams]="queryParams | async" - class="btn btn-outline-secondary"> + <a routerLink="/instance/{{ (instance | async).name }}/search-multiple/position" [queryParams]="queryParams | async" + class="search-back btn btn-outline-secondary"> <span class="fas fa-arrow-left"></span> Position </a> </div> <div *ngIf="(selectedDatasets | async).length > 0" class="col col-auto"> - <a routerLink="/instance/{{ instanceSelected | async }}/search-multiple/result" [queryParams]="queryParams | async" - class="btn btn-outline-primary"> + <a routerLink="/instance/{{ (instance | async).name }}/search-multiple/result" [queryParams]="queryParams | async" + class="search-next btn btn-outline-primary"> Result <span class="fas fa-arrow-right"></span> </a> </div> diff --git a/client/src/app/instance/search-multiple/containers/position.component.html b/client/src/app/instance/search-multiple/containers/position.component.html index 24f6ec30ba505fd245e759129ca9373e3dba7bf5..53e1f28d19e93d5da478eb2483a8f2cf6e931b86 100644 --- a/client/src/app/instance/search-multiple/containers/position.component.html +++ b/client/src/app/instance/search-multiple/containers/position.component.html @@ -1,37 +1,26 @@ <app-spinner *ngIf="(pristine | async) || (datasetFamilyListIsLoading | async) || (datasetListIsLoading | async)"> </app-spinner> -<div *ngIf="!(pristine | async) && (datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)" class="row mt-4"> - <div class="col-12"> - <div class="border rounded my-2"> - <p class="border-bottom bg-light text-primary mb-0 py-4 pl-4">Cone Search</p> - <div class="row p-4"> - <div class="col"> - <app-cone-search - [coneSearch]="coneSearch | async" - [resolver]="resolver | async" - [resolverIsLoading]="resolverIsLoading | async" - [resolverIsLoaded]="resolverIsLoaded | async" - (retrieveCoordinates)="retrieveCoordinates($event)" #cs> - </app-cone-search> - </div> - <div class="col-2 text-center align-self-end"> - <button class="btn btn-outline-success" *ngIf="!(coneSearch | async)" [hidden]="cs.form.invalid" (click)="addConeSearch(cs.getConeSearch())"> - <span class="fas fa-plus fa-fw"></span> - </button> - <button class="btn btn-outline-danger" *ngIf="coneSearch | async" (click)="deleteConeSearch()"> - <span class="fa fa-times fa-fw"></span> - </button> - </div> - </div> - </div> - </div> -</div> +<ng-container *ngIf="!(pristine | async) && (datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async)"> + <app-parameters-panel + [coneSearch]="coneSearch | async"> + </app-parameters-panel> + + <app-cone-search-panel + [coneSearch]="coneSearch | async" + [resolverIsLoading]="resolverIsLoading | async" + [resolverIsLoaded]="resolverIsLoaded | async" + (addConeSearch)="addConeSearch($event)" + (updateConeSearch)="updateConeSearch($event)" + (deleteConeSearch)="deleteConeSearch()" + (retrieveCoordinates)="retrieveCoordinates($event)"> + </app-cone-search-panel> +</ng-container> <div *ngIf="coneSearch | async" class="row mt-5 justify-content-end"> <div class="col col-auto"> - <a routerLink="/instance/{{ instanceSelected | async }}/search-multiple/datasets" [queryParams]="queryParams | async" - class="btn btn-outline-primary">Datasets <span class="fas fa-arrow-right"></span> + <a routerLink="/instance/{{ (instance | async).name }}/search-multiple/datasets" [queryParams]="queryParams | async" + class="search-next btn btn-outline-primary">Datasets <span class="fas fa-arrow-right"></span> </a> </div> </div> diff --git a/client/src/app/instance/search-multiple/containers/position.component.spec.ts b/client/src/app/instance/search-multiple/containers/position.component.spec.ts index 84a0914057bb7b80650f61a4919096a35bd27f54..9af01525b8f6fab8be2b817458304864bba5ad2d 100644 --- a/client/src/app/instance/search-multiple/containers/position.component.spec.ts +++ b/client/src/app/instance/search-multiple/containers/position.component.spec.ts @@ -6,7 +6,7 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { PositionComponent } from './position.component'; import { Dataset, DatasetFamily } from '../../../metamodel/models'; -import { ConeSearch, Resolver, SearchMultipleQueryParams } from '../../store/models'; +import { ConeSearch, SearchMultipleQueryParams } from '../../store/models'; import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component'; import * as searchMultipleActions from '../../store/actions/search-multiple.actions'; import * as coneSearchActions from '../../store/actions/cone-search.actions'; @@ -18,7 +18,6 @@ describe('[Instance][SearchMultiple][Container] PositionComponent', () => { @Component({ selector: 'app-cone-search', template: '' }) class ConeSearchStubComponent { @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; } diff --git a/client/src/app/instance/search-multiple/containers/position.component.ts b/client/src/app/instance/search-multiple/containers/position.component.ts index a56e99ce0021ad9d2162bda673db692ca65f53e7..2cbbe5a268d663b6c2f76f78e565dc617ccc9a3d 100644 --- a/client/src/app/instance/search-multiple/containers/position.component.ts +++ b/client/src/app/instance/search-multiple/containers/position.component.ts @@ -13,7 +13,7 @@ import { Store } from '@ngrx/store'; import { Observable } from 'rxjs'; import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component'; -import { Resolver, ConeSearch } from '../../store/models'; +import { ConeSearch } from '../../store/models'; import * as searchMultipleActions from '../../store/actions/search-multiple.actions'; import * as coneSearchActions from '../../store/actions/cone-search.actions'; import * as coneSearchSelector from '../../store/selectors/cone-search.selector'; @@ -30,13 +30,11 @@ import * as coneSearchSelector from '../../store/selectors/cone-search.selector' templateUrl: 'position.component.html' }) export class PositionComponent extends AbstractSearchMultipleComponent implements OnInit { - public resolver: Observable<Resolver>; public resolverIsLoading: Observable<boolean>; public resolverIsLoaded: Observable<boolean>; constructor(protected store: Store<{ }>) { super(store); - this.resolver = this.store.select(coneSearchSelector.selectResolver); this.resolverIsLoading = this.store.select(coneSearchSelector.selectResolverIsLoading); this.resolverIsLoaded = this.store.select(coneSearchSelector.selectResolverIsLoaded); } @@ -57,6 +55,15 @@ export class PositionComponent extends AbstractSearchMultipleComponent implement this.store.dispatch(coneSearchActions.addConeSearch({ coneSearch })); } + /** + * Dispatches action to update cone search. + * + * @param {ConeSearch} coneSearch - The cone search. + */ + updateConeSearch(coneSearch: ConeSearch): void { + this.store.dispatch(coneSearchActions.updateConeSearch({ coneSearch })); + } + /** * Dispatches action to remove cone search. */ diff --git a/client/src/app/instance/search-multiple/containers/result-multiple.component.html b/client/src/app/instance/search-multiple/containers/result-multiple.component.html index 87f5bed1b94f5d6bc3719da92df5493613827c92..9e2f60c4360498eb041345b7a1c913bb809e153a 100644 --- a/client/src/app/instance/search-multiple/containers/result-multiple.component.html +++ b/client/src/app/instance/search-multiple/containers/result-multiple.component.html @@ -4,7 +4,7 @@ <div *ngIf="(datasetFamilyListIsLoaded | async) && (datasetListIsLoaded | async) || (dataLengthIsLoaded | async)" class="row mt-4"> <div class="col-12"> <app-overview - [instanceSelected]="instanceSelected | async" + [instanceSelected]="(instance | async).name" [datasetFamilyList]="datasetFamilyList | async" [datasetList]="datasetList | async" [coneSearch]="coneSearch | async" @@ -16,8 +16,8 @@ </div> <div class="row mt-5 justify-content-between"> <div class="col"> - <a routerLink="/instance/{{ instanceSelected | async }}/search-multiple/datasets" [queryParams]="queryParams | async" - class="btn btn-outline-secondary"> + <a routerLink="/instance/{{ (instance | async).name }}/search-multiple/datasets" [queryParams]="queryParams | async" + class="search-back btn btn-outline-secondary"> <span class="fas fa-arrow-left"></span> Datasets </a> </div> diff --git a/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts b/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts index 4cb2ae0c0191b4ceedd1debde6e128842952c307..52f62c4b5dfad2934c0546b01f77a10e5d8ae5c7 100644 --- a/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts +++ b/client/src/app/instance/search-multiple/containers/result-multiple.component.spec.ts @@ -63,12 +63,4 @@ describe('[Instance][SearchMultiple][Container] ResultMultipleComponent', () => done(); }); }); - - it('#ngOnDestroy() should unsubscribe from pristineSubscription', () => { - component.pristineSubscription = of().subscribe(); - const spy = jest.spyOn(component.pristineSubscription, 'unsubscribe'); - jest.spyOn(AbstractSearchMultipleComponent.prototype, 'ngOnDestroy').mockReturnThis(); - component.ngOnDestroy(); - expect(spy).toHaveBeenCalledTimes(1); - }); }); diff --git a/client/src/app/instance/search-multiple/containers/result-multiple.component.ts b/client/src/app/instance/search-multiple/containers/result-multiple.component.ts index cd50bfbc06ae6f0320273184cca8b1cb0fb4a733..fc86939f46efff2c48ff42a30bdaf40699e3d9b2 100644 --- a/client/src/app/instance/search-multiple/containers/result-multiple.component.ts +++ b/client/src/app/instance/search-multiple/containers/result-multiple.component.ts @@ -12,7 +12,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { Store } from '@ngrx/store'; -import { SearchMultipleDatasetLength, SearchMultipleDatasetData } from '../../store/models'; +import { SearchMultipleDatasetLength } from '../../store/models'; import { AbstractSearchMultipleComponent } from './abstract-search-multiple.component'; import * as searchMultipleActions from '../../store/actions/search-multiple.actions'; import * as searchMultipleSelector from 'src/app/instance/store/selectors/search-multiple.selector'; @@ -33,9 +33,6 @@ export class ResultMultipleComponent extends AbstractSearchMultipleComponent imp public dataLength: Observable<SearchMultipleDatasetLength[]>; public dataLengthIsLoading: Observable<boolean>; public dataLengthIsLoaded: Observable<boolean>; - public data: Observable<SearchMultipleDatasetData[]>; - public dataIsLoading: Observable<boolean>; - public dataIsLoaded: Observable<boolean>; public pristineSubscription: Subscription; constructor(protected store: Store<{ }>) { @@ -43,9 +40,6 @@ export class ResultMultipleComponent extends AbstractSearchMultipleComponent imp this.dataLength = this.store.select(searchMultipleSelector.selectDataLength); this.dataLengthIsLoading = this.store.select(searchMultipleSelector.selectDataLengthIsLoading); this.dataLengthIsLoaded = this.store.select(searchMultipleSelector.selectDataLengthIsLoaded); - this.data = this.store.select(searchMultipleSelector.selectData); - this.dataIsLoading = this.store.select(searchMultipleSelector.selectDataIsLoading); - this.dataIsLoaded = this.store.select(searchMultipleSelector.selectDataIsLoaded); } ngOnInit(): void { @@ -64,6 +58,5 @@ export class ResultMultipleComponent extends AbstractSearchMultipleComponent imp ngOnDestroy(): void { if (this.pristineSubscription) this.pristineSubscription.unsubscribe(); - super.ngOnDestroy(); } } diff --git a/client/src/app/instance/search-multiple/search-multiple.component.html b/client/src/app/instance/search-multiple/search-multiple.component.html index 7f7342be55b65395e810bc751799628776dea30e..e9095b8dd47323444d19c078257ff44789e239bf 100644 --- a/client/src/app/instance/search-multiple/search-multiple.component.html +++ b/client/src/app/instance/search-multiple/search-multiple.component.html @@ -2,7 +2,6 @@ <app-progress-bar-multiple [instance]="instance | async" [currentStep]="currentStep | async" - [positionStepChecked]="positionStepChecked | async" [datasetsStepChecked]="datasetsStepChecked | async" [resultStepChecked]="resultStepChecked | async" [coneSearch]="coneSearch | async" diff --git a/client/src/app/instance/search-multiple/search-multiple.component.ts b/client/src/app/instance/search-multiple/search-multiple.component.ts index b0d2b7b88a44d5099b04b2455761c63191ecc8da..0f5eb576f31cc41d668545086f1cae60b50f5b63 100644 --- a/client/src/app/instance/search-multiple/search-multiple.component.ts +++ b/client/src/app/instance/search-multiple/search-multiple.component.ts @@ -29,7 +29,6 @@ import * as coneSearchSelector from '../store/selectors/cone-search.selector'; export class SearchMultipleComponent { public instance: Observable<Instance>; public currentStep: Observable<string>; - public positionStepChecked: Observable<boolean>; public datasetsStepChecked: Observable<boolean>; public resultStepChecked: Observable<boolean>; public coneSearch: Observable<ConeSearch>; @@ -39,7 +38,6 @@ export class SearchMultipleComponent { constructor(private store: Store<{ }>) { this.instance = this.store.select(instanceSelector.selectInstanceByRouteName); this.currentStep = this.store.select(searchMultipleSelector.selectCurrentStep); - this.positionStepChecked = this.store.select(searchMultipleSelector.selectPositionStepChecked); this.datasetsStepChecked = this.store.select(searchMultipleSelector.selectDatasetsStepChecked); this.resultStepChecked = this.store.select(searchMultipleSelector.selectResultStepChecked); this.coneSearch = this.store.select(coneSearchSelector.selectConeSearch); diff --git a/client/src/app/instance/search/components/criteria-list-parameters.component.html b/client/src/app/instance/search/components/criteria-list-parameters.component.html index 12705318b1cee7bb713afa8b36b8082c9b7e27cf..a3d8505259d5b6fdef8b6276858c10bef1e47af0 100644 --- a/client/src/app/instance/search/components/criteria-list-parameters.component.html +++ b/client/src/app/instance/search/components/criteria-list-parameters.component.html @@ -1,4 +1,4 @@ -<div *ngFor="let criterion of criteriaList" class="search_criterium" [ngStyle]="{'background-color': backgroundColor }"> +<div *ngFor="let criterion of criteriaList" class="search_criterium"> <strong>{{ getAttribute(criterion.id).form_label }}</strong> {{ printCriterion(criterion) }} </div> diff --git a/client/src/app/instance/search/components/criteria-list-parameters.component.scss b/client/src/app/instance/search/components/criteria-list-parameters.component.scss index 2b99cafdb3eca2de694fd8c2a15a7afc18f236ec..fe64ac25e2c2f05e575cb839869354fa271b7981 100644 --- a/client/src/app/instance/search/components/criteria-list-parameters.component.scss +++ b/client/src/app/instance/search/components/criteria-list-parameters.component.scss @@ -4,4 +4,5 @@ padding: .1em .5em; margin: .2em; font-weight: bold; + font-size: 16px; } diff --git a/client/src/app/instance/search/components/criteria-list-parameters.component.ts b/client/src/app/instance/search/components/criteria-list-parameters.component.ts index 19e491bd3994edeef9cad764dc098e07e728ce74..cb81b76a2b97515e5fa61b03b6a3da3b43229c5a 100644 --- a/client/src/app/instance/search/components/criteria-list-parameters.component.ts +++ b/client/src/app/instance/search/components/criteria-list-parameters.component.ts @@ -21,7 +21,6 @@ import { Attribute } from 'src/app/metamodel/models'; export class CriteriaListParametersComponent { @Input() criteriaList: Criterion[]; @Input() attributeList: Attribute[]; - @Input() backgroundColor: string; /** * Returns attribute for the given attribute ID. diff --git a/client/src/app/instance/search/components/criteria/cone-search-tab.component.html b/client/src/app/instance/search/components/criteria/cone-search-tab.component.html index 4cea639ac70912313fc2722952534b4d7a8a3c80..ce576d7087fe87bff2e67680c93e8c2f1b49fb85 100644 --- a/client/src/app/instance/search/components/criteria/cone-search-tab.component.html +++ b/client/src/app/instance/search/components/criteria/cone-search-tab.component.html @@ -16,16 +16,17 @@ <div class="col"> <app-cone-search [coneSearch]="coneSearch" - [resolver]="resolver" + [defaultRadius]="coneSearchConfig.default_radius" + [defaultRaDecUnit]="coneSearchConfig.default_ra_dec_unit" + [resolverEnabled]="coneSearchConfig.resolver_enabled" [resolverIsLoading]="resolverIsLoading" [resolverIsLoaded]="resolverIsLoaded" - (retrieveCoordinates)="retrieveCoordinates.emit($event)" #cs> + (retrieveCoordinates)="retrieveCoordinates.emit($event)" + (emitAdd)="emitAdd(cs.getConeSearch())" + #cs> </app-cone-search> </div> <div class="col-2 text-center align-self-end"> - <button class="btn btn-outline-success" *ngIf="!coneSearch" [hidden]="cs.form.invalid" (click)="addConeSearch.emit(cs.getConeSearch())"> - <span class="fas fa-plus fa-fw"></span> - </button> <button class="btn btn-outline-danger" *ngIf="coneSearch" (click)="deleteConeSearch.emit()"> <span class="fa fa-times fa-fw"></span> </button> diff --git a/client/src/app/instance/search/components/criteria/cone-search-tab.component.spec.ts b/client/src/app/instance/search/components/criteria/cone-search-tab.component.spec.ts index f268da6353db89672ea076ecf666d81806a1067b..7299cc4bff92495fb4402b28f0653b0d62433632 100644 --- a/client/src/app/instance/search/components/criteria/cone-search-tab.component.spec.ts +++ b/client/src/app/instance/search/components/criteria/cone-search-tab.component.spec.ts @@ -14,14 +14,13 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { AccordionModule } from 'ngx-bootstrap/accordion'; import { ConeSearchTabComponent } from './cone-search-tab.component'; -import { ConeSearch, Resolver } from '../../../store/models'; +import { ConeSearch } from '../../../store/models'; import { DatasetByNamePipe } from '../../../../shared/pipes/dataset-by-name.pipe'; describe('[Instance][Search][Component][Criteria] ConeSearchTabComponent', () => { @Component({ selector: 'app-cone-search', template: '' }) class ConeSearchStubComponent { @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; } diff --git a/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts b/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts index fb0e71b89a86404b32e4e178efe52b1e60284052..4d24cc79446c5ec4580ff3a313881d8d96a9a2f1 100644 --- a/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts +++ b/client/src/app/instance/search/components/criteria/cone-search-tab.component.ts @@ -10,7 +10,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; import { ConeSearchConfig, Dataset } from 'src/app/metamodel/models'; -import { ConeSearch, Resolver } from 'src/app/instance/store/models'; +import { ConeSearch, coneSearchToString } from 'src/app/instance/store/models'; /** * @class @@ -26,10 +26,24 @@ export class ConeSearchTabComponent { @Input() datasetList: Dataset[]; @Input() coneSearch: ConeSearch; @Input() coneSearchConfig: ConeSearchConfig; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; @Output() addConeSearch: EventEmitter<ConeSearch> = new EventEmitter(); + @Output() updateConeSearch: EventEmitter<ConeSearch> = new EventEmitter(); @Output() deleteConeSearch: EventEmitter<{ }> = new EventEmitter(); @Output() retrieveCoordinates: EventEmitter<string> = new EventEmitter(); + + /** + * Emits event to add or update cone-search. + * + * @fires EventEmitter<ConeSearch> + */ + emitAdd(newConeSearch: ConeSearch): void { + if (!this.coneSearch) { + this.addConeSearch.emit(newConeSearch); + } + if (this.coneSearch && coneSearchToString(this.coneSearch) !== coneSearchToString(newConeSearch)) { + this.updateConeSearch.emit(newConeSearch); + } + } } diff --git a/client/src/app/instance/search/components/criteria/criteria-by-family.component.html b/client/src/app/instance/search/components/criteria/criteria-by-family.component.html index fa4bc0823c2528089f3fa980ec930dacec8997eb..59dc44c48450c09d258524a2c901aa72bfa2ecd3 100644 --- a/client/src/app/instance/search/components/criteria/criteria-by-family.component.html +++ b/client/src/app/instance/search/components/criteria/criteria-by-family.component.html @@ -4,6 +4,7 @@ [criterion]="getCriterion(attribute.id)" [criteriaList]="criteriaList" (addCriterion)="emitAdd($event)" + (updateCriterion)="emitUpdate($event)" (deleteCriterion)="emitDelete($event)"> </app-criterion> </div> diff --git a/client/src/app/instance/search/components/criteria/criteria-by-family.component.spec.ts b/client/src/app/instance/search/components/criteria/criteria-by-family.component.spec.ts index adcc1587adf9f7f2aae7869f794eb4842d8f6fe1..c2863548af82d3e378fee2881678fe7ab749e9e4 100644 --- a/client/src/app/instance/search/components/criteria/criteria-by-family.component.spec.ts +++ b/client/src/app/instance/search/components/criteria/criteria-by-family.component.spec.ts @@ -197,6 +197,8 @@ describe('[Instance][Search][Component][Criteria] CriteriaByFamilyComponent', () order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, diff --git a/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts b/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts index edc3ae5cc773c6c0afe38b7bc2b14f4217283bad..fa8c7617c6a89bb65eb4eff253797b3fb0b44fac 100644 --- a/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts +++ b/client/src/app/instance/search/components/criteria/criteria-by-family.component.ts @@ -25,6 +25,7 @@ export class CriteriaByFamilyComponent { @Input() attributeList: Attribute[]; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); /** @@ -60,6 +61,17 @@ export class CriteriaByFamilyComponent { this.addCriterion.emit(criterion); } + /** + * Emits event to update the given criterion to the criteria list. + * + * @param {Criterion} updatedCriterion - The updated criterion. + * + * @fires EventEmitter<Criterion> + */ + emitUpdate(updatedCriterion: Criterion): void { + this.updateCriterion.emit(updatedCriterion); + } + /** * Emits event to remove the given criterion ID from the criteria list. * 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 fa9d3aef3286c6ac5d3fb9cdd32279b4c00f2d3b..da39e6820fb4dcd3947b8bd2830b0a3603cf1729 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 @@ -17,6 +17,7 @@ [attributeList]="attributeList | attributeListByFamily:family.id" [criteriaList]="criteriaList" (addCriterion)="emitAdd($event)" + (updateCriterion)="emitUpdate($event)" (deleteCriterion)="emitDelete($event)"> </app-criteria-by-family> </accordion-group> diff --git a/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts b/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts index f781372a5cf74bd91196d2375ff945b629262937..a11d3b6be64f7e0a70c6253c64bee4d8c53593f2 100644 --- a/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts +++ b/client/src/app/instance/search/components/criteria/criteria-tabs.component.ts @@ -26,6 +26,7 @@ export class CriteriaTabsComponent { @Input() criteriaFamilyList: CriteriaFamily[]; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); /** @@ -39,6 +40,17 @@ export class CriteriaTabsComponent { this.addCriterion.emit(criterion); } + /** + * Emits event to update the given criterion to the criteria list. + * + * @param {Criterion} updatedCriterion - The updated criterion. + * + * @fires EventEmitter<Criterion> + */ + emitUpdate(updatedCriterion: Criterion): void { + this.updateCriterion.emit(updatedCriterion); + } + /** * Emits event to remove the given criterion ID to the criteria list. * diff --git a/client/src/app/instance/search/components/criteria/criterion.component.html b/client/src/app/instance/search/components/criteria/criterion.component.html index f9249c619b86339377989b806c7bef02cf295fea..a20b44c936b8d7ed0be717e29cc66fc63ca3c512 100644 --- a/client/src/app/instance/search/components/criteria/criterion.component.html +++ b/client/src/app/instance/search/components/criteria/criterion.component.html @@ -6,9 +6,6 @@ <ng-template searchType></ng-template> </div> <div class="col-2 text-center align-self-center"> - <button class="btn btn-outline-success" *ngIf="!criterion" [hidden]="!searchTypeComponent.isValid() && !searchTypeComponent.nullOrNotNull" (click)="emitAdd()"> - <span class="fas fa-plus fa-fw"></span> - </button> <button class="btn btn-outline-danger" *ngIf="criterion" (click)="deleteCriterion.emit(attribute.id)"> <span class="fa fa-times fa-fw"></span> </button> diff --git a/client/src/app/instance/search/components/criteria/criterion.component.ts b/client/src/app/instance/search/components/criteria/criterion.component.ts index 245f6fba7466aaba222547c067c764facfa8ad8c..26d4e8175cb8e64d6f944250fe225ba7ede726a0 100644 --- a/client/src/app/instance/search/components/criteria/criterion.component.ts +++ b/client/src/app/instance/search/components/criteria/criterion.component.ts @@ -12,6 +12,7 @@ import { Component, Input, Output, EventEmitter, ViewChild, SimpleChanges, OnIni import { Attribute } from 'src/app/metamodel/models'; import { Criterion, FieldCriterion } from 'src/app/instance/store/models'; import { SearchTypeLoaderDirective, AbstractSearchTypeComponent, getSearchTypeComponent } from './search-type'; +import { criterionToString } from 'src/app/instance/store/models'; @Component({ selector: 'app-criterion', @@ -22,6 +23,7 @@ export class CriterionComponent implements OnInit, OnChanges { @Input() criterion: Criterion; @Input() criteriaList: Criterion[]; @Output() addCriterion: EventEmitter<Criterion> = new EventEmitter(); + @Output() updateCriterion: EventEmitter<Criterion> = new EventEmitter(); @Output() deleteCriterion: EventEmitter<number> = new EventEmitter(); @ViewChild(SearchTypeLoaderDirective, {static: true}) SearchTypeLoaderDirective!: SearchTypeLoaderDirective; @@ -30,12 +32,19 @@ export class CriterionComponent implements OnInit, OnChanges { ngOnInit() { const viewContainerRef = this.SearchTypeLoaderDirective.viewContainerRef; + viewContainerRef.clear(); const componentRef = viewContainerRef.createComponent<AbstractSearchTypeComponent>( getSearchTypeComponent(this.attribute.search_type) ); componentRef.instance.setAttribute(this.attribute); componentRef.instance.setCriterion(this.criterion); componentRef.instance.setCriteriaList(this.criteriaList); + componentRef.instance.emitAdd.subscribe(() => this.emitAdd()); + componentRef.instance.emitDelete.subscribe(() => { + if (this.criterion) { + this.deleteCriterion.emit(this.criterion.id) + } + }); this.searchTypeComponent = componentRef.instance; } @@ -65,6 +74,14 @@ export class CriterionComponent implements OnInit, OnChanges { } else { criterion = this.searchTypeComponent.getCriterion(); } - this.addCriterion.emit(criterion); + + const existingCriterion = this.criteriaList.find(c => c.id === criterion.id) + if (existingCriterion) { + if (criterionToString(existingCriterion) !== criterionToString(criterion)) { + this.updateCriterion.emit(criterion); + } + } else { + this.addCriterion.emit(criterion); + } } } diff --git a/client/src/app/instance/search/components/criteria/search-criteria-list.component.html b/client/src/app/instance/search/components/criteria/search-criteria-list.component.html index a5525f7c7e0fa4165e98f9e38f5989b982b07ea4..a21a17b8512eef4143f9003a456b332c2cd10b01 100644 --- a/client/src/app/instance/search/components/criteria/search-criteria-list.component.html +++ b/client/src/app/instance/search/components/criteria/search-criteria-list.component.html @@ -1,35 +1,38 @@ -<accordion class="panel card sticky-top search_criteria_list" [isAnimated]="true"> - <accordion-group #cs panelClass="abstract-accordion lead" [isOpen]="true" class="mt-2"> - <button class="btn btn-link btn-block clearfix pb-1" accordion-heading> - <div class="pull-left float-left font-weight-bold"> - <h4>Search criteria on {{ dataset.label }} - <span *ngIf="cs.isOpen"> - <span class="fas fa-chevron-up"></span> - </span> - <span *ngIf="!cs.isOpen"> - <span class="fas fa-chevron-down"></span> - </span></h4> +<div class="search-info jumbotron row mx-0 mb-4 py-4 sticky-top search_criteria_list"> + <div class="col"> + <div class="row mb-2"> + <div class="lead"> + <span class="font-weight-bold">Search criteria on {{ dataset.label }}</span> + <p *ngIf="!coneSearch && !(criteriaList.length > 0)" class="font-italic mt-2">No criteria selected</p> + <accordion class="panel" [isAnimated]="true" *ngIf="coneSearch || criteriaList.length > 0"> + <accordion-group #cl panelClass="abstract-accordion lead" [isOpen]="true" class="mt-2"> + <button class="btn btn-link btn-block clearfix pb-1" accordion-heading> + <div class="pull-left float-left font-weight-bold"> + <p class="mb-0">Search criteria + <span *ngIf="cl.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!cl.isOpen"> + <span class="fas fa-chevron-down"></span> + </span></p> + </div> + </button> + <app-cone-search-parameters *ngIf="coneSearch" + [coneSearch]="coneSearch"> + </app-cone-search-parameters> + <app-criteria-list-parameters *ngIf="criteriaList.length > 0" + [criteriaList]="criteriaList" + [attributeList]="attributeList"> + </app-criteria-list-parameters> + </accordion-group> + </accordion> </div> - </button> - - <p *ngIf="!coneSearch && criteriaList.length < 1"> - To add search criteria, fill fields in the form bellow and click on the - <strong><span class="fas fa-plus fa-fw"></span></strong> button for each - search constraint. To remove a constraint click on the - <strong><span class="fas fa-times fa-fw"></span></strong>. - </p> - <app-cone-search-parameters *ngIf="coneSearch" - [coneSearch]="coneSearch" - [backgroundColor]="instance.design_color"> - </app-cone-search-parameters> - <app-criteria-list-parameters *ngIf="criteriaList.length > 0" - [criteriaList]="criteriaList" - [attributeList]="attributeList" - [backgroundColor]="instance.design_color"> - </app-criteria-list-parameters> - <p class="last">Once you have added your search criteria, if any, you can - <a routerLink="/instance/{{ instance.name }}/search/output/{{ datasetSelected }}" [queryParams]="queryParams"> - select the columns to display</a>. - </p> - </accordion-group> -</accordion> + </div> + <div *ngIf="instance.search_info_help_enabled" class="row"> + <p>Once you have added your search criteria, if any, you can select the + <a class="btn btn-outline-primary" routerLink="/instance/{{ instance.name }}/search/output/{{ datasetSelected }}" [queryParams]="queryParams"> + output columns <span class="fas fa-arrow-right"></span></a> + </p> + </div> + </div> +</div> diff --git a/client/src/app/instance/search/components/criteria/search-criteria-list.component.scss b/client/src/app/instance/search/components/criteria/search-criteria-list.component.scss index 974ee7f43c278b5c76d0367f946f558f2c20ba3f..2539d804ce7bc591b1d0419602600175cdc96093 100644 --- a/client/src/app/instance/search/components/criteria/search-criteria-list.component.scss +++ b/client/src/app/instance/search/components/criteria/search-criteria-list.component.scss @@ -1,11 +1,3 @@ .search_criteria_list { top: 100px; - padding: 0.75rem 1.25rem; - background-color: rgba(247, 247, 247, 0.95); - border-bottom: 1px solid rgba(0, 0, 0, 0.125); - margin-bottom: 1em; -} -.last { - clear: both; - padding-top: 0.5em; } diff --git a/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts b/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts index 2ef2b50d64685e780185810cff8751ab25acd572..8bbf855f58576b8616bb295bf70c8872db6e13d1 100644 --- a/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/abstract-search-type.component.ts @@ -7,24 +7,41 @@ * file that was distributed with this source code. */ -import { Directive } from '@angular/core'; +import { Directive, EventEmitter, OnInit, OnDestroy } from '@angular/core'; import { UntypedFormGroup } from '@angular/forms'; import { Attribute } from 'src/app/metamodel/models'; import { Criterion } from 'src/app/instance/store/models'; import { searchTypeOperators } from 'src/app/shared/utils'; +import { debounceTime, Subscription } from 'rxjs'; @Directive() -export abstract class AbstractSearchTypeComponent { +export abstract class AbstractSearchTypeComponent implements OnInit, OnDestroy { attribute: Attribute; criteriaList: Criterion[]; + emitAdd: EventEmitter<{}> = new EventEmitter<{}>(); + emitDelete: EventEmitter<{}> = new EventEmitter<{}>(); form: UntypedFormGroup; + formValueChangesSubscription: Subscription; operators = searchTypeOperators; nullOrNotNull: string = ''; constructor() { } + ngOnInit() { + this.formValueChangesSubscription = this.form.valueChanges.pipe( + debounceTime(300), + ) + .subscribe(() => { + if (this.isValid()) { + this.emitAdd.emit(); + } else { + this.emitDelete.emit(); + } + }); + } + setAttribute(attribute: Attribute) { this.attribute = attribute; } @@ -32,10 +49,9 @@ export abstract class AbstractSearchTypeComponent { setCriterion(criterion: Criterion) { if (criterion) { this.form.patchValue(criterion); - this.form.disable(); } else { - this.form.enable(); this.form.reset(); + this.enable(); this.nullOrNotNull = ''; } } @@ -71,4 +87,8 @@ export abstract class AbstractSearchTypeComponent { return 'number'; } } + + ngOnDestroy(): void { + this.formValueChangesSubscription.unsubscribe(); + } } diff --git a/client/src/app/instance/search/components/criteria/search-type/between.component.ts b/client/src/app/instance/search/components/criteria/search-type/between.component.ts index 9df636547f7c037a189a8ec9ce6488942eaa5727..4095d96be9acbb05970b7fabaeab3cad0200f27a 100644 --- a/client/src/app/instance/search/components/criteria/search-type/between.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/between.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component } from '@angular/core'; +import { Component} from '@angular/core'; import { UntypedFormGroup, UntypedFormControl, Validators } from '@angular/forms'; import { AbstractSearchTypeComponent } from './abstract-search-type.component'; @@ -56,7 +56,8 @@ export class BetweenComponent extends AbstractSearchTypeComponent { return { id: this.attribute.id, type: 'between', - ...this.form.value + min: (this.form.controls.min.value) ? this.form.controls.min.value : null, + max: (this.form.controls.max.value) ? this.form.controls.max.value : null, } as BetweenCriterion; } @@ -87,7 +88,10 @@ export class BetweenComponent extends AbstractSearchTypeComponent { } isValid() { - return this.form.controls.min.value || this.form.controls.max.value; + return this.form.controls.min.value + || this.form.controls.max.value + || this.form.controls.label.value === 'nl' + || this.form.controls.label.value === 'nnl'; } labelOnChange() { diff --git a/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts index 69aa61b31fc26ea3405f7de2f544c76aaf912a61..e969245e8fb27e6f02f4e48e7d2c8bd3c1b0233a 100644 --- a/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/checkbox.component.ts @@ -82,7 +82,9 @@ export class CheckboxComponent extends AbstractSearchTypeComponent { isValid(): boolean { const selected = this.getCheckboxes().value; const values = [...this.attribute.options.filter((option, index) => selected[index])]; - return values.length > 0; + return values.length > 0 + || this.form.controls.label.value === 'nl' + || this.form.controls.label.value === 'nnl'; } /** diff --git a/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts b/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts index 8af34f3626a85aafc7e5dbf6c8be63003c94a944..7182a2e4200d8efba372661ed761c2a432f9e5e4 100644 --- a/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/datalist.component.ts @@ -55,13 +55,6 @@ export class DatalistComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - /** * Return placeholder. * diff --git a/client/src/app/instance/search/components/criteria/search-type/date.component.ts b/client/src/app/instance/search/components/criteria/search-type/date.component.ts index a86ed3a0dcdfbfe8956b9299ad430ce6166fe4c0..cc43f07232e05030bad282804a102b1f4e2d59fe 100644 --- a/client/src/app/instance/search/components/criteria/search-type/date.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/date.component.ts @@ -67,13 +67,6 @@ export class DateComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - /** * Return placeholder. * diff --git a/client/src/app/instance/search/components/criteria/search-type/datetime.component.ts b/client/src/app/instance/search/components/criteria/search-type/datetime.component.ts index 2e8ab01d5b4c28c833279ca20244ce7a695b2f3e..91f7235ee19324e6cb329de7abaf88f38814a5cb 100644 --- a/client/src/app/instance/search/components/criteria/search-type/datetime.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/datetime.component.ts @@ -78,13 +78,6 @@ export class DateTimeComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - /** * Returns string array to represent the given time. * diff --git a/client/src/app/instance/search/components/criteria/search-type/field.component.ts b/client/src/app/instance/search/components/criteria/search-type/field.component.ts index 7d0e74271cc7515c66f91d41cd7dd33430a1395c..c3d2a87b56641993b0c8ec77bd0d800093e48414 100644 --- a/client/src/app/instance/search/components/criteria/search-type/field.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/field.component.ts @@ -56,13 +56,6 @@ export class FieldComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - operatorOnChange() { if (this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl') { this.form.controls.value.disable(); diff --git a/client/src/app/instance/search/components/criteria/search-type/radio.component.ts b/client/src/app/instance/search/components/criteria/search-type/radio.component.ts index e8bd853fa115c1ee9bf13a6c54018596c5427362..439f31d2de5e3c89f2ae34003e3e40931a1a7662 100644 --- a/client/src/app/instance/search/components/criteria/search-type/radio.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/radio.component.ts @@ -65,13 +65,6 @@ export class RadioComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - operatorOnChange() { if (this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl') { this.form.controls.radio.disable(); diff --git a/client/src/app/instance/search/components/criteria/search-type/select.component.ts b/client/src/app/instance/search/components/criteria/search-type/select.component.ts index d9a20cda84260382145c9e162a18fe744590bab5..4276e583b544c725e22c44b7d0ec5e09c2a473f0 100644 --- a/client/src/app/instance/search/components/criteria/search-type/select.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/select.component.ts @@ -63,13 +63,6 @@ export class SelectComponent extends AbstractSearchTypeComponent { isValid(): boolean { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } operatorOnChange() { if (this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl') { diff --git a/client/src/app/instance/search/components/criteria/search-type/time.component.ts b/client/src/app/instance/search/components/criteria/search-type/time.component.ts index 24fb5846760e6992ba12ae2f3950bcc8eeed1eaf..e209a859188b12772d91d6b5e224e83cebf66512 100644 --- a/client/src/app/instance/search/components/criteria/search-type/time.component.ts +++ b/client/src/app/instance/search/components/criteria/search-type/time.component.ts @@ -73,13 +73,6 @@ export class TimeComponent extends AbstractSearchTypeComponent { return this.form.valid || this.form.controls.operator.value === 'nl' || this.form.controls.operator.value === 'nnl'; } - enable() { - super.enable(); - if (!this.attribute.dynamic_operator) { - this.form.controls.operator.disable(); - } - } - /** * Returns string array to represent the given time. * diff --git a/client/src/app/instance/search/components/dataset/dataset-card.component.html b/client/src/app/instance/search/components/dataset/dataset-card.component.html index eebb222ef4271d8069adb962538442ef1363c253..f1882c3f0490134f8fce7af6e0532c1784d011b3 100644 --- a/client/src/app/instance/search/components/dataset/dataset-card.component.html +++ b/client/src/app/instance/search/components/dataset/dataset-card.component.html @@ -14,7 +14,7 @@ <div class="col-auto"> <button *ngIf="dataset.name !== datasetSelected && isDatasetAccessible()" (click)="selectDataset(dataset.name)" - class="btn btn-outline-secondary"> + class="dataset-select-btn btn btn-outline-secondary"> <span *ngIf="!dataset.public" class="fa-solid fa-lock-open"></span> <span *ngIf="dataset.public" class="fa-solid fa-globe"></span> Select @@ -22,8 +22,8 @@ <button *ngIf="!isDatasetAccessible()" class="btn btn-outline-danger disabled" title="You are not authorized to access this dataset"> <span class="fa-solid fa-lock"></span> Private </button> - <span *ngIf="dataset.name === datasetSelected"> - <span class="far fa-check-circle fa-2x text-success"></span> + <span *ngIf="dataset.name === datasetSelected" class="search-dataset-selected"> + <span class="far fa-check-circle fa-2x"></span> </span> </div> </div> diff --git a/client/src/app/instance/search/components/index.ts b/client/src/app/instance/search/components/index.ts index 34843871fca4c5dbe8806550909fd4c0d6dbe259..dc7ef8c7eb68fe12ac295cc44611394aea110739 100644 --- a/client/src/app/instance/search/components/index.ts +++ b/client/src/app/instance/search/components/index.ts @@ -9,7 +9,6 @@ import { ProgressBarComponent } from './progress-bar.component'; import { AttributeLabelComponent } from './attribute-label.component'; -import { ConeSearchParametersComponent } from './cone-search-parameters.component'; import { CriteriaListParametersComponent } from './criteria-list-parameters.component'; import { datasetComponents } from './dataset'; import { criteriaComponents } from './criteria'; @@ -20,7 +19,6 @@ import { resultComponents } from './result'; export const dummiesComponents = [ ProgressBarComponent, AttributeLabelComponent, - ConeSearchParametersComponent, CriteriaListParametersComponent, OutputInfoComponent, datasetComponents, 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 dde866cbd63129c3e857a9eabf9c585876badd09..4921404c34302a9b1c8ae38958c1c364274439a0 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 @@ -2,13 +2,13 @@ <div class="row mb-1"> <div class="col pr-1"> <button (click)="selectAll()" [disabled]="isAllSelected" - class="btn btn-sm btn-block btn-outline-secondary letter-spacing"> + class="select-all btn btn-sm btn-block btn-outline-secondary letter-spacing"> Select All </button> </div> <div class="col pl-1"> <button (click)="unselectAll()" [disabled]="isAllUnselected" - class="btn btn-sm btn-block btn-outline-secondary letter-spacing"> + class="select-all btn btn-sm btn-block btn-outline-secondary letter-spacing"> Unselect All </button> </div> @@ -17,7 +17,7 @@ <div *ngFor="let attribute of attributeList"> <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" [ngStyle]="{ 'color': designColor }"></span> + <span class="fas fa-fw fa-check-square output_columns_selected"></span> <app-attribute-label [label]="attribute.form_label" [description]="attribute.description"></app-attribute-label> </button> diff --git a/client/src/app/instance/search/components/output/output-by-category.component.scss b/client/src/app/instance/search/components/output/output-by-category.component.scss index 0320f4ee3952557490ecdf470b7f784fea48a595..3eb9eff26fb3f77f046da53dc4758eba6709e007 100644 --- a/client/src/app/instance/search/components/output/output-by-category.component.scss +++ b/client/src/app/instance/search/components/output/output-by-category.component.scss @@ -12,6 +12,7 @@ overflow-y: auto; border: 1px solid #ced4da; border-radius: .25rem; + background-color: white; } .letter-spacing { diff --git a/client/src/app/instance/search/components/output/output-by-category.component.spec.ts b/client/src/app/instance/search/components/output/output-by-category.component.spec.ts index f207fa77884ef96d3239638c0abc7b3ac4be3f10..0734df83bef997d31a1e2da874182bd906a8a2b2 100644 --- a/client/src/app/instance/search/components/output/output-by-category.component.spec.ts +++ b/client/src/app/instance/search/components/output/output-by-category.component.spec.ts @@ -78,6 +78,8 @@ describe('[Instance][Search][Component][Output] OutputByCategoryComponent', () = order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -112,6 +114,8 @@ describe('[Instance][Search][Component][Output] OutputByCategoryComponent', () = order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -155,6 +159,8 @@ describe('[Instance][Search][Component][Output] OutputByCategoryComponent', () = order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -189,6 +195,8 @@ describe('[Instance][Search][Component][Output] OutputByCategoryComponent', () = order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, 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 84e593e1c6c898738b2c6702f4d7d7f64aca74f3..7ccac74c3ff16ad7ebe223ba64a3fd108f6c3956 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,7 +25,6 @@ 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 b880a0bbcee55e3f10209d38eee79ed8dc96f0ab..ab978a3cd3b812b871e0940a128340ae688952d2 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 @@ -4,8 +4,7 @@ <app-output-by-category [categoryLabel]="category.label" [attributeList]="getAttributeByCategory(category.id)" - [outputList]="outputList" - [designColor]="designColor" + [outputList]="outputList" [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.spec.ts b/client/src/app/instance/search/components/output/output-by-family.component.spec.ts index 7d51fae6a93f71051e7842dfd8244af0b3af36fa..7e27b8335785fb22f2cde14841c99f1661f9b149 100644 --- a/client/src/app/instance/search/components/output/output-by-family.component.spec.ts +++ b/client/src/app/instance/search/components/output/output-by-family.component.spec.ts @@ -101,6 +101,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -135,6 +137,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -176,6 +180,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -210,6 +216,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -251,6 +259,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -285,6 +295,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -326,6 +338,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -360,6 +374,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -401,6 +417,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -435,6 +453,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -476,6 +496,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -510,6 +532,8 @@ describe('[Instance][Search][Component][Output] OutputByFamilyComponent', () => order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, 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 522f090ccb589a067c04f402608b92730a5b824a..a5adc6fec96d574c3379b900ee3459ea8a2f501e 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,7 +25,6 @@ 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-info.component.html b/client/src/app/instance/search/components/output/output-info.component.html index a1ddb49c091da843c50cda57be5ada611bbd9a4c..cd50f0b14b52af0cede2c75226917e8d62d358bc 100644 --- a/client/src/app/instance/search/components/output/output-info.component.html +++ b/client/src/app/instance/search/components/output/output-info.component.html @@ -1,20 +1,18 @@ -<accordion class="panel card sticky-top top_information_list" [isAnimated]="true"> - <accordion-group #cs panelClass="abstract-accordion lead" [isOpen]="true" class="mt-2"> - <button class="btn btn-link btn-block clearfix pb-1" accordion-heading> - <div class="pull-left float-left font-weight-bold"> - <h4>Output column selection for {{ dataset.label }} - <span *ngIf="cs.isOpen"> - <span class="fas fa-chevron-up"></span> - </span> - <span *ngIf="!cs.isOpen"> - <span class="fas fa-chevron-down"></span> - </span></h4> +<div *ngIf="instance.search_info_help_enabled" class="search-info jumbotron row mx-0 mb-4 py-4 sticky-top output-info"> + <div class="col"> + <div class="row mb-2"> + <div class="lead"> + <span class="font-weight-bold">Output column selection for {{ dataset.label }}</span> </div> - </button> - - <p>Here you can customise the list of the table columns you want to display in the result - table. You can then - <a routerLink="/instance/{{ instanceSelected }}/search/result/{{ datasetSelected }}" [queryParams]="queryParams" - >display the results</a>.</p> - </accordion-group> -</accordion> + </div> + <div class="row"> + <p> + Here you can customise the list of the table columns you want to display in the result + table. You can then display the + <a class="btn btn-outline-primary" routerLink="/instance/{{ instance.name }}/search/result/{{ datasetSelected }}" [queryParams]="queryParams"> + result table <span class="fas fa-arrow-right"></span> + </a> + </p> + </div> + </div> +</div> diff --git a/client/src/app/instance/search/components/output/output-info.component.scss b/client/src/app/instance/search/components/output/output-info.component.scss index 15e2ed4d3dfed83fa9c5b96773ec68b09c6da4a9..271849f13a22bcd098ef397c69ab94f5c8abc558 100644 --- a/client/src/app/instance/search/components/output/output-info.component.scss +++ b/client/src/app/instance/search/components/output/output-info.component.scss @@ -1,7 +1,3 @@ -accordion { +.output-info { top: 100px; - padding: 0.75rem 1.25rem; - background-color: rgba(247, 247, 247, 0.95); - border-bottom: 1px solid rgba(0, 0, 0, 0.125); - margin-bottom: 1em; } diff --git a/client/src/app/instance/search/components/output/output-info.component.ts b/client/src/app/instance/search/components/output/output-info.component.ts index cb283d2a25ac681c987bcfed5785bce8dda0080a..ea4e997dcfcbc5f96db6cc6e21f62e1821fb89fe 100644 --- a/client/src/app/instance/search/components/output/output-info.component.ts +++ b/client/src/app/instance/search/components/output/output-info.component.ts @@ -8,16 +8,17 @@ */ import { Component, Input } from '@angular/core'; -import {SearchQueryParams} from 'src/app/instance/store/models'; -import {Dataset} from 'src/app/metamodel/models'; + +import { SearchQueryParams } from 'src/app/instance/store/models'; +import { Instance, Dataset } from 'src/app/metamodel/models'; @Component({ - selector: 'app-output-info', - templateUrl: './output-info.component.html', - styleUrls: ['./output-info.component.scss'] + selector: 'app-output-info', + templateUrl: './output-info.component.html', + styleUrls: ['./output-info.component.scss'] }) export class OutputInfoComponent { - @Input() instanceSelected: String; + @Input() instance: Instance; @Input() dataset: Dataset; @Input() datasetSelected: String; @Input() queryParams: SearchQueryParams; 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 597dfc4065bff1e2e573b712c713603045e5ae71..1d29737861c6947d2645cfe1528a968314d1ebe7 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 @@ -13,7 +13,6 @@ [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 28cdb42f1657d686e11d1954b6eb5b2606e4db00..fb7f25a51ea94f7308567b7438532a1b9343c518 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 @@ -25,6 +25,5 @@ export class OutputTabsComponent { @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/progress-bar.component.html b/client/src/app/instance/search/components/progress-bar.component.html index 2ace1c67facae51e76a5f1bdad2b1c6128bf844e..ba5d6ecf577756726edd3e8a42e17101362f3650 100644 --- a/client/src/app/instance/search/components/progress-bar.component.html +++ b/client/src/app/instance/search/components/progress-bar.component.html @@ -1,75 +1,44 @@ <div class="row text-center"> <div class="col"> - <h1 [ngStyle]="{'color': instance.progress_bar_title_color }">{{ instance.progress_bar_title }}</h1> - <p [ngStyle]="{'color': instance.progress_bar_subtitle_color }">{{ instance.progress_bar_subtitle }}</p> + <h1 class="progress-bar-title">{{ instance.progress_bar_title }}</h1> + <p class="progress-bar-subtitle">{{ instance.progress_bar_subtitle }}</p> </div> </div> <div class="progress-navigation"> - <div class="progress progress-with-circle" [ngStyle]="{'background-color': instance.progress_bar_color }"> - <div class="progress-bar" - [ngClass]="getStepClass()" - [ngStyle]="{'background-color': instance.progress_bar_active_color }" - role="progressbar" - aria-valuenow="1" - aria-valuemin="1" - aria-valuemax="4"> - </div> + <div class="progress progress-with-circle"> + <div class="progress-bar" [ngClass]="getStepClass()" role="progressbar"></div> </div> <ul class="nav nav-pills"> <li class="nav-item checked" [ngClass]="{'active': currentStep === 'dataset'}"> - <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)"> + <a class="nav-link" routerLink="/instance/{{ instance.name }}/search/dataset/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-book"></span> </div> - Dataset selection + {{ instance.progress_bar_step_dataset_title }} </a> </li> - <li id="criteriaStep" class="nav-item" [ngClass]="{'active': currentStep === 'criteria', 'checked': criteriaStepChecked}"> - <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)"> + <li class="nav-item" [ngClass]="{'active': currentStep === 'criteria', 'checked': criteriaStepChecked}"> + <a class="nav-link" [ngClass]="{'disabled': !datasetSelected}" routerLink="/instance/{{ instance.name }}/search/criteria/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-filter"></span> </div> - Search criteria - </a> - <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> - Search criteria + {{ instance.progress_bar_step_criteria_title }} </a> </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'output', 'checked': outputStepChecked}"> - <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)"> + <a class="nav-link" [ngClass]="{'disabled': !datasetSelected}" routerLink="/instance/{{ instance.name }}/search/output/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-eye"></span> </div> - Output columns - </a> - <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 columns + {{ instance.progress_bar_step_output_title }} </a> </li> <li class="nav-item" [ngClass]="{'active': currentStep === 'result', 'checked': resultStepChecked}"> - <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 table - </a> - <a *ngIf="!datasetSelected" class="nav-link" [ngClass]="{'disabled': !datasetSelected}" [ngStyle]="getNavItemAStyle('result', resultStepChecked)" data-toggle="tab"> - <div class="icon-circle" [ngStyle]="getNavItemIconCircleStyle('result', resultStepChecked)"> + <a class="nav-link" [ngClass]="{'disabled': outputList.length < 1}" routerLink="/instance/{{ instance.name }}/search/result/{{ datasetSelected }}" [queryParams]="queryParams" data-toggle="tab"> + <div class="icon-circle"> <span class="fas fa-table"></span> </div> - Result table + {{ instance.progress_bar_step_result_title }} </a> </li> </ul> 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 598ec57556e067b29c66651168fc10794fd9d4ce..e71bbb619d741db243f7e0c8166ec68620dc50b6 100644 --- a/client/src/app/instance/search/components/progress-bar.component.scss +++ b/client/src/app/instance/search/components/progress-bar.component.scss @@ -27,9 +27,9 @@ transition: width .3s ease; } -.nav-link { +/* .nav-link { font-weight: bold; -} +} */ .nav-pills { background-color: #F3F2EE; @@ -42,9 +42,7 @@ .nav-pills li a { padding: 0; - //max-width: 78px; margin: 0 auto; - color: rgba(0, 0, 0, 0.2); border-radius: 50%; position: relative; top: -32px; @@ -86,6 +84,7 @@ top: 23px; } +/* Progressbar active coloration */ .datasetStep { width: 11%; } @@ -101,11 +100,3 @@ .resultStep { width: 100%; } - -.btn-clear-form span { - display: none; -} - -.btn-clear-form:hover span { - display: inline; -} diff --git a/client/src/app/instance/search/components/progress-bar.component.spec.ts b/client/src/app/instance/search/components/progress-bar.component.spec.ts index 5934b27f7eb696711f74028c8cd54166e8142d00..2457abdcc37041ae9eba653b688fe77a0f7a6c12 100644 --- a/client/src/app/instance/search/components/progress-bar.component.spec.ts +++ b/client/src/app/instance/search/components/progress-bar.component.spec.ts @@ -45,150 +45,4 @@ describe('[Instance][Search][Component] ProgressBarComponent', () => { style = component.getStepClass(); expect(style).toBe('resultStep'); }); - - it('#getNavItemAStyle() should return link color theme', () => { - component.instance = { - name: 'myInstance', - label: 'My Instance', - description: 'My Instance description', - scientific_manager: 'M. Dupont', - instrument: 'Multiple', - wavelength_domain: 'Visible', - display: 10, - data_path: 'data/path', - files_path: 'files', - public: true, - portal_logo: 'logo.png', - design_color: 'green', - design_background_color: 'darker green', - design_logo: 'path/to/logo', - design_favicon: 'path/to/favicon', - navbar_background_color: '#F8F9FA', - navbar_border_bottom_color: '#DEE2E6', - navbar_color_href: '#000000', - footer_background_color: '#F8F9FA', - footer_border_top_color: '#DEE2E6', - footer_text_color: '#000000', - family_border_color: '#DFDFDF', - family_header_background_color: '#F7F7F7', - family_title_color: '#007BFF', - family_title_bold: false, - family_background_color: '#FFFFFF', - family_color: '#212529', - progress_bar_title: 'Dataset search', - progress_bar_title_color: '#000000', - progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', - progress_bar_subtitle_color: '#6C757D', - progress_bar_color: '#E9ECEF', - progress_bar_active_color: '#7AC29A', - progress_bar_circle_color: '#FFFFFF', - progress_bar_circle_icon_color: '#CCCCCC', - progress_bar_circle_icon_active_color: '#FFFFFF', - progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', - result_datatable_bordered: true, - result_datatable_border_color: '#DEE2E6', - result_datatable_header_background_color: '#FFFFFF', - result_datatable_header_text_color: '#000000', - result_datatable_rows_background_color: '#FFFFFF', - result_datatable_rows_text_color: '#000000', - result_datatable_sorted_color: '#C5C5C5', - result_datatable_sorted_active_color: '#000000', - result_datatable_link_color: '#007BFF', - result_datatable_link_hover_color: '#0056B3', - result_datatable_rows_selected_color: '#7AC29A', - samp_enabled: true, - back_to_portal: true, - user_menu_enabled: true, - search_by_criteria_allowed: true, - search_by_criteria_label: 'Search', - search_multiple_allowed: true, - search_multiple_label: 'Search multiple', - search_multiple_all_datasets_selected: false, - documentation_allowed: true, - documentation_label: 'Documentation', - nb_dataset_families: 1, - nb_datasets: 2 - }; - component.currentStep = 'a'; - expect(component.getNavItemAStyle('b', false)).toEqual({"color": "#91B2BF"}); - expect(component.getNavItemAStyle('b', true)).toEqual({ color: '#7AC29A' }); - }); - - it('#getNavItemIconCircleStyle() should return circle color theme', () => { - component.instance = { - name: 'myInstance', - label: 'My Instance', - description: 'My Instance description', - scientific_manager: 'M. Dupont', - instrument: 'Multiple', - wavelength_domain: 'Visible', - display: 10, - data_path: 'data/path', - files_path: 'files', - public: true, - portal_logo: 'logo.png', - design_color: 'green', - design_background_color: 'darker green', - design_logo: 'path/to/logo', - design_favicon: 'path/to/favicon', - navbar_background_color: '#F8F9FA', - navbar_border_bottom_color: '#DEE2E6', - navbar_color_href: '#000000', - footer_background_color: '#F8F9FA', - footer_border_top_color: '#DEE2E6', - footer_text_color: '#000000', - family_border_color: '#DFDFDF', - family_header_background_color: '#F7F7F7', - family_title_color: '#007BFF', - family_title_bold: false, - family_background_color: '#FFFFFF', - family_color: '#212529', - progress_bar_title: 'Dataset search', - progress_bar_title_color: '#000000', - progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', - progress_bar_subtitle_color: '#6C757D', - progress_bar_color: '#E9ECEF', - progress_bar_active_color: '#7AC29A', - progress_bar_circle_color: '#FFFFFF', - progress_bar_circle_icon_color: '#CCCCCC', - progress_bar_circle_icon_active_color: '#FFFFFF', - progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', - result_datatable_bordered: true, - result_datatable_border_color: '#DEE2E6', - result_datatable_header_background_color: '#FFFFFF', - result_datatable_header_text_color: '#000000', - result_datatable_rows_background_color: '#FFFFFF', - result_datatable_rows_text_color: '#000000', - result_datatable_sorted_color: '#C5C5C5', - result_datatable_sorted_active_color: '#000000', - result_datatable_link_color: '#007BFF', - result_datatable_link_hover_color: '#0056B3', - result_datatable_rows_selected_color: '#7AC29A', - samp_enabled: true, - back_to_portal: true, - user_menu_enabled: true, - search_by_criteria_allowed: true, - search_by_criteria_label: 'Search', - search_multiple_allowed: true, - search_multiple_label: 'Search multiple', - search_multiple_all_datasets_selected: false, - documentation_allowed: true, - documentation_label: 'Documentation', - nb_dataset_families: 1, - nb_datasets: 2 - }; - component.currentStep = 'a'; - expect(component.getNavItemIconCircleStyle('a', false)).toEqual({ 'background-color': '#7AC29A', 'border-color': '#7AC29A', 'color': '#FFFFFF' }); - expect(component.getNavItemIconCircleStyle('b', true)).toEqual({ 'color': '#7AC29A', 'border-color': '#7AC29A', 'background-color': '#FFFFFF' }); - }); }); 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 6bdd6b9c02c7befb3807e1ffd54de9ee1569d0a9..461e23728c9ca792f73465568c35c8423702bb61 100644 --- a/client/src/app/instance/search/components/progress-bar.component.ts +++ b/client/src/app/instance/search/components/progress-bar.component.ts @@ -51,44 +51,4 @@ export class ProgressBarComponent { return 'datasetStep'; } } - - /** - * Returns link color theme. - * - * @return { color: string } | null - */ - getNavItemAStyle(currentStep: string, checked: boolean): { color: string } | null { - if (this.currentStep === currentStep || checked) { - return { - 'color': this.instance.progress_bar_active_color - } - } else { - return { - 'color': this.instance.progress_bar_text_color - } - } - } - - /** - * Returns circle color theme. - * - * @return { } - */ - getNavItemIconCircleStyle(currentStep: string, checked: boolean): {} { - let style = {}; - if (this.currentStep === currentStep) { - style['border-color'] = this.instance.progress_bar_active_color; - style['background-color'] = this.instance.progress_bar_active_color; - style['color'] = this.instance.progress_bar_circle_icon_active_color; - } else if (checked) { - style['background-color'] = this.instance.progress_bar_circle_color; - style['border-color'] = this.instance.progress_bar_active_color; - style['color'] = this.instance.progress_bar_active_color; - } else { - style['border-color'] = this.instance.progress_bar_color; - style['background-color'] = this.instance.progress_bar_circle_color; - style['color'] = this.instance.progress_bar_circle_icon_color; - } - return style; - } } diff --git a/client/src/app/instance/search/components/result/datatable-actions.component.html b/client/src/app/instance/search/components/result/datatable-actions.component.html index fd173437885bbe0526e6e829caf99ec4b5fffcab..28a1284a1d25e77a850bdfdbe4d17f0cb07aa2a1 100644 --- a/client/src/app/instance/search/components/result/datatable-actions.component.html +++ b/client/src/app/instance/search/components/result/datatable-actions.component.html @@ -1,5 +1,5 @@ <div *ngIf="dataset.datatable_selectable_rows" class="btn-group mb-2" dropdown [isDisabled]="selectedData.length < 1"> - <button id="button-basic" dropdownToggle type="button" class="btn btn-primary dropdown-toggle" + <button id="button-basic" dropdownToggle type="button" class="btn-datatable-actions btn btn-primary dropdown-toggle" aria-controls="dropdown-basic"> <span *ngIf="!selectedData.length">Actions on selected rows (select rows first)</span> <span *ngIf="selectedData.length">Actions on {{selectedData.length}} rows </span> diff --git a/client/src/app/instance/search/components/result/datatable.component.html b/client/src/app/instance/search/components/result/datatable.component.html index 732e19d461085fe62f02e9417c4cdd9c9b5164d5..c3a26ca6232be6e79b4f7fa9f5320e98573a435d 100644 --- a/client/src/app/instance/search/components/result/datatable.component.html +++ b/client/src/app/instance/search/components/result/datatable.component.html @@ -1,14 +1,14 @@ <app-spinner *ngIf="dataIsLoading"></app-spinner> -<div class="table-responsive" *ngIf="dataIsLoaded"> +<div class="datatable-responsive table-responsive" *ngIf="dataIsLoaded"> <table id="datatable" class="table table-hover" [ngClass]="{'table-bordered': instance.result_datatable_bordered}" aria-describedby="List of results"> <thead> - <tr [ngStyle]="{ 'background-color': instance.result_datatable_header_background_color, 'color': instance.result_datatable_header_text_color }"> + <tr> <th *ngIf="dataset.datatable_selectable_rows" scope="col" class="select">#</th> <th *ngFor="let attribute of getOutputList()" scope="col" draggable="true" class="datatable-title"> <app-attribute-label [label]="attribute.label" [description]="attribute.description"></app-attribute-label> - <span *ngIf="attribute.id === sortedCol && attribute.order_by" class="pl-2" class="clickable" (click)="sort(attribute.id)" [ngStyle]="{ 'color': instance.result_datatable_sorted_active_color, 'background-color': instance.result_datatable_header_background_color }"> + <span *ngIf="attribute.id === sortedCol && attribute.order_by" class="pl-2 clickable column-sorted" (click)="sort(attribute.id)"> <span [ngClass]="{'active': sortedOrder === 'a', 'inactive': sortedOrder === 'd'}"> <span class="fas fa-fw fa-sort-amount-down-alt"></span> </span> @@ -16,11 +16,11 @@ <span class="fas fa-fw fa-sort-amount-up"></span> </span> </span> - <span *ngIf="attribute.id !== sortedCol && attribute.order_by" class="pl-2" class="clickable" (click)="sort(attribute.id)"> - <span class="unsorted" [ngStyle]="{ 'color': instance.result_datatable_sorted_color }"> + <span *ngIf="attribute.id !== sortedCol && attribute.order_by" class="pl-2 clickable click-to-sort" (click)="sort(attribute.id)"> + <span class="unsorted"> <span class="fas fa-fw fa-arrows-alt-v"></span> </span> - <span class="on-hover" [ngStyle]="{ 'color': instance.result_datatable_sorted_color, 'background-color': instance.result_datatable_header_background_color }"> + <span class="on-hover"> <span class="fas fa-fw fa-sort-amount-down-alt"></span> </span> </span> @@ -28,7 +28,7 @@ </tr> </thead> <tbody> - <tr *ngFor="let datum of data" [ngStyle]="{'background-color': datumSelectedInPlot(datum) ? instance.result_datatable_rows_selected_color : instance.result_datatable_rows_background_color, 'color': instance.result_datatable_rows_text_color }"> + <tr *ngFor="let datum of data" [ngClass]="{'datum-selected-in-plot': datumSelectedInPlot(datum)}"> <td *ngIf="dataset.datatable_selectable_rows" class="data-selected align-middle" (click)="toggleSelection(datum)"> <button class="btn btn-block text-left p-0 m-0"> @@ -36,19 +36,20 @@ <span class="far fa-square fa-lg text-secondary"></span> </span> <span *ngIf="isSelected(datum)"> - <span class="fas fa-check-square fa-lg" [ngStyle]="{ 'color': instance.result_datatable_rows_selected_color }"></span> + <span class="fas fa-check-square fa-lg checked"></span> </span> </button> </td> <td *ngFor="let attribute of getOutputList()" class="align-middle"> - <app-renderer + <app-display-result-renderer + [rendererType]="'result'" [value]="datum[attribute.label]" [dataset]="dataset" [instance]="instance" [attribute]="attribute" [queryParams]="queryParams" (downloadFile)="downloadFile.emit($event)"> - </app-renderer> + </app-display-result-renderer> </td> </tr> </tbody> diff --git a/client/src/app/instance/search/components/result/datatable.component.scss b/client/src/app/instance/search/components/result/datatable.component.scss index 57929e9388bd884018777955624457aeabc5122c..e93df4067f2c6d8c64ec946541f51b5cb3f388b2 100644 --- a/client/src/app/instance/search/components/result/datatable.component.scss +++ b/client/src/app/instance/search/components/result/datatable.component.scss @@ -17,11 +17,11 @@ table th:not(.select) { } .over-left { - border-left: 3px dotted #666; + border-left: 3px dotted #666 !important; } .over-right { - border-right: 3px dotted #666; + border-right: 3px dotted #666 !important; } .data-selected { diff --git a/client/src/app/instance/search/components/result/datatable.component.spec.ts b/client/src/app/instance/search/components/result/datatable.component.spec.ts index 5a4c640c0bff2b95c7d8dd459c93618f61373cf3..cae274206a1409c6f36d03bfb8d44726c581ca2d 100644 --- a/client/src/app/instance/search/components/result/datatable.component.spec.ts +++ b/client/src/app/instance/search/components/result/datatable.component.spec.ts @@ -143,6 +143,8 @@ describe('[Instance][Search][Component][Result] DatatableComponent', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/instance/search/components/result/renderer.component.html b/client/src/app/instance/search/components/result/display-result-renderer.component.html similarity index 100% rename from client/src/app/instance/search/components/result/renderer.component.html rename to client/src/app/instance/search/components/result/display-result-renderer.component.html diff --git a/client/src/app/instance/search/components/result/display-result-renderer.component.ts b/client/src/app/instance/search/components/result/display-result-renderer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..565f7b85434ec9c56fb75638118fc65d4bd9851c --- /dev/null +++ b/client/src/app/instance/search/components/result/display-result-renderer.component.ts @@ -0,0 +1,24 @@ +/** + * 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, Type } from '@angular/core'; + +import { AbstractDisplayRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-display-renderer.component'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; +import { getResultRendererComponent } from './renderer'; + +@Component({ + selector: 'app-display-result-renderer', + templateUrl: 'display-result-renderer.component.html' +}) +export class DisplayResultRendererComponent extends AbstractDisplayRendererComponent { + getRendererComponent(renderer: string): Type<AbstractRendererComponent> { + return getResultRendererComponent(renderer); + } +} diff --git a/client/src/app/instance/search/components/result/index.ts b/client/src/app/instance/search/components/result/index.ts index 175e098cefd615d49a068d6d755a7353895a235b..f624c7affc3c6de1aa40c2dac877f30ded9e1513 100644 --- a/client/src/app/instance/search/components/result/index.ts +++ b/client/src/app/instance/search/components/result/index.ts @@ -14,7 +14,7 @@ import { DatatableActionsComponent } from './datatable-actions.component'; import { UrlDisplayComponent } from './url-display.component'; import { DatatableComponent } from './datatable.component'; import { ConeSearchPlotComponent } from './cone-search-plot.component'; -import { RendererComponent } from './renderer.component'; +import { DisplayResultRendererComponent } from './display-result-renderer.component'; import { ConeSearchImageComponent } from './cone-search-image.component'; import { rendererComponents } from './renderer'; @@ -26,7 +26,7 @@ export const resultComponents = [ DatatableActionsComponent, ConeSearchPlotComponent, DownloadResultComponent, - RendererComponent, + DisplayResultRendererComponent, ConeSearchImageComponent, rendererComponents ]; diff --git a/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.html b/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.html index fc275d821bd8e1cad35785b55adc0f83e746210e..d8f206aaeefcca276dea1e67b34601ec00d0710a 100644 --- a/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.html +++ b/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.html @@ -1,5 +1,5 @@ <a *ngIf="value" routerLink="/instance/{{ instance.name }}/search/detail/{{ dataset.name }}/{{ value }}" [queryParams]="queryParams" - [ngClass]="{'btn btn-outline-primary btn-sm' : getConfig().display == 'text-button'}"> + [ngClass]="{'btn btn-outline-primary btn-sm btn-block' : getConfig().display == 'text-button'}"> {{ value }} </a> diff --git a/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.ts b/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.ts index 86897a58952d06c20752e78b6b5e429312031fe0..f1ad4b4b13a0f51f7b69fb358247e34046bf8de7 100644 --- a/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.ts +++ b/client/src/app/instance/search/components/result/renderer/detail-link-renderer.component.ts @@ -9,7 +9,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; import { DetailLinkRendererConfig } from 'src/app/metamodel/models/renderers/detail-link-renderer-config.model'; /** diff --git a/client/src/app/instance/search/components/result/renderer/index.ts b/client/src/app/instance/search/components/result/renderer/index.ts index 89f6bf2c7615fd7a1a3f88638c533c9c4942af44..bf53faaed8905aee54a093bff8d3d2ef675cbb79 100644 --- a/client/src/app/instance/search/components/result/renderer/index.ts +++ b/client/src/app/instance/search/components/result/renderer/index.ts @@ -7,54 +7,23 @@ * file that was distributed with this source code. */ -import { RendererLoaderDirective } from './renderer-loader.directive'; -import { DefaultRendererComponent } from './default-renderer.component'; -import { DetailLinkRendererComponent } from './detail-link-renderer.component'; -import { LinkRendererComponent } from './link-renderer.component'; -import { DownloadRendererComponent } from './download-renderer.component'; -import { ImageRendererComponent } from './image-renderer.component'; -import { JsonRendererComponent } from './json-renderer.component'; +import { Type } from '@angular/core'; -export * from './abstract-renderer.component'; -export * from './renderer-loader.directive'; +import { DetailLinkRendererComponent } from './detail-link-renderer.component'; +import { getRendererComponent } from 'src/app/instance/search/shared-renderer/components'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; export const rendererComponents = [ - RendererLoaderDirective, - DefaultRendererComponent, - DetailLinkRendererComponent, - LinkRendererComponent, - DownloadRendererComponent, - ImageRendererComponent, - JsonRendererComponent + DetailLinkRendererComponent ]; -export const getRendererComponent = (renderer: string) => { - let nameOfRendererComponent = null; +export const getResultRendererComponent = (renderer: string): Type<AbstractRendererComponent> => { + let nameOfRendererComponent = getRendererComponent(renderer); switch(renderer) { case 'detail-link': { nameOfRendererComponent = DetailLinkRendererComponent; break; } - case 'link': { - nameOfRendererComponent = LinkRendererComponent; - break; - } - case 'download': { - nameOfRendererComponent = DownloadRendererComponent; - break; - } - case 'image': { - nameOfRendererComponent = ImageRendererComponent; - break; - } - case 'json': { - nameOfRendererComponent = JsonRendererComponent; - break; - } - default: { - nameOfRendererComponent = DefaultRendererComponent; - break; - } } return nameOfRendererComponent; } diff --git a/client/src/app/instance/search/components/result/result-info.component.html b/client/src/app/instance/search/components/result/result-info.component.html index 6d2ccfe269bf62ecf9c81b265c64cf91f4794b13..796463e343e5525cba5133578b624810c8584912 100644 --- a/client/src/app/instance/search/components/result/result-info.component.html +++ b/client/src/app/instance/search/components/result/result-info.component.html @@ -18,15 +18,11 @@ </div> </button> <app-cone-search-parameters *ngIf="coneSearch" - [coneSearch]="coneSearch" - [backgroundColor]="instance.design_color" - [ngStyle]="{'font-size': '16px' }"> + [coneSearch]="coneSearch"> </app-cone-search-parameters> <app-criteria-list-parameters *ngIf="criteriaList.length > 0" [criteriaList]="criteriaList" - [attributeList]="attributeList" - [backgroundColor]="instance.design_color" - [ngStyle]="{'font-size': '16px' }"> + [attributeList]="attributeList"> </app-criteria-list-parameters> </accordion-group> </accordion> diff --git a/client/src/app/instance/search/containers/abstract-search.component.spec.ts b/client/src/app/instance/search/containers/abstract-search.component.spec.ts index b304927b12119b87fa5d65eb8c08358f25c105aa..4e3998c24dc72fbeae81b0cbfa79e3fc78849618 100644 --- a/client/src/app/instance/search/containers/abstract-search.component.spec.ts +++ b/client/src/app/instance/search/containers/abstract-search.component.spec.ts @@ -25,10 +25,6 @@ describe('[Instance][Search][Container] AbstractSearchComponent', () => { ngOnInit() { super.ngOnInit(); } - - ngOnDestroy() { - super.ngOnDestroy(); - } } let component: MyFakeComponent; @@ -54,17 +50,9 @@ describe('[Instance][Search][Container] AbstractSearchComponent', () => { const spy = jest.spyOn(store, 'dispatch'); component.ngOnInit(); Promise.resolve(null).then(function() { - expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith(searchActions.initSearch()); - expect(spy).toHaveBeenCalledWith(searchActions.loadDefaultFormParameters()); done(); }); }); - - it('#ngOnDestroy() should unsubscribe from attributeListIsLoadedSubscription', () => { - component.attributeListIsLoadedSubscription = of().subscribe(); - const spy = jest.spyOn(component.attributeListIsLoadedSubscription, 'unsubscribe'); - component.ngOnDestroy(); - expect(spy).toHaveBeenCalledTimes(1); - }); }); diff --git a/client/src/app/instance/search/containers/abstract-search.component.ts b/client/src/app/instance/search/containers/abstract-search.component.ts index 265889220b952045aec693857c240e266365a9cb..685141f2ee5311182dfb660bd1aa98f8ce83cd10 100644 --- a/client/src/app/instance/search/containers/abstract-search.component.ts +++ b/client/src/app/instance/search/containers/abstract-search.component.ts @@ -7,13 +7,13 @@ * file that was distributed with this source code. */ -import { Directive, OnInit, OnDestroy } from '@angular/core'; +import { Directive, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; -import { Observable, Subscription } from 'rxjs'; +import { Observable } from 'rxjs'; import { ConeSearch, Criterion, SearchQueryParams } from '../../store/models'; -import { Dataset, Attribute, CriteriaFamily, OutputFamily, OutputCategory } from 'src/app/metamodel/models'; +import { Instance, Dataset, Attribute, CriteriaFamily, OutputFamily, OutputCategory } 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'; @@ -34,9 +34,10 @@ import * as coneSearchSelector from '../../store/selectors/cone-search.selector' * @implements OnDestroy */ @Directive() -export abstract class AbstractSearchComponent implements OnInit, OnDestroy { +export abstract class AbstractSearchComponent implements OnInit { public datasetSelected: Observable<string>; public instanceSelected: Observable<string>; + public instance: Observable<Instance>; public datasetListIsLoading: Observable<boolean>; public datasetListIsLoaded: Observable<boolean>; public datasetList: Observable<Dataset[]>; @@ -58,11 +59,11 @@ export abstract class AbstractSearchComponent implements OnInit, OnDestroy { public outputList: Observable<number[]>; public queryParams: Observable<SearchQueryParams>; public coneSearch: Observable<ConeSearch>; - public attributeListIsLoadedSubscription: Subscription; constructor(protected store: Store<{ }>) { this.datasetSelected = store.select(datasetSelector.selectDatasetNameByRoute); this.instanceSelected = store.select(instanceSelector.selectInstanceNameByRoute); + this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.datasetListIsLoading = store.select(datasetSelector.selectDatasetListIsLoading); this.datasetListIsLoaded = store.select(datasetSelector.selectDatasetListIsLoaded); this.datasetList = store.select(datasetSelector.selectAllDatasets); @@ -90,14 +91,5 @@ export abstract class AbstractSearchComponent implements OnInit, OnDestroy { // 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(searchActions.initSearch())); - this.attributeListIsLoadedSubscription = this.attributeListIsLoaded.subscribe(attributeListIsLoaded => { - if (attributeListIsLoaded) { - Promise.resolve(null).then(() => this.store.dispatch(searchActions.loadDefaultFormParameters())); - } - }); - } - - ngOnDestroy(): void { - if (this.attributeListIsLoadedSubscription) this.attributeListIsLoadedSubscription.unsubscribe(); } } diff --git a/client/src/app/instance/search/containers/criteria.component.html b/client/src/app/instance/search/containers/criteria.component.html index 41898accec3adaef3dea3bd317a9ebf33ac50876..73ce251929f86be36df218a7da3115767ca85017 100644 --- a/client/src/app/instance/search/containers/criteria.component.html +++ b/client/src/app/instance/search/containers/criteria.component.html @@ -22,10 +22,10 @@ [datasetList]="datasetList | async" [coneSearch]="coneSearch | async" [coneSearchConfig]="coneSearchConfig | async" - [resolver]="resolver | async" [resolverIsLoading]="resolverIsLoading | async" [resolverIsLoaded]="resolverIsLoaded | async" (addConeSearch)="addConeSearch($event)" + (updateConeSearch)="updateConeSearch($event)" (deleteConeSearch)="deleteConeSearch()" (retrieveCoordinates)="retrieveCoordinates($event)"> </app-cone-search-tab> @@ -34,6 +34,7 @@ [criteriaFamilyList]="criteriaFamilyList | async" [criteriaList]="criteriaList | async" (addCriterion)="addCriterion($event)" + (updateCriterion)="updateCriterion($event)" (deleteCriterion)="deleteCriterion($event)"> </app-criteria-tabs> </div> @@ -43,14 +44,14 @@ <div class="col"> <a routerLink="/instance/{{ instanceSelected | async }}/search/dataset/{{ datasetSelected | async }}" [queryParams]="queryParams | async" - class="btn btn-outline-secondary"> - <span class="fas fa-arrow-left"></span> Dataset selection + class="search-back btn btn-outline-secondary"> + <span class="fas fa-arrow-left"></span> {{ (instance | async).progress_bar_step_dataset_title }} </a> </div> <div class="col col-auto"> <a routerLink="/instance/{{ instanceSelected | async }}/search/output/{{ datasetSelected | async }}" [queryParams]="queryParams | async" - class="btn btn-outline-primary"> - Output columns <span class="fas fa-arrow-right"></span> + class="search-next btn btn-outline-primary"> + {{ (instance | async).progress_bar_step_output_title }} <span class="fas fa-arrow-right"></span> </a> </div> </div> diff --git a/client/src/app/instance/search/containers/criteria.component.spec.ts b/client/src/app/instance/search/containers/criteria.component.spec.ts index 350bcf906f561c51984411f8af0753e83ef76d14..cbc3aeaed785b3a3259ac8ae33307453a4e3995c 100644 --- a/client/src/app/instance/search/containers/criteria.component.spec.ts +++ b/client/src/app/instance/search/containers/criteria.component.spec.ts @@ -15,7 +15,7 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { CriteriaComponent } from './criteria.component'; import { Attribute, CriteriaFamily, Dataset, OutputCategory, OutputFamily } from '../../../metamodel/models'; -import { ConeSearch, Criterion, Resolver, SearchQueryParams, SvomKeyword } from '../../store/models'; +import { ConeSearch, Criterion, SearchQueryParams, SvomKeyword } from '../../store/models'; import { SortByCriteriaDisplayPipe } from '../pipes/sort-by-criteria-display.pipe'; import * as searchActions from '../../store/actions/search.actions'; import { AbstractSearchComponent } from './abstract-search.component'; @@ -31,7 +31,6 @@ describe('[Instance][Search][Container] CriteriaComponent', () => { @Input() datasetSelected: string; @Input() datasetList: Dataset[]; @Input() coneSearch: ConeSearch; - @Input() resolver: Resolver; @Input() resolverIsLoading: boolean; @Input() resolverIsLoaded: boolean; } @@ -90,10 +89,9 @@ describe('[Instance][Search][Container] CriteriaComponent', () => { jest.spyOn(AbstractSearchComponent.prototype, 'ngOnInit').mockReturnThis(); component.ngOnInit(); Promise.resolve(null).then(function() { - expect(spy).toHaveBeenCalledTimes(3); + expect(spy).toHaveBeenCalledTimes(2); expect(spy).toHaveBeenCalledWith(searchActions.changeStep({ step: 'criteria' })); expect(spy).toHaveBeenCalledWith(searchActions.checkCriteria()); - expect(spy).toHaveBeenCalledWith(coneSearchConfigActions.loadConeSearchConfig()); done(); }); }); diff --git a/client/src/app/instance/search/containers/criteria.component.ts b/client/src/app/instance/search/containers/criteria.component.ts index b850069b983d64d58700eff797aa1e0224e890c9..cb78817b14fc9b92861d1e10a7a99f1a789e9fb8 100644 --- a/client/src/app/instance/search/containers/criteria.component.ts +++ b/client/src/app/instance/search/containers/criteria.component.ts @@ -14,14 +14,13 @@ import { Observable } from 'rxjs'; import { AbstractSearchComponent } from './abstract-search.component'; import { ConeSearchConfig, Dataset, Instance } from 'src/app/metamodel/models'; -import { ConeSearch, Criterion, Resolver } from '../../store/models'; +import { ConeSearch, Criterion } from '../../store/models'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; +import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; import * as searchActions from '../../store/actions/search.actions'; import * as coneSearchActions from '../../store/actions/cone-search.actions'; import * as coneSearchSelector from '../../store/selectors/cone-search.selector'; -import * as coneSearchConfigActions from 'src/app/metamodel/actions/cone-search-config.actions'; -import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; /** * @class @@ -32,9 +31,7 @@ import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-sear templateUrl: 'criteria.component.html' }) export class CriteriaComponent extends AbstractSearchComponent { - public instance: Observable<Instance>; public dataset: Observable<Dataset>; - public resolver: Observable<Resolver>; public resolverIsLoading: Observable<boolean>; public resolverIsLoaded: Observable<boolean>; public coneSearchConfig: Observable<ConeSearchConfig>; @@ -43,9 +40,7 @@ export class CriteriaComponent extends AbstractSearchComponent { constructor(protected store: Store<{ }>) { super(store); - this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.dataset = store.select(datasetSelector.selectDatasetByRouteName); - this.resolver = this.store.select(coneSearchSelector.selectResolver); this.resolverIsLoading = this.store.select(coneSearchSelector.selectResolverIsLoading); this.resolverIsLoaded = this.store.select(coneSearchSelector.selectResolverIsLoaded); this.coneSearchConfig = store.select(coneSearchConfigSelector.selectConeSearchConfig); @@ -58,7 +53,6 @@ export class CriteriaComponent extends AbstractSearchComponent { // This micro task prevent the expression has changed after view init error Promise.resolve(null).then(() => this.store.dispatch(searchActions.changeStep({ step: 'criteria' }))); Promise.resolve(null).then(() => this.store.dispatch(searchActions.checkCriteria())); - Promise.resolve(null).then(() => this.store.dispatch(coneSearchConfigActions.loadConeSearchConfig())); super.ngOnInit(); } @@ -71,6 +65,15 @@ export class CriteriaComponent extends AbstractSearchComponent { this.store.dispatch(searchActions.addCriterion({ criterion })); } + /** + * Dispatches action to update the given criterion to the search. + * + * @param {Criterion} updatedCriterion - The updated criterion. + */ + updateCriterion(updatedCriterion: Criterion): void { + this.store.dispatch(searchActions.updateCriterion({ updatedCriterion })) + } + /** * Dispatches action to remove the given criterion ID to the search. * @@ -89,6 +92,15 @@ export class CriteriaComponent extends AbstractSearchComponent { this.store.dispatch(coneSearchActions.addConeSearch({ coneSearch })); } + /** + * Dispatches action to update cone search. + * + * @param {ConeSearch} coneSearch - The cone search. + */ + updateConeSearch(coneSearch: ConeSearch): void { + this.store.dispatch(coneSearchActions.updateConeSearch({ coneSearch })); + } + /** * Dispatches action to remove the cone search. */ diff --git a/client/src/app/instance/search/containers/dataset.component.html b/client/src/app/instance/search/containers/dataset.component.html index 819d307f8ee879dfaa4c8ab2246f5e7c2fe15f69..c5b44cc162e190045193c30d4cfa4cde55622e9c 100644 --- a/client/src/app/instance/search/containers/dataset.component.html +++ b/client/src/app/instance/search/containers/dataset.component.html @@ -35,7 +35,7 @@ <div *ngIf="datasetSelected | async" class="row mt-5 justify-content-end"> <div class="col col-auto"> <a routerLink="/instance/{{ instanceSelected | async}}/search/criteria/{{ datasetSelected | async }}" [queryParams]="queryParams | async" - class="btn btn-outline-primary">Search criteria <span class="fas fa-arrow-right"></span> + class="search-next btn btn-outline-primary">{{ (instance | async).progress_bar_step_criteria_title }} <span class="fas fa-arrow-right"></span> </a> </div> </div> diff --git a/client/src/app/instance/search/containers/dataset.component.spec.ts b/client/src/app/instance/search/containers/dataset.component.spec.ts index c52aefb6c988c2423f331b2c93435be8fc139c72..68c0e8df07802abdff23d21a0a84535ff8b98c27 100644 --- a/client/src/app/instance/search/containers/dataset.component.spec.ts +++ b/client/src/app/instance/search/containers/dataset.component.spec.ts @@ -91,17 +91,9 @@ describe('[Instance][Search][Container] DatasetComponent', () => { jest.spyOn(AbstractSearchComponent.prototype, 'ngOnInit').mockReturnThis(); component.ngOnInit(); Promise.resolve(null).then(function() { - expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledTimes(1); expect(spy).toHaveBeenCalledWith(searchActions.changeStep({ step: 'dataset' })); - expect(spy).toHaveBeenCalledWith(searchActions.initSearch()); done(); }); }); - - it('#ngOnDestroy() should unsubscribe from datasetSelectedSubscription', () => { - component.datasetSelectedSubscription = of().subscribe(); - const spy = jest.spyOn(component.datasetSelectedSubscription, 'unsubscribe'); - component.ngOnDestroy(); - expect(spy).toHaveBeenCalledTimes(1); - }); }); diff --git a/client/src/app/instance/search/containers/dataset.component.ts b/client/src/app/instance/search/containers/dataset.component.ts index 7f24ff31fb884edf0baca82f354dcb01064422aa..25f1c2b55e185a6fba2c53cdc1b1122a0d2dc7a4 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, Subscription } from 'rxjs'; +import { Observable } from 'rxjs'; import { AbstractSearchComponent } from './abstract-search.component'; import { DatasetFamily, DatasetGroup } from 'src/app/metamodel/models'; @@ -37,7 +37,6 @@ export class DatasetComponent extends AbstractSearchComponent { public datasetGroupList: Observable<DatasetGroup[]>; public datasetGroupListIsLoading: Observable<boolean>; public datasetGroupListIsLoaded: Observable<boolean>; - public datasetSelectedSubscription: Subscription; constructor(protected store: Store<{ }>, private config: AppConfigService) { super(store); @@ -55,11 +54,6 @@ export class DatasetComponent extends AbstractSearchComponent { // 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(searchActions.changeStep({ step: 'dataset' }))); - this.datasetSelectedSubscription = this.datasetSelected.subscribe(datasetSelected => { - if (datasetSelected) { - Promise.resolve(null).then(() => this.store.dispatch(searchActions.initSearch())); - } - }) super.ngOnInit(); } @@ -80,9 +74,4 @@ export class DatasetComponent extends AbstractSearchComponent { getAdminRoles(): string[] { return this.config.adminRoles; } - - ngOnDestroy(): void { - if (this.datasetSelectedSubscription) 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 9db7529281aa90542c11116d6f669396ee99649f..0e4cfa8ad12fa7c21ac28199390f4a53b94bdf90 100644 --- a/client/src/app/instance/search/containers/output.component.html +++ b/client/src/app/instance/search/containers/output.component.html @@ -8,7 +8,7 @@ && (outputCategoryListIsLoaded | async)" class="row mt-4"> <div class="col-12"> <app-output-info - [instanceSelected]="instanceSelected | async" + [instance]="instance | async" [dataset]="dataset | async" [datasetSelected]="datasetSelected | async" [queryParams]="queryParams | async"> @@ -18,7 +18,6 @@ [outputFamilyList]="outputFamilyList | async" [outputCategoryList]="outputCategoryList | async" [outputList]="outputList | async" - [designColor]="(instance | async).design_color" (change)="updateOutputList($event)"> </app-output-tabs> </div> @@ -27,19 +26,19 @@ <div class="row mt-5 justify-content-between"> <div class="col"> <a routerLink="/instance/{{ instanceSelected | async }}/search/criteria/{{ datasetSelected | async }}" [queryParams]="queryParams | async" - class="btn btn-outline-secondary"> - <span class="fas fa-arrow-left"></span> Search criteria + class="search-back btn btn-outline-secondary"> + <span class="fas fa-arrow-left"></span> {{ (instance | async).progress_bar_step_criteria_title }} </a> </div> <!-- Simplifier ? --> <div class="col col-auto"> - <button *ngIf="(outputList | async).length < 1; else notEmpty" class="btn btn-outline-primary disabled not-allowed" title="At least 1 output required!"> - Result table <span class="fas fa-arrow-right"></span> + <button *ngIf="(outputList | async).length < 1; else notEmpty" class="search-next btn btn-outline-primary disabled not-allowed" title="At least 1 output required!"> + {{ (instance | async).progress_bar_step_result_title }} <span class="fas fa-arrow-right"></span> </button> <ng-template #notEmpty> <a routerLink="/instance/{{ instanceSelected | async }}/search/result/{{ datasetSelected | async }}" [queryParams]="queryParams | async" - class="btn btn-outline-primary"> - Result table <span class="fas fa-arrow-right"></span> + class="search-next btn btn-outline-primary"> + {{ (instance | async).progress_bar_step_result_title }} <span class="fas fa-arrow-right"></span> </a> </ng-template> </div> diff --git a/client/src/app/instance/search/containers/output.component.ts b/client/src/app/instance/search/containers/output.component.ts index e3a20028ca7248d3c3f5198b9ef8244dc2f98b1c..726c6bfe2af3f299226dc993e9f83d3f17e75aee 100644 --- a/client/src/app/instance/search/containers/output.component.ts +++ b/client/src/app/instance/search/containers/output.component.ts @@ -27,12 +27,10 @@ import * as searchActions from '../../store/actions/search.actions'; templateUrl: 'output.component.html' }) export class OutputComponent extends AbstractSearchComponent { - public instance: Observable<Instance>; public dataset: Observable<Dataset>; constructor(protected store: Store<{ }>) { super(store); - this.instance = store.select(instanceSelector.selectInstanceByRouteName); this.dataset = store.select(datasetSelector.selectDatasetByRouteName); } diff --git a/client/src/app/instance/search/containers/result.component.html b/client/src/app/instance/search/containers/result.component.html index 2b28026b00c5c946bc04ee17fa2a0ea649af86c4..dfef4272f5f1d109aa7b5e4aa0a3f1ecc1534a27 100644 --- a/client/src/app/instance/search/containers/result.component.html +++ b/client/src/app/instance/search/containers/result.component.html @@ -19,7 +19,7 @@ </div> </div> <ng-container *ngIf="(dataLength | async) > 0"> - <div class="anis-result-header jumbotron row mb-4 py-4"> + <div class="search-info jumbotron row mx-0 mb-4 py-4"> <div class="col"> <app-result-info [instance]="instance | async" @@ -29,7 +29,7 @@ [criteriaList]="criteriaList | async" [coneSearch]="coneSearch | async"> </app-result-info> - <div class="lead mt-4"> + <div class="lead mt-2"> <app-download-result [instance]="instance | async" [dataset]="dataset | async" @@ -132,8 +132,8 @@ </div> <div class="row mt-5 justify-content-between"> <div class="col"> - <a routerLink="/instance/{{ instanceSelected | async }}/search/output/{{ datasetSelected | async }}" [queryParams]="queryParams | async" class="btn btn-outline-secondary"> - <span class="fas fa-arrow-left"></span> Output columns + <a routerLink="/instance/{{ instanceSelected | async }}/search/output/{{ datasetSelected | async }}" [queryParams]="queryParams | async" class="search-back btn btn-outline-secondary"> + <span class="fas fa-arrow-left"></span> {{ (instance | async).progress_bar_step_output_title }} </a> </div> </div> diff --git a/client/src/app/instance/search/containers/result.component.spec.ts b/client/src/app/instance/search/containers/result.component.spec.ts index d84173c57aaee2907a6edf03bbae93409c914f8a..d89e8504922d10017a6534f256a22cc645be610f 100644 --- a/client/src/app/instance/search/containers/result.component.spec.ts +++ b/client/src/app/instance/search/containers/result.component.spec.ts @@ -124,12 +124,11 @@ describe('[Instance][Search][Container] ResultComponent', () => { jest.spyOn(AbstractSearchComponent.prototype, 'ngOnInit').mockReturnThis(); component.ngOnInit(); Promise.resolve(null).then(function() { - expect(spy).toHaveBeenCalledTimes(5); + expect(spy).toHaveBeenCalledTimes(4); expect(spy).toHaveBeenCalledWith(searchActions.changeStep({ step: 'result' })); expect(spy).toHaveBeenCalledWith(searchActions.checkResult()); - expect(spy).toHaveBeenCalledWith(searchActions.retrieveDataLength()); expect(spy).toHaveBeenCalledWith(imageActions.loadImageList()); - expect(spy).toHaveBeenCalledWith(coneSearchConfigActions.loadConeSearchConfig()); + expect(spy).toHaveBeenCalledWith(searchActions.retrieveDataLength()); done(); }); }); diff --git a/client/src/app/instance/search/containers/result.component.ts b/client/src/app/instance/search/containers/result.component.ts index a24e7e583414bbdd0e7334cf726511b6e589ae2b..1f0d7dbbdf625bde1c0105de200ade814c564049 100644 --- a/client/src/app/instance/search/containers/result.component.ts +++ b/client/src/app/instance/search/containers/result.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; @@ -25,7 +25,6 @@ import * as archiveSelector from '../../store/selectors/archive.selector'; import * as imageActions from 'src/app/metamodel/actions/image.actions'; import * as imageSelector from 'src/app/metamodel/selectors/image.selector'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; -import * as coneSearchConfigActions from 'src/app/metamodel/actions/cone-search-config.actions'; import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; /** @@ -39,8 +38,7 @@ import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-sear selector: 'app-result', templateUrl: 'result.component.html' }) -export class ResultComponent extends AbstractSearchComponent { - public instance: Observable<Instance>; +export class ResultComponent extends AbstractSearchComponent implements OnInit, OnDestroy { public dataset: Observable<Dataset>; public dataLength: Observable<number>; public dataLengthIsLoading: Observable<boolean>; @@ -66,7 +64,6 @@ export class ResultComponent extends AbstractSearchComponent { constructor(protected store: Store<{}>) { super(store); this.dataset = store.select(datasetSelector.selectDatasetByRouteName); - 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); @@ -89,14 +86,13 @@ export class ResultComponent extends AbstractSearchComponent { // This micro task prevent the expression has changed after view init error Promise.resolve(null).then(() => this.store.dispatch(searchActions.changeStep({ step: 'result' }))); Promise.resolve(null).then(() => this.store.dispatch(searchActions.checkResult())); - super.ngOnInit(); + Promise.resolve(null).then(() => this.store.dispatch(imageActions.loadImageList())); this.pristineSubscription = this.pristine.subscribe(pristine => { if (!pristine) { Promise.resolve(null).then(() => this.store.dispatch(searchActions.retrieveDataLength())); } }); - Promise.resolve(null).then(() => this.store.dispatch(imageActions.loadImageList())); - Promise.resolve(null).then(() => this.store.dispatch(coneSearchConfigActions.loadConeSearchConfig())); + super.ngOnInit(); } /** @@ -149,6 +145,11 @@ export class ResultComponent extends AbstractSearchComponent { this.store.dispatch(searchActions.deleteSelectedData({ id })); } + /** + * Dispatches action to launch the file download + * + * @param { url: string, filename: string } download + */ downloadFile(download: { url: string, filename: string }): void { this.store.dispatch(searchActions.downloadFile(download)); } @@ -170,15 +171,6 @@ export class ResultComponent extends AbstractSearchComponent { this.store.dispatch(searchActions.updateOutputList({ outputList })); } - /** - * Dispatches action to destroy search results. - */ - ngOnDestroy(): void { - this.store.dispatch(searchActions.destroyResults()); - this.store.dispatch(archiveActions.resetArchive()); - if (this.pristineSubscription) this.pristineSubscription.unsubscribe(); - super.ngOnDestroy(); - } /** * update image plot background href value * @@ -206,4 +198,13 @@ export class ResultComponent extends AbstractSearchComponent { updateSelectId(id: any) { this.selectId = id; } + + /** + * Dispatches action to destroy search results. + */ + ngOnDestroy(): void { + this.store.dispatch(searchActions.destroyResults()); + this.store.dispatch(archiveActions.resetArchive()); + if (this.pristineSubscription) this.pristineSubscription.unsubscribe(); + } } diff --git a/client/src/app/instance/search/detail/components/detail-content.component.html b/client/src/app/instance/search/detail/components/detail-content.component.html index ab86c2cb330ff13217b5be25c6a9c5b47fca8fab..b87d7144410cbe438e77c1a2968f3001299e0837 100644 --- a/client/src/app/instance/search/detail/components/detail-content.component.html +++ b/client/src/app/instance/search/detail/components/detail-content.component.html @@ -1,5 +1,5 @@ <ngx-dynamic-hooks - class="detail-{{datasetName}}" + class="detail detail-{{dataset.name}}" [content]="detailConfig.content" [parsers]="getParsers()" [context]="getContext()"> diff --git a/client/src/app/instance/search/detail/components/detail-content.component.ts b/client/src/app/instance/search/detail/components/detail-content.component.ts index 3923f1a88ed1f4bf03ba7c9d5dcd5b980c61d01f..2c53aab3b81ccb4eb83f95bdc84d087c3a44b334 100644 --- a/client/src/app/instance/search/detail/components/detail-content.component.ts +++ b/client/src/app/instance/search/detail/components/detail-content.component.ts @@ -9,7 +9,8 @@ import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core'; -import { DetailConfig, Attribute, OutputFamily, OutputCategory } from 'src/app/metamodel/models'; +import { DetailConfig, Attribute, Dataset, OutputFamily, OutputCategory, Instance } from 'src/app/metamodel/models'; +import { SearchQueryParams } from 'src/app/instance/store/models'; import { globalParsers } from 'src/app/shared/dynamic-content'; import { componentParsers } from '../dynamic-content'; import { StyleService } from 'src/app/shared/services/style.service'; @@ -26,21 +27,25 @@ import { StyleService } from 'src/app/shared/services/style.service'; export class DetailContentComponent implements OnInit { @Input() detailConfig: DetailConfig; @Input() object: any; - @Input() datasetName: string; + @Input() dataset: Dataset; + @Input() instance: Instance; @Input() attributeList: Attribute[]; @Input() outputFamilyList: OutputFamily[]; @Input() outputCategoryList: OutputCategory[]; + @Input() queryParams: SearchQueryParams; constructor(private style: StyleService) { } ngOnInit() { - this.style.addCSS( - this.detailConfig.style_sheet.replace( - /(.+{)/g, - (match, $1) => `.detail-${this.datasetName} ${$1}` - ), - 'detail' - ); + if (this.detailConfig.style_sheet) { + this.style.addCSS( + this.detailConfig.style_sheet.replace( + /(.+{)/g, + (match, $1) => `.detail-${this.dataset.name} ${$1}` + ), + 'detail' + ); + } } getParsers() { @@ -53,10 +58,12 @@ export class DetailContentComponent implements OnInit { getContext() { return { object: this.object, - datasetName: this.datasetName, + dataset: this.dataset, + instance: this.instance, attributeList: this.attributeList, outputFamilyList: this.outputFamilyList, - outputCategoryList: this.outputCategoryList + outputCategoryList: this.outputCategoryList, + queryParams: this.queryParams }; } } diff --git a/client/src/app/instance/search/detail/components/display-detail-renderer.component.html b/client/src/app/instance/search/detail/components/display-detail-renderer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..439211e3299a9ef1024ed08e4a0d9ad40494425f --- /dev/null +++ b/client/src/app/instance/search/detail/components/display-detail-renderer.component.html @@ -0,0 +1 @@ +<ng-template renderer></ng-template> diff --git a/client/src/app/instance/search/detail/components/display-detail-renderer.component.ts b/client/src/app/instance/search/detail/components/display-detail-renderer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..c286fb1276ededff4f9689b29bf9cbbcd8ebc2de --- /dev/null +++ b/client/src/app/instance/search/detail/components/display-detail-renderer.component.ts @@ -0,0 +1,24 @@ +/** + * 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, Type } from '@angular/core'; + +import { AbstractDisplayRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-display-renderer.component'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; +import { getDetailRendererComponent } from './renderer'; + +@Component({ + selector: 'app-display-detail-renderer', + templateUrl: 'display-detail-renderer.component.html' +}) +export class DisplayDetailRendererComponent extends AbstractDisplayRendererComponent { + getRendererComponent(renderer: string): Type<AbstractRendererComponent> { + return getDetailRendererComponent(renderer); + } +} diff --git a/client/src/app/instance/search/detail/components/index.ts b/client/src/app/instance/search/detail/components/index.ts index 0dcbf58e5e5f4fdf19dfc73aac0bc8039807a695..1e9bb66c42390e737639655f1e615dda018b26fb 100644 --- a/client/src/app/instance/search/detail/components/index.ts +++ b/client/src/app/instance/search/detail/components/index.ts @@ -8,7 +8,9 @@ */ import { DetailContentComponent } from './detail-content.component'; +import { DisplayDetailRendererComponent } from './display-detail-renderer.component'; export const dummiesComponents = [ - DetailContentComponent + DetailContentComponent, + DisplayDetailRendererComponent ]; diff --git a/client/src/app/instance/search/detail/components/renderer/index.ts b/client/src/app/instance/search/detail/components/renderer/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e737a2d0e09e20f8b3acd0e1b1f9695aff48ebbd --- /dev/null +++ b/client/src/app/instance/search/detail/components/renderer/index.ts @@ -0,0 +1,25 @@ +/** + * 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 { Type } from '@angular/core'; + +import { getRendererComponent } from 'src/app/instance/search/shared-renderer/components'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; + +export const rendererComponents = [ + +]; + +export const getDetailRendererComponent = (renderer: string): Type<AbstractRendererComponent> => { + let nameOfRendererComponent = getRendererComponent(renderer); + switch(renderer) { + + } + return nameOfRendererComponent; +} diff --git a/client/src/app/instance/search/detail/containers/detail.component.html b/client/src/app/instance/search/detail/containers/detail.component.html index 9c0a7eb8e8cc8c977e3eb39e08d854bb28642503..bf0ee00b02977a0866a508ee2e444784288270ef 100644 --- a/client/src/app/instance/search/detail/containers/detail.component.html +++ b/client/src/app/instance/search/detail/containers/detail.component.html @@ -1,7 +1,7 @@ <div class="container-fluid"> <div *ngIf="!(pristine | async)" class="row mt-2 mb-2 justify-content-between"> <div class="col"> - <a routerLink="/instance/{{ instanceSelected | async }}/search/result/{{ datasetSelected | async }}" [queryParams]="queryParams | async" class="btn btn-outline-secondary"> + <a routerLink="/instance/{{ (instance | async).name }}/search/result/{{ (dataset | async).name }}" [queryParams]="queryParams | async" class="search-back btn btn-outline-secondary"> <span class="fa fa-backward"></span> Back to search results </a> </div> @@ -20,10 +20,12 @@ <app-detail-content [detailConfig]="detailConfig | async" [object]="object | async" - [datasetName]="datasetSelected | async" + [dataset]="dataset | async" + [instance]="instance | async" [attributeList]="attributeList | async" [outputFamilyList]="outputFamilyList | async" - [outputCategoryList]="outputCategoryList | async"> + [outputCategoryList]="outputCategoryList | async" + [queryParams]="queryParams | async"> </app-detail-content> </ng-container> </div> diff --git a/client/src/app/instance/search/detail/containers/detail.component.spec.ts b/client/src/app/instance/search/detail/containers/detail.component.spec.ts index e572d05ff75b123d38f74dfc91be6642e406ecc0..242668dddb0210447a08d166156605188e00144d 100644 --- a/client/src/app/instance/search/detail/containers/detail.component.spec.ts +++ b/client/src/app/instance/search/detail/containers/detail.component.spec.ts @@ -62,11 +62,10 @@ describe('[Instance][Search][Container] DetailComponent', () => { const spy = jest.spyOn(store, 'dispatch'); component.ngOnInit(); Promise.resolve(null).then(function() { - expect(spy).toHaveBeenCalledTimes(4); + expect(spy).toHaveBeenCalledTimes(3); expect(spy).toHaveBeenCalledWith(searchActions.initSearch()); - expect(spy).toHaveBeenCalledWith(searchActions.loadDefaultFormParameters()); - expect(spy).toHaveBeenCalledWith(detailActions.retrieveObject()); expect(spy).toHaveBeenCalledWith(detailConfigActions.loadDetailConfig()); + expect(spy).toHaveBeenCalledWith(detailActions.retrieveObject()); done(); }); }); diff --git a/client/src/app/instance/search/detail/containers/detail.component.ts b/client/src/app/instance/search/detail/containers/detail.component.ts index 7e354d22926ce2574faebca4e53b688021e022de..05deb1e5da8d6ed0598c593251089a2c7e939b49 100644 --- a/client/src/app/instance/search/detail/containers/detail.component.ts +++ b/client/src/app/instance/search/detail/containers/detail.component.ts @@ -8,12 +8,11 @@ */ import { Component, OnInit, OnDestroy } from '@angular/core'; -import { Location } from '@angular/common'; import { Store } from '@ngrx/store'; import { Observable, Subscription } from 'rxjs'; -import { Attribute, OutputCategory, OutputFamily, DetailConfig } from 'src/app/metamodel/models'; +import { Attribute, OutputCategory, OutputFamily, DetailConfig, Dataset, Instance } from 'src/app/metamodel/models'; import { SearchQueryParams } from 'src/app/instance/store/models'; import * as detailActions from 'src/app/instance/store/actions/detail.actions'; import * as detailSelector from 'src/app/instance/store/selectors/detail.selector'; @@ -39,8 +38,8 @@ import * as detailConfigSelector from 'src/app/metamodel/selectors/detail-config templateUrl: 'detail.component.html' }) export class DetailComponent implements OnInit, OnDestroy { - public instanceSelected: Observable<string>; - public datasetSelected: Observable<string>; + public dataset: Observable<Dataset>; + public instance: Observable<Instance>; public pristine: Observable<boolean>; public detailConfig: Observable<DetailConfig>; public detailConfigIsLoading: Observable<boolean>; @@ -61,9 +60,9 @@ export class DetailComponent implements OnInit, OnDestroy { public attributeListIsLoadedSubscription: Subscription; - constructor(private location: Location, private store: Store<{ }>) { - this.instanceSelected = store.select(instanceSelector.selectInstanceNameByRoute); - this.datasetSelected = store.select(datasetSelector.selectDatasetNameByRoute); + constructor(private store: Store<{ }>) { + this.instance = store.select(instanceSelector.selectInstanceByRouteName); + this.dataset = store.select(datasetSelector.selectDatasetByRouteName); this.pristine = store.select(searchSelector.selectPristine); this.detailConfig = store.select(detailConfigSelector.selectDetailConfig); this.detailConfigIsLoading = store.select(detailConfigSelector.selectDetailConfigIsLoading); @@ -87,13 +86,12 @@ export class DetailComponent implements OnInit, OnDestroy { // 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(searchActions.initSearch())); + Promise.resolve(null).then(() => this.store.dispatch(detailConfigActions.loadDetailConfig())); 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())); } }); - Promise.resolve(null).then(() => this.store.dispatch(detailConfigActions.loadDetailConfig())); } /** diff --git a/client/src/app/instance/search/detail/detail.module.ts b/client/src/app/instance/search/detail/detail.module.ts index c70863ad9f82f7d27d5d8ddc079e87c7319d66ec..d780cbfb5d371766d219a9eebc97173333178c59 100644 --- a/client/src/app/instance/search/detail/detail.module.ts +++ b/client/src/app/instance/search/detail/detail.module.ts @@ -13,6 +13,7 @@ import { SharedModule } from 'src/app/shared/shared.module'; import { DetailRoutingModule, routedComponents } from './detail-routing.module'; import { dummiesComponents } from './components'; import { hookParsers, dynamicComponents } from './dynamic-content'; +import { SharedRendererModule } from '../shared-renderer/shared-renderer.module'; /** * @class @@ -21,7 +22,8 @@ import { hookParsers, dynamicComponents } from './dynamic-content'; @NgModule({ imports: [ SharedModule, - DetailRoutingModule + DetailRoutingModule, + SharedRendererModule ], declarations: [ routedComponents, diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.html new file mode 100644 index 0000000000000000000000000000000000000000..e443e91312cb410532f42a627bbcd2c8a2dcbbbe --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.html @@ -0,0 +1 @@ +<img [src]="getValue()" alt="Not found" [ngStyle]="getStyle()"> \ No newline at end of file diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..10bbdc7f05b6b532bb490ebf24c8045341c4c865 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-image.component.ts @@ -0,0 +1,63 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { getHost } from 'src/app/shared/utils'; +import { Attribute, Dataset } from 'src/app/metamodel/models'; +import { AppConfigService } from 'src/app/app-config.service'; + +@Component({ + selector: 'app-display-image', + templateUrl: 'display-image.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplayImageComponent { + @Input() object: any; + @Input() attributeList: Attribute[]; + @Input() dataset: Dataset; + @Input() attributeImageId: number; + @Input() type: string; + @Input() width: string; + @Input() height: string; + + constructor(private appConfig: AppConfigService) { } + + /** + * Returns source image. + * + * @return string + */ + getValue(): string { + if (this.type === 'fits') { + return `${this.appConfig.servicesUrl}/fits-to-png/${this.dataset.name}?filename=${this.getPath()}` + + `&stretch=linear&pmin=0.25&pmax=99.75&axes=true`; + } else if (this.type === 'image') { + return `${getHost(this.appConfig.apiUrl)}/dataset/${this.dataset.name}/file-explorer${this.getPath()}`; + } else { + return this.object[this.getAttributeImage().label] as string; + } + } + + getPath() { + let path = this.object[this.getAttributeImage().label]; + if (path[0] !== '/') { + path = '/' + path; + } + return path; + } + + getAttributeImage() { + return this.attributeList.find(attribute => attribute.id === this.attributeImageId); + } + + getStyle() { + let style = { + "width": '100%' + } as any; + if (this.width && this.height) { + style = { + "width": this.width, + "height": this.height + }; + } + return style; + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.html new file mode 100644 index 0000000000000000000000000000000000000000..eed45dc78075ec85cdd626e070aa86687142e76e --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.html @@ -0,0 +1,33 @@ +<!-- Accordion categories --> +<accordion [isAnimated]="true"> + <accordion-group [panelClass]="'custom-accordion'" #ag [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> + <span class="pull-left float-left"> + {{ getCategory().label }} + + <span *ngIf="ag.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!ag.isOpen"> + <span class="fas fa-chevron-down"></span> + </span> + </span> + </button> + + <!-- Output list --> + <div *ngFor="let attribute of getAttributeListByOutputCategory(getCategory().id)" class="row pb-2"> + <div class="col-5 font-weight-bold">{{ attribute.form_label }}</div> + <div class="col"> + <app-display-detail-renderer + [rendererType]="'detail'" + [value]="object[attribute.label]" + [dataset]="dataset" + [instance]="instance" + [attribute]="attribute" + [queryParams]="queryParams" + (downloadFile)="downloadFile($event)"> + </app-display-detail-renderer> + </div> + </div> + </accordion-group> +</accordion> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..015fe691ba98fa0c6de7ba82852eaf51c1ed177f --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-category.component.ts @@ -0,0 +1,41 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { Store } from '@ngrx/store'; + +import { Attribute, Dataset, Instance, OutputCategory } from 'src/app/metamodel/models'; +import { SearchQueryParams } from 'src/app/instance/store/models'; +import * as searchActions from 'src/app/instance/store/actions/search.actions'; + +@Component({ + selector: 'app-display-object-by-output-category', + templateUrl: 'display-object-by-output-category.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplayObjectByOutputCategoryComponent { + @Input() object: any; + @Input() dataset: Dataset; + @Input() instance: Instance; + @Input() attributeList: Attribute[]; + @Input() outputCategoryList: OutputCategory[]; + @Input() queryParams: SearchQueryParams; + @Input() outputCategoryId: number; + + constructor(protected store: Store<{}>) { } + + getCategory() { + return this.outputCategoryList.find(outputCategory => outputCategory.id === this.outputCategoryId); + } + + getAttributeListByOutputCategory(idOutputCategory: number): Attribute[] { + return this.attributeList.filter(attribute => attribute.id_detail_output_category === idOutputCategory); + } + + /** + * Dispatches action to launch the file download + * + * @param { url: string, filename: string } download + */ + downloadFile(download: { url: string, filename: string }): void { + this.store.dispatch(searchActions.downloadFile(download)); + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.html new file mode 100644 index 0000000000000000000000000000000000000000..03c8324e56d54ebc07c1d6e32bf7ce0760b93ba2 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.html @@ -0,0 +1,51 @@ +<!-- Accordion families --> +<accordion [isAnimated]="true"> + <accordion-group [panelClass]="'custom-accordion'" #ag [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix" accordion-heading> + <span class="pull-left float-left"> + {{ getFamily().label }} + + <span *ngIf="ag.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!ag.isOpen"> + <span class="fas fa-chevron-down"></span> + </span> + </span> + </button> + + <!-- Accordion categories --> + <accordion [isAnimated]="true"> + <accordion-group *ngFor="let category of getOutputCategoryListByFamily(getFamily().id)" [panelClass]="'custom-accordion'" #ag [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> + <span class="pull-left float-left"> + {{ category.label }} + + <span *ngIf="ag.isOpen"> + <span class="fas fa-chevron-up"></span> + </span> + <span *ngIf="!ag.isOpen"> + <span class="fas fa-chevron-down"></span> + </span> + </span> + </button> + + <!-- Output list --> + <div *ngFor="let attribute of getAttributeListByOutputCategory(category.id)" class="row pb-2"> + <div class="col-5 font-weight-bold">{{ attribute.form_label }}</div> + <div class="col"> + <app-display-detail-renderer + [rendererType]="'detail'" + [value]="object[attribute.label]" + [dataset]="dataset" + [instance]="instance" + [attribute]="attribute" + [queryParams]="queryParams" + (downloadFile)="downloadFile($event)"> + </app-display-detail-renderer> + </div> + </div> + </accordion-group> + </accordion> + </accordion-group> +</accordion> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..fda6fb34fb8839a005ab7da584c8dd553a8433af --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object-by-output-family.component.ts @@ -0,0 +1,48 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { Store } from '@ngrx/store'; + +import { Attribute, Dataset, Instance, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; +import { SearchQueryParams } from 'src/app/instance/store/models'; +import * as searchActions from 'src/app/instance/store/actions/search.actions'; + +@Component({ + selector: 'app-display-object-by-output-family', + templateUrl: 'display-object-by-output-family.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplayObjectByOutputFamilyComponent { + @Input() object: any; + @Input() dataset: Dataset; + @Input() instance: Instance; + @Input() attributeList: Attribute[]; + @Input() outputFamilyList: OutputFamily[]; + @Input() outputCategoryList: OutputCategory[]; + @Input() queryParams: SearchQueryParams; + @Input() outputFamilyId: number; + + constructor(protected store: Store<{}>) { } + + getFamily() { + return this.outputFamilyList.find(outputFamily => outputFamily.id === this.outputFamilyId); + } + + getOutputCategoryListByFamily(idOutputFamily: number): OutputCategory[] { + return this.outputCategoryList + .filter(outputCategory => outputCategory.id_output_family === idOutputFamily) + .filter(outputCategory => this.getAttributeListByOutputCategory(outputCategory.id).length > 0); + } + + getAttributeListByOutputCategory(idOutputCategory: number): Attribute[] { + return this.attributeList.filter(attribute => attribute.id_detail_output_category === idOutputCategory); + } + + /** + * Dispatches action to launch the file download + * + * @param { url: string, filename: string } download + */ + downloadFile(download: { url: string, filename: string }): void { + this.store.dispatch(searchActions.downloadFile(download)); + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html index 5c1adc90c23c6bec1e06f2c4e4499b6319cea7e0..a143e2d79e10b225072509c321cec9a048d52c45 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.html @@ -1,8 +1,8 @@ <!-- Accordion families --> <accordion [isAnimated]="true"> - <accordion-group *ngFor="let family of outputFamilyList" #ag [isOpen]="true" class="pl-2"> - <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> - <span class="pull-left float-left text-primary"> + <accordion-group *ngFor="let family of getOutputFamilyList()" [panelClass]="'custom-accordion'" #ag [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix" accordion-heading> + <span class="pull-left float-left"> {{ family.label }} <span *ngIf="ag.isOpen"> @@ -16,9 +16,9 @@ <!-- Accordion categories --> <accordion [isAnimated]="true"> - <accordion-group *ngFor="let category of getOutputCategoryListByFamily(family.id)" #ag [isOpen]="true" class="pl-4"> - <button class="btn btn-link btn-block clearfix pb-2" accordion-heading> - <span class="pull-left float-left text-primary"> + <accordion-group *ngFor="let category of getOutputCategoryListByFamily(family.id)" [panelClass]="'custom-accordion'" #ag [isOpen]="true" class="my-2"> + <button class="btn btn-link btn-block clearfix" accordion-heading> + <span class="pull-left float-left"> {{ category.label }} <span *ngIf="ag.isOpen"> @@ -33,9 +33,19 @@ <!-- Output list --> <div *ngFor="let attribute of getAttributeListByOutputCategory(category.id)" class="row pb-2"> <div class="col-5 font-weight-bold">{{ attribute.form_label }}</div> - <div class="col">{{ object[attribute.label] }}</div> + <div class="col"> + <app-display-detail-renderer + [rendererType]="'detail'" + [value]="object[attribute.label]" + [dataset]="dataset" + [instance]="instance" + [attribute]="attribute" + [queryParams]="queryParams" + (downloadFile)="downloadFile($event)"> + </app-display-detail-renderer> + </div> </div> </accordion-group> </accordion> </accordion-group> -</accordion> \ No newline at end of file +</accordion> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts index 1c029c11508c6dbce4d80c0a89fb24e29e900430..aeefb7d73bed7850cec789da74dc0bd97a4592fc 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-object.component.ts @@ -9,7 +9,11 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; -import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; +import { Store } from '@ngrx/store'; + +import { Attribute, Dataset, Instance, OutputCategory, OutputFamily } from 'src/app/metamodel/models'; +import { SearchQueryParams } from 'src/app/instance/store/models'; +import * as searchActions from 'src/app/instance/store/actions/search.actions'; /** * @class @@ -22,15 +26,35 @@ import { Attribute, OutputCategory, OutputFamily } from 'src/app/metamodel/model }) export class DisplayObjectComponent { @Input() object: any; + @Input() dataset: Dataset; + @Input() instance: Instance; @Input() attributeList: Attribute[]; @Input() outputFamilyList: OutputFamily[]; @Input() outputCategoryList: OutputCategory[]; + @Input() queryParams: SearchQueryParams; + + constructor(protected store: Store<{}>) { } + + getOutputFamilyList() { + return this.outputFamilyList.filter(family => this.getOutputCategoryListByFamily(family.id).length > 0); + } getOutputCategoryListByFamily(idOutputFamily: number): OutputCategory[] { - return this.outputCategoryList.filter(outputCategory => outputCategory.id_output_family === idOutputFamily); + return this.outputCategoryList + .filter(outputCategory => outputCategory.id_output_family === idOutputFamily) + .filter(outputCategory => this.getAttributeListByOutputCategory(outputCategory.id).length > 0); } getAttributeListByOutputCategory(idOutputCategory: number): Attribute[] { return this.attributeList.filter(attribute => attribute.id_detail_output_category === idOutputCategory); } + + /** + * Dispatches action to launch the file download + * + * @param { url: string, filename: string } download + */ + downloadFile(download: { url: string, filename: string }): void { + this.store.dispatch(searchActions.downloadFile(download)); + } } diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html index b779cc47211c89b6f36fd14b0fd435e532d3ec9d..22913efbd16ed7d79d5a2ae739598be360f22cac 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-ra-dec.component.html @@ -1,11 +1,15 @@ -<table class="table mb-1" aria-describedby="Object coordinates"> - <tr> - <th scope="col">Alpha</th> - <th scope="col">Delta</th> - <th scope="col" class="text-center" rowspan="2"><img src="assets/cesam_anis80.png" alt="CeSAM logo" /></th> - </tr> - <tr> - <td>{{ object[getAttributeRa().label] }}</td> - <td>{{ object[getAttributeDec().label] }}</td> - </tr> -</table> +<div class="search-info jumbotron row mx-0 mb-4 py-4"> + <div class="col"> + <table class="table mb-1" aria-describedby="Object coordinates"> + <tr> + <th scope="col">Alpha</th> + <th scope="col">Delta</th> + <th scope="col" class="text-center" rowspan="2"><img src="assets/cesam_anis80.png" alt="CeSAM logo" /></th> + </tr> + <tr> + <td>{{ object[getAttributeRa().label] }}</td> + <td>{{ object[getAttributeDec().label] }}</td> + </tr> + </table> + </div> +</div> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html index f908a1e04a212c8fe72ca15abc8601591eabbf39..a61ace1c9c3693c3f303ebce4627fb612c7f7966 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-spectra.component.html @@ -1 +1,5 @@ -<app-spectra-graph *ngIf="spectraCSV | async as data" [z]="getZ()" [spectraCSV]="data"></app-spectra-graph> +<div class="search-info jumbotron row mx-0 mb-4 py-4"> + <div class="col"> + <app-spectra-graph *ngIf="spectraCSV | async as data" [z]="getZ()" [spectraCSV]="data"></app-spectra-graph> + </div> +</div> diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.html b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.html new file mode 100644 index 0000000000000000000000000000000000000000..035011ce7f1480265a082c3227754ce09bbe4a74 --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.html @@ -0,0 +1 @@ +{{ object[getAttributeById().label] }} \ No newline at end of file diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..ad1dca1c5eefcc8639ab25bb5c181662cea0914c --- /dev/null +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/display-value-by-attribute.component.ts @@ -0,0 +1,18 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; + +import { Attribute } from 'src/app/metamodel/models'; + +@Component({ + selector: 'app-display-value-by-attribute', + templateUrl: 'display-value-by-attribute.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DisplayValueByAttributeComponent { + @Input() object: any; + @Input() attributeList: Attribute[]; + @Input() attributeId: number; + + getAttributeById() { + return this.attributeList.find(attribute => attribute.id === this.attributeId); + } +} diff --git a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts index 638b3adffd64ac35dbf5ad0626d2ae78c7970d20..440ca4677f4b391fb2c61421b5ca81ab7e2127ea 100644 --- a/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts +++ b/client/src/app/instance/search/detail/dynamic-content/dynamic-components/index.ts @@ -8,13 +8,21 @@ */ import { DisplayObjectComponent } from './display-object.component'; +import { DisplayObjectByOutputCategoryComponent } from './display-object-by-output-category.component'; +import { DisplayObjectByOutputFamilyComponent } from './display-object-by-output-family.component'; +import { DisplayValueByAttributeComponent } from './display-value-by-attribute.component'; import { DisplayRaDecComponent } from './display-ra-dec.component'; import { DisplaySpectraComponent } from './display-spectra.component'; +import { DisplayImageComponent } from './display-image.component'; import { SpectraGraphComponent } from './spectra-graph/spectra-graph.component'; export const dynamicComponents = [ DisplayObjectComponent, + DisplayObjectByOutputCategoryComponent, + DisplayObjectByOutputFamilyComponent, + DisplayValueByAttributeComponent, DisplayRaDecComponent, DisplaySpectraComponent, + DisplayImageComponent, SpectraGraphComponent ]; diff --git a/client/src/app/instance/search/pipes/sort-by-criteria-display.pipe.spec.ts b/client/src/app/instance/search/pipes/sort-by-criteria-display.pipe.spec.ts index 5d33a8a949622628798404072d61368f9f398ae5..1df22bcbfaa5797e69ef417316fbc496e456c7f0 100644 --- a/client/src/app/instance/search/pipes/sort-by-criteria-display.pipe.spec.ts +++ b/client/src/app/instance/search/pipes/sort-by-criteria-display.pipe.spec.ts @@ -38,6 +38,8 @@ describe('[Instance][Search][Pipe] SortByCriteriaDisplayPipe', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -72,6 +74,8 @@ describe('[Instance][Search][Pipe] SortByCriteriaDisplayPipe', () => { order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/instance/search/pipes/sort-by-detail-display.spec.ts b/client/src/app/instance/search/pipes/sort-by-detail-display.spec.ts index 3f5ceb31d9166bd7969e6516e89092ad7cb37548..1fb40a24a3faa9bd14227df1e064d2a4997924cc 100644 --- a/client/src/app/instance/search/pipes/sort-by-detail-display.spec.ts +++ b/client/src/app/instance/search/pipes/sort-by-detail-display.spec.ts @@ -38,6 +38,8 @@ describe('[Instance][Search][Pipe] SortByDetailDisplay', () => { order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -76,6 +78,8 @@ describe('[Instance][Search][Pipe] SortByDetailDisplay', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, diff --git a/client/src/app/instance/search/pipes/sort-by-output-display.pipe.spec.ts b/client/src/app/instance/search/pipes/sort-by-output-display.pipe.spec.ts index e820aa250610b93703590c46ff78ccbe6a89c207..4fc1c9d3896883d528a1ece3bc967aba6621a907 100644 --- a/client/src/app/instance/search/pipes/sort-by-output-display.pipe.spec.ts +++ b/client/src/app/instance/search/pipes/sort-by-output-display.pipe.spec.ts @@ -38,6 +38,8 @@ describe('[Instance][Search][Pipe] SortByOutputDisplayPipe', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -72,6 +74,8 @@ describe('[Instance][Search][Pipe] SortByOutputDisplayPipe', () => { order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/instance/search/search.module.ts b/client/src/app/instance/search/search.module.ts index e633fbb3bce0cf46b60004ea2d201630bda58b36..73830113caf177e3bb576b58109861d13676c4f2 100644 --- a/client/src/app/instance/search/search.module.ts +++ b/client/src/app/instance/search/search.module.ts @@ -10,11 +10,11 @@ import { NgModule } from '@angular/core'; import { SharedModule } from 'src/app/shared/shared.module'; -// import { DynamicContentModule } from '../dynamic-content/dynamic-content.module'; import { ConeSearchModule } from '../cone-search/cone-search.module'; import { SearchRoutingModule, routedComponents } from './search-routing.module'; import { dummiesComponents } from './components'; import { searchPipes } from './pipes'; +import { SharedRendererModule } from './shared-renderer/shared-renderer.module'; /** * @class @@ -23,9 +23,9 @@ import { searchPipes } from './pipes'; @NgModule({ imports: [ SharedModule, - //DynamicContentModule, ConeSearchModule, - SearchRoutingModule + SearchRoutingModule, + SharedRendererModule ], declarations: [ routedComponents, diff --git a/client/src/app/instance/search/components/result/renderer.component.ts b/client/src/app/instance/search/shared-renderer/abstract-display-renderer.component.ts similarity index 65% rename from client/src/app/instance/search/components/result/renderer.component.ts rename to client/src/app/instance/search/shared-renderer/abstract-display-renderer.component.ts index f8332530c6b630a9c80acef0ca60c97359acf2a6..da5be296a6fd870ad6107168e921d60c07d8c5bc 100644 --- a/client/src/app/instance/search/components/result/renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/abstract-display-renderer.component.ts @@ -7,18 +7,17 @@ * file that was distributed with this source code. */ -import { Component, ComponentRef, Input, Output, EventEmitter, ViewChild, OnInit, OnDestroy } from '@angular/core'; +import { Directive, ComponentRef, Input, Output, EventEmitter, ViewChild, OnInit, OnDestroy, Type } from '@angular/core'; import { Attribute, Dataset, Instance } from 'src/app/metamodel/models'; import { SearchQueryParams } from 'src/app/instance/store/models'; -import { RendererLoaderDirective, AbstractRendererComponent, getRendererComponent } from './renderer'; -import { DownloadRendererComponent } from './renderer/download-renderer.component'; - -@Component({ - selector: 'app-renderer', - templateUrl: 'renderer.component.html' -}) -export class RendererComponent implements OnInit, OnDestroy { +import { RendererLoaderDirective } from 'src/app/instance/search/shared-renderer/renderer-loader.directive'; +import { AbstractRendererComponent } from 'src/app/instance/search/shared-renderer/abstract-renderer.component'; +import { DownloadRendererComponent } from 'src/app/instance/search/shared-renderer/components'; + +@Directive({}) +export abstract class AbstractDisplayRendererComponent implements OnInit, OnDestroy { + @Input() rendererType: string; @Input() value: string | number; @Input() dataset: Dataset; @Input() instance: Instance; @@ -33,9 +32,11 @@ export class RendererComponent implements OnInit, OnDestroy { ngOnInit() { const viewContainerRef = this.rendererLoaderDirective.viewContainerRef; + const renderer = (this.rendererType === 'result') ? this.attribute.renderer : this.attribute.detail_renderer; this.componentRef = viewContainerRef.createComponent<AbstractRendererComponent>( - getRendererComponent(this.attribute.renderer) + this.getRendererComponent(renderer) ); + this.componentRef.instance.rendererType = this.rendererType; this.componentRef.instance.value = this.value; this.componentRef.instance.dataset = this.dataset; this.componentRef.instance.instance = this.instance; @@ -47,6 +48,8 @@ export class RendererComponent implements OnInit, OnDestroy { this.rendererComponent = this.componentRef.instance; } + abstract getRendererComponent(renderer: string): Type<AbstractRendererComponent>; + ngOnDestroy() { this.componentRef.destroy(); } diff --git a/client/src/app/instance/search/components/result/renderer/abstract-renderer.component.ts b/client/src/app/instance/search/shared-renderer/abstract-renderer.component.ts similarity index 67% rename from client/src/app/instance/search/components/result/renderer/abstract-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/abstract-renderer.component.ts index efb9cef5ed0eace4da5dddd12ed97e624c019373..a85e732e3c763361cf9bcf1c1e6bf69c3537d5ac 100644 --- a/client/src/app/instance/search/components/result/renderer/abstract-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/abstract-renderer.component.ts @@ -7,18 +7,25 @@ * file that was distributed with this source code. */ -import { Directive, Input, Output, EventEmitter } from '@angular/core'; +import { Directive, Input } from '@angular/core'; import { Attribute, Dataset, Instance, RendererConfig } from 'src/app/metamodel/models'; import { SearchQueryParams } from 'src/app/instance/store/models'; @Directive() export abstract class AbstractRendererComponent { + @Input() rendererType: string; @Input() value: string | number; @Input() dataset: Dataset; @Input() instance: Instance; @Input() attribute: Attribute; @Input() queryParams: SearchQueryParams; - abstract getConfig(): RendererConfig; + getConfig(): RendererConfig { + if (this.rendererType === 'result') { + return this.attribute.renderer_config; + } else { + return this.attribute.detail_renderer_config; + } + } } diff --git a/client/src/app/instance/search/components/result/renderer/default-renderer.component.html b/client/src/app/instance/search/shared-renderer/components/default-renderer.component.html similarity index 100% rename from client/src/app/instance/search/components/result/renderer/default-renderer.component.html rename to client/src/app/instance/search/shared-renderer/components/default-renderer.component.html diff --git a/client/src/app/instance/search/components/result/renderer/default-renderer.component.ts b/client/src/app/instance/search/shared-renderer/components/default-renderer.component.ts similarity index 83% rename from client/src/app/instance/search/components/result/renderer/default-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/components/default-renderer.component.ts index e2cce488dbb0178ffc2e329e258784221178ffa8..0fbcaf7441520cfcb6bbce34416a705129b7b70d 100644 --- a/client/src/app/instance/search/components/result/renderer/default-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/components/default-renderer.component.ts @@ -9,7 +9,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from '../abstract-renderer.component'; /** * @class @@ -22,6 +22,6 @@ import { AbstractRendererComponent } from './abstract-renderer.component'; }) export class DefaultRendererComponent extends AbstractRendererComponent { getConfig() { - return this.attribute.renderer_config; + return super.getConfig(); } } diff --git a/client/src/app/instance/search/components/result/renderer/download-renderer.component.html b/client/src/app/instance/search/shared-renderer/components/download-renderer.component.html similarity index 100% rename from client/src/app/instance/search/components/result/renderer/download-renderer.component.html rename to client/src/app/instance/search/shared-renderer/components/download-renderer.component.html diff --git a/client/src/app/instance/search/components/result/renderer/download-renderer.component.spec.ts b/client/src/app/instance/search/shared-renderer/components/download-renderer.component.spec.ts similarity index 97% rename from client/src/app/instance/search/components/result/renderer/download-renderer.component.spec.ts rename to client/src/app/instance/search/shared-renderer/components/download-renderer.component.spec.ts index a0cfef34ce59f56c154055b362fb44e0f63b3136..3f709ee2e47d159a0493863ae83dfa8048a505d1 100644 --- a/client/src/app/instance/search/components/result/renderer/download-renderer.component.spec.ts +++ b/client/src/app/instance/search/shared-renderer/components/download-renderer.component.spec.ts @@ -90,6 +90,8 @@ describe('[Instance][Search][Component][Result][Renderer] DownloadRendererCompon order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -106,6 +108,7 @@ describe('[Instance][Search][Component][Result][Renderer] DownloadRendererCompon id_detail_output_category: null }; + component.rendererType = 'result'; component.attribute = attribute; component.value = 'myId'; expect(component.getText()).toEqual('This is myId'); diff --git a/client/src/app/instance/search/components/result/renderer/download-renderer.component.ts b/client/src/app/instance/search/shared-renderer/components/download-renderer.component.ts similarity index 93% rename from client/src/app/instance/search/components/result/renderer/download-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/components/download-renderer.component.ts index 6c862f46b69d8dceb7a5dc423c0a0c411714929a..9dc735258dd2a63d9977058d809f4d1d56e6d7b9 100644 --- a/client/src/app/instance/search/components/result/renderer/download-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/components/download-renderer.component.ts @@ -12,7 +12,7 @@ import { Component, ChangeDetectionStrategy, Output, EventEmitter } from '@angul import { DownloadRendererConfig } from 'src/app/metamodel/models/renderers/download-renderer-config.model'; import { getHost } from 'src/app/shared/utils'; import { AppConfigService } from 'src/app/app-config.service'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from '../abstract-renderer.component'; /** * @class @@ -31,7 +31,7 @@ export class DownloadRendererComponent extends AbstractRendererComponent { } getConfig() { - return this.attribute.renderer_config as DownloadRendererConfig; + return super.getConfig() as DownloadRendererConfig; } /** diff --git a/client/src/app/instance/search/components/result/renderer/image-renderer.component.html b/client/src/app/instance/search/shared-renderer/components/image-renderer.component.html similarity index 100% rename from client/src/app/instance/search/components/result/renderer/image-renderer.component.html rename to client/src/app/instance/search/shared-renderer/components/image-renderer.component.html diff --git a/client/src/app/instance/search/components/result/renderer/image-renderer.component.spec.ts b/client/src/app/instance/search/shared-renderer/components/image-renderer.component.spec.ts similarity index 97% rename from client/src/app/instance/search/components/result/renderer/image-renderer.component.spec.ts rename to client/src/app/instance/search/shared-renderer/components/image-renderer.component.spec.ts index 7e5bf77964fa2b2a210f0950ecb6251425c18778..cb902c10a8ac83acb85029771dceaf130da80808 100644 --- a/client/src/app/instance/search/components/result/renderer/image-renderer.component.spec.ts +++ b/client/src/app/instance/search/shared-renderer/components/image-renderer.component.spec.ts @@ -64,6 +64,8 @@ describe('[Instance][Search][Component][Result][Renderer] ImageRendererComponent order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -101,6 +103,7 @@ describe('[Instance][Search][Component][Result][Renderer] ImageRendererComponent full_data_path: '/data/path' }; + component.rendererType = 'result'; component.value = 'myObjId'; component.attribute = attribute; component.dataset = dataset; diff --git a/client/src/app/instance/search/components/result/renderer/image-renderer.component.ts b/client/src/app/instance/search/shared-renderer/components/image-renderer.component.ts similarity index 93% rename from client/src/app/instance/search/components/result/renderer/image-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/components/image-renderer.component.ts index cc53ed6b456bcff94bef78e824653ce0ee1c48ab..689ae5b31b76387d15890688f47785c5e383987d 100644 --- a/client/src/app/instance/search/components/result/renderer/image-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/components/image-renderer.component.ts @@ -15,7 +15,7 @@ import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service'; import { getHost } from 'src/app/shared/utils'; import { ImageRendererConfig } from 'src/app/metamodel/models/renderers'; import { AppConfigService } from 'src/app/app-config.service'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from '../abstract-renderer.component'; /** * @class @@ -34,7 +34,7 @@ export class ImageRendererComponent extends AbstractRendererComponent { } getConfig() { - return this.attribute.renderer_config as ImageRendererConfig; + return super.getConfig() as ImageRendererConfig; } /** diff --git a/client/src/app/instance/search/shared-renderer/components/index.ts b/client/src/app/instance/search/shared-renderer/components/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..4cdc6ebc9c546ab5feae59dd191dc47838be7811 --- /dev/null +++ b/client/src/app/instance/search/shared-renderer/components/index.ts @@ -0,0 +1,58 @@ +/** + * 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 { Type } from '@angular/core'; + +import { AbstractRendererComponent } from '../abstract-renderer.component'; +import { DefaultRendererComponent } from './default-renderer.component'; +import { LinkRendererComponent } from './link-renderer.component'; +import { DownloadRendererComponent } from './download-renderer.component'; +import { ImageRendererComponent } from './image-renderer.component'; +import { JsonRendererComponent } from './json-renderer.component'; + +export * from './default-renderer.component'; +export * from './link-renderer.component'; +export * from './download-renderer.component'; +export * from './image-renderer.component'; +export * from './json-renderer.component'; + +export const sharedRendererComponents = [ + DefaultRendererComponent, + LinkRendererComponent, + DownloadRendererComponent, + ImageRendererComponent, + JsonRendererComponent +]; + +export const getRendererComponent = (renderer: string): Type<AbstractRendererComponent> => { + let nameOfRendererComponent = null; + switch(renderer) { + case 'link': { + nameOfRendererComponent = LinkRendererComponent; + break; + } + case 'download': { + nameOfRendererComponent = DownloadRendererComponent; + break; + } + case 'image': { + nameOfRendererComponent = ImageRendererComponent; + break; + } + case 'json': { + nameOfRendererComponent = JsonRendererComponent; + break; + } + default: { + nameOfRendererComponent = DefaultRendererComponent; + break; + } + } + return nameOfRendererComponent; +} diff --git a/client/src/app/instance/search/components/result/renderer/json-renderer.component.html b/client/src/app/instance/search/shared-renderer/components/json-renderer.component.html similarity index 81% rename from client/src/app/instance/search/components/result/renderer/json-renderer.component.html rename to client/src/app/instance/search/shared-renderer/components/json-renderer.component.html index be56dca2b33b13cd226e730fa4c39ae887f00bda..35b91cce34b82e86ce3c9f257dc0f15e013e97f1 100644 --- a/client/src/app/instance/search/components/result/renderer/json-renderer.component.html +++ b/client/src/app/instance/search/shared-renderer/components/json-renderer.component.html @@ -1,6 +1,6 @@ -<button *ngIf="value" class="btn btn-outline-primary btn-sm" (click)="openModal(modal)"> +<a *ngIf="value" class="btn btn-outline-primary btn-sm" (click)="openModal(modal)"> JSON -</button> +</a> <ng-template #modal> <div class="modal-header"> diff --git a/client/src/app/instance/search/components/result/renderer/json-renderer.component.ts b/client/src/app/instance/search/shared-renderer/components/json-renderer.component.ts similarity index 90% rename from client/src/app/instance/search/components/result/renderer/json-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/components/json-renderer.component.ts index 77e192fd60ff16dc5964f5f4a1b72aa495d4816a..eb277caaf34573a8b6cf423afcb8ce78e5435e53 100644 --- a/client/src/app/instance/search/components/result/renderer/json-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/components/json-renderer.component.ts @@ -11,7 +11,7 @@ import { Component, ChangeDetectionStrategy, TemplateRef } from '@angular/core'; import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from '../abstract-renderer.component'; /** * @class @@ -30,7 +30,7 @@ export class JsonRendererComponent extends AbstractRendererComponent { } getConfig() { - return this.attribute.renderer_config; + return super.getConfig(); } /** diff --git a/client/src/app/instance/search/components/result/renderer/link-renderer.component.html b/client/src/app/instance/search/shared-renderer/components/link-renderer.component.html similarity index 100% rename from client/src/app/instance/search/components/result/renderer/link-renderer.component.html rename to client/src/app/instance/search/shared-renderer/components/link-renderer.component.html diff --git a/client/src/app/instance/search/components/result/renderer/link-renderer.component.spec.ts b/client/src/app/instance/search/shared-renderer/components/link-renderer.component.spec.ts similarity index 94% rename from client/src/app/instance/search/components/result/renderer/link-renderer.component.spec.ts rename to client/src/app/instance/search/shared-renderer/components/link-renderer.component.spec.ts index b0cdbfede3bba2eb2eac2f64e455fce06f732cfd..549741031f05cb15aebfbd5c6d9d24da26a9ed82 100644 --- a/client/src/app/instance/search/components/result/renderer/link-renderer.component.spec.ts +++ b/client/src/app/instance/search/shared-renderer/components/link-renderer.component.spec.ts @@ -59,6 +59,8 @@ describe('[Instance][Search][Component][Result][Renderer] LinkRendererComponent' order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -75,6 +77,7 @@ describe('[Instance][Search][Component][Result][Renderer] LinkRendererComponent' id_detail_output_category: null }; + component.rendererType = 'result'; component.attribute = attribute; component.value = 'myId'; expect(component.getValue()).toEqual('http://test.com/myId'); @@ -111,6 +114,8 @@ describe('[Instance][Search][Component][Result][Renderer] LinkRendererComponent' order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -127,6 +132,7 @@ describe('[Instance][Search][Component][Result][Renderer] LinkRendererComponent' id_detail_output_category: null }; + component.rendererType = 'result'; component.attribute = attribute; component.value = 'myId'; expect(component.getText()).toEqual('This is myId'); diff --git a/client/src/app/instance/search/components/result/renderer/link-renderer.component.ts b/client/src/app/instance/search/shared-renderer/components/link-renderer.component.ts similarity index 88% rename from client/src/app/instance/search/components/result/renderer/link-renderer.component.ts rename to client/src/app/instance/search/shared-renderer/components/link-renderer.component.ts index f30ff23f920c5a22b45f0ed0fd27ec0fdeb5fc5e..d2be92690b62b3b3381f5d9d5cb30db361010409 100644 --- a/client/src/app/instance/search/components/result/renderer/link-renderer.component.ts +++ b/client/src/app/instance/search/shared-renderer/components/link-renderer.component.ts @@ -10,7 +10,7 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; import { LinkRendererConfig } from 'src/app/metamodel/models/renderers/link-renderer-config.model'; -import { AbstractRendererComponent } from './abstract-renderer.component'; +import { AbstractRendererComponent } from '../abstract-renderer.component'; /** * @class @@ -23,7 +23,7 @@ import { AbstractRendererComponent } from './abstract-renderer.component'; }) export class LinkRendererComponent extends AbstractRendererComponent { getConfig() { - return this.attribute.renderer_config as LinkRendererConfig; + return super.getConfig() as LinkRendererConfig; } /** diff --git a/client/src/app/instance/search/components/result/renderer/renderer-loader.directive.ts b/client/src/app/instance/search/shared-renderer/renderer-loader.directive.ts similarity index 100% rename from client/src/app/instance/search/components/result/renderer/renderer-loader.directive.ts rename to client/src/app/instance/search/shared-renderer/renderer-loader.directive.ts diff --git a/client/src/app/instance/search/shared-renderer/shared-renderer.module.ts b/client/src/app/instance/search/shared-renderer/shared-renderer.module.ts new file mode 100644 index 0000000000000000000000000000000000000000..84c50f0acb7172511387a9957ed3809349354292 --- /dev/null +++ b/client/src/app/instance/search/shared-renderer/shared-renderer.module.ts @@ -0,0 +1,33 @@ +/** + * 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 { SharedModule } from 'src/app/shared/shared.module'; +import { sharedRendererComponents } from './components'; +import { RendererLoaderDirective } from './renderer-loader.directive'; + +/** + * @class + * @classdesc Shared module. + */ +@NgModule({ + declarations: [ + sharedRendererComponents, + RendererLoaderDirective + ], + imports: [ + SharedModule + ], + exports: [ + sharedRendererComponents, + RendererLoaderDirective + ] +}) +export class SharedRendererModule { } diff --git a/client/src/app/instance/store/actions/cone-search.actions.ts b/client/src/app/instance/store/actions/cone-search.actions.ts index 779b424153952b2ca4f4e0dba7157b5a97c55c0e..1490f09834f770a1e96972389271431f69b0c89f 100644 --- a/client/src/app/instance/store/actions/cone-search.actions.ts +++ b/client/src/app/instance/store/actions/cone-search.actions.ts @@ -12,6 +12,7 @@ import { createAction, props } from '@ngrx/store'; import { ConeSearch, Resolver } from '../models'; export const addConeSearch = createAction('[ConeSearch] Add Cone Search', props<{ coneSearch: ConeSearch }>()); +export const updateConeSearch = createAction('[ConeSearch] Update Cone Search', props<{ coneSearch: ConeSearch }>()); export const deleteConeSearch = createAction('[ConeSearch] Delete Cone Search'); export const retrieveCoordinates = createAction('[ConeSearch] Retrieve Coordinates', props<{ name: string }>()); export const retrieveCoordinatesSuccess = createAction('[ConeSearch] Retrieve Coordinates Success', props<{ resolver: Resolver }>()); diff --git a/client/src/app/instance/store/actions/search-multiple.actions.ts b/client/src/app/instance/store/actions/search-multiple.actions.ts index 87d20074517eeb51f87b1895a8c81f6d9a5161a8..1dd207977345616e4968533dea9865507fa3df9d 100644 --- a/client/src/app/instance/store/actions/search-multiple.actions.ts +++ b/client/src/app/instance/store/actions/search-multiple.actions.ts @@ -9,7 +9,7 @@ import { createAction, props } from '@ngrx/store'; -import { SearchMultipleDatasetLength, SearchMultipleDatasetData } from '../models'; +import { SearchMultipleDatasetLength } from '../models'; export const initSearch = createAction('[Search Multiple] Init Search'); export const restartSearch = createAction('[Search Multiple] Restart Search'); @@ -21,6 +21,3 @@ export const updateSelectedDatasets = createAction('[Search Multiple] Update Sel export const retrieveDataLength = createAction('[Search Multiple] Retrieve Data Length'); export const retrieveDataLengthSuccess = createAction('[Search Multiple] Retrieve Data Length Success', props<{ dataLength: SearchMultipleDatasetLength[] }>()); export const retrieveDataLengthFail = createAction('[Search Multiple] Retrieve Data Length Fail'); -export const retrieveData = createAction('[Search Multiple] Retrieve Data'); -export const retrieveDataSuccess = createAction('[Search Multiple] Retrieve Data Success', props<{ data: SearchMultipleDatasetData[] }>()); -export const retrieveDataFail = createAction('[Search Multiple] Retrieve Data Fail'); diff --git a/client/src/app/instance/store/actions/search.actions.ts b/client/src/app/instance/store/actions/search.actions.ts index 86333f653f87a2d19ab33f8ed3e092e20654105c..613a5f50f7d9031ba5c7f4fc9ebd22320a3802cc 100644 --- a/client/src/app/instance/store/actions/search.actions.ts +++ b/client/src/app/instance/store/actions/search.actions.ts @@ -15,6 +15,7 @@ export const initSearch = createAction('[Search] Init Search'); export const restartSearch = createAction('[Search] Restart Search'); export const resetSearch = createAction('[Search] Reset Search'); export const destroyResults = createAction('[Search] Destroy Results'); +export const tryLoadDefaultFormParameters = createAction('[Search] Try Load Default Form Parameters'); export const loadDefaultFormParameters = createAction('[Search] Load Default Form Parameters'); export const markAsDirty = createAction('[Search] Mark As Dirty'); export const changeCurrentDataset = createAction('[Search] Change Current Dataset', props<{ currentDataset: string }>()); @@ -24,6 +25,7 @@ export const checkOutput = createAction('[Search] Check Output'); export const checkResult = createAction('[Search] Check Result'); export const updateCriteriaList = createAction('[Search] Update Criteria List', props<{ criteriaList: Criterion[] }>()); export const addCriterion = createAction('[Search] Add Criterion', props<{ criterion: Criterion }>()); +export const updateCriterion = createAction('[Search] Update Criterion', props<{ updatedCriterion: Criterion }>()); export const deleteCriterion = createAction('[Search] Delete Criterion', props<{ idCriterion: number }>()); export const updateOutputList = createAction('[Search] Update Output List', props<{ outputList: number[] }>()); export const retrieveDataLength = createAction('[Search] Retrieve Data Length'); diff --git a/client/src/app/instance/store/effects/cone-search.effects.spec.ts b/client/src/app/instance/store/effects/cone-search.effects.spec.ts index cf86c8d2c962b7957c25476a5aea93a839520ce1..1033c5b6063e8162dd82f39936268c8eeeb8efa9 100644 --- a/client/src/app/instance/store/effects/cone-search.effects.spec.ts +++ b/client/src/app/instance/store/effects/cone-search.effects.spec.ts @@ -2,6 +2,7 @@ import { TestBed } from '@angular/core/testing'; import { provideMockActions } from '@ngrx/effects/testing'; import { EffectsMetadata, getEffectsMetadata } from '@ngrx/effects'; +import { provideMockStore } from '@ngrx/store/testing'; import { Observable } from 'rxjs'; import { cold, hot } from 'jasmine-marbles'; import { ToastrService } from 'ngx-toastr'; @@ -10,6 +11,7 @@ import { ConeSearchEffects } from './cone-search.effects'; import { ConeSearchService } from '../services/cone-search.service'; import * as coneSearchActions from '../actions/cone-search.actions'; import { Resolver } from '../models'; +import * as fromConeSearch from 'src/app/instance/store/reducers/cone-search.reducer'; describe('[Instance][Store] ConeSearchEffects', () => { let actions = new Observable(); @@ -17,6 +19,9 @@ describe('[Instance][Store] ConeSearchEffects', () => { let metadata: EffectsMetadata<ConeSearchEffects>; let coneSearchService: ConeSearchService; let toastr: ToastrService; + const initialState = { + coneSearch: { ...fromConeSearch.initialState } + }; beforeEach(() => { TestBed.configureTestingModule({ @@ -24,7 +29,8 @@ describe('[Instance][Store] ConeSearchEffects', () => { ConeSearchEffects, { provide: ConeSearchService, useValue: { retrieveCoordinates: jest.fn() }}, { provide: ToastrService, useValue: { error: jest.fn() } }, - provideMockActions(() => actions) + provideMockActions(() => actions), + provideMockStore({ initialState }) ] }).compileComponents(); effects = TestBed.inject(ConeSearchEffects); diff --git a/client/src/app/instance/store/effects/cone-search.effects.ts b/client/src/app/instance/store/effects/cone-search.effects.ts index cf07473456a1f6fc83a62a79553ca5f033efff4a..d8606c24de6fd17699c754ea6e1d90cfa0375a0a 100644 --- a/client/src/app/instance/store/effects/cone-search.effects.ts +++ b/client/src/app/instance/store/effects/cone-search.effects.ts @@ -9,13 +9,15 @@ import { Injectable } from '@angular/core'; -import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects'; +import { Store } from '@ngrx/store'; import { of } from 'rxjs'; import { map, tap, mergeMap, catchError } from 'rxjs/operators'; import { ToastrService } from 'ngx-toastr'; import * as coneSearchActions from '../actions/cone-search.actions'; import { ConeSearchService } from '../services/cone-search.service'; +import * as coneSearchSelector from '../selectors/cone-search.selector'; /** * @class @@ -23,14 +25,13 @@ import { ConeSearchService } from '../services/cone-search.service'; */ @Injectable() export class ConeSearchEffects { - /** * Calls actions to retrieve object coordinates. */ retrieveCoordinates$ = createEffect((): any => this.actions$.pipe( ofType(coneSearchActions.retrieveCoordinates), - mergeMap((action) => this.coneSearchService.retrieveCoordinates(action.name) + mergeMap(action => this.coneSearchService.retrieveCoordinates(action.name) .pipe( map(response => { const parser = new DOMParser(); @@ -42,7 +43,7 @@ export class ConeSearchEffects { const ra = +xml.getElementsByTagName('jradeg')[0].childNodes[0].nodeValue; const dec = +xml.getElementsByTagName('jdedeg')[0].childNodes[0].nodeValue; const resolver = { name, ra, dec }; - return coneSearchActions.retrieveCoordinatesSuccess({ resolver }); + return coneSearchActions.retrieveCoordinatesSuccess({ resolver }) }), catchError(() => of(coneSearchActions.retrieveCoordinatesFail())) ) @@ -50,6 +51,27 @@ export class ConeSearchEffects { ) ); + /** + * Calls actions to retrieve object coordinates. + */ + retrieveCoordinatesSuccess$ = createEffect((): any => + this.actions$.pipe( + ofType(coneSearchActions.retrieveCoordinatesSuccess), + concatLatestFrom(() => this.store.select(coneSearchSelector.selectConeSearch)), + map(([action, coneSearch]) => { + const radius = (coneSearch) ? coneSearch.radius : 2; + const updatedConeSearch = { + ra: action.resolver.ra, + dec: action.resolver.dec, + radius + }; + return coneSearchActions.updateConeSearch({ + coneSearch: updatedConeSearch + }); + }) + ) + ); + /** * Displays retrieve object coordinates error notification. */ @@ -63,6 +85,7 @@ export class ConeSearchEffects { constructor( private actions$: Actions, private coneSearchService: ConeSearchService, - private toastr: ToastrService + private toastr: ToastrService, + private store: Store<{ }> ) {} } diff --git a/client/src/app/instance/store/effects/detail.effects.spec.ts b/client/src/app/instance/store/effects/detail.effects.spec.ts index 6bedb172285c22e8c8ed3e0785bea087c838eeb4..176a92b01c1040af30d0281bb4055e70693417eb 100644 --- a/client/src/app/instance/store/effects/detail.effects.spec.ts +++ b/client/src/app/instance/store/effects/detail.effects.spec.ts @@ -95,6 +95,8 @@ describe('[Instance][Store] DetailEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -150,6 +152,8 @@ describe('[Instance][Store] DetailEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/instance/store/effects/search-multiple.effects.spec.ts b/client/src/app/instance/store/effects/search-multiple.effects.spec.ts index b1c85d29fd472b9fa215d61982e3295e5b18134d..c4ca949bdb3b45bd97fbacd516fabb21aa64ebb4 100644 --- a/client/src/app/instance/store/effects/search-multiple.effects.spec.ts +++ b/client/src/app/instance/store/effects/search-multiple.effects.spec.ts @@ -141,13 +141,21 @@ describe('[Instance][Store] SearchMultipleEffects', () => { files_path: 'files', public: true, portal_logo: 'logo.png', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: 'path/to/logo', + design_logo_href: null, design_favicon: 'path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', @@ -156,23 +164,50 @@ describe('[Instance][Store] SearchMultipleEffects', () => { family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', + footer_logos: null, progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', @@ -257,38 +292,73 @@ describe('[Instance][Store] SearchMultipleEffects', () => { files_path: 'files', public: true, portal_logo: 'logo.png', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: 'path/to/logo', + design_logo_href: null, design_favicon: 'path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', + footer_logos: null, family_border_color: '#DFDFDF', family_header_background_color: '#F7F7F7', family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', diff --git a/client/src/app/instance/store/effects/search-multiple.effects.ts b/client/src/app/instance/store/effects/search-multiple.effects.ts index bfdf3a1bf9aa7732e14d6665c8f50d9b9393ccc0..66a0a4e9ab8442147c909e8d957d3acd57f88079 100644 --- a/client/src/app/instance/store/effects/search-multiple.effects.ts +++ b/client/src/app/instance/store/effects/search-multiple.effects.ts @@ -15,7 +15,7 @@ import { forkJoin, of } from 'rxjs'; import { map, tap, mergeMap, catchError } from 'rxjs/operators'; import { ToastrService } from 'ngx-toastr'; -import { SearchMultipleDatasetLength } from '../models'; +import { SearchMultipleDatasetLength, coneSearchToString, stringToConeSearch } from '../models'; import { SearchService } from '../services/search.service'; import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector'; import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; @@ -26,7 +26,6 @@ import * as coneSearchSelector from '../selectors/cone-search.selector'; @Injectable() export class SearchMultipleEffects { - /** * Calls actions to initialize search multiple. */ @@ -60,12 +59,7 @@ export class SearchMultipleEffects { // Update cone search if (coneSearchByRoute) { - const params = coneSearchByRoute.split(':'); - const coneSearch = { - ra: +params[0], - dec: +params[1], - radius: +params[2] - }; + const coneSearch = stringToConeSearch(coneSearchByRoute); actions.push(coneSearchActions.addConeSearch({ coneSearch })); } @@ -112,7 +106,7 @@ export class SearchMultipleEffects { ]), mergeMap(([, selectedDatasets, coneSearch]) => { const queries = selectedDatasets.map(datasetName => this.searchService.retrieveDataLength( - `${datasetName}?a=count&cs=${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}` + `${datasetName}?a=count&cs=${coneSearchToString(coneSearch)}` ).pipe( map((response: { nb: number }[]) => ({ datasetName, length: response[0].nb })) )); diff --git a/client/src/app/instance/store/effects/search.effects.spec.ts b/client/src/app/instance/store/effects/search.effects.spec.ts index 436528864caa23d27230d2df7402fa349e3e2bbf..f5c164ad906421a9ef8d17065699015a474de0b3 100644 --- a/client/src/app/instance/store/effects/search.effects.spec.ts +++ b/client/src/app/instance/store/effects/search.effects.spec.ts @@ -21,6 +21,8 @@ import * as outputCategoryActions from '../../../metamodel/actions/output-catego import * as attributeSelector from '../../../metamodel/selectors/attribute.selector'; import * as coneSearchSelector from '../selectors/cone-search.selector'; import * as coneSearchActions from '../actions/cone-search.actions'; +import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; +import * as coneSearchConfigActions from 'src/app/metamodel/actions/cone-search-config.actions'; import { Criterion, PaginationOrder } from '../models'; describe('[Instance][Store] SearchEffects', () => { @@ -43,6 +45,7 @@ describe('[Instance][Store] SearchEffects', () => { let mockConeSearchSelectorSelectConeSearch; let mockSearchSelectorSelectOutputListByRoute; let mockSearchSelectorSelectOutputList; + let mocksSearchSelectorSelectConeSearchConfig; beforeEach(() => { TestBed.configureTestingModule({ @@ -96,6 +99,9 @@ describe('[Instance][Store] SearchEffects', () => { mockSearchSelectorSelectOutputList = store.overrideSelector( searchSelector.selectOutputList,[] ); + mocksSearchSelectorSelectConeSearchConfig = store.overrideSelector( + coneSearchConfigSelector.selectConeSearchConfig,null + ); }); it('should be created', () => { @@ -133,12 +139,14 @@ describe('[Instance][Store] SearchEffects', () => { const action = searchActions.initSearch(); actions = hot('-a', { a: action }); - const expected = cold('-(bcdef)', { + const expected = cold('-(bcdefgh)', { b: searchActions.changeCurrentDataset({ currentDataset: 'myDatasetName' }), c: attributeActions.loadAttributeList(), d: criteriaFamilyActions.loadCriteriaFamilyList(), e: outputFamilyActions.loadOutputFamilyList(), - f: outputCategoryActions.loadOutputCategoryList() + f: outputCategoryActions.loadOutputCategoryList(), + g: coneSearchConfigActions.loadConeSearchConfig(), + h: searchActions.tryLoadDefaultFormParameters() }); expect(effects.initSearch$).toBeObservable(expected); @@ -160,15 +168,17 @@ describe('[Instance][Store] SearchEffects', () => { const action = searchActions.initSearch(); actions = hot('-a', { a: action }); - const expected = cold('-(bcdefghi)', { + const expected = cold('-(bcdefghijk)', { b: searchActions.changeCurrentDataset({ currentDataset: 'myDatasetName' }), c: attributeActions.loadAttributeList(), d: criteriaFamilyActions.loadCriteriaFamilyList(), e: outputFamilyActions.loadOutputFamilyList(), f: outputCategoryActions.loadOutputCategoryList(), - g: searchActions.checkCriteria(), - h: searchActions.checkOutput(), - i: searchActions.checkResult() + g: coneSearchConfigActions.loadConeSearchConfig(), + h: searchActions.tryLoadDefaultFormParameters(), + i: searchActions.checkCriteria(), + j: searchActions.checkOutput(), + k: searchActions.checkResult() }); expect(effects.initSearch$).toBeObservable(expected); @@ -209,10 +219,13 @@ describe('[Instance][Store] SearchEffects', () => { describe('restartSearch$ effect', () => { it('should dispatch the initSearch action', () => { const action = searchActions.restartSearch(); - const outcome = searchActions.initSearch(); actions = hot('-a', { a: action }); - const expected = cold('-b', { b: outcome }); + const expected = cold('-(bcd)', { + b: attributeActions.resetAttributeList(), + c: coneSearchConfigActions.resetConeSearchConfig(), + d: searchActions.initSearch() + }); expect(effects.restartSearch$).toBeObservable(expected); }); @@ -302,6 +315,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -336,6 +351,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -401,6 +418,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -435,6 +454,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -452,7 +473,7 @@ describe('[Instance][Store] SearchEffects', () => { searchSelector.selectCriteriaListByRoute, '1::eq::un;2::eq::deux' ); mockSearchSelectorSelectOutputListByRoute = store.overrideSelector( - searchSelector.selectOutputListByRoute, null + searchSelector.selectOutputListByRoute, '1;2;3' ); const action = searchActions.loadDefaultFormParameters(); @@ -463,7 +484,7 @@ describe('[Instance][Store] SearchEffects', () => { {'id':2,'type':'field','operator':'eq','value':'deux'} ]; const defaultConeSearch = null; - const defaultOutputList = []; + const defaultOutputList = [1, 2, 3]; const expected = cold('-(bcde)', { b: searchActions.updateCriteriaList({ criteriaList: criteriaList }), c: coneSearchActions.addConeSearch({ coneSearch: defaultConeSearch }), @@ -533,6 +554,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -567,6 +590,8 @@ describe('[Instance][Store] SearchEffects', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, diff --git a/client/src/app/instance/store/effects/search.effects.ts b/client/src/app/instance/store/effects/search.effects.ts index d40af8c60d800596e0af98e9f6dc84cbd91348cc..d6962274e993e543a1915924b4a0e1fb00f67267 100644 --- a/client/src/app/instance/store/effects/search.effects.ts +++ b/client/src/app/instance/store/effects/search.effects.ts @@ -10,14 +10,14 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects'; -import { Store, Action } from '@ngrx/store'; -import { of } from 'rxjs'; -import { map, tap, mergeMap, catchError } from 'rxjs/operators'; +import { Store, Action, select } from '@ngrx/store'; +import { of, combineLatest } from 'rxjs'; +import { map, switchMap, tap, mergeMap, catchError, skipWhile } from 'rxjs/operators'; import { ToastrService } from 'ngx-toastr'; import { KeycloakService } from 'keycloak-angular'; import FileSaver from 'file-saver'; -import { ConeSearch, criterionToString, stringToCriterion } from '../models'; +import { ConeSearch, criterionToString, stringToCriterion, coneSearchToString, stringToConeSearch } from '../models'; import { SearchService } from '../services/search.service'; import * as searchActions from '../actions/search.actions'; import * as attributeActions from 'src/app/metamodel/actions/attribute.actions'; @@ -29,6 +29,8 @@ import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector'; import * as searchSelector from '../selectors/search.selector'; import * as coneSearchActions from '../actions/cone-search.actions'; import * as coneSearchSelector from '../selectors/cone-search.selector'; +import * as coneSearchConfigActions from 'src/app/metamodel/actions/cone-search-config.actions'; +import * as coneSearchConfigSelector from 'src/app/metamodel/selectors/cone-search-config.selector'; import * as authSelector from 'src/app/auth/auth.selector'; /** @@ -37,7 +39,6 @@ import * as authSelector from 'src/app/auth/auth.selector'; */ @Injectable() export class SearchEffects { - /** * Calls actions to initialize search. */ @@ -63,7 +64,9 @@ export class SearchEffects { attributeActions.loadAttributeList(), criteriaFamilyActions.loadCriteriaFamilyList(), outputFamilyActions.loadOutputFamilyList(), - outputCategoryActions.loadOutputCategoryList() + outputCategoryActions.loadOutputCategoryList(), + coneSearchConfigActions.loadConeSearchConfig(), + searchActions.tryLoadDefaultFormParameters() ]; if (steps) { if(steps[0] === '1') { @@ -96,7 +99,34 @@ export class SearchEffects { restartSearch$ = createEffect((): any => this.actions$.pipe( ofType(searchActions.restartSearch), - map(() => searchActions.initSearch()) + mergeMap(() => [ + attributeActions.resetAttributeList(), + coneSearchConfigActions.resetConeSearchConfig(), + searchActions.initSearch() + ]) + ) + ); + + resetSearch$ = createEffect((): any => + this.actions$.pipe( + ofType(searchActions.resetSearch), + mergeMap(() => [ + attributeActions.resetAttributeList(), + coneSearchConfigActions.resetConeSearchConfig() + ]) + ) + ); + + tryLoadDefaultFormParameters$ = createEffect((): any => + this.actions$.pipe( + ofType(searchActions.tryLoadDefaultFormParameters), + switchMap(() => combineLatest([ + this.store.pipe(select(attributeSelector.selectAttributeListIsLoaded)), + this.store.pipe(select(coneSearchConfigSelector.selectConeSearchConfigIsLoaded)), + ]).pipe( + skipWhile(([attributeListIsLoaded, coneSearchConfigIsLoaded]) => !attributeListIsLoaded || !coneSearchConfigIsLoaded), + map(() => searchActions.loadDefaultFormParameters()) + )) ) ); @@ -110,11 +140,12 @@ export class SearchEffects { this.store.select(searchSelector.selectPristine), this.store.select(searchSelector.selectCurrentDataset), this.store.select(attributeSelector.selectAllAttributes), + this.store.select(coneSearchConfigSelector.selectConeSearchConfig), this.store.select(searchSelector.selectCriteriaListByRoute), this.store.select(coneSearchSelector.selectConeSearchByRoute), this.store.select(searchSelector.selectOutputListByRoute) ]), - mergeMap(([, pristine, currentDataset, attributeList, criteriaList, coneSearch, outputList]) => { + mergeMap(([, pristine, currentDataset, attributeList, coneSearchConfig, criteriaList, coneSearch, outputList]) => { // Default form parameters already loaded or no dataset selected if (!pristine || !currentDataset) { return of({ type: '[No Action] Load Default Form Parameters' }); @@ -129,22 +160,13 @@ export class SearchEffects { const attribute = attributeList.find(a => a.id === parseInt(params[0], 10)); return stringToCriterion(attribute, params); }); - } else { - // Build default criteria list with the attribute list metamodel configuration - defaultCriteriaList = attributeList - .filter(attribute => attribute.id_criteria_family && attribute.search_type && attribute.min) - .map(attribute => stringToCriterion(attribute)); } // Update cone search let defaultConeSearch: ConeSearch = null; if (coneSearch) { - const params = coneSearch.split(':'); - defaultConeSearch = { - ra: +params[0], - dec: +params[1], - radius: +params[2] - }; + // Build cone-search with the URL query parameters (cs) + defaultConeSearch = stringToConeSearch(coneSearch); } // Update output list @@ -152,8 +174,27 @@ export class SearchEffects { if (outputList) { // Build output list with the URL query parameters (a) defaultOutputList = outputList.split(';').map((o: string) => parseInt(o, 10)); - } else { - // Build default output list with the attribute list metamodel configuration + } + + // If the user has moved from step 1 to 2 + // outputList is empty and ANIS cand build + // 1. default criteria list with the attribute list metamodel configuration + // 2. default output list with the attribute list metamodel configuration + if (!outputList) { + defaultCriteriaList = attributeList + .filter(attribute => attribute.id_criteria_family && attribute.search_type && (attribute.min || attribute.max)) + .map(attribute => stringToCriterion(attribute)); + + if (coneSearchConfig + && coneSearchConfig.default_ra !== null + && coneSearchConfig.default_dec !== null + && coneSearchConfig.default_radius !== null + ) { + defaultConeSearch = stringToConeSearch( + `${coneSearchConfig.default_ra}:${coneSearchConfig.default_dec}:${coneSearchConfig.default_radius}` + ); + } + defaultOutputList = attributeList .filter(attribute => attribute.selected && attribute.id_output_category) .sort((a, b) => a.output_display - b.output_display) @@ -188,7 +229,7 @@ export class SearchEffects { query += `&c=${criteriaList.map(criterion => criterionToString(criterion)).join(';')}`; } if (coneSearch) { - query += `&cs=${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}`; + query += `&cs=${coneSearchToString(coneSearch)}`; } return this.searchService.retrieveDataLength(query) @@ -228,7 +269,7 @@ export class SearchEffects { query += `&c=${criteriaList.map(criterion => criterionToString(criterion)).join(';')}`; } if (coneSearch) { - query += `&cs=${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}`; + query += `&cs=${coneSearchToString(coneSearch)}`; } query += `&p=${action.pagination.nbItems}:${action.pagination.page}`; diff --git a/client/src/app/instance/store/models/cone-search.model.ts b/client/src/app/instance/store/models/cone-search.model.ts index 392bc0496efc6097d7c2041f20be37d8d5a2f0f7..afc2db69395e31d1f2e1e26968892caf8ebd3c9b 100644 --- a/client/src/app/instance/store/models/cone-search.model.ts +++ b/client/src/app/instance/store/models/cone-search.model.ts @@ -16,3 +16,36 @@ export class ConeSearch { dec: number; radius: number; } + +/** + * Returns cone-search notation for Anis Server. + * + * @param {ConeSearch} coneSearch - The cone-search to transform. + * + * @return string + * + * @example + * coneSearchToString(coneSearch) + */ +export const coneSearchToString = (coneSearch: ConeSearch): string => { + return `${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}`; +}; + +/** + * Returns cone-search object from serialized cone-search notation. + * + * @param {string[]} params - The cone-search parameters. + * + * @return ConeSearch + * + * @example + * stringToCriterion('280.5:0.0:10') + */ +export const stringToConeSearch = (params: string): ConeSearch => { + const csParams = params.split(':'); + return { + ra: +csParams[0], + dec: +csParams[1], + radius: +csParams[2] + }; +} diff --git a/client/src/app/instance/store/models/criterion.model.spec.ts b/client/src/app/instance/store/models/criterion.model.spec.ts index d678d277b5f8603aa9057b4810543e338ada5df8..f40dc95afcb39b100085a9f48f7b6d5407eae141 100644 --- a/client/src/app/instance/store/models/criterion.model.spec.ts +++ b/client/src/app/instance/store/models/criterion.model.spec.ts @@ -58,6 +58,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -94,6 +96,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -130,6 +134,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -166,6 +172,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -202,6 +210,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, options: null, vo_utype: null, vo_ucd: null, @@ -249,6 +259,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, vo_utype: null, vo_ucd: null, vo_unit: null, @@ -289,6 +301,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, vo_utype: null, vo_ucd: null, vo_unit: null, @@ -325,6 +339,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, vo_utype: null, vo_ucd: null, vo_unit: null, @@ -361,6 +377,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, vo_utype: null, vo_ucd: null, vo_unit: null, @@ -396,6 +414,8 @@ describe('[Instance][Store] CriterionModel', () => { order_by: true, archive: false, detail_display: 1, + detail_renderer: null, + detail_renderer_config: null, vo_utype: null, vo_ucd: null, vo_unit: null, diff --git a/client/src/app/instance/store/models/criterion.model.ts b/client/src/app/instance/store/models/criterion.model.ts index 3abcabaf8d12c3619f2259b63d65b700ddd687f1..b9193009bcb3aba5be84ca830ce089efa8df09bd 100644 --- a/client/src/app/instance/store/models/criterion.model.ts +++ b/client/src/app/instance/store/models/criterion.model.ts @@ -127,7 +127,10 @@ export const stringToCriterion = (attribute: Attribute, params: string[] = null) return { id: attribute.id, type: 'between', min: null, max: params[2] } as BetweenCriterion; } } else { - return { id: attribute.id, type: 'between', min: attribute.min.toString(), max: attribute.max.toString() } as BetweenCriterion; + const min = (attribute.min) ? attribute.min.toString() : null; + const max = (attribute.max) ? attribute.max.toString() : null; + console.log(max); + return { id: attribute.id, type: 'between', min, max } as BetweenCriterion; } case 'select-multiple': case 'checkbox': diff --git a/client/src/app/instance/store/models/index.ts b/client/src/app/instance/store/models/index.ts index 67be1059cf6ae8f9f0530f91f275da1cf1252ae6..17085214a99584c8d9e67374d9562f57df670955 100644 --- a/client/src/app/instance/store/models/index.ts +++ b/client/src/app/instance/store/models/index.ts @@ -6,5 +6,4 @@ export * from './pagination.model'; export * from './cone-search.model'; export * from './resolver.model'; export * from './search-multiple-dataset-length'; -export * from './search-multiple-dataset-data'; export * from './svom-keyword.model'; diff --git a/client/src/app/instance/store/reducers/cone-search.reducer.spec.ts b/client/src/app/instance/store/reducers/cone-search.reducer.spec.ts index fefb4582eb5fde44b332f78a7ee00f8b52532d65..ba89431b0742ce45a42ac9cd39f307c195742eb3 100644 --- a/client/src/app/instance/store/reducers/cone-search.reducer.spec.ts +++ b/client/src/app/instance/store/reducers/cone-search.reducer.spec.ts @@ -20,7 +20,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { const state = fromConeSearch.coneSearchReducer(initialState, action); expect(state.coneSearch).toEqual(coneSearch); - expect(state.resolver).toBeNull(); expect(state.resolverIsLoading).toBeFalsy(); expect(state.resolverIsLoaded).toBeFalsy(); expect(state).not.toBe(initialState); @@ -35,7 +34,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { const state = fromConeSearch.coneSearchReducer(initialState, action); expect(state.coneSearch).toBeNull(); - expect(state.resolver).toBeNull(); expect(state.resolverIsLoading).toBeFalsy(); expect(state.resolverIsLoaded).toBeFalsy(); expect(state).not.toBe(initialState); @@ -47,7 +45,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { const state = fromConeSearch.coneSearchReducer(initialState, action); expect(state.coneSearch).toBeNull(); - expect(state.resolver).toBeNull(); expect(state.resolverIsLoading).toBeTruthy(); expect(state.resolverIsLoaded).toBeFalsy(); expect(state).not.toBe(initialState); @@ -60,7 +57,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { const state = fromConeSearch.coneSearchReducer(initialState, action); expect(state.coneSearch).toBeNull(); - expect(state.resolver).toBe(resolver); expect(state.resolverIsLoading).toBeFalsy(); expect(state.resolverIsLoaded).toBeTruthy(); expect(state).not.toBe(initialState); @@ -75,7 +71,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { const state = fromConeSearch.coneSearchReducer(initialState, action); expect(state.coneSearch).toBeNull(); - expect(state.resolver).toBeNull(); expect(state.resolverIsLoading).toBeFalsy(); expect(state.resolverIsLoaded).toBeFalsy(); expect(state).not.toBe(initialState); @@ -88,13 +83,6 @@ describe('[Instance][Store] ConeSearch reducer', () => { expect(fromConeSearch.selectConeSearch(state)).toBeNull(); }); - it('should get resolver', () => { - const action = {} as Action; - const state = fromConeSearch.coneSearchReducer(undefined, action); - - expect(fromConeSearch.selectResolver(state)).toBeNull(); - }); - it('should get resolverIsLoading', () => { const action = {} as Action; const state = fromConeSearch.coneSearchReducer(undefined, action); diff --git a/client/src/app/instance/store/reducers/cone-search.reducer.ts b/client/src/app/instance/store/reducers/cone-search.reducer.ts index 63715d1aa66fae148a0659776ca14df072b727c8..558e1a27d9a24f63163c5a3ed8cc9591300e1e63 100644 --- a/client/src/app/instance/store/reducers/cone-search.reducer.ts +++ b/client/src/app/instance/store/reducers/cone-search.reducer.ts @@ -10,7 +10,7 @@ import { createReducer, on } from '@ngrx/store'; import * as coneSearchActions from '../actions/cone-search.actions'; -import { ConeSearch, Resolver } from '../models'; +import { ConeSearch } from '../models'; /** * Interface for cone search state. @@ -19,14 +19,12 @@ import { ConeSearch, Resolver } from '../models'; */ export interface State { coneSearch: ConeSearch; - resolver: Resolver; resolverIsLoading: boolean; resolverIsLoaded: boolean; } export const initialState: State = { coneSearch: null, - resolver: null, resolverIsLoading: false, resolverIsLoaded: false } @@ -37,18 +35,20 @@ export const coneSearchReducer = createReducer( ...state, coneSearch })), - on(coneSearchActions.deleteConeSearch, state => ({ + on(coneSearchActions.updateConeSearch, (state, { coneSearch }) => ({ ...state, - coneSearch: null + coneSearch + })), + on(coneSearchActions.deleteConeSearch, state => ({ + ...initialState })), on(coneSearchActions.retrieveCoordinates, state => ({ ...state, resolverIsLoading: true, resolverIsLoaded: false })), - on(coneSearchActions.retrieveCoordinatesSuccess, (state, { resolver }) => ({ + on(coneSearchActions.retrieveCoordinatesSuccess, state => ({ ...state, - resolver, resolverIsLoading: false, resolverIsLoaded: true })), @@ -59,6 +59,5 @@ export const coneSearchReducer = createReducer( ); export const selectConeSearch = (state: State) => state.coneSearch; -export const selectResolver = (state: State) => state.resolver; export const selectResolverIsLoading = (state: State) => state.resolverIsLoading; export const selectResolverIsLoaded = (state: State) => state.resolverIsLoaded; diff --git a/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts b/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts index e270b579ada00ea021adfe65537f7d1d48650022..100956512dce5d1972799579f6f6f50fe5a74914 100644 --- a/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts +++ b/client/src/app/instance/store/reducers/search-multiple.reducer.spec.ts @@ -2,7 +2,7 @@ import { Action } from '@ngrx/store'; import * as fromSearchMultiple from './search-multiple.reducer'; import * as searchMultipleActions from '../actions/search-multiple.actions'; -import { SearchMultipleDatasetData, SearchMultipleDatasetLength } from '../models'; +import { SearchMultipleDatasetLength } from '../models'; describe('[Instance][Store] SearchMultiple reducer', () => { it('unknown action should return the default state', () => { @@ -20,16 +20,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toEqual('position'); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -40,16 +36,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toEqual('myStep'); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -60,16 +52,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeFalsy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -80,16 +68,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeTruthy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -100,16 +84,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeTruthy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -121,7 +101,6 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(1); @@ -129,9 +108,6 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -145,16 +121,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeTruthy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -169,7 +141,6 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); @@ -177,9 +148,6 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.dataLengthIsLoaded).toBeTruthy(); expect(state.dataLength.length).toEqual(1); expect(state.dataLength).toEqual(dataLength); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -193,87 +161,12 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); expect(state.datasetsStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.selectedDatasets.length).toEqual(0); expect(state.dataLengthIsLoading).toBeFalsy(); expect(state.dataLengthIsLoaded).toBeFalsy(); expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); - expect(state).not.toBe(initialState); - }); - - it('retrieveData action should set dataIsLoading to true and dataIsLoaded to false', () => { - const initialState = { - ...fromSearchMultiple.initialState, - dataIsLoaded: true - }; - const action = searchMultipleActions.retrieveData(); - const state = fromSearchMultiple.searchMultipleReducer(initialState, action); - - expect(state.pristine).toBeTruthy(); - expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); - expect(state.datasetsStepChecked).toBeFalsy(); - expect(state.resultStepChecked).toBeFalsy(); - expect(state.selectedDatasets.length).toEqual(0); - expect(state.dataLengthIsLoading).toBeFalsy(); - expect(state.dataLengthIsLoaded).toBeFalsy(); - expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeTruthy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); - expect(state).not.toBe(initialState); - }); - - it('retrieveDataSuccess action should set data, set dataIsLoading to false and dataIsLoaded to true', () => { - const initialState = { - ...fromSearchMultiple.initialState, - dataIsLoading: true - }; - const data: SearchMultipleDatasetData[] = [{ datasetName: 'myDataset', data: ['myData'] }]; - const action = searchMultipleActions.retrieveDataSuccess({ data }); - const state = fromSearchMultiple.searchMultipleReducer(initialState, action); - - expect(state.pristine).toBeTruthy(); - expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); - expect(state.datasetsStepChecked).toBeFalsy(); - expect(state.resultStepChecked).toBeFalsy(); - expect(state.selectedDatasets.length).toEqual(0); - expect(state.dataLengthIsLoading).toBeFalsy(); - expect(state.dataLengthIsLoaded).toBeFalsy(); - expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeTruthy(); - expect(state.data.length).toEqual(1); - expect(state.data).toEqual(data); - expect(state).not.toBe(initialState); - }); - - it('retrieveDataFail action should set dataIsLoading to false', () => { - const initialState = { - ...fromSearchMultiple.initialState, - dataIsLoading: true - }; - const action = searchMultipleActions.retrieveDataFail(); - const state = fromSearchMultiple.searchMultipleReducer(initialState, action); - - expect(state.pristine).toBeTruthy(); - expect(state.currentStep).toBeNull(); - expect(state.positionStepChecked).toBeFalsy(); - expect(state.datasetsStepChecked).toBeFalsy(); - expect(state.resultStepChecked).toBeFalsy(); - expect(state.selectedDatasets.length).toEqual(0); - expect(state.dataLengthIsLoading).toBeFalsy(); - expect(state.dataLengthIsLoaded).toBeFalsy(); - expect(state.dataLength.length).toEqual(0); - expect(state.dataIsLoading).toBeFalsy(); - expect(state.dataIsLoaded).toBeFalsy(); - expect(state.data.length).toEqual(0); expect(state).not.toBe(initialState); }); @@ -291,13 +184,6 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(fromSearchMultiple.selectCurrentStep(state)).toBeNull(); }); - it('should get positionStepChecked', () => { - const action = {} as Action; - const state = fromSearchMultiple.searchMultipleReducer(undefined, action); - - expect(fromSearchMultiple.selectPositionStepChecked(state)).toBeFalsy(); - }); - it('should get datasetsStepChecked', () => { const action = {} as Action; const state = fromSearchMultiple.searchMultipleReducer(undefined, action); @@ -339,25 +225,4 @@ describe('[Instance][Store] SearchMultiple reducer', () => { expect(fromSearchMultiple.selectDataLength(state).length).toEqual(0); }); - - it('should get dataIsLoading', () => { - const action = {} as Action; - const state = fromSearchMultiple.searchMultipleReducer(undefined, action); - - expect(fromSearchMultiple.selectDataIsLoading(state)).toBeFalsy(); - }); - - it('should get dataIsLoaded', () => { - const action = {} as Action; - const state = fromSearchMultiple.searchMultipleReducer(undefined, action); - - expect(fromSearchMultiple.selectDataIsLoaded(state)).toBeFalsy(); - }); - - it('should get data', () => { - const action = {} as Action; - const state = fromSearchMultiple.searchMultipleReducer(undefined, action); - - expect(fromSearchMultiple.selectData(state).length).toEqual(0); - }); }); diff --git a/client/src/app/instance/store/reducers/search-multiple.reducer.ts b/client/src/app/instance/store/reducers/search-multiple.reducer.ts index d5cf3af087b2055e2b0caa99b846102e2c363ba2..1d6c8dfa17dec55d1bb1686654ba8739dccdf600 100644 --- a/client/src/app/instance/store/reducers/search-multiple.reducer.ts +++ b/client/src/app/instance/store/reducers/search-multiple.reducer.ts @@ -9,7 +9,7 @@ import { createReducer, on } from '@ngrx/store'; -import { SearchMultipleDatasetLength, SearchMultipleDatasetData } from '../models'; +import { SearchMultipleDatasetLength } from '../models'; import * as searchMultipleActions from '../actions/search-multiple.actions'; /** @@ -20,32 +20,23 @@ import * as searchMultipleActions from '../actions/search-multiple.actions'; export interface State { pristine: boolean; currentStep: string; - // TODO: remove unused positionStepChecked variable - positionStepChecked: boolean; datasetsStepChecked: boolean; resultStepChecked: boolean; selectedDatasets: string[]; dataLengthIsLoading: boolean; dataLengthIsLoaded: boolean; dataLength: SearchMultipleDatasetLength[]; - dataIsLoading: boolean; - dataIsLoaded: boolean; - data: SearchMultipleDatasetData[]; } export const initialState: State = { pristine: true, currentStep: null, - positionStepChecked: false, datasetsStepChecked: false, resultStepChecked: false, selectedDatasets: [], dataLengthIsLoading: false, dataLengthIsLoaded: false, - dataLength: [], - dataIsLoading: false, - dataIsLoaded: false, - data: [] + dataLength: [] }; export const searchMultipleReducer = createReducer( @@ -88,33 +79,14 @@ export const searchMultipleReducer = createReducer( on(searchMultipleActions.retrieveDataLengthFail, state => ({ ...state, dataLengthIsLoading: false - })), - on(searchMultipleActions.retrieveData, state => ({ - ...state, - dataIsLoading: true, - dataIsLoaded: false - })), - on(searchMultipleActions.retrieveDataSuccess, (state, { data }) => ({ - ...state, - data, - dataIsLoading: false, - dataIsLoaded: true - })), - on(searchMultipleActions.retrieveDataFail, state => ({ - ...state, - dataIsLoading: false })) ); export const selectPristine = (state: State) => state.pristine; export const selectCurrentStep = (state: State) => state.currentStep; -export const selectPositionStepChecked = (state: State) => state.positionStepChecked; export const selectDatasetsStepChecked = (state: State) => state.datasetsStepChecked; export const selectResultStepChecked = (state: State) => state.resultStepChecked; export const selectSelectedDatasets = (state: State) => state.selectedDatasets; export const selectDataLengthIsLoading = (state: State) => state.dataLengthIsLoading; export const selectDataLengthIsLoaded = (state: State) => state.dataLengthIsLoaded; export const selectDataLength = (state: State) => state.dataLength; -export const selectDataIsLoading = (state: State) => state.dataIsLoading; -export const selectDataIsLoaded = (state: State) => state.dataIsLoaded; -export const selectData = (state: State) => state.data; diff --git a/client/src/app/instance/store/reducers/search.reducer.spec.ts b/client/src/app/instance/store/reducers/search.reducer.spec.ts index b89b21eecb2c35cb02498049230a399e401c01bb..b39b17eccec5f9f89d9759432d038512af1d6c9b 100644 --- a/client/src/app/instance/store/reducers/search.reducer.spec.ts +++ b/client/src/app/instance/store/reducers/search.reducer.spec.ts @@ -20,8 +20,8 @@ describe('[Instance][Store] Search reducer', () => { expect(state.pristine).toBeTruthy(); expect(state.currentDataset).toBeNull(); - expect(state.currentStep).toBe('dataset'); - expect(state.criteriaStepChecked).toBeFalsy(); + expect(state.currentStep).toBe('criteria'); + expect(state.criteriaStepChecked).toBeTruthy(); expect(state.outputStepChecked).toBeFalsy(); expect(state.resultStepChecked).toBeFalsy(); expect(state.coneSearchAdded).toBeFalsy(); diff --git a/client/src/app/instance/store/reducers/search.reducer.ts b/client/src/app/instance/store/reducers/search.reducer.ts index e81da50750d1d573e65d2d3e307ef8408b147a5d..e00a8b3b0c4a9cb2f27bd72fac886af543ad109a 100644 --- a/client/src/app/instance/store/reducers/search.reducer.ts +++ b/client/src/app/instance/store/reducers/search.reducer.ts @@ -59,7 +59,8 @@ export const searchReducer = createReducer( initialState, on(searchActions.restartSearch, () => ({ ...initialState, - currentStep: 'dataset' + currentStep: 'criteria', + criteriaStepChecked: true })), on(searchActions.changeStep, (state, { step }) => ({ ...state, @@ -93,6 +94,12 @@ export const searchReducer = createReducer( ...state, criteriaList: [...state.criteriaList, criterion] })), + on(searchActions.updateCriterion, (state, { updatedCriterion }) => ({ + ...state, + criteriaList: state.criteriaList.map( + criterion => (criterion.id === updatedCriterion.id) ? updatedCriterion : criterion + ) + })), on(searchActions.deleteCriterion, (state, { idCriterion }) => ({ ...state, criteriaList: [...state.criteriaList.filter(c => c.id !== idCriterion)] diff --git a/client/src/app/instance/store/selectors/cone-search.selector.spec.ts b/client/src/app/instance/store/selectors/cone-search.selector.spec.ts index 81414c207e6609015ab05152f7dbf1a64be488a5..6ea6f013ac2b287433063f40a485deb2d0c0e39c 100644 --- a/client/src/app/instance/store/selectors/cone-search.selector.spec.ts +++ b/client/src/app/instance/store/selectors/cone-search.selector.spec.ts @@ -7,11 +7,6 @@ describe('[Instance][Store] Cone search selector', () => { expect(coneSearchSelector.selectConeSearch(state)).toBeNull(); }); - it('should get resolver', () => { - const state = { instance: { coneSearch: { ...fromConeSearch.initialState }}}; - expect(coneSearchSelector.selectResolver(state)).toBeNull(); - }); - it('should get resolverIsLoading', () => { const state = { instance: { coneSearch: { ...fromConeSearch.initialState }}}; expect(coneSearchSelector.selectResolverIsLoading(state)).toBeFalsy(); diff --git a/client/src/app/instance/store/selectors/cone-search.selector.ts b/client/src/app/instance/store/selectors/cone-search.selector.ts index 695bba185eacc01db90b4dfface55f691ee3d3c7..88da0162faca7fa25ab80f8a34152c0633301cfb 100644 --- a/client/src/app/instance/store/selectors/cone-search.selector.ts +++ b/client/src/app/instance/store/selectors/cone-search.selector.ts @@ -22,11 +22,6 @@ export const selectConeSearch = createSelector( fromConeSearch.selectConeSearch ); -export const selectResolver = createSelector( - selectConeSearchState, - fromConeSearch.selectResolver -); - export const selectResolverIsLoading = createSelector( selectConeSearchState, fromConeSearch.selectResolverIsLoading diff --git a/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts b/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts index 8c39e57671523b10719ad24cd6a38688c038f27c..4a9d88b4e94c260ceb4a5cb5c1c27ab070570d32 100644 --- a/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts +++ b/client/src/app/instance/store/selectors/search-multiple.selector.spec.ts @@ -14,11 +14,6 @@ describe('[Instance][Store] Search multiple selector', () => { expect(searchMultipleSelector.selectCurrentStep(state)).toBeNull(); }); - it('should get positionStepChecked', () => { - const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}}; - expect(searchMultipleSelector.selectPositionStepChecked(state)).toBeFalsy(); - }); - it('should get datasetsStepChecked', () => { const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}}; expect(searchMultipleSelector.selectDatasetsStepChecked(state)).toBeFalsy(); @@ -49,21 +44,6 @@ describe('[Instance][Store] Search multiple selector', () => { expect(searchMultipleSelector.selectDataLength(state).length).toEqual(0); }); - it('should get dataIsLoading', () => { - const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}}; - expect(searchMultipleSelector.selectDataIsLoading(state)).toBeFalsy(); - }); - - it('should get dataIsLoaded', () => { - const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}}; - expect(searchMultipleSelector.selectDataIsLoaded(state)).toBeFalsy(); - }); - - it('should get data', () => { - const state = { instance: { searchMultiple: { ...fromSearchMultiple.initialState }}}; - expect(searchMultipleSelector.selectData(state).length).toEqual(0); - }); - it('should get queryParams', () => { const state = { instance: { diff --git a/client/src/app/instance/store/selectors/search-multiple.selector.ts b/client/src/app/instance/store/selectors/search-multiple.selector.ts index f505bf0618b945beda21741ed178a680f95058ba..1175f6316d238ed0a969a76a88de3f7d75edd5e9 100644 --- a/client/src/app/instance/store/selectors/search-multiple.selector.ts +++ b/client/src/app/instance/store/selectors/search-multiple.selector.ts @@ -9,7 +9,7 @@ import { createSelector } from '@ngrx/store'; -import { SearchMultipleQueryParams, ConeSearch } from '../models'; +import { SearchMultipleQueryParams, ConeSearch, coneSearchToString } from '../models'; import * as reducer from '../../instance.reducer'; import * as fromSearchMultiple from '../reducers/search-multiple.reducer'; import * as coneSearchSelector from './cone-search.selector'; @@ -29,11 +29,6 @@ export const selectCurrentStep = createSelector( fromSearchMultiple.selectCurrentStep ); -export const selectPositionStepChecked = createSelector( - selectSearchMultipleState, - fromSearchMultiple.selectPositionStepChecked -); - export const selectDatasetsStepChecked = createSelector( selectSearchMultipleState, fromSearchMultiple.selectDatasetsStepChecked @@ -64,21 +59,6 @@ export const selectDataLength = createSelector( fromSearchMultiple.selectDataLength ); -export const selectDataIsLoading = createSelector( - selectSearchMultipleState, - fromSearchMultiple.selectDataIsLoading -); - -export const selectDataIsLoaded = createSelector( - selectSearchMultipleState, - fromSearchMultiple.selectDataIsLoaded -); - -export const selectData = createSelector( - selectSearchMultipleState, - fromSearchMultiple.selectData -); - export const selectQueryParams = createSelector( coneSearchSelector.selectConeSearch, selectSelectedDatasets, @@ -89,7 +69,7 @@ export const selectQueryParams = createSelector( if (coneSearch) { queryParams = { ...queryParams, - cs: `${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}` + cs: `${coneSearchToString(coneSearch)}` }; } if (selectedDatasets.length > 0) { diff --git a/client/src/app/instance/store/selectors/search.selector.ts b/client/src/app/instance/store/selectors/search.selector.ts index 968e07b19bae8ca98cff3634001c8425651e5fbb..78d2e6d0a06c4e6f74b7e801b3341c827b785745 100644 --- a/client/src/app/instance/store/selectors/search.selector.ts +++ b/client/src/app/instance/store/selectors/search.selector.ts @@ -9,7 +9,7 @@ import { createSelector } from '@ngrx/store'; -import { Criterion, SearchQueryParams, criterionToString, ConeSearch } from '../models'; +import { Criterion, SearchQueryParams, criterionToString, ConeSearch, coneSearchToString } from '../models'; import * as reducer from '../../instance.reducer'; import * as fromSearch from '../reducers/search.reducer'; import * as coneSearchSelector from './cone-search.selector'; @@ -124,7 +124,7 @@ export const selectQueryParams = createSelector( if (coneSearch) { queryParams = { ...queryParams, - cs: `${coneSearch.ra}:${coneSearch.dec}:${coneSearch.radius}` + cs: coneSearchToString(coneSearch) }; } if (criteriaList.length > 0) { diff --git a/client/src/app/metamodel/actions/attribute.actions.ts b/client/src/app/metamodel/actions/attribute.actions.ts index 4bd5d6401e8c0218f9f3e5a5fefe9bee4d048189..63c9f6f8d3f2fa5677cc39ab678759dd83cdd1fe 100644 --- a/client/src/app/metamodel/actions/attribute.actions.ts +++ b/client/src/app/metamodel/actions/attribute.actions.ts @@ -11,6 +11,7 @@ import { createAction, props } from '@ngrx/store'; import { Attribute } from '../models'; +export const resetAttributeList = createAction('[Metamodel] Reset Attribute List'); export const loadAttributeList = createAction('[Metamodel] Load Attribute List'); export const loadAttributeListSuccess = createAction('[Metamodel] Load Attribute List Success', props<{ attributes: Attribute[] }>()); export const loadAttributeListFail = createAction('[Metamodel] Load Attribute List Fail'); diff --git a/client/src/app/metamodel/actions/cone-search-config.actions.ts b/client/src/app/metamodel/actions/cone-search-config.actions.ts index e9346bb57052fcfd95422f00f35073addd19450d..7ca1e7d963b5f6f738a6ccd69a5fa9ace58d53dd 100644 --- a/client/src/app/metamodel/actions/cone-search-config.actions.ts +++ b/client/src/app/metamodel/actions/cone-search-config.actions.ts @@ -11,6 +11,7 @@ import { createAction, props } from '@ngrx/store'; import { ConeSearchConfig } from '../models'; +export const resetConeSearchConfig = createAction('[Metamodel] Reset Cone Search Config'); export const loadConeSearchConfig = createAction('[Metamodel] Load Cone Search Config'); export const loadConeSearchConfigSuccess = createAction('[Metamodel] Load Cone Search Config Success', props<{ coneSearchConfig: ConeSearchConfig }>()); export const loadConeSearchConfigFail = createAction('[Metamodel] Load Cone Search Config Fail'); diff --git a/client/src/app/metamodel/effects/instance.effects.spec.ts b/client/src/app/metamodel/effects/instance.effects.spec.ts index fc2ca615d568484307418ffff54b0e0ebb60f2dc..3dd8b60da8b95f3ccf724af60b63de13a1fbf45d 100644 --- a/client/src/app/metamodel/effects/instance.effects.spec.ts +++ b/client/src/app/metamodel/effects/instance.effects.spec.ts @@ -204,8 +204,6 @@ describe('[Metamodel][Effects] InstanceEffects', () => { 'Instance successfully edited', 'The existing instance has been edited into the database' ); - expect(routerSpy).toHaveBeenCalledTimes(1); - expect(routerSpy).toHaveBeenCalledWith(['/admin/instance/instance-list']); }); }); diff --git a/client/src/app/metamodel/effects/instance.effects.ts b/client/src/app/metamodel/effects/instance.effects.ts index bbd8dcc3945e8624d47c73c8a5226fb2a7b242cd..a6fa6327b577d4aaecd89721e8cc7397234743c0 100644 --- a/client/src/app/metamodel/effects/instance.effects.ts +++ b/client/src/app/metamodel/effects/instance.effects.ts @@ -99,10 +99,7 @@ export class InstanceEffects { editInstanceSuccess$ = createEffect(() => this.actions$.pipe( ofType(instanceActions.editInstanceSuccess), - tap(() => { - this.router.navigate(['/admin/instance/instance-list']); - this.toastr.success('Instance successfully edited', 'The existing instance has been edited into the database') - }) + tap(() => this.toastr.success('Instance successfully edited', 'The existing instance has been edited into the database')) ), { dispatch: false } ); diff --git a/client/src/app/metamodel/models/attribute.model.ts b/client/src/app/metamodel/models/attribute.model.ts index ab96827eca36153c04b2b853ea1f47c5b6ccd7e5..0ae58e28c79a4e670814a51fd94940220c1141e0 100644 --- a/client/src/app/metamodel/models/attribute.model.ts +++ b/client/src/app/metamodel/models/attribute.model.ts @@ -38,6 +38,8 @@ export interface Attribute { order_by: boolean; archive: boolean; detail_display: number; + detail_renderer: string; + detail_renderer_config: RendererConfig; options: Option[]; vo_utype: string; vo_ucd: string; diff --git a/client/src/app/metamodel/models/cone-search-config.model.ts b/client/src/app/metamodel/models/cone-search-config.model.ts index b067ff0d41911a9158e27cf8387b37ddf2c02dac..85228e87e9dabb4fb8304b680e32caa9086ed11f 100644 --- a/client/src/app/metamodel/models/cone-search-config.model.ts +++ b/client/src/app/metamodel/models/cone-search-config.model.ts @@ -18,5 +18,10 @@ export interface ConeSearchConfig { opened: boolean; column_ra: number; column_dec: number; + resolver_enabled: boolean; + default_ra: number; + default_dec: number; + default_radius: number; + default_ra_dec_unit: string; plot_enabled: boolean; } diff --git a/client/src/app/metamodel/models/index.ts b/client/src/app/metamodel/models/index.ts index 12e9e400a19a77764cc1c28aad386786e3b0fec9..6fba669fd1b90350ed484c3975ff7195c70f82d3 100644 --- a/client/src/app/metamodel/models/index.ts +++ b/client/src/app/metamodel/models/index.ts @@ -25,3 +25,4 @@ export * from './detail-config.model'; export * from './file.model'; export * from './webpage.model'; export * from './webpage-family'; +export * from './logo.model'; diff --git a/client/src/app/metamodel/models/instance.model.ts b/client/src/app/metamodel/models/instance.model.ts index e472c3806f2ecaa0ee9ae01ce0ac104f34c6e63c..2849ef3623d5acc0b2fb1229ebf0983e139d647a 100644 --- a/client/src/app/metamodel/models/instance.model.ts +++ b/client/src/app/metamodel/models/instance.model.ts @@ -7,6 +7,8 @@ * file that was distributed with this source code. */ +import { Logo } from './logo.model'; + /** * Interface for instance. * @@ -24,48 +26,83 @@ export interface Instance { files_path: string; public: boolean; portal_logo: string; - design_color: string; + portal_color: string; design_background_color: string; + design_text_color: string; + design_font_family: string; + design_link_color: string; + design_link_hover_color: string; design_logo: string; + design_logo_href: string; design_favicon: string; navbar_background_color: string; navbar_border_bottom_color: string; navbar_color_href: string; + navbar_font_family: string; + navbar_sign_in_btn_color: string; + navbar_user_btn_color: string; footer_background_color: string; footer_border_top_color: string; footer_text_color: string; + footer_logos: Logo[]; family_border_color: string; family_header_background_color: string; family_title_color: string; family_title_bold: boolean; family_background_color: string; - family_color: string; + family_text_color: string; progress_bar_title: string; progress_bar_title_color: string; progress_bar_subtitle: string; progress_bar_subtitle_color: string; + progress_bar_step_dataset_title: string; + progress_bar_step_criteria_title: string; + progress_bar_step_output_title: string; + progress_bar_step_result_title: string; progress_bar_color: string; progress_bar_active_color: string; progress_bar_circle_color: string; progress_bar_circle_icon_color: string; progress_bar_circle_icon_active_color: string; progress_bar_text_color: string; - result_header_background_color: string; - result_header_text_color: string; - result_header_btn_color: string; - result_header_btn_hover_color: string; - result_header_btn_text_color: string; + progress_bar_text_bold: boolean; + search_next_btn_color: string; + search_next_btn_hover_color: string; + search_next_btn_hover_text_color: string; + search_back_btn_color: string; + search_back_btn_hover_color: string; + search_back_btn_hover_text_color: string; + search_info_background_color: string; + search_info_text_color: string; + search_info_help_enabled: boolean; + dataset_select_btn_color: string; + dataset_select_btn_hover_color: string; + dataset_select_btn_hover_text_color: string; + dataset_selected_icon_color: string; + search_criterion_background_color: string; + search_criterion_text_color: string; + output_columns_selected_color: string; + output_columns_select_all_btn_color: string; + output_columns_select_all_btn_hover_color: string; + output_columns_select_all_btn_hover_text_color: string; + result_download_btn_color: string; + result_download_btn_hover_color: string; + result_download_btn_text_color: string; + result_datatable_actions_btn_color: string; + result_datatable_actions_btn_hover_color: string; + result_datatable_actions_btn_text_color: string; result_datatable_bordered: boolean; + result_datatable_bordered_radius: boolean; result_datatable_border_color: string; result_datatable_header_background_color: string; result_datatable_header_text_color: string; result_datatable_rows_background_color: string; result_datatable_rows_text_color: string; - result_datatable_sorted_color: string, - result_datatable_sorted_active_color: string, - result_datatable_link_color: string, - result_datatable_link_hover_color: string, - result_datatable_rows_selected_color: string, + result_datatable_sorted_color: string; + result_datatable_sorted_active_color: string; + result_datatable_link_color: string; + result_datatable_link_hover_color: string; + result_datatable_rows_selected_color: string; samp_enabled: boolean; back_to_portal: boolean; user_menu_enabled: boolean; diff --git a/client/src/app/instance/store/models/search-multiple-dataset-data.ts b/client/src/app/metamodel/models/logo.model.ts similarity index 60% rename from client/src/app/instance/store/models/search-multiple-dataset-data.ts rename to client/src/app/metamodel/models/logo.model.ts index 0f3d0d86928cb33b5ca735f14aea4fc281b1d4da..9da48b8a3f5e5a432b1871b5bf382c803aa92f18 100644 --- a/client/src/app/instance/store/models/search-multiple-dataset-data.ts +++ b/client/src/app/metamodel/models/logo.model.ts @@ -8,11 +8,13 @@ */ /** - * Interface for search multiple data. + * Interface for logo. * - * @interface SearchMultipleDatasetData + * @interface Logo */ -export interface SearchMultipleDatasetData { - datasetName: string; - data: any[]; +export interface Logo { + href: string; + title: string; + file: string; + display: number; } diff --git a/client/src/app/metamodel/reducers/attribute.reducer.ts b/client/src/app/metamodel/reducers/attribute.reducer.ts index 3def9fef90535dcb6dcf5875d2b84dd7dbe78ebc..a50f4bd65e25253252332713e59be56fb5568bba 100644 --- a/client/src/app/metamodel/reducers/attribute.reducer.ts +++ b/client/src/app/metamodel/reducers/attribute.reducer.ts @@ -32,6 +32,11 @@ export const initialState: State = adapter.getInitialState({ export const attributeReducer = createReducer( initialState, + on(attributeActions.resetAttributeList, () => { + return { + ...initialState + } + }), on(attributeActions.loadAttributeList, (state) => { return { ...state, diff --git a/client/src/app/metamodel/reducers/cone-search-config.reducer.ts b/client/src/app/metamodel/reducers/cone-search-config.reducer.ts index b2aa464a313e29e61879fde21d8776b7ae0b60a8..5caea58a28b95e08867d6a0be736aa609b5d85c8 100644 --- a/client/src/app/metamodel/reducers/cone-search-config.reducer.ts +++ b/client/src/app/metamodel/reducers/cone-search-config.reducer.ts @@ -31,6 +31,11 @@ export const initialState: State = { export const coneSearchConfigReducer = createReducer( initialState, + on(coneSearchActions.resetConeSearchConfig, () => { + return { + ...initialState + } + }), on(coneSearchActions.loadConeSearchConfig, (state) => { return { ...state, diff --git a/client/src/app/portal/components/instance-card.component.html b/client/src/app/portal/components/instance-card.component.html index 06eafcaf036986bb721a0c38be1d24abeb009616..47c511825d6f04fe48c2e83dfd643aad256d3155 100644 --- a/client/src/app/portal/components/instance-card.component.html +++ b/client/src/app/portal/components/instance-card.component.html @@ -1,6 +1,6 @@ <div class="card card-instance"> <img *ngIf="instance.portal_logo" class="card-header card-img-top card-instance-img" src="{{ getLogoSrc() }}" alt="Card image cap"> - <div *ngIf="!instance.portal_logo" class="card-header card-instance-letter" [ngStyle]="{'background-color': instance.design_color }">{{ instance.label[0] }}</div> + <div *ngIf="!instance.portal_logo" class="card-header card-instance-letter" [ngStyle]="{'background-color': instance.portal_color }">{{ instance.label[0] }}</div> <div class="card-body card-instance-body"> <h5 class="card-title">{{ instance.label }}</h5> <p> diff --git a/client/src/app/portal/containers/portal-home.component.html b/client/src/app/portal/containers/portal-home.component.html index ba726a547cb4689f290c2be833c770c860bb8301..343f6bd4dadc0d6b0842d9e244aba03f9838e8fa 100644 --- a/client/src/app/portal/containers/portal-home.component.html +++ b/client/src/app/portal/containers/portal-home.component.html @@ -1,38 +1,41 @@ -<header> - <app-portal-navbar - [isAuthenticated]="isAuthenticated | async" - [userProfile]="userProfile | async" - [userRoles]="userRoles | async" - [authenticationEnabled]="getAuthenticationEnabled()" - [adminRoles]="getAdminRoles()" - (login)="login()" - (logout)="logout()" - (openEditProfile)="openEditProfile()"> - </app-portal-navbar> -</header> -<main role="main" class="container-fluid pb-4"> - <div class="container"> - <ng-container *ngIf="(instanceList | async).length === 0"> - <div class="col-12 lead text-center font-weight-bold"> - Oops! No instances available... - <span *ngIf="!(isAuthenticated | async)"> - Try to sign in to access to protected instances. - </span> - </div> - </ng-container> - - <div class="row justify-content-center"> - <div class="col-auto mb-3" *ngFor="let instance of (instanceList | async)"> - <app-instance-card - [instance]="instance" - [authenticationEnabled]="getAuthenticationEnabled()" - [isAuthenticated]="isAuthenticated | async" - [userRoles]="userRoles | async" - [adminRoles]="getAdminRoles()" - [instanceGroupList]="instanceGroupList | async" - [apiUrl]="getApiUrl()"> - </app-instance-card> +<div class="d-flex flex-column h-100"> + <header> + <app-portal-navbar + [isAuthenticated]="isAuthenticated | async" + [userProfile]="userProfile | async" + [userRoles]="userRoles | async" + [authenticationEnabled]="getAuthenticationEnabled()" + [adminRoles]="getAdminRoles()" + (login)="login()" + (logout)="logout()" + (openEditProfile)="openEditProfile()"> + </app-portal-navbar> + </header> + <main role="main" class="container-fluid pb-4"> + <div class="container"> + <ng-container *ngIf="(instanceList | async).length === 0"> + <div class="col-12 lead text-center font-weight-bold"> + Oops! No instances available... + <span *ngIf="!(isAuthenticated | async)"> + Try to sign in to access to protected instances. + </span> + </div> + </ng-container> + + <div class="row justify-content-center"> + <div class="col-auto mb-3" *ngFor="let instance of (instanceList | async)"> + <app-instance-card + [instance]="instance" + [authenticationEnabled]="getAuthenticationEnabled()" + [isAuthenticated]="isAuthenticated | async" + [userRoles]="userRoles | async" + [adminRoles]="getAdminRoles()" + [instanceGroupList]="instanceGroupList | async" + [apiUrl]="getApiUrl()"> + </app-instance-card> + </div> </div> </div> - </div> -</main> + </main> + <app-footer class="footer mt-auto"></app-footer> +</div> diff --git a/client/src/app/portal/containers/portal-home.component.ts b/client/src/app/portal/containers/portal-home.component.ts index 92b94a2d76add42862c44dd15994a60c088fe1c2..52df372e15a75f137f26205ce2aae3cea7815d53 100644 --- a/client/src/app/portal/containers/portal-home.component.ts +++ b/client/src/app/portal/containers/portal-home.component.ts @@ -34,7 +34,6 @@ import { StyleService } from 'src/app/shared/services/style.service'; }) export class PortalHomeComponent implements OnInit { public favIcon: HTMLLinkElement = document.querySelector('#favicon'); - public body: HTMLBodyElement = document.querySelector('body'); public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; public userRoles: Observable<string[]>; @@ -52,7 +51,6 @@ export class PortalHomeComponent implements OnInit { ngOnInit() { this.favIcon.href = 'favicon.ico'; - this.body.style.backgroundColor = 'white'; this.style.setStyles('.footer', { 'background-color': '#F8F9FA', 'border-top': 'none', diff --git a/client/src/app/shared/components/footer.component.html b/client/src/app/shared/components/footer.component.html new file mode 100644 index 0000000000000000000000000000000000000000..4492f7132d15fb6f53e368c003e95e5bffc0ed76 --- /dev/null +++ b/client/src/app/shared/components/footer.component.html @@ -0,0 +1,40 @@ +<footer> + <div class="container my-3"> + <div class="row justify-content-center font-weight-bold mb-1"> + © ANIS 2014 - {{ year }} + </div> + <div class="row justify-content-center font-weight-bold mb-4"> + Currently based on ANIS v{{ anisClientVersion }}. + </div> + <div class="row justify-content-center font-weight-bold mb-4"> + Code licensed CeCILL. + </div> + <div class="row justify-content-around"> + <div class="col mb-3 text-center"> + <a href="http://cesam.lam.fr" title="Centre de données Astrophysique de Marseille"> + <img class="img-fluid" src="assets/logo_cesam_s.png" alt="CeSAM" /> + </a> + </div> + <div class="col text-center"> + <a href="http://lam.fr" title="Laboratoire d'Astrophysique de Marseille"> + <img class="img-fluid" src="assets/logo_lam_s.png" alt="LAM" /> + </a> + </div> + <div class="col text-center"> + <a href="http://www.univ-amu.fr" title="Aix*Marseille Université"> + <img class="img-fluid" src="assets/logo_amu_s.png" alt="AMU" /> + </a> + </div> + <div class="col text-center"> + <a href="http://www.insu.cnrs.fr" title="Institut National des Sciences de l'Univers"> + <img class="img-fluid" src="assets/logo_insu_s.png" alt="INSU" /> + </a> + </div> + <div class="col text-center"> + <a href="http://anis.lam.fr" title="AstroNomical Information System"> + <img class="img-fluid" src="assets/cesam_anis40.png" alt="ANIS" /> + </a> + </div> + </div> + </div> +</footer> \ No newline at end of file diff --git a/client/src/app/shared/components/footer.component.ts b/client/src/app/shared/components/footer.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..2f5697fa31a82a38f802ac58c41dfd8e5884381a --- /dev/null +++ b/client/src/app/shared/components/footer.component.ts @@ -0,0 +1,11 @@ +import { Component, ChangeDetectionStrategy } from '@angular/core'; + +@Component({ + selector: 'app-footer', + templateUrl: 'footer.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FooterComponent { + public anisClientVersion: string = '3.7.0'; + public year: number = (new Date()).getFullYear(); +} diff --git a/client/src/app/shared/components/index.ts b/client/src/app/shared/components/index.ts index 18a3063846b295a531f6311a1637ce0c83265947..e332eb5a04713460840acd1e9d40d995f39b0fd1 100644 --- a/client/src/app/shared/components/index.ts +++ b/client/src/app/shared/components/index.ts @@ -7,8 +7,10 @@ * file that was distributed with this source code. */ -import { SpinnerComponent } from "./spinner.component"; +import { SpinnerComponent } from './spinner.component'; +import { FooterComponent } from './footer.component'; export const sharedComponents = [ - SpinnerComponent + SpinnerComponent, + FooterComponent ]; diff --git a/client/src/index.html b/client/src/index.html index 38450df159b25845e1b994fd60679c2732d8e63c..6d603b0b5ccc230cdbfd54dbee60c26d129e7b73 100644 --- a/client/src/index.html +++ b/client/src/index.html @@ -8,6 +8,6 @@ <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> + <app-root></app-root> </body> </html> diff --git a/client/src/styles.scss b/client/src/styles.scss index cc113e36a07ad7d75efe87cb0dc9b00f1b9cf8d0..b316e6034d187fe70efc4ca8566c1b531e8b0b66 100644 --- a/client/src/styles.scss +++ b/client/src/styles.scss @@ -72,7 +72,7 @@ content: counter(linenumber); /* Global styles */ main { - margin-top: 100px; + padding-top: 100px; } .ng-select-container { diff --git a/client/src/test-data.ts b/client/src/test-data.ts index 22c003c1c9089a94abbc4d9dc24f9f57cf1f07fa..2a2fb87dc4f34b5fc73d8d7bd7957423bae47db3 100644 --- a/client/src/test-data.ts +++ b/client/src/test-data.ts @@ -56,38 +56,73 @@ export const INSTANCE_LIST: Instance[] = [ files_path: 'files', public: true, portal_logo: '', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: 'path/to/logo', + design_logo_href: null, design_favicon: 'path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', + footer_logos: null, family_border_color: '#DFDFDF', family_header_background_color: '#F7F7F7', family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', @@ -123,38 +158,73 @@ export const INSTANCE_LIST: Instance[] = [ files_path: 'files', public: true, portal_logo: 'logo.png', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: 'path/to/logo', + design_logo_href: null, design_favicon: 'path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', + footer_logos: null, family_border_color: '#DFDFDF', family_header_background_color: '#F7F7F7', family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', @@ -192,38 +262,73 @@ export const INSTANCE: Instance = { files_path: 'files', public: true, portal_logo: 'logo.png', - design_color: 'green', + portal_color: 'green', design_background_color: 'darker green', + design_text_color: '#212529', + design_font_family: 'Roboto, sans-serif', + design_link_color: '#007BFF', + design_link_hover_color: '#0056B3', design_logo: '/path/to/logo', + design_logo_href: null, design_favicon: '/path/to/favicon', navbar_background_color: '#F8F9FA', navbar_border_bottom_color: '#DEE2E6', navbar_color_href: '#000000', + navbar_font_family: 'Roboto, sans-serif', + navbar_sign_in_btn_color: '#28A745', + navbar_user_btn_color: '#7AC29A', footer_background_color: '#F8F9FA', footer_border_top_color: '#DEE2E6', footer_text_color: '#000000', + footer_logos: null, family_border_color: '#DFDFDF', family_header_background_color: '#F7F7F7', family_title_color: '#007BFF', family_title_bold: false, family_background_color: '#FFFFFF', - family_color: '#212529', + family_text_color: '#212529', progress_bar_title: 'Dataset search', progress_bar_title_color: '#000000', progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.', progress_bar_subtitle_color: '#6C757D', + progress_bar_step_dataset_title: 'Dataset selection', + progress_bar_step_criteria_title: 'Search criteria', + progress_bar_step_output_title: 'Output columns', + progress_bar_step_result_title: 'Result table', progress_bar_color: '#E9ECEF', progress_bar_active_color: '#7AC29A', progress_bar_circle_color: '#FFFFFF', progress_bar_circle_icon_color: '#CCCCCC', progress_bar_circle_icon_active_color: '#FFFFFF', progress_bar_text_color: '#91B2BF', - result_header_background_color: '#E9ECEF', - result_header_text_color: '#000000', - result_header_btn_color: '#007BFF', - result_header_btn_hover_color: '#0069D9', - result_header_btn_text_color: '#FFFFFF', + progress_bar_text_bold: false, + search_next_btn_color: '#007BFF', + search_next_btn_hover_color: '#007BFF', + search_next_btn_hover_text_color: '#FFFFFF', + search_back_btn_color: '#6C757D', + search_back_btn_hover_color: '#6C757D', + search_back_btn_hover_text_color: '#FFFFFF', + search_info_background_color: '#E9ECEF', + search_info_text_color: '#000000', + search_info_help_enabled: true, + dataset_select_btn_color: '#6C757D', + dataset_select_btn_hover_color: '#6C757D', + dataset_select_btn_hover_text_color: '#FFFFFF', + dataset_selected_icon_color: '#28A745', + search_criterion_background_color: '#7AC29A', + search_criterion_text_color: '#000000', + output_columns_selected_color: '#7AC29A', + output_columns_select_all_btn_color: '#6C757D', + output_columns_select_all_btn_hover_color: '#6C757D', + output_columns_select_all_btn_hover_text_color: '#FFFFFF', + result_download_btn_color: '#007BFF', + result_download_btn_hover_color: '#0069D9', + result_download_btn_text_color: '#FFFFFF', + result_datatable_actions_btn_color: '#007BFF', + result_datatable_actions_btn_hover_color: '#0069D9', + result_datatable_actions_btn_text_color: '#FFFFFF', result_datatable_bordered: true, + result_datatable_bordered_radius: false, result_datatable_border_color: '#DEE2E6', result_datatable_header_background_color: '#FFFFFF', result_datatable_header_text_color: '#000000', @@ -366,6 +471,8 @@ export const ATTRIBUTE_LIST: Attribute[] = [ order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -404,6 +511,8 @@ export const ATTRIBUTE_LIST: Attribute[] = [ order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -442,6 +551,8 @@ export const ATTRIBUTE_LIST: Attribute[] = [ order_by: true, archive: false, detail_display: 3, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -480,6 +591,8 @@ export const ATTRIBUTE_LIST: Attribute[] = [ order_by: true, archive: false, detail_display: 4, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, @@ -520,6 +633,8 @@ export const ATTRIBUTE: Attribute = { order_by: true, archive: false, detail_display: 2, + detail_renderer: null, + detail_renderer_config: null, options: [ { label: 'Three', value: 'three', display: 3 }, { label: 'One', value: 'one', display: 1 }, diff --git a/conf-dev/create-db.sh b/conf-dev/create-db.sh index 5375f265fba8f6083b3c1271ec6a9a1ca3e9ee1f..17c4b5e160338a7b63482852aed4ccb551b16b4f 100644 --- a/conf-dev/create-db.sh +++ b/conf-dev/create-db.sh @@ -8,7 +8,7 @@ set -e 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","description":"Instance for the test","scientific_manager":"M. Durand","instrument":"Multiple","wavelength_domain":"Visible imaging / Spectroscopy","display":10,"data_path":"\/DEFAULT","files_path":"\/INSTANCE_FILES","public":true,"portal_logo":"","design_color":"#7AC29A","design_background_color":"#ffffff","design_logo":"/logo.png","design_favicon":"/favicon.ico","navbar_background_color":"#F8F9FA","navbar_border_bottom_color":"#DEE2E6","navbar_color_href":"#000000","footer_background_color":"#F8F9FA","footer_border_top_color":"#DEE2E6","footer_text_color":"#000000","family_border_color":"#DFDFDF","family_header_background_color":"#F7F7F7","family_title_color":"#007BFF","family_title_bold":false,"family_background_color":"#FFFFFF","family_color":"#212529","progress_bar_title":"Dataset search","progress_bar_title_color":"#000000","progress_bar_subtitle":"Select a dataset, add criteria, select output columns and display the result.","progress_bar_subtitle_color":"#6C757D","progress_bar_color":"#E9ECEF","progress_bar_active_color":"#7AC29A","progress_bar_circle_color":"#FFFFFF","progress_bar_circle_icon_color":"#CCCCCC","progress_bar_circle_icon_active_color":"#FFFFFF","progress_bar_text_color":"#91B2BF","result_header_background_color":"#E9ECEF","result_header_text_color":"#000000","result_header_btn_color":"#007BFF","result_header_btn_hover_color":"#0069D9","result_header_btn_text_color":"#FFFFFF","result_datatable_bordered":true,"result_datatable_border_color":"#DEE2E6","result_datatable_header_background_color":"#FFFFFF","result_datatable_header_text_color":"#000000","result_datatable_rows_background_color":"#FFFFFF","result_datatable_rows_text_color":"#000000","result_datatable_sorted_color":"#C5C5C5","result_datatable_sorted_active_color":"#000000","result_datatable_link_color":"#007BFF","result_datatable_link_hover_color":"#0056B3","result_datatable_rows_selected_color":"#7AC29A","samp_enabled":true,"back_to_portal":true,"user_menu_enabled":true,"search_by_criteria_allowed":true,"search_by_criteria_label":"Search","search_multiple_allowed":false,"search_multiple_label":"Search multiple","search_multiple_all_datasets_selected":false,"documentation_allowed":false,"documentation_label":"Documentation"}' --header 'Content-Type: application/json' -X POST http://localhost/instance +curl -d '{"name":"default","label":"Default instance","description":"Instance for the test","scientific_manager":"M. Durand","instrument":"Multiple","wavelength_domain":"Visible imaging / Spectroscopy","display":10,"data_path":"\/DEFAULT","files_path":"\/INSTANCE_FILES","public":true,"portal_logo":"","portal_color":"#7AC29A","design_background_color":"#FFFFFF","design_text_color":"#212529","design_font_family":"Roboto, sans-serif","design_link_color":"#007BFF","design_link_hover_color":"#0056B3","design_logo":"/logo.png","design_logo_href":null,"design_favicon":"/favicon.ico","navbar_background_color":"#F8F9FA","navbar_border_bottom_color":"#DEE2E6","navbar_color_href":"#000000","navbar_font_family":"Roboto, sans-serif","navbar_sign_in_btn_color":"#28A745","navbar_user_btn_color":"#7AC29A","footer_background_color":"#F8F9FA","footer_border_top_color":"#DEE2E6","footer_text_color":"#000000","footer_logos":[{"href":"http:\/\/lam.fr","title":"Laboratoire d'\''Astrophysique de Marseille","file":"\/logo_lam_s.png","display":20},{"href":"http:\/\/www.univ-amu.fr","title":"Aix*Marseille Universit\u00e9","file":"\/logo_amu_s.png","display":30},{"href":"http:\/\/anis.lam.fr","title":"AstroNomical Information System","file":"\/cesam_anis40.png","display":50},{"href":"http:\/\/cesam.lam.fr","title":"Centre de donn\u00e9es Astrophysique de Marseille","file":"\/logo_cesam_s.png","display":10},{"href":"http:\/\/www.insu.cnrs.fr","title":"Institut National des Sciences de l'\''Univers","file":"\/logo_insu_s.png","display":40}],"family_border_color":"#DFDFDF","family_header_background_color":"#F7F7F7","family_title_color":"#007BFF","family_title_bold":false,"family_background_color":"#FFFFFF","family_text_color":"#212529","progress_bar_title":"Dataset search","progress_bar_title_color":"#000000","progress_bar_subtitle":"Select a dataset, add criteria, select output columns and display the result.","progress_bar_subtitle_color":"#6C757D","progress_bar_step_dataset_title":"Dataset selection","progress_bar_step_criteria_title":"Search criteria","progress_bar_step_output_title":"Output columns","progress_bar_step_result_title":"Result table","progress_bar_color":"#E9ECEF","progress_bar_active_color":"#7AC29A","progress_bar_circle_color":"#FFFFFF","progress_bar_circle_icon_color":"#CCCCCC","progress_bar_circle_icon_active_color":"#FFFFFF","progress_bar_text_color":"#91B2BF","progress_bar_text_bold":false,"search_next_btn_color":"#007BFF","search_next_btn_hover_color":"#007BFF","search_next_btn_hover_text_color":"#FFFFFF","search_back_btn_color":"#6C757D","search_back_btn_hover_color":"#6C757D","search_back_btn_hover_text_color":"#FFFFFF","dataset_select_btn_color":"#6C757D","dataset_select_btn_hover_color":"#6C757D","dataset_select_btn_hover_text_color":"#FFFFFF","dataset_selected_icon_color":"#28A745","search_info_background_color":"#E9ECEF","search_info_text_color":"#000000","search_info_help_enabled":true,"search_criterion_background_color":"#7AC29A","search_criterion_text_color":"#000000","result_download_btn_color":"#007BFF","result_download_btn_hover_color":"#0069D9","result_download_btn_text_color":"#FFFFFF","output_columns_selected_color":"#7AC29A","output_columns_select_all_btn_color":"#6C757D","output_columns_select_all_btn_hover_color":"#6C757D","output_columns_select_all_btn_hover_text_color":"#FFFFFF","result_datatable_actions_btn_color":"#007BFF","result_datatable_actions_btn_hover_color":"#0069D9","result_datatable_actions_btn_text_color":"#FFFFFF","result_datatable_bordered":true,"result_datatable_bordered_radius":false,"result_datatable_border_color":"#DEE2E6","result_datatable_header_background_color":"#FFFFFF","result_datatable_header_text_color":"#000000","result_datatable_rows_background_color":"#FFFFFF","result_datatable_rows_text_color":"#000000","result_datatable_sorted_color":"#C5C5C5","result_datatable_sorted_active_color":"#000000","result_datatable_link_color":"#007BFF","result_datatable_link_hover_color":"#0056B3","result_datatable_rows_selected_color":"#7AC29A","samp_enabled":true,"back_to_portal":true,"user_menu_enabled":true,"search_by_criteria_allowed":true,"search_by_criteria_label":"Search","search_multiple_allowed":false,"search_multiple_label":"Search multiple","search_multiple_all_datasets_selected":false,"documentation_allowed":false,"documentation_label":"Documentation"}' --header 'Content-Type: application/json' -X POST http://localhost/instance # Add dataset families curl -d '{"label":"Default dataset family","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/dataset-family @@ -28,39 +28,39 @@ curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: 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,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"field","type":"decimal","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"detail-link","renderer_config":{"display":"text"},"detail_display":10,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":2,"name":"alpha","label":"alpha","form_label":"alpha","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":3,"name":"delta","label":"delta","form_label":"delta","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":4,"name":"selmag","label":"selmag","form_label":"selmag","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":5,"name":"errselmag","label":"errselmag","form_label":"errselmag","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":6,"name":"pointing","label":"pointing","form_label":"pointing","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":7,"name":"quadrant","label":"quadrant","form_label":"quadrant","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":70,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":8,"name":"zspec","label":"zspec","form_label":"zspec","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":80,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":9,"name":"zflg","label":"zflg","form_label":"zflg","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":"datalist","type":"decimal","operator":"in","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":90,"selected":true,"order_by":true,"archive":false,"options":[{"label":"1,2,3,4,9","value":"1,2,3,4,9","display":10},{"label":"2,3,4,9","value":"2,3,4,9","display":20},{"label":"3,4","value":"3,4","display":30},{"label":"1,2,3,4,9,21,22,23,24,29","value":"1,2,3,4,9,21,22,23,24,29","display":40},{"label":"2,3,4,9,22,23,24,29","value":"2,3,4,9,22,23,24,29","display":50}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":10,"name":"norm","label":"norm","form_label":"norm","description":null,"primary_key":false,"output_display":100,"criteria_display":100,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":100,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":11,"name":"epoch","label":"epoch","form_label":"epoch","description":null,"primary_key":false,"output_display":110,"criteria_display":110,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":110,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":12,"name":"photomask","label":"photomask","form_label":"photomask","description":null,"primary_key":false,"output_display":120,"criteria_display":120,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":120,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":56,"name":"spec1d","label":"spec1d","form_label":"spec1d","description":null,"primary_key":false,"output_display":560,"criteria_display":560,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":560,"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":57,"name":"spec1dnoise","label":"spec1dnoise","form_label":"spec1dnoise","description":null,"primary_key":false,"output_display":570,"criteria_display":570,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":570,"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute -curl -d '{"id":58,"name":"spec1dsky","label":"spec1dsky","form_label":"spec1dsky","description":null,"primary_key":false,"output_display":580,"criteria_display":580,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":580,"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":1,"name":"num","label":"num","form_label":"num","description":null,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"field","type":"decimal","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"detail-link","renderer_config":{"display":"text"},"detail_display":10,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":2,"name":"alpha","label":"alpha","form_label":"alpha","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":3,"name":"delta","label":"delta","form_label":"delta","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":4,"name":"selmag","label":"selmag","form_label":"selmag","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":5,"name":"errselmag","label":"errselmag","form_label":"errselmag","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":6,"name":"pointing","label":"pointing","form_label":"pointing","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":7,"name":"quadrant","label":"quadrant","form_label":"quadrant","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":70,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":8,"name":"zspec","label":"zspec","form_label":"zspec","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":80,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":1,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":9,"name":"zflg","label":"zflg","form_label":"zflg","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":"datalist","type":"decimal","operator":"in","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":90,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":[{"label":"1,2,3,4,9","value":"1,2,3,4,9","display":10},{"label":"2,3,4,9","value":"2,3,4,9","display":20},{"label":"3,4","value":"3,4","display":30},{"label":"1,2,3,4,9,21,22,23,24,29","value":"1,2,3,4,9,21,22,23,24,29","display":40},{"label":"2,3,4,9,22,23,24,29","value":"2,3,4,9,22,23,24,29","display":50}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":10,"name":"norm","label":"norm","form_label":"norm","description":null,"primary_key":false,"output_display":100,"criteria_display":100,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":100,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":11,"name":"epoch","label":"epoch","form_label":"epoch","description":null,"primary_key":false,"output_display":110,"criteria_display":110,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":110,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":12,"name":"photomask","label":"photomask","form_label":"photomask","description":null,"primary_key":false,"output_display":120,"criteria_display":120,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":120,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":56,"name":"spec1d","label":"spec1d","form_label":"spec1d","description":null,"primary_key":false,"output_display":560,"criteria_display":560,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":560,"detail_renderer":"download","detail_renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":57,"name":"spec1dnoise","label":"spec1dnoise","form_label":"spec1dnoise","description":null,"primary_key":false,"output_display":570,"criteria_display":570,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":570,"detail_renderer":"download","detail_renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute +curl -d '{"id":58,"name":"spec1dsky","label":"spec1dsky","form_label":"spec1dsky","description":null,"primary_key":false,"output_display":580,"criteria_display":580,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":580,"detail_renderer":"download","detail_renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"selected":true,"order_by":false,"archive":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":1,"id_detail_output_category":1}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/attribute # Add vipers_dr2_w1 detail config -curl -d '{"content":"<div class=\"row\">\n <div class=\"col col-md-8 col-sm-12\">\n <app-display-spectra\n [object]=\"context.object\"\n [datasetName]=\"context.datasetName\"\n [attributeList]=\"context.attributeList\"\n [attributeSpectraId]=\"56\"\n [attributeZId]=\"8\">\n </app-display-spectra>\n </div>\n <div class=\"col col-md-4 col-sm-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n <app-display-object \n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [outputFamilyList]=\"context.outputFamilyList\"\n [outputCategoryList]=\"context.outputCategoryList\">\n </app-display-object>\n </div>\n</div>","style_sheet":""}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/detail-config +curl -d '{"content":"<div class=\"row\">\n <div class=\"col-md-8 col-sm-12\">\n <app-display-spectra\n [object]=\"context.object\"\n [datasetName]=\"context.dataset.name\"\n [attributeList]=\"context.attributeList\"\n [attributeSpectraId]=\"56\"\n [attributeZId]=\"8\">\n </app-display-spectra>\n </div>\n <div class=\"col-md-4 col-sm-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n <app-display-object \n [object]=\"context.object\"\n [dataset]=\"context.dataset\"\n [instance]=\"context.instance\"\n [attributeList]=\"context.attributeList\"\n [outputFamilyList]=\"context.outputFamilyList\"\n [outputCategoryList]=\"context.outputCategoryList\"\n [queryParams]=\"context.queryParams\">\n </app-display-object>\n </div>\n</div>\n","style_sheet":""}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vipers_dr2_w1/detail-config # Add sp_cards attributes curl -d '{"label":"Card","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/criteria-family curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/output-family 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,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"detail_display":10,"selected":true,"order_by":true,"archive":false,"detail":false,"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},{"label":"OBLC_ECL","value":"OBLC_ECL","display":40}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":2,"name":"sp_id","label":"sp_id","form_label":"SP IAP ID","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":3,"name":"version","label":"version","form_label":"Version","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":4,"name":"program","label":"program","form_label":"Program","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"CP","value":"CP","display":10},{"label":"GP","value":"GP","display":20}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":5,"name":"instrument","label":"instrument","form_label":"Instrument","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"ALL","value":"ALL","display":10},{"label":"MXT","value":"MXT","display":20}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":6,"name":"type","label":"type","form_label":"Type","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":7,"name":"json_schema","label":"json_schema","form_label":"JSON Schema (original)","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"detail_display":70,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":8,"name":"search_kw","label":"search_kw","form_label":"KWs searchable","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"detail_display":80,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute -curl -d '{"id":9,"name":"json_schema_uploaded","label":"json_schema_uploaded","form_label":"json_schema_uploaded","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":90,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":1,"name":"acronym","label":"acronym","form_label":"Product Acronym","description":null,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"detail_display":10,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"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},{"label":"OBLC_ECL","value":"OBLC_ECL","display":40}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":2,"name":"sp_id","label":"sp_id","form_label":"SP IAP ID","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":3,"name":"version","label":"version","form_label":"Version","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":4,"name":"program","label":"program","form_label":"Program","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"CP","value":"CP","display":10},{"label":"GP","value":"GP","display":20}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":5,"name":"instrument","label":"instrument","form_label":"Instrument","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"ALL","value":"ALL","display":10},{"label":"MXT","value":"MXT","display":20}],"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,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":6,"name":"type","label":"type","form_label":"Type","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":7,"name":"json_schema","label":"json_schema","form_label":"JSON Schema (original)","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"detail_display":70,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":8,"name":"search_kw","label":"search_kw","form_label":"KWs searchable","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"detail_display":80,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":2,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/sp_cards/attribute +curl -d '{"id":9,"name":"json_schema_uploaded","label":"json_schema_uploaded","form_label":"json_schema_uploaded","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":null,"type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":90,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":null,"id_detail_output_category":null,"id_detail_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,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/criteria-family @@ -68,35 +68,35 @@ curl -d '{"label":"Default parameters","display":10,"opened":true}' --header 'Co 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 -curl -d '{"id":1,"name":"id","label":"id","form_label":"id","description":"Observation Ident","primary_key":true,"output_display":10,"criteria_display":10,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":10,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":2,"name":"ra","label":"ra","form_label":"Alpha J2000","description":"Alpha J2000","primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":3,"name":"dec","label":"dec","form_label":"Delta J2000","description":"Delta J2000","primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":4,"name":"date_time","label":"date_time","form_label":"Date Time","description":"Date Time","primary_key":false,"output_display":40,"criteria_display":40,"search_type":"between-date","type":"datetime","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":5,"name":"exposure_time","label":"exposure_time","form_label":"Exposure Time","description":"Exposure Time","primary_key":false,"output_display":50,"criteria_display":50,"search_type":"between","type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":6,"name":"filter","label":"filter","form_label":"Filter","description":"Filter","primary_key":false,"output_display":60,"criteria_display":60,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"Halpha","value":"Halpha","display":10},{"label":"SDSS g","value":"SDSS g","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":7,"name":"object_name","label":"object_name","form_label":"Object name","description":"Object name","primary_key":false,"output_display":70,"criteria_display":70,"search_type":"field","type":"string","operator":"lk","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"link","renderer_config":{"href":"http:\/\/cdsportal.u-strasbg.fr\/?target=$value","display":"text","text":"$value","icon":"fas fa-link","blank":true},"detail_display":70,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":8,"name":"fits_file","label":"fits_file","form_label":"fits_file","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":80,"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":9,"name":"fits_png","label":"fits_png","form_label":"fits_png","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"image","renderer_config":{"type":"fits","display":"modal","width":"50","height":"50"},"detail_display":90,"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute -curl -d '{"id":10,"name":"id_obspack","label":"id_obspack","form_label":"id_obspack","description":null,"primary_key":false,"type":"integer","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"options":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":100,"output_display":100,"selected":true,"renderer":"link","renderer_config":{"href":"/instance/default/search/result/iris_obspack?s=100&a=1;2;3&c=1::eq::$value","display":"text","text":"$value","icon":"fas fa-link","blank":false},"order_by":true,"archive":false,"detail_display":100,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":1,"name":"id","label":"id","form_label":"id","description":"Observation Ident","primary_key":true,"output_display":10,"criteria_display":10,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"detail-link","renderer_config":{"display":"text"},"detail_display":10,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":2,"name":"ra","label":"ra","form_label":"Alpha J2000","description":"Alpha J2000","primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":3,"name":"dec","label":"dec","form_label":"Delta J2000","description":"Delta J2000","primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":3,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":4,"name":"date_time","label":"date_time","form_label":"Date Time","description":"Date Time","primary_key":false,"output_display":40,"criteria_display":40,"search_type":"between-date","type":"datetime","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":5,"name":"exposure_time","label":"exposure_time","form_label":"Exposure Time","description":"Exposure Time","primary_key":false,"output_display":50,"criteria_display":50,"search_type":"between","type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":6,"name":"filter","label":"filter","form_label":"Filter","description":"Filter","primary_key":false,"output_display":60,"criteria_display":60,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":[{"label":"Halpha","value":"Halpha","display":10},{"label":"SDSS g","value":"SDSS g","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":7,"name":"object_name","label":"object_name","form_label":"Object name","description":"Object name","primary_key":false,"output_display":70,"criteria_display":70,"search_type":"field","type":"string","operator":"lk","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"link","renderer_config":{"href":"http:\/\/cdsportal.u-strasbg.fr\/?target=$value","display":"text","text":"$value","icon":"fas fa-link","blank":true},"detail_display":70,"detail_renderer":"link","detail_renderer_config":{"href":"http:\/\/cdsportal.u-strasbg.fr\/?target=$value","display":"text","text":"$value","icon":"fas fa-link","blank":true},"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":3,"id_output_category":4,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":8,"name":"fits_file","label":"fits_file","form_label":"fits_file","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"download","renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"detail_display":80,"detail_renderer":"download","detail_renderer_config":{"display":"icon-button","text":"DOWNLOAD","icon":"fas fa-download"},"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":4}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":9,"name":"fits_png","label":"fits_png","form_label":"fits_png","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"image","renderer_config":{"type":"fits","display":"modal","width":"50","height":"50"},"detail_display":90,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":false,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute +curl -d '{"id":10,"name":"id_obspack","label":"id_obspack","form_label":"id_obspack","description":null,"primary_key":false,"type":"integer","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"options":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":100,"output_display":100,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"renderer":"link","renderer_config":{"href":"/instance/default/search/result/iris_obspack?s=100&a=1;2;3&c=1::eq::$value","display":"text","text":"$value","icon":"fas fa-link","blank":false},"order_by":true,"archive":false,"detail_display":100,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":4,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/attribute # Add observations detail config -curl -d '{"content":"<div class=\"row justify-content-center\">\n <div class=\"col col-lg-10 col-xl-8 mt-4\">\n <div class=\"row\">\n <div class=\"col-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n </div>\n </div>\n\n <app-display-object \n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [outputFamilyList]=\"context.outputFamilyList\"\n [outputCategoryList]=\"context.outputCategoryList\">\n </app-display-object>\n </div>\n</div>","style_sheet":""}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/detail-config +curl -d '{"content":"<h1 class=\"text-center\">\n <app-display-value-by-attribute\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeId]=\"7\">\n </app-display-value-by-attribute>\n</h1>\n<div class=\"row\">\n <div class=\"col-md-8 col-sm-12 col-xs-12\">\n <app-display-image\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [dataset]=\"context.dataset\"\n [attributeImageId]=\"9\"\n [type]=\"'\''fits'\''\">\n </app-display-image>\n </div>\n <div class=\"col-md-4 col-sm-12 col-xs-12\">\n <app-display-ra-dec\n [object]=\"context.object\"\n [attributeList]=\"context.attributeList\"\n [attributeRaId]=\"2\"\n [attributeDecId]=\"3\">\n </app-display-ra-dec>\n <app-display-object-by-output-category\n [object]=\"context.object\"\n [dataset]=\"context.dataset\"\n [instance]=\"context.instance\"\n [attributeList]=\"context.attributeList\"\n [outputCategoryList]=\"context.outputCategoryList\"\n [queryParams]=\"context.queryParams\"\n [outputCategoryId]=\"4\">\n </app-display-object-by-output-category>\n </div>\n</div>\n","style_sheet":"h1 {\n color: red;\n}\n\n.panel-heading.card-header {\n background-color: #dee2ff;\n}\n\n.panel .btn.btn-link .text-primary {\n color: red !important;\n}\n"}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/observations/detail-config # Add vvds_f02_udeep attributes curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/criteria-family curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/output-family 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,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":10,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":2,"name":"id_iau","label":"id_iau","form_label":"id_iau","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":3,"name":"alpha","label":"alpha","form_label":"alpha","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":4,"name":"delta","label":"delta","form_label":"delta","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":5,"name":"z_spec","label":"z_spec","form_label":"z_spec","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":4,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":6,"name":"zflag","label":"zflag","form_label":"zflag","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute -curl -d '{"id":7,"name":"sel_mag","label":"sel_mag","form_label":"sel_mag","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":70,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":4,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":1,"name":"vvds_ident","label":"vvds_ident","form_label":"vvds_ident","description":null,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":10,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":2,"name":"id_iau","label":"id_iau","form_label":"id_iau","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":20,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":3,"name":"alpha","label":"alpha","form_label":"alpha","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":30,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":4,"name":"delta","label":"delta","form_label":"delta","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":40,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":5,"name":"z_spec","label":"z_spec","form_label":"z_spec","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":50,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":4,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":6,"name":"zflag","label":"zflag","form_label":"zflag","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":null,"type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":60,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":null,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute +curl -d '{"id":7,"name":"sel_mag","label":"sel_mag","form_label":"sel_mag","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":"between","type":"decimal","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_display":70,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":4,"id_output_category":5,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/attribute # Add vvds_f02_udeep cone search -curl -d '{"enabled":true,"opened":false,"column_ra":3,"column_dec":4,"plot_enabled":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/cone-search-config +curl -d '{"enabled":true,"opened":false,"column_ra":3,"column_dec":4,"resolver_enabled":true,"default_ra":null,"default_dec":null,"default_radius":2.0,"default_ra_dec_unit":"degree","plot_enabled":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/cone-search-config # Add vvds_f02_udeep image curl -d '{"label":"Mag i","file_path":"/IMAGES/CFHTLS_D-85_i_022559-042940_T0007_MEDIAN.fits","file_size":1498320000,"ra_min":35.994643451078,"ra_max":36.99765934121,"dec_min":-3.9943006310031,"dec_max":-4.9941936740893,"stretch":"linear","pmin":0.2,"pmax":99}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/vvds_f02_udeep/image @@ -108,21 +108,21 @@ curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/5/output-category curl -d '{"label":"Additionnal","display":20}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/5/output-category -curl -d '{"id":1,"name":"product_id","label":"product_id","form_label":"Product ID","description":null,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"field","type":"integer","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":10,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":2,"name":"obs_id","label":"obs_id","form_label":"Observation ID","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":"field","type":"bigint","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":20,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":3,"name":"acronym","label":"acronym","form_label":"Product Acronym","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":30,"options":[{"label":"ECL-DET-UBC","value":"ECL-DET-UBC","display":10},{"label":"OBLC_ECL","value":"OBLC_ECL","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":4,"name":"url","label":"url","form_label":"Product URL","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"link","renderer_config":{"href":"$value","display":"text","text":"$value","icon":"fas fa-link","blank":true},"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":40,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":5,"name":"criteria","label":"criteria","form_label":"Product criteria (based on KWs searchables)","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"svom_json_kw","type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":50,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":6,"name":"added_at","label":"added_at","form_label":"Added at","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":"between-date","type":"datetime","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":60,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":7,"name":"product_version","label":"product_version","form_label":"Version","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":70,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":8,"name":"program","label":"program","form_label":"Program","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":80,"options":[{"label":"CoreProgram","value":"CoreProgram","display":10},{"label":"GeneralProgram","value":"GeneralProgram","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":9,"name":"instrument","label":"instrument","form_label":"Instrument","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":90,"options":[{"label":"ECL","value":"ECL","display":10}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":10,"name":"type","label":"type","form_label":"Type","description":null,"primary_key":false,"output_display":100,"criteria_display":100,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":100,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":11,"name":"upload_filename","label":"upload_filename","form_label":"Filename","description":null,"primary_key":false,"output_display":110,"criteria_display":110,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":110,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":12,"name":"burst_id","label":"burst_id","form_label":"Burst ID","description":null,"primary_key":false,"output_display":120,"criteria_display":120,"search_type":"field","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":120,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":13,"name":"pipeline_version","label":"pipeline_version","form_label":"Pipeline version","description":null,"primary_key":false,"output_display":130,"criteria_display":130,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":130,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":14,"name":"schema_version","label":"schema_version","form_label":"Schema version","description":null,"primary_key":false,"output_display":140,"criteria_display":140,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":140,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute -curl -d '{"id":15,"name":"src_id","label":"src_id","form_label":"SRC ID","description":null,"primary_key":false,"output_display":150,"criteria_display":150,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":150,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":1,"name":"product_id","label":"product_id","form_label":"Product ID","description":null,"primary_key":true,"output_display":10,"criteria_display":10,"search_type":"field","type":"integer","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":[],"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":10,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":2,"name":"obs_id","label":"obs_id","form_label":"Observation ID","description":null,"primary_key":false,"output_display":20,"criteria_display":20,"search_type":"field","type":"bigint","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":20,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":3,"name":"acronym","label":"acronym","form_label":"Product Acronym","description":null,"primary_key":false,"output_display":30,"criteria_display":30,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":30,"options":[{"label":"ECL-DET-UBC","value":"ECL-DET-UBC","display":10},{"label":"OBLC_ECL","value":"OBLC_ECL","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":4,"name":"url","label":"url","form_label":"Product URL","description":null,"primary_key":false,"output_display":40,"criteria_display":40,"search_type":null,"type":"text","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"link","renderer_config":{"href":"$value","display":"text","text":"$value","icon":"fas fa-link","blank":true},"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":40,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":5,"name":"criteria","label":"criteria","form_label":"Product criteria (based on KWs searchables)","description":null,"primary_key":false,"output_display":50,"criteria_display":50,"search_type":"svom_json_kw","type":"json","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":"json","renderer_config":[],"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":50,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":6,"name":"added_at","label":"added_at","form_label":"Added at","description":null,"primary_key":false,"output_display":60,"criteria_display":60,"search_type":"between-date","type":"datetime","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":60,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":7,"name":"product_version","label":"product_version","form_label":"Version","description":null,"primary_key":false,"output_display":70,"criteria_display":70,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":70,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":8,"name":"program","label":"program","form_label":"Program","description":null,"primary_key":false,"output_display":80,"criteria_display":80,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":80,"options":[{"label":"CoreProgram","value":"CoreProgram","display":10},{"label":"GeneralProgram","value":"GeneralProgram","display":20}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":9,"name":"instrument","label":"instrument","form_label":"Instrument","description":null,"primary_key":false,"output_display":90,"criteria_display":90,"search_type":"select","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":90,"options":[{"label":"ECL","value":"ECL","display":10}],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":6,"id_output_category":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":10,"name":"type","label":"type","form_label":"Type","description":null,"primary_key":false,"output_display":100,"criteria_display":100,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":100,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":11,"name":"upload_filename","label":"upload_filename","form_label":"Filename","description":null,"primary_key":false,"output_display":110,"criteria_display":110,"search_type":null,"type":"string","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":110,"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":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":12,"name":"burst_id","label":"burst_id","form_label":"Burst ID","description":null,"primary_key":false,"output_display":120,"criteria_display":120,"search_type":"field","type":"string","operator":"eq","dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"order_by":true,"archive":false,"detail":false,"detail_display":120,"options":[],"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":5,"id_output_category":6,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":13,"name":"pipeline_version","label":"pipeline_version","form_label":"Pipeline version","description":null,"primary_key":false,"output_display":130,"criteria_display":130,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":130,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":14,"name":"schema_version","label":"schema_version","form_label":"Schema version","description":null,"primary_key":false,"output_display":140,"criteria_display":140,"search_type":null,"type":"float","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":140,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute +curl -d '{"id":15,"name":"src_id","label":"src_id","form_label":"SRC ID","description":null,"primary_key":false,"output_display":150,"criteria_display":150,"search_type":null,"type":"integer","operator":null,"dynamic_operator":true,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"renderer":null,"renderer_config":null,"detail_renderer":null,"detail_renderer_config":null,"selected":false,"order_by":true,"archive":false,"detail":false,"detail_display":150,"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":7,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/products/attribute # Add iris_obspack attributes curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/criteria-family @@ -130,9 +130,9 @@ curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: curl -d '{"label":"Default","display":10,"opened":true}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/output-family curl -d '{"label":"Default","display":10}' --header 'Content-Type: application/json' -X POST http://localhost/output-family/6/output-category -curl -d '{"id":1,"name":"id","label":"id","form_label":"id","description":null,"primary_key":true,"type":"integer","search_type":"field","operator":"eq","dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":10,"output_display":10,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":10,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":7,"id_output_category":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute -curl -d '{"id":2,"name":"date","label":"date","form_label":"date","description":null,"primary_key":false,"type":"datetime","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":20,"output_display":20,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":20,"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":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute -curl -d '{"id":3,"name":"observer","label":"observer","form_label":"observer","description":null,"primary_key":false,"type":"string","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":30,"output_display":30,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":30,"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":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute +curl -d '{"id":1,"name":"id","label":"id","form_label":"id","description":null,"primary_key":true,"type":"integer","search_type":"field","operator":"eq","dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":10,"output_display":10,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":10,"options":null,"vo_utype":null,"vo_ucd":null,"vo_unit":null,"vo_description":null,"vo_datatype":null,"vo_size":null,"id_criteria_family":7,"id_output_category":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute +curl -d '{"id":2,"name":"date","label":"date","form_label":"date","description":null,"primary_key":false,"type":"datetime","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":20,"output_display":20,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":20,"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":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute +curl -d '{"id":3,"name":"observer","label":"observer","form_label":"observer","description":null,"primary_key":false,"type":"string","search_type":null,"operator":null,"dynamic_operator":null,"min":null,"max":null,"placeholder_min":null,"placeholder_max":null,"criteria_display":30,"output_display":30,"detail_renderer":null,"detail_renderer_config":null,"selected":true,"renderer":null,"renderer_config":null,"order_by":true,"archive":false,"detail_display":30,"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":8,"id_detail_output_category":null}' --header 'Content-Type: application/json' -X POST http://localhost/dataset/iris_obspack/attribute # Add webpages curl -d '{"label":"Default","icon":null,"display":10}' --header 'Content-Type: application/json' -X POST http://localhost/instance/default/webpage-family diff --git a/conf-dev/matomo-config.ini.php b/conf-dev/matomo-config.ini.php index 5d6604d6cfbe544345ec277d022b7fb89cea9a5b..70923559d020e6c95c2024ed77ea62fbc03a6ebd 100644 --- a/conf-dev/matomo-config.ini.php +++ b/conf-dev/matomo-config.ini.php @@ -12,6 +12,14 @@ charset = "utf8mb4" salt = "e33c87faae68b909891f6dfc0dc3e5f3" trusted_hosts[] = "localhost:8888" enable_trusted_host_check=0 +noreply_email_address = "noreply@matomo.anis.fr" +login_password_recovery_replyto_email_address = "no-reply@matomo.anis.fr" + +[mail] +transport = "smtp" +port = 25 +host = "mailer" +encryption = 'none'; [PluginsInstalled] PluginsInstalled[] = "Diagnostics" diff --git a/conf-dev/matomo.sql b/conf-dev/matomo.sql index f9062c2aa92cc46e79090a44f8f4273380818465..524feece2cfce3c4cf06e7a16180f988978580af 100644 --- a/conf-dev/matomo.sql +++ b/conf-dev/matomo.sql @@ -1146,13 +1146,15 @@ CREATE TABLE `matomo_user` ( -- -- Dumping data for table `matomo_user` +-- User: cesamsi@lam.fr +-- Pass: TempO.010122 -- LOCK TABLES `matomo_user` WRITE; /*!40000 ALTER TABLE `matomo_user` DISABLE KEYS */; INSERT INTO `matomo_user` VALUES ('anonymous','','anonymous@example.org','',0,'2022-09-07 18:57:33','2022-09-07 18:57:33',NULL,NULL,NULL,NULL,NULL), -('cesamsi@lam.fr','$2y$10$XOrh94bIauTXiwES.LTxYO7NO0cw58Ih09Owimw9VpEAb10fBCtLq','cesamsi@lam.fr','',1,'2022-09-07 18:58:39','2022-09-07 18:58:39',NULL,NULL,NULL,NULL,NULL); +('cesamsi@lam.fr','$2y$10$fl0UB4kU/LDNRLXEMLMv2.Spun10egNh9BkRT5Zmhg0koFPgB5rNC','cesamsi@lam.fr','',1,'2022-09-07 18:58:39','2022-09-07 18:58:39',NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `matomo_user` ENABLE KEYS */; UNLOCK TABLES; diff --git a/server/doctrine-proxy/__CG__AppEntityAttribute.php b/server/doctrine-proxy/__CG__AppEntityAttribute.php index e9734fb01579e1ab7e3a2421e77fc5e46fd5ea72..02130f7c1d5646eb8befef87d3704d8a456032c6 100644 --- a/server/doctrine-proxy/__CG__AppEntityAttribute.php +++ b/server/doctrine-proxy/__CG__AppEntityAttribute.php @@ -67,10 +67,10 @@ class Attribute extends \App\Entity\Attribute implements \Doctrine\ORM\Proxy\Pro public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'id', 'dataset', 'name', 'label', 'formLabel', 'description', 'primaryKey', 'type', 'searchType', 'operator', 'dynamicOperator', 'min', 'max', 'options', 'placeholderMin', 'placeholderMax', 'criteriaDisplay', 'outputDisplay', 'selected', 'renderer', 'rendererConfig', 'orderBy', 'archive', 'detailDisplay', 'voUtype', 'voUcd', 'voUnit', 'voDescription', 'voDatatype', 'voSize', 'criteriaFamily', 'outputCategory', 'detailOutputCategory']; + return ['__isInitialized__', 'id', 'dataset', 'name', 'label', 'formLabel', 'description', 'primaryKey', 'type', 'searchType', 'operator', 'dynamicOperator', 'min', 'max', 'options', 'placeholderMin', 'placeholderMax', 'criteriaDisplay', 'outputDisplay', 'selected', 'renderer', 'rendererConfig', 'orderBy', 'archive', 'detailDisplay', 'detailRenderer', 'detailRendererConfig', 'voUtype', 'voUcd', 'voUnit', 'voDescription', 'voDatatype', 'voSize', 'criteriaFamily', 'outputCategory', 'detailOutputCategory']; } - return ['__isInitialized__', 'id', 'dataset', 'name', 'label', 'formLabel', 'description', 'primaryKey', 'type', 'searchType', 'operator', 'dynamicOperator', 'min', 'max', 'options', 'placeholderMin', 'placeholderMax', 'criteriaDisplay', 'outputDisplay', 'selected', 'renderer', 'rendererConfig', 'orderBy', 'archive', 'detailDisplay', 'voUtype', 'voUcd', 'voUnit', 'voDescription', 'voDatatype', 'voSize', 'criteriaFamily', 'outputCategory', 'detailOutputCategory']; + return ['__isInitialized__', 'id', 'dataset', 'name', 'label', 'formLabel', 'description', 'primaryKey', 'type', 'searchType', 'operator', 'dynamicOperator', 'min', 'max', 'options', 'placeholderMin', 'placeholderMax', 'criteriaDisplay', 'outputDisplay', 'selected', 'renderer', 'rendererConfig', 'orderBy', 'archive', 'detailDisplay', 'detailRenderer', 'detailRendererConfig', 'voUtype', 'voUcd', 'voUnit', 'voDescription', 'voDatatype', 'voSize', 'criteriaFamily', 'outputCategory', 'detailOutputCategory']; } /** @@ -698,6 +698,50 @@ class Attribute extends \App\Entity\Attribute implements \Doctrine\ORM\Proxy\Pro return parent::setDetailDisplay($detailDisplay); } + /** + * {@inheritDoc} + */ + public function getDetailRenderer() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDetailRenderer', []); + + return parent::getDetailRenderer(); + } + + /** + * {@inheritDoc} + */ + public function setDetailRenderer($detailRenderer) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDetailRenderer', [$detailRenderer]); + + return parent::setDetailRenderer($detailRenderer); + } + + /** + * {@inheritDoc} + */ + public function getDetailRendererConfig() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDetailRendererConfig', []); + + return parent::getDetailRendererConfig(); + } + + /** + * {@inheritDoc} + */ + public function setDetailRendererConfig($detailRendererConfig) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDetailRendererConfig', [$detailRendererConfig]); + + return parent::setDetailRendererConfig($detailRendererConfig); + } + /** * {@inheritDoc} */ diff --git a/server/doctrine-proxy/__CG__AppEntityConeSearchConfig.php b/server/doctrine-proxy/__CG__AppEntityConeSearchConfig.php index 42b64ffdbbd31efbafd96e552dc2cae97e7ad7aa..ddb98c40f3fbbe5c9766ed6fb22b52f66d0a498c 100644 --- a/server/doctrine-proxy/__CG__AppEntityConeSearchConfig.php +++ b/server/doctrine-proxy/__CG__AppEntityConeSearchConfig.php @@ -67,10 +67,10 @@ class ConeSearchConfig extends \App\Entity\ConeSearchConfig implements \Doctrine public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'id', 'enabled', 'opened', 'columnRa', 'columnDec', 'plotEnabled']; + return ['__isInitialized__', 'id', 'enabled', 'opened', 'columnRa', 'columnDec', 'resolverEnabled', 'defaultRa', 'defaultDec', 'defaultRadius', 'defaultRaDecUnit', 'plotEnabled']; } - return ['__isInitialized__', 'id', 'enabled', 'opened', 'columnRa', 'columnDec', 'plotEnabled']; + return ['__isInitialized__', 'id', 'enabled', 'opened', 'columnRa', 'columnDec', 'resolverEnabled', 'defaultRa', 'defaultDec', 'defaultRadius', 'defaultRaDecUnit', 'plotEnabled']; } /** @@ -280,6 +280,116 @@ class ConeSearchConfig extends \App\Entity\ConeSearchConfig implements \Doctrine return parent::setColumnDec($columnDec); } + /** + * {@inheritDoc} + */ + public function getResolverEnabled() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResolverEnabled', []); + + return parent::getResolverEnabled(); + } + + /** + * {@inheritDoc} + */ + public function setResolverEnabled($resolverEnabled) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResolverEnabled', [$resolverEnabled]); + + return parent::setResolverEnabled($resolverEnabled); + } + + /** + * {@inheritDoc} + */ + public function getDefaultRa() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDefaultRa', []); + + return parent::getDefaultRa(); + } + + /** + * {@inheritDoc} + */ + public function setDefaultRa($defaultRa) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDefaultRa', [$defaultRa]); + + return parent::setDefaultRa($defaultRa); + } + + /** + * {@inheritDoc} + */ + public function getDefaultDec() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDefaultDec', []); + + return parent::getDefaultDec(); + } + + /** + * {@inheritDoc} + */ + public function setDefaultDec($defaultDec) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDefaultDec', [$defaultDec]); + + return parent::setDefaultDec($defaultDec); + } + + /** + * {@inheritDoc} + */ + public function getDefaultRadius() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDefaultRadius', []); + + return parent::getDefaultRadius(); + } + + /** + * {@inheritDoc} + */ + public function setDefaultRadius($defaultRadius) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDefaultRadius', [$defaultRadius]); + + return parent::setDefaultRadius($defaultRadius); + } + + /** + * {@inheritDoc} + */ + public function getDefaultRaDecUnit() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDefaultRaDecUnit', []); + + return parent::getDefaultRaDecUnit(); + } + + /** + * {@inheritDoc} + */ + public function setDefaultRaDecUnit($defaultRaDecUnit) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDefaultRaDecUnit', [$defaultRaDecUnit]); + + return parent::setDefaultRaDecUnit($defaultRaDecUnit); + } + /** * {@inheritDoc} */ diff --git a/server/doctrine-proxy/__CG__AppEntityInstance.php b/server/doctrine-proxy/__CG__AppEntityInstance.php index 697ea08e79f602ce7a76370ab4c51fc02aaa0e7b..6d3d76abab0152825599515e17e25f406f845647 100644 --- a/server/doctrine-proxy/__CG__AppEntityInstance.php +++ b/server/doctrine-proxy/__CG__AppEntityInstance.php @@ -67,10 +67,10 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy public function __sleep() { if ($this->__isInitialized__) { - return ['__isInitialized__', 'name', 'label', 'description', 'scientificManager', 'instrument', 'wavelengthDomain', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'navbarBackgroundColor', 'navbarBorderBottomColor', 'navbarColorHref', 'footerBackgroundColor', 'footerBorderTopColor', 'footerTextColor', 'familyBorderColor', 'familyHeaderBackgroundColor', 'familyTitleColor', 'familyTitleBold', 'familyBackgroundColor', 'familyColor', 'progressBarTitle', 'progressBarTitleColor', 'progressBarSubtitle', 'progressBarSubtitleColor', 'progressBarColor', 'progressBarActiveColor', 'progressBarCircleColor', 'progressBarCircleIconColor', 'progressBarCircleIconActiveColor', 'progressBarTextColor', 'resultHeaderBackgroundColor', 'resultHeaderTextColor', 'resultHeaderBtnColor', 'resultHeaderBtnHoverColor', 'resultHeaderBtnTextColor', 'resultDatatableBordered', 'resultDatatableBorderColor', 'resultDatatableHeaderBackgroundColor', 'resultDatatableHeaderTextColor', 'resultDatatableRowsBackgroundColor', 'resultDatatableRowsTextColor', 'resultDatatableSortedColor', 'resultDatatableSortedActiveColor', 'resultDatatableLinkColor', 'resultDatatableLinkHoverColor', 'resultDatatableRowsSelectedColor', 'sampEnabled', 'backToPortal', 'userMenuEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; + return ['__isInitialized__', 'name', 'label', 'description', 'scientificManager', 'instrument', 'wavelengthDomain', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'portalColor', 'designBackgroundColor', 'designTextColor', 'designFontFamily', 'designLinkColor', 'designLinkHoverColor', 'designLogo', 'designLogoHref', 'designFavicon', 'navbarBackgroundColor', 'navbarBorderBottomColor', 'navbarColorHref', 'navbarFontFamily', 'navbarSignInBtnColor', 'navbarUserBtnColor', 'footerBackgroundColor', 'footerBorderTopColor', 'footerTextColor', 'footerLogos', 'familyBorderColor', 'familyHeaderBackgroundColor', 'familyTitleColor', 'familyTitleBold', 'familyBackgroundColor', 'familyTextColor', 'progressBarTitle', 'progressBarTitleColor', 'progressBarSubtitle', 'progressBarSubtitleColor', 'progressBarStepDatasetTitle', 'progressBarStepCriteriaTitle', 'progressBarStepOutputTitle', 'progressBarStepResultTitle', 'progressBarColor', 'progressBarActiveColor', 'progressBarCircleColor', 'progressBarCircleIconColor', 'progressBarCircleIconActiveColor', 'progressBarTextColor', 'progressBarTextBold', 'searchNextBtnColor', 'searchNextBtnHoverColor', 'searchNextBtnHoverTextColor', 'searchBackBtnColor', 'searchBackBtnHoverColor', 'searchBackBtnHoverTextColor', 'searchInfoBackgroundColor', 'searchInfoTextColor', 'searchInfoHelpEnabled', 'datasetSelectBtnColor', 'datasetSelectBtnHoverColor', 'datasetSelectBtnHoverTextColor', 'datasetSelectedIconColor', 'searchCriterionBackgroundColor', 'searchCriterionTextColor', 'outputColumnsSelectedColor', 'outputColumnsSelectAllBtnColor', 'outputColumnsSelectAllBtnHoverColor', 'outputColumnsSelectAllBtnHoverTextColor', 'resultDownloadBtnColor', 'resultDownloadBtnHoverColor', 'resultDownloadBtnTextColor', 'resultDatatableActionsBtnColor', 'resultDatatableActionsBtnHoverColor', 'resultDatatableActionsBtnTextColor', 'resultDatatableBordered', 'resultDatatableBorderedRadius', 'resultDatatableBorderColor', 'resultDatatableHeaderBackgroundColor', 'resultDatatableHeaderTextColor', 'resultDatatableRowsBackgroundColor', 'resultDatatableRowsTextColor', 'resultDatatableSortedColor', 'resultDatatableSortedActiveColor', 'resultDatatableLinkColor', 'resultDatatableLinkHoverColor', 'resultDatatableRowsSelectedColor', 'sampEnabled', 'backToPortal', 'userMenuEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; } - return ['__isInitialized__', 'name', 'label', 'description', 'scientificManager', 'instrument', 'wavelengthDomain', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'navbarBackgroundColor', 'navbarBorderBottomColor', 'navbarColorHref', 'footerBackgroundColor', 'footerBorderTopColor', 'footerTextColor', 'familyBorderColor', 'familyHeaderBackgroundColor', 'familyTitleColor', 'familyTitleBold', 'familyBackgroundColor', 'familyColor', 'progressBarTitle', 'progressBarTitleColor', 'progressBarSubtitle', 'progressBarSubtitleColor', 'progressBarColor', 'progressBarActiveColor', 'progressBarCircleColor', 'progressBarCircleIconColor', 'progressBarCircleIconActiveColor', 'progressBarTextColor', 'resultHeaderBackgroundColor', 'resultHeaderTextColor', 'resultHeaderBtnColor', 'resultHeaderBtnHoverColor', 'resultHeaderBtnTextColor', 'resultDatatableBordered', 'resultDatatableBorderColor', 'resultDatatableHeaderBackgroundColor', 'resultDatatableHeaderTextColor', 'resultDatatableRowsBackgroundColor', 'resultDatatableRowsTextColor', 'resultDatatableSortedColor', 'resultDatatableSortedActiveColor', 'resultDatatableLinkColor', 'resultDatatableLinkHoverColor', 'resultDatatableRowsSelectedColor', 'sampEnabled', 'backToPortal', 'userMenuEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; + return ['__isInitialized__', 'name', 'label', 'description', 'scientificManager', 'instrument', 'wavelengthDomain', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'portalColor', 'designBackgroundColor', 'designTextColor', 'designFontFamily', 'designLinkColor', 'designLinkHoverColor', 'designLogo', 'designLogoHref', 'designFavicon', 'navbarBackgroundColor', 'navbarBorderBottomColor', 'navbarColorHref', 'navbarFontFamily', 'navbarSignInBtnColor', 'navbarUserBtnColor', 'footerBackgroundColor', 'footerBorderTopColor', 'footerTextColor', 'footerLogos', 'familyBorderColor', 'familyHeaderBackgroundColor', 'familyTitleColor', 'familyTitleBold', 'familyBackgroundColor', 'familyTextColor', 'progressBarTitle', 'progressBarTitleColor', 'progressBarSubtitle', 'progressBarSubtitleColor', 'progressBarStepDatasetTitle', 'progressBarStepCriteriaTitle', 'progressBarStepOutputTitle', 'progressBarStepResultTitle', 'progressBarColor', 'progressBarActiveColor', 'progressBarCircleColor', 'progressBarCircleIconColor', 'progressBarCircleIconActiveColor', 'progressBarTextColor', 'progressBarTextBold', 'searchNextBtnColor', 'searchNextBtnHoverColor', 'searchNextBtnHoverTextColor', 'searchBackBtnColor', 'searchBackBtnHoverColor', 'searchBackBtnHoverTextColor', 'searchInfoBackgroundColor', 'searchInfoTextColor', 'searchInfoHelpEnabled', 'datasetSelectBtnColor', 'datasetSelectBtnHoverColor', 'datasetSelectBtnHoverTextColor', 'datasetSelectedIconColor', 'searchCriterionBackgroundColor', 'searchCriterionTextColor', 'outputColumnsSelectedColor', 'outputColumnsSelectAllBtnColor', 'outputColumnsSelectAllBtnHoverColor', 'outputColumnsSelectAllBtnHoverTextColor', 'resultDownloadBtnColor', 'resultDownloadBtnHoverColor', 'resultDownloadBtnTextColor', 'resultDatatableActionsBtnColor', 'resultDatatableActionsBtnHoverColor', 'resultDatatableActionsBtnTextColor', 'resultDatatableBordered', 'resultDatatableBorderedRadius', 'resultDatatableBorderColor', 'resultDatatableHeaderBackgroundColor', 'resultDatatableHeaderTextColor', 'resultDatatableRowsBackgroundColor', 'resultDatatableRowsTextColor', 'resultDatatableSortedColor', 'resultDatatableSortedActiveColor', 'resultDatatableLinkColor', 'resultDatatableLinkHoverColor', 'resultDatatableRowsSelectedColor', 'sampEnabled', 'backToPortal', 'userMenuEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; } /** @@ -415,23 +415,23 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy /** * {@inheritDoc} */ - public function getDesignColor() + public function getPortalColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getPortalColor', []); - return parent::getDesignColor(); + return parent::getPortalColor(); } /** * {@inheritDoc} */ - public function setDesignColor($designColor) + public function setPortalColor($portalColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignColor', [$designColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setPortalColor', [$portalColor]); - return parent::setDesignColor($designColor); + return parent::setPortalColor($portalColor); } /** @@ -456,6 +456,94 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setDesignBackgroundColor($designBackgroundColor); } + /** + * {@inheritDoc} + */ + public function getDesignTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignTextColor', []); + + return parent::getDesignTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setDesignTextColor($designTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignTextColor', [$designTextColor]); + + return parent::setDesignTextColor($designTextColor); + } + + /** + * {@inheritDoc} + */ + public function getDesignFontFamily() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignFontFamily', []); + + return parent::getDesignFontFamily(); + } + + /** + * {@inheritDoc} + */ + public function setDesignFontFamily($designFontFamily) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignFontFamily', [$designFontFamily]); + + return parent::setDesignFontFamily($designFontFamily); + } + + /** + * {@inheritDoc} + */ + public function getDesignLinkColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignLinkColor', []); + + return parent::getDesignLinkColor(); + } + + /** + * {@inheritDoc} + */ + public function setDesignLinkColor($designLinkColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignLinkColor', [$designLinkColor]); + + return parent::setDesignLinkColor($designLinkColor); + } + + /** + * {@inheritDoc} + */ + public function getDesignLinkHoverColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignLinkHoverColor', []); + + return parent::getDesignLinkHoverColor(); + } + + /** + * {@inheritDoc} + */ + public function setDesignLinkHoverColor($designLinkHoverColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignLinkHoverColor', [$designLinkHoverColor]); + + return parent::setDesignLinkHoverColor($designLinkHoverColor); + } + /** * {@inheritDoc} */ @@ -500,6 +588,28 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setDesignFavicon($designFavicon); } + /** + * {@inheritDoc} + */ + public function getDesignLogoHref() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDesignLogoHref', []); + + return parent::getDesignLogoHref(); + } + + /** + * {@inheritDoc} + */ + public function setDesignLogoHref($designLogoHref) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDesignLogoHref', [$designLogoHref]); + + return parent::setDesignLogoHref($designLogoHref); + } + /** * {@inheritDoc} */ @@ -566,6 +676,72 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setNavbarColorHref($navbarColorHref); } + /** + * {@inheritDoc} + */ + public function getNavbarFontFamily() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getNavbarFontFamily', []); + + return parent::getNavbarFontFamily(); + } + + /** + * {@inheritDoc} + */ + public function setNavbarFontFamily($navbarFontFamily) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setNavbarFontFamily', [$navbarFontFamily]); + + return parent::setNavbarFontFamily($navbarFontFamily); + } + + /** + * {@inheritDoc} + */ + public function getNavbarSignInBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getNavbarSignInBtnColor', []); + + return parent::getNavbarSignInBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setNavbarSignInBtnColor($navbarSignInBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setNavbarSignInBtnColor', [$navbarSignInBtnColor]); + + return parent::setNavbarSignInBtnColor($navbarSignInBtnColor); + } + + /** + * {@inheritDoc} + */ + public function getNavbarUserBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getNavbarUserBtnColor', []); + + return parent::getNavbarUserBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setNavbarUserBtnColor($navbarUserBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setNavbarUserBtnColor', [$navbarUserBtnColor]); + + return parent::setNavbarUserBtnColor($navbarUserBtnColor); + } + /** * {@inheritDoc} */ @@ -632,6 +808,28 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setFooterTextColor($footerTextColor); } + /** + * {@inheritDoc} + */ + public function getFooterLogos() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getFooterLogos', []); + + return parent::getFooterLogos(); + } + + /** + * {@inheritDoc} + */ + public function setFooterLogos($footerLogos) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setFooterLogos', [$footerLogos]); + + return parent::setFooterLogos($footerLogos); + } + /** * {@inheritDoc} */ @@ -745,23 +943,23 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy /** * {@inheritDoc} */ - public function getFamilyColor() + public function getFamilyTextColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getFamilyColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getFamilyTextColor', []); - return parent::getFamilyColor(); + return parent::getFamilyTextColor(); } /** * {@inheritDoc} */ - public function setFamilyColor($familyColor) + public function setFamilyTextColor($familyTextColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setFamilyColor', [$familyColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setFamilyTextColor', [$familyTextColor]); - return parent::setFamilyColor($familyColor); + return parent::setFamilyTextColor($familyTextColor); } /** @@ -852,6 +1050,94 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setProgressBarSubtitleColor($progressBarSubtitleColor); } + /** + * {@inheritDoc} + */ + public function getProgressBarStepDatasetTitle() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getProgressBarStepDatasetTitle', []); + + return parent::getProgressBarStepDatasetTitle(); + } + + /** + * {@inheritDoc} + */ + public function setProgressBarStepDatasetTitle($progressBarStepDatasetTitle) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setProgressBarStepDatasetTitle', [$progressBarStepDatasetTitle]); + + return parent::setProgressBarStepDatasetTitle($progressBarStepDatasetTitle); + } + + /** + * {@inheritDoc} + */ + public function getProgressBarStepCriteriaTitle() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getProgressBarStepCriteriaTitle', []); + + return parent::getProgressBarStepCriteriaTitle(); + } + + /** + * {@inheritDoc} + */ + public function setProgressBarStepCriteriaTitle($progressBarStepCriteriaTitle) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setProgressBarStepCriteriaTitle', [$progressBarStepCriteriaTitle]); + + return parent::setProgressBarStepCriteriaTitle($progressBarStepCriteriaTitle); + } + + /** + * {@inheritDoc} + */ + public function getProgressBarStepOutputTitle() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getProgressBarStepOutputTitle', []); + + return parent::getProgressBarStepOutputTitle(); + } + + /** + * {@inheritDoc} + */ + public function setProgressBarStepOutputTitle($progressBarStepOutputTitle) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setProgressBarStepOutputTitle', [$progressBarStepOutputTitle]); + + return parent::setProgressBarStepOutputTitle($progressBarStepOutputTitle); + } + + /** + * {@inheritDoc} + */ + public function getProgressBarStepResultTitle() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getProgressBarStepResultTitle', []); + + return parent::getProgressBarStepResultTitle(); + } + + /** + * {@inheritDoc} + */ + public function setProgressBarStepResultTitle($progressBarStepResultTitle) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setProgressBarStepResultTitle', [$progressBarStepResultTitle]); + + return parent::setProgressBarStepResultTitle($progressBarStepResultTitle); + } + /** * {@inheritDoc} */ @@ -987,133 +1273,617 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy /** * {@inheritDoc} */ - public function getResultHeaderBackgroundColor() + public function getProgressBarTextBold() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultHeaderBackgroundColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getProgressBarTextBold', []); - return parent::getResultHeaderBackgroundColor(); + return parent::getProgressBarTextBold(); } /** * {@inheritDoc} */ - public function setResultHeaderBackgroundColor($resultHeaderBackgroundColor) + public function setProgressBarTextBold($progressBarTextBold) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultHeaderBackgroundColor', [$resultHeaderBackgroundColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setProgressBarTextBold', [$progressBarTextBold]); - return parent::setResultHeaderBackgroundColor($resultHeaderBackgroundColor); + return parent::setProgressBarTextBold($progressBarTextBold); } /** * {@inheritDoc} */ - public function getResultHeaderTextColor() + public function getSearchNextBtnColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultHeaderTextColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchNextBtnColor', []); - return parent::getResultHeaderTextColor(); + return parent::getSearchNextBtnColor(); } /** * {@inheritDoc} */ - public function setResultHeaderTextColor($resultHeaderTextColor) + public function setSearchNextBtnColor($searchNextBtnColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultHeaderTextColor', [$resultHeaderTextColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchNextBtnColor', [$searchNextBtnColor]); - return parent::setResultHeaderTextColor($resultHeaderTextColor); + return parent::setSearchNextBtnColor($searchNextBtnColor); } /** * {@inheritDoc} */ - public function getResultHeaderBtnColor() + public function getSearchNextBtnHoverColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultHeaderBtnColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchNextBtnHoverColor', []); - return parent::getResultHeaderBtnColor(); + return parent::getSearchNextBtnHoverColor(); } /** * {@inheritDoc} */ - public function setResultHeaderBtnColor($resultHeaderBtnColor) + public function setSearchNextBtnHoverColor($searchNextBtnHoverColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultHeaderBtnColor', [$resultHeaderBtnColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchNextBtnHoverColor', [$searchNextBtnHoverColor]); - return parent::setResultHeaderBtnColor($resultHeaderBtnColor); + return parent::setSearchNextBtnHoverColor($searchNextBtnHoverColor); } /** * {@inheritDoc} */ - public function getResultHeaderBtnHoverColor() + public function getSearchNextBtnHoverTextColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultHeaderBtnHoverColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchNextBtnHoverTextColor', []); - return parent::getResultHeaderBtnHoverColor(); + return parent::getSearchNextBtnHoverTextColor(); } /** * {@inheritDoc} */ - public function setResultHeaderBtnHoverColor($resultHeaderBtnHoverColor) + public function setSearchNextBtnHoverTextColor($searchNextBtnHoverTextColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultHeaderBtnHoverColor', [$resultHeaderBtnHoverColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchNextBtnHoverTextColor', [$searchNextBtnHoverTextColor]); - return parent::setResultHeaderBtnHoverColor($resultHeaderBtnHoverColor); + return parent::setSearchNextBtnHoverTextColor($searchNextBtnHoverTextColor); } /** * {@inheritDoc} */ - public function getResultHeaderBtnTextColor() + public function getSearchBackBtnColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultHeaderBtnTextColor', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchBackBtnColor', []); - return parent::getResultHeaderBtnTextColor(); + return parent::getSearchBackBtnColor(); } /** * {@inheritDoc} */ - public function setResultHeaderBtnTextColor($resultHeaderBtnTextColor) + public function setSearchBackBtnColor($searchBackBtnColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultHeaderBtnTextColor', [$resultHeaderBtnTextColor]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchBackBtnColor', [$searchBackBtnColor]); - return parent::setResultHeaderBtnTextColor($resultHeaderBtnTextColor); + return parent::setSearchBackBtnColor($searchBackBtnColor); } /** * {@inheritDoc} */ - public function getResultDatatableBordered() + public function getSearchBackBtnHoverColor() { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableBordered', []); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchBackBtnHoverColor', []); - return parent::getResultDatatableBordered(); + return parent::getSearchBackBtnHoverColor(); } /** * {@inheritDoc} */ - public function setResultDatatableBordered($resultDatatableBordered) + public function setSearchBackBtnHoverColor($searchBackBtnHoverColor) { - $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableBordered', [$resultDatatableBordered]); + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchBackBtnHoverColor', [$searchBackBtnHoverColor]); - return parent::setResultDatatableBordered($resultDatatableBordered); + return parent::setSearchBackBtnHoverColor($searchBackBtnHoverColor); + } + + /** + * {@inheritDoc} + */ + public function getSearchBackBtnHoverTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchBackBtnHoverTextColor', []); + + return parent::getSearchBackBtnHoverTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setSearchBackBtnHoverTextColor($searchBackBtnHoverTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchBackBtnHoverTextColor', [$searchBackBtnHoverTextColor]); + + return parent::setSearchBackBtnHoverTextColor($searchBackBtnHoverTextColor); + } + + /** + * {@inheritDoc} + */ + public function setSearchInfoBackgroundColor($searchInfoBackgroundColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchInfoBackgroundColor', [$searchInfoBackgroundColor]); + + return parent::setSearchInfoBackgroundColor($searchInfoBackgroundColor); + } + + /** + * {@inheritDoc} + */ + public function getSearchInfoTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchInfoTextColor', []); + + return parent::getSearchInfoTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setSearchInfoTextColor($searchInfoTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchInfoTextColor', [$searchInfoTextColor]); + + return parent::setSearchInfoTextColor($searchInfoTextColor); + } + + /** + * {@inheritDoc} + */ + public function getSearchInfoHelpEnabled() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchInfoHelpEnabled', []); + + return parent::getSearchInfoHelpEnabled(); + } + + /** + * {@inheritDoc} + */ + public function setSearchInfoHelpEnabled($searchInfoHelpEnabled) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchInfoHelpEnabled', [$searchInfoHelpEnabled]); + + return parent::setSearchInfoHelpEnabled($searchInfoHelpEnabled); + } + + /** + * {@inheritDoc} + */ + public function getDatasetSelectBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetSelectBtnColor', []); + + return parent::getDatasetSelectBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setDatasetSelectBtnColor($datasetSelectBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDatasetSelectBtnColor', [$datasetSelectBtnColor]); + + return parent::setDatasetSelectBtnColor($datasetSelectBtnColor); + } + + /** + * {@inheritDoc} + */ + public function getDatasetSelectBtnHoverColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetSelectBtnHoverColor', []); + + return parent::getDatasetSelectBtnHoverColor(); + } + + /** + * {@inheritDoc} + */ + public function setDatasetSelectBtnHoverColor($datasetSelectBtnHoverColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDatasetSelectBtnHoverColor', [$datasetSelectBtnHoverColor]); + + return parent::setDatasetSelectBtnHoverColor($datasetSelectBtnHoverColor); + } + + /** + * {@inheritDoc} + */ + public function getDatasetSelectBtnHoverTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetSelectBtnHoverTextColor', []); + + return parent::getDatasetSelectBtnHoverTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setDatasetSelectBtnHoverTextColor($datasetSelectBtnHoverTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDatasetSelectBtnHoverTextColor', [$datasetSelectBtnHoverTextColor]); + + return parent::setDatasetSelectBtnHoverTextColor($datasetSelectBtnHoverTextColor); + } + + /** + * {@inheritDoc} + */ + public function getDatasetSelectedIconColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getDatasetSelectedIconColor', []); + + return parent::getDatasetSelectedIconColor(); + } + + /** + * {@inheritDoc} + */ + public function setDatasetSelectedIconColor($datasetSelectedIconColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setDatasetSelectedIconColor', [$datasetSelectedIconColor]); + + return parent::setDatasetSelectedIconColor($datasetSelectedIconColor); + } + + /** + * {@inheritDoc} + */ + public function getSearchInfoBackgroundColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchInfoBackgroundColor', []); + + return parent::getSearchInfoBackgroundColor(); + } + + /** + * {@inheritDoc} + */ + public function getSearchCriterionBackgroundColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchCriterionBackgroundColor', []); + + return parent::getSearchCriterionBackgroundColor(); + } + + /** + * {@inheritDoc} + */ + public function setSearchCriterionBackgroundColor($searchCriterionBackgroundColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchCriterionBackgroundColor', [$searchCriterionBackgroundColor]); + + return parent::setSearchCriterionBackgroundColor($searchCriterionBackgroundColor); + } + + /** + * {@inheritDoc} + */ + public function getSearchCriterionTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getSearchCriterionTextColor', []); + + return parent::getSearchCriterionTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setSearchCriterionTextColor($searchCriterionTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setSearchCriterionTextColor', [$searchCriterionTextColor]); + + return parent::setSearchCriterionTextColor($searchCriterionTextColor); + } + + /** + * {@inheritDoc} + */ + public function getOutputColumnsSelectedColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOutputColumnsSelectedColor', []); + + return parent::getOutputColumnsSelectedColor(); + } + + /** + * {@inheritDoc} + */ + public function setOutputColumnsSelectedColor($outputColumnsSelectedColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOutputColumnsSelectedColor', [$outputColumnsSelectedColor]); + + return parent::setOutputColumnsSelectedColor($outputColumnsSelectedColor); + } + + /** + * {@inheritDoc} + */ + public function getOutputColumnsSelectAllBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOutputColumnsSelectAllBtnColor', []); + + return parent::getOutputColumnsSelectAllBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setOutputColumnsSelectAllBtnColor($outputColumnsSelectAllBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOutputColumnsSelectAllBtnColor', [$outputColumnsSelectAllBtnColor]); + + return parent::setOutputColumnsSelectAllBtnColor($outputColumnsSelectAllBtnColor); + } + + /** + * {@inheritDoc} + */ + public function getOutputColumnsSelectAllBtnHoverColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOutputColumnsSelectAllBtnHoverColor', []); + + return parent::getOutputColumnsSelectAllBtnHoverColor(); + } + + /** + * {@inheritDoc} + */ + public function setOutputColumnsSelectAllBtnHoverColor($outputColumnsSelectAllBtnHoverColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOutputColumnsSelectAllBtnHoverColor', [$outputColumnsSelectAllBtnHoverColor]); + + return parent::setOutputColumnsSelectAllBtnHoverColor($outputColumnsSelectAllBtnHoverColor); + } + + /** + * {@inheritDoc} + */ + public function getOutputColumnsSelectAllBtnHoverTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getOutputColumnsSelectAllBtnHoverTextColor', []); + + return parent::getOutputColumnsSelectAllBtnHoverTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setOutputColumnsSelectAllBtnHoverTextColor($outputColumnsSelectAllBtnHoverTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setOutputColumnsSelectAllBtnHoverTextColor', [$outputColumnsSelectAllBtnHoverTextColor]); + + return parent::setOutputColumnsSelectAllBtnHoverTextColor($outputColumnsSelectAllBtnHoverTextColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDownloadBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDownloadBtnColor', []); + + return parent::getResultDownloadBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDownloadBtnColor($resultDownloadBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDownloadBtnColor', [$resultDownloadBtnColor]); + + return parent::setResultDownloadBtnColor($resultDownloadBtnColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDownloadBtnHoverColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDownloadBtnHoverColor', []); + + return parent::getResultDownloadBtnHoverColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDownloadBtnHoverColor($resultDownloadBtnHoverColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDownloadBtnHoverColor', [$resultDownloadBtnHoverColor]); + + return parent::setResultDownloadBtnHoverColor($resultDownloadBtnHoverColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDownloadBtnTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDownloadBtnTextColor', []); + + return parent::getResultDownloadBtnTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDownloadBtnTextColor($resultDownloadBtnTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDownloadBtnTextColor', [$resultDownloadBtnTextColor]); + + return parent::setResultDownloadBtnTextColor($resultDownloadBtnTextColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDatatableActionsBtnColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableActionsBtnColor', []); + + return parent::getResultDatatableActionsBtnColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDatatableActionsBtnColor($resultDatatableActionsBtnColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableActionsBtnColor', [$resultDatatableActionsBtnColor]); + + return parent::setResultDatatableActionsBtnColor($resultDatatableActionsBtnColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDatatableActionsBtnHoverColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableActionsBtnHoverColor', []); + + return parent::getResultDatatableActionsBtnHoverColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDatatableActionsBtnHoverColor($resultDatatableActionsBtnHoverColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableActionsBtnHoverColor', [$resultDatatableActionsBtnHoverColor]); + + return parent::setResultDatatableActionsBtnHoverColor($resultDatatableActionsBtnHoverColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDatatableActionsBtnTextColor() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableActionsBtnTextColor', []); + + return parent::getResultDatatableActionsBtnTextColor(); + } + + /** + * {@inheritDoc} + */ + public function setResultDatatableActionsBtnTextColor($resultDatatableActionsBtnTextColor) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableActionsBtnTextColor', [$resultDatatableActionsBtnTextColor]); + + return parent::setResultDatatableActionsBtnTextColor($resultDatatableActionsBtnTextColor); + } + + /** + * {@inheritDoc} + */ + public function getResultDatatableBordered() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableBordered', []); + + return parent::getResultDatatableBordered(); + } + + /** + * {@inheritDoc} + */ + public function setResultDatatableBordered($resultDatatableBordered) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableBordered', [$resultDatatableBordered]); + + return parent::setResultDatatableBordered($resultDatatableBordered); + } + + /** + * {@inheritDoc} + */ + public function getResultDatatableBorderedRadius() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getResultDatatableBorderedRadius', []); + + return parent::getResultDatatableBorderedRadius(); + } + + /** + * {@inheritDoc} + */ + public function setResultDatatableBorderedRadius($resultDatatableBorderedRadius) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setResultDatatableBorderedRadius', [$resultDatatableBorderedRadius]); + + return parent::setResultDatatableBorderedRadius($resultDatatableBorderedRadius); } /** diff --git a/server/src/Action/AttributeAction.php b/server/src/Action/AttributeAction.php index 4ceb4096c1a7eaf5ba2c3f9d653a3805b0ae9e9e..d64378ff00285177d7633d525f67779ba13cc5f8 100644 --- a/server/src/Action/AttributeAction.php +++ b/server/src/Action/AttributeAction.php @@ -86,6 +86,8 @@ final class AttributeAction extends AbstractAction 'order_by', 'archive', 'detail_display', + 'detail_renderer', + 'detail_renderer_config', 'vo_utype', 'vo_ucd', 'vo_unit', @@ -151,6 +153,8 @@ final class AttributeAction extends AbstractAction $attribute->setOrderBy($parsedBody['order_by']); $attribute->setArchive($parsedBody['archive']); $attribute->setDetailDisplay($parsedBody['detail_display']); + $attribute->setDetailRenderer($parsedBody['detail_renderer']); + $attribute->setDetailRendererConfig($parsedBody['detail_renderer_config']); $attribute->setVoUtype($parsedBody['vo_utype']); $attribute->setVoUcd($parsedBody['vo_ucd']); $attribute->setVoUnit($parsedBody['vo_unit']); diff --git a/server/src/Action/AttributeListAction.php b/server/src/Action/AttributeListAction.php index e1496b10d00f994be42136fd2cdaaa719a39c80a..3b2d580a33742787963a691c5580eb85f1508560 100644 --- a/server/src/Action/AttributeListAction.php +++ b/server/src/Action/AttributeListAction.php @@ -88,6 +88,8 @@ final class AttributeListAction extends AbstractAction 'order_by', 'archive', 'detail_display', + 'detail_renderer', + 'detail_renderer_config', 'vo_utype', 'vo_ucd', 'vo_unit', @@ -149,6 +151,8 @@ final class AttributeListAction extends AbstractAction $attribute->setOrderBy($parsedBody['order_by']); $attribute->setArchive($parsedBody['archive']); $attribute->setDetailDisplay($parsedBody['detail_display']); + $attribute->setDetailRenderer($parsedBody['detail_renderer']); + $attribute->setDetailRendererConfig($parsedBody['detail_renderer_config']); $attribute->setVoUtype($parsedBody['vo_utype']); $attribute->setVoUcd($parsedBody['vo_ucd']); $attribute->setVoUnit($parsedBody['vo_unit']); diff --git a/server/src/Action/ConeSearchConfigAction.php b/server/src/Action/ConeSearchConfigAction.php index 8d2be835b9111cf14dce36c513c6ab3832d920e8..a6ab51eacc374e49ae00447ada44cff3704ac3f2 100644 --- a/server/src/Action/ConeSearchConfigAction.php +++ b/server/src/Action/ConeSearchConfigAction.php @@ -108,6 +108,11 @@ final class ConeSearchConfigAction extends AbstractAction 'opened', 'column_ra', 'column_dec', + 'resolver_enabled', + 'default_ra', + 'default_dec', + 'default_radius', + 'default_ra_dec_unit', 'plot_enabled' ); @@ -135,6 +140,11 @@ final class ConeSearchConfigAction extends AbstractAction $coneSearchConfig->setOpened($parsedBody['opened']); $coneSearchConfig->setColumnRa($parsedBody['column_ra']); $coneSearchConfig->setColumnDec($parsedBody['column_dec']); + $coneSearchConfig->setResolverEnabled($parsedBody['resolver_enabled']); + $coneSearchConfig->setDefaultRa($parsedBody['default_ra']); + $coneSearchConfig->setDefaultDec($parsedBody['default_dec']); + $coneSearchConfig->setDefaultRadius($parsedBody['default_radius']); + $coneSearchConfig->setDefaultRaDecUnit($parsedBody['default_ra_dec_unit']); $coneSearchConfig->setPlotEnabled($parsedBody['plot_enabled']); $dataset->setConeSearchConfig($coneSearchConfig); @@ -157,6 +167,11 @@ final class ConeSearchConfigAction extends AbstractAction $coneSearchConfig->setOpened($parsedBody['opened']); $coneSearchConfig->setColumnRa($parsedBody['column_ra']); $coneSearchConfig->setColumnDec($parsedBody['column_dec']); + $coneSearchConfig->setResolverEnabled($parsedBody['resolver_enabled']); + $coneSearchConfig->setDefaultRa($parsedBody['default_ra']); + $coneSearchConfig->setDefaultDec($parsedBody['default_dec']); + $coneSearchConfig->setDefaultRadius($parsedBody['default_radius']); + $coneSearchConfig->setDefaultRaDecUnit($parsedBody['default_ra_dec_unit']); $coneSearchConfig->setPlotEnabled($parsedBody['plot_enabled']); $this->em->flush(); } diff --git a/server/src/Action/InstanceAction.php b/server/src/Action/InstanceAction.php index c32fc0214658ad1150ab544cc29bcc2e69edc789..c5a5319ab2772f6adff8912ddd3c37dce947a1e8 100644 --- a/server/src/Action/InstanceAction.php +++ b/server/src/Action/InstanceAction.php @@ -74,38 +74,73 @@ final class InstanceAction extends AbstractAction 'files_path', 'public', 'portal_logo', - 'design_color', + 'portal_color', 'design_background_color', + 'design_text_color', + 'design_font_family', + 'design_link_color', + 'design_link_hover_color', 'design_logo', + 'design_logo_href', 'design_favicon', 'navbar_background_color', 'navbar_border_bottom_color', 'navbar_color_href', + 'navbar_font_family', + 'navbar_sign_in_btn_color', + 'navbar_user_btn_color', 'footer_background_color', 'footer_border_top_color', 'footer_text_color', + 'footer_logos', 'family_border_color', 'family_header_background_color', 'family_title_color', 'family_title_bold', 'family_background_color', - 'family_color', + 'family_text_color', 'progress_bar_title', 'progress_bar_title_color', 'progress_bar_subtitle', 'progress_bar_subtitle_color', + 'progress_bar_step_dataset_title', + 'progress_bar_step_criteria_title', + 'progress_bar_step_output_title', + 'progress_bar_step_result_title', 'progress_bar_color', 'progress_bar_active_color', 'progress_bar_circle_color', 'progress_bar_circle_icon_color', 'progress_bar_circle_icon_active_color', 'progress_bar_text_color', - 'result_header_background_color', - 'result_header_text_color', - 'result_header_btn_color', - 'result_header_btn_hover_color', - 'result_header_btn_text_color', + 'progress_bar_text_bold', + 'search_next_btn_color', + 'search_next_btn_hover_color', + 'search_next_btn_hover_text_color', + 'search_back_btn_color', + 'search_back_btn_hover_color', + 'search_back_btn_hover_text_color', + 'search_info_background_color', + 'search_info_text_color', + 'search_info_help_enabled', + 'dataset_select_btn_color', + 'dataset_select_btn_hover_color', + 'dataset_select_btn_hover_text_color', + 'dataset_selected_icon_color', + 'search_criterion_background_color', + 'search_criterion_text_color', + 'output_columns_selected_color', + 'output_columns_select_all_btn_color', + 'output_columns_select_all_btn_hover_color', + 'output_columns_select_all_btn_hover_text_color', + 'result_download_btn_color', + 'result_download_btn_hover_color', + 'result_download_btn_text_color', + 'result_datatable_actions_btn_color', + 'result_datatable_actions_btn_hover_color', + 'result_datatable_actions_btn_text_color', 'result_datatable_bordered', + 'result_datatable_bordered_radius', 'result_datatable_border_color', 'result_datatable_header_background_color', 'result_datatable_header_text_color', @@ -171,38 +206,75 @@ final class InstanceAction extends AbstractAction $instance->setFilesPath($parsedBody['files_path']); $instance->setPublic($parsedBody['public']); $instance->setPortalLogo($parsedBody['portal_logo']); - $instance->setDesignColor($parsedBody['design_color']); + $instance->setPortalColor($parsedBody['portal_color']); $instance->setDesignBackgroundColor($parsedBody['design_background_color']); + $instance->setDesignTextColor($parsedBody['design_text_color']); + $instance->setDesignFontFamily($parsedBody['design_font_family']); + $instance->setDesignLinkColor($parsedBody['design_link_color']); + $instance->setDesignLinkHoverColor($parsedBody['design_link_hover_color']); $instance->setDesignLogo($parsedBody['design_logo']); + $instance->setDesignLogoHref($parsedBody['design_logo_href']); $instance->setDesignFavicon($parsedBody['design_favicon']); $instance->setNavbarBackgroundColor($parsedBody['navbar_background_color']); $instance->setNavbarBorderBottomColor($parsedBody['navbar_border_bottom_color']); $instance->setNavbarColorHref($parsedBody['navbar_color_href']); + $instance->setNavbarFontFamily($parsedBody['navbar_font_family']); + $instance->setNavbarSignInBtnColor($parsedBody['navbar_sign_in_btn_color']); + $instance->setNavbarUserBtnColor($parsedBody['navbar_user_btn_color']); $instance->setFooterBackgroundColor($parsedBody['footer_background_color']); $instance->setFooterBorderTopColor($parsedBody['footer_border_top_color']); $instance->setFooterTextColor($parsedBody['footer_text_color']); + $instance->setFooterLogos($parsedBody['footer_logos']); $instance->setFamilyBorderColor($parsedBody['family_border_color']); $instance->setFamilyHeaderBackgroundColor($parsedBody['family_header_background_color']); $instance->setFamilyTitleColor($parsedBody['family_title_color']); $instance->setFamilyTitleBold($parsedBody['family_title_bold']); $instance->setFamilyBackgroundColor($parsedBody['family_background_color']); - $instance->setFamilyColor($parsedBody['family_color']); + $instance->setFamilyTextColor($parsedBody['family_text_color']); $instance->setProgressBarTitle($parsedBody['progress_bar_title']); $instance->setProgressBarTitleColor($parsedBody['progress_bar_title_color']); $instance->setProgressBarSubtitle($parsedBody['progress_bar_subtitle']); $instance->setProgressBarSubtitleColor($parsedBody['progress_bar_subtitle_color']); + $instance->setProgressBarStepDatasetTitle($parsedBody['progress_bar_step_dataset_title']); + $instance->setProgressBarStepCriteriaTitle($parsedBody['progress_bar_step_criteria_title']); + $instance->setProgressBarStepOutputTitle($parsedBody['progress_bar_step_output_title']); + $instance->setProgressBarStepResultTitle($parsedBody['progress_bar_step_result_title']); $instance->setProgressBarColor($parsedBody['progress_bar_color']); $instance->setProgressBarActiveColor($parsedBody['progress_bar_active_color']); $instance->setProgressBarCircleColor($parsedBody['progress_bar_circle_color']); $instance->setProgressBarCircleIconColor($parsedBody['progress_bar_circle_icon_color']); $instance->setProgressBarCircleIconActiveColor($parsedBody['progress_bar_circle_icon_active_color']); $instance->setProgressBarTextColor($parsedBody['progress_bar_text_color']); - $instance->setResultHeaderBackgroundColor($parsedBody['result_header_background_color']); - $instance->setResultHeaderTextColor($parsedBody['result_header_text_color']); - $instance->setResultHeaderBtnColor($parsedBody['result_header_btn_color']); - $instance->setResultHeaderBtnHoverColor($parsedBody['result_header_btn_hover_color']); - $instance->setResultHeaderBtnTextColor($parsedBody['result_header_btn_text_color']); + $instance->setProgressBarTextBold($parsedBody['progress_bar_text_bold']); + $instance->setSearchNextBtnColor($parsedBody['search_next_btn_color']); + $instance->setSearchNextBtnHoverColor($parsedBody['search_next_btn_hover_color']); + $instance->setSearchNextBtnHoverTextColor($parsedBody['search_next_btn_hover_text_color']); + $instance->setSearchBackBtnColor($parsedBody['search_back_btn_color']); + $instance->setSearchBackBtnHoverColor($parsedBody['search_back_btn_hover_color']); + $instance->setSearchBackBtnHoverTextColor($parsedBody['search_back_btn_hover_text_color']); + $instance->setSearchInfoBackgroundColor($parsedBody['search_info_background_color']); + $instance->setSearchInfoTextColor($parsedBody['search_info_text_color']); + $instance->setSearchInfoHelpEnabled($parsedBody['search_info_help_enabled']); + $instance->setDatasetSelectBtnColor($parsedBody['dataset_select_btn_color']); + $instance->setDatasetSelectBtnHoverColor($parsedBody['dataset_select_btn_hover_color']); + $instance->setDatasetSelectBtnHoverTextColor($parsedBody['dataset_select_btn_hover_text_color']); + $instance->setDatasetSelectedIconColor($parsedBody['dataset_selected_icon_color']); + $instance->setSearchCriterionBackgroundColor($parsedBody['search_criterion_background_color']); + $instance->setSearchCriterionTextColor($parsedBody['search_criterion_text_color']); + $instance->setOutputColumnsSelectedColor($parsedBody['output_columns_selected_color']); + $instance->setOutputColumnsSelectAllBtnColor($parsedBody['output_columns_select_all_btn_color']); + $instance->setOutputColumnsSelectAllBtnHoverColor($parsedBody['output_columns_select_all_btn_hover_color']); + $instance->setOutputColumnsSelectAllBtnHoverTextColor($parsedBody[ + 'output_columns_select_all_btn_hover_text_color' + ]); + $instance->setResultDownloadBtnColor($parsedBody['result_download_btn_color']); + $instance->setResultDownloadBtnHoverColor($parsedBody['result_download_btn_hover_color']); + $instance->setResultDownloadBtnTextColor($parsedBody['result_download_btn_text_color']); + $instance->setResultDatatableActionsBtnColor($parsedBody['result_datatable_actions_btn_color']); + $instance->setResultDatatableActionsBtnHoverColor($parsedBody['result_datatable_actions_btn_hover_color']); + $instance->setResultDatatableActionsBtnTextColor($parsedBody['result_datatable_actions_btn_text_color']); $instance->setResultDatatableBordered($parsedBody['result_datatable_bordered']); + $instance->setResultDatatableBorderedRadius($parsedBody['result_datatable_bordered_radius']); $instance->setResultDatatableBorderColor($parsedBody['result_datatable_border_color']); $instance->setResultDatatableHeaderBackgroundColor($parsedBody['result_datatable_header_background_color']); $instance->setResultDatatableHeaderTextColor($parsedBody['result_datatable_header_text_color']); diff --git a/server/src/Action/InstanceListAction.php b/server/src/Action/InstanceListAction.php index 64f3842ecb5b75dee2fd337a48a92f699f371faf..6029ad3c10ea96886c2caea33e13dc220f2f1339 100644 --- a/server/src/Action/InstanceListAction.php +++ b/server/src/Action/InstanceListAction.php @@ -74,38 +74,73 @@ final class InstanceListAction extends AbstractAction 'files_path', 'public', 'portal_logo', - 'design_color', + 'portal_color', 'design_background_color', + 'design_text_color', + 'design_font_family', + 'design_link_color', + 'design_link_hover_color', 'design_logo', + 'design_logo_href', 'design_favicon', 'navbar_background_color', 'navbar_border_bottom_color', 'navbar_color_href', + 'navbar_font_family', + 'navbar_sign_in_btn_color', + 'navbar_user_btn_color', 'footer_background_color', 'footer_border_top_color', 'footer_text_color', + 'footer_logos', 'family_border_color', 'family_header_background_color', 'family_title_color', 'family_title_bold', 'family_background_color', - 'family_color', + 'family_text_color', 'progress_bar_title', 'progress_bar_title_color', 'progress_bar_subtitle', 'progress_bar_subtitle_color', + 'progress_bar_step_dataset_title', + 'progress_bar_step_criteria_title', + 'progress_bar_step_output_title', + 'progress_bar_step_result_title', 'progress_bar_color', 'progress_bar_active_color', 'progress_bar_circle_color', 'progress_bar_circle_icon_color', 'progress_bar_circle_icon_active_color', 'progress_bar_text_color', - 'result_header_background_color', - 'result_header_text_color', - 'result_header_btn_color', - 'result_header_btn_hover_color', - 'result_header_btn_text_color', + 'progress_bar_text_bold', + 'search_next_btn_color', + 'search_next_btn_hover_color', + 'search_next_btn_hover_text_color', + 'search_back_btn_color', + 'search_back_btn_hover_color', + 'search_back_btn_hover_text_color', + 'search_info_background_color', + 'search_info_text_color', + 'search_info_help_enabled', + 'dataset_select_btn_color', + 'dataset_select_btn_hover_color', + 'dataset_select_btn_hover_text_color', + 'dataset_selected_icon_color', + 'search_criterion_background_color', + 'search_criterion_text_color', + 'output_columns_selected_color', + 'output_columns_select_all_btn_color', + 'output_columns_select_all_btn_hover_color', + 'output_columns_select_all_btn_hover_text_color', + 'result_download_btn_color', + 'result_download_btn_hover_color', + 'result_download_btn_text_color', + 'result_datatable_actions_btn_color', + 'result_datatable_actions_btn_hover_color', + 'result_datatable_actions_btn_text_color', 'result_datatable_bordered', + 'result_datatable_bordered_radius', 'result_datatable_border_color', 'result_datatable_header_background_color', 'result_datatable_header_text_color', @@ -165,38 +200,75 @@ final class InstanceListAction extends AbstractAction $instance->setFilesPath($parsedBody['files_path']); $instance->setPublic($parsedBody['public']); $instance->setPortalLogo($parsedBody['portal_logo']); - $instance->setDesignColor($parsedBody['design_color']); + $instance->setPortalColor($parsedBody['portal_color']); $instance->setDesignBackgroundColor($parsedBody['design_background_color']); + $instance->setDesignTextColor($parsedBody['design_text_color']); + $instance->setDesignFontFamily($parsedBody['design_font_family']); + $instance->setDesignLinkColor($parsedBody['design_link_color']); + $instance->setDesignLinkHoverColor($parsedBody['design_link_hover_color']); $instance->setDesignLogo($parsedBody['design_logo']); + $instance->setDesignLogoHref($parsedBody['design_logo_href']); $instance->setDesignFavicon($parsedBody['design_favicon']); $instance->setNavbarBackgroundColor($parsedBody['navbar_background_color']); $instance->setNavbarBorderBottomColor($parsedBody['navbar_border_bottom_color']); $instance->setNavbarColorHref($parsedBody['navbar_color_href']); + $instance->setNavbarFontFamily($parsedBody['navbar_font_family']); + $instance->setNavbarSignInBtnColor($parsedBody['navbar_sign_in_btn_color']); + $instance->setNavbarUserBtnColor($parsedBody['navbar_user_btn_color']); $instance->setFooterBackgroundColor($parsedBody['footer_background_color']); $instance->setFooterBorderTopColor($parsedBody['footer_border_top_color']); $instance->setFooterTextColor($parsedBody['footer_text_color']); + $instance->setFooterLogos($parsedBody['footer_logos']); $instance->setFamilyBorderColor($parsedBody['family_border_color']); $instance->setFamilyHeaderBackgroundColor($parsedBody['family_header_background_color']); $instance->setFamilyTitleColor($parsedBody['family_title_color']); $instance->setFamilyTitleBold($parsedBody['family_title_bold']); $instance->setFamilyBackgroundColor($parsedBody['family_background_color']); - $instance->setFamilyColor($parsedBody['family_color']); + $instance->setFamilyTextColor($parsedBody['family_text_color']); $instance->setProgressBarTitle($parsedBody['progress_bar_title']); $instance->setProgressBarTitleColor($parsedBody['progress_bar_title_color']); $instance->setProgressBarSubtitle($parsedBody['progress_bar_subtitle']); $instance->setProgressBarSubtitleColor($parsedBody['progress_bar_subtitle_color']); + $instance->setProgressBarStepDatasetTitle($parsedBody['progress_bar_step_dataset_title']); + $instance->setProgressBarStepCriteriaTitle($parsedBody['progress_bar_step_criteria_title']); + $instance->setProgressBarStepOutputTitle($parsedBody['progress_bar_step_output_title']); + $instance->setProgressBarStepResultTitle($parsedBody['progress_bar_step_result_title']); $instance->setProgressBarColor($parsedBody['progress_bar_color']); $instance->setProgressBarActiveColor($parsedBody['progress_bar_active_color']); $instance->setProgressBarCircleColor($parsedBody['progress_bar_circle_color']); $instance->setProgressBarCircleIconColor($parsedBody['progress_bar_circle_icon_color']); $instance->setProgressBarCircleIconActiveColor($parsedBody['progress_bar_circle_icon_active_color']); $instance->setProgressBarTextColor($parsedBody['progress_bar_text_color']); - $instance->setResultHeaderBackgroundColor($parsedBody['result_header_background_color']); - $instance->setResultHeaderTextColor($parsedBody['result_header_text_color']); - $instance->setResultHeaderBtnColor($parsedBody['result_header_btn_color']); - $instance->setResultHeaderBtnHoverColor($parsedBody['result_header_btn_hover_color']); - $instance->setResultHeaderBtnTextColor($parsedBody['result_header_btn_text_color']); + $instance->setProgressBarTextBold($parsedBody['progress_bar_text_bold']); + $instance->setSearchNextBtnColor($parsedBody['search_next_btn_color']); + $instance->setSearchNextBtnHoverColor($parsedBody['search_next_btn_hover_color']); + $instance->setSearchNextBtnHoverTextColor($parsedBody['search_next_btn_hover_text_color']); + $instance->setSearchBackBtnColor($parsedBody['search_back_btn_color']); + $instance->setSearchBackBtnHoverColor($parsedBody['search_back_btn_hover_color']); + $instance->setSearchBackBtnHoverTextColor($parsedBody['search_back_btn_hover_text_color']); + $instance->setSearchInfoBackgroundColor($parsedBody['search_info_background_color']); + $instance->setSearchInfoTextColor($parsedBody['search_info_text_color']); + $instance->setSearchInfoHelpEnabled($parsedBody['search_info_help_enabled']); + $instance->setDatasetSelectBtnColor($parsedBody['dataset_select_btn_color']); + $instance->setDatasetSelectBtnHoverColor($parsedBody['dataset_select_btn_hover_color']); + $instance->setDatasetSelectBtnHoverTextColor($parsedBody['dataset_select_btn_hover_text_color']); + $instance->setDatasetSelectedIconColor($parsedBody['dataset_selected_icon_color']); + $instance->setSearchCriterionBackgroundColor($parsedBody['search_criterion_background_color']); + $instance->setSearchCriterionTextColor($parsedBody['search_criterion_text_color']); + $instance->setOutputColumnsSelectedColor($parsedBody['output_columns_selected_color']); + $instance->setOutputColumnsSelectAllBtnColor($parsedBody['output_columns_select_all_btn_color']); + $instance->setOutputColumnsSelectAllBtnHoverColor($parsedBody['output_columns_select_all_btn_hover_color']); + $instance->setOutputColumnsSelectAllBtnHoverTextColor($parsedBody[ + 'output_columns_select_all_btn_hover_text_color' + ]); + $instance->setResultDownloadBtnColor($parsedBody['result_download_btn_color']); + $instance->setResultDownloadBtnHoverColor($parsedBody['result_download_btn_hover_color']); + $instance->setResultDownloadBtnTextColor($parsedBody['result_download_btn_text_color']); + $instance->setResultDatatableActionsBtnColor($parsedBody['result_datatable_actions_btn_color']); + $instance->setResultDatatableActionsBtnHoverColor($parsedBody['result_datatable_actions_btn_hover_color']); + $instance->setResultDatatableActionsBtnTextColor($parsedBody['result_datatable_actions_btn_text_color']); $instance->setResultDatatableBordered($parsedBody['result_datatable_bordered']); + $instance->setResultDatatableBorderedRadius($parsedBody['result_datatable_bordered_radius']); $instance->setResultDatatableBorderColor($parsedBody['result_datatable_border_color']); $instance->setResultDatatableHeaderBackgroundColor($parsedBody['result_datatable_header_background_color']); $instance->setResultDatatableHeaderTextColor($parsedBody['result_datatable_header_text_color']); diff --git a/server/src/Entity/Attribute.php b/server/src/Entity/Attribute.php index 946f5b5db9ac36afe81070974308f36db6467a8b..0c76c76df1a21c731d7e30f75092e4059a998df7 100644 --- a/server/src/Entity/Attribute.php +++ b/server/src/Entity/Attribute.php @@ -192,6 +192,20 @@ class Attribute implements \JsonSerializable */ protected $detailDisplay; + /** + * @var string + * + * @Column(type="string", name="detail_renderer", nullable=true) + */ + protected $detailRenderer; + + /** + * @var string + * + * @Column(type="json", name="detail_renderer_config", nullable=true) + */ + protected $detailRendererConfig; + /** * @var string * @@ -499,6 +513,26 @@ class Attribute implements \JsonSerializable $this->detailDisplay = $detailDisplay; } + public function getDetailRenderer() + { + return $this->detailRenderer; + } + + public function setDetailRenderer($detailRenderer) + { + $this->detailRenderer = $detailRenderer; + } + + public function getDetailRendererConfig() + { + return $this->detailRendererConfig; + } + + public function setDetailRendererConfig($detailRendererConfig) + { + $this->detailRendererConfig = $detailRendererConfig; + } + public function getVoUtype() { return $this->voUtype; @@ -615,6 +649,8 @@ class Attribute implements \JsonSerializable 'order_by' => $this->getOrderBy(), 'archive' => $this->getArchive(), 'detail_display' => $this->getDetailDisplay(), + 'detail_renderer' => $this->getDetailRenderer(), + 'detail_renderer_config' => $this->getDetailRendererConfig(), 'vo_utype' => $this->getVoUtype(), 'vo_ucd' => $this->getVoUcd(), 'vo_unit' => $this->getVoUnit(), diff --git a/server/src/Entity/ConeSearchConfig.php b/server/src/Entity/ConeSearchConfig.php index 5d63582526a9eb85dc4ae9de723eaeb61dbe7345..9ec28c9fd6e357278983990a73dfe1245490186c 100644 --- a/server/src/Entity/ConeSearchConfig.php +++ b/server/src/Entity/ConeSearchConfig.php @@ -58,6 +58,41 @@ class ConeSearchConfig implements \JsonSerializable */ protected $columnDec; + /** + * @var bool + * + * @Column(type="boolean", name="resolver_enabled", nullable=false, options={"default" : true}) + */ + protected $resolverEnabled; + + /** + * @var float + * + * @Column(type="float", name="default_ra", nullable=true) + */ + protected $defaultRa; + + /** + * @var float + * + * @Column(type="float", name="default_dec", nullable=true) + */ + protected $defaultDec; + + /** + * @var float + * + * @Column(type="float", name="default_radius", nullable=false, options={"default" : "2.0"})) + */ + protected $defaultRadius; + + /** + * @var string + * + * @Column(type="string", name="default_ra_dec_unit", nullable=false, options={"default" : "degree"})) + */ + protected $defaultRaDecUnit; + /** * @var bool * @@ -110,6 +145,56 @@ class ConeSearchConfig implements \JsonSerializable $this->columnDec = $columnDec; } + public function getResolverEnabled() + { + return $this->resolverEnabled; + } + + public function setResolverEnabled($resolverEnabled) + { + $this->resolverEnabled = $resolverEnabled; + } + + public function getDefaultRa() + { + return $this->defaultRa; + } + + public function setDefaultRa($defaultRa) + { + $this->defaultRa = $defaultRa; + } + + public function getDefaultDec() + { + return $this->defaultDec; + } + + public function setDefaultDec($defaultDec) + { + $this->defaultDec = $defaultDec; + } + + public function getDefaultRadius() + { + return $this->defaultRadius; + } + + public function setDefaultRadius($defaultRadius) + { + $this->defaultRadius = $defaultRadius; + } + + public function getDefaultRaDecUnit() + { + return $this->defaultRaDecUnit; + } + + public function setDefaultRaDecUnit($defaultRaDecUnit) + { + $this->defaultRaDecUnit = $defaultRaDecUnit; + } + public function getPlotEnabled() { return $this->plotEnabled; @@ -128,7 +213,12 @@ class ConeSearchConfig implements \JsonSerializable 'opened' => $this->getOpened(), 'column_ra' => $this->getColumnRa(), 'column_dec' => $this->getColumnDec(), - 'plot_enabled' => $this->getPlotEnabled(), + 'resolver_enabled' => $this->getResolverEnabled(), + 'default_ra' => $this->getDefaultRa(), + 'default_dec' => $this->getDefaultDec(), + 'default_radius' => $this->getDefaultRadius(), + 'default_ra_dec_unit' => $this->getDefaultRaDecUnit(), + 'plot_enabled' => $this->getPlotEnabled() ]; } } diff --git a/server/src/Entity/Instance.php b/server/src/Entity/Instance.php index 956591b0b994d96182e22b71e9f9c2a205e20289..1d288b42c307ea6af85ccbf0468c6456ca9b4043 100644 --- a/server/src/Entity/Instance.php +++ b/server/src/Entity/Instance.php @@ -104,9 +104,9 @@ class Instance implements \JsonSerializable /** * @var string * - * @Column(type="string", name="design_color", nullable=true) + * @Column(type="string", name="portal_color", nullable=true) */ - protected $designColor; + protected $portalColor; /** * @var string @@ -115,6 +115,34 @@ class Instance implements \JsonSerializable */ protected $designBackgroundColor; + /** + * @var string + * + * @Column(type="string", name="design_text_color", nullable=false, options={"default" : "#212529"}) + */ + protected $designTextColor; + + /** + * @var string + * + * @Column(type="string", name="design_font_family", nullable=false, options={"default" : "Roboto, sans-serif"}) + */ + protected $designFontFamily; + + /** + * @var string + * + * @Column(type="string", name="design_link_color", nullable=false, options={"default" : "#007BFF"}) + */ + protected $designLinkColor; + + /** + * @var string + * + * @Column(type="string", name="design_link_hover_color", nullable=false, options={"default" : "#0056B3"}) + */ + protected $designLinkHoverColor; + /** * @var string * @@ -122,6 +150,13 @@ class Instance implements \JsonSerializable */ protected $designLogo; + /** + * @var string + * + * @Column(type="string", name="design_logo_href", nullable=true) + */ + protected $designLogoHref; + /** * @var string * @@ -150,6 +185,27 @@ class Instance implements \JsonSerializable */ protected $navbarColorHref; + /** + * @var string + * + * @Column(type="string", name="navbar_font_family", nullable=false, options={"default" : "Roboto, sans-serif"}) + */ + protected $navbarFontFamily; + + /** + * @var string + * + * @Column(type="string", name="navbar_sign_in_btn_color", nullable=false, options={"default" : "#28A745"}) + */ + protected $navbarSignInBtnColor; + + /** + * @var string + * + * @Column(type="string", name="navbar_user_btn_color", nullable=false, options={"default" : "#7AC29A"}) + */ + protected $navbarUserBtnColor; + /** * @var string * @@ -171,6 +227,13 @@ class Instance implements \JsonSerializable */ protected $footerTextColor; + /** + * @var string + * + * @Column(type="json", name="footer_logos", nullable=true) + */ + protected $footerLogos; + /** * @var string * @@ -209,9 +272,9 @@ class Instance implements \JsonSerializable /** * @var string * - * @Column(type="string", name="family_color", nullable=false, options={"default" : "#212529"}) + * @Column(type="string", name="family_text_color", nullable=false, options={"default" : "#212529"}) */ - protected $familyColor; + protected $familyTextColor; /** * @var string @@ -243,6 +306,42 @@ class Instance implements \JsonSerializable */ protected $progressBarSubtitleColor; + /** + * @var string + * + * @Column(type="string", name="progress_bar_step_dataset_title", nullable=false, options={ + * "default" : "Dataset selection" + * }) + */ + protected $progressBarStepDatasetTitle; + + /** + * @var string + * + * @Column(type="string", name="progress_bar_step_criteria_title", nullable=false, options={ + * "default" : "Search criteria" + * }) + */ + protected $progressBarStepCriteriaTitle; + + /** + * @var string + * + * @Column(type="string", name="progress_bar_step_output_title", nullable=false, options={ + * "default" : "Output columns" + * }) + */ + protected $progressBarStepOutputTitle; + + /** + * @var string + * + * @Column(type="string", name="progress_bar_step_result_title", nullable=false, options={ + * "default" : "Result table" + * }) + */ + protected $progressBarStepResultTitle; + /** * @var string * @@ -287,40 +386,205 @@ class Instance implements \JsonSerializable */ protected $progressBarTextColor; + /** + * @var bool + * + * @Column(type="boolean", name="progress_bar_text_bold", nullable=false, options={"default" : false}) + */ + protected $progressBarTextBold; + + /** + * @var string + * + * @Column(type="string", name="search_next_btn_color", nullable=false, options={"default" : "#007BFF"}) + */ + protected $searchNextBtnColor; + + /** + * @var string + * + * @Column(type="string", name="search_next_btn_hover_color", nullable=false, options={"default" : "#007BFF"}) + */ + protected $searchNextBtnHoverColor; + + /** + * @var string + * + * @Column(type="string", name="search_next_btn_hover_text_color", nullable=false, options={"default" : "#FFFFFF"}) + */ + protected $searchNextBtnHoverTextColor; + + /** + * @var string + * + * @Column(type="string", name="search_back_btn_color", nullable=false, options={"default" : "#6C757D"}) + */ + protected $searchBackBtnColor; + + /** + * @var string + * + * @Column(type="string", name="search_back_btn_hover_color", nullable=false, options={"default" : "#6C757D"}) + */ + protected $searchBackBtnHoverColor; + + /** + * @var string + * + * @Column(type="string", name="search_back_btn_hover_text_color", nullable=false, options={"default" : "#FFFFFF"}) + */ + protected $searchBackBtnHoverTextColor; + + /** + * @var string + * + * @Column(type="string", name="search_info_background_color", nullable=false, options={"default" : "#E9ECEF"}) + */ + protected $searchInfoBackgroundColor; + + /** + * @var string + * + * @Column(type="string", name="search_info_text_color", nullable=false, options={"default" : "#000000"}) + */ + protected $searchInfoTextColor; + + /** + * @var bool + * + * @Column(type="boolean", name="search_info_help_enabled", nullable=false, options={"default" : true}) + */ + protected $searchInfoHelpEnabled; + /** * @var string * - * @Column(type="string", name="result_header_background_color", nullable=false, options={"default" : "#E9ECEF"}) + * @Column(type="string", name="dataset_select_btn_color", nullable=false, options={"default" : "#6C757D"}) */ - protected $resultHeaderBackgroundColor; + protected $datasetSelectBtnColor; /** * @var string * - * @Column(type="string", name="result_header_text_color", nullable=false, options={"default" : "#000000"}) + * @Column(type="string", name="dataset_select_btn_hover_color", nullable=false, options={"default" : "#6C757D"}) */ - protected $resultHeaderTextColor; + protected $datasetSelectBtnHoverColor; /** * @var string * - * @Column(type="string", name="result_header_btn_color", nullable=false, options={"default" : "#007BFF"}) + * @Column(type="string", name="dataset_select_btn_hover_text_color", nullable=false, options={ + * "default" : "#FFFFFF" + * }) */ - protected $resultHeaderBtnColor; + protected $datasetSelectBtnHoverTextColor; /** * @var string * - * @Column(type="string", name="result_header_btn_hover_color", nullable=false, options={"default" : "#0069D9"}) + * @Column(type="string", name="dataset_selected_icon_color", nullable=false, options={"default" : "#28A745"}) */ - protected $resultHeaderBtnHoverColor; + protected $datasetSelectedIconColor; /** * @var string * - * @Column(type="string", name="result_header_btn_text_color", nullable=false, options={"default" : "#FFFFFF"}) + * @Column(type="string", name="search_criterion_background_color", nullable=false, options={ + * "default" : "#7AC29A" + * }) */ - protected $resultHeaderBtnTextColor; + protected $searchCriterionBackgroundColor; + + /** + * @var string + * + * @Column(type="string", name="search_criterion_text_color", nullable=false, options={ + * "default" : "#000000" + * }) + */ + protected $searchCriterionTextColor; + + /** + * @var string + * + * @Column(type="string", name="output_columns_selected_color", nullable=false, options={"default" : "#7AC29A"}) + */ + protected $outputColumnsSelectedColor; + + /** + * @var string + * + * @Column(type="string", name="output_columns_select_all_btn_color", nullable=false, options={ + * "default" : "#6C757D" + * }) + */ + protected $outputColumnsSelectAllBtnColor; + + /** + * @var string + * + * @Column(type="string", name="output_columns_select_all_btn_hover_color", nullable=false, options={ + * "default" : "#6C757D" + * }) + */ + protected $outputColumnsSelectAllBtnHoverColor; + + /** + * @var string + * + * @Column(type="string", name="output_columns_select_all_btn_hover_text_color", nullable=false, options={ + * "default" : "#FFFFFF" + * }) + */ + protected $outputColumnsSelectAllBtnHoverTextColor; + + /** + * @var string + * + * @Column(type="string", name="result_download_btn_color", nullable=false, options={"default" : "#007BFF"}) + */ + protected $resultDownloadBtnColor; + + /** + * @var string + * + * @Column(type="string", name="result_download_btn_hover_color", nullable=false, options={"default" : "#0069D9"}) + */ + protected $resultDownloadBtnHoverColor; + + /** + * @var string + * + * @Column(type="string", name="result_download_btn_text_color", nullable=false, options={"default" : "#FFFFFF"}) + */ + protected $resultDownloadBtnTextColor; + + /** + * @var string + * + * @Column(type="string", name="result_datatable_actions_btn_color", nullable=false, options={ + * "default" : "#007BFF" + * }) + */ + protected $resultDatatableActionsBtnColor; + + /** + * @var string + * + * @Column(type="string", name="result_datatable_actions_btn_hover_color", nullable=false, options={ + * "default" : "#0069D9" + * }) + */ + protected $resultDatatableActionsBtnHoverColor; + + /** + * @var string + * + * @Column(type="string", name="result_datatable_actions_btn_text_color", nullable=false, options={ + * "default" : "#FFFFFF" + * }) + */ + protected $resultDatatableActionsBtnTextColor; /** * @var bool @@ -329,6 +593,13 @@ class Instance implements \JsonSerializable */ protected $resultDatatableBordered; + /** + * @var bool + * + * @Column(type="boolean", name="result_datatable_bordered_radius", nullable=false, options={"default" : false}) + */ + protected $resultDatatableBorderedRadius; + /** * @var string * @@ -602,14 +873,14 @@ class Instance implements \JsonSerializable $this->portalLogo = $portalLogo; } - public function getDesignColor() + public function getPortalColor() { - return $this->designColor; + return $this->portalColor; } - public function setDesignColor($designColor) + public function setPortalColor($portalColor) { - $this->designColor = $designColor; + $this->portalColor = $portalColor; } public function getDesignBackgroundColor() @@ -622,6 +893,46 @@ class Instance implements \JsonSerializable $this->designBackgroundColor = $designBackgroundColor; } + public function getDesignTextColor() + { + return $this->designTextColor; + } + + public function setDesignTextColor($designTextColor) + { + return $this->designTextColor = $designTextColor; + } + + public function getDesignFontFamily() + { + return $this->designFontFamily; + } + + public function setDesignFontFamily($designFontFamily) + { + $this->designFontFamily = $designFontFamily; + } + + public function getDesignLinkColor() + { + return $this->designLinkColor; + } + + public function setDesignLinkColor($designLinkColor) + { + $this->designLinkColor = $designLinkColor; + } + + public function getDesignLinkHoverColor() + { + return $this->designLinkHoverColor; + } + + public function setDesignLinkHoverColor($designLinkHoverColor) + { + $this->designLinkHoverColor = $designLinkHoverColor; + } + public function getDesignLogo() { return $this->designLogo; @@ -642,6 +953,16 @@ class Instance implements \JsonSerializable $this->designFavicon = $designFavicon; } + public function getDesignLogoHref() + { + return $this->designLogoHref; + } + + public function setDesignLogoHref($designLogoHref) + { + $this->designLogoHref = $designLogoHref; + } + public function getNavbarBackgroundColor() { return $this->navbarBackgroundColor; @@ -672,6 +993,36 @@ class Instance implements \JsonSerializable $this->navbarColorHref = $navbarColorHref; } + public function getNavbarFontFamily() + { + return $this->navbarFontFamily; + } + + public function setNavbarFontFamily($navbarFontFamily) + { + $this->navbarFontFamily = $navbarFontFamily; + } + + public function getNavbarSignInBtnColor() + { + return $this->navbarSignInBtnColor; + } + + public function setNavbarSignInBtnColor($navbarSignInBtnColor) + { + $this->navbarSignInBtnColor = $navbarSignInBtnColor; + } + + public function getNavbarUserBtnColor() + { + return $this->navbarUserBtnColor; + } + + public function setNavbarUserBtnColor($navbarUserBtnColor) + { + $this->navbarUserBtnColor = $navbarUserBtnColor; + } + public function getFooterBackgroundColor() { return $this->footerBackgroundColor; @@ -702,6 +1053,16 @@ class Instance implements \JsonSerializable $this->footerTextColor = $footerTextColor; } + public function getFooterLogos() + { + return $this->footerLogos; + } + + public function setFooterLogos($footerLogos) + { + $this->footerLogos = $footerLogos; + } + public function getFamilyBorderColor() { return $this->familyBorderColor; @@ -752,14 +1113,14 @@ class Instance implements \JsonSerializable $this->familyBackgroundColor = $familyBackgroundColor; } - public function getFamilyColor() + public function getFamilyTextColor() { - return $this->familyColor; + return $this->familyTextColor; } - public function setFamilyColor($familyColor) + public function setFamilyTextColor($familyTextColor) { - $this->familyColor = $familyColor; + $this->familyTextColor = $familyTextColor; } public function getProgressBarTitle() @@ -802,6 +1163,46 @@ class Instance implements \JsonSerializable $this->progressBarSubtitleColor = $progressBarSubtitleColor; } + public function getProgressBarStepDatasetTitle() + { + return $this->progressBarStepDatasetTitle; + } + + public function setProgressBarStepDatasetTitle($progressBarStepDatasetTitle) + { + $this->progressBarStepDatasetTitle = $progressBarStepDatasetTitle; + } + + public function getProgressBarStepCriteriaTitle() + { + return $this->progressBarStepCriteriaTitle; + } + + public function setProgressBarStepCriteriaTitle($progressBarStepCriteriaTitle) + { + $this->progressBarStepCriteriaTitle = $progressBarStepCriteriaTitle; + } + + public function getProgressBarStepOutputTitle() + { + return $this->progressBarStepOutputTitle; + } + + public function setProgressBarStepOutputTitle($progressBarStepOutputTitle) + { + $this->progressBarStepOutputTitle = $progressBarStepOutputTitle; + } + + public function getProgressBarStepResultTitle() + { + return $this->progressBarStepResultTitle; + } + + public function setProgressBarStepResultTitle($progressBarStepResultTitle) + { + $this->progressBarStepResultTitle = $progressBarStepResultTitle; + } + public function getProgressBarColor() { return $this->progressBarColor; @@ -862,54 +1263,264 @@ class Instance implements \JsonSerializable $this->progressBarTextColor = $progressBarTextColor; } - public function getResultHeaderBackgroundColor() + public function getProgressBarTextBold() + { + return $this->progressBarTextBold; + } + + public function setProgressBarTextBold($progressBarTextBold) + { + $this->progressBarTextBold = $progressBarTextBold; + } + + public function getSearchNextBtnColor() + { + return $this->searchNextBtnColor; + } + + public function setSearchNextBtnColor($searchNextBtnColor) { - return $this->resultHeaderBackgroundColor; + $this->searchNextBtnColor = $searchNextBtnColor; } - public function setResultHeaderBackgroundColor($resultHeaderBackgroundColor) + public function getSearchNextBtnHoverColor() { - $this->resultHeaderBackgroundColor = $resultHeaderBackgroundColor; + return $this->searchNextBtnHoverColor; } - public function getResultHeaderTextColor() + public function setSearchNextBtnHoverColor($searchNextBtnHoverColor) { - return $this->resultHeaderTextColor; + $this->searchNextBtnHoverColor = $searchNextBtnHoverColor; } - public function setResultHeaderTextColor($resultHeaderTextColor) + public function getSearchNextBtnHoverTextColor() { - $this->resultHeaderTextColor = $resultHeaderTextColor; + return $this->searchNextBtnHoverTextColor; } - public function getResultHeaderBtnColor() + public function setSearchNextBtnHoverTextColor($searchNextBtnHoverTextColor) { - return $this->resultHeaderBtnColor; + $this->searchNextBtnHoverTextColor = $searchNextBtnHoverTextColor; } - public function setResultHeaderBtnColor($resultHeaderBtnColor) + public function getSearchBackBtnColor() { - $this->resultHeaderBtnColor = $resultHeaderBtnColor; + return $this->searchBackBtnColor; } - public function getResultHeaderBtnHoverColor() + public function setSearchBackBtnColor($searchBackBtnColor) { - return $this->resultHeaderBtnHoverColor; + $this->searchBackBtnColor = $searchBackBtnColor; } - public function setResultHeaderBtnHoverColor($resultHeaderBtnHoverColor) + public function getSearchBackBtnHoverColor() { - $this->resultHeaderBtnHoverColor = $resultHeaderBtnHoverColor; + return $this->searchBackBtnHoverColor; } - public function getResultHeaderBtnTextColor() + public function setSearchBackBtnHoverColor($searchBackBtnHoverColor) { - return $this->resultHeaderBtnTextColor; + $this->searchBackBtnHoverColor = $searchBackBtnHoverColor; } - public function setResultHeaderBtnTextColor($resultHeaderBtnTextColor) + public function getSearchBackBtnHoverTextColor() { - $this->resultHeaderBtnTextColor = $resultHeaderBtnTextColor; + return $this->searchBackBtnHoverTextColor; + } + + public function setSearchBackBtnHoverTextColor($searchBackBtnHoverTextColor) + { + $this->searchBackBtnHoverTextColor = $searchBackBtnHoverTextColor; + } + + public function setSearchInfoBackgroundColor($searchInfoBackgroundColor) + { + $this->searchInfoBackgroundColor = $searchInfoBackgroundColor; + } + + public function getSearchInfoTextColor() + { + return $this->searchInfoTextColor; + } + + public function setSearchInfoTextColor($searchInfoTextColor) + { + $this->searchInfoTextColor = $searchInfoTextColor; + } + + public function getSearchInfoHelpEnabled() + { + return $this->searchInfoHelpEnabled; + } + + public function setSearchInfoHelpEnabled($searchInfoHelpEnabled) + { + $this->searchInfoHelpEnabled = $searchInfoHelpEnabled; + } + + public function getDatasetSelectBtnColor() + { + return $this->datasetSelectBtnColor; + } + + public function setDatasetSelectBtnColor($datasetSelectBtnColor) + { + $this->datasetSelectBtnColor = $datasetSelectBtnColor; + } + + public function getDatasetSelectBtnHoverColor() + { + return $this->datasetSelectBtnHoverColor; + } + + public function setDatasetSelectBtnHoverColor($datasetSelectBtnHoverColor) + { + $this->datasetSelectBtnHoverColor = $datasetSelectBtnHoverColor; + } + + public function getDatasetSelectBtnHoverTextColor() + { + return $this->datasetSelectBtnHoverTextColor; + } + + public function setDatasetSelectBtnHoverTextColor($datasetSelectBtnHoverTextColor) + { + $this->datasetSelectBtnHoverTextColor = $datasetSelectBtnHoverTextColor; + } + + public function getDatasetSelectedIconColor() + { + return $this->datasetSelectedIconColor; + } + + public function setDatasetSelectedIconColor($datasetSelectedIconColor) + { + $this->datasetSelectedIconColor = $datasetSelectedIconColor; + } + + public function getSearchInfoBackgroundColor() + { + return $this->searchInfoBackgroundColor; + } + + public function getSearchCriterionBackgroundColor() + { + return $this->searchCriterionBackgroundColor; + } + + public function setSearchCriterionBackgroundColor($searchCriterionBackgroundColor) + { + $this->searchCriterionBackgroundColor = $searchCriterionBackgroundColor; + } + + public function getSearchCriterionTextColor() + { + return $this->searchCriterionTextColor; + } + + public function setSearchCriterionTextColor($searchCriterionTextColor) + { + $this->searchCriterionTextColor = $searchCriterionTextColor; + } + + public function getOutputColumnsSelectedColor() + { + return $this->outputColumnsSelectedColor; + } + + public function setOutputColumnsSelectedColor($outputColumnsSelectedColor) + { + $this->outputColumnsSelectedColor = $outputColumnsSelectedColor; + } + + public function getOutputColumnsSelectAllBtnColor() + { + return $this->outputColumnsSelectAllBtnColor; + } + + public function setOutputColumnsSelectAllBtnColor($outputColumnsSelectAllBtnColor) + { + $this->outputColumnsSelectAllBtnColor = $outputColumnsSelectAllBtnColor; + } + + public function getOutputColumnsSelectAllBtnHoverColor() + { + return $this->outputColumnsSelectAllBtnHoverColor; + } + + public function setOutputColumnsSelectAllBtnHoverColor($outputColumnsSelectAllBtnHoverColor) + { + $this->outputColumnsSelectAllBtnHoverColor = $outputColumnsSelectAllBtnHoverColor; + } + + public function getOutputColumnsSelectAllBtnHoverTextColor() + { + return $this->outputColumnsSelectAllBtnHoverTextColor; + } + + public function setOutputColumnsSelectAllBtnHoverTextColor($outputColumnsSelectAllBtnHoverTextColor) + { + $this->outputColumnsSelectAllBtnHoverTextColor = $outputColumnsSelectAllBtnHoverTextColor; + } + + public function getResultDownloadBtnColor() + { + return $this->resultDownloadBtnColor; + } + + public function setResultDownloadBtnColor($resultDownloadBtnColor) + { + $this->resultDownloadBtnColor = $resultDownloadBtnColor; + } + + public function getResultDownloadBtnHoverColor() + { + return $this->resultDownloadBtnHoverColor; + } + + public function setResultDownloadBtnHoverColor($resultDownloadBtnHoverColor) + { + $this->resultDownloadBtnHoverColor = $resultDownloadBtnHoverColor; + } + + public function getResultDownloadBtnTextColor() + { + return $this->resultDownloadBtnTextColor; + } + + public function setResultDownloadBtnTextColor($resultDownloadBtnTextColor) + { + $this->resultDownloadBtnTextColor = $resultDownloadBtnTextColor; + } + + public function getResultDatatableActionsBtnColor() + { + return $this->resultDatatableActionsBtnColor; + } + + public function setResultDatatableActionsBtnColor($resultDatatableActionsBtnColor) + { + $this->resultDatatableActionsBtnColor = $resultDatatableActionsBtnColor; + } + + public function getResultDatatableActionsBtnHoverColor() + { + return $this->resultDatatableActionsBtnHoverColor; + } + + public function setResultDatatableActionsBtnHoverColor($resultDatatableActionsBtnHoverColor) + { + $this->resultDatatableActionsBtnHoverColor = $resultDatatableActionsBtnHoverColor; + } + + public function getResultDatatableActionsBtnTextColor() + { + return $this->resultDatatableActionsBtnTextColor; + } + + public function setResultDatatableActionsBtnTextColor($resultDatatableActionsBtnTextColor) + { + $this->resultDatatableActionsBtnTextColor = $resultDatatableActionsBtnTextColor; } public function getResultDatatableBordered() @@ -922,6 +1533,16 @@ class Instance implements \JsonSerializable $this->resultDatatableBordered = $resultDatatableBordered; } + public function getResultDatatableBorderedRadius() + { + return $this->resultDatatableBorderedRadius; + } + + public function setResultDatatableBorderedRadius($resultDatatableBorderedRadius) + { + $this->resultDatatableBorderedRadius = $resultDatatableBorderedRadius; + } + public function getResultDatatableBorderColor() { return $this->resultDatatableBorderColor; @@ -1150,38 +1771,73 @@ class Instance implements \JsonSerializable 'files_path' => $this->getFilesPath(), 'public' => $this->getPublic(), 'portal_logo' => $this->getPortalLogo(), - 'design_color' => $this->getDesignColor(), + 'portal_color' => $this->getPortalColor(), 'design_background_color' => $this->getDesignBackgroundColor(), + 'design_text_color' => $this->getDesignTextColor(), + 'design_font_family' => $this->getDesignFontFamily(), + 'design_link_color' => $this->getDesignLinkColor(), + 'design_link_hover_color' => $this->getDesignLinkHoverColor(), 'design_logo' => $this->getDesignLogo(), + 'design_logo_href' => $this->getDesignLogoHref(), 'design_favicon' => $this->getDesignFavicon(), 'navbar_background_color' => $this->getNavbarBackgroundColor(), 'navbar_border_bottom_color' => $this->getNavbarBorderBottomColor(), 'navbar_color_href' => $this->getNavbarColorHref(), + 'navbar_font_family' => $this->getNavbarFontFamily(), + 'navbar_sign_in_btn_color' => $this->getNavbarSignInBtnColor(), + 'navbar_user_btn_color' => $this->getNavbarUserBtnColor(), 'footer_background_color' => $this->getFooterBackgroundColor(), 'footer_border_top_color' => $this->getFooterBorderTopColor(), 'footer_text_color' => $this->getFooterTextColor(), + 'footer_logos' => $this->getFooterLogos(), 'family_border_color' => $this->getFamilyBorderColor(), 'family_header_background_color' => $this->getFamilyHeaderBackgroundColor(), 'family_title_color' => $this->getFamilyTitleColor(), 'family_title_bold' => $this->getFamilyTitleBold(), 'family_background_color' => $this->getFamilyBackgroundColor(), - 'family_color' => $this->getFamilyColor(), + 'family_text_color' => $this->getFamilyTextColor(), 'progress_bar_title' => $this->getProgressBarTitle(), 'progress_bar_title_color' => $this->getProgressBarTitleColor(), 'progress_bar_subtitle' => $this->getProgressBarSubtitle(), 'progress_bar_subtitle_color' => $this->getProgressBarSubtitleColor(), + 'progress_bar_step_dataset_title' => $this->getProgressBarStepDatasetTitle(), + 'progress_bar_step_criteria_title' => $this->getProgressBarStepCriteriaTitle(), + 'progress_bar_step_output_title' => $this->getProgressBarStepOutputTitle(), + 'progress_bar_step_result_title' => $this->getProgressBarStepResultTitle(), 'progress_bar_color' => $this->getProgressBarColor(), 'progress_bar_active_color' => $this->getProgressBarActiveColor(), 'progress_bar_circle_color' => $this->getProgressBarCircleColor(), 'progress_bar_circle_icon_color' => $this->getProgressBarCircleIconColor(), 'progress_bar_circle_icon_active_color' => $this->getProgressBarCircleIconActiveColor(), 'progress_bar_text_color' => $this->getProgressBarTextColor(), - 'result_header_background_color' => $this->getResultHeaderBackgroundColor(), - 'result_header_text_color' => $this->getResultHeaderTextColor(), - 'result_header_btn_color' => $this->getResultHeaderBtnColor(), - 'result_header_btn_hover_color' => $this->getResultHeaderBtnHoverColor(), - 'result_header_btn_text_color' => $this->getResultHeaderBtnTextColor(), + 'progress_bar_text_bold' => $this->getProgressBarTextBold(), + 'search_next_btn_color' => $this->getSearchNextBtnColor(), + 'search_next_btn_hover_color' => $this->getSearchNextBtnHoverColor(), + 'search_next_btn_hover_text_color' => $this->getSearchNextBtnHoverTextColor(), + 'search_back_btn_color' => $this->getSearchBackBtnColor(), + 'search_back_btn_hover_color' => $this->getSearchBackBtnHoverColor(), + 'search_back_btn_hover_text_color' => $this->getSearchBackBtnHoverTextColor(), + 'search_info_background_color' => $this->getSearchInfoBackgroundColor(), + 'search_info_text_color' => $this->getSearchInfoTextColor(), + 'search_info_help_enabled' => $this->getSearchInfoHelpEnabled(), + 'dataset_select_btn_color' => $this->getDatasetSelectBtnColor(), + 'dataset_select_btn_hover_color' => $this->getDatasetSelectBtnHoverColor(), + 'dataset_select_btn_hover_text_color' => $this->getDatasetSelectBtnHoverTextColor(), + 'dataset_selected_icon_color' => $this->getDatasetSelectedIconColor(), + 'search_criterion_background_color' => $this->getSearchCriterionBackgroundColor(), + 'search_criterion_text_color' => $this->getSearchCriterionTextColor(), + 'output_columns_selected_color' => $this->getOutputColumnsSelectedColor(), + 'output_columns_select_all_btn_color' => $this->getOutputColumnsSelectAllBtnColor(), + 'output_columns_select_all_btn_hover_color' => $this->getOutputColumnsSelectAllBtnHoverColor(), + 'output_columns_select_all_btn_hover_text_color' => $this->getOutputColumnsSelectAllBtnHoverTextColor(), + 'result_download_btn_color' => $this->getResultDownloadBtnColor(), + 'result_download_btn_hover_color' => $this->getResultDownloadBtnHoverColor(), + 'result_download_btn_text_color' => $this->getResultDownloadBtnTextColor(), + 'result_datatable_actions_btn_color' => $this->getResultDatatableActionsBtnColor(), + 'result_datatable_actions_btn_hover_color' => $this->getResultDatatableActionsBtnHoverColor(), + 'result_datatable_actions_btn_text_color' => $this->getResultDatatableActionsBtnTextColor(), 'result_datatable_bordered' => $this->getResultDatatableBordered(), + 'result_datatable_bordered_radius' => $this->getResultDatatableBorderedRadius(), 'result_datatable_border_color' => $this->getResultDatatableBorderColor(), 'result_datatable_header_background_color' => $this->getResultDatatableHeaderBackgroundColor(), 'result_datatable_header_text_color' => $this->getResultDatatableHeaderTextColor(), diff --git a/server/tests/Action/AttributeActionTest.php b/server/tests/Action/AttributeActionTest.php index 0617eb9516e2ebe7017146203d99d8a29b93a1be..fb141e27546471e40a907f2e5742c347d586eb92 100644 --- a/server/tests/Action/AttributeActionTest.php +++ b/server/tests/Action/AttributeActionTest.php @@ -153,6 +153,8 @@ final class AttributeActionTest extends TestCase 'archive' => false, 'detail' => false, 'detail_display' => 10, + 'detail_renderer' => null, + 'detail_renderer_config' => null, 'vo_utype' => null, 'vo_ucd' => null, 'vo_unit' => null, diff --git a/server/tests/Action/AttributeListActionTest.php b/server/tests/Action/AttributeListActionTest.php index 85e3368ace16c9107f8272c884c4b2e73ff43a63..9f5c5a4315c6b88d43ab1fe37ec0cc5dc990d243 100644 --- a/server/tests/Action/AttributeListActionTest.php +++ b/server/tests/Action/AttributeListActionTest.php @@ -105,6 +105,8 @@ final class AttributeListActionTest extends TestCase 'archive' => false, 'detail' => false, 'detail_display' => 10, + 'detail_renderer' => null, + 'detail_renderer_config' => null, 'vo_utype' => null, 'vo_ucd' => null, 'vo_unit' => null, diff --git a/server/tests/Action/InstanceActionTest.php b/server/tests/Action/InstanceActionTest.php index d5d2f8128478df787fa67194246789dd4e09b632..3c0ec2c2af289d3ad894704bf721e9d2948410ab 100644 --- a/server/tests/Action/InstanceActionTest.php +++ b/server/tests/Action/InstanceActionTest.php @@ -88,38 +88,73 @@ final class InstanceActionTest extends TestCase 'files_path' => '/INSTANCE_FILES', 'public' => true, 'portal_logo' => '', - 'design_color' => '#7AC29A', + 'portal_color' => '#7AC29A', 'design_background_color' => '#FFFFFF', + 'design_text_color' => '#212529', + 'design_font_family' => 'Roboto, sans-serif', + 'design_link_color' => '#007BFF', + 'design_link_hover_color' => '#0056B3', 'design_logo' => 'logo.png', + 'design_logo_href' => null, 'design_favicon' => 'favicon.ico', 'navbar_background_color' => '#F8F9FA', 'navbar_border_bottom_color' => '#DEE2E6', 'navbar_color_href' => '#000000', + 'navbar_font_family' => 'auto', + 'navbar_sign_in_btn_color' => '#28A745', + 'navbar_user_btn_color' => '#7AC29A', 'footer_background_color' => '#F8F9FA', 'footer_border_top_color' => '#DEE2E6', 'footer_text_color' => '#000000', + 'footer_logos' => null, 'family_border_color' => '#DFDFDF', 'family_header_background_color' => '#F7F7F7', 'family_title_color' => '#007BFF', 'family_title_bold' => false, 'family_background_color' => '#FFFFFF', - 'family_color' => '#212529', + 'family_text_color' => '#212529', 'progress_bar_title' => 'Dataset search', 'progress_bar_title_color' => '#000000', 'progress_bar_subtitle' => 'Select a dataset, add criteria, select output columns and display the result.', 'progress_bar_subtitle_color' => '#6C757D', + 'progress_bar_step_dataset_title' => 'Dataset selection', + 'progress_bar_step_criteria_title' => 'Search criteria', + 'progress_bar_step_output_title' => 'Output columns', + 'progress_bar_step_result_title' => 'Result table', 'progress_bar_color' => '#E9ECEF', 'progress_bar_active_color' => '#7AC29A', 'progress_bar_circle_color' => '#FFFFFF', 'progress_bar_circle_icon_color' => '#CCCCCC', 'progress_bar_circle_icon_active_color' => '#FFFFFF', 'progress_bar_text_color' => '#91B2BF', - 'result_header_background_color' => '#E9ECEF', - 'result_header_text_color' => '#000000', - 'result_header_btn_color' => '#007BFF', - 'result_header_btn_hover_color' => '#0069D9', - 'result_header_btn_text_color' => '#FFFFFF', + 'progress_bar_text_bold' => false, + 'search_next_btn_color' => '#007BFF', + 'search_next_btn_hover_color' => '#007BFF', + 'search_next_btn_hover_text_color' => '#FFFFFF', + 'search_back_btn_color' => '#6C757D', + 'search_back_btn_hover_color' => '#6C757D', + 'search_back_btn_hover_text_color' => '#FFFFFF', + 'search_info_background_color' => '#E9ECEF', + 'search_info_text_color' => '#000000', + 'search_info_help_enabled' => true, + 'dataset_select_btn_color' => '#6C757D', + 'dataset_select_btn_hover_color' => '#6C757D', + 'dataset_select_btn_hover_text_color' => '#FFFFFF', + 'dataset_selected_icon_color' => '#28A745', + 'search_criterion_background_color' => '#7AC29A', + 'search_criterion_text_color' => '#000000', + 'output_columns_selected_color' => '#7AC29A', + 'output_columns_select_all_btn_color' => '#6C757D', + 'output_columns_select_all_btn_hover_color' => '#6C757D', + 'output_columns_select_all_btn_hover_text_color' => '#FFFFFF', + 'result_download_btn_color' => '#007BFF', + 'result_download_btn_hover_color' => '#0069D9', + 'result_download_btn_text_color' => '#FFFFFF', + 'result_datatable_actions_btn_color' => '#007BFF', + 'result_datatable_actions_btn_hover_color' => '#0069D9', + 'result_datatable_actions_btn_text_color' => '#FFFFFF', 'result_datatable_bordered' => true, + 'result_datatable_bordered_radius' => false, 'result_datatable_border_color' => '#DEE2E6', 'result_datatable_header_background_color' => '#FFFFFF', 'result_datatable_header_text_color' => '#000000', diff --git a/server/tests/Action/InstanceListActionTest.php b/server/tests/Action/InstanceListActionTest.php index 7af0c72b25162a031805bd403d8f6ec6dff2cddd..dc860f9d392710c78a2c60121b633ffce6f8450c 100644 --- a/server/tests/Action/InstanceListActionTest.php +++ b/server/tests/Action/InstanceListActionTest.php @@ -72,38 +72,73 @@ final class InstanceListActionTest extends TestCase 'files_path' => '/INSTANCE_FILES', 'public' => true, 'portal_logo' => '', - 'design_color' => '#7AC29A', + 'portal_color' => '#7AC29A', 'design_background_color' => '#FFFFFF', + 'design_text_color' => '#212529', + 'design_font_family' => 'Roboto, sans-serif', + 'design_link_color' => '#007BFF', + 'design_link_hover_color' => '#0056B3', 'design_logo' => 'logo.png', + 'design_logo_href' => null, 'design_favicon' => 'favicon.ico', 'navbar_background_color' => '#F8F9FA', 'navbar_border_bottom_color' => '#DEE2E6', 'navbar_color_href' => '#000000', + 'navbar_font_family' => 'auto', + 'navbar_sign_in_btn_color' => '#28A745', + 'navbar_user_btn_color' => '#7AC29A', 'footer_background_color' => '#F8F9FA', 'footer_border_top_color' => '#DEE2E6', 'footer_text_color' => '#000000', + 'footer_logos' => null, 'family_border_color' => '#DFDFDF', 'family_header_background_color' => '#F7F7F7', 'family_title_color' => '#007BFF', 'family_title_bold' => false, 'family_background_color' => '#FFFFFF', - 'family_color' => '#212529', + 'family_text_color' => '#212529', 'progress_bar_title' => 'Dataset search', 'progress_bar_title_color' => '#000000', 'progress_bar_subtitle' => 'Select a dataset, add criteria, select output columns and display the result.', 'progress_bar_subtitle_color' => '#6C757D', + 'progress_bar_step_dataset_title' => 'Dataset selection', + 'progress_bar_step_criteria_title' => 'Search criteria', + 'progress_bar_step_output_title' => 'Output columns', + 'progress_bar_step_result_title' => 'Result table', 'progress_bar_color' => '#E9ECEF', 'progress_bar_active_color' => '#7AC29A', 'progress_bar_circle_color' => '#FFFFFF', 'progress_bar_circle_icon_color' => '#CCCCCC', 'progress_bar_circle_icon_active_color' => '#FFFFFF', 'progress_bar_text_color' => '#91B2BF', - 'result_header_background_color' => '#E9ECEF', - 'result_header_text_color' => '#000000', - 'result_header_btn_color' => '#007BFF', - 'result_header_btn_hover_color' => '#0069D9', - 'result_header_btn_text_color' => '#FFFFFF', + 'progress_bar_text_bold' => false, + 'search_next_btn_color' => '#007BFF', + 'search_next_btn_hover_color' => '#007BFF', + 'search_next_btn_hover_text_color' => '#FFFFFF', + 'search_back_btn_color' => '#6C757D', + 'search_back_btn_hover_color' => '#6C757D', + 'search_back_btn_hover_text_color' => '#FFFFFF', + 'search_info_background_color' => '#E9ECEF', + 'search_info_text_color' => '#000000', + 'search_info_help_enabled' => true, + 'dataset_select_btn_color' => '#6C757D', + 'dataset_select_btn_hover_color' => '#6C757D', + 'dataset_select_btn_hover_text_color' => '#FFFFFF', + 'dataset_selected_icon_color' => '#28A745', + 'search_criterion_background_color' => '#7AC29A', + 'search_criterion_text_color' => '#000000', + 'output_columns_selected_color' => '#7AC29A', + 'output_columns_select_all_btn_color' => '#6C757D', + 'output_columns_select_all_btn_hover_color' => '#6C757D', + 'output_columns_select_all_btn_hover_text_color' => '#FFFFFF', + 'result_download_btn_color' => '#007BFF', + 'result_download_btn_hover_color' => '#0069D9', + 'result_download_btn_text_color' => '#FFFFFF', + 'result_datatable_actions_btn_color' => '#007BFF', + 'result_datatable_actions_btn_hover_color' => '#0069D9', + 'result_datatable_actions_btn_text_color' => '#FFFFFF', 'result_datatable_bordered' => true, + 'result_datatable_bordered_radius' => false, 'result_datatable_border_color' => '#DEE2E6', 'result_datatable_header_background_color' => '#FFFFFF', 'result_datatable_header_text_color' => '#000000',