[IMP] spreadsheet: update o_spreadsheet to latest version
### Contains the following commits: https://github.com/odoo/o-spreadsheet/commit/4dc340fc [REL] 16.5.0-alpha.10 https://github.com/odoo/o-spreadsheet/commit/c6e5d58e [IMP] dates: cache date parsing https://github.com/odoo/o-spreadsheet/commit/38e44577 [IMP] range: don't spend time building a zone https://github.com/odoo/o-spreadsheet/commit/7e491948 [IMP] cell: faster formula string https://github.com/odoo/o-spreadsheet/commit/d6a498b4 [FIX] evaluation: don't build formula content for errors https://github.com/odoo/o-spreadsheet/commit/5e2a7640 [IMP] evaluation: don't create useless Errors https://github.com/odoo/o-spreadsheet/commit/d5ff0843 [IMP] Composer: highlight fuzzy matched letters in autocomplete dropdown https://github.com/odoo/o-spreadsheet/commit/3562883e [IMP] Composer: always sort autocomplete elements https://github.com/odoo/o-spreadsheet/commit/e8d76dd3 [IMP] Composer: Select autocomplete results on mouseover Task: 3387413 https://github.com/odoo/o-spreadsheet/commit/b6dc8877 [IMP] evaluation: don't spend time building formula string https://github.com/odoo/o-spreadsheet/commit/078e888d [FIX] evaluation: compute cell only once closes odoo/odoo#138145 Signed-off-by: Rémi Rahir (rar) <rar@odoo.com>
This commit is contained in:
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
||||
* @see https://github.com/odoo/o-spreadsheet
|
||||
* @version 16.5.0-alpha.9
|
||||
* @date 2023-10-03T13:36:38.605Z
|
||||
* @hash c46de914
|
||||
* @version 16.5.0-alpha.10
|
||||
* @date 2023-10-10T08:16:10.236Z
|
||||
* @hash 4dc340fc
|
||||
*/
|
||||
|
||||
(function (exports, owl) {
|
||||
@@ -131,6 +131,7 @@
|
||||
const GRID_BORDER_COLOR = "#E2E3E3";
|
||||
const FROZEN_PANE_HEADER_BORDER_COLOR = "#BCBCBC";
|
||||
const FROZEN_PANE_BORDER_COLOR = "#DADFE8";
|
||||
const COMPOSER_ASSISTANT_COLOR = "#9B359B";
|
||||
// Color picker defaults as upper case HEX to match `toHex`helper
|
||||
const COLOR_PICKER_DEFAULTS = [
|
||||
"#000000",
|
||||
@@ -1242,7 +1243,17 @@
|
||||
function isDateTime(str, locale) {
|
||||
return parseDateTime(str, locale) !== null;
|
||||
}
|
||||
const CACHE = new Map();
|
||||
function parseDateTime(str, locale) {
|
||||
if (!CACHE.has(locale)) {
|
||||
CACHE.set(locale, new Map());
|
||||
}
|
||||
if (!CACHE.get(locale).has(str)) {
|
||||
CACHE.get(locale).set(str, _parseDateTime(str, locale));
|
||||
}
|
||||
return CACHE.get(locale).get(str);
|
||||
}
|
||||
function _parseDateTime(str, locale) {
|
||||
str = str.trim();
|
||||
let time = null;
|
||||
const timeMatch = str.match(timeRegexp);
|
||||
@@ -2100,7 +2111,7 @@
|
||||
const SORT_TYPES_ORDER = ["number", "string", "boolean", "undefined"];
|
||||
function assert(condition, message) {
|
||||
if (!condition()) {
|
||||
throw new Error(message);
|
||||
throw new EvaluationError(CellErrorType.GenericError, message);
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -4062,8 +4073,9 @@
|
||||
}
|
||||
get zone() {
|
||||
const { left, top, bottom, right } = this._zone;
|
||||
if (right !== undefined && bottom !== undefined)
|
||||
return { left, top, right, bottom };
|
||||
if (right !== undefined && bottom !== undefined) {
|
||||
return this._zone;
|
||||
}
|
||||
else if (bottom === undefined && right !== undefined) {
|
||||
return { right, top, left, bottom: this.getSheetSize(this.sheetId).numberOfRows - 1 };
|
||||
}
|
||||
@@ -5169,7 +5181,7 @@
|
||||
return textCell((value || "").toString(), localeFormat);
|
||||
}
|
||||
catch (error) {
|
||||
return errorCell((value || "").toString(), new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
|
||||
return errorCell(new EvaluationError(CellErrorType.GenericError, error.message || DEFAULT_ERROR_MESSAGE));
|
||||
}
|
||||
}
|
||||
function textCell(value, localeFormat) {
|
||||
@@ -5236,7 +5248,7 @@
|
||||
formattedValue,
|
||||
};
|
||||
}
|
||||
function errorCell(content, error) {
|
||||
function errorCell(error) {
|
||||
return {
|
||||
type: CellValueType.error,
|
||||
value: error.errorType,
|
||||
@@ -26307,16 +26319,31 @@
|
||||
row: Number,
|
||||
};
|
||||
|
||||
function getHtmlContentFromPattern(pattern, value, highlightColor, className) {
|
||||
const pendingHtmlContent = [];
|
||||
pattern = pattern.toLowerCase();
|
||||
for (const patternChar of pattern) {
|
||||
const index = value.toLocaleLowerCase().indexOf(patternChar);
|
||||
if (index === -1) {
|
||||
continue;
|
||||
}
|
||||
pendingHtmlContent.push({ value: value.slice(0, index), color: "" }, { value: value[index], color: highlightColor, class: className });
|
||||
value = value.slice(index + 1);
|
||||
}
|
||||
pendingHtmlContent.push({ value });
|
||||
const htmlContent = pendingHtmlContent.filter((content) => content.value);
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
css /* scss */ `
|
||||
.o-autocomplete-dropdown {
|
||||
pointer-events: auto;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
max-width: 400px;
|
||||
& > div:hover {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.o-autocomplete-value-focus {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
& > div {
|
||||
@@ -26334,7 +26361,9 @@
|
||||
TextValueProvider.props = {
|
||||
values: Array,
|
||||
selectedIndex: { type: Number, optional: true },
|
||||
getHtmlContent: Function,
|
||||
onValueSelected: Function,
|
||||
onValueHovered: Function,
|
||||
};
|
||||
|
||||
class ContentEditableHelper {
|
||||
@@ -26683,8 +26712,8 @@
|
||||
.o-formula-assistant-focus {
|
||||
div:first-child,
|
||||
span {
|
||||
color: purple;
|
||||
text-shadow: 0px 0px 1px purple;
|
||||
color: ${COMPOSER_ASSISTANT_COLOR};
|
||||
text-shadow: 0px 0px 1px ${COMPOSER_ASSISTANT_COLOR};
|
||||
}
|
||||
div:last-child {
|
||||
color: black;
|
||||
@@ -26729,6 +26758,7 @@
|
||||
|
||||
const functions = functionRegistry.content;
|
||||
const ASSISTANT_WIDTH = 300;
|
||||
const AUTOCOMPLETE_ENTRIES = 10;
|
||||
const selectionIndicatorClass = "selector-flag";
|
||||
const selectionIndicatorColor = "#a9a9a9";
|
||||
const selectionIndicator = "␣";
|
||||
@@ -26778,6 +26808,13 @@
|
||||
position: absolute;
|
||||
margin: 1px 4px;
|
||||
pointer-events: none;
|
||||
|
||||
.o-semi-bold {
|
||||
/** FIXME: to remove in favor of Bootstrap
|
||||
* 'fw-semibold' when we upgrade to Bootstrap 5.2
|
||||
*/
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -26798,6 +26835,7 @@
|
||||
values: [],
|
||||
selectedIndex: undefined,
|
||||
type: "function",
|
||||
getHtmlContent: () => [],
|
||||
});
|
||||
functionDescriptionState = owl.useState({
|
||||
showDescription: false,
|
||||
@@ -27040,24 +27078,27 @@
|
||||
text,
|
||||
description,
|
||||
};
|
||||
})
|
||||
.sort((a, b) => {
|
||||
return a.text.length - b.text.length || a.text.localeCompare(b.text);
|
||||
});
|
||||
if (searchTerm) {
|
||||
values = fuzzyLookup(searchTerm, values, (t) => t.text);
|
||||
values = fuzzyLookup(searchTerm, values, (t) => t.text).slice(0, AUTOCOMPLETE_ENTRIES);
|
||||
}
|
||||
else {
|
||||
// alphabetical order
|
||||
values = values.sort((a, b) => a.text.localeCompare(b.text));
|
||||
}
|
||||
this.autoCompleteState.values = values.slice(0, 10);
|
||||
this.autoCompleteState.values = values.slice(0, AUTOCOMPLETE_ENTRIES);
|
||||
this.autoCompleteState.getHtmlContent = (value) => getHtmlContentFromPattern(searchTerm, value, COMPOSER_ASSISTANT_COLOR, "o-semi-bold");
|
||||
this.autoCompleteState.selectedIndex = 0;
|
||||
}
|
||||
updateAutoCompleteIndex(index) {
|
||||
this.autoCompleteState.selectedIndex = clip(0, index, 10);
|
||||
}
|
||||
/**
|
||||
* This is required to ensure the content helper selection is
|
||||
* properly updated on "onclick" events. Depending on the browser,
|
||||
* the callback onClick from the composer will be executed before
|
||||
* the selection was updated in the dom, which means we capture an
|
||||
* wrong selection which is then forced upon the content helper on
|
||||
* patchContent.
|
||||
* processContent.
|
||||
*/
|
||||
onMousedown(ev) {
|
||||
if (ev.button > 0) {
|
||||
@@ -27327,6 +27368,7 @@
|
||||
this.autoCompleteState.type = "dataValidation";
|
||||
this.autoCompleteState.selectedIndex = undefined;
|
||||
this.autoCompleteState.values = values.map((value) => ({ text: value, description: "" }));
|
||||
this.autoCompleteState.getHtmlContent = (value) => [{ value }];
|
||||
}
|
||||
}
|
||||
Composer.props = {
|
||||
@@ -34971,10 +35013,11 @@
|
||||
* Reconstructs the original formula string based on a normalized form and its dependencies
|
||||
*/
|
||||
getFormulaCellContent(sheetId, cell, dependencies) {
|
||||
const ranges = dependencies || [...cell.dependencies];
|
||||
const ranges = dependencies || cell.dependencies;
|
||||
let rangeIndex = 0;
|
||||
return concat(cell.compiledFormula.tokens.map((token) => {
|
||||
if (token.type === "REFERENCE") {
|
||||
const range = ranges.shift();
|
||||
const range = ranges[rangeIndex++];
|
||||
return this.getters.getRangeString(range, sheetId);
|
||||
}
|
||||
return token.value;
|
||||
@@ -39188,7 +39231,7 @@
|
||||
const evaluatedCell = this.getEvaluatedCell(position);
|
||||
if (evaluatedCell.type === CellValueType.empty) {
|
||||
const cell = this.getters.getCell(position);
|
||||
if (!cell || cell.content === "") {
|
||||
if (!cell || (!cell.isFormula && cell.content === "")) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -39401,7 +39444,7 @@
|
||||
constructor(context, getters) {
|
||||
this.context = context;
|
||||
this.getters = getters;
|
||||
this.compilationParams = buildCompilationParameters(context, getters, (position) => this.computeCell(this.encodePosition(position)));
|
||||
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
||||
}
|
||||
getEvaluatedCell(position) {
|
||||
return (this.evaluatedCells.get(this.encodePosition(position)) ||
|
||||
@@ -39429,7 +39472,7 @@
|
||||
this.formulaDependencies().addDependencies(positionId, dependencies);
|
||||
}
|
||||
updateCompilationParameters() {
|
||||
this.compilationParams = buildCompilationParameters(this.context, this.getters, (position) => this.computeCell(this.encodePosition(position)));
|
||||
this.compilationParams = buildCompilationParameters(this.context, this.getters, this.computeAndSave.bind(this));
|
||||
}
|
||||
evaluateCells(positions) {
|
||||
const cells = positions.map(this.encodePosition.bind(this));
|
||||
@@ -39545,15 +39588,21 @@
|
||||
this.cellsBeingComputed.delete(cellId);
|
||||
}
|
||||
}
|
||||
handleError(e, cell) {
|
||||
if (!(e instanceof Error)) {
|
||||
e = new Error(e);
|
||||
computeAndSave(position) {
|
||||
const positionId = this.encodePosition(position);
|
||||
const evaluatedCell = this.computeCell(positionId);
|
||||
if (!this.evaluatedCells.has(positionId)) {
|
||||
this.setEvaluatedCell(positionId, evaluatedCell);
|
||||
}
|
||||
return evaluatedCell;
|
||||
}
|
||||
handleError(e, cell) {
|
||||
if (!(e instanceof EvaluationError)) {
|
||||
e = new EvaluationError(CellErrorType.GenericError, e.message);
|
||||
}
|
||||
const msg = e?.errorType || CellErrorType.GenericError;
|
||||
// apply function name
|
||||
const __lastFnCalled = this.compilationParams[2].__lastFnCalled || "";
|
||||
const error = new EvaluationError(msg, e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled), e.logLevel !== undefined ? e.logLevel : CellErrorLevel.error);
|
||||
return errorCell(cell.content, error);
|
||||
e.message = e.message.replace("[[FUNCTION_NAME]]", __lastFnCalled);
|
||||
return errorCell(e);
|
||||
}
|
||||
computeFormulaCell(cellData) {
|
||||
const cellId = cellData.id;
|
||||
@@ -55110,9 +55159,9 @@
|
||||
exports.tokenize = tokenize;
|
||||
|
||||
|
||||
__info__.version = "16.5.0-alpha.9";
|
||||
__info__.date = "2023-10-03T13:36:38.605Z";
|
||||
__info__.hash = "c46de914";
|
||||
__info__.version = "16.5.0-alpha.10";
|
||||
__info__.date = "2023-10-10T08:16:10.236Z";
|
||||
__info__.hash = "4dc340fc";
|
||||
|
||||
|
||||
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<!--
|
||||
This file is generated by o-spreadsheet build tools. Do not edit it.
|
||||
@see https://github.com/odoo/o-spreadsheet
|
||||
@version 16.5.0-alpha.9
|
||||
@date 2023-10-03T13:36:42.361Z
|
||||
@hash c46de914
|
||||
@version 16.5.0-alpha.10
|
||||
@date 2023-10-10T08:16:13.959Z
|
||||
@hash 4dc340fc
|
||||
-->
|
||||
<odoo>
|
||||
<t t-name="o-spreadsheet-ActionButton">
|
||||
@@ -430,8 +430,19 @@
|
||||
<div
|
||||
class="d-flex flex-column text-start"
|
||||
t-att-class="{'o-autocomplete-value-focus': props.selectedIndex === v_index}"
|
||||
t-on-click="() => this.props.onValueSelected(v.text)">
|
||||
<div class="o-autocomplete-value text-truncate" t-esc="v.text"/>
|
||||
t-on-click="() => this.props.onValueSelected(v.text)"
|
||||
t-on-mousemove="() => this.props.onValueHovered(v_index)">
|
||||
<div class="o-autocomplete-value text-truncate">
|
||||
<t t-set="htmlContent" t-value="props.getHtmlContent(v.text)"/>
|
||||
<span
|
||||
t-foreach="htmlContent"
|
||||
t-as="content"
|
||||
t-key="content_index"
|
||||
t-att-class="content.class"
|
||||
t-attf-style="color: {{content.color || 'inherit'}};"
|
||||
t-esc="content.value"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="o-autocomplete-description text-truncate"
|
||||
t-esc="v.description"
|
||||
@@ -476,6 +487,8 @@
|
||||
values="autoCompleteState.values"
|
||||
selectedIndex="autoCompleteState.selectedIndex"
|
||||
onValueSelected.bind="this.autoComplete"
|
||||
onValueHovered.bind="this.updateAutoCompleteIndex"
|
||||
getHtmlContent="autoCompleteState.getHtmlContent"
|
||||
/>
|
||||
<FunctionDescriptionProvider
|
||||
t-if="functionDescriptionState.showDescription"
|
||||
|
||||
Reference in New Issue
Block a user