Adding TinyMCe through richtext input to Crud
This commit is contained in:
20
front/app/package-lock.json
generated
20
front/app/package-lock.json
generated
@@ -20,6 +20,7 @@
|
|||||||
"@ngx-formly/bootstrap": "^6.0.0",
|
"@ngx-formly/bootstrap": "^6.0.0",
|
||||||
"@ngx-formly/core": "^6.0.0",
|
"@ngx-formly/core": "^6.0.0",
|
||||||
"@popperjs/core": "^2.11.6",
|
"@popperjs/core": "^2.11.6",
|
||||||
|
"@tinymce/tinymce-angular": "^7.0.0",
|
||||||
"ngx-bootstrap-icons": "^1.9.1",
|
"ngx-bootstrap-icons": "^1.9.1",
|
||||||
"ngx-wig": "^15.1.4",
|
"ngx-wig": "^15.1.4",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
@@ -3383,6 +3384,20 @@
|
|||||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
|
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@tinymce/tinymce-angular": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-angular/-/tinymce-angular-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-IKNaG/ihlxE1XCfq6lzULbnsqZO9KNJtlpu5jo6JDJDL9zcFzj/N2A16Kk7rTj1yfmDoB1IXAk/BpMOvgDY8cg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tinymce": "^6.0.0 || ^5.5.0",
|
||||||
|
"tslib": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": ">=14.0.0",
|
||||||
|
"@angular/core": ">=14.0.0",
|
||||||
|
"@angular/forms": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tootallnate/once": {
|
"node_modules/@tootallnate/once": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||||
@@ -10978,6 +10993,11 @@
|
|||||||
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/tinymce": {
|
||||||
|
"version": "6.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.3.1.tgz",
|
||||||
|
"integrity": "sha512-+oCwXuTxAdJXVJ0130OxQz0JDNsqg3deuzgeUo8X5Vb27EzCJgXwO5eWvCxvkxpQo4oiHMVlM4tUIpTUHufHGQ=="
|
||||||
|
},
|
||||||
"node_modules/tmp": {
|
"node_modules/tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"@ngx-formly/bootstrap": "^6.0.0",
|
"@ngx-formly/bootstrap": "^6.0.0",
|
||||||
"@ngx-formly/core": "^6.0.0",
|
"@ngx-formly/core": "^6.0.0",
|
||||||
"@popperjs/core": "^2.11.6",
|
"@popperjs/core": "^2.11.6",
|
||||||
|
"@tinymce/tinymce-angular": "^7.0.0",
|
||||||
"ngx-bootstrap-icons": "^1.9.1",
|
"ngx-bootstrap-icons": "^1.9.1",
|
||||||
"ngx-wig": "^15.1.4",
|
"ngx-wig": "^15.1.4",
|
||||||
"rxjs": "~7.5.0",
|
"rxjs": "~7.5.0",
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import { FormsModule, ReactiveFormsModule} from '@angular/forms';
|
|||||||
import { FormlyModule } from '@ngx-formly/core';
|
import { FormlyModule } from '@ngx-formly/core';
|
||||||
import { FormlyBootstrapModule } from '@ngx-formly/bootstrap';
|
import { FormlyBootstrapModule } from '@ngx-formly/bootstrap';
|
||||||
|
|
||||||
|
import { EditorModule } from '@tinymce/tinymce-angular';
|
||||||
|
|
||||||
import { CardComponent } from './card/card.component';
|
import { CardComponent } from './card/card.component';
|
||||||
import { ListComponent } from './list/list.component';
|
import { ListComponent } from './list/list.component';
|
||||||
import { ArrayTypeComponent } from "./types/array.type";
|
import { ArrayTypeComponent } from "./types/array.type";
|
||||||
@@ -23,6 +25,7 @@ import { ForeignkeyTypeComponent } from "./types/foreignkey.type";
|
|||||||
import { HiddenTypeComponent } from "./types/hidden.type";
|
import { HiddenTypeComponent } from "./types/hidden.type";
|
||||||
import { DictionaryTypeComponent } from "./types/dictionary.type";
|
import { DictionaryTypeComponent } from "./types/dictionary.type";
|
||||||
import { DictionaryService } from "./types/dictionary.service";
|
import { DictionaryService } from "./types/dictionary.service";
|
||||||
|
import { RichtextTypeComponent } from "./types/richtext.type";
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@@ -36,7 +39,8 @@ import { DictionaryService } from "./types/dictionary.service";
|
|||||||
MultiSchemaTypeComponent,
|
MultiSchemaTypeComponent,
|
||||||
ForeignkeyTypeComponent,
|
ForeignkeyTypeComponent,
|
||||||
HiddenTypeComponent,
|
HiddenTypeComponent,
|
||||||
DictionaryTypeComponent
|
DictionaryTypeComponent,
|
||||||
|
RichtextTypeComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
JsonschemasService,
|
JsonschemasService,
|
||||||
@@ -63,9 +67,11 @@ import { DictionaryService } from "./types/dictionary.service";
|
|||||||
{ name: 'foreign-key', component: ForeignkeyTypeComponent },
|
{ name: 'foreign-key', component: ForeignkeyTypeComponent },
|
||||||
{ name: 'hidden', component: HiddenTypeComponent },
|
{ name: 'hidden', component: HiddenTypeComponent },
|
||||||
{ name: 'dictionary', component: DictionaryTypeComponent },
|
{ name: 'dictionary', component: DictionaryTypeComponent },
|
||||||
|
{ name: 'richtext', component: RichtextTypeComponent },
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
FormlyBootstrapModule
|
FormlyBootstrapModule,
|
||||||
|
EditorModule
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CardComponent,
|
CardComponent,
|
||||||
|
|||||||
109
front/app/src/common/crud/types/richtext.type.ts
Normal file
109
front/app/src/common/crud/types/richtext.type.ts
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import {Component, OnInit} from "@angular/core";
|
||||||
|
import { FormlyFieldInput } from "@ngx-formly/bootstrap/input";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'formly-richtext-type',
|
||||||
|
template: `
|
||||||
|
<ng-template #labelTemplate>
|
||||||
|
<label *ngIf="props.label && props.hideLabel !== true" [attr.for]="id" class="form-label">
|
||||||
|
{{ props.label }}
|
||||||
|
<span *ngIf="props.required && props.hideRequiredMarker !== true" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template #inputTemplate>
|
||||||
|
<editor *ngIf="! this.field.props.disabled"
|
||||||
|
apiKey="mjk3fhupxy3pitud9iyfqse231zpuuosqedmlgydrjx6mjlo"
|
||||||
|
[init]="getInitConfig()"
|
||||||
|
[formControl]="formControl"
|
||||||
|
[class.is-invalid]="showError"
|
||||||
|
[formlyAttributes]="field"
|
||||||
|
[inline]="false"
|
||||||
|
(onGetContent)="onGetContent($event)"
|
||||||
|
(onBeforeAddUndo)="onBeforeAddUndo($event)"
|
||||||
|
></editor>
|
||||||
|
<div *ngIf="this.field.props.disabled" [innerHTML]="formControl.value" class="form-control">
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<!-- <div class="mb-3" [class.form-floating]="props.labelPosition === 'floating'" [class.has-error]="showError">-->
|
||||||
|
<ng-container *ngIf="props.labelPosition !== 'floating'">
|
||||||
|
<ng-container [ngTemplateOutlet]="labelTemplate"></ng-container>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container [ngTemplateOutlet]="inputTemplate"></ng-container>
|
||||||
|
<div *ngIf="showError" class="invalid-feedback" [style.display]="'block'">
|
||||||
|
<formly-validation-message [field]="field"></formly-validation-message>
|
||||||
|
</div>
|
||||||
|
<small *ngIf="props.description" class="form-text text-muted">{{ props.description }}</small>
|
||||||
|
<!-- </div>-->
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
export class RichtextTypeComponent extends FormlyFieldInput implements OnInit {
|
||||||
|
multiline = true;
|
||||||
|
|
||||||
|
init_multiline = {
|
||||||
|
plugins: 'lists image imagetools table code searchreplace autoresize',
|
||||||
|
menubar: 'edit insert format tools table',
|
||||||
|
menu: {
|
||||||
|
edit: { title: 'Edit', items: 'undo redo | cut copy paste | selectall | searchreplace' },
|
||||||
|
insert: { title: 'Insert', items: 'image link media template codesample inserttable | charmap emoticons hr | pagebreak nonbreaking anchor toc | insertdatetime' },
|
||||||
|
format: { title: 'Format', items: 'bold italic underline strikethrough superscript subscript codeformat | formats blockformats fontformats fontsizes align lineheight | removeformat' },
|
||||||
|
tools: { title: 'Tools', items: 'spellchecker spellcheckerlanguage | code wordcount' },
|
||||||
|
table: { title: 'Table', items: 'inserttable | cell row column | tableprops deletetable' }
|
||||||
|
},
|
||||||
|
toolbar: 'undo redo | styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | outdent indent bullist numlist | table image',
|
||||||
|
statusbar: false,
|
||||||
|
autoresize_bottom_margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
init_singleline = {
|
||||||
|
plugins: 'autoresize',
|
||||||
|
menubar: '',
|
||||||
|
toolbar: 'undo redo | bold italic underline',
|
||||||
|
statusbar: false,
|
||||||
|
autoresize_bottom_margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.props.hasOwnProperty('multiline')) {
|
||||||
|
// @ts-ignore
|
||||||
|
this.multiline = this.props['multiline']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getInitConfig() {
|
||||||
|
let result: { menubar: string, toolbar: string };
|
||||||
|
if (this.multiline) {
|
||||||
|
result = this.init_multiline;
|
||||||
|
} else {
|
||||||
|
result = this.init_singleline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.field.props.readonly) {
|
||||||
|
result.menubar = '';
|
||||||
|
result.toolbar = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
onGetContent(param: any) {
|
||||||
|
if (!this.multiline) {
|
||||||
|
const result = param.event.content.match(/<p>(.*)<\/p>/);
|
||||||
|
if (result) {
|
||||||
|
param.event.content = result[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeAddUndo(param: any) {
|
||||||
|
if (!this.multiline) {
|
||||||
|
if (param.event.level.content.indexOf('</p><p>') > -1) {
|
||||||
|
param.event.preventDefault()
|
||||||
|
param.editor.setContent(param.event.level.content.replace('</p><p>', ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user