Implementaiton of preview tab.
This commit is contained in:
@@ -195,4 +195,8 @@ public class PublicationUseCases {
|
|||||||
public List<Publication> getLatest() {
|
public List<Publication> getLatest() {
|
||||||
return publicationPort.getLatest();
|
return publicationPort.getLatest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String previewContent(String publicationText) {
|
||||||
|
return parserService.parse(publicationText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.codiki.domain.publication.exception.NoPublicationSearchResultExceptio
|
|||||||
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
import org.codiki.domain.publication.exception.PublicationNotFoundException;
|
||||||
import org.codiki.domain.publication.model.Publication;
|
import org.codiki.domain.publication.model.Publication;
|
||||||
import org.codiki.domain.publication.model.PublicationEditionRequest;
|
import org.codiki.domain.publication.model.PublicationEditionRequest;
|
||||||
|
import org.codiki.exposition.publication.model.PreviewContentRequest;
|
||||||
import org.codiki.exposition.publication.model.PublicationDto;
|
import org.codiki.exposition.publication.model.PublicationDto;
|
||||||
import org.codiki.exposition.publication.model.PublicationEditionRequestDto;
|
import org.codiki.exposition.publication.model.PublicationEditionRequestDto;
|
||||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
@@ -91,4 +92,9 @@ public class PublicationController {
|
|||||||
|
|
||||||
return publications;
|
return publications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/preview")
|
||||||
|
public String previewPublicationContent(@RequestBody PreviewContentRequest request) {
|
||||||
|
return publicationUseCases.previewContent(request.text());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package org.codiki.exposition.publication.model;
|
||||||
|
|
||||||
|
public record PreviewContentRequest(
|
||||||
|
String text
|
||||||
|
) {}
|
||||||
@@ -26,4 +26,9 @@ export class PublicationRestService {
|
|||||||
params = params.set('query', searchCriteria);
|
params = params.set('query', searchCriteria);
|
||||||
return lastValueFrom(this.httpClient.get<Publication[]>('/api/publications', { params }));
|
return lastValueFrom(this.httpClient.get<Publication[]>('/api/publications', { params }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preview(publicationText: string): Promise<string> {
|
||||||
|
const request = { text: publicationText };
|
||||||
|
return lastValueFrom(this.httpClient.post<string>('/api/publications/preview', request));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<h1>Modification de l'article {{ publication.title }}</h1>
|
<h1>Modification de l'article {{ publication.title }}</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<mat-tab-group dynamicHeight>
|
<mat-tab-group dynamicHeight (selectedIndexChange)="onTabChange($event)">
|
||||||
<mat-tab label="Edition">
|
<mat-tab label="Edition">
|
||||||
<div class="form-content">
|
<div class="form-content">
|
||||||
<div class="first-part">
|
<div class="first-part">
|
||||||
@@ -66,7 +66,19 @@
|
|||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
<mat-tab label="Previewing">
|
<mat-tab label="Previewing">
|
||||||
|
<div class="preview">
|
||||||
|
@if ((isPreviewing$ | async) === true) {
|
||||||
|
<h2>Preview is loading...</h2>
|
||||||
|
<mat-spinner></mat-spinner>
|
||||||
|
} @else {
|
||||||
|
<img class="illustration" src="/pictures/{{ publication.illustrationId }}" />
|
||||||
|
<header>
|
||||||
|
<h1>{{ publication.title }}</h1>
|
||||||
|
<h2>{{ publication.description }}</h2>
|
||||||
|
</header>
|
||||||
|
<main [innerHTML]="publication.parsedText"></main>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
</mat-tab-group>
|
</mat-tab-group>
|
||||||
<footer>
|
<footer>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
border-radius: .5em;
|
border-radius: .5em;
|
||||||
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),0 2px 10px 0 rgba(0,0,0,.12);
|
||||||
|
|
||||||
header {
|
& > header {
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
background-color: #3f51b5;
|
background-color: #3f51b5;
|
||||||
color: white;
|
color: white;
|
||||||
@@ -145,3 +145,38 @@ button, a.button {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.illustration {
|
||||||
|
height: 12em;
|
||||||
|
object-fit: cover;
|
||||||
|
transition: height .2s ease-in-out;
|
||||||
|
|
||||||
|
@media screen and (min-width: 450px) {
|
||||||
|
height: 15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 600px) {
|
||||||
|
height: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 750px) {
|
||||||
|
height: 25em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding: 2em;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,6 +55,10 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
|
|||||||
return this.publicationEditionService.isSaving$;
|
return this.publicationEditionService.isSaving$;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isPreviewing$(): Observable<boolean> {
|
||||||
|
return this.publicationEditionService.isPreviewing$;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
['title', 'description', 'text'].forEach(fieldName => {
|
['title', 'description', 'text'].forEach(fieldName => {
|
||||||
const fieldSubscription = this.publicationEditionForm.controls[fieldName].valueChanges
|
const fieldSubscription = this.publicationEditionForm.controls[fieldName].valueChanges
|
||||||
@@ -135,6 +139,11 @@ export class PublicationEditionComponent implements OnInit, OnDestroy {
|
|||||||
console.log(`cursor position updated: [${positionStart}, ${positionEnd}] (${selectedCharacterCount})`);
|
console.log(`cursor position updated: [${positionStart}, ${positionEnd}] (${selectedCharacterCount})`);
|
||||||
this.publicationEditionService.editCursorPosition(positionStart, positionEnd);
|
this.publicationEditionService.editCursorPosition(positionStart, positionEnd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTabChange(tabSelectedIndex: number): void {
|
||||||
|
if (tabSelectedIndex === 1) {
|
||||||
|
this.publicationEditionService.loadPreview();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,7 @@ export class PublicationEditionService implements OnDestroy {
|
|||||||
private stateSubject = new BehaviorSubject<PublicationEditionState>(copy(DEFAULT_STATE));
|
private stateSubject = new BehaviorSubject<PublicationEditionState>(copy(DEFAULT_STATE));
|
||||||
private subscriptions: Subscription[] = [];
|
private subscriptions: Subscription[] = [];
|
||||||
private isSavingSubject = new BehaviorSubject<boolean>(false);
|
private isSavingSubject = new BehaviorSubject<boolean>(false);
|
||||||
|
private isPreviewingSubject = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
this.subscriptions.forEach(subscription => subscription.unsubscribe());
|
||||||
@@ -85,6 +86,10 @@ export class PublicationEditionService implements OnDestroy {
|
|||||||
return this.isSavingSubject.asObservable();
|
return this.isSavingSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isPreviewing$(): Observable<boolean> {
|
||||||
|
return this.isPreviewingSubject.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
get state$(): Observable<PublicationEditionState> {
|
get state$(): Observable<PublicationEditionState> {
|
||||||
return this.stateSubject.asObservable();
|
return this.stateSubject.asObservable();
|
||||||
}
|
}
|
||||||
@@ -262,4 +267,19 @@ export class PublicationEditionService implements OnDestroy {
|
|||||||
})
|
})
|
||||||
.finally(() => this.isSavingSubject.next(false));
|
.finally(() => this.isSavingSubject.next(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadPreview(): void {
|
||||||
|
const state = this._state;
|
||||||
|
|
||||||
|
this.isPreviewingSubject.next(true);
|
||||||
|
this.publicationRestService.preview(state.publication.text)
|
||||||
|
.then(parsedText => {
|
||||||
|
state.publication.parsedText = parsedText;
|
||||||
|
this._save(state);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
})
|
||||||
|
.finally(() => this.isPreviewingSubject.next(false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,3 +8,7 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user