Skip to content

fix tour test_link_to_document #4767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
21 changes: 18 additions & 3 deletions addons/html_builder/static/src/core/core_builder_action_plugin.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Plugin } from "@html_editor/plugin";
import { CSS_SHORTHANDS, applyNeededCss, areCssValuesEqual } from "@html_builder/utils/utils_css";
import {
CSS_SHORTHANDS,
applyNeededCss,
areCssValuesEqual,
normalizeColor,
} from "@html_builder/utils/utils_css";

export function withoutTransition(editingElement, callback) {
if (editingElement.classList.contains("o_we_force_no_transition")) {
Expand Down Expand Up @@ -263,17 +268,27 @@ const attributeAction = {
};

const dataAttributeAction = {
getValue: ({ editingElement, params: { mainParam: attributeName } = {} }) =>
editingElement.dataset[attributeName],
// if it's a color action, we have to normalize the value
getValue: ({ editingElement, params: { mainParam: attributeName } = {} }) => {
if (!/(^color|Color)($|(?=[A-Z]))/.test(attributeName)) {
return editingElement.dataset[attributeName];
}
const color = normalizeColor(editingElement.dataset[attributeName]);
return color;
},
isApplied: ({ editingElement, params: { mainParam: attributeName } = {}, value }) => {
if (value) {
const match = value.match(/^var\(--(.*)\)$/);
value = match ? match[1] : value;
return editingElement.dataset[attributeName] === value;
} else {
return !(attributeName in editingElement.dataset);
}
},
apply: ({ editingElement, params: { mainParam: attributeName } = {}, value }) => {
if (value) {
const match = value.match(/^var\(--(.*)\)$/);
value = match ? match[1] : value;
editingElement.dataset[attributeName] = value;
} else {
delete editingElement.dataset[attributeName];
Expand Down
3 changes: 2 additions & 1 deletion addons/html_builder/static/src/core/setup_editor_plugin.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Plugin } from "@html_editor/plugin";
import { _t } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { withSequence } from "@html_editor/utils/resource";

export class SetupEditorPlugin extends Plugin {
static id = "setup_editor_plugin";
static shared = ["getEditableAreas"];
resources = {
clean_for_save_handlers: this.cleanForSave.bind(this),
normalize_handlers: this.setContenteditable.bind(this),
normalize_handlers: withSequence(0, this.setContenteditable.bind(this)),
};

setup() {
Expand Down
7 changes: 5 additions & 2 deletions addons/html_builder/static/src/snippets/snippet_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,12 @@ export class SnippetViewer extends Component {
}
if (this.props.state.search) {
const strMatches = (str) =>
str.toLowerCase().includes(this.props.state.search.toLowerCase());
str ? str.toLowerCase().includes(this.props.state.search.toLowerCase()) : false;
return snippetStructures.filter(
(snippet) => strMatches(snippet.title) || strMatches(snippet.keyWords || "")
(snippet) =>
strMatches(snippet.name) ||
strMatches(snippet.title) ||
strMatches(snippet.keyWords)
);
}

Expand Down
8 changes: 5 additions & 3 deletions addons/html_editor/static/src/main/font/color_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
rgbaToHex,
COLOR_COMBINATION_CLASSES_REGEX,
} from "@web/core/utils/colors";
import { backgroundImageCssToParts } from "@html_editor/utils/image";
import { ColorSelector } from "./color_selector";

const RGBA_OPACITY = 0.6;
Expand Down Expand Up @@ -136,7 +137,8 @@ export class ColorPlugin extends Plugin {
getElementColors(el) {
const elStyle = getComputedStyle(el);
const backgroundImage = elStyle.backgroundImage;
const hasGradient = isColorGradient(backgroundImage);
const gradient = backgroundImageCssToParts(backgroundImage).gradient;
const hasGradient = isColorGradient(gradient);
const hasTextGradientClass = el.classList.contains("text-gradient");

let backgroundColor = elStyle.backgroundColor;
Expand All @@ -155,9 +157,9 @@ export class ColorPlugin extends Plugin {
}

return {
color: hasGradient && hasTextGradientClass ? backgroundImage : rgbaToHex(elStyle.color),
color: hasGradient && hasTextGradientClass ? gradient : rgbaToHex(elStyle.color),
backgroundColor:
hasGradient && !hasTextGradientClass ? backgroundImage : rgbaToHex(backgroundColor),
hasGradient && !hasTextGradientClass ? gradient : rgbaToHex(backgroundColor),
};
}

Expand Down
1 change: 0 additions & 1 deletion addons/html_editor/static/src/main/link/link_popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ export class LinkPopover extends Component {
this.state.url = deducedUrl
? this.correctLink(deducedUrl)
: this.correctLink(this.state.url);
this.loadAsyncLinkPreview();
}
onClickEdit() {
this.state.editing = true;
Expand Down
8 changes: 4 additions & 4 deletions addons/html_editor/static/src/main/media/image_crop_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export class ImageCropPlugin extends Plugin {
onSave: async (newDataset) => {
// todo: should use the mutex if there is one?
const updateImageAttributes =
await this.dependencies.imagePostProcess.processImage(
selectedImg,
newDataset
);
await this.dependencies.imagePostProcess.processImage({
img: selectedImg,
newDataset,
});
updateImageAttributes();
this.dependencies.history.addStep();
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ export class ImagePostProcessPlugin extends Plugin {
*
* @param {HTMLImageElement} img the image to which modifications are applied
* @param {Object} newDataset an object containing the modifications to apply
* @param {Function} [onImageInfoLoaded] can be used to fill
* newDataset after having access to image info, return true to cancel call
* @returns {Function} callback that sets dataURL of the image with the
* applied modifications to `img` element
*/
async processImage(img, newDataset = {}) {
async processImage({ img, newDataset = {}, onImageInfoLoaded }) {
const processContext = {};
if (!newDataset.originalSrc || !newDataset.mimetypeBeforeConversion) {
Object.assign(newDataset, await loadImageInfo(img));
}
if (onImageInfoLoaded) {
if (await onImageInfoLoaded(newDataset)) {
return () => {};
}
}
for (const cb of this.getResource("process_image_warmup_handlers")) {
const addedContext = await cb(img, newDataset);
if (addedContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export class ImageSelector extends FileSelector {

this.fileMimetypes = IMAGE_MIMETYPES.join(",");
this.isImageField =
!!this.props.media?.closest("[data-oe-type=image]") || !!this.env.addFieldImage;
!!this.props.media?.closest("[data-oe-type=image]") || !!this.props.addFieldImage;
}

get canLoadMore() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export class MediaDialog extends Component {
this.addTab(TABS.IMAGES, {
useMediaLibrary: this.props.useMediaLibrary,
multiSelect: this.props.multiImages,
addFieldImage: this.props.addFieldImage,
});
}
if (!noIcons) {
Expand Down
22 changes: 16 additions & 6 deletions addons/html_editor/static/src/main/media/media_plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,12 @@ export class MediaPlugin extends Plugin {
}
}

onSaveMediaDialog(element, { node }) {
async onSaveMediaDialog(element, { node }) {
if (!element) {
// @todo @phoenix to remove
throw new Error("Element is required: onSaveMediaDialog");
// return;
}

if (node) {
const changedIcon = isIconElement(node) && isIconElement(element);
if (changedIcon) {
Expand All @@ -151,11 +150,25 @@ export class MediaPlugin extends Plugin {
// Collapse selection after the inserted/replaced element.
const [anchorNode, anchorOffset] = rightPos(element);
this.dependencies.selection.setSelection({ anchorNode, anchorOffset });
this.delegateTo("afer_save_media_dialog_handlers", element);
this.delegateTo("after_save_media_dialog_handlers", element);
this.dependencies.history.addStep();
}

openMediaDialog(params = {}, editableEl = null) {
const oldSave =
params.save || ((element) => this.onSaveMediaDialog(element, { node: params.node }));
params.save = async (...args) => {
const selection = args[0];
const elements = selection
? selection[Symbol.iterator]
? selection
: [selection]
: [];
for (const onMediaDialogSaved of this.getResource("on_media_dialog_saved_handlers")) {
await onMediaDialogSaved(elements, { node: params.node });
}
return oldSave(...args);
};
const { resModel, resId, field, type } = this.getRecordInfo(editableEl);
const mediaDialogClosedPromise = this.dependencies.dialog.addDialog(MediaDialog, {
resModel,
Expand All @@ -165,9 +178,6 @@ export class MediaPlugin extends Plugin {
((resModel === "ir.ui.view" && field === "arch") || type === "html")
), // @todo @phoenix: should be removed and moved to config.mediaModalParams
media: params.node,
save: (element) => {
this.onSaveMediaDialog(element, { node: params.node });
},
onAttachmentChange: this.config.onAttachmentChange || (() => {}),
noVideos: !this.config.allowMediaDialogVideo,
noImages: !this.config.allowImage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class CaptionPlugin extends Plugin {
clean_for_save_handlers: this.cleanForSave.bind(this),
mount_component_handlers: this.setupNewCaption.bind(this),
delete_image_handlers: this.handleDeleteImage.bind(this),
afer_save_media_dialog_handlers: this.onImageReplaced.bind(this),
after_save_media_dialog_handlers: this.onImageReplaced.bind(this),
hints: [{ selector: "FIGCAPTION", text: _t("Write a caption...") }],
unsplittable_node_predicates: [
(node) => ["FIGURE", "FIGCAPTION"].includes(node.nodeName), // avoid merge
Expand Down
12 changes: 6 additions & 6 deletions addons/test_website/static/tests/tours/image_upload_progress.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { insertSnippet, registerWebsitePreviewTour } from "@website/js/tours/tour_utils";

import { FileSelectorControlPanel } from "@web_editor/components/media_dialog/file_selector";
import { FileSelectorControlPanel } from "@html_editor/main/media/media_dialog/file_selector";
import { patch } from "@web/core/utils/patch";

let patchWithError = false;
Expand Down Expand Up @@ -72,7 +72,7 @@ registerWebsitePreviewTour('test_image_upload_progress', {
run: "click",
}, {
content: "click on add images to open image dialog (in multi mode)",
trigger: 'we-customizeblock-option [data-add-images]',
trigger: "button[data-action-id='addImage']",
run: "click",
}, {
content: "manually trigger input change",
Expand Down Expand Up @@ -123,7 +123,7 @@ registerWebsitePreviewTour('test_image_upload_progress', {
run: "click",
}, {
content: "click on replace media to open image dialog",
trigger: 'we-customizeblock-option [data-replace-media]',
trigger: "button[data-action-id='replaceMedia']",
run: "click",
}, {
content: "manually trigger input change",
Expand Down Expand Up @@ -162,7 +162,7 @@ registerWebsitePreviewTour('test_image_upload_progress', {
run: "click",
}, {
content: "click on replace media to open image dialog",
trigger: 'we-customizeblock-option [data-replace-media]',
trigger: "button[data-action-id='replaceMedia']",
run: "click",
}, {
content: "manually trigger input change",
Expand Down Expand Up @@ -206,7 +206,7 @@ registerWebsitePreviewTour('test_image_upload_progress_unsplash', {
run: "click",
}, {
content: "click on replace media to open image dialog",
trigger: 'we-customizeblock-option [data-replace-media]',
trigger: "button[data-action-id='replaceMedia']",
run: "click",
}, {
content: "search 'fox' images",
Expand All @@ -230,7 +230,7 @@ registerWebsitePreviewTour('test_image_upload_progress_unsplash', {
run: "click",
}, {
content: "unsplash image (mocked to logo) should have been used",
trigger: ":iframe #wrap .s_image_gallery .img[data-original-src^='/unsplash/HQqIOc8oYro/fox']",
trigger: ":iframe #wrap .s_image_gallery img[src^='/unsplash/HQqIOc8oYro/fox']",
run() {
unpatchMediaDialog();
},
Expand Down
3 changes: 2 additions & 1 deletion addons/test_website/static/tests/tours/reset_views.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ registerWebsitePreviewTour(
() => [
{
content: "Drag the Intro snippet group and drop it in #oe_structure_test_website_page.",
trigger: '#oe_snippets .oe_snippet[name="Intro"] .oe_snippet_thumbnail:not(.o_we_ongoing_insertion)',
trigger:
"#snippet_groups .o_snippet[name='Intro'] .o_snippet_thumbnail:not(.o_we_ongoing_insertion) .o_snippet_thumbnail_area",
// id starting by 'oe_structure..' will actually create an inherited view
run: "drag_and_drop :iframe #oe_structure_test_website_page",
},
Expand Down
3 changes: 0 additions & 3 deletions addons/test_website/tests/test_image_upload_progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
from odoo import http
import unittest


# TODO master-mysterious-egg fix error
@unittest.skip("prepare mysterious-egg for merging")
@odoo.tests.common.tagged('post_install', '-at_install')
class TestImageUploadProgress(odoo.tests.HttpCase):

Expand Down
2 changes: 0 additions & 2 deletions addons/test_website/tests/test_reset_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ def test_06_reset_specific_view_controller_inexisting_template(self):
self.assertEqual(total_views + 1, self.View.search_count([('type', '=', 'qweb')]), "Missing COW view (2)")
self.fix_it('/test_view')

# TODO master-mysterious-egg fix error
@unittest.skip("prepare mysterious-egg for merging")
@mute_logger('odoo.http')
def test_07_reset_page_view_complete_flow(self):
self.start_tour(self.env['website'].get_client_action_url('/test_page_view'), 'test_reset_page_view_complete_flow_part1', login="admin")
Expand Down
3 changes: 1 addition & 2 deletions addons/test_website/tests/test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@

@odoo.tests.tagged('-at_install', 'post_install')
class TestWebsiteSettings(odoo.tests.HttpCase):
# TODO master-mysterious-egg fix error
@unittest.skip("prepare mysterious-egg for merging")

def test_01_multi_website_settings(self):
# If not enabled (like in demo data), landing on res.config will try
# to disable module_sale_quotation_builder and raise an issue
Expand Down
10 changes: 10 additions & 0 deletions addons/web/static/src/core/utils/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ export function convertCSSColorToRgba(cssColor) {
}

// Otherwise, check if cssColor is an hexadecimal code color
// first check if it's in its compact form (e.g. #FFF)
if (/^#([0-9a-f]{3})$/i.test(cssColor)) {
return {
red: parseInt(cssColor[1] + cssColor[1], 16),
green: parseInt(cssColor[2] + cssColor[2], 16),
blue: parseInt(cssColor[3] + cssColor[3], 16),
opacity: 100,
};
}

if (/^#([0-9A-F]{6}|[0-9A-F]{8})$/i.test(cssColor)) {
return {
red: parseInt(cssColor.substr(1, 2), 16),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class BackgroundImageOptionPlugin extends Plugin {
editingElement.querySelector(".o_we_bg_filter")?.remove();
this.applyReplaceBackgroundImage.bind(this)({
editingElement: editingElement,
loadResult: "",
loadResult: undefined,
params: { forceClean: true },
});
this.dispatchTo("on_bg_image_hide_handlers", editingElement);
Expand Down Expand Up @@ -134,31 +134,38 @@ export class BackgroundImageOptionPlugin extends Plugin {
newEditingEl.classList.toggle("o_modified_image_to_save", isModifiedImage);
}
}
loadReplaceBackgroundImage() {
loadReplaceBackgroundImage({ editingElement }) {
return new Promise((resolve) => {
const onClose = this.dependencies.media.openMediaDialog({
onlyImages: true,
save: (imageEl) => {
resolve(imageEl.getAttribute("src"));
node: editingElement,
save: async (imageEl) => {
resolve(imageEl);
},
});
onClose.then(resolve);
});
}
applyReplaceBackgroundImage({
editingElement,
loadResult: imageSrc,
loadResult: imageEl,
params: { forceClean = false },
}) {
if (!forceClean && !imageSrc) {
if (!forceClean && !imageEl) {
// Do nothing: no images has been selected on the media dialog
return;
}
this.setImageBackground(editingElement, imageSrc);
const src = imageEl?.src || "";
this.setImageBackground(editingElement, src);
for (const attr of removeOnImageChangeAttrs) {
delete editingElement.dataset[attr];
}
// TODO: call _autoOptimizeImage of the ImageHandlersOption
if (imageEl) {
if (src.startsWith("data:")) {
editingElement.classList.add("o_modified_image_to_save");
}
Object.assign(editingElement.dataset, imageEl.dataset);
}
}
/**
*
Expand Down
Loading