From 563c83c383ad814a3fa284f1478b58ad071544c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Agneray?= <francois.agneray@lam.fr>
Date: Thu, 9 Jun 2022 17:08:35 +0200
Subject: [PATCH] Add webpages (admin) => done

---
 .../instance-buttons.component.html           |  2 +-
 .../admin/instance/instance-routing.module.ts |  2 +-
 .../{webpages => webpage}/components/index.ts |  8 ++--
 .../components/webpage-card.component.html    | 20 ++++++++
 .../components/webpage-card.component.scss    | 12 +++++
 .../components/webpage-card.component.ts      | 13 +++++
 .../components/webpage-form.component.html}   | 10 ++--
 .../components/webpage-form.component.ts      | 37 +++++++++++++++
 .../containers/edit-webpage.component.html    | 38 +++++++++++++++
 .../containers/edit-webpage.component.ts      | 40 ++++++++++++++++
 .../containers/new-webpage.component.html     | 36 ++++++++++++++
 .../containers/new-webpage.component.ts       | 24 ++++++++++
 .../containers/webpage-list.component.html    | 37 +++++++++++++++
 .../containers/webpage-list.component.scss    | 19 ++++++++
 .../containers/webpage-list.component.ts}     | 17 ++-----
 .../webpage-routing.module.ts}                | 14 ++++--
 .../webpage.module.ts}                        |  6 +--
 .../components/webpage-content.component.ts   | 28 -----------
 .../webpage-list-menu.component.html          | 39 ---------------
 .../components/webpage-list-menu.component.ts | 47 -------------------
 .../containers/webpages-list.component.html   | 32 -------------
 .../app/metamodel/effects/webpage.effects.ts  | 14 +++++-
 .../metamodel/selectors/webpage.selector.ts   |  4 +-
 23 files changed, 317 insertions(+), 182 deletions(-)
 rename client/src/app/admin/instance/{webpages => webpage}/components/index.ts (57%)
 create mode 100644 client/src/app/admin/instance/webpage/components/webpage-card.component.html
 create mode 100644 client/src/app/admin/instance/webpage/components/webpage-card.component.scss
 create mode 100644 client/src/app/admin/instance/webpage/components/webpage-card.component.ts
 rename client/src/app/admin/instance/{webpages/components/webpage-content.component.html => webpage/components/webpage-form.component.html} (65%)
 create mode 100644 client/src/app/admin/instance/webpage/components/webpage-form.component.ts
 create mode 100644 client/src/app/admin/instance/webpage/containers/edit-webpage.component.html
 create mode 100644 client/src/app/admin/instance/webpage/containers/edit-webpage.component.ts
 create mode 100644 client/src/app/admin/instance/webpage/containers/new-webpage.component.html
 create mode 100644 client/src/app/admin/instance/webpage/containers/new-webpage.component.ts
 create mode 100644 client/src/app/admin/instance/webpage/containers/webpage-list.component.html
 create mode 100644 client/src/app/admin/instance/webpage/containers/webpage-list.component.scss
 rename client/src/app/admin/instance/{webpages/containers/webpages-list.component.ts => webpage/containers/webpage-list.component.ts} (74%)
 rename client/src/app/admin/instance/{webpages/webpages-routing.module.ts => webpage/webpage-routing.module.ts} (51%)
 rename client/src/app/admin/instance/{webpages/webpages.module.ts => webpage/webpage.module.ts} (85%)
 delete mode 100644 client/src/app/admin/instance/webpages/components/webpage-content.component.ts
 delete mode 100644 client/src/app/admin/instance/webpages/components/webpage-list-menu.component.html
 delete mode 100644 client/src/app/admin/instance/webpages/components/webpage-list-menu.component.ts
 delete mode 100644 client/src/app/admin/instance/webpages/containers/webpages-list.component.html

diff --git a/client/src/app/admin/instance/dataset/components/instance-buttons.component.html b/client/src/app/admin/instance/dataset/components/instance-buttons.component.html
index 95380400..cfa2e25e 100644
--- a/client/src/app/admin/instance/dataset/components/instance-buttons.component.html
+++ b/client/src/app/admin/instance/dataset/components/instance-buttons.component.html
@@ -5,7 +5,7 @@
         </button>
     </div>
     <div class="btn-group mr-2" role="group" aria-label="Edit webpages">
-        <button routerLink="/admin/instance/configure-instance/{{ instance.name }}/webpages" title="Edit instances webpages" class="btn btn-outline-primary">
+        <button routerLink="/admin/instance/configure-instance/{{ instance.name }}/webpage" title="Edit instances webpages" class="btn btn-outline-primary">
             <span class="fas fa-file-lines"></span> Edit instance webpages
         </button>
     </div>
diff --git a/client/src/app/admin/instance/instance-routing.module.ts b/client/src/app/admin/instance/instance-routing.module.ts
index a0ea13dd..1c39ca08 100644
--- a/client/src/app/admin/instance/instance-routing.module.ts
+++ b/client/src/app/admin/instance/instance-routing.module.ts
@@ -30,7 +30,7 @@ const routes: Routes = [
             { path: '', redirectTo: 'dataset/dataset-list', pathMatch: 'full' },
             { path: 'dataset', loadChildren: () => import('./dataset/dataset.module').then(m => m.DatasetModule) },
             { path: 'dataset-group', loadChildren: () => import('./dataset-group/dataset-group.module').then(m => m.DatasetGroupModule) },
-            { path: 'webpages', loadChildren: () => import('./webpages/webpages.module').then(m => m.WebpagesModule) },
+            { path: 'webpage', loadChildren: () => import('./webpage/webpage.module').then(m => m.WebpageModule) },
         ]
     },
 ];
diff --git a/client/src/app/admin/instance/webpages/components/index.ts b/client/src/app/admin/instance/webpage/components/index.ts
similarity index 57%
rename from client/src/app/admin/instance/webpages/components/index.ts
rename to client/src/app/admin/instance/webpage/components/index.ts
index b624023a..e80b4670 100644
--- a/client/src/app/admin/instance/webpages/components/index.ts
+++ b/client/src/app/admin/instance/webpage/components/index.ts
@@ -7,10 +7,10 @@
  * file that was distributed with this source code.
  */
 
-import { WebpageListMenuComponent } from './webpage-list-menu.component';
-import { WebpageContentComponent } from './webpage-content.component';
+import { WebpageCardComponent } from './webpage-card.component';
+import { WebpageFormComponent } from './webpage-form.component';
 
 export const dummiesComponents = [
-    WebpageListMenuComponent,
-    WebpageContentComponent
+    WebpageCardComponent,
+    WebpageFormComponent
 ];
diff --git a/client/src/app/admin/instance/webpage/components/webpage-card.component.html b/client/src/app/admin/instance/webpage/components/webpage-card.component.html
new file mode 100644
index 00000000..70fdbcd3
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/components/webpage-card.component.html
@@ -0,0 +1,20 @@
+<div class="card">
+    <div class="card-body">
+        <h5 class="card-title font-weight-bold">{{ webpage.label }}</h5>
+        <ul class="card-text list-unstyled pl-4">
+            <li>Title: <span class="badge badge-secondary">{{ webpage.title }}</span></li>
+            <li>Display: <span class="badge badge-secondary">{{ webpage.display }}</span></li>
+        </ul>
+    </div>
+    <div class="card-footer bg-transparent text-right">
+        <a title="Edit this webpage" routerLink="edit-webpage/{{webpage.id}}" class="btn btn-outline-primary">
+            <span class="fas fa-edit"></span>
+        </a>
+        &nbsp;
+        <app-delete-btn
+            [type]="'webpage'"
+            [label]="webpage.label"
+            (confirm)="deleteWebpage.emit(webpage)">
+        </app-delete-btn>
+    </div>
+</div>
diff --git a/client/src/app/admin/instance/webpage/components/webpage-card.component.scss b/client/src/app/admin/instance/webpage/components/webpage-card.component.scss
new file mode 100644
index 00000000..2325ac15
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/components/webpage-card.component.scss
@@ -0,0 +1,12 @@
+/**
+ * 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.
+ */
+
+.card {
+    height: 200px;
+}
\ No newline at end of file
diff --git a/client/src/app/admin/instance/webpage/components/webpage-card.component.ts b/client/src/app/admin/instance/webpage/components/webpage-card.component.ts
new file mode 100644
index 00000000..5f6a4fa2
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/components/webpage-card.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input, Output, EventEmitter } from '@angular/core';
+
+import { Webpage } from 'src/app/metamodel/models';
+
+@Component({
+    selector: 'app-webpage-card',
+    templateUrl: 'webpage-card.component.html',
+    styleUrls: ['webpage-card.component.scss']
+})
+export class WebpageCardComponent {
+    @Input() webpage: Webpage;
+    @Output() deleteWebpage: EventEmitter<Webpage> = new EventEmitter();
+}
diff --git a/client/src/app/admin/instance/webpages/components/webpage-content.component.html b/client/src/app/admin/instance/webpage/components/webpage-form.component.html
similarity index 65%
rename from client/src/app/admin/instance/webpages/components/webpage-content.component.html
rename to client/src/app/admin/instance/webpage/components/webpage-form.component.html
index a7dd4a56..2212bf67 100644
--- a/client/src/app/admin/instance/webpages/components/webpage-content.component.html
+++ b/client/src/app/admin/instance/webpage/components/webpage-form.component.html
@@ -1,4 +1,4 @@
-<form [formGroup]="form" (ngSubmit)="savePage()" novalidate>
+<form [formGroup]="form" (ngSubmit)="submit()" novalidate>
     <div class="form-group">
         <label for="label">Label</label>
         <input type="text" class="form-control" id="label" name="label" formControlName="label">
@@ -13,12 +13,10 @@
     </div>
     <div class="form-group">
         <label for="content">Content</label>
-        <editor formControlName="content" [init]="{ plugins: 'lists link image table code help wordcount' }">
+        <editor [init]="{ plugins: 'lists link image table code help wordcount' }" formControlName="content">
         </editor>
     </div>
-    <div class="form-group">
-        <button [disabled]="!form.valid" type="submit" class="btn btn-primary">
-            <span class="fa fa-database"></span> Save
-        </button>
+    <div class="form-group pt-4">
+        <ng-content></ng-content>
     </div>
 </form>
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
new file mode 100644
index 00000000..7bf927e1
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/components/webpage-form.component.ts
@@ -0,0 +1,37 @@
+import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
+
+import { Webpage } from 'src/app/metamodel/models';
+
+@Component({
+    selector: 'app-webpage-form',
+    templateUrl: 'webpage-form.component.html'
+})
+export class WebpageFormComponent implements OnInit {
+    @Input() webpage: Webpage;
+    @Output() onSubmit: EventEmitter<Webpage> = new EventEmitter();
+
+    public form = new FormGroup({
+        label: new FormControl('', [Validators.required]),
+        display: new FormControl('', [Validators.required]),
+        title: new FormControl('', [Validators.required]),
+        content: new FormControl('', [Validators.required])
+    });
+
+    ngOnInit() {
+        if (this.webpage) {
+            this.form.patchValue(this.webpage);
+        }
+    }
+
+    submit() {
+        if (this.webpage) {
+            this.onSubmit.emit({
+                ...this.webpage,
+                ...this.form.getRawValue()
+            });
+        } else {
+            this.onSubmit.emit(this.form.getRawValue());
+        }
+    }
+}
diff --git a/client/src/app/admin/instance/webpage/containers/edit-webpage.component.html b/client/src/app/admin/instance/webpage/containers/edit-webpage.component.html
new file mode 100644
index 00000000..ce385f22
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/edit-webpage.component.html
@@ -0,0 +1,38 @@
+<app-spinner *ngIf="webpageListIsLoading | async"></app-spinner>
+
+<div *ngIf="webpageListIsLoaded | async" class="container-fluid">
+    <nav aria-label="breadcrumb">
+        <ol class="breadcrumb">
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/instance-list">
+                    Instances
+                </a>
+            </li>
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}">
+                    Configure instance {{ instanceName | async }}
+                </a>
+            </li>
+            <li class="breadcrumb-item active">
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}/webpage">
+                    Edit instance webpages
+                </a>
+            </li>
+            <li class="breadcrumb-item active" aria-current="page">Edit webpage {{ (webpage | async).label }}</li>
+        </ol>
+    </nav>
+</div>
+
+<div *ngIf="webpageListIsLoaded | async" class="container">
+    <div class="row">
+        <div class="col-12">
+            <app-webpage-form [webpage]="webpage | async" (onSubmit)="editWebpage($event)" #formWebpage>
+                <button [disabled]="!formWebpage.form.valid || formWebpage.form.pristine" type="submit" class="btn btn-primary">
+                    <span class="fa fa-database"></span> Edit webpage
+                </button>
+                &nbsp;
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}/webpage" class="btn btn-danger">Cancel</a>
+            </app-webpage-form>
+        </div>
+    </div>
+</div>
diff --git a/client/src/app/admin/instance/webpage/containers/edit-webpage.component.ts b/client/src/app/admin/instance/webpage/containers/edit-webpage.component.ts
new file mode 100644
index 00000000..0345156d
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/edit-webpage.component.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 { Component } from '@angular/core';
+
+import { Observable } from 'rxjs';
+import { Store } from '@ngrx/store';
+
+import { Webpage } from 'src/app/metamodel/models';
+import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector';
+import * as webpageActions from 'src/app/metamodel/actions/webpage.actions';
+import * as webpageSelector from 'src/app/metamodel/selectors/webpage.selector';
+
+@Component({
+    selector: 'app-edit-webpage',
+    templateUrl: 'edit-webpage.component.html'
+})
+export class EditWebpageComponent {
+    public instanceName: Observable<string>;
+    public webpageListIsLoading: Observable<boolean>;
+    public webpageListIsLoaded: Observable<boolean>;
+    public webpage: Observable<Webpage>;
+
+    constructor(private store: Store<{ }>) {
+        this.instanceName = this.store.select(instanceSelector.selectInstanceNameByRoute);
+        this.webpageListIsLoading = store.select(webpageSelector.selectWebpageListIsLoading);
+        this.webpageListIsLoaded = store.select(webpageSelector.selectWebpageListIsLoaded);
+        this.webpage = this.store.select(webpageSelector.selectWebpageByRouteId);
+    }
+
+    editWebpage(webpage: Webpage) {
+        this.store.dispatch(webpageActions.editWebpage({ webpage }));
+    }
+}
diff --git a/client/src/app/admin/instance/webpage/containers/new-webpage.component.html b/client/src/app/admin/instance/webpage/containers/new-webpage.component.html
new file mode 100644
index 00000000..643466e2
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/new-webpage.component.html
@@ -0,0 +1,36 @@
+<div class="container-fluid">
+    <nav aria-label="breadcrumb">
+        <ol class="breadcrumb">
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/instance-list">
+                    Instances
+                </a>
+            </li>
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}">
+                    Configure instance {{ instanceName | async }}
+                </a>
+            </li>
+            <li class="breadcrumb-item active">
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}/webpage">
+                    Edit instance webpages
+                </a>
+            </li>
+            <li class="breadcrumb-item active" aria-current="page">New webpage</li>
+        </ol>
+    </nav>
+</div>
+
+<div class="container">
+    <div class="row">
+        <div class="col-12">
+            <app-webpage-form (onSubmit)="addNewWebpage($event)" #formWebpage>
+                <button [disabled]="!formWebpage.form.valid || formWebpage.form.pristine" type="submit" class="btn btn-primary">
+                    <span class="fa fa-database"></span> Add the new webpage
+                </button>
+                &nbsp;
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}/webpage" class="btn btn-danger">Cancel</a>
+            </app-webpage-form>
+        </div>
+    </div>
+</div>
diff --git a/client/src/app/admin/instance/webpage/containers/new-webpage.component.ts b/client/src/app/admin/instance/webpage/containers/new-webpage.component.ts
new file mode 100644
index 00000000..cc25e37b
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/new-webpage.component.ts
@@ -0,0 +1,24 @@
+import { Component } from '@angular/core';
+
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs';
+
+import { Webpage } from 'src/app/metamodel/models';
+import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector';
+import * as webpageActions from 'src/app/metamodel/actions/webpage.actions';
+
+@Component({
+    selector: 'app-new-webpage',
+    templateUrl: 'new-webpage.component.html'
+})
+export class NewWebpageComponent {
+    public instanceName: Observable<string>;
+
+    constructor(private store: Store<{ }>) {
+        this.instanceName = this.store.select(instanceSelector.selectInstanceNameByRoute);
+    }
+
+    addNewWebpage(webpage: Webpage) {
+        this.store.dispatch(webpageActions.addWebpage({ webpage }));
+    }
+}
diff --git a/client/src/app/admin/instance/webpage/containers/webpage-list.component.html b/client/src/app/admin/instance/webpage/containers/webpage-list.component.html
new file mode 100644
index 00000000..3542c4d7
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/webpage-list.component.html
@@ -0,0 +1,37 @@
+<div class="container-fluid">
+    <nav aria-label="breadcrumb">
+        <ol class="breadcrumb">
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/instance-list">
+                    Instances
+                </a>
+            </li>
+            <li class="breadcrumb-item">
+                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}">
+                    Configure instance {{ instanceName | async }}
+                </a>
+            </li>
+            <li class="breadcrumb-item active" aria-current="page">Edit instance webpages</li>
+        </ol>
+    </nav>
+</div>
+
+<app-spinner *ngIf="webpageListIsLoading | async"></app-spinner>
+
+<div *ngIf="webpageListIsLoaded | async" class="container">
+    <div class="row row-cols-1 row-cols-sm-2 row-cols-md-3">
+        <div class="col mb-3" *ngFor="let webpage of (webpageList | async)">
+            <app-webpage-card 
+                [webpage]="webpage"
+                (deleteWebpage)="deleteWebpage($event)">
+            </app-webpage-card>
+        </div>
+        <div class="col mb-3 h-100 d-table">
+            <div routerLink="new-webpage" class="card card-add d-table-cell align-middle pointer" title="Add a new webpage">
+                <div class="card-body text-center">
+                    <span class="fas fa-plus fa-4x text-light"></span>
+                </div>
+            </div>
+        </div>    
+    </div>
+</div>
diff --git a/client/src/app/admin/instance/webpage/containers/webpage-list.component.scss b/client/src/app/admin/instance/webpage/containers/webpage-list.component.scss
new file mode 100644
index 00000000..0ac62a85
--- /dev/null
+++ b/client/src/app/admin/instance/webpage/containers/webpage-list.component.scss
@@ -0,0 +1,19 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+.card-add {
+    height: 200px;
+    background-color: #A8C96E;
+    transition: font-size 0.3s;
+}
+
+.card-add:hover {
+    background-color: #9dc25b;
+    font-size: 20px;
+}
diff --git a/client/src/app/admin/instance/webpages/containers/webpages-list.component.ts b/client/src/app/admin/instance/webpage/containers/webpage-list.component.ts
similarity index 74%
rename from client/src/app/admin/instance/webpages/containers/webpages-list.component.ts
rename to client/src/app/admin/instance/webpage/containers/webpage-list.component.ts
index 102e62b6..1316f48a 100644
--- a/client/src/app/admin/instance/webpages/containers/webpages-list.component.ts
+++ b/client/src/app/admin/instance/webpage/containers/webpage-list.component.ts
@@ -18,32 +18,23 @@ import * as webpageActions from 'src/app/metamodel/actions/webpage.actions';
 import * as webpageSelector from 'src/app/metamodel/selectors/webpage.selector';
 
 @Component({
-    selector: 'app-webpages-list',
-    templateUrl: 'webpages-list.component.html'
+    selector: 'app-webpage-list',
+    templateUrl: 'webpage-list.component.html',
+    styleUrls: ['webpage-list.component.scss']
 })
-export class WebpagesListComponent {
+export class WebpageListComponent {
     public instanceName: Observable<string>;
     public webpageListIsLoading: Observable<boolean>;
     public webpageListIsLoaded: Observable<boolean>;
     public webpageList: Observable<Webpage[]>;
-    public webpageSelected: Observable<Webpage>;
 
     constructor(private store: Store<{ }>) {
-        this.webpageSelected = store.select(webpageSelector.selectWebpageByQueryParamId);
         this.instanceName = this.store.select(instanceSelector.selectInstanceNameByRoute);
         this.webpageListIsLoading = store.select(webpageSelector.selectWebpageListIsLoading);
         this.webpageListIsLoaded = store.select(webpageSelector.selectWebpageListIsLoaded);
         this.webpageList = store.select(webpageSelector.selectAllWebpages);
     }
 
-    addWebpage(webpage: Webpage) {
-        this.store.dispatch(webpageActions.addWebpage({ webpage }));
-    }
-
-    editWebpage(webpage: Webpage) {
-        this.store.dispatch(webpageActions.editWebpage({ webpage }));
-    }
-
     deleteWebpage(webpage: Webpage) {
         this.store.dispatch(webpageActions.deleteWebpage({ webpage }));
     }
diff --git a/client/src/app/admin/instance/webpages/webpages-routing.module.ts b/client/src/app/admin/instance/webpage/webpage-routing.module.ts
similarity index 51%
rename from client/src/app/admin/instance/webpages/webpages-routing.module.ts
rename to client/src/app/admin/instance/webpage/webpage-routing.module.ts
index 5af6138b..c162b80f 100644
--- a/client/src/app/admin/instance/webpages/webpages-routing.module.ts
+++ b/client/src/app/admin/instance/webpage/webpage-routing.module.ts
@@ -10,10 +10,14 @@
 import { NgModule } from '@angular/core';
 import { Routes, RouterModule } from '@angular/router';
 
-import { WebpagesListComponent } from './containers/webpages-list.component';
+import { WebpageListComponent } from './containers/webpage-list.component';
+import { NewWebpageComponent } from './containers/new-webpage.component';
+import { EditWebpageComponent } from './containers/edit-webpage.component';
 
 const routes: Routes = [
-    { path: '', component: WebpagesListComponent }
+    { path: '', component: WebpageListComponent },
+    { path: 'new-webpage', component: NewWebpageComponent },
+    { path: 'edit-webpage/:id', component: EditWebpageComponent }
 ];
 
 /**
@@ -24,8 +28,10 @@ const routes: Routes = [
     imports: [RouterModule.forChild(routes)],
     exports: [RouterModule]
 })
-export class DatasetRoutingModule { }
+export class WebpageRoutingModule { }
 
 export const routedComponents = [
-    WebpagesListComponent
+    WebpageListComponent,
+    NewWebpageComponent,
+    EditWebpageComponent
 ];
diff --git a/client/src/app/admin/instance/webpages/webpages.module.ts b/client/src/app/admin/instance/webpage/webpage.module.ts
similarity index 85%
rename from client/src/app/admin/instance/webpages/webpages.module.ts
rename to client/src/app/admin/instance/webpage/webpage.module.ts
index b503c4c3..fa6df84f 100644
--- a/client/src/app/admin/instance/webpages/webpages.module.ts
+++ b/client/src/app/admin/instance/webpage/webpage.module.ts
@@ -12,7 +12,7 @@ import { NgModule } from '@angular/core';
 import { EditorModule, TINYMCE_SCRIPT_SRC } from '@tinymce/tinymce-angular';
 
 import { SharedModule } from 'src/app/shared/shared.module';
-import { DatasetRoutingModule, routedComponents } from './webpages-routing.module';
+import { WebpageRoutingModule, routedComponents } from './webpage-routing.module';
 import { dummiesComponents } from './components';
 import { AdminSharedModule } from '../../admin-shared/admin-shared.module';
 
@@ -23,7 +23,7 @@ import { AdminSharedModule } from '../../admin-shared/admin-shared.module';
 @NgModule({
     imports: [
         SharedModule,
-        DatasetRoutingModule,
+        WebpageRoutingModule,
         AdminSharedModule,
         EditorModule
     ],
@@ -35,4 +35,4 @@ import { AdminSharedModule } from '../../admin-shared/admin-shared.module';
         { provide: TINYMCE_SCRIPT_SRC, useValue: 'tinymce/tinymce.min.js' }
     ]
 })
-export class WebpagesModule { }
+export class WebpageModule { }
diff --git a/client/src/app/admin/instance/webpages/components/webpage-content.component.ts b/client/src/app/admin/instance/webpages/components/webpage-content.component.ts
deleted file mode 100644
index 34630166..00000000
--- a/client/src/app/admin/instance/webpages/components/webpage-content.component.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Component, Input } from '@angular/core';
-import { FormGroup, FormControl, Validators } from '@angular/forms';
-
-import { Webpage } from 'src/app/metamodel/models';
-
-@Component({
-    selector: 'app-webpage-content',
-    templateUrl: 'webpage-content.component.html'
-})
-export class WebpageContentComponent {
-    @Input() webPage: Webpage;
-
-    public form = new FormGroup({
-        label: new FormControl('', [Validators.required]),
-        display: new FormControl('', [Validators.required]),
-        title: new FormControl('', [Validators.required]),
-        content: new FormControl('', Validators.required)
-    });
-
-    ngOnInit() {
-        this.form.patchValue(this.webPage);
-        this.form.controls.content.markAsPristine();
-    }
-
-    savePage() {
-        console.log(this.form.value);
-    }
-}
\ No newline at end of file
diff --git a/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.html b/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.html
deleted file mode 100644
index e9a72201..00000000
--- a/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<nav>
-    <div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
-        <a *ngFor="let webpage of webpageList" routerLink="./" [queryParams]="{webpage_selected: webpage.id}" class="nav-link" [ngClass]="{'active': isActive(webpage)}" data-toggle="pill" role="tab">
-            {{ webpage.label }}
-        </a>
-        <a (click)="openModal(template)" class="nav-link text-center pointer" title="Add a new webpage" data-toggle="pill" role="tab">
-            <span class="fas fa-plus"></span>
-        </a>
-    </div>
-</nav>
-
-<ng-template #template>
-    <div class="modal-header">
-        <h4 class="modal-title pull-left"><strong>Add a new webpage</strong></h4>
-    </div>
-    <div class="modal-body">
-        <form [formGroup]="form" (ngSubmit)="submit()" novalidate>
-            <div class="form-group">
-                <label for="label">Label</label>
-                <input type="text" class="form-control" id="label" name="label" formControlName="label">
-            </div>
-            <div class="form-group">
-                <label for="display">Display</label>
-                <input type="number" class="form-control" id="display" name="display" formControlName="display">
-            </div>
-            <div class="form-group">
-                <label for="title">Title</label>
-                <input type="text" class="form-control" id="title" name="title" formControlName="title">
-            </div>
-            <div class="form-group">
-                <button [disabled]="!form.valid || form.pristine" type="submit" class="btn btn-primary">
-                    <span class="fa fa-database"></span> Add the webpage
-                </button>
-                &nbsp;
-                <a (click)="modalRef.hide()" type="button" class="btn btn-danger">Cancel</a>
-            </div>
-        </form>
-    </div>
-</ng-template>
diff --git a/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.ts b/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.ts
deleted file mode 100644
index 94abf57a..00000000
--- a/client/src/app/admin/instance/webpages/components/webpage-list-menu.component.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { Component, ChangeDetectionStrategy, Input, Output, EventEmitter, TemplateRef } from '@angular/core';
-import { FormGroup, FormControl, Validators } from '@angular/forms';
-
-import { BsModalService } from 'ngx-bootstrap/modal';
-import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';
-
-import { Webpage } from 'src/app/metamodel/models';
-
-@Component({
-    selector: 'app-webpage-list-menu',
-    templateUrl: 'webpage-list-menu.component.html',
-    changeDetection: ChangeDetectionStrategy.OnPush
-})
-export class WebpageListMenuComponent {
-    @Input() webpageList: Webpage[];
-    @Input() webpageSelected: Webpage;
-    @Output() addWebpage: EventEmitter<Webpage> = new EventEmitter();
-
-    modalRef: BsModalRef;
-    public form = new FormGroup({
-        label: new FormControl('', [Validators.required]),
-        display: new FormControl('', [Validators.required]),
-        title: new FormControl('', [Validators.required]),
-        content: new FormControl('Add your text here...', [Validators.required])
-    });
-
-    constructor(private modalService: BsModalService) { }
-
-    isActive(webpage: Webpage) {
-        let active = false;
-        if (this.webpageSelected && webpage.id === this.webpageSelected.id) {
-            active = true;
-        }
-        return active;
-    }
-
-    openModal(template: TemplateRef<any>) {
-        this.modalRef = this.modalService.show(template);
-    }
-
-    submit() {
-        this.addWebpage.emit(this.form.value);
-        this.form.reset();
-        this.form.controls.content.setValue('Add your text here...');
-        this.modalRef.hide();
-    }
-}
diff --git a/client/src/app/admin/instance/webpages/containers/webpages-list.component.html b/client/src/app/admin/instance/webpages/containers/webpages-list.component.html
deleted file mode 100644
index 174c553c..00000000
--- a/client/src/app/admin/instance/webpages/containers/webpages-list.component.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<div class="container-fluid">
-    <nav aria-label="breadcrumb">
-        <ol class="breadcrumb">
-            <li class="breadcrumb-item">
-                <a routerLink="/admin/instance/instance-list">
-                    Instances
-                </a>
-            </li>
-            <li class="breadcrumb-item">
-                <a routerLink="/admin/instance/configure-instance/{{ instanceName | async }}">
-                    Configure instance {{ instanceName | async }}
-                </a>
-            </li>
-            <li class="breadcrumb-item active" aria-current="page">Edit instance webpages</li>
-        </ol>
-    </nav>
-
-    <app-spinner *ngIf="webpageListIsLoading | async"></app-spinner>
-
-    <div *ngIf="webpageListIsLoaded | async" class="row">
-        <div class="col-md-2 col-sm-12 mb-2">
-            <app-webpage-list-menu 
-                [webpageList]="webpageList | async"
-                [webpageSelected]="webpageSelected | async"
-                (addWebpage)="addWebpage($event)">
-            </app-webpage-list-menu>
-        </div>
-        <div *ngIf="webpageSelected | async" class="col-md-10 col-sm-12">
-            <app-webpage-content [webPage]="webpageSelected | async"></app-webpage-content>
-        </div>
-    </div>
-</div>
diff --git a/client/src/app/metamodel/effects/webpage.effects.ts b/client/src/app/metamodel/effects/webpage.effects.ts
index 8294a507..83a0e823 100644
--- a/client/src/app/metamodel/effects/webpage.effects.ts
+++ b/client/src/app/metamodel/effects/webpage.effects.ts
@@ -8,6 +8,7 @@
  */
 
 import { Injectable } from '@angular/core';
+import { Router } from '@angular/router';
 
 import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects';
 import { Store } from '@ngrx/store';
@@ -63,7 +64,11 @@ export class WebpageEffects {
     addWebpageSuccess$ = createEffect(() =>
         this.actions$.pipe(
             ofType(webpageActions.addWebpageSuccess),
-            tap(() => this.toastr.success('Webpage successfully added', 'The new webpage was added into the database'))
+            concatLatestFrom(() => this.store.select(instanceSelector.selectInstanceNameByRoute)),
+            tap(([, instanceName]) => {
+                this.router.navigateByUrl(`/admin/instance/configure-instance/${instanceName}/webpage`);
+                this.toastr.success('Webpage successfully added', 'The new webpage was added into the database');
+            })
         ), { dispatch: false }
     );
 
@@ -98,7 +103,11 @@ export class WebpageEffects {
     editWebpageSuccess$ = createEffect(() =>
         this.actions$.pipe(
             ofType(webpageActions.editWebpageSuccess),
-            tap(() => this.toastr.success('Webpage successfully edited', 'The existing webpage has been edited into the database'))
+            concatLatestFrom(() => this.store.select(instanceSelector.selectInstanceNameByRoute)),
+            tap(([, instanceName]) => {
+                this.router.navigateByUrl(`/admin/instance/configure-instance/${instanceName}/webpage`);
+                this.toastr.success('Webpage successfully edited', 'The existing webpage has been edited into the database')
+            })
         ), { dispatch: false }
     );
 
@@ -150,6 +159,7 @@ export class WebpageEffects {
     constructor(
         private actions$: Actions,
         private webpageService: WebpageService,
+        private router: Router,
         private toastr: ToastrService,
         private store: Store<{ }>
     ) {}
diff --git a/client/src/app/metamodel/selectors/webpage.selector.ts b/client/src/app/metamodel/selectors/webpage.selector.ts
index 1ca79a3d..c81396fe 100644
--- a/client/src/app/metamodel/selectors/webpage.selector.ts
+++ b/client/src/app/metamodel/selectors/webpage.selector.ts
@@ -47,8 +47,8 @@ export const selectWebpageListIsLoaded = createSelector(
     fromWebpage.selectWebpageListIsLoaded
 );
 
-export const selectWebpageByQueryParamId = createSelector(
+export const selectWebpageByRouteId = createSelector(
     selectWebpageEntities,
     reducer.selectRouterState,
-    (entities, router) => entities[router.state.queryParams.webpage_selected]
+    (entities, router) => entities[router.state.params.id]
 );
-- 
GitLab