收发文

This commit is contained in:
李鹏宇
2024-08-02 17:47:33 +08:00
parent a5d7c5978b
commit 78cde9a8b4
37 changed files with 587 additions and 264 deletions
+19
View File
@@ -0,0 +1,19 @@
{
'name': 'TinyMCE Editor',
'summary': 'TinyMCE Editor for Html Field',
'author': 'Hoang Minh Hieu',
'version': '17.0.1.0.0',
'license': 'OPL-1',
'support ': 'hieuhoangminh1996@gmail.com',
'depends': ['web'],
'assets': {
'web.assets_backend': [
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.scss',
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.xml',
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.js',
],
},
'images': ['static/description/main_screenshot.png'],
'price': 35,
'currency': 'USD',
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>This module replaces Odoo html editor with TinyMCE editor.</title>
</head>
<body>
<section class="mb64">
<h2 class="text-info">
This module replaces Odoo html editor with TinyMCE editor.
</h2>
</section>
<section class="mb64">
<h3>Screenshot</h3>
<img src="main_screenshot.png" class="w-75">
<h3>Usage</h3>
<img src="usage.png" class="w-50">
</section>
<section class="mb64">
<h2 class="">
Contact me
</h2>
<p>
Skype: <a href="skype:live:hieuhoangminh1996">live:hieuhoangminh1996</a>
<br>
Email: <a href="mailto:hieuhoangminh1996@gmail.com">hieuhoangminh1996@gmail.com</a>
<br>
<br>
Email subject should begin with
<span class="text-info font-weight-bold">[Odoo Module]</span>
</p>
</section>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,130 @@
/** @odoo-module **/
import {_t} from '@web/core/l10n/translation';
import {Component, onWillStart, onMounted, onPatched, onWillUnmount, useEffect} from '@odoo/owl';
import {standardFieldProps} from '@web/views/fields/standard_field_props';
import {registry} from '@web/core/registry';
import {TranslationButton} from '@web/views/fields/translation_button';
import {loadJS} from '@web/core/assets';
import {cookie} from '@web/core/browser/cookie';
export class FieldTinyMCE extends Component {
static template = 'web_editor_tinymce.TinyMCE';
static components = {
TranslationButton,
};
static props = {
...standardFieldProps,
placeholder: {type: String, optional: true},
dynamicPlaceholder: {type: Boolean, optional: true},
dynamicPlaceholderModelReferenceField: {type: String, optional: true},
};
static defaultProps = {
dynamicPlaceholder: false,
};
setup() {
super.setup();
this.editorId = `tinymce_${this.props.name}`
const useDarkMode = this.theme === 'dark';
this.defaultTinymceConfig = {
selector: `#${this.editorId}`,
plugins: 'autoresize preview importcss searchreplace autolink directionality code visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons accordion',
editimage_cors_hosts: ['picsum.photos'],
image_advtab: true,
importcss_append: true,
height: 'auto',
image_caption: true,
quickbars_selection_toolbar: 'bold italic | quicklink h2 h3 blockquote quickimage quicktable',
noneditable_class: 'mceNonEditable',
toolbar_mode: 'sliding',
contextmenu: 'link image table',
skin: useDarkMode ? 'oxide-dark' : 'oxide',
content_css: useDarkMode ? 'dark' : 'default',
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }',
placeholder: this.props.placeholder,
}
onWillStart(async () => {
await loadJS('web_editor_tinymce/static/lib/tinymce/tinymce.min.js');
});
onMounted(async () => {
await this.initEditor();
})
useEffect(() => {
this.updateEditor();
})
onWillUnmount(async () => {
this.removeEditor()
})
}
get value() {
return this.props.record.data[this.props.name] || '';
}
get theme() {
return cookie.get('color_scheme');
}
get isTranslatable() {
return this.props.record.fields[this.props.name].translate;
}
get tinymceConfig() {
return {
...this.defaultTinymceConfig,
menubar: !this.props.readonly && 'file edit view insert format tools table help',
toolbar: !this.props.readonly && 'undo redo | accordion accordionremove | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist | link image | table media | lineheight outdent indent| forecolor backcolor removeformat | charmap emoticons | code fullscreen preview | save print | pagebreak anchor codesample | ltr rtl',
readonly: this.props.readonly,
setup: this.setupEditor.bind(this),
init_instance_callback: this.initCallback.bind(this),
}
}
setupEditor(editor) {
editor.on('change', e => {
const value = tinymce.activeEditor.getContent();
if (value !== this.value) {
this.props.record.update({[this.props.name]: value})
}
});
}
removeEditor() {
if (this.editor) {
this.editor.remove()
}
}
async initEditor() {
this.removeEditor()
const config = this.tinymceConfig;
this.editor = (await tinymce.init(config))[0];
}
initCallback(editor) {
editor.setContent(this.value);
}
updateEditor() {
if (!this.editor || this.props.record.dirty) {
return
}
this.editor.setContent(this.value);
}
}
export const fieldTinyMCE = {
component: FieldTinyMCE,
displayName: _t('TinyMCE'),
supportedTypes: ['html', 'text'],
extractProps: ({attrs, options}) => ({
placeholder: attrs.placeholder,
dynamicPlaceholder: options?.dynamic_placeholder || false,
dynamicPlaceholderModelReferenceField:
options?.dynamic_placeholder_model_reference_field || '',
}),
}
registry.category('fields').add('tinymce', fieldTinyMCE);
@@ -0,0 +1,3 @@
.o_field_tinymce {
width: 100%;
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<template xml:space="preserve">
<t t-name="web_editor_tinymce.TinyMCE" owl="1">
<div class="tinymce_editor_container w-100 position-relative"
t-att-class="{'o_field_translate': isTranslatable}"
>
<textarea t-att-id="editorId" t-ref="input"/>
<span t-if="isTranslatable and !props.readonly"
class="position-absolute top-0 end-0 p-2"
style="z-index: 2;"
>
<TranslationButton
fieldName="props.name"
record="props.record"
/>
</span>
</div>
</t>
</template>