Refactor image URL handling and enhance tutorial component layout
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ export class DialogUploadImageComponent {
|
||||
}
|
||||
|
||||
selectUploadedImage() {
|
||||
this.selectUploadedImageClicked.emit(this.imageUpload?.fileInfo?.url);
|
||||
this.selectUploadedImageClicked.emit(this.imageUpload?.fileInfo);
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
|
||||
+62
-45
@@ -4,38 +4,55 @@
|
||||
</mat-card-header>
|
||||
<mat-card-content >
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Title</mat-label>
|
||||
|
||||
<mat-label class="label-style">Title</mat-label>
|
||||
<input matInput required
|
||||
[(ngModel)]="tutorial.title">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Use title image</mat-label>
|
||||
<img style="width: 120px; height: 120px" src="{{tutorial.titleimage}}" alt="">
|
||||
<input matInput
|
||||
[(ngModel)]="tutorial.titleimage">
|
||||
</mat-form-field>
|
||||
<button mat-raised-button color="primary" (click)="openSelectImageDialog('100ms', '5ms')">Select image</button>
|
||||
<button mat-raised-button color="primary" (click)="openUploadImageDialog('100ms', '5ms')">Upload image</button>
|
||||
<div class="example-full-width">
|
||||
<mat-label>Description</mat-label>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text">
|
||||
<div class="markdown-editor-container">
|
||||
<div class="markdown-editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor
|
||||
textareaId="editor1"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.description"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
|
||||
<mat-label class="label-style">Title image</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<table class="example-full-width">
|
||||
<tr>
|
||||
<td style="width: 120px;">
|
||||
<img style="width: 120px; height: 120px" src="{{tutorial.titleimage}}" alt="">
|
||||
</td>
|
||||
<td>
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Title image</mat-label>
|
||||
<input matInput disabled
|
||||
[(ngModel)]="tutorial.titleimage">
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-raised-button color="primary" (click)="openSelectImageDialog('100ms', '5ms')">Select image</button>
|
||||
<button mat-raised-button color="primary" (click)="openUploadImageDialog('100ms', '5ms')">Upload image</button>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="example-full-width">
|
||||
<mat-label class="label-style">Description</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text | Result">
|
||||
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Editor">
|
||||
<div class="markdown-editor-container">
|
||||
<div class="markdown-editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor
|
||||
textareaId="editor1"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.description"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
@@ -47,26 +64,26 @@
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
<div class="example-full-width">
|
||||
<mat-label>Body</mat-label>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text">
|
||||
<div class="markdown-editor-container">
|
||||
<div class="markdown-editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor
|
||||
textareaId="editor2"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.body"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
</div>
|
||||
<markdown class="variable-binding" [data]="tutorial.body"></markdown>
|
||||
</div>
|
||||
|
||||
<div class="example-full-width">
|
||||
<mat-label class="label-style">Body</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text | Result">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.body"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor style="color: #1a1a1a"
|
||||
textareaId="editor2"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.body"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
<markdown class="preview" [data]="tutorial.body"></markdown>
|
||||
|
||||
+15
-3
@@ -9,9 +9,7 @@
|
||||
.markdown-editor-container{
|
||||
display: flex;
|
||||
}
|
||||
mat-card{
|
||||
margin: 20px;
|
||||
}
|
||||
|
||||
mat-card-title{
|
||||
color: cyan;
|
||||
}
|
||||
@@ -55,3 +53,17 @@ mat-card-title{
|
||||
/* display: block;
|
||||
float: right;*/
|
||||
}
|
||||
|
||||
.label-style{
|
||||
font-size: -webkit-xxx-large;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.mat-mdc-card-outlined {
|
||||
background-color: var(--mat-card-outlined-container-color, var(--mat-sys-surface));
|
||||
border-radius:0;
|
||||
border-width: var(--mat-card-outlined-outline-width, 1px);
|
||||
border-color: var(--mat-card-outlined-outline-color, var(--mat-sys-outline-variant));
|
||||
box-shadow: var(--mat-card-outlined-container-elevation, var(--mat-sys-level0));
|
||||
}
|
||||
|
||||
+6
-5
@@ -16,6 +16,7 @@ import {MatDialog} from '@angular/material/dialog';
|
||||
import {DialogSelectImageComponent} from '../dialog-select-image.component/dialog-select-image.component';
|
||||
import {DialogUploadImageComponent} from '../dialog-upload-image.component/dialog-upload-image.component';
|
||||
import {FileUploadComponent} from '../../../components/file-upload.component/file-upload.component';
|
||||
import {MatDivider} from '@angular/material/divider';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tutorial-add.component',
|
||||
@@ -33,7 +34,8 @@ import {FileUploadComponent} from '../../../components/file-upload.component/fil
|
||||
MatTabGroup,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
AngularMarkdownEditorModule
|
||||
AngularMarkdownEditorModule,
|
||||
MatDivider
|
||||
],
|
||||
templateUrl: './tutorial-add.component.html',
|
||||
styleUrl: './tutorial-add.component.scss',
|
||||
@@ -43,9 +45,9 @@ export class TutorialAddComponent implements OnInit{
|
||||
|
||||
tutorial: Tutorial = new Tutorial();
|
||||
submitted = false;
|
||||
bsEditorInstance!: EditorInstance;
|
||||
markdownText = '';
|
||||
showEditor = true;
|
||||
bsEditorInstance!: EditorInstance;
|
||||
tutorialForm!: FormGroup;
|
||||
editorOptions!: EditorOption;
|
||||
|
||||
@@ -84,6 +86,7 @@ const language = 'typescript';
|
||||
this.editorOptions = {
|
||||
autofocus: false,
|
||||
iconlibrary: 'fa',
|
||||
height: 300,
|
||||
savable: false,
|
||||
onFullscreenExit: (e) => this.hidePreview(),
|
||||
onShow: (e) => this.bsEditorInstance = e,
|
||||
@@ -99,9 +102,7 @@ const language = 'typescript';
|
||||
isPreview: [true]
|
||||
});
|
||||
}
|
||||
selectImage() {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
/** highlight all code found, needs to be wrapped in timer to work properly */
|
||||
highlight() {
|
||||
setTimeout(() => {
|
||||
|
||||
+88
-14
@@ -4,23 +4,97 @@
|
||||
</mat-card-header>
|
||||
<mat-card-content >
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Title</mat-label>
|
||||
<mat-label class="label-style">Title</mat-label>
|
||||
<input matInput required
|
||||
[(ngModel)]="tutorial.title">
|
||||
</mat-form-field>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text">
|
||||
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
<markdown class="preview" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Example">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="markdown"></markdown>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<mat-label class="label-style">Title image</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<table class="example-full-width">
|
||||
<tr>
|
||||
<td style="width: 120px;">
|
||||
<img style="width: 120px; height: 120px" src="{{tutorial.titleimage}}" alt="">
|
||||
</td>
|
||||
<td>
|
||||
<mat-form-field class="example-full-width">
|
||||
<mat-label>Title image</mat-label>
|
||||
<input matInput disabled
|
||||
[(ngModel)]="tutorial.titleimage">
|
||||
</mat-form-field>
|
||||
<div>
|
||||
<button mat-raised-button color="primary" (click)="openSelectImageDialog('100ms', '5ms')">Select image</button>
|
||||
<button mat-raised-button color="primary" (click)="openUploadImageDialog('100ms', '5ms')">Upload image</button>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="example-full-width">
|
||||
<mat-label class="label-style">Description</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text | Result">
|
||||
<textarea class="variable-textarea" [(ngModel)]="tutorial.description"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Editor">
|
||||
<div class="markdown-editor-container">
|
||||
<div class="markdown-editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor
|
||||
textareaId="editor1"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.description"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
<markdown class="preview" [data]="tutorial.description"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Example">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="markdown"></markdown>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
<div class="example-full-width">
|
||||
<mat-label class="label-style">Body</mat-label>
|
||||
<mat-divider></mat-divider>
|
||||
<mat-tab-group>
|
||||
<mat-tab label="Markdown text | Result">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="tutorial.body"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Editor">
|
||||
<form novalidate>
|
||||
<angular-markdown-editor style="color: #1a1a1a"
|
||||
textareaId="editor2"
|
||||
[options]="editorOptions"
|
||||
name="markdownText"
|
||||
[(ngModel)]="tutorial.body"
|
||||
(onFullscreenExit)="hidePreview()"
|
||||
>
|
||||
</angular-markdown-editor>
|
||||
</form>
|
||||
</mat-tab>
|
||||
<mat-tab label="Result">
|
||||
<markdown class="preview" [data]="tutorial.body"></markdown>
|
||||
</mat-tab>
|
||||
<mat-tab label="Example">
|
||||
<textarea class="variable-textarea" [(ngModel)]="markdown"></textarea>
|
||||
<markdown class="variable-binding" [data]="markdown"></markdown>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
|
||||
|
||||
+133
-6
@@ -1,13 +1,18 @@
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
|
||||
import {MarkdownComponent} from 'ngx-markdown';
|
||||
import {Component, CUSTOM_ELEMENTS_SCHEMA, inject, OnInit} from '@angular/core';
|
||||
import {MarkdownComponent, MarkdownService} from 'ngx-markdown';
|
||||
import {MatButton} from '@angular/material/button';
|
||||
import {MatCard, MatCardActions, MatCardContent, MatCardHeader} from '@angular/material/card';
|
||||
import {MatError, MatFormField, MatInput, MatLabel} from '@angular/material/input';
|
||||
import {MatTab, MatTabGroup} from '@angular/material/tabs';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {FormBuilder, FormGroup, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {Tutorial} from '../../../models/tutorial.model';
|
||||
import {UserApiService} from '../user-api.service';
|
||||
import {ActivatedRoute, RouterLink} from '@angular/router';
|
||||
import {AngularMarkdownEditorModule, EditorInstance, EditorOption} from 'angular-markdown-editor';
|
||||
import {MatDivider} from '@angular/material/divider';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {DialogSelectImageComponent} from '../dialog-select-image.component/dialog-select-image.component';
|
||||
import {DialogUploadImageComponent} from '../dialog-upload-image.component/dialog-upload-image.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-tutorial-edit.component',
|
||||
@@ -27,17 +32,28 @@ import {ActivatedRoute, RouterLink} from '@angular/router';
|
||||
FormsModule,
|
||||
MatFormField,
|
||||
RouterLink,
|
||||
MatError
|
||||
MatError,
|
||||
AngularMarkdownEditorModule,
|
||||
MatDivider
|
||||
],
|
||||
templateUrl: './tutorial-edit.component.html',
|
||||
styleUrl: './tutorial-edit.component.scss',
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class TutorialEditComponent {
|
||||
export class TutorialEditComponent implements OnInit{
|
||||
|
||||
tutorial: Tutorial = new Tutorial();
|
||||
submitted = false;
|
||||
hasError = false;
|
||||
errorMessage = '';
|
||||
markdownText="";
|
||||
bsEditorInstance!: EditorInstance;
|
||||
tutorialForm!: FormGroup;
|
||||
editorOptions!: EditorOption;
|
||||
|
||||
readonly dialog = inject(MatDialog);
|
||||
|
||||
|
||||
markdown = `## Markdown __rulez__!
|
||||
---
|
||||
|
||||
@@ -56,7 +72,11 @@ const language = 'typescript';
|
||||
> Blockquote to the max`;
|
||||
private id: string | null | undefined;
|
||||
|
||||
constructor(private userApiService: UserApiService, private route: ActivatedRoute) {
|
||||
constructor(private userApiService: UserApiService,
|
||||
private route: ActivatedRoute,
|
||||
private fb: FormBuilder,
|
||||
private markdownService: MarkdownService
|
||||
) {
|
||||
|
||||
this.route.queryParams
|
||||
.subscribe(params => {
|
||||
@@ -71,6 +91,62 @@ const language = 'typescript';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.editorOptions = {
|
||||
autofocus: false,
|
||||
iconlibrary: 'fa',
|
||||
height: 300,
|
||||
savable: false,
|
||||
onFullscreenExit: (e) => this.hidePreview(),
|
||||
onShow: (e) => this.bsEditorInstance = e,
|
||||
parser: (val) => this.parse(val)
|
||||
};
|
||||
this.buildForm(this.tutorial.description);
|
||||
|
||||
}
|
||||
|
||||
buildForm(markdownText: string | undefined) {
|
||||
this.tutorialForm = this.fb.group({
|
||||
body: [markdownText],
|
||||
isPreview: [true]
|
||||
});
|
||||
}
|
||||
/** highlight all code found, needs to be wrapped in timer to work properly */
|
||||
highlight() {
|
||||
setTimeout(() => {
|
||||
this.markdownService.highlight();
|
||||
});
|
||||
}
|
||||
|
||||
hidePreview() {
|
||||
if (this.bsEditorInstance && this.bsEditorInstance.hidePreview) {
|
||||
this.bsEditorInstance.hidePreview();
|
||||
}
|
||||
}
|
||||
|
||||
showFullScreen(isFullScreen: boolean) {
|
||||
if (this.bsEditorInstance && this.bsEditorInstance.setFullscreen) {
|
||||
this.bsEditorInstance.showPreview();
|
||||
this.bsEditorInstance.setFullscreen(isFullScreen);
|
||||
}
|
||||
}
|
||||
|
||||
parse(inputValue: string) {
|
||||
const markedOutput = this.markdownService.parse(inputValue.trim());
|
||||
this.highlight();
|
||||
|
||||
return markedOutput;
|
||||
}
|
||||
|
||||
onFormChanges(): void {
|
||||
this.tutorialForm.valueChanges.subscribe(formData => {
|
||||
if (formData) {
|
||||
this.markdownText = formData.body;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateTutorial(): void {
|
||||
this.userApiService.update(this.id, this.tutorial)
|
||||
.subscribe(
|
||||
@@ -87,4 +163,55 @@ const language = 'typescript';
|
||||
this.hasError = true;
|
||||
});
|
||||
}
|
||||
|
||||
openSelectImageDialog(enterAnimationDuration: string, exitAnimationDuration: string) {
|
||||
|
||||
let dialogSelectRef = this.dialog.open(DialogSelectImageComponent, {
|
||||
height: '500px',
|
||||
width: '600px',
|
||||
enterAnimationDuration,
|
||||
exitAnimationDuration,
|
||||
// data: {username: this.dialogLoginData.username, password: this.dialogLoginData.password}
|
||||
});
|
||||
dialogSelectRef.componentInstance.uploadClicked.subscribe(result => {
|
||||
dialogSelectRef.close();
|
||||
this.openUploadImageDialog(enterAnimationDuration, exitAnimationDuration);
|
||||
})
|
||||
|
||||
const dialogSelectSubscription = dialogSelectRef.componentInstance.selectClicked
|
||||
.subscribe(result => {
|
||||
console.log('Got the data!', result);
|
||||
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
this.tutorial.titleimage = result.url;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
openUploadImageDialog(enterAnimationDuration: string, exitAnimationDuration: string) {
|
||||
let dialogSelectRef = this.dialog.open(DialogUploadImageComponent, {
|
||||
height: '500px',
|
||||
width: '600px',
|
||||
enterAnimationDuration,
|
||||
exitAnimationDuration,
|
||||
// data: {username: this.dialogLoginData.username, password: this.dialogLoginData.password}
|
||||
});
|
||||
dialogSelectRef.componentInstance.openSelectDialogClicked.subscribe(result => {
|
||||
dialogSelectRef.close();
|
||||
this.openSelectImageDialog(enterAnimationDuration, exitAnimationDuration);
|
||||
})
|
||||
|
||||
const dialogUploadSubscription = dialogSelectRef.componentInstance.selectUploadedImageClicked
|
||||
.subscribe(result => {
|
||||
console.log('Got the data!', result);
|
||||
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
this.tutorial.titleimage = result.url;
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user