add supportive material editor to UI

This commit is contained in:
amentis 2023-11-03 13:30:11 +02:00
parent b6278ab1ef
commit c37530c022
32 changed files with 266 additions and 102 deletions

View File

@ -1,10 +1,31 @@
package eu.eudat.commons.enums; package eu.eudat.commons.enums;
public enum SupportiveMaterialFieldType { import eu.eudat.data.converters.enums.DatabaseEnum;
faq, import java.util.Map;
about,
glossary, public enum SupportiveMaterialFieldType implements DatabaseEnum<Short> {
termsofservice,
userguide Faq((short) 0),
About((short) 1),
Glossary((short) 2),
TermsOfService((short) 3),
UserGuide((short) 4);
private final Short value;
SupportiveMaterialFieldType(Short value) {
this.value = value;
}
@Override
public Short getValue() {
return value;
}
private static final Map<Short, SupportiveMaterialFieldType> map = EnumUtils.getEnumValueMap(SupportiveMaterialFieldType.class);
public static SupportiveMaterialFieldType of(Short i) {
return map.get(i);
}
} }

View File

@ -1,13 +1,19 @@
package eu.eudat.model.persist; package eu.eudat.model.persist;
import eu.eudat.commons.enums.SupportiveMaterialFieldType;
import eu.eudat.commons.validation.ValidEnum;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
public class UserGuidePersist { public class SupportiveMaterialPersist {
@NotNull(message = "{validation.empty}") @NotNull(message = "{validation.empty}")
@NotEmpty(message = "{validation.empty}") @NotEmpty(message = "{validation.empty}")
private String name; private String name;
@ValidEnum(message = "{validation.empty}")
private SupportiveMaterialFieldType type;
@NotNull(message = "{validation.empty}") @NotNull(message = "{validation.empty}")
@NotEmpty(message = "{validation.empty}") @NotEmpty(message = "{validation.empty}")
private String html; private String html;
@ -20,6 +26,14 @@ public class UserGuidePersist {
this.name = name; this.name = name;
} }
public SupportiveMaterialFieldType getType() {
return type;
}
public void setType(SupportiveMaterialFieldType type) {
this.type = type;
}
public String getHtml() { public String getHtml() {
return html; return html;
} }

View File

@ -1,6 +1,6 @@
package eu.eudat.service.supportivematerial; package eu.eudat.service.supportivematerial;
import eu.eudat.model.persist.UserGuidePersist; import eu.eudat.model.persist.SupportiveMaterialPersist;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -10,7 +10,6 @@ import org.springframework.stereotype.Service;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -62,10 +61,10 @@ public class SupportiveMaterialService {
return new ResponseEntity<>(supportiveMaterialCacheItem.getContent(), responseHeaders, HttpStatus.OK); return new ResponseEntity<>(supportiveMaterialCacheItem.getContent(), responseHeaders, HttpStatus.OK);
} }
public void persist(UserGuidePersist userGuidePersist, String fileName) throws IOException { public void persist(SupportiveMaterialPersist model) throws IOException {
this.supportiveMaterialCacheService.evict(fileName); this.supportiveMaterialCacheService.evict(model.getName());
OutputStream os = new FileOutputStream(fileName); OutputStream os = new FileOutputStream(model.getName());
os.write(userGuidePersist.getHtml().getBytes()); os.write(model.getHtml().getBytes());
os.close(); os.close();
} }
} }

View File

@ -3,7 +3,7 @@ package eu.eudat.controllers.v2;
import eu.eudat.authorization.Permission; import eu.eudat.authorization.Permission;
import eu.eudat.commons.enums.SupportiveMaterialFieldType; import eu.eudat.commons.enums.SupportiveMaterialFieldType;
import eu.eudat.logic.managers.MetricsManager; import eu.eudat.logic.managers.MetricsManager;
import eu.eudat.model.persist.UserGuidePersist; import eu.eudat.model.persist.SupportiveMaterialPersist;
import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.helpers.responses.ResponseItem;
import eu.eudat.service.supportivematerial.SupportiveMaterialService; import eu.eudat.service.supportivematerial.SupportiveMaterialService;
import eu.eudat.types.ApiMessageCode; import eu.eudat.types.ApiMessageCode;
@ -19,6 +19,7 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -38,24 +39,23 @@ public class SupportiveMaterialController {
} }
@GetMapping("{lang}") @GetMapping("{lang}")
public ResponseEntity<byte[]> getMaterial(@PathVariable(name = "lang") String lang, String field) throws IOException { public ResponseEntity<byte[]> getMaterial(@PathVariable(name = "lang") String lang, int field) throws IOException {
if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, field)){ if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, SupportiveMaterialFieldType.of((short) field).name())){
return new ResponseEntity<>(HttpStatus.NOT_FOUND); return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} }
try (Stream<Path> paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty(field +".path"))))) {
try (Stream<Path> paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty(SupportiveMaterialFieldType.of((short) field).name().toLowerCase() +".path"))))) {
return this.supportiveMaterialService.getResponseEntity(lang, paths); return this.supportiveMaterialService.getResponseEntity(lang, paths);
} }
} }
@PostMapping("current") @PostMapping("persist")
public @ResponseBody public @ResponseBody
ResponseEntity<ResponseItem<String>> persist(@RequestBody UserGuidePersist guide, String field) throws IOException { ResponseEntity<ResponseItem<String>> persist(@RequestBody SupportiveMaterialPersist model) throws IOException {
this.authorizationService.authorizeForce(Permission.AdminRole); this.authorizationService.authorizeForce(Permission.AdminRole);
if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, field)){
return new ResponseEntity<>(HttpStatus.NOT_FOUND); //String fileName = this.environment.getProperty(model.getName()+ ".path");
} this.supportiveMaterialService.persist(model);
String fileName = this.environment.getProperty(field+ ".path") + guide.getName();
this.supportiveMaterialService.persist(guide, fileName);
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated"));
} }

View File

@ -0,0 +1,17 @@
<p>&nbsp;</p>
<p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
</p>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>&Sigma;&chi;&epsilon;&tau;&iota;&kappa;ά &mu;&epsilon; &tau;&omicron; Argos</h1>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p>&Tau;&omicron; ARGOS &epsilon;ί&nu;&alpha;&iota; έ&nu;&alpha; &delta;&iota;&alpha;&delta;&iota;&kappa;&tau;&upsilon;&alpha;&kappa;ό &epsilon;&rho;&gamma;&alpha;&lambda;&epsilon;ί&omicron; &gamma;&iota;&alpha; &tau;&eta;&nu; &upsilon;&pi;&omicron;&sigma;&tau;ή&rho;&iota;&xi;&eta; &alpha;&upsilon;&tau;&omicron;&mu;&alpha;&tau;&omicron;&pi;&omicron;&iota;&eta;&mu;έ&nu;&omega;&nu; &delta;&iota;&alpha;&delta;&iota;&kappa;&alpha;&sigma;&iota;ώ&nu; &gamma;&iota;&alpha; &tau;&eta; &delta;&eta;&mu;&iota;&omicron;&upsilon;&rho;&gamma;ί&alpha;, &tau;&eta; &delta;&iota;&alpha;&chi;&epsilon;ί&rho;&iota;&sigma;&eta;, &tau;&eta;&nu; &kappa;&omicron;&iota;&nu;ή &chi;&rho;ή&sigma;&eta; &kappa;&alpha;&iota; &tau;&eta; &sigma;ύ&nu;&delta;&epsilon;&sigma;&eta; &tau;&omega;&nu; DMP &mu;&epsilon; &epsilon;&rho;&epsilon;&upsilon;&nu;&eta;&tau;&iota;&kappa;ά &alpha;&nu;&tau;&iota;&kappa;&epsilon;ί&mu;&epsilon;&nu;&alpha; &sigma;&tau;&alpha; &omicron;&pi;&omicron;ί&alpha; &alpha;&nu;&tau;&iota;&sigma;&tau;&omicron;&iota;&chi;&omicron;ύ&nu;. &Alpha;&pi;&omicron;&tau;&epsilon;&lambda;&epsilon;ί &kappa;&omicron;&iota;&nu;ή &pi;&rho;&omicron;&sigma;&pi;ά&theta;&epsilon;&iota;&alpha; &tau;&omicron;&upsilon; OpenAIRE &kappa;&alpha;&iota; &tau;&eta;&sigmaf; EUDAT &nu;&alpha; &pi;&alpha;&rho;&alpha;&delta;ώ&sigma;&omicron;&upsilon;&nu; &mu;&iota;&alpha; &alpha;&nu;&omicron;&iota;&chi;&tau;ή &pi;&lambda;&alpha;&tau;&phi;ό&rho;&mu;&alpha; &gamma;&iota;&alpha; &tau;&omicron;&nu; &Sigma;&chi;&epsilon;&delta;&iota;&alpha;&sigma;&mu;ό &Delta;&iota;&alpha;&chi;&epsilon;ί&rho;&iota;&sigma;&eta;&sigmaf; &Delta;&epsilon;&delta;&omicron;&mu;έ&nu;&omega;&nu; &pi;&omicron;&upsilon; &nu;&alpha; &alpha;&nu;&tau;&iota;&mu;&epsilon;&tau;&omega;&pi;ί&zeta;&epsilon;&iota; &tau;&iota;&sigmaf; &beta;έ&lambda;&tau;&iota;&sigma;&tau;&epsilon;&sigmaf; &pi;&rho;&alpha;&kappa;&tau;&iota;&kappa;έ&sigmaf; FAIR &kappa;&alpha;&iota; Open &kappa;&alpha;&iota; &nu;&alpha; &mu;&eta;&nu; &pi;&rho;&omicron;ϋ&pi;&omicron;&theta;έ&tau;&epsilon;&iota; &epsilon;&mu;&pi;ό&delta;&iota;&alpha; &gamma;&iota;&alpha; &tau;&eta; &chi;&rho;ή&sigma;&eta; &kappa;&alpha;&iota; &tau;&eta;&nu; &upsilon;&iota;&omicron;&theta;έ&tau;&eta;&sigma;ή &tau;&eta;&sigmaf;. &Tau;&omicron; &kappa;ά&nu;&epsilon;&iota; &epsilon;&phi;&alpha;&rho;&mu;ό&zeta;&omicron;&nu;&tau;&alpha;&sigmaf; &kappa;&omicron;&iota;&nu;ά &pi;&rho;ό&tau;&upsilon;&pi;&alpha; &gamma;&iota;&alpha; &mu;&eta;&chi;&alpha;&nu;&iota;&kappa;ά &epsilon;&nu;&epsilon;&rho;&gamma;ά DMPs, ό&pi;&omega;&sigmaf; &omicron;&rho;ί&zeta;&omicron;&nu;&tau;&alpha;&iota; &alpha;&pi;ό &tau;&eta;&nu; &pi;&alpha;&gamma;&kappa;ό&sigma;&mu;&iota;&alpha; &kappa;&omicron;&iota;&nu;ό&tau;&eta;&tau;&alpha; &epsilon;&rho;&epsilon;&upsilon;&nu;&eta;&tau;&iota;&kappa;ώ&nu; &delta;&epsilon;&delta;&omicron;&mu;έ&nu;&omega;&nu; &tau;&eta;&sigmaf; RDA &kappa;&alpha;&iota; &epsilon;&pi;&iota;&kappa;&omicron;&iota;&nu;&omega;&nu;ώ&nu;&tau;&alpha;&sigmaf; &kappa;&alpha;&iota; &delta;&iota;&alpha;&beta;&omicron;&upsilon;&lambda;&epsilon;ύ&omicron;&nu;&tau;&alpha;&sigmaf; &tau;&omicron;&upsilon;&sigmaf; &epsilon;&rho;&epsilon;&upsilon;&nu;&eta;&tau;έ&sigmaf;, &tau;&iota;&sigmaf; &epsilon;&rho;&epsilon;&upsilon;&nu;&eta;&tau;&iota;&kappa;έ&sigmaf; &kappa;&omicron;&iota;&nu;ό&tau;&eta;&tau;&epsilon;&sigmaf; &kappa;&alpha;&iota; &tau;&omicron;&upsilon;&sigmaf; &chi;&rho;&eta;&mu;&alpha;&tau;&omicron;&delta;ό&tau;&epsilon;&sigmaf; &gamma;&iota;&alpha; &nu;&alpha; &pi;&rho;&omicron;&beta;&lambda;&eta;&mu;&alpha;&tau;&iota;&sigma;&tau;&omicron;ύ&nu; &kappa;&alpha;&lambda;ύ&tau;&epsilon;&rho;&alpha; &gamma;&iota;&alpha; &tau;&iota;&sigmaf; &alpha;&nu;ά&gamma;&kappa;&epsilon;&sigmaf; &tau;&omicron;&upsilon;&sigmaf;.<br><br>&Tau;&omicron; ARGOS &pi;&alpha;&rho;έ&chi;&epsilon;&iota; έ&nu;&alpha; &epsilon;&upsilon;έ&lambda;&iota;&kappa;&tau;&omicron; &pi;&epsilon;&rho;&iota;&beta;ά&lambda;&lambda;&omicron;&nu; &kappa;&alpha;&iota; &mu;&iota;&alpha; &epsilon;ύ&kappa;&omicron;&lambda;&eta; &delta;&iota;&epsilon;&pi;&alpha;&phi;ή &gamma;&iota;&alpha; &tau;&eta;&nu; &pi;&lambda;&omicron;ή&gamma;&eta;&sigma;&eta; &kappa;&alpha;&iota; &chi;&rho;ή&sigma;&eta; &tau;&omega;&nu; &chi;&rho;&eta;&sigma;&tau;ώ&nu;.</p>
</div>
</div>
</div>

View File

@ -240,11 +240,11 @@ const appRoutes: Routes = [
}, },
}, },
{ {
path: 'user-guide-editor', path: 'supportive-material',
loadChildren: () => import('./ui/user-guide-editor/user-guide-editor.module').then(m => m.UserGuideEditorModule), loadChildren: () => import('./ui/supportive-material-editor/supportive-material-editor.module').then(m => m.SupportiveMaterialEditorModule),
data: { data: {
breadcrumb: true, breadcrumb: true,
title: 'GENERAL.TITLES.GUIDE-EDITOR' title: 'GENERAL.TITLES.SUPPORTIVE-MATERIAL'
}, },
}, },
{ {

View File

@ -1,7 +1,7 @@
export enum SupportiveMaterialFieldType { export enum SupportiveMaterialFieldType {
faq = 'faq', Faq = 0,
about = 'about', About = 1,
glossary = 'glossary', Glossary = 2,
termsofservice = 'termsofservice', TermsOfService = 3,
userguide = 'userguide' UserGuide = 4
} }

View File

@ -0,0 +1,7 @@
import { SupportiveMaterialFieldType } from "@app/core/common/enum/supportive-material-field-type";
export interface SupportiveMaterialPersist{
name: string;
type: SupportiveMaterialFieldType;
html: string;
}

View File

@ -2,26 +2,26 @@ import { Injectable } from "@angular/core";
import { ConfigurationService } from "../configuration/configuration.service"; import { ConfigurationService } from "../configuration/configuration.service";
import { HttpClient, HttpResponse } from "@angular/common/http"; import { HttpClient, HttpResponse } from "@angular/common/http";
import { Observable } from "rxjs"; import { Observable } from "rxjs";
import { SupportiveMaterialFieldType } from "@app/core/common/enum/supportive-material-field-type";
import { SupportiveMaterialPersist } from "@app/core/model/supportive-material/supportive-material";
import { BaseHttpV2Service } from "../http/base-http-v2.service";
@Injectable() @Injectable()
export class SupportiveMaterialService{ export class SupportiveMaterialService{
private baseUrl : string;
constructor( constructor(
private http: HttpClient, private http: BaseHttpV2Service,
private configurationService: ConfigurationService private configurationService: ConfigurationService
) { ) {
this.baseUrl = `${configurationService.server}material`;
} }
public getMaterial(lang: string, field: string): Observable<HttpResponse<Blob>> { private get apiBase(): string { return `${this.configurationService.server}material`; }
return this.http.get(`${this.baseUrl}/${lang}`, {params: {field}, responseType: 'blob', observe: 'response', headers: {'Content-type': 'text/html',
'Accept': 'text/html', public getMaterial(lang: string, field: number): Observable<HttpResponse<Blob>> {
'Access-Control-Allow-Origin': this.configurationService.app, return this.http.get(`${this.apiBase}/${lang}`, {params: {field}, responseType: 'blob', observe: 'response' });
'Access-Control-Allow-Credentials': 'true'} });
} }
public persist(data: any, field: string): Observable<String> { public persist(item :SupportiveMaterialPersist): Observable<String> {
return this.http.post<string>(`${this.baseUrl}/current`, data, {params: {field}}); return this.http.post<string>(`${this.apiBase}/persist`, item);
} }
} }

View File

@ -33,7 +33,7 @@ export class AboutComponent extends BaseComponent implements OnInit {
this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/about'])); this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/about']));
}); });
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.about) this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.About)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
const blob = new Blob([response.body], { type: 'text/html' }); const blob = new Blob([response.body], { type: 'text/html' });

View File

@ -28,7 +28,7 @@ export class FaqContentComponent extends BaseComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.matomoService.trackPageView('FAQ'); this.matomoService.trackPageView('FAQ');
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.faq) this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.Faq)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
const blob = new Blob([response.body], { type: 'text/html' }); const blob = new Blob([response.body], { type: 'text/html' });

View File

@ -36,7 +36,7 @@ export class GlossaryContentComponent extends BaseComponent implements OnInit {
this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/glossary'])); this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/glossary']));
}); });
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.glossary) this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.Glossary)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
const blob = new Blob([response.body], { type: 'text/html' }); const blob = new Blob([response.body], { type: 'text/html' });

View File

@ -33,7 +33,7 @@ export class TermsComponent extends BaseComponent implements OnInit {
this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/terms-and-conditions'])); this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/terms-and-conditions']));
}); });
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.termsofservice) this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.TermsOfService)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
const blob = new Blob([response.body], { type: 'text/html' }); const blob = new Blob([response.body], { type: 'text/html' });

View File

@ -55,7 +55,7 @@ export const ADMIN_ROUTES: RouteInfo[] = [
{ path: '/description-template-type', title: 'SIDE-BAR.DESCRIPTION-TEMPLATE-TYPES', icon: 'library_books' }, { path: '/description-template-type', title: 'SIDE-BAR.DESCRIPTION-TEMPLATE-TYPES', icon: 'library_books' },
{ path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' }, { path: '/users', title: 'SIDE-BAR.USERS', icon: 'people' },
{ path: '/language-editor', title: 'SIDE-BAR.LANGUAGE-EDITOR', icon: 'language' }, { path: '/language-editor', title: 'SIDE-BAR.LANGUAGE-EDITOR', icon: 'language' },
{ path: '/user-guide-editor', title: 'SIDE-BAR.GUIDE-EDITOR', icon: 'import_contacts' } { path: '/supportive-material', title: 'SIDE-BAR.SUPPORTIVE-MATERIAL', icon: 'import_contacts' }
]; ];
export const DATASET_TEMPLATE_ROUTES: RouteInfo[] = [ export const DATASET_TEMPLATE_ROUTES: RouteInfo[] = [

View File

@ -1,8 +1,30 @@
<div class="user-guide-editor"> <div class="supportive-material-editor">
<form (ngSubmit)="submit()" [formGroup]="formGroup"> <form (ngSubmit)="submit()" [formGroup]="formGroup">
<div> <div>
<mat-card class="col-md-8 offset-md-2"> <mat-card class="col-md-8 offset-md-2">
<mat-card-title><div>{{'GUIDE.TITLE' | translate}}</div></mat-card-title> <div>
<div class ="material">
<mat-form-field>
<mat-label>Material type</mat-label>
<mat-select [value] ="selectedMaterial" (selectionChange)="selectedMaterialChanged($event.value)">
<mat-option *ngFor="let vis of visiblesMaterialsTypes" [value]="vis">
{{vis.name | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div class ="lang">
<mat-form-field>
<mat-label>Language</mat-label>
<mat-select [value] ="selectedLang" (selectionChange)="selectedLangChanged($event.value)">
<mat-option *ngFor="let vis of visiblesLangTypes" [value]="vis">
{{vis.name | translate}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<!-- <mat-card-title><div>{{selectedMaterial.name | translate}}</div></mat-card-title> -->
<mat-card-content> <mat-card-content>
<editor [init]="{ <editor [init]="{
base_url: '/tinymce', base_url: '/tinymce',

View File

@ -0,0 +1,28 @@
.supportive-material-editor {
//padding-top: 5em;
padding-bottom: 2em;
margin-top: 1em;
.material{
//width: 80px;
//height: 80px;
float: left;
margin: 20px;
}
.lang{
//width: 80px;
//height: 80px;
float: right;
margin: 20px;
}
.save-btn {
padding-top: inherit !important;
top: auto !important;
width: 56px !important;
bottom: 10px;
position: fixed;
right: 40px;
}
}

View File

@ -14,13 +14,25 @@ import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service';
import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type';
import { SupportiveMaterialPersist } from '@app/core/model/supportive-material/supportive-material';
interface VisibleMaterialType{
name: string;
type: SupportiveMaterialFieldType;
}
interface VisibleLangType{
name: string;
type: string;
}
@Component({ @Component({
selector: 'app-user-guide-editor', selector: 'app-supportive-material-editor',
templateUrl: './user-guide-editor.component.html', templateUrl: './supportive-material-editor.component.html',
styleUrls: ['./user-guide-editor.component.scss'] styleUrls: ['./supportive-material-editor.component.scss']
}) })
export class UserGuideEditorComponent extends BaseComponent implements OnInit { export class SupportiveMaterialEditorComponent extends BaseComponent implements OnInit {
public formGroup: UntypedFormGroup; public formGroup: UntypedFormGroup;
private formBuilder: UntypedFormBuilder; private formBuilder: UntypedFormBuilder;
@ -34,14 +46,57 @@ export class UserGuideEditorComponent extends BaseComponent implements OnInit {
private matomoService: MatomoService private matomoService: MatomoService
) { super(); } ) { super(); }
visiblesMaterialsTypes: VisibleMaterialType[] = [
{name: "FOOTER.FAQ", type: SupportiveMaterialFieldType.Faq},
{name: "FOOTER.ABOUT", type: SupportiveMaterialFieldType.About},
{name: "FOOTER.GLOSSARY", type: SupportiveMaterialFieldType.Glossary},
{name: "FOOTER.TERMS-OF-SERVICE", type: SupportiveMaterialFieldType.TermsOfService},
{name: "FOOTER.GUIDE", type: SupportiveMaterialFieldType.UserGuide}
]
visiblesLangTypes: VisibleLangType[] = [
{name: "GENERAL.LANGUAGES.ENGLISH", type: "en"},
{name: "GENERAL.LANGUAGES.GREEK", type: "gr"},
{name: "GENERAL.LANGUAGES.SPANISH", type: "es"},
{name: "GENERAL.LANGUAGES.GERMAN", type: "de"},
{name: "GENERAL.LANGUAGES.TURKISH", type: "tr"},
{name: "GENERAL.LANGUAGES.SLOVAK", type: "sk"},
{name: "GENERAL.LANGUAGES.SERBIAN", type: "sr"},
{name: "GENERAL.LANGUAGES.PORTUGUESE", type: "pt"},
{name: "GENERAL.LANGUAGES.CROATIAN", type: "hr"},
{name: "GENERAL.LANGUAGES.POLISH", type: "pl"}
]
selectedMaterial: VisibleMaterialType;
selectedLang: VisibleLangType;
ngOnInit() { ngOnInit() {
this.matomoService.trackPageView('Admin: User Guide Editor'); this.selectedMaterial = this.visiblesMaterialsTypes.find(x => x.type == SupportiveMaterialFieldType.Faq);
this.selectedLang = this.visiblesLangTypes.find(x => x.type == this.languageService.getCurrentLanguage());
this.getSupportiveMaterialData();
}
public selectedMaterialChanged(item: VisibleMaterialType){
this.selectedMaterial = item;
this.getSupportiveMaterialData();
}
public selectedLangChanged(item: VisibleLangType){
this.selectedLang = item;
this.getSupportiveMaterialData();
}
private getSupportiveMaterialData(){
this.matomoService.trackPageView(`Admin: ${this.selectedMaterial.name} Editor`);
this.formBuilder = new UntypedFormBuilder(); this.formBuilder = new UntypedFormBuilder();
this.formGroup = this.formBuilder.group({ this.formGroup = this.formBuilder.group({
name: [''], name: [''],
html: [''] html: ['']
}); });
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.userguide).pipe(takeUntil(this._destroyed)).subscribe(data => { this.supportiveMaterialService.getMaterial(this.selectedLang.type, this.selectedMaterial.type).pipe(takeUntil(this._destroyed)).subscribe(data => {
const contentDispositionHeader = data.headers.get('Content-Disposition'); const contentDispositionHeader = data.headers.get('Content-Disposition');
const filename = contentDispositionHeader.split(';')[1].trim().split('=')[1].replace(/"/g, ''); const filename = contentDispositionHeader.split(';')[1].trim().split('=')[1].replace(/"/g, '');
@ -77,7 +132,12 @@ export class UserGuideEditorComponent extends BaseComponent implements OnInit {
let result = this.parseText(this.formGroup.get('html').value); let result = this.parseText(this.formGroup.get('html').value);
//result = result.replace(/href="#/g, 'class="href" path="'); //result = result.replace(/href="#/g, 'class="href" path="');
this.formGroup.get('html').patchValue(result); this.formGroup.get('html').patchValue(result);
this.supportiveMaterialService.persist(this.formGroup.value, SupportiveMaterialFieldType.userguide).pipe(takeUntil(this._destroyed)) const item = {name: this.formGroup.value['name'], type: this.selectedMaterial.type ,html: this.formGroup.value['html']} as SupportiveMaterialPersist
if(item.name.endsWith("_en.html") && this.selectedLang.type != "en" ){
item.name = item.name.replace("_en.html", `_${this.selectedLang.type}.html`);
}
this.supportiveMaterialService.persist(item).pipe(takeUntil(this._destroyed))
.subscribe( .subscribe(
complete => { complete => {
this.onCallbackSuccess(complete); this.onCallbackSuccess(complete);

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { EditorModule } from '@tinymce/tinymce-angular';
import { SupportiveMaterialEditorRoutingModule } from './supportive-material-editor.routing';
import { SupportiveMaterialEditorComponent } from './supportive-material-editor.component';
import { CommonUiModule } from '@common/ui/common-ui.module';
import { CommonFormsModule } from '@common/forms/common-forms.module';
@NgModule({
declarations: [SupportiveMaterialEditorComponent],
imports: [
CommonUiModule,
CommonFormsModule,
SupportiveMaterialEditorRoutingModule,
EditorModule
]
})
export class SupportiveMaterialEditorModule { }

View File

@ -1,15 +1,15 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; import { Routes, RouterModule } from '@angular/router';
import { UserGuideEditorComponent } from './user-guide-editor.component'; import { SupportiveMaterialEditorComponent } from './supportive-material-editor.component';
import { AdminAuthGuard } from '@app/core/admin-auth-guard.service'; import { AdminAuthGuard } from '@app/core/admin-auth-guard.service';
const routes: Routes = [ const routes: Routes = [
{ path: '', component: UserGuideEditorComponent, canActivate: [AdminAuthGuard] }, { path: '', component: SupportiveMaterialEditorComponent, canActivate: [AdminAuthGuard] },
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forChild(routes)], imports: [RouterModule.forChild(routes)],
exports: [RouterModule] exports: [RouterModule]
}) })
export class UserGuideEditorRoutingModule { } export class SupportiveMaterialEditorRoutingModule { }

View File

@ -1,14 +0,0 @@
.user-guide-editor {
//padding-top: 5em;
padding-bottom: 2em;
margin-top: 1em;
.save-btn {
padding-top: inherit !important;
top: auto !important;
width: 56px !important;
bottom: 10px;
position: fixed;
right: 40px;
}
}

View File

@ -1,18 +0,0 @@
import { NgModule } from '@angular/core';
import { EditorModule } from '@tinymce/tinymce-angular';
import { UserGuideEditorRoutingModule } from './user-guide-editor.routing';
import { UserGuideEditorComponent } from './user-guide-editor.component';
import { CommonUiModule } from '@common/ui/common-ui.module';
import { CommonFormsModule } from '@common/forms/common-forms.module';
@NgModule({
declarations: [UserGuideEditorComponent],
imports: [
CommonUiModule,
CommonFormsModule,
UserGuideEditorRoutingModule,
EditorModule
]
})
export class UserGuideEditorModule { }

View File

@ -51,7 +51,7 @@ export class UserGuideContentComponent extends BaseComponent implements OnInit {
this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.translate.onLangChange.subscribe((event: LangChangeEvent) => {
this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/user-guide'])); this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/user-guide']));
}); });
this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.userguide) this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.UserGuide)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
const blob = new Blob([response.body], { type: 'text/html' }); const blob = new Blob([response.body], { type: 'text/html' });

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Benutzerhandbuch bearbeiten", "GUIDE-EDITOR": "Benutzerhandbuch bearbeiten",
"CO-BRANDING": "Co-Branding", "CO-BRANDING": "Co-Branding",
"SUPPORT": "Support", "SUPPORT": "Support",
"FEEDBACK": "Send feedback" "FEEDBACK": "Send feedback",
"SUPPORTIVE-MATERIAL": "Unterstützendes Material"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -331,7 +331,8 @@
"GUIDE-EDITOR": "User Guide Editor", "GUIDE-EDITOR": "User Guide Editor",
"CO-BRANDING": "Co-Branding", "CO-BRANDING": "Co-Branding",
"SUPPORT": "Support", "SUPPORT": "Support",
"FEEDBACK": "Send feedback" "FEEDBACK": "Send feedback",
"SUPPORTIVE-MATERIAL": "Supportive Material"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Editor de la guía de usuario", "GUIDE-EDITOR": "Editor de la guía de usuario",
"CO-BRANDING": "Marca compartida", "CO-BRANDING": "Marca compartida",
"SUPPORT": "Soporte", "SUPPORT": "Soporte",
"FEEDBACK": "Enviar feedback" "FEEDBACK": "Enviar feedback",
"SUPPORTIVE-MATERIAL": "Μaterial de Αpoyo"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Οδηγός Χρήστη", "GUIDE-EDITOR": "Οδηγός Χρήστη",
"CO-BRANDING": "Co-Branding", "CO-BRANDING": "Co-Branding",
"SUPPORT": "Υποστήριξη", "SUPPORT": "Υποστήριξη",
"FEEDBACK": "Στείλετε τα σχόλιά σας" "FEEDBACK": "Στείλετε τα σχόλιά σας",
"SUPPORTIVE-MATERIAL": "Υποστηρικτικό Yλικό"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Uređivanje uputa za korisnike", "GUIDE-EDITOR": "Uređivanje uputa za korisnike",
"CO-BRANDING": "Razvoj i suradnja", "CO-BRANDING": "Razvoj i suradnja",
"SUPPORT": "Podrška", "SUPPORT": "Podrška",
"FEEDBACK": "Molimo pošaljite nam svoje sugestije i komentare" "FEEDBACK": "Molimo pošaljite nam svoje sugestije i komentare",
"SUPPORTIVE-MATERIAL": "Potporni Materijal"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Edytor podręcznika użytkownika", "GUIDE-EDITOR": "Edytor podręcznika użytkownika",
"CO-BRANDING": "Wspólne oznaczenie", "CO-BRANDING": "Wspólne oznaczenie",
"SUPPORT": "Wsparcie", "SUPPORT": "Wsparcie",
"FEEDBACK": "Wyślij opinię" "FEEDBACK": "Wyślij opinię",
"SUPPORTIVE-MATERIAL": "Materiał Pomocniczy"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Editor do Guia de Utilizador", "GUIDE-EDITOR": "Editor do Guia de Utilizador",
"CO-BRANDING": "Co-Branding", "CO-BRANDING": "Co-Branding",
"SUPPORT": "Suporte", "SUPPORT": "Suporte",
"FEEDBACK": "Enviar comentários" "FEEDBACK": "Enviar comentários",
"SUPPORTIVE-MATERIAL": "Material de Suporte"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Úprava používateľskej príručky", "GUIDE-EDITOR": "Úprava používateľskej príručky",
"CO-BRANDING": "Co-Branding", "CO-BRANDING": "Co-Branding",
"SUPPORT": "Podpora", "SUPPORT": "Podpora",
"FEEDBACK": "Poslať spätnú väzbu" "FEEDBACK": "Poslať spätnú väzbu",
"SUPPORTIVE-MATERIAL": "Podporný materiál"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Uređivanje vodiča za korisnike", "GUIDE-EDITOR": "Uređivanje vodiča za korisnike",
"CO-BRANDING": "Partnerstvo", "CO-BRANDING": "Partnerstvo",
"SUPPORT": "Podrška", "SUPPORT": "Podrška",
"FEEDBACK": "Pošaljite nam sugestije i komentare" "FEEDBACK": "Pošaljite nam sugestije i komentare",
"SUPPORTIVE-MATERIAL": "Потпорни материјал"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {

View File

@ -285,7 +285,8 @@
"GUIDE-EDITOR": "Kullanıcı Rehberi Editörü", "GUIDE-EDITOR": "Kullanıcı Rehberi Editörü",
"CO-BRANDING": "Birlikte Markalama", "CO-BRANDING": "Birlikte Markalama",
"SUPPORT": "Destek", "SUPPORT": "Destek",
"FEEDBACK": "Geribildirim Yolla" "FEEDBACK": "Geribildirim Yolla",
"SUPPORTIVE-MATERIAL": "Destekleyici Malzeme"
}, },
"DATASET-PROFILE-EDITOR": { "DATASET-PROFILE-EDITOR": {
"TITLE": { "TITLE": {