diff --git a/front/app/package-lock.json b/front/app/package-lock.json index fec80129..be3cd7b4 100644 --- a/front/app/package-lock.json +++ b/front/app/package-lock.json @@ -20,6 +20,7 @@ "@ngx-formly/bootstrap": "^6.0.0", "@ngx-formly/core": "^6.0.0", "@popperjs/core": "^2.11.6", + "@tinymce/tinymce-angular": "^7.0.0", "ngx-bootstrap-icons": "^1.9.1", "ngx-wig": "^15.1.4", "rxjs": "~7.5.0", @@ -3383,6 +3384,20 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "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": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -10978,6 +10993,11 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "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": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", diff --git a/front/app/package.json b/front/app/package.json index 61d43839..292d2bed 100644 --- a/front/app/package.json +++ b/front/app/package.json @@ -22,6 +22,7 @@ "@ngx-formly/bootstrap": "^6.0.0", "@ngx-formly/core": "^6.0.0", "@popperjs/core": "^2.11.6", + "@tinymce/tinymce-angular": "^7.0.0", "ngx-bootstrap-icons": "^1.9.1", "ngx-wig": "^15.1.4", "rxjs": "~7.5.0", diff --git a/front/app/src/common/crud/crud.module.ts b/front/app/src/common/crud/crud.module.ts index 4f53e47d..2f38ce73 100644 --- a/front/app/src/common/crud/crud.module.ts +++ b/front/app/src/common/crud/crud.module.ts @@ -7,6 +7,8 @@ import { FormsModule, ReactiveFormsModule} from '@angular/forms'; import { FormlyModule } from '@ngx-formly/core'; import { FormlyBootstrapModule } from '@ngx-formly/bootstrap'; +import { EditorModule } from '@tinymce/tinymce-angular'; + import { CardComponent } from './card/card.component'; import { ListComponent } from './list/list.component'; import { ArrayTypeComponent } from "./types/array.type"; @@ -23,6 +25,7 @@ import { ForeignkeyTypeComponent } from "./types/foreignkey.type"; import { HiddenTypeComponent } from "./types/hidden.type"; import { DictionaryTypeComponent } from "./types/dictionary.type"; import { DictionaryService } from "./types/dictionary.service"; +import { RichtextTypeComponent } from "./types/richtext.type"; @NgModule({ @@ -36,7 +39,8 @@ import { DictionaryService } from "./types/dictionary.service"; MultiSchemaTypeComponent, ForeignkeyTypeComponent, HiddenTypeComponent, - DictionaryTypeComponent + DictionaryTypeComponent, + RichtextTypeComponent ], providers: [ JsonschemasService, @@ -63,9 +67,11 @@ import { DictionaryService } from "./types/dictionary.service"; { name: 'foreign-key', component: ForeignkeyTypeComponent }, { name: 'hidden', component: HiddenTypeComponent }, { name: 'dictionary', component: DictionaryTypeComponent }, + { name: 'richtext', component: RichtextTypeComponent }, ] }), - FormlyBootstrapModule + FormlyBootstrapModule, + EditorModule ], exports: [ CardComponent, diff --git a/front/app/src/common/crud/types/richtext.type.ts b/front/app/src/common/crud/types/richtext.type.ts new file mode 100644 index 00000000..33651ba5 --- /dev/null +++ b/front/app/src/common/crud/types/richtext.type.ts @@ -0,0 +1,109 @@ +import {Component, OnInit} from "@angular/core"; +import { FormlyFieldInput } from "@ngx-formly/bootstrap/input"; + +@Component({ + selector: 'formly-richtext-type', + template: ` + + + + + +
+
+
+ + + + + + +
+ +
+ {{ props.description }} + + `, +}) +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>/); + if (result) { + param.event.content = result[1]; + } + } + } + + onBeforeAddUndo(param: any) { + if (!this.multiline) { + if (param.event.level.content.indexOf('

') > -1) { + param.event.preventDefault() + param.editor.setContent(param.event.level.content.replace('

', '')); + } + } + } + + + +} \ No newline at end of file