[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:
qsm-odoo
2020-06-02 09:42:19 +00:00
parent 69190959ce
commit d9c4d928f7
9 changed files with 192 additions and 54 deletions
@@ -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 {
+27 -3
View File
@@ -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&nbsp;</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 {
+1 -7
View File
@@ -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>