diff --git a/client/src/app/admin/admin.component.ts b/client/src/app/admin/admin.component.ts index 57ebd0e4293df864cd09386c3bdc48a25be33979..b31b8d79070b7c89617c37275640a35178e913e1 100644 --- a/client/src/app/admin/admin.component.ts +++ b/client/src/app/admin/admin.component.ts @@ -20,6 +20,7 @@ import * as surveyActions from 'src/app/metamodel/actions/survey.actions'; import * as databaseActions from 'src/app/metamodel/actions/database.actions'; import * as selectActions from 'src/app/metamodel/actions/select.actions'; import * as optionActions from 'src/app/metamodel/actions/select-option.actions'; +import * as instanceGroupActions from 'src/app/metamodel/actions/instance-group.actions'; import { AppConfigService } from 'src/app/app-config.service'; @Component({ @@ -35,6 +36,7 @@ import { AppConfigService } from 'src/app/app-config.service'; export class AdminComponent implements OnInit { public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public title: HTMLLinkElement = document.querySelector('#title'); + public body: HTMLBodyElement = document.querySelector('body'); public links = [ { label: 'Instances', icon: 'fas fa-object-group', routerLink: 'instance/instance-list' }, { label: 'Surveys', icon: 'fas fa-table', routerLink: 'survey/survey-list'}, @@ -56,10 +58,12 @@ export class AdminComponent implements OnInit { ngOnInit() { this.favIcon.href = 'favicon.ico'; this.title.innerHTML = 'ANIS - Admin'; + this.body.style.backgroundColor = 'white'; Promise.resolve(null).then(() => this.store.dispatch(surveyActions.loadSurveyList())); Promise.resolve(null).then(() => this.store.dispatch(databaseActions.loadDatabaseList())); Promise.resolve(null).then(() => this.store.dispatch(selectActions.loadSelectList())); Promise.resolve(null).then(() => this.store.dispatch(optionActions.loadSelectOptionList())); + Promise.resolve(null).then(() => this.store.dispatch(instanceGroupActions.loadInstanceGroupList())); } getBaseHref() { 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 417127669b03932e4449dd2648a208a856c3e97e..06f689f946492894913aa41a959a7e8915910dda 100644 --- a/client/src/app/admin/instance/components/instance-form.component.html +++ b/client/src/app/admin/instance/components/instance-form.component.html @@ -132,6 +132,10 @@ <input class="custom-control-input" type="checkbox" id="samp_enabled" name="samp_enabled" formControlName="samp_enabled"> <label class="custom-control-label" for="samp_enabled">Samp enabled</label> </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> + </div> <div class="custom-control custom-switch mb-2"> <input class="custom-control-input" type="checkbox" id="search_by_criteria_allowed" name="search_by_criteria_allowed" formControlName="search_by_criteria_allowed" (change)="checkDisableSearchByCriteriaAllowed()"> <label class="custom-control-label" for="search_by_criteria_allowed">Classic search allowed</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 cd351cb4cba1fe952e2ea9ef367cdc24e8e57fd0..7ee22005564c21e61fd1a93c02d2256a5f93d7a3 100644 --- a/client/src/app/admin/instance/components/instance-form.component.ts +++ b/client/src/app/admin/instance/components/instance-form.component.ts @@ -46,6 +46,7 @@ the fast implementation of a project data exchange platform in a dedicated infor home_component_logo: new FormControl('home_component_logo.png', [Validators.required]) }), samp_enabled: new FormControl(true), + back_to_portal: new FormControl(true), search_by_criteria_allowed: new FormControl(true), search_by_criteria_label: new FormControl({value: 'Search', disabled: false}), search_multiple_allowed: new FormControl(false), diff --git a/client/src/app/admin/instance/containers/edit-instance-group.component.html b/client/src/app/admin/instance/containers/edit-instance-group.component.html index 99eb49d85c79a9e50cf32c8a9aad21d3f0c4d947..d00e72bf1d9bf0795b96d3e5ba8526bfec388da8 100644 --- a/client/src/app/admin/instance/containers/edit-instance-group.component.html +++ b/client/src/app/admin/instance/containers/edit-instance-group.component.html @@ -26,7 +26,7 @@ <span class="fa fa-database"></span> Update instance group information </button> - <a routerLink="/admin/instance/group" role="button" class="btn btn-danger">Cancel</a> + <a routerLink="/admin/instance/instance-group" role="button" class="btn btn-danger">Cancel</a> </app-instance-group-form> </div> </div> diff --git a/client/src/app/admin/instance/containers/edit-instance-group.component.ts b/client/src/app/admin/instance/containers/edit-instance-group.component.ts index 47dd9cafe321eb64a78f0a0ad272a28fef64da4f..72be239d721430381344811718b2cfa617b8dd8c 100644 --- a/client/src/app/admin/instance/containers/edit-instance-group.component.ts +++ b/client/src/app/admin/instance/containers/edit-instance-group.component.ts @@ -7,7 +7,7 @@ * file that was distributed with this source code. */ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { Observable } from 'rxjs'; import { Store } from '@ngrx/store'; @@ -20,7 +20,7 @@ import * as instanceGroupSelector from 'src/app/metamodel/selectors/instance-gro selector: 'app-edit-instance-group', templateUrl: 'edit-instance-group.component.html' }) -export class EditInstanceGroupComponent implements OnInit { +export class EditInstanceGroupComponent { public instanceGroupListIsLoading: Observable<boolean>; public instanceGroupListIsLoaded: Observable<boolean>; public instanceGroup: Observable<InstanceGroup>; @@ -37,10 +37,6 @@ export class EditInstanceGroupComponent implements OnInit { this.instanceList = store.select(instanceSelector.selectAllInstances); } - ngOnInit() { - Promise.resolve(null).then(() => this.store.dispatch(instanceGroupActions.loadInstanceGroupList())); - } - editInstanceGroup(instanceGroup: InstanceGroup) { this.store.dispatch(instanceGroupActions.editInstanceGroup({ instanceGroup })); } diff --git a/client/src/app/admin/instance/containers/instance-group-list.component.ts b/client/src/app/admin/instance/containers/instance-group-list.component.ts index a3f054a84d3072fe1a1ae933d1488eed8aac97da..c874f8cdeec3bb6298801ae0105bb166c68e025d 100644 --- a/client/src/app/admin/instance/containers/instance-group-list.component.ts +++ b/client/src/app/admin/instance/containers/instance-group-list.component.ts @@ -19,7 +19,7 @@ import * as instanceGroupSelector from 'src/app/metamodel/selectors/instance-gro selector: 'app-instance-group-list', templateUrl: 'instance-group-list.component.html' }) -export class InstanceGroupListComponent implements OnInit { +export class InstanceGroupListComponent { public instanceGroupListIsLoading: Observable<boolean>; public instanceGroupListIsLoaded: Observable<boolean>; public instanceGroupList: Observable<InstanceGroup[]>; @@ -30,10 +30,6 @@ export class InstanceGroupListComponent implements OnInit { this.instanceGroupList = store.select(instanceGroupSelector.selectAllInstanceGroups); } - ngOnInit() { - Promise.resolve(null).then(() => this.store.dispatch(instanceGroupActions.loadInstanceGroupList())); - } - deleteInstanceGroup(instanceGroup: InstanceGroup) { this.store.dispatch(instanceGroupActions.deleteInstanceGroup({ instanceGroup })); } diff --git a/client/src/app/instance/instance.component.ts b/client/src/app/instance/instance.component.ts index fe75d5f433685394fea1b56695e85117b6f2dc52..6db00730a3bbcfb3d3b5ba10eac31285a59f1f49 100644 --- a/client/src/app/instance/instance.component.ts +++ b/client/src/app/instance/instance.component.ts @@ -37,6 +37,7 @@ import { AppConfigService } from 'src/app/app-config.service'; export class InstanceComponent implements OnInit, OnDestroy { public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public title: HTMLLinkElement = document.querySelector('#title'); + public body: HTMLBodyElement = document.querySelector('body'); public links = [ { label: 'Home', icon: 'fas fa-home', routerLink: 'home' } ]; @@ -76,6 +77,7 @@ export class InstanceComponent implements OnInit, OnDestroy { this.favIcon.href = `${this.config.apiUrl}/instance/${instance.name}/file-explorer${instance.design_favicon}`; } this.title.innerHTML = instance.label; + this.body.style.backgroundColor = instance.design_background_color; } }) } diff --git a/client/src/app/metamodel/models/instance.model.ts b/client/src/app/metamodel/models/instance.model.ts index 7962ff594997884de69813951c79a0b7c3f4bdab..0ac2e840a37362025eb10a1ea15dba77d2f9829a 100644 --- a/client/src/app/metamodel/models/instance.model.ts +++ b/client/src/app/metamodel/models/instance.model.ts @@ -29,6 +29,7 @@ export interface Instance { home_component_logo: string; }; samp_enabled: boolean; + back_to_portal: boolean; search_by_criteria_allowed: boolean; search_by_criteria_label: string; search_multiple_allowed: boolean; diff --git a/client/src/app/portal/containers/portal-home.component.ts b/client/src/app/portal/containers/portal-home.component.ts index 6ec0b9d55f477ec826989c3d13ace512eab7a15c..5bc6fe2acee504f766740b69b047e6fecf666a7a 100644 --- a/client/src/app/portal/containers/portal-home.component.ts +++ b/client/src/app/portal/containers/portal-home.component.ts @@ -34,6 +34,7 @@ import { AppConfigService } from 'src/app/app-config.service'; export class PortalHomeComponent implements OnInit { public favIcon: HTMLLinkElement = document.querySelector('#favicon'); public title: HTMLLinkElement = document.querySelector('#title'); + public body: HTMLBodyElement = document.querySelector('body'); public links = []; public isAuthenticated: Observable<boolean>; public userProfile: Observable<UserProfile>; @@ -53,6 +54,7 @@ export class PortalHomeComponent implements OnInit { ngOnInit() { this.favIcon.href = 'favicon.ico'; this.title.innerHTML = 'ANIS - Portal'; + this.body.style.backgroundColor = 'white'; } /** diff --git a/client/src/app/shared/components/navbar.component.html b/client/src/app/shared/components/navbar.component.html index 17f37000293c26df5dd768abfc6a4a0165c6ba19..498db98d2b57da63900ac5e6923487bbf551d753 100644 --- a/client/src/app/shared/components/navbar.component.html +++ b/client/src/app/shared/components/navbar.component.html @@ -19,7 +19,7 @@ </ul> <ul class="navbar-nav justify-content-end"> <li class="nav-item pr-3"> - <a *ngIf="!isPortalRoute()" class="nav-link" routerLink="/portal" routerLinkActive="active"> + <a *ngIf="isAdminRoute() || (instance && instance.back_to_portal)" class="nav-link" routerLink="/portal" routerLinkActive="active"> <span class="fa-solid fa-right-to-bracket"></span> Back to portal </a> </li> diff --git a/conf-dev/create-db.sh b/conf-dev/create-db.sh index 28a54e9983ab56f7e7e17f2dc0f46333da127eac..92e8206dfbb53f72128172a8e7ffbe3dd8b8fd15 100644 --- a/conf-dev/create-db.sh +++ b/conf-dev/create-db.sh @@ -60,7 +60,7 @@ curl -d '{"label":"Spectra graph","value":"spectra_graph","display":20,"select_n curl -d '{"label":"Test","dbname":"anis_test","dbtype":"pdo_pgsql","dbhost":"db","dbport":5432,"dblogin":"anis","dbpassword":"anis"}' --header 'Content-Type: application/json' -X POST http://localhost/database # Add default instance -curl -d '{"name":"default","label":"Default instance","description":"Instance for the test","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","home_component":"WelcomeComponent","home_component_config":{"home_component_text":"AstroNomical Information System","home_component_logo":"home_component_logo.png"},"samp_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","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","home_component":"WelcomeComponent","home_component_config":{"home_component_text":"AstroNomical Information System","home_component_logo":"/home_component_logo.png"},"samp_enabled":true,"back_to_portal":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 ANIS, SVOM and IRIS surveys curl -d '{"name":"anis_survey","label":"ANIS survey","description":"Survey used for testing","link":"https://anis.lam.fr","manager":"F. Agneray","id_database":1}' --header 'Content-Type: application/json' -X POST http://localhost/survey diff --git a/server/doctrine-proxy/__CG__AppEntityInstance.php b/server/doctrine-proxy/__CG__AppEntityInstance.php index 7b3ee86945dcfc9ec724aeb2c4c9cf32022b27a0..ed87c9138c09d718b5527218db49e1e630a4288b 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', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'homeComponent', 'homeComponentConfig', 'sampEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; + return ['__isInitialized__', 'name', 'label', 'description', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'homeComponent', 'homeComponentConfig', 'sampEnabled', 'backToPortal', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; } - return ['__isInitialized__', 'name', 'label', 'description', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'homeComponent', 'homeComponentConfig', 'sampEnabled', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; + return ['__isInitialized__', 'name', 'label', 'description', 'display', 'dataPath', 'filesPath', 'public', 'portalLogo', 'designColor', 'designBackgroundColor', 'designLogo', 'designFavicon', 'homeComponent', 'homeComponentConfig', 'sampEnabled', 'backToPortal', 'searchByCriteriaAllowed', 'searchByCriteriaLabel', 'searchMultipleAllowed', 'searchMultipleLabel', 'searchMultipleAllDatasetsSelected', 'documentationAllowed', 'documentationLabel', 'datasetFamilies']; } /** @@ -500,6 +500,28 @@ class Instance extends \App\Entity\Instance implements \Doctrine\ORM\Proxy\Proxy return parent::setSampEnabled($sampEnabled); } + /** + * {@inheritDoc} + */ + public function getBackToPortal() + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'getBackToPortal', []); + + return parent::getBackToPortal(); + } + + /** + * {@inheritDoc} + */ + public function setBackToPortal($backToPortal) + { + + $this->__initializer__ && $this->__initializer__->__invoke($this, 'setBackToPortal', [$backToPortal]); + + return parent::setBackToPortal($backToPortal); + } + /** * {@inheritDoc} */ diff --git a/server/src/Action/InstanceAction.php b/server/src/Action/InstanceAction.php index a9044e59228ad6f6d61a172b9f0568548ca4d83d..f116e2be3b69391e9745d34a9afced027d8ecd12 100644 --- a/server/src/Action/InstanceAction.php +++ b/server/src/Action/InstanceAction.php @@ -109,6 +109,7 @@ final class InstanceAction extends AbstractAction $instance->setHomeComponent($parsedBody['home_component']); $instance->setHomeComponentConfig($parsedBody['home_component_config']); $instance->setSampEnabled($parsedBody['samp_enabled']); + $instance->setBackToPortal($parsedBody['back_to_portal']); $instance->setSearchByCriteriaAllowed($parsedBody['search_by_criteria_allowed']); $instance->setSearchByCriteriaLabel($parsedBody['search_by_criteria_label']); $instance->setSearchMultipleAllowed($parsedBody['search_multiple_allowed']); diff --git a/server/src/Action/InstanceListAction.php b/server/src/Action/InstanceListAction.php index 408253749283fdb789d51966b64ffd4802066ad4..eaafb1fab5f9dc89f7513f05f56b8ec3d342a051 100644 --- a/server/src/Action/InstanceListAction.php +++ b/server/src/Action/InstanceListAction.php @@ -142,6 +142,7 @@ final class InstanceListAction extends AbstractAction $instance->setHomeComponent($parsedBody['home_component']); $instance->setHomeComponentConfig($parsedBody['home_component_config']); $instance->setSampEnabled($parsedBody['samp_enabled']); + $instance->setBackToPortal($parsedBody['back_to_portal']); $instance->setSearchByCriteriaAllowed($parsedBody['search_by_criteria_allowed']); $instance->setSearchByCriteriaLabel($parsedBody['search_by_criteria_label']); $instance->setSearchMultipleAllowed($parsedBody['search_multiple_allowed']); diff --git a/server/src/Entity/Instance.php b/server/src/Entity/Instance.php index bfc15464b84c3ffe155a14320fb0e39442df91f9..3a8280651068deb3c1da651d26dd51c6d857fa47 100644 --- a/server/src/Entity/Instance.php +++ b/server/src/Entity/Instance.php @@ -129,6 +129,13 @@ class Instance implements \JsonSerializable */ protected $sampEnabled; + /** + * @var bool + * + * @Column(type="boolean", name="back_to_portal", nullable=false) + */ + protected $backToPortal; + /** * @var bool * @@ -337,6 +344,16 @@ class Instance implements \JsonSerializable $this->sampEnabled = $sampEnabled; } + public function getBackToPortal() + { + return $this->backToPortal; + } + + public function setBackToPortal($backToPortal) + { + $this->backToPortal = $backToPortal; + } + public function getSearchByCriteriaAllowed() { return $this->searchByCriteriaAllowed; @@ -439,6 +456,7 @@ class Instance implements \JsonSerializable 'home_component' => $this->getHomeComponent(), 'home_component_config' => $this->getHomeComponentConfig(), 'samp_enabled' => $this->getSampEnabled(), + 'back_to_portal' => $this->getBackToPortal(), 'search_by_criteria_allowed' => $this->getSearchByCriteriaAllowed(), 'search_by_criteria_label' => $this->getSearchByCriteriaLabel(), 'search_multiple_allowed' => $this->getSearchMultipleAllowed(),