mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-11-02 20:30:20 -06:00
[PATCH] Upstream patch - 30042023
This commit is contained in:
1 parent
2de5398f04
commit
548132474e
33 files changed
+6260
-401
No files matched your search
@@ -69,6 +69,41 @@ var AttributeTranslateDialog = Dialog.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// Used to translate the text of `<select/>` options since it should not be
|
||||
// possible to interact with the content of `.o_translation_select` elements.
|
||||
const SelectTranslateDialog = Dialog.extend({
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
init: function (parent, options) {
|
||||
this._super(parent, {
|
||||
...options,
|
||||
title: _t("Translate Selection Option"),
|
||||
buttons: [
|
||||
{text: _t("Close"), click: this.save}
|
||||
],
|
||||
});
|
||||
this.optionEl = this.options.targetEl;
|
||||
this.translationObject = this.optionEl.closest('[data-oe-translation-id]');
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
const inputEl = document.createElement('input');
|
||||
inputEl.className = 'form-control my-3';
|
||||
inputEl.value = this.optionEl.textContent;
|
||||
inputEl.addEventListener('keyup', () => {
|
||||
this.optionEl.textContent = inputEl.value;
|
||||
const translationUpdated = inputEl.value !== this.optionEl.dataset.initialTranslationValue;
|
||||
this.translationObject.classList.toggle('o_dirty', translationUpdated);
|
||||
this.optionEl.classList.add('o_option_translated');
|
||||
});
|
||||
this.el.appendChild(inputEl);
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
var WysiwygTranslate = WysiwygMultizone.extend({
|
||||
custom_events: _.extend({}, WysiwygMultizone.prototype.custom_events || {}, {
|
||||
ready_to_save: '_onSave',
|
||||
@@ -101,8 +136,9 @@ var WysiwygTranslate = WysiwygMultizone.extend({
|
||||
return promise.then(function () {
|
||||
self._relocateEditorBar();
|
||||
var attrs = ['placeholder', 'title', 'alt'];
|
||||
const $editable = self._getEditableArea();
|
||||
_.each(attrs, function (attr) {
|
||||
self._getEditableArea().filter('[' + attr + '*="data-oe-translation-id="]').filter(':empty, input, select, textarea, img').each(function () {
|
||||
$editable.filter('[' + attr + '*="data-oe-translation-id="]').filter(':empty, input, select, textarea, img').each(function () {
|
||||
var $node = $(this);
|
||||
var translation = $node.data('translation') || {};
|
||||
var trans = $node.attr(attr);
|
||||
@@ -125,6 +161,25 @@ var WysiwygTranslate = WysiwygMultizone.extend({
|
||||
});
|
||||
});
|
||||
|
||||
// Hack: we add a temporary element to handle option's text
|
||||
// translations from the linked <select/>. The final values are
|
||||
// copied to the original element right before save.
|
||||
$editable.filter('[data-oe-translation-id] > select').each((index, select) => {
|
||||
// Keep the default width of the translation `<span/>`.
|
||||
select.parentElement.classList.remove('o_is_inline_editable');
|
||||
const selectTranslationEl = document.createElement('div');
|
||||
selectTranslationEl.className = 'o_translation_select';
|
||||
const optionNames = [...select.options].map(option => option.text);
|
||||
optionNames.forEach(option => {
|
||||
const optionEl = document.createElement('div');
|
||||
optionEl.textContent = option;
|
||||
optionEl.dataset.initialTranslationValue = option;
|
||||
optionEl.className = 'o_translation_select_option';
|
||||
selectTranslationEl.appendChild(optionEl);
|
||||
});
|
||||
select.before(selectTranslationEl);
|
||||
});
|
||||
|
||||
self.translations = [];
|
||||
self.$editables_attr = self._getEditableArea().filter('.o_translatable_attribute');
|
||||
self.$editables_attribute = $('.o_editable_translatable_attribute');
|
||||
@@ -274,18 +329,25 @@ var WysiwygTranslate = WysiwygMultizone.extend({
|
||||
});
|
||||
});
|
||||
|
||||
this.$editables_attr.prependEvent('mousedown.translator click.translator mouseup.translator', function (ev) {
|
||||
if (ev.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
if (ev.type !== 'mousedown') {
|
||||
return;
|
||||
}
|
||||
this.$editables_attr
|
||||
.add(this._getEditableArea().filter('.o_translation_select_option'))
|
||||
.prependEvent('mousedown.translator click.translator mouseup.translator', function (ev) {
|
||||
if (ev.ctrlKey) {
|
||||
return;
|
||||
}
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
if (ev.type !== 'mousedown') {
|
||||
return;
|
||||
}
|
||||
|
||||
new AttributeTranslateDialog(self, {}, ev.target).open();
|
||||
});
|
||||
const targetEl = ev.target;
|
||||
if (targetEl.closest('.o_translation_select')) {
|
||||
new SelectTranslateDialog(self, {size: 'medium', targetEl}).open();
|
||||
} else {
|
||||
new AttributeTranslateDialog(self, {}, targetEl).open();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -294,6 +356,19 @@ var WysiwygTranslate = WysiwygMultizone.extend({
|
||||
|
||||
_onSave: function (ev) {
|
||||
ev.stopPropagation();
|
||||
// Adapt translation values for `select` > `options`s and remove all
|
||||
// temporary `.o_translation_select` elements.
|
||||
for (const optionsEl of this.el.querySelectorAll('.o_translation_select')) {
|
||||
const selectEl = optionsEl.nextElementSibling;
|
||||
const translatedOptions = optionsEl.children;
|
||||
const selectOptions = selectEl.tagName === 'SELECT' ? [...selectEl.options] : [];
|
||||
if (selectOptions.length === translatedOptions.length) {
|
||||
selectOptions.map((option, i) => {
|
||||
option.text = translatedOptions[i].textContent;
|
||||
});
|
||||
}
|
||||
optionsEl.remove();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -281,6 +281,10 @@ $-header-nav-link-height: $nav-link-height;
|
||||
.o_footer_copyright {
|
||||
@include o-apply-colors('copyright', $background: o-color('footer'));
|
||||
}
|
||||
.s_popup {
|
||||
// The colors of the footer must not impact the "all pages" popup.
|
||||
@include o-apply-colors(1);
|
||||
}
|
||||
}
|
||||
|
||||
h2, h3, h4, h5, h6 {
|
||||
@@ -1551,3 +1555,18 @@ $ribbon-padding: 100px;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
[data-oe-translation-id] {
|
||||
> .o_translation_select {
|
||||
border: $input-border-width solid $input-border-color;
|
||||
@include border-radius($input-border-radius, 0);
|
||||
|
||||
// Hide translatable `<select/>`s since we use `.o_translation_select`
|
||||
// elements to handle translations.
|
||||
& + select {
|
||||
display: none !important;
|
||||
}
|
||||
> div:not(:last-child) {
|
||||
border-bottom: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,13 +81,17 @@
|
||||
}
|
||||
|
||||
html[lang] > body.editor_enable [data-oe-translation-state] {
|
||||
background: rgba($o-we-content-to-translate-color, 0.5) !important;
|
||||
|
||||
&[data-oe-translation-state="translated"] {
|
||||
background: rgba($o-we-translated-content-color, 0.5) !important;
|
||||
&, & .o_translation_select_option {
|
||||
background: rgba($o-we-content-to-translate-color, 0.5) !important;
|
||||
}
|
||||
|
||||
&.o_dirty {
|
||||
&[data-oe-translation-state="translated"] {
|
||||
&, & .o_translation_select_option {
|
||||
background: rgba($o-we-translated-content-color, 0.5) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.o_dirty, & .o_option_translated {
|
||||
background: rgba($o-we-translated-content-color, 0.25) !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user