From bfebbb582dc7983a28aaa1dfc95d9f16a607be58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Fri, 1 Apr 2022 15:47:08 +0200
Subject: [PATCH] Add back to portal and background color options

---
 client/src/app/admin/admin.component.ts       |  4 +++
 .../components/instance-form.component.html   |  4 +++
 .../components/instance-form.component.ts     |  1 +
 .../edit-instance-group.component.html        |  2 +-
 .../edit-instance-group.component.ts          |  8 ++----
 .../instance-group-list.component.ts          |  6 +----
 client/src/app/instance/instance.component.ts |  2 ++
 .../app/metamodel/models/instance.model.ts    |  1 +
 .../containers/portal-home.component.ts       |  2 ++
 .../shared/components/navbar.component.html   |  2 +-
 conf-dev/create-db.sh                         |  2 +-
 .../__CG__AppEntityInstance.php               | 26 +++++++++++++++++--
 server/src/Action/InstanceAction.php          |  1 +
 server/src/Action/InstanceListAction.php      |  1 +
 server/src/Entity/Instance.php                | 18 +++++++++++++
 15 files changed, 64 insertions(+), 16 deletions(-)

diff --git a/client/src/app/admin/admin.component.ts b/client/src/app/admin/admin.component.ts
index 57ebd0e4..b31b8d79 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 41712766..06f689f9 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 cd351cb4..7ee22005 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 99eb49d8..d00e72bf 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>
                 &nbsp;
-                <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 47dd9caf..72be239d 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 a3f054a8..c874f8cd 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 fe75d5f4..6db00730 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 7962ff59..0ac2e840 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 6ec0b9d5..5bc6fe2a 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 17f37000..498db98d 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 28a54e99..92e8206d 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 7b3ee869..ed87c913 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 a9044e59..f116e2be 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 40825374..eaafb1fa 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 bfc15464..3a828065 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(),
-- 
GitLab