[IMP] web_editor, *: integrate new o_cc${xxx} classes in the colorpicker
*: website Part of https://github.com/odoo/odoo/pull/45856 task-2197038
This commit is contained in:
@@ -139,6 +139,33 @@ function _areCssValuesEqual(value1, value2, cssProp, $target) {
|
||||
const numValue2 = _convertValueToUnit(value2, data[1], cssProp, $target);
|
||||
return (Math.abs(numValue1 - numValue2) < Number.EPSILON);
|
||||
}
|
||||
/**
|
||||
* @param {string|number} name
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function _isColorCombinationName(name) {
|
||||
const number = parseInt(name);
|
||||
return (!isNaN(number) && number % 100 !== 0);
|
||||
}
|
||||
/**
|
||||
* @param {string[]} colorNames
|
||||
* @param {string} [prefix='bg-']
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function _computeColorClasses(colorNames, prefix = 'bg-') {
|
||||
let hasCCClasses = false;
|
||||
const classes = colorNames.map(c => {
|
||||
if (_isColorCombinationName(c)) {
|
||||
hasCCClasses = true;
|
||||
return `o_cc${c}`;
|
||||
}
|
||||
return (prefix + c);
|
||||
});
|
||||
if (hasCCClasses) {
|
||||
classes.push('o_cc');
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
return {
|
||||
CSS_SHORTHANDS: CSS_SHORTHANDS,
|
||||
@@ -148,5 +175,7 @@ return {
|
||||
convertNumericToUnit: _convertNumericToUnit,
|
||||
getNumericAndUnit: _getNumericAndUnit,
|
||||
areCssValuesEqual: _areCssValuesEqual,
|
||||
isColorCombinationName: _isColorCombinationName,
|
||||
computeColorClasses: _computeColorClasses,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1086,11 +1086,15 @@ const ColorpickerUserValueWidget = SelectUserValueWidget.extend({
|
||||
* @returns {Promise}
|
||||
*/
|
||||
_renderColorPalette: function () {
|
||||
const options = {};
|
||||
options.selectedColor = this._value;
|
||||
const options = {
|
||||
selectedColor: this._value,
|
||||
};
|
||||
if (this.options.dataAttributes.excluded) {
|
||||
options.excluded = this.options.dataAttributes.excluded.replace(/ /g, '').split(',');
|
||||
}
|
||||
if (this.options.dataAttributes.withCombinations) {
|
||||
options.withCombinations = !!this.options.dataAttributes.withCombinations;
|
||||
}
|
||||
const oldColorPalette = this.colorPalette;
|
||||
this.colorPalette = new ColorPaletteWidget(this, options);
|
||||
if (oldColorPalette) {
|
||||
@@ -1108,14 +1112,17 @@ const ColorpickerUserValueWidget = SelectUserValueWidget.extend({
|
||||
_updateUI: async function (color) {
|
||||
await this._super(...arguments);
|
||||
|
||||
this.colorPreviewEl.classList.remove(...this.colorPalette.getColorNames().map(c => 'bg-' + c));
|
||||
const classes = weUtils.computeColorClasses(this.colorPalette.getColorNames());
|
||||
this.colorPreviewEl.classList.remove(...classes);
|
||||
this.colorPreviewEl.style.removeProperty('background-color');
|
||||
|
||||
if (this._value) {
|
||||
if (ColorpickerWidget.isCSSColor(this._value)) {
|
||||
this.colorPreviewEl.style.backgroundColor = this._value;
|
||||
} else if (weUtils.isColorCombinationName(this._value)) {
|
||||
this.colorPreviewEl.classList.add('o_cc', `o_cc${this._value}`);
|
||||
} else {
|
||||
this.colorPreviewEl.classList.add('bg-' + this._value);
|
||||
this.colorPreviewEl.classList.add(`bg-${this._value}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,9 +1638,15 @@ const SnippetOptionWidget = Widget.extend({
|
||||
// other potential color names (to remove) and if we know about a prefix
|
||||
// (otherwise we suppose that we should use the actual related color).
|
||||
if (params.colorNames && params.colorPrefix) {
|
||||
const classes = params.colorNames.map(c => params.colorPrefix + c);
|
||||
const classes = weUtils.computeColorClasses(params.colorNames, params.colorPrefix);
|
||||
this.$target[0].classList.remove(...classes);
|
||||
|
||||
if (weUtils.isColorCombinationName(widgetValue)) {
|
||||
// Those are the special color combinations classes. Just have
|
||||
// to add it (and adding the potential extra class) then leave.
|
||||
this.$target[0].classList.add('o_cc', `o_cc${widgetValue}`, params.extraClass);
|
||||
return;
|
||||
}
|
||||
if (params.colorNames.includes(widgetValue)) {
|
||||
const originalCSSValue = window.getComputedStyle(this.$target[0])[cssProps[0]];
|
||||
const className = params.colorPrefix + widgetValue;
|
||||
@@ -1924,7 +1937,8 @@ const SnippetOptionWidget = Widget.extend({
|
||||
case 'selectStyle': {
|
||||
if (params.colorPrefix && params.colorNames) {
|
||||
for (const c of params.colorNames) {
|
||||
if (this.$target[0].classList.contains(params.colorPrefix + c)) {
|
||||
const className = weUtils.computeColorClasses([c], params.colorPrefix)[0];
|
||||
if (this.$target[0].classList.contains(className)) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ const session = require('web.session');
|
||||
const {ColorpickerWidget} = require('web.Colorpicker');
|
||||
const Widget = require('web.Widget');
|
||||
const summernoteCustomColors = require('web_editor.rte.summernote_custom_colors');
|
||||
const weUtils = require('web_editor.utils');
|
||||
|
||||
const qweb = core.qweb;
|
||||
|
||||
@@ -14,9 +15,10 @@ const ColorPaletteWidget = Widget.extend({
|
||||
// ! for xmlDependencies, see loadDependencies function
|
||||
template: 'web_editor.snippet.option.colorpicker',
|
||||
events: {
|
||||
'click button': '_onColorButtonClick',
|
||||
'mouseenter button': '_onColorButtonEnter',
|
||||
'mouseleave button': '_onColorButtonLeave',
|
||||
'click .o_we_color_btn': '_onColorButtonClick',
|
||||
'mouseenter .o_we_color_btn': '_onColorButtonEnter',
|
||||
'mouseleave .o_we_color_btn': '_onColorButtonLeave',
|
||||
'click .o_we_colorpicker_switch_pane_btn': '_onSwitchPaneButtonClick',
|
||||
},
|
||||
custom_events: {
|
||||
'colorpicker_select': '_onColorPickerSelect',
|
||||
@@ -42,9 +44,13 @@ const ColorPaletteWidget = Widget.extend({
|
||||
excluded: [],
|
||||
excludeSectionOf: null,
|
||||
$editable: $(),
|
||||
withCombinations: false,
|
||||
}, options || {});
|
||||
|
||||
this.selectedColor = '';
|
||||
this.resetButton = this.options.resetButton;
|
||||
this.withCombinations = this.options.withCombinations;
|
||||
|
||||
this.trigger_up('request_editable', {callback: val => this.options.$editable = val});
|
||||
},
|
||||
/**
|
||||
@@ -60,28 +66,20 @@ const ColorPaletteWidget = Widget.extend({
|
||||
start: async function () {
|
||||
const res = this._super.apply(this, arguments);
|
||||
|
||||
const $colorSection = this.$('.o_colorpicker_sections');
|
||||
const $wrapper = $colorSection.find('.o_colorpicker_section_tabs');
|
||||
const $colorSection = this.$('.o_colorpicker_sections[data-color-tab="theme-colors"]');
|
||||
const $clpicker = qweb.has_template('web_editor.colorpicker')
|
||||
? $(qweb.render('web_editor.colorpicker'))
|
||||
: $(`<colorpicker><div class="o_colorpicker_section" data-name="common"></div></colorpicker>`);
|
||||
$clpicker.appendTo($wrapper);
|
||||
$clpicker.find('button').addClass('o_we_color_btn');
|
||||
$clpicker.appendTo($colorSection);
|
||||
|
||||
// Remove excluded palettes (note: only hide them to still be able
|
||||
// to remove their related colors on the DOM target)
|
||||
_.each(this.options.excluded, function (exc) {
|
||||
$colorSection.find('[data-name="' + exc + '"]').addClass('d-none');
|
||||
_.each(this.options.excluded, exc => {
|
||||
this.$('[data-name="' + exc + '"]').addClass('d-none');
|
||||
});
|
||||
if (this.options.excludeSectionOf) {
|
||||
$colorSection.find('[data-name]:has([data-color="' + this.options.excludeSectionOf + '"])').addClass('d-none');
|
||||
}
|
||||
|
||||
if (this.options.resetButton) {
|
||||
let $section = this.$('.o_colorpicker_section[data-name="theme"]');
|
||||
if ($section.hasClass('d-none')) {
|
||||
$section = $section.insertBefore('<div class="o_colorpicker_section" data-name="reset"/>');
|
||||
}
|
||||
this._createColorButton('', ['o_colorpicker_reset', 'float-right']).appendTo($section);
|
||||
this.$('[data-name]:has([data-color="' + this.options.excludeSectionOf + '"])').addClass('d-none');
|
||||
}
|
||||
|
||||
this.el.querySelectorAll('.o_colorpicker_section').forEach(elem => {
|
||||
@@ -109,9 +107,14 @@ const ColorPaletteWidget = Widget.extend({
|
||||
this.el.querySelectorAll('button[data-color]').forEach(elem => {
|
||||
const colorName = elem.dataset.color;
|
||||
const $color = $(elem);
|
||||
$color.addClass('bg-' + colorName);
|
||||
const isCCName = weUtils.isColorCombinationName(colorName);
|
||||
if (isCCName) {
|
||||
$color.find('.o_we_cc_preview_wrapper').addClass(`o_cc o_cc${colorName}`);
|
||||
} else {
|
||||
$color.addClass(`bg-${colorName}`);
|
||||
}
|
||||
this.colorNames.push(colorName);
|
||||
if (!elem.classList.contains('d-none')) {
|
||||
if (!isCCName && !elem.classList.contains('d-none')) {
|
||||
const color = ColorpickerWidget.normalizeCSSColor(this.style.getPropertyValue('--' + colorName).trim());
|
||||
this.colorToColorNames[color] = colorName;
|
||||
}
|
||||
@@ -140,7 +143,7 @@ const ColorPaletteWidget = Widget.extend({
|
||||
this.colorPicker = new ColorpickerWidget(this, {
|
||||
defaultColor: defaultColor,
|
||||
});
|
||||
await this.colorPicker.prependTo(this.$el);
|
||||
await this.colorPicker.prependTo($colorSection);
|
||||
return res;
|
||||
},
|
||||
/**
|
||||
@@ -217,12 +220,8 @@ const ColorPaletteWidget = Widget.extend({
|
||||
_addCustomColorButton: function (color, classes = []) {
|
||||
classes.push('o_custom_color');
|
||||
const $themeSection = this.$('.o_colorpicker_section[data-name="theme"]');
|
||||
// There is 8 buttons on a colorpalette line, the clear button is always the last of the first line.
|
||||
if (this.options.resetButton && $themeSection.find('button').length < 8) {
|
||||
const $resetButton = $themeSection.find('.o_colorpicker_reset');
|
||||
return this._createColorButton(color, classes).insertBefore($resetButton);
|
||||
}
|
||||
return this._createColorButton(color, classes).appendTo($themeSection);
|
||||
const $button = this._createColorButton(color, classes);
|
||||
return $button.appendTo($themeSection);
|
||||
},
|
||||
/**
|
||||
* Return a color button.
|
||||
@@ -233,7 +232,7 @@ const ColorPaletteWidget = Widget.extend({
|
||||
*/
|
||||
_createColorButton: function (color, classes) {
|
||||
return $('<button/>', {
|
||||
class: classes.join(' '),
|
||||
class: 'o_we_color_btn ' + classes.join(' '),
|
||||
style: 'background-color:' + color + ';',
|
||||
});
|
||||
},
|
||||
@@ -338,6 +337,20 @@ const ColorPaletteWidget = Widget.extend({
|
||||
target: this.colorPicker.el,
|
||||
}, 'custom_color_picked');
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onSwitchPaneButtonClick(ev) {
|
||||
ev.stopPropagation();
|
||||
this.el.querySelectorAll('.o_we_colorpicker_switch_pane_btn').forEach(el => {
|
||||
el.classList.remove('active');
|
||||
});
|
||||
ev.currentTarget.classList.add('active');
|
||||
this.el.querySelectorAll('.o_colorpicker_sections').forEach(el => {
|
||||
el.classList.toggle('d-none', el.dataset.colorTab !== ev.currentTarget.dataset.target);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -635,13 +635,55 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
}
|
||||
|
||||
.o_we_cc_preview_container {
|
||||
background-color: white !important;
|
||||
background-image: url("/web_editor/static/src/img/transparent.png") !important;
|
||||
font-family: sans-serif !important;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
.o_we_cc_preview_wrapper > * {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.o_we_color_combination_btn_text {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: 0.8em !important;
|
||||
}
|
||||
.o_we_color_combination_btn_title {
|
||||
font-size: 1em !important;
|
||||
}
|
||||
.o_we_color_combination_btn_btn {
|
||||
padding: 0 1px !important;
|
||||
border-radius: 2px !important;
|
||||
font-size: 0.8em !important;
|
||||
}
|
||||
|
||||
// SNIPPET OPTIONS
|
||||
.colorpicker {
|
||||
padding: 3px;
|
||||
.d-flex .btn.o_we_colorpicker_switch_pane_btn {
|
||||
font-size: 0.8em !important;
|
||||
|
||||
&.active {
|
||||
border-bottom: 1px solid $o-we-handles-accent-color !important;
|
||||
}
|
||||
|
||||
+ .o_colorpicker_reset {
|
||||
border: 1px solid var(--o-we-color) !important;
|
||||
border-radius: 2px !important;
|
||||
font-size: 0.8em !important;
|
||||
padding: 0 2px !important;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
.o_colorpicker_sections {
|
||||
font-size: 14px;
|
||||
|
||||
button {
|
||||
.o_we_color_btn, .o_we_color_combination_btn {
|
||||
float: left;
|
||||
width: percentage(1 / 8);
|
||||
padding-top: percentage(1 / 8);
|
||||
@@ -664,12 +706,30 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
}
|
||||
|
||||
.o_we_color_combination_btn {
|
||||
float: none;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-clip: padding-box;
|
||||
border-top: 4px solid transparent;
|
||||
border-bottom: 4px solid transparent;
|
||||
|
||||
> .o_we_cc_preview_wrapper {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
+ .o_we_color_combination_btn {
|
||||
margin-top: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
.o_colorpicker_section {
|
||||
|
||||
> :first-child {
|
||||
margin: 4px 0;
|
||||
}
|
||||
button {
|
||||
.o_we_color_btn {
|
||||
position: relative;
|
||||
|
||||
&.selected::before {
|
||||
@@ -688,7 +748,7 @@ body.editor_enable.editor_has_snippets {
|
||||
}
|
||||
|
||||
&[data-name="transparent_grayscale"], &[data-name="theme"], &[data-name="reset"] {
|
||||
button {
|
||||
.o_we_color_btn {
|
||||
@include o-alpha-button-preview;
|
||||
|
||||
&::before, &::after {
|
||||
|
||||
@@ -43,11 +43,35 @@
|
||||
|
||||
<!-- options -->
|
||||
<div t-name="web_editor.snippet.option.colorpicker" class="colorpicker">
|
||||
|
||||
<div class="o_colorpicker_sections">
|
||||
<div class="tab-content o_colorpicker_section_tabs"/>
|
||||
<div class="d-flex px-1">
|
||||
<button t-if="widget.withCombinations" type="button" class="btn flex-grow-1 o_we_colorpicker_switch_pane_btn active" data-target="color-combinations">Combinations</button>
|
||||
<button type="button" t-attf-class="btn flex-grow-1 o_we_colorpicker_switch_pane_btn #{widget.withCombinations ? '' : 'active'}" data-target="theme-colors">Custom</button>
|
||||
<button t-if="widget.resetButton" type="button" class="btn flex-grow-1 o_we_color_btn o_colorpicker_reset">
|
||||
<t t-if="widget.withCombinations">None</t>
|
||||
<t t-else="">Reset</t>
|
||||
</button>
|
||||
</div>
|
||||
<div t-attf-class="o_colorpicker_sections #{widget.withCombinations ? '' : 'd-none'} px-1" data-color-tab="color-combinations">
|
||||
<!-- List all Presets -->
|
||||
<t t-foreach="5" t-as="i">
|
||||
<t t-call="web_editor.colorpalette.combination.btn">
|
||||
<t t-set="number" t-value="i + 1"/>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
<div t-attf-class="o_colorpicker_sections #{widget.withCombinations ? 'd-none' : ''} p-1" data-color-tab="theme-colors"/>
|
||||
</div>
|
||||
<t t-name="web_editor.colorpalette.combination.btn">
|
||||
<button type="button" class="o_we_color_btn o_we_color_combination_btn o_we_cc_preview_container"
|
||||
t-att-data-color="number" t-attf-title="Preset #{number}">
|
||||
<div class="o_we_cc_preview_wrapper d-flex justify-content-between align-items-end">
|
||||
<h1 class="o_we_color_combination_btn_title">Title</h1>
|
||||
<p class="o_we_color_combination_btn_text flex-grow-1">Text</p>
|
||||
<span class="o_we_color_combination_btn_btn btn btn-sm btn-primary o_btn_preview mr-1"><small>Button</small></span>
|
||||
<span class="o_we_color_combination_btn_btn btn btn-sm btn-secondary o_btn_preview"><small>Button</small></span>
|
||||
</div>
|
||||
</button>
|
||||
</t>
|
||||
|
||||
<t t-name="web_editor.many2one.button">
|
||||
<div class="btn-group">
|
||||
|
||||
@@ -201,7 +201,7 @@ QUnit.module('web_editor', {}, function () {
|
||||
assert.ok($field.find('.note-back-color-preview').hasClass('show'),
|
||||
"should display the color picker");
|
||||
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button[style="background-color:#00FFFF;"]'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview .o_we_color_btn[style="background-color:#00FFFF;"]'));
|
||||
|
||||
assert.ok(!$field.find('.note-back-color-preview').hasClass('show'),
|
||||
"should close the color picker");
|
||||
@@ -227,7 +227,7 @@ QUnit.module('web_editor', {}, function () {
|
||||
// text is selected
|
||||
|
||||
await openColorpicker('.note-toolbar .note-back-color-preview');
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button.bg-gamma'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview .o_we_color_btn.bg-gamma'));
|
||||
|
||||
assert.strictEqual($field.find('.note-editable').html(),
|
||||
'<p>t<font style="background-color: rgb(0, 255, 255);">oto t</font><font style="" class="bg-gamma">oto </font><font class="bg-gamma" style="">to</font>to</p><p>tata</p>',
|
||||
@@ -386,7 +386,7 @@ QUnit.module('web_editor', {}, function () {
|
||||
}
|
||||
|
||||
await openColorpicker('.note-toolbar .note-back-color-preview');
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview button.bg-gamma'));
|
||||
await testUtils.dom.click($field.find('.note-toolbar .note-back-color-preview .o_we_color_btn.bg-gamma'));
|
||||
|
||||
await testUtils.form.clickSave(form);
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ const {ColorpickerWidget} = require('web.Colorpicker');
|
||||
const config = require('web.config');
|
||||
var core = require('web.core');
|
||||
var Dialog = require('web.Dialog');
|
||||
const wUtils = require('website.utils');
|
||||
const weUtils = require('web_editor.utils');
|
||||
var options = require('web_editor.snippets.options');
|
||||
const wUtils = require('website.utils');
|
||||
require('website.s_popup_options');
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
@@ -135,7 +135,7 @@ $i: 1;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
> button {
|
||||
> .o_we_color_btn {
|
||||
|
||||
&:hover,
|
||||
&.selected {
|
||||
@@ -152,8 +152,11 @@ $i: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.note-palette-title {
|
||||
color: $o-we-color-text-light;
|
||||
.note-palette-title, a, button:not(.o_we_color_combination_btn) {
|
||||
|
||||
&, &:hover {
|
||||
color: $o-we-color-text-light;
|
||||
}
|
||||
}
|
||||
|
||||
.palette-reset {
|
||||
|
||||
@@ -325,18 +325,12 @@
|
||||
data-js="MainColorpicker"
|
||||
data-selector="section, .carousel-item, section .row > div, .o_record_cover_container"
|
||||
data-exclude=".parallax, .o_gallery .carousel-item, .s_col_no_bgcolor, .s_col_no_bgcolor.row > div, .o_gallery .row > div, .s_carousel_wrapper, .s_tabs .oe_structure > *">
|
||||
<we-select data-trigger="bg_color_opt" data-trigger-value="">
|
||||
<we-button data-select-class="o_cc o_cc1">Color combinations 1</we-button>
|
||||
<we-button data-select-class="o_cc o_cc2">Color combinations 2</we-button>
|
||||
<we-button data-select-class="o_cc o_cc3">Color combinations 3</we-button>
|
||||
<we-button data-select-class="o_cc o_cc4">Color combinations 4</we-button>
|
||||
<we-button data-select-class="o_cc o_cc5">Color combinations 5</we-button>
|
||||
</we-select>
|
||||
<we-colorpicker string="Background Color"
|
||||
data-name="bg_color_opt"
|
||||
data-select-style="true"
|
||||
data-css-property="background-color"
|
||||
data-color-prefix="bg-"
|
||||
data-with-combinations="true"
|
||||
data-dependencies="!cover_background_opt"/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user