[IMP] web, *: add supportedOptions documentation as field metadata
*: mail, mass_mailing, sms, web_editor This commit adds a new supportedOptions attribute that can be added to any field widget metadata object. This documentation can be used from other places (Studio for example) by getting the field from the registry and then read this key. This attribute can contain an array, detailing the list of available options for the field widget. By using an array, it can be ordered easily without having an object with keys unalphabetically. Ordering the options can make sense, especially when two options are tied to each other, it is easier to group them one after the other. (eg: 'start_date' first, then 'end_date') Each option documented is an object and has the following attributes: - help: contains more details on the current option and its use - name: name used in the options object from the node - label: a label with a more explicit name than the option name - type: the type of value that must be used as a value (string, boolean, selection, field, domain) - choices: for options with a 'selection': can be used to know available values where multiple values can be chosen as the value. This must be an array containing the options. - availableTypes: for options with a 'field' selection: can be used to filter the available fieldNames to choose as a value. - default: the value that is used by default, when the option is not set in the options task-3259617 closes odoo/odoo#118713 Related: odoo/enterprise#39847 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
+9
@@ -1,5 +1,6 @@
|
||||
/* @odoo-module */
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import {
|
||||
Many2OneAvatarField,
|
||||
@@ -84,6 +85,14 @@ export const kanbanMany2OneAvatarUserField = {
|
||||
...kanbanMany2OneAvatarField,
|
||||
component: KanbanMany2OneAvatarUserField,
|
||||
additionalClasses: [...kanbanMany2OneAvatarField.additionalClasses, "o_field_many2one_avatar"],
|
||||
supportedOptions: [
|
||||
...(kanbanMany2OneAvatarField.supportedOptions || []),
|
||||
{
|
||||
label: _lt("Display avatar name"),
|
||||
name: "display_avatar_name",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
extractProps({ options }) {
|
||||
const props = kanbanMany2OneAvatarField.extractProps(...arguments);
|
||||
props.displayAvatarName = options.display_avatar_name || false;
|
||||
|
||||
@@ -604,6 +604,11 @@ export const massMailingHtmlField = {
|
||||
...htmlField,
|
||||
component: MassMailingHtmlField,
|
||||
displayName: _lt("Email"),
|
||||
supportedOptions: [...htmlField.supportedOptions, {
|
||||
label: _lt("Filter templates"),
|
||||
name: "filterTemplates",
|
||||
type: "boolean"
|
||||
}],
|
||||
extractProps({ attrs, options }) {
|
||||
const props = htmlField.extractProps(...arguments);
|
||||
props.filterTemplates = options.filterTemplates;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { PhoneField, phoneField, formPhoneField } from "@web/views/fields/phone/phone_field";
|
||||
import { SendSMSButton } from '@sms/components/sms_button/sms_button';
|
||||
@@ -25,6 +26,12 @@ const patchDescr = {
|
||||
props.enableButton = options.enable_sms;
|
||||
return props;
|
||||
},
|
||||
supportedOptions: [{
|
||||
label: _lt("Enable SMS"),
|
||||
name: "enable_sms",
|
||||
type: "boolean",
|
||||
default: true,
|
||||
}],
|
||||
};
|
||||
|
||||
patch(phoneField, "sms.PhoneField", patchDescr);
|
||||
|
||||
@@ -69,7 +69,14 @@ export class AceField extends Component {
|
||||
export const aceField = {
|
||||
component: AceField,
|
||||
displayName: _lt("Ace Editor"),
|
||||
supportedTypes: ["text"],
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Mode"),
|
||||
name: "mode",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["text", "html"],
|
||||
extractProps: ({ options }) => ({
|
||||
mode: options.mode,
|
||||
}),
|
||||
|
||||
@@ -68,6 +68,13 @@ export class BinaryField extends Component {
|
||||
export const binaryField = {
|
||||
component: BinaryField,
|
||||
displayName: _lt("File"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Accepted file extensions"),
|
||||
name: "accepted_file_extensions",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["binary"],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
acceptedFileExtensions: options.accepted_file_extensions,
|
||||
|
||||
@@ -24,6 +24,13 @@ export class BooleanIconField extends Component {
|
||||
export const booleanIconField = {
|
||||
component: BooleanIconField,
|
||||
displayName: _lt("Boolean Icon"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Icon"),
|
||||
name: "icon",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["boolean"],
|
||||
extractProps: ({ options, string }) => ({
|
||||
icon: options.icon,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { loadJS } from "@web/core/assets";
|
||||
import { luxonToMoment, momentToLuxon } from "@web/core/l10n/dates";
|
||||
@@ -157,6 +158,29 @@ export class DateRangeField extends Component {
|
||||
|
||||
export const dateRangeField = {
|
||||
component: DateRangeField,
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Format type"),
|
||||
name: "format_type",
|
||||
type: "selection",
|
||||
choices: [
|
||||
{ value: "date", label: _lt("Date") },
|
||||
{ value: "datetime", label: _lt("Datetime") },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: _lt("Related Start Date"),
|
||||
name: "related_start_date",
|
||||
type: "field",
|
||||
availableTypes: ["date", "datetime"],
|
||||
},
|
||||
{
|
||||
label: _lt("Related End Date"),
|
||||
name: "related_end_date",
|
||||
type: "field",
|
||||
availableTypes: ["date", "datetime"],
|
||||
},
|
||||
],
|
||||
supportedTypes: ["date", "datetime"],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
relatedEndDateField: options.related_end_date,
|
||||
|
||||
@@ -148,6 +148,18 @@ export class DomainField extends Component {
|
||||
export const domainField = {
|
||||
component: DomainField,
|
||||
displayName: _lt("Domain"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Edit in dialog"),
|
||||
name: "in_dialog",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Model"),
|
||||
name: "model",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["char"],
|
||||
isEmpty: () => false,
|
||||
extractProps({ options }, dynamicInfo) {
|
||||
|
||||
@@ -55,6 +55,23 @@ export class FloatField extends Component {
|
||||
export const floatField = {
|
||||
component: FloatField,
|
||||
displayName: _lt("Float"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Digits"),
|
||||
name: "digits",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Type"),
|
||||
name: "type",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Step"),
|
||||
name: "step",
|
||||
type: "number",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["float"],
|
||||
isEmpty: () => false,
|
||||
extractProps: ({ attrs, options }) => {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { registry } from "@web/core/registry";
|
||||
import { floatField, FloatField } from "../float/float_field";
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
|
||||
export class FloatFactorField extends FloatField {
|
||||
static props = {
|
||||
@@ -29,6 +30,14 @@ export class FloatFactorField extends FloatField {
|
||||
export const floatFactorField = {
|
||||
...floatField,
|
||||
component: FloatFactorField,
|
||||
supportedOptions: [
|
||||
...floatField.supportedOptions,
|
||||
{
|
||||
label: _lt("Factor"),
|
||||
name: "factor",
|
||||
type: "number",
|
||||
},
|
||||
],
|
||||
extractProps({ options }) {
|
||||
const props = floatField.extractProps(...arguments);
|
||||
props.factor = options.factor;
|
||||
|
||||
@@ -38,6 +38,13 @@ export class FloatTimeField extends Component {
|
||||
export const floatTimeField = {
|
||||
component: FloatTimeField,
|
||||
displayName: _lt("Time"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Type"),
|
||||
name: "type",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["float"],
|
||||
isEmpty: () => false,
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { formatFloatFactor } from "../formatters";
|
||||
import { standardFieldProps } from "../standard_field_props";
|
||||
@@ -55,6 +56,33 @@ export class FloatToggleField extends Component {
|
||||
|
||||
export const floatToggleField = {
|
||||
component: FloatToggleField,
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Digits"),
|
||||
name: "digits",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Type"),
|
||||
name: "type",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Range"),
|
||||
name: "range",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Factor"),
|
||||
name: "factor",
|
||||
type: "number",
|
||||
},
|
||||
{
|
||||
label: _lt("Disable readonly"),
|
||||
name: "force_button",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["float"],
|
||||
isEmpty: () => false,
|
||||
extractProps: ({ attrs, options }) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { _lt, _t } from "@web/core/l10n/translation";
|
||||
import { loadJS } from "@web/core/assets";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { formatFloat } from "@web/views/fields/formatters";
|
||||
@@ -97,6 +97,19 @@ GaugeField.props = {
|
||||
|
||||
export const gaugeField = {
|
||||
component: GaugeField,
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Title"),
|
||||
name: "title",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Max value field"),
|
||||
name: "max_value",
|
||||
type: "field",
|
||||
availableTypes: ["integer", "float"],
|
||||
},
|
||||
],
|
||||
extractProps: ({ options }) => ({
|
||||
maxValueField: options.max_field,
|
||||
title: options.title,
|
||||
|
||||
@@ -140,6 +140,40 @@ export class ImageField extends Component {
|
||||
export const imageField = {
|
||||
component: ImageField,
|
||||
displayName: _lt("Image"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Enable zoom"),
|
||||
name: "zoom",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Zoom delay"),
|
||||
name: "zoom_delay",
|
||||
type: "number",
|
||||
help: _lt("Delay the apparition of the zoomed image with a value in milliseconds"),
|
||||
},
|
||||
{
|
||||
label: _lt("Accepted file extensions"),
|
||||
name: "accepted_file_extensions",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Size"),
|
||||
name: "size",
|
||||
type: "selection",
|
||||
choices: [
|
||||
{ label: _lt("Small"), value: "[0,90]" },
|
||||
{ label: _lt("Medium"), value: "[0,180]" },
|
||||
{ label: _lt("Large"), value: "[0,270]" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: _lt("Preview image"),
|
||||
name: "preview_image",
|
||||
type: "field",
|
||||
availableTypes: ["binary"],
|
||||
},
|
||||
],
|
||||
supportedTypes: ["binary"],
|
||||
fieldDependencies: [{ name: "write_date", type: "datetime" }],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
|
||||
@@ -52,6 +52,18 @@ export class ImageUrlField extends Component {
|
||||
export const imageUrlField = {
|
||||
component: ImageUrlField,
|
||||
displayName: _lt("Image"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Size"),
|
||||
name: "size",
|
||||
type: "selection",
|
||||
choices: [
|
||||
{ label: _lt("Small"), value: "[0,90]" },
|
||||
{ label: _lt("Medium"), value: "[0,180]" },
|
||||
{ label: _lt("Large"), value: "[0,270]" },
|
||||
],
|
||||
},
|
||||
],
|
||||
supportedTypes: ["char"],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
width: options.size ? options.size[0] : attrs.width,
|
||||
|
||||
@@ -42,6 +42,18 @@ export class IntegerField extends Component {
|
||||
export const integerField = {
|
||||
component: IntegerField,
|
||||
displayName: _lt("Integer"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Type"),
|
||||
name: "type",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Step"),
|
||||
name: "step",
|
||||
type: "number",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["integer"],
|
||||
isEmpty: (record, fieldName) => record.data[fieldName] === false,
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { standardFieldProps } from "../standard_field_props";
|
||||
@@ -62,6 +63,13 @@ export class Many2ManyBinaryField extends Component {
|
||||
|
||||
export const many2ManyBinaryField = {
|
||||
component: Many2ManyBinaryField,
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Accepted file extensions"),
|
||||
name: "accepted_file_extensions",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["many2many"],
|
||||
isEmpty: () => false,
|
||||
relatedFields: [
|
||||
|
||||
@@ -255,6 +255,18 @@ export class Many2ManyTagsField extends Component {
|
||||
export const many2ManyTagsField = {
|
||||
component: Many2ManyTagsField,
|
||||
displayName: _lt("Tags"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Disable creation"),
|
||||
name: "no_create",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Use colors"),
|
||||
name: "color_field",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["many2many"],
|
||||
isSet: (value) => value.count > 0,
|
||||
relatedFields: ({ options }) => {
|
||||
@@ -358,6 +370,14 @@ export class Many2ManyTagsFieldColorEditable extends Many2ManyTagsField {
|
||||
export const many2ManyTagsFieldColorEditable = {
|
||||
...many2ManyTagsField,
|
||||
component: Many2ManyTagsFieldColorEditable,
|
||||
supportedOptions: [
|
||||
...many2ManyTagsField.supportedOptions,
|
||||
{
|
||||
label: _lt("Prevent color edition"),
|
||||
name: "no_edit_color",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
extractProps({ options }) {
|
||||
const props = many2ManyTagsField.extractProps(...arguments);
|
||||
props.canEditColor = !options.no_edit_color && !!options.color_field;
|
||||
|
||||
@@ -310,6 +310,28 @@ export class Many2OneField extends Component {
|
||||
export const many2OneField = {
|
||||
component: Many2OneField,
|
||||
displayName: _lt("Many2one"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Disable creation"),
|
||||
name: "no_create",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Disable opening"),
|
||||
name: "no_opening",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("No quick create"),
|
||||
name: "no_quick_create",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("No create edit"),
|
||||
name: "no_create_edit",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["many2one"],
|
||||
extractProps({ attrs, decorations, options, string }, dynamicInfo) {
|
||||
const canCreate =
|
||||
|
||||
@@ -148,6 +148,30 @@ export class ProgressBarField extends Component {
|
||||
export const progressBarField = {
|
||||
component: ProgressBarField,
|
||||
displayName: _lt("Progress Bar"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Editable"),
|
||||
name: "editable",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Edit max value"),
|
||||
name: "edit_max_value",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Current value field"),
|
||||
name: "current_value",
|
||||
type: "field",
|
||||
availableTypes: ["integer", "float"],
|
||||
},
|
||||
{
|
||||
label: _lt("Max value field"),
|
||||
name: "max_value",
|
||||
type: "field",
|
||||
availableTypes: ["integer", "float"],
|
||||
},
|
||||
],
|
||||
supportedTypes: ["integer", "float"],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
maxValueField: options.max_value,
|
||||
@@ -156,7 +180,7 @@ export const progressBarField = {
|
||||
isCurrentValueEditable: options.editable && !options.edit_max_value,
|
||||
isMaxValueEditable: options.editable && options.edit_max_value,
|
||||
title: attrs.title,
|
||||
overflowClass: options.overflow_class || 'bg-secondary',
|
||||
overflowClass: options.overflow_class || "bg-secondary",
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@@ -70,6 +70,13 @@ export class RadioField extends Component {
|
||||
export const radioField = {
|
||||
component: RadioField,
|
||||
displayName: _lt("Radio"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Display horizontally"),
|
||||
name: "horizontal",
|
||||
type: "boolean",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["many2one", "selection"],
|
||||
isEmpty: (record, fieldName) => record.data[fieldName] === false,
|
||||
extractProps: ({ options, string }) => ({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { _lt } from "@web/core/l10n/translation";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { SignatureDialog } from "@web/core/signature/signature_dialog";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
@@ -137,6 +138,36 @@ export class SignatureField extends Component {
|
||||
|
||||
export const signatureField = {
|
||||
component: SignatureField,
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Prefill with"),
|
||||
name: "full_name",
|
||||
type: "field",
|
||||
availableTypes: ["char", "many2one"],
|
||||
help: _lt("The selected field will be used to pre-fill the signature"),
|
||||
},
|
||||
{
|
||||
label: _lt("Default font"),
|
||||
name: "default_font",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
label: _lt("Size"),
|
||||
name: "size",
|
||||
type: "selection",
|
||||
choices: [
|
||||
{ label: _lt("Small"), value: "[0,90]" },
|
||||
{ label: _lt("Medium"), value: "[0,180]" },
|
||||
{ label: _lt("Large"), value: "[0,270]" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: _lt("Preview image field"),
|
||||
name: "preview_image",
|
||||
type: "field",
|
||||
availableTypes: ["binary"],
|
||||
},
|
||||
],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
defaultFont: options.default_font || "",
|
||||
fullName: options.full_name,
|
||||
|
||||
@@ -221,6 +221,18 @@ export class StatusBarField extends Component {
|
||||
export const statusBarField = {
|
||||
component: StatusBarField,
|
||||
displayName: _lt("Status"),
|
||||
supportedOptions: [
|
||||
{
|
||||
label: _lt("Clickable"),
|
||||
name: "clickable",
|
||||
type: "boolean",
|
||||
},
|
||||
{
|
||||
label: _lt("Fold field"),
|
||||
name: "fold_field",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
supportedTypes: ["many2one", "selection"],
|
||||
isEmpty: (record, fieldName) => record.model.env.isSmall && !record.data[fieldName],
|
||||
legacySpecialData: "_fetchSpecialStatus",
|
||||
|
||||
@@ -646,6 +646,48 @@ HtmlField.props = {
|
||||
export const htmlField = {
|
||||
component: HtmlField,
|
||||
displayName: _lt("Html"),
|
||||
supportedOptions: [{
|
||||
label: _lt("CSS Edit"),
|
||||
name: "cssEdit",
|
||||
type: "string"
|
||||
}, {
|
||||
label: _lt("Height"),
|
||||
name: "height",
|
||||
type: "string"
|
||||
}, {
|
||||
label: _lt("Min height"),
|
||||
name: "minHeight",
|
||||
type: "string"
|
||||
}, {
|
||||
label: _lt("Max height"),
|
||||
name: "maxHeight",
|
||||
type: "string"
|
||||
}, {
|
||||
label: _lt("Snippets"),
|
||||
name: "snippets",
|
||||
type: "string"
|
||||
}, {
|
||||
label: _lt("No videos"),
|
||||
name: "noVideos",
|
||||
type: "boolean",
|
||||
default: true
|
||||
}, {
|
||||
label: _lt("Resizable"),
|
||||
name: "resizable",
|
||||
type: "boolean",
|
||||
}, {
|
||||
label: _lt("Dynamic placeholder"),
|
||||
name: "dynamic_placeholder",
|
||||
type: "boolean",
|
||||
}, {
|
||||
label: _lt("Collaborative"),
|
||||
name: "collaborative",
|
||||
type: "boolean",
|
||||
}, {
|
||||
label: _lt("Codeview"),
|
||||
name: "codeview",
|
||||
type: "boolean",
|
||||
}],
|
||||
supportedTypes: ["html"],
|
||||
extractProps({ attrs, options }, dynamicInfo) {
|
||||
const wysiwygOptions = {
|
||||
|
||||
Reference in New Issue
Block a user