From 87da3049addb876c3a71bd559aedd164c7aaf518 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Wed, 15 Jun 2022 21:33:08 +0200
Subject: [PATCH] Webpage feature => WIP

---
 .../components/webpage-form.component.html    |  2 +-
 .../components/webpage-form.component.ts      |  7 ++++
 .../app/instance/instance-routing.module.ts   |  1 +
 client/src/app/instance/instance.component.ts |  4 +++
 .../app/instance/webpage/components/index.ts  |  5 +++
 .../components/webpage-content.component.html |  1 +
 .../components/webpage-content.component.ts   | 31 ++++++++++++++++
 .../webpage/containers/webpage.component.html |  6 ++++
 .../webpage/containers/webpage.component.ts   | 36 +++++++++++++++++++
 .../webpage/webpage-routing.module.ts         | 31 ++++++++++++++++
 .../app/instance/webpage/webpage.module.ts    | 30 ++++++++++++++++
 server/src/Entity/Webpage.php                 |  2 +-
 12 files changed, 154 insertions(+), 2 deletions(-)
 create mode 100644 client/src/app/instance/webpage/components/index.ts
 create mode 100644 client/src/app/instance/webpage/components/webpage-content.component.html
 create mode 100644 client/src/app/instance/webpage/components/webpage-content.component.ts
 create mode 100644 client/src/app/instance/webpage/containers/webpage.component.html
 create mode 100644 client/src/app/instance/webpage/containers/webpage.component.ts
 create mode 100644 client/src/app/instance/webpage/webpage-routing.module.ts
 create mode 100644 client/src/app/instance/webpage/webpage.module.ts

diff --git a/client/src/app/admin/instance/webpage/components/webpage-form.component.html b/client/src/app/admin/instance/webpage/components/webpage-form.component.html
index b688f901..6ce897b1 100644
--- a/client/src/app/admin/instance/webpage/components/webpage-form.component.html
+++ b/client/src/app/admin/instance/webpage/components/webpage-form.component.html
@@ -20,7 +20,7 @@
     </div>
     <div class="form-group">
         <label for="content">Content</label>
-        <editor [init]="{ plugins: 'lists link image table code help wordcount' }" formControlName="content">
+        <editor [init]="getEditorConfig()" formControlName="content">
         </editor>
     </div>
     <div class="form-group pt-4">
diff --git a/client/src/app/admin/instance/webpage/components/webpage-form.component.ts b/client/src/app/admin/instance/webpage/components/webpage-form.component.ts
index f34e5ec8..27322aed 100644
--- a/client/src/app/admin/instance/webpage/components/webpage-form.component.ts
+++ b/client/src/app/admin/instance/webpage/components/webpage-form.component.ts
@@ -40,4 +40,11 @@ export class WebpageFormComponent implements OnInit {
             this.onSubmit.emit(this.form.getRawValue());
         }
     }
+
+    getEditorConfig() {
+        return {
+            plugins: "lists link image table code help wordcount media",
+            content_css: "https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
+        };
+    }
 }
diff --git a/client/src/app/instance/instance-routing.module.ts b/client/src/app/instance/instance-routing.module.ts
index e7679bc2..8b2b49e2 100644
--- a/client/src/app/instance/instance-routing.module.ts
+++ b/client/src/app/instance/instance-routing.module.ts
@@ -18,6 +18,7 @@ const routes: Routes = [
         path: ':iname', component: InstanceComponent, canActivate: [InstanceAuthGuard], children: [
             { path: '', redirectTo: 'home', pathMatch: 'full' },
             { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
+            { path: 'webpage', loadChildren: () => import('./webpage/webpage.module').then(m => m.WebpageModule) },
             { path: 'search', loadChildren: () => import('./search/search.module').then(m => m.SearchModule) },
             { path: 'search-multiple', loadChildren: () => import('./search-multiple/search-multiple.module').then(m => m.SearchMultipleModule) },
             { path: 'documentation', loadChildren: () => import('./documentation/documentation.module').then(m => m.DocumentationModule) }
diff --git a/client/src/app/instance/instance.component.ts b/client/src/app/instance/instance.component.ts
index dc692bd8..66e2fc4d 100644
--- a/client/src/app/instance/instance.component.ts
+++ b/client/src/app/instance/instance.component.ts
@@ -22,6 +22,8 @@ import * as datasetActions from 'src/app/metamodel/actions/dataset.actions';
 import * as datasetFamilyActions from 'src/app/metamodel/actions/dataset-family.actions';
 import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector';
 import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions';
+import * as webpageFamilyActions from 'src/app/metamodel/actions/webpage-family.actions';
+import * as webpageActions from 'src/app/metamodel/actions/webpage.actions';
 import { AppConfigService } from 'src/app/app-config.service';
 
 /**
@@ -63,6 +65,8 @@ export class InstanceComponent implements OnInit, OnDestroy {
         Promise.resolve(null).then(() => this.store.dispatch(datasetFamilyActions.loadDatasetFamilyList()));
         Promise.resolve(null).then(() => this.store.dispatch(datasetActions.loadDatasetList()));
         Promise.resolve(null).then(() => this.store.dispatch(datasetGroupActions.loadDatasetGroupList()));
+        Promise.resolve(null).then(() => this.store.dispatch(webpageFamilyActions.loadWebpageFamilyList()));
+        Promise.resolve(null).then(() => this.store.dispatch(webpageActions.loadWebpageList()));
         this.instanceSubscription = this.instance.subscribe(instance => {
             if (instance) {
                 if (instance.search_by_criteria_allowed) {
diff --git a/client/src/app/instance/webpage/components/index.ts b/client/src/app/instance/webpage/components/index.ts
new file mode 100644
index 00000000..28c122e3
--- /dev/null
+++ b/client/src/app/instance/webpage/components/index.ts
@@ -0,0 +1,5 @@
+import { WebpageComponent } from './webpage-content.component';
+
+export const dummiesComponents = [
+    WebpageComponent
+];
diff --git a/client/src/app/instance/webpage/components/webpage-content.component.html b/client/src/app/instance/webpage/components/webpage-content.component.html
new file mode 100644
index 00000000..9c8448cc
--- /dev/null
+++ b/client/src/app/instance/webpage/components/webpage-content.component.html
@@ -0,0 +1 @@
+<div [innerHtml]="safeHTML(webpage.content)"></div>
\ No newline at end of file
diff --git a/client/src/app/instance/webpage/components/webpage-content.component.ts b/client/src/app/instance/webpage/components/webpage-content.component.ts
new file mode 100644
index 00000000..d0929018
--- /dev/null
+++ b/client/src/app/instance/webpage/components/webpage-content.component.ts
@@ -0,0 +1,31 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component, Input } from '@angular/core';
+import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
+
+import { Webpage } from 'src/app/metamodel/models';
+
+/**
+ * @class
+ * @classdesc Webpage content component.
+ */
+@Component({
+    selector: 'app-webpage-content',
+    templateUrl: 'webpage-content.component.html'
+})
+export class WebpageComponent {
+    @Input() webpage: Webpage;
+
+    constructor(private sanitizer: DomSanitizer) { }
+
+    safeHTML(content: string): SafeHtml {
+        return this.sanitizer.bypassSecurityTrustHtml(content);
+    }
+}
diff --git a/client/src/app/instance/webpage/containers/webpage.component.html b/client/src/app/instance/webpage/containers/webpage.component.html
new file mode 100644
index 00000000..e6c9db3b
--- /dev/null
+++ b/client/src/app/instance/webpage/containers/webpage.component.html
@@ -0,0 +1,6 @@
+<div class="container">
+    <app-spinner *ngIf="webpageListIsLoading | async"></app-spinner>
+
+    <app-webpage-content *ngIf="webpageListIsLoaded | async" [webpage]="webpage | async">
+    </app-webpage-content>
+</div>
diff --git a/client/src/app/instance/webpage/containers/webpage.component.ts b/client/src/app/instance/webpage/containers/webpage.component.ts
new file mode 100644
index 00000000..c659ad6a
--- /dev/null
+++ b/client/src/app/instance/webpage/containers/webpage.component.ts
@@ -0,0 +1,36 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component } from '@angular/core';
+
+import { Observable } from 'rxjs';
+import { Store } from '@ngrx/store';
+
+import { Webpage } from 'src/app/metamodel/models';
+import * as webpageSelector from 'src/app/metamodel/selectors/webpage.selector';
+
+/**
+ * @class
+ * @classdesc Webpage component.
+ */
+@Component({
+    selector: 'app-webpage',
+    templateUrl: 'webpage.component.html'
+})
+export class WebpageComponent {
+    public webpageListIsLoading: Observable<boolean>;
+    public webpageListIsLoaded: Observable<boolean>;
+    public webpage: Observable<Webpage>;
+
+    constructor(private store: Store<{ }>) {
+        this.webpageListIsLoading = store.select(webpageSelector.selectWebpageListIsLoading);
+        this.webpageListIsLoaded = store.select(webpageSelector.selectWebpageListIsLoaded);
+        this.webpage = this.store.select(webpageSelector.selectWebpageByRouteId);
+    }
+}
diff --git a/client/src/app/instance/webpage/webpage-routing.module.ts b/client/src/app/instance/webpage/webpage-routing.module.ts
new file mode 100644
index 00000000..8350c2e1
--- /dev/null
+++ b/client/src/app/instance/webpage/webpage-routing.module.ts
@@ -0,0 +1,31 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { WebpageComponent } from './containers/webpage.component';
+
+const routes: Routes = [
+    { path: ':id', component: WebpageComponent }
+];
+
+/**
+ * @class
+ * @classdesc Webpage routing module.
+ */
+@NgModule({
+    imports: [RouterModule.forChild(routes)],
+    exports: [RouterModule]
+})
+export class WebpageRoutingModule { }
+
+export const routedComponents = [
+    WebpageComponent
+];
diff --git a/client/src/app/instance/webpage/webpage.module.ts b/client/src/app/instance/webpage/webpage.module.ts
new file mode 100644
index 00000000..62484227
--- /dev/null
+++ b/client/src/app/instance/webpage/webpage.module.ts
@@ -0,0 +1,30 @@
+/**
+ * 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 { WebpageRoutingModule, routedComponents } from './webpage-routing.module';
+import { dummiesComponents } from './components';
+
+/**
+ * @class
+ * @classdesc Webpage module.
+ */
+@NgModule({
+    imports: [
+        SharedModule,
+        WebpageRoutingModule
+    ],
+    declarations: [
+        routedComponents,
+        dummiesComponents
+    ]
+})
+export class WebpageModule { }
diff --git a/server/src/Entity/Webpage.php b/server/src/Entity/Webpage.php
index dc5db4b5..96c14d04 100644
--- a/server/src/Entity/Webpage.php
+++ b/server/src/Entity/Webpage.php
@@ -54,7 +54,7 @@ class Webpage implements \JsonSerializable
     /**
      * @var string
      *
-     * @Column(type="string", name="content", nullable=false)
+     * @Column(type="text", name="content", nullable=false)
      */
     protected $content;
 
-- 
GitLab