[IMP] web, web_editor: knowledge file command overhaul preparations
- Allow providing a custom `MediaDialog` class through `openMediaDialog` to allow Knowledge custom behaviors. - Export the rendering part of `save` for the `MediaDialog` so it can be overridden. task-3172056 Part-of: odoo/odoo#127021
This commit is contained in:
@@ -132,6 +132,91 @@ export class MediaDialog extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the selected media for insertion in the editor
|
||||
*
|
||||
* @param {Array<Object>} selectedMedia
|
||||
* @returns {Array<HTMLElement>}
|
||||
*/
|
||||
async renderMedia(selectedMedia) {
|
||||
const elements = await TABS[this.state.activeTab].Component.createElements(selectedMedia, { rpc: this.rpc, orm: this.orm });
|
||||
elements.forEach(element => {
|
||||
if (this.props.media) {
|
||||
element.classList.add(...this.props.media.classList);
|
||||
const style = this.props.media.getAttribute('style');
|
||||
if (style) {
|
||||
element.setAttribute('style', style);
|
||||
}
|
||||
if (this.state.activeTab === TABS.IMAGES.id) {
|
||||
if (this.props.media.dataset.shape) {
|
||||
element.dataset.shape = this.props.media.dataset.shape;
|
||||
}
|
||||
if (this.props.media.dataset.shapeColors) {
|
||||
element.dataset.shapeColors = this.props.media.dataset.shapeColors;
|
||||
}
|
||||
if (this.props.media.dataset.shapeFlip) {
|
||||
element.dataset.shapeFlip = this.props.media.dataset.shapeFlip;
|
||||
}
|
||||
if (this.props.media.dataset.shapeRotate) {
|
||||
element.dataset.shapeRotate = this.props.media.dataset.shapeRotate;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffect) {
|
||||
element.dataset.hoverEffect = this.props.media.dataset.hoverEffect;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectColor) {
|
||||
element.dataset.hoverEffectColor = this.props.media.dataset.hoverEffectColor;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectStrokeWidth) {
|
||||
element.dataset.hoverEffectStrokeWidth = this.props.media.dataset.hoverEffectStrokeWidth;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectIntensity) {
|
||||
element.dataset.hoverEffectIntensity = this.props.media.dataset.hoverEffectIntensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const otherTab of Object.keys(TABS).filter(key => key !== this.state.activeTab)) {
|
||||
for (const property of TABS[otherTab].Component.mediaSpecificStyles) {
|
||||
element.style.removeProperty(property);
|
||||
}
|
||||
element.classList.remove(...TABS[otherTab].Component.mediaSpecificClasses);
|
||||
const extraClassesToRemove = [];
|
||||
for (const name of TABS[otherTab].Component.mediaExtraClasses) {
|
||||
if (typeof(name) === 'string') {
|
||||
extraClassesToRemove.push(name);
|
||||
} else { // Regex
|
||||
for (const className of element.classList) {
|
||||
if (className.match(name)) {
|
||||
extraClassesToRemove.push(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove classes that do not also exist in the target type.
|
||||
element.classList.remove(...extraClassesToRemove.filter(candidateName => {
|
||||
for (const name of TABS[this.state.activeTab].Component.mediaExtraClasses) {
|
||||
if (typeof(name) === 'string') {
|
||||
if (candidateName === name) {
|
||||
return false;
|
||||
}
|
||||
} else { // Regex
|
||||
for (const className of element.classList) {
|
||||
if (className.match(candidateName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
element.classList.remove(...this.initialIconClasses);
|
||||
element.classList.remove('o_modified_image_to_save');
|
||||
element.classList.remove('oe_edited_link');
|
||||
element.classList.add(...TABS[this.state.activeTab].Component.mediaSpecificClasses);
|
||||
});
|
||||
return elements;
|
||||
}
|
||||
|
||||
selectMedia(media, tabId, multiSelect) {
|
||||
if (multiSelect) {
|
||||
const isMediaSelected = this.selectedMedia[tabId].map(({ id }) => id).includes(media.id);
|
||||
@@ -159,81 +244,7 @@ export class MediaDialog extends Component {
|
||||
const saveSelectedMedia = selectedMedia.length
|
||||
&& (this.state.activeTab !== TABS.ICONS.id || selectedMedia[0].initialIconChanged || !this.props.media);
|
||||
if (saveSelectedMedia) {
|
||||
const elements = await TABS[this.state.activeTab].Component.createElements(selectedMedia, { rpc: this.rpc, orm: this.orm });
|
||||
elements.forEach(element => {
|
||||
if (this.props.media) {
|
||||
element.classList.add(...this.props.media.classList);
|
||||
const style = this.props.media.getAttribute('style');
|
||||
if (style) {
|
||||
element.setAttribute('style', style);
|
||||
}
|
||||
if (this.state.activeTab === TABS.IMAGES.id) {
|
||||
if (this.props.media.dataset.shape) {
|
||||
element.dataset.shape = this.props.media.dataset.shape;
|
||||
}
|
||||
if (this.props.media.dataset.shapeColors) {
|
||||
element.dataset.shapeColors = this.props.media.dataset.shapeColors;
|
||||
}
|
||||
if (this.props.media.dataset.shapeFlip) {
|
||||
element.dataset.shapeFlip = this.props.media.dataset.shapeFlip;
|
||||
}
|
||||
if (this.props.media.dataset.shapeRotate) {
|
||||
element.dataset.shapeRotate = this.props.media.dataset.shapeRotate;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffect) {
|
||||
element.dataset.hoverEffect = this.props.media.dataset.hoverEffect;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectColor) {
|
||||
element.dataset.hoverEffectColor = this.props.media.dataset.hoverEffectColor;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectStrokeWidth) {
|
||||
element.dataset.hoverEffectStrokeWidth = this.props.media.dataset.hoverEffectStrokeWidth;
|
||||
}
|
||||
if (this.props.media.dataset.hoverEffectIntensity) {
|
||||
element.dataset.hoverEffectIntensity = this.props.media.dataset.hoverEffectIntensity;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const otherTab of Object.keys(TABS).filter(key => key !== this.state.activeTab)) {
|
||||
for (const property of TABS[otherTab].Component.mediaSpecificStyles) {
|
||||
element.style.removeProperty(property);
|
||||
}
|
||||
element.classList.remove(...TABS[otherTab].Component.mediaSpecificClasses);
|
||||
const extraClassesToRemove = [];
|
||||
for (const name of TABS[otherTab].Component.mediaExtraClasses) {
|
||||
if (typeof(name) === 'string') {
|
||||
extraClassesToRemove.push(name);
|
||||
} else { // Regex
|
||||
for (const className of element.classList) {
|
||||
if (className.match(name)) {
|
||||
extraClassesToRemove.push(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove classes that do not also exist in the target type.
|
||||
element.classList.remove(...extraClassesToRemove.filter(candidateName => {
|
||||
for (const name of TABS[this.state.activeTab].Component.mediaExtraClasses) {
|
||||
if (typeof(name) === 'string') {
|
||||
if (candidateName === name) {
|
||||
return false;
|
||||
}
|
||||
} else { // Regex
|
||||
for (const className of element.classList) {
|
||||
if (className.match(candidateName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
element.classList.remove(...this.initialIconClasses);
|
||||
element.classList.remove('o_modified_image_to_save');
|
||||
element.classList.remove('oe_edited_link');
|
||||
element.classList.add(...TABS[this.state.activeTab].Component.mediaSpecificClasses);
|
||||
});
|
||||
const elements = await this.renderMedia(selectedMedia);
|
||||
if (this.props.multiImages) {
|
||||
this.props.save(elements);
|
||||
} else {
|
||||
|
||||
@@ -1496,6 +1496,7 @@ export class Wysiwyg extends Component {
|
||||
* @param {object} params
|
||||
* @param {Node} [params.node] Optionnal
|
||||
* @param {Node} [params.htmlClass] Optionnal
|
||||
* @param {Class} [params.MediaDialog] Optional
|
||||
*/
|
||||
openMediaDialog(params = {}) {
|
||||
const sel = this.odooEditor.document.getSelection();
|
||||
@@ -1512,7 +1513,7 @@ export class Wysiwyg extends Component {
|
||||
const editable = OdooEditorLib.closestElement(params.node || range.startContainer, '.o_editable') || this.odooEditor.editable;
|
||||
const { resModel, resId, field, type } = this._getRecordInfo(editable);
|
||||
|
||||
this.env.services.dialog.add(MediaDialog, {
|
||||
this.env.services.dialog.add(params.MediaDialog || MediaDialog, {
|
||||
resModel,
|
||||
resId,
|
||||
useMediaLibrary: !!(field && (resModel === 'ir.ui.view' && field === 'arch' || type === 'html')),
|
||||
|
||||
Reference in New Issue
Block a user