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 b688f901a3ee89be5d45f597cf0988a5f3eb1ae7..6ce897b1e18e24ad04bbc586801edd279a28e06c 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 f34e5ec8a1a8b11383cd2d515f1c2e27eee01df5..27322aed7e2f7282ae7a54acfea38b78fd7467ef 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 e7679bc2e7366856f410e83c92738806c23b3902..8b2b49e23e89141f206cec94ce673e389dcdfd54 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 dc692bd80d951ea5908d6529174138ef802a78ad..66e2fc4df9788f64d7b4cb3b47671ef939025365 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 0000000000000000000000000000000000000000..28c122e3ead6c199771514aeb447141d7880c7a0 --- /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 0000000000000000000000000000000000000000..9c8448cc2f62047998c7f7103f7a59a4fb3696af --- /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 0000000000000000000000000000000000000000..d09290184c5c4c27c0ab26fba477c4e717e5e58c --- /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 0000000000000000000000000000000000000000..e6c9db3b20bcefbf455c1f2194083840f3bcb3c1 --- /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 0000000000000000000000000000000000000000..c659ad6a21123fa287233dda1ec88407211ea500 --- /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 0000000000000000000000000000000000000000..8350c2e16be056af67fef13f0b4d4defcfa30ce4 --- /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 0000000000000000000000000000000000000000..624842276504d65b1e61920e28351a47b82b3ca0 --- /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 dc5db4b5461a916654b36ca006c367508a5d9a85..96c14d04169601f70a2f47478d1df20e743bdbc0 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;