-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
299 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
...ckend/src/main/java/com/github/hakenadu/plantuml/controller/DocumentImagesController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.github.hakenadu.plantuml.controller; | ||
|
||
import java.util.UUID; | ||
|
||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.web.bind.annotation.CrossOrigin; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
import com.github.hakenadu.plantuml.service.ImageService; | ||
import com.github.hakenadu.plantuml.service.document.DocumentService; | ||
import com.github.hakenadu.plantuml.service.document.exception.DocumentServiceException; | ||
import com.github.hakenadu.plantuml.service.exception.ImageServiceException; | ||
|
||
@Profile({ "local", "webdav", "redis" }) | ||
@RestController | ||
@RequestMapping("/documents/{id}") | ||
@CrossOrigin | ||
public class DocumentImagesController { | ||
|
||
private final DocumentService documentService; | ||
private final ImageService imageService; | ||
|
||
public DocumentImagesController(final DocumentService documentService, final ImageService imageService) { | ||
this.documentService = documentService; | ||
this.imageService = imageService; | ||
} | ||
|
||
@GetMapping(path = "/images/svg", produces = "image/svg+xml") | ||
public byte[] getSvg(final @PathVariable UUID id, final @RequestParam String key) | ||
throws ImageServiceException, DocumentServiceException { | ||
return imageService.getSvg(documentService.getDocument(id, key)); | ||
} | ||
|
||
@GetMapping(path = "/images/png", produces = MediaType.IMAGE_PNG_VALUE) | ||
public byte[] getPng(final @PathVariable UUID id, final @RequestParam String key) | ||
throws ImageServiceException, DocumentServiceException { | ||
return imageService.getPng(documentService.getDocument(id, key)); | ||
} | ||
} |
252 changes: 128 additions & 124 deletions
252
plantuml-editor-frontend/src/app/services/config.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,124 +1,128 @@ | ||
import {Injectable} from '@angular/core'; | ||
import {HttpClient} from '@angular/common/http'; | ||
import {Observable, of} from 'rxjs'; | ||
import {environment} from '../../environments/environment'; | ||
import {DomSanitizer, SafeHtml, SafeUrl} from '@angular/platform-browser'; | ||
import {map} from 'rxjs/operators'; | ||
|
||
export type IconConfig = MaterialIconConfig | ImgIconConfig; | ||
|
||
export interface MaterialIconConfig { | ||
type: 'material'; | ||
name: string; | ||
} | ||
|
||
export interface ImgIconConfig { | ||
type: 'img'; | ||
src: string | SafeUrl; | ||
width?: string; | ||
height?: string; | ||
} | ||
|
||
export type FooterActionConfig = PopupFooterActionConfig | LinkFooterActionConfig; | ||
|
||
export interface PopupFooterActionConfig { | ||
type: 'popup'; | ||
icon: IconConfig; | ||
tooltip?: string; | ||
content: string | SafeHtml; | ||
} | ||
|
||
export interface LinkFooterActionConfig { | ||
type: 'link'; | ||
icon: IconConfig; | ||
tooltip?: string; | ||
href: string | SafeUrl; | ||
} | ||
|
||
export interface IntroConfig { | ||
description?: string | SafeHtml; | ||
slideshow?: { | ||
showMessage?: boolean, | ||
visible?: boolean | ||
}; | ||
} | ||
|
||
export interface FooterConfig { | ||
actions?: FooterActionConfig[]; | ||
} | ||
|
||
export interface ShareConfig { | ||
description?: string | SafeHtml; | ||
} | ||
|
||
export interface FrontendConfig { | ||
intro?: IntroConfig; | ||
footer?: FooterConfig; | ||
share?: ShareConfig; | ||
} | ||
|
||
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class ConfigService { | ||
|
||
private _config?: FrontendConfig; | ||
private _config$: Observable<FrontendConfig>; | ||
|
||
constructor(private httpClient: HttpClient, | ||
private domSanitizer: DomSanitizer) { | ||
if (environment.configUrl !== undefined && environment.configUrl !== null) { | ||
this._config$ = this.httpClient.get<FrontendConfig>(`${environment.configUrl}/frontend/`); | ||
} else { // for local development read config from environment.ts | ||
const config = environment.config; | ||
this._config$ = of(config ? <FrontendConfig>config : {}); | ||
} | ||
this._config$.pipe(map(config => this.sanitize(config))).subscribe(config => this._config = config); | ||
} | ||
|
||
private sanitizeFooterConfig(config: FrontendConfig) { | ||
if (!config?.footer?.actions) { | ||
return; | ||
} | ||
|
||
for (const action of config.footer.actions) { | ||
switch (action.type) { | ||
case 'popup': | ||
action.content = this.domSanitizer.bypassSecurityTrustHtml(<string>action.content); | ||
break; | ||
case 'link': | ||
action.href = this.domSanitizer.bypassSecurityTrustUrl(<string>action.href); | ||
break; | ||
} | ||
if (action.icon.type === 'img') { | ||
action.icon.src = this.domSanitizer.bypassSecurityTrustUrl(<string>action.icon.src) | ||
} | ||
} | ||
} | ||
|
||
private sanitizeIntroConfig(config: FrontendConfig) { | ||
if (config?.intro?.description) { | ||
config.intro.description = this.domSanitizer.bypassSecurityTrustHtml(<string>config.intro.description); | ||
} | ||
} | ||
|
||
private sanitizeShareConfig(config: FrontendConfig) { | ||
if (config?.share?.description) { | ||
config.share.description = this.domSanitizer.bypassSecurityTrustHtml(<string>config.share.description); | ||
} | ||
} | ||
|
||
private sanitize(config: FrontendConfig): FrontendConfig { | ||
this.sanitizeIntroConfig(config); | ||
this.sanitizeFooterConfig(config); | ||
this.sanitizeShareConfig(config); | ||
return config; | ||
} | ||
|
||
get config$(): Observable<FrontendConfig> { | ||
if (this._config) { | ||
return of(this._config); | ||
} | ||
return this._config$; | ||
} | ||
} | ||
import {Injectable} from '@angular/core'; | ||
import {HttpClient} from '@angular/common/http'; | ||
import {Observable, of} from 'rxjs'; | ||
import {environment} from '../../environments/environment'; | ||
import {DomSanitizer, SafeHtml, SafeUrl} from '@angular/platform-browser'; | ||
import {map} from 'rxjs/operators'; | ||
|
||
export type IconConfig = MaterialIconConfig | ImgIconConfig; | ||
|
||
export interface MaterialIconConfig { | ||
type: 'material'; | ||
name: string; | ||
} | ||
|
||
export interface ImgIconConfig { | ||
type: 'img'; | ||
src: string | SafeUrl; | ||
width?: string; | ||
height?: string; | ||
} | ||
|
||
export type FooterActionConfig = PopupFooterActionConfig | LinkFooterActionConfig; | ||
|
||
export interface PopupFooterActionConfig { | ||
type: 'popup'; | ||
icon: IconConfig; | ||
tooltip?: string; | ||
content: string | SafeHtml; | ||
} | ||
|
||
export interface LinkFooterActionConfig { | ||
type: 'link'; | ||
icon: IconConfig; | ||
tooltip?: string; | ||
href: string | SafeUrl; | ||
} | ||
|
||
export interface IntroConfig { | ||
description?: string | SafeHtml; | ||
slideshow?: { | ||
showMessage?: boolean, | ||
visible?: boolean | ||
}; | ||
} | ||
|
||
export interface FooterConfig { | ||
actions?: FooterActionConfig[]; | ||
} | ||
|
||
export interface ShareConfig { | ||
description?: string | SafeHtml; | ||
imageOnlyLinks?: { | ||
visible?: boolean; | ||
warningMessage?: string; | ||
} | ||
} | ||
|
||
export interface FrontendConfig { | ||
intro?: IntroConfig; | ||
footer?: FooterConfig; | ||
share?: ShareConfig; | ||
} | ||
|
||
@Injectable({ | ||
providedIn: 'root' | ||
}) | ||
export class ConfigService { | ||
|
||
private _config?: FrontendConfig; | ||
private _config$: Observable<FrontendConfig>; | ||
|
||
constructor(private httpClient: HttpClient, | ||
private domSanitizer: DomSanitizer) { | ||
if (environment.configUrl !== undefined && environment.configUrl !== null) { | ||
this._config$ = this.httpClient.get<FrontendConfig>(`${environment.configUrl}/frontend/`); | ||
} else { // for local development read config from environment.ts | ||
const config = environment.config; | ||
this._config$ = of(config ? <FrontendConfig>config : {}); | ||
} | ||
this._config$.pipe(map(config => this.sanitize(config))).subscribe(config => this._config = config); | ||
} | ||
|
||
private sanitizeFooterConfig(config: FrontendConfig) { | ||
if (!config?.footer?.actions) { | ||
return; | ||
} | ||
|
||
for (const action of config.footer.actions) { | ||
switch (action.type) { | ||
case 'popup': | ||
action.content = this.domSanitizer.bypassSecurityTrustHtml(<string>action.content); | ||
break; | ||
case 'link': | ||
action.href = this.domSanitizer.bypassSecurityTrustUrl(<string>action.href); | ||
break; | ||
} | ||
if (action.icon.type === 'img') { | ||
action.icon.src = this.domSanitizer.bypassSecurityTrustUrl(<string>action.icon.src) | ||
} | ||
} | ||
} | ||
|
||
private sanitizeIntroConfig(config: FrontendConfig) { | ||
if (config?.intro?.description) { | ||
config.intro.description = this.domSanitizer.bypassSecurityTrustHtml(<string>config.intro.description); | ||
} | ||
} | ||
|
||
private sanitizeShareConfig(config: FrontendConfig) { | ||
if (config?.share?.description) { | ||
config.share.description = this.domSanitizer.bypassSecurityTrustHtml(<string>config.share.description); | ||
} | ||
} | ||
|
||
private sanitize(config: FrontendConfig): FrontendConfig { | ||
this.sanitizeIntroConfig(config); | ||
this.sanitizeFooterConfig(config); | ||
this.sanitizeShareConfig(config); | ||
return config; | ||
} | ||
|
||
get config$(): Observable<FrontendConfig> { | ||
if (this._config) { | ||
return of(this._config); | ||
} | ||
return this._config$; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.