@odoo/o-spreadsheet 19.1.2 → 19.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/o-spreadsheet-engine.d.ts +10 -6
- package/dist/o-spreadsheet-engine.esm.js +130 -16
- package/dist/o-spreadsheet-engine.iife.js +130 -16
- package/dist/o-spreadsheet-engine.min.iife.js +312 -312
- package/dist/o-spreadsheet.d.ts +17 -10
- package/dist/o_spreadsheet.css +20 -10
- package/dist/o_spreadsheet.esm.js +678 -589
- package/dist/o_spreadsheet.iife.js +678 -589
- package/dist/o_spreadsheet.min.iife.js +9 -9
- package/dist/o_spreadsheet.xml +97 -103
- package/package.json +2 -2
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 19.
|
|
6
|
-
* @date 2026-01-07T16:21:
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 19.2.0-alpha.2
|
|
6
|
+
* @date 2026-01-07T16:21:35.251Z
|
|
7
|
+
* @hash ac2fa3e
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { useEnv, useSubEnv, onWillUnmount, useComponent, status, Component, useRef, onMounted, useEffect, App, blockDom, useState, onPatched, useExternalListener, onWillUpdateProps, onWillStart, onWillPatch, xml, useChildSubEnv, markRaw, toRaw } from '@odoo/owl';
|
|
@@ -10482,6 +10482,7 @@ function changeCFRuleLocale(rule, changeContentLocale) {
|
|
|
10482
10482
|
case "dateIsAfter":
|
|
10483
10483
|
case "dateIsOnOrAfter":
|
|
10484
10484
|
case "dateIsOnOrBefore":
|
|
10485
|
+
case "top10":
|
|
10485
10486
|
rule.values = rule.values.map((v) => changeContentLocale(v));
|
|
10486
10487
|
return rule;
|
|
10487
10488
|
case "beginsWithText":
|
|
@@ -14631,6 +14632,7 @@ const DVTerms = {
|
|
|
14631
14632
|
dateValue: _t("The value must be a date"),
|
|
14632
14633
|
validRange: _t("The value must be a valid range"),
|
|
14633
14634
|
validFormula: _t("The formula must be valid"),
|
|
14635
|
+
positiveNumber: _t("The value must be a positive number"),
|
|
14634
14636
|
},
|
|
14635
14637
|
Errors: {
|
|
14636
14638
|
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid."),
|
|
@@ -34019,6 +34021,7 @@ const CF_OPERATOR_TYPE_CONVERSION_MAP = {
|
|
|
34019
34021
|
greaterThanOrEqual: "isGreaterOrEqualTo",
|
|
34020
34022
|
lessThan: "isLessThan",
|
|
34021
34023
|
lessThanOrEqual: "isLessOrEqualTo",
|
|
34024
|
+
top10: "top10",
|
|
34022
34025
|
};
|
|
34023
34026
|
/** Conversion map CF types in XLSX <=> Cf types in o_spreadsheet */
|
|
34024
34027
|
const CF_TYPE_CONVERSION_MAP = {
|
|
@@ -34559,6 +34562,7 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
34559
34562
|
const rule = cf.cfRules[0];
|
|
34560
34563
|
let operator;
|
|
34561
34564
|
const values = [];
|
|
34565
|
+
const cfAdditionalProperties = {};
|
|
34562
34566
|
if (rule.dxfId === undefined &&
|
|
34563
34567
|
!(rule.type === "colorScale" || rule.type === "iconSet" || rule.type === "dataBar"))
|
|
34564
34568
|
continue;
|
|
@@ -34567,7 +34571,6 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
34567
34571
|
case "containsErrors":
|
|
34568
34572
|
case "notContainsErrors":
|
|
34569
34573
|
case "duplicateValues":
|
|
34570
|
-
case "top10":
|
|
34571
34574
|
case "uniqueValues":
|
|
34572
34575
|
case "timePeriod":
|
|
34573
34576
|
// Not supported
|
|
@@ -34618,6 +34621,18 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
34618
34621
|
values.push(prefixFormulaWithEqual(rule.formula[1]));
|
|
34619
34622
|
}
|
|
34620
34623
|
break;
|
|
34624
|
+
case "top10":
|
|
34625
|
+
if (rule.rank === undefined)
|
|
34626
|
+
continue;
|
|
34627
|
+
operator = CF_OPERATOR_TYPE_CONVERSION_MAP[rule.type];
|
|
34628
|
+
values.push(rule.rank.toString());
|
|
34629
|
+
if (rule.percent) {
|
|
34630
|
+
cfAdditionalProperties.isPercent = true;
|
|
34631
|
+
}
|
|
34632
|
+
if (rule.bottom) {
|
|
34633
|
+
cfAdditionalProperties.isBottom = true;
|
|
34634
|
+
}
|
|
34635
|
+
break;
|
|
34621
34636
|
}
|
|
34622
34637
|
if (operator && rule.dxfId !== undefined) {
|
|
34623
34638
|
cfs.push({
|
|
@@ -34628,6 +34643,7 @@ function convertConditionalFormats(xlsxCfs, dxfs, warningManager) {
|
|
|
34628
34643
|
type: "CellIsRule",
|
|
34629
34644
|
operator: operator,
|
|
34630
34645
|
values: values,
|
|
34646
|
+
...cfAdditionalProperties,
|
|
34631
34647
|
style: convertStyle({ fontStyle: dxfs[rule.dxfId].font, fillStyle: dxfs[rule.dxfId].fill }, warningManager),
|
|
34632
34648
|
},
|
|
34633
34649
|
});
|
|
@@ -34846,6 +34862,8 @@ function convertOperator(operator) {
|
|
|
34846
34862
|
return "greaterThanOrEqual";
|
|
34847
34863
|
case "dateIsOnOrBefore":
|
|
34848
34864
|
return "lessThanOrEqual";
|
|
34865
|
+
case "top10":
|
|
34866
|
+
return "top10";
|
|
34849
34867
|
}
|
|
34850
34868
|
}
|
|
34851
34869
|
// -------------------------------------
|
|
@@ -40629,15 +40647,20 @@ criterionEvaluatorRegistry.add("isValueInList", {
|
|
|
40629
40647
|
getPreview: (criterion) => _t("Value one of: %s", criterion.values.join(", ")),
|
|
40630
40648
|
});
|
|
40631
40649
|
criterionEvaluatorRegistry.add("isValueInRange", {
|
|
40632
|
-
type: "
|
|
40633
|
-
|
|
40650
|
+
type: "isValueInRange",
|
|
40651
|
+
preComputeCriterion: (criterion, criterionRanges, getters) => {
|
|
40652
|
+
if (criterionRanges.length === 0) {
|
|
40653
|
+
return new Set();
|
|
40654
|
+
}
|
|
40655
|
+
const sheetId = criterionRanges[0].sheetId;
|
|
40656
|
+
const criterionValues = getters.getDataValidationRangeValues(sheetId, criterion);
|
|
40657
|
+
return new Set(criterionValues.map((value) => value.value.toString().toLowerCase()));
|
|
40658
|
+
},
|
|
40659
|
+
isValueValid: (value, criterion, valuesSet) => {
|
|
40634
40660
|
if (!value) {
|
|
40635
40661
|
return false;
|
|
40636
40662
|
}
|
|
40637
|
-
|
|
40638
|
-
return criterionValues
|
|
40639
|
-
.map((value) => value.value.toLowerCase())
|
|
40640
|
-
.includes(value.toString().toLowerCase());
|
|
40663
|
+
return valuesSet.has(value.toString().toLowerCase());
|
|
40641
40664
|
},
|
|
40642
40665
|
getErrorString: (criterion) => _t("The value must be a value in the range %s", String(criterion.values[0])),
|
|
40643
40666
|
isCriterionValueValid: (value) => rangeReference.test(value),
|
|
@@ -40714,6 +40737,67 @@ criterionEvaluatorRegistry.add("isNotEmpty", {
|
|
|
40714
40737
|
name: _t("Is not empty"),
|
|
40715
40738
|
getPreview: () => _t("Is not empty"),
|
|
40716
40739
|
});
|
|
40740
|
+
criterionEvaluatorRegistry.add("top10", {
|
|
40741
|
+
type: "top10",
|
|
40742
|
+
preComputeCriterion: (criterion, criterionRanges, getters) => {
|
|
40743
|
+
let value = tryToNumber(criterion.values[0], DEFAULT_LOCALE);
|
|
40744
|
+
if (value === undefined || value <= 0) {
|
|
40745
|
+
return undefined;
|
|
40746
|
+
}
|
|
40747
|
+
const numberValues = [];
|
|
40748
|
+
for (const range of criterionRanges) {
|
|
40749
|
+
for (const value of getters.getRangeValues(range)) {
|
|
40750
|
+
if (typeof value === "number") {
|
|
40751
|
+
numberValues.push(value);
|
|
40752
|
+
}
|
|
40753
|
+
}
|
|
40754
|
+
}
|
|
40755
|
+
const sortedValues = numberValues.sort((a, b) => a - b);
|
|
40756
|
+
if (criterion.isPercent) {
|
|
40757
|
+
value = clip(value, 1, 100);
|
|
40758
|
+
}
|
|
40759
|
+
let index = 0;
|
|
40760
|
+
if (criterion.isBottom && !criterion.isPercent) {
|
|
40761
|
+
index = value - 1;
|
|
40762
|
+
}
|
|
40763
|
+
else if (criterion.isBottom && criterion.isPercent) {
|
|
40764
|
+
index = Math.floor((sortedValues.length * value) / 100) - 1;
|
|
40765
|
+
}
|
|
40766
|
+
else if (!criterion.isBottom && criterion.isPercent) {
|
|
40767
|
+
index = sortedValues.length - Math.floor((sortedValues.length * value) / 100);
|
|
40768
|
+
}
|
|
40769
|
+
else {
|
|
40770
|
+
index = sortedValues.length - value;
|
|
40771
|
+
}
|
|
40772
|
+
index = clip(index, 0, sortedValues.length - 1);
|
|
40773
|
+
return sortedValues[index];
|
|
40774
|
+
},
|
|
40775
|
+
isValueValid: (value, criterion, threshold) => {
|
|
40776
|
+
if (typeof value !== "number" || threshold === undefined) {
|
|
40777
|
+
return false;
|
|
40778
|
+
}
|
|
40779
|
+
return criterion.isBottom ? value <= threshold : value >= threshold;
|
|
40780
|
+
},
|
|
40781
|
+
getErrorString: (criterion) => {
|
|
40782
|
+
const args = {
|
|
40783
|
+
value: String(criterion.values[0]),
|
|
40784
|
+
percentSymbol: criterion.isPercent ? "%" : "",
|
|
40785
|
+
};
|
|
40786
|
+
return criterion.isBottom
|
|
40787
|
+
? _t("The value must be in bottom %(value)s%(percentSymbol)s", args)
|
|
40788
|
+
: _t("The value must be in top %(value)s%(percentSymbol)s", args);
|
|
40789
|
+
},
|
|
40790
|
+
isCriterionValueValid: (value) => checkValueIsPositiveNumber(value),
|
|
40791
|
+
criterionValueErrorString: DVTerms.CriterionError.positiveNumber,
|
|
40792
|
+
numberOfValues: () => 1,
|
|
40793
|
+
name: _t("Is in Top/Bottom ranking"),
|
|
40794
|
+
getPreview: (criterion) => {
|
|
40795
|
+
const args = { value: criterion.values[0], percentSymbol: criterion.isPercent ? "%" : "" };
|
|
40796
|
+
return criterion.isBottom
|
|
40797
|
+
? _t("Value is in bottom %(value)s%(percentSymbol)s", args)
|
|
40798
|
+
: _t("Value is in top %(value)s%(percentSymbol)s", args);
|
|
40799
|
+
},
|
|
40800
|
+
});
|
|
40717
40801
|
function getNumberCriterionlocalizedValues(criterion, locale) {
|
|
40718
40802
|
return criterion.values.map((value) => {
|
|
40719
40803
|
return value !== undefined
|
|
@@ -40735,6 +40819,10 @@ function checkValueIsNumber(value) {
|
|
|
40735
40819
|
const valueAsNumber = tryToNumber(value, DEFAULT_LOCALE);
|
|
40736
40820
|
return valueAsNumber !== undefined;
|
|
40737
40821
|
}
|
|
40822
|
+
function checkValueIsPositiveNumber(value) {
|
|
40823
|
+
const valueAsNumber = tryToNumber(value, DEFAULT_LOCALE);
|
|
40824
|
+
return valueAsNumber !== undefined && valueAsNumber > 0;
|
|
40825
|
+
}
|
|
40738
40826
|
|
|
40739
40827
|
// -----------------------------------------------------------------------------
|
|
40740
40828
|
// Constants
|
|
@@ -51109,6 +51197,10 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
|
|
|
51109
51197
|
break;
|
|
51110
51198
|
case "CellIsRule":
|
|
51111
51199
|
const formulas = cf.rule.values.map((value) => value.startsWith("=") ? compile(value) : undefined);
|
|
51200
|
+
const evaluator = criterionEvaluatorRegistry.get(cf.rule.operator);
|
|
51201
|
+
const criterion = { ...cf.rule, type: cf.rule.operator };
|
|
51202
|
+
const ranges = cf.ranges.map((xc) => this.getters.getRangeFromSheetXC(sheetId, xc));
|
|
51203
|
+
const preComputedCriterion = evaluator.preComputeCriterion?.(criterion, ranges, this.getters);
|
|
51112
51204
|
for (const ref of cf.ranges) {
|
|
51113
51205
|
const zone = this.getters.getRangeFromSheetXC(sheetId, ref).zone;
|
|
51114
51206
|
for (let row = zone.top; row <= zone.bottom; row++) {
|
|
@@ -51121,7 +51213,7 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
|
|
|
51121
51213
|
}
|
|
51122
51214
|
return value;
|
|
51123
51215
|
});
|
|
51124
|
-
if (this.getRuleResultForTarget(target, { ...cf.rule, values })) {
|
|
51216
|
+
if (this.getRuleResultForTarget(target, { ...cf.rule, values }, preComputedCriterion)) {
|
|
51125
51217
|
if (!computedStyle[col])
|
|
51126
51218
|
computedStyle[col] = [];
|
|
51127
51219
|
// we must combine all the properties of all the CF rules applied to the given cell
|
|
@@ -51284,7 +51376,7 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
|
|
|
51284
51376
|
}
|
|
51285
51377
|
}
|
|
51286
51378
|
}
|
|
51287
|
-
getRuleResultForTarget(target, rule) {
|
|
51379
|
+
getRuleResultForTarget(target, rule, preComputedCriterion) {
|
|
51288
51380
|
const cell = this.getters.getEvaluatedCell(target);
|
|
51289
51381
|
if (cell.type === CellValueType.error) {
|
|
51290
51382
|
return false;
|
|
@@ -51301,11 +51393,12 @@ class EvaluationConditionalFormatPlugin extends CoreViewPlugin {
|
|
|
51301
51393
|
return false;
|
|
51302
51394
|
}
|
|
51303
51395
|
const evaluatedCriterion = {
|
|
51396
|
+
...rule,
|
|
51304
51397
|
type: rule.operator,
|
|
51305
51398
|
values: evaluatedCriterionValues.map(toScalar),
|
|
51306
51399
|
dateValue: rule.dateValue || "exactDate",
|
|
51307
51400
|
};
|
|
51308
|
-
return evaluator.isValueValid(cell.value ?? "", evaluatedCriterion,
|
|
51401
|
+
return evaluator.isValueValid(cell.value ?? "", evaluatedCriterion, preComputedCriterion);
|
|
51309
51402
|
}
|
|
51310
51403
|
}
|
|
51311
51404
|
|
|
@@ -51322,17 +51415,20 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
|
|
|
51322
51415
|
"isDataValidationInvalid",
|
|
51323
51416
|
];
|
|
51324
51417
|
validationResults = {};
|
|
51418
|
+
criterionPreComputeResult = {};
|
|
51325
51419
|
handle(cmd) {
|
|
51326
51420
|
if (invalidateEvaluationCommands.has(cmd.type) ||
|
|
51327
51421
|
cmd.type === "EVALUATE_CELLS" ||
|
|
51328
51422
|
(cmd.type === "UPDATE_CELL" && ("content" in cmd || "format" in cmd))) {
|
|
51329
51423
|
this.validationResults = {};
|
|
51424
|
+
this.criterionPreComputeResult = {};
|
|
51330
51425
|
return;
|
|
51331
51426
|
}
|
|
51332
51427
|
switch (cmd.type) {
|
|
51333
51428
|
case "ADD_DATA_VALIDATION_RULE":
|
|
51334
51429
|
case "REMOVE_DATA_VALIDATION_RULE":
|
|
51335
51430
|
delete this.validationResults[cmd.sheetId];
|
|
51431
|
+
delete this.criterionPreComputeResult[cmd.sheetId];
|
|
51336
51432
|
break;
|
|
51337
51433
|
}
|
|
51338
51434
|
}
|
|
@@ -51475,7 +51571,15 @@ class EvaluationDataValidationPlugin extends CoreViewPlugin {
|
|
|
51475
51571
|
return undefined;
|
|
51476
51572
|
}
|
|
51477
51573
|
const evaluatedCriterion = { ...criterion, values: evaluatedCriterionValues.map(toScalar) };
|
|
51478
|
-
if (
|
|
51574
|
+
if (!this.criterionPreComputeResult[sheetId]) {
|
|
51575
|
+
this.criterionPreComputeResult[sheetId] = {};
|
|
51576
|
+
}
|
|
51577
|
+
let preComputedCriterion = this.criterionPreComputeResult[sheetId][rule.id];
|
|
51578
|
+
if (preComputedCriterion === undefined) {
|
|
51579
|
+
preComputedCriterion = evaluator.preComputeCriterion?.(rule.criterion, rule.ranges, this.getters);
|
|
51580
|
+
this.criterionPreComputeResult[sheetId][rule.id] = preComputedCriterion;
|
|
51581
|
+
}
|
|
51582
|
+
if (evaluator.isValueValid(cellValue, evaluatedCriterion, preComputedCriterion)) {
|
|
51479
51583
|
return undefined;
|
|
51480
51584
|
}
|
|
51481
51585
|
return evaluator.getErrorString(evaluatedCriterion, this.getters, sheetId);
|
|
@@ -57170,6 +57274,7 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
57170
57274
|
if (filterValue.type === "none")
|
|
57171
57275
|
continue;
|
|
57172
57276
|
const evaluator = criterionEvaluatorRegistry.get(filterValue.type);
|
|
57277
|
+
const preComputedCriterion = evaluator.preComputeCriterion?.(filterValue, [filter.filteredRange], this.getters);
|
|
57173
57278
|
const evaluatedCriterionValues = filterValue.values.map((value) => {
|
|
57174
57279
|
if (!value.startsWith("=")) {
|
|
57175
57280
|
return parseLiteral(value, DEFAULT_LOCALE);
|
|
@@ -57187,7 +57292,7 @@ class FilterEvaluationPlugin extends UIPlugin {
|
|
|
57187
57292
|
for (let row = filteredZone.top; row <= filteredZone.bottom; row++) {
|
|
57188
57293
|
const position = { sheetId, col: filter.col, row };
|
|
57189
57294
|
const value = this.getters.getEvaluatedCell(position).value ?? "";
|
|
57190
|
-
if (!evaluator.isValueValid(value, evaluatedCriterion,
|
|
57295
|
+
if (!evaluator.isValueValid(value, evaluatedCriterion, preComputedCriterion)) {
|
|
57191
57296
|
hiddenRows.add(row);
|
|
57192
57297
|
}
|
|
57193
57298
|
}
|
|
@@ -61314,6 +61419,8 @@ function cellRuleFormula(ranges, rule) {
|
|
|
61314
61419
|
case undefined:
|
|
61315
61420
|
throw new Error("dateValue should be defined");
|
|
61316
61421
|
}
|
|
61422
|
+
case "top10":
|
|
61423
|
+
return [];
|
|
61317
61424
|
}
|
|
61318
61425
|
}
|
|
61319
61426
|
function cellRuleTypeAttributes(rule) {
|
|
@@ -61346,6 +61453,14 @@ function cellRuleTypeAttributes(rule) {
|
|
|
61346
61453
|
case "dateIs":
|
|
61347
61454
|
case "customFormula":
|
|
61348
61455
|
return [["type", "expression"]];
|
|
61456
|
+
case "top10": {
|
|
61457
|
+
return [
|
|
61458
|
+
["type", "top10"],
|
|
61459
|
+
["rank", rule.values[0]],
|
|
61460
|
+
["percent", rule.isPercent ? "1" : "0"],
|
|
61461
|
+
["bottom", rule.isBottom ? "1" : "0"],
|
|
61462
|
+
];
|
|
61463
|
+
}
|
|
61349
61464
|
}
|
|
61350
61465
|
}
|
|
61351
61466
|
function addDataBarRule(cf, rule) {
|
|
@@ -64928,13 +65043,16 @@ function downloadFile(dataUrl, fileName) {
|
|
|
64928
65043
|
document.body.removeChild(a);
|
|
64929
65044
|
}
|
|
64930
65045
|
/**
|
|
64931
|
-
* Detects
|
|
65046
|
+
* Detects the current browser brand and subsequent rendering engine
|
|
64932
65047
|
*/
|
|
64933
65048
|
function isBrowserFirefox() {
|
|
64934
65049
|
return /Firefox/i.test(navigator.userAgent);
|
|
64935
65050
|
}
|
|
65051
|
+
function isBrowserChrome() {
|
|
65052
|
+
return /Chrome/i.test(navigator.userAgent);
|
|
65053
|
+
}
|
|
64936
65054
|
function isBrowserSafari() {
|
|
64937
|
-
return /Safari/i.test(navigator.userAgent);
|
|
65055
|
+
return !isBrowserChrome() && /Safari/i.test(navigator.userAgent);
|
|
64938
65056
|
}
|
|
64939
65057
|
// Mobile detection
|
|
64940
65058
|
function maxTouchPoints() {
|
|
@@ -65063,6 +65181,7 @@ const cfOperators = [
|
|
|
65063
65181
|
"dateIsAfter",
|
|
65064
65182
|
"dateIsOnOrBefore",
|
|
65065
65183
|
"dateIsOnOrAfter",
|
|
65184
|
+
"top10",
|
|
65066
65185
|
];
|
|
65067
65186
|
const availableConditionalFormatOperators = new Set(cfOperators);
|
|
65068
65187
|
|
|
@@ -73034,6 +73153,26 @@ class SingleInputCriterionForm extends CriterionForm {
|
|
|
73034
73153
|
}
|
|
73035
73154
|
}
|
|
73036
73155
|
|
|
73156
|
+
class Top10CriterionForm extends CriterionForm {
|
|
73157
|
+
static template = "o-spreadsheet-Top10CriterionForm";
|
|
73158
|
+
static components = { CriterionInput };
|
|
73159
|
+
onValueChanged(value) {
|
|
73160
|
+
const criterion = deepCopy(this.props.criterion);
|
|
73161
|
+
criterion.values[0] = value;
|
|
73162
|
+
this.updateCriterion(criterion);
|
|
73163
|
+
}
|
|
73164
|
+
updateIsBottom(ev) {
|
|
73165
|
+
const criterion = deepCopy(this.props.criterion);
|
|
73166
|
+
criterion.isBottom = ev.target.value === "bottom";
|
|
73167
|
+
this.updateCriterion(criterion);
|
|
73168
|
+
}
|
|
73169
|
+
updateIsPercent(ev) {
|
|
73170
|
+
const criterion = deepCopy(this.props.criterion);
|
|
73171
|
+
criterion.isPercent = ev.target.value === "percent";
|
|
73172
|
+
this.updateCriterion(criterion);
|
|
73173
|
+
}
|
|
73174
|
+
}
|
|
73175
|
+
|
|
73037
73176
|
/**
|
|
73038
73177
|
* Start listening to pointer events and apply the given callbacks.
|
|
73039
73178
|
*
|
|
@@ -74203,6 +74342,7 @@ const criterionCategoriesSequences = {
|
|
|
74203
74342
|
text: 20,
|
|
74204
74343
|
number: 30,
|
|
74205
74344
|
date: 40,
|
|
74345
|
+
relative: 45,
|
|
74206
74346
|
misc: 50,
|
|
74207
74347
|
};
|
|
74208
74348
|
const criterionComponentRegistry = new Registry$1();
|
|
@@ -74380,6 +74520,12 @@ criterionComponentRegistry.add("isNotEmpty", {
|
|
|
74380
74520
|
category: "misc",
|
|
74381
74521
|
sequence: 6,
|
|
74382
74522
|
});
|
|
74523
|
+
criterionComponentRegistry.add("top10", {
|
|
74524
|
+
type: "top10",
|
|
74525
|
+
component: Top10CriterionForm,
|
|
74526
|
+
category: "relative",
|
|
74527
|
+
sequence: 7,
|
|
74528
|
+
});
|
|
74383
74529
|
function getCriterionMenuItems(callback, availableTypes) {
|
|
74384
74530
|
const items = criterionComponentRegistry
|
|
74385
74531
|
.getAll()
|
|
@@ -76010,7 +76156,17 @@ const FORMAT_PERCENT_ACTION = (env) => setFormatter(env, "0.00%");
|
|
|
76010
76156
|
// Side panel
|
|
76011
76157
|
//------------------------------------------------------------------------------
|
|
76012
76158
|
const OPEN_CF_SIDEPANEL_ACTION = (env) => {
|
|
76013
|
-
|
|
76159
|
+
const sheetId = env.model.getters.getActiveSheetId();
|
|
76160
|
+
const zones = env.model.getters.getSelectedZones();
|
|
76161
|
+
const rules = env.model.getters.getConditionalFormats(sheetId);
|
|
76162
|
+
const ruleIds = env.model.getters.getRulesSelection(sheetId, zones);
|
|
76163
|
+
if (ruleIds.length === 1) {
|
|
76164
|
+
return env.openSidePanel("ConditionalFormattingEditor", {
|
|
76165
|
+
cf: rules.find((r) => r.id === ruleIds[0]),
|
|
76166
|
+
isNewCf: false,
|
|
76167
|
+
});
|
|
76168
|
+
}
|
|
76169
|
+
return env.openSidePanel("ConditionalFormatting");
|
|
76014
76170
|
};
|
|
76015
76171
|
const INSERT_LINK = (env) => {
|
|
76016
76172
|
const { col, row } = env.model.getters.getActivePosition();
|
|
@@ -77008,12 +77164,12 @@ const insertDropdown = {
|
|
|
77008
77164
|
const zones = env.model.getters.getSelectedZones();
|
|
77009
77165
|
const sheetId = env.model.getters.getActiveSheetId();
|
|
77010
77166
|
const ranges = zones.map((zone) => env.model.getters.getRangeDataFromZone(sheetId, zone));
|
|
77011
|
-
const
|
|
77167
|
+
const ruleId = env.model.uuidGenerator.smallUuid();
|
|
77012
77168
|
env.model.dispatch("ADD_DATA_VALIDATION_RULE", {
|
|
77013
77169
|
ranges,
|
|
77014
77170
|
sheetId,
|
|
77015
77171
|
rule: {
|
|
77016
|
-
id:
|
|
77172
|
+
id: ruleId,
|
|
77017
77173
|
criterion: {
|
|
77018
77174
|
type: "isValueInList",
|
|
77019
77175
|
values: [],
|
|
@@ -77021,16 +77177,11 @@ const insertDropdown = {
|
|
|
77021
77177
|
},
|
|
77022
77178
|
},
|
|
77023
77179
|
});
|
|
77024
|
-
const rule = env.model.getters.getDataValidationRule(sheetId,
|
|
77180
|
+
const rule = env.model.getters.getDataValidationRule(sheetId, ruleId);
|
|
77025
77181
|
if (!rule) {
|
|
77026
77182
|
return;
|
|
77027
77183
|
}
|
|
77028
|
-
env.openSidePanel("DataValidationEditor", {
|
|
77029
|
-
rule: localizeDataValidationRule(rule, env.model.getters.getLocale()),
|
|
77030
|
-
onExit: () => {
|
|
77031
|
-
env.replaceSidePanel("DataValidation", "DataValidationEditor");
|
|
77032
|
-
},
|
|
77033
|
-
});
|
|
77184
|
+
env.openSidePanel("DataValidationEditor", { ruleId });
|
|
77034
77185
|
},
|
|
77035
77186
|
isEnabled: (env) => !env.isSmall,
|
|
77036
77187
|
icon: "o-spreadsheet-Icon.INSERT_DROPDOWN",
|
|
@@ -85482,210 +85633,36 @@ class IconPicker extends Component {
|
|
|
85482
85633
|
}
|
|
85483
85634
|
}
|
|
85484
85635
|
|
|
85485
|
-
|
|
85486
|
-
|
|
85487
|
-
useHighlights({
|
|
85488
|
-
get highlights() {
|
|
85489
|
-
return hoverState.hovered ? highlightProvider.highlights : [];
|
|
85490
|
-
},
|
|
85491
|
-
});
|
|
85492
|
-
}
|
|
85493
|
-
function useHighlights(highlightProvider) {
|
|
85494
|
-
const stores = useStoreProvider();
|
|
85495
|
-
const store = useLocalStore(HighlightStore);
|
|
85496
|
-
onMounted(() => {
|
|
85497
|
-
store.register(highlightProvider);
|
|
85498
|
-
});
|
|
85499
|
-
let currentHighlights = highlightProvider.highlights;
|
|
85500
|
-
useEffect((highlights) => {
|
|
85501
|
-
if (!deepEquals(highlights, currentHighlights)) {
|
|
85502
|
-
currentHighlights = highlights;
|
|
85503
|
-
stores.trigger("store-updated");
|
|
85504
|
-
}
|
|
85505
|
-
}, () => [highlightProvider.highlights]);
|
|
85506
|
-
}
|
|
85507
|
-
|
|
85508
|
-
class ConditionalFormatPreview extends Component {
|
|
85509
|
-
static template = "o-spreadsheet-ConditionalFormatPreview";
|
|
85510
|
-
icons = ICONS;
|
|
85511
|
-
ref = useRef("cfPreview");
|
|
85512
|
-
setup() {
|
|
85513
|
-
useHighlightsOnHover(this.ref, this);
|
|
85514
|
-
}
|
|
85515
|
-
getPreviewImageStyle() {
|
|
85516
|
-
const rule = this.props.conditionalFormat.rule;
|
|
85517
|
-
if (rule.type === "CellIsRule") {
|
|
85518
|
-
return cssPropertiesToCss(cellStyleToCss(rule.style));
|
|
85519
|
-
}
|
|
85520
|
-
else if (rule.type === "ColorScaleRule") {
|
|
85521
|
-
const minColor = colorNumberToHex(rule.minimum.color);
|
|
85522
|
-
const midColor = rule.midpoint ? colorNumberToHex(rule.midpoint.color) : null;
|
|
85523
|
-
const maxColor = colorNumberToHex(rule.maximum.color);
|
|
85524
|
-
const baseString = "background-image: linear-gradient(to right, ";
|
|
85525
|
-
return midColor
|
|
85526
|
-
? baseString + minColor + ", " + midColor + ", " + maxColor + ")"
|
|
85527
|
-
: baseString + minColor + ", " + maxColor + ")";
|
|
85528
|
-
}
|
|
85529
|
-
else if (rule.type === "DataBarRule") {
|
|
85530
|
-
const barColor = colorNumberToHex(rule.color);
|
|
85531
|
-
const gradient = `background-image: linear-gradient(to right, ${barColor} 50%, white 50%)`;
|
|
85532
|
-
return `${gradient}; color: ${TEXT_BODY};`;
|
|
85533
|
-
}
|
|
85534
|
-
return "";
|
|
85535
|
-
}
|
|
85536
|
-
getDescription() {
|
|
85537
|
-
const cf = this.props.conditionalFormat;
|
|
85538
|
-
switch (cf.rule.type) {
|
|
85539
|
-
case "CellIsRule":
|
|
85540
|
-
return criterionEvaluatorRegistry
|
|
85541
|
-
.get(cf.rule.operator)
|
|
85542
|
-
.getPreview({ ...cf.rule, type: cf.rule.operator }, this.env.model.getters);
|
|
85543
|
-
case "ColorScaleRule":
|
|
85544
|
-
return CfTerms.ColorScale;
|
|
85545
|
-
case "IconSetRule":
|
|
85546
|
-
return CfTerms.IconSet;
|
|
85547
|
-
case "DataBarRule":
|
|
85548
|
-
return CfTerms.DataBar;
|
|
85549
|
-
}
|
|
85550
|
-
}
|
|
85551
|
-
deleteConditionalFormat() {
|
|
85552
|
-
this.env.model.dispatch("REMOVE_CONDITIONAL_FORMAT", {
|
|
85553
|
-
id: this.props.conditionalFormat.id,
|
|
85554
|
-
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
85555
|
-
});
|
|
85556
|
-
}
|
|
85557
|
-
onMouseDown(event) {
|
|
85558
|
-
this.props.onMouseDown(event);
|
|
85559
|
-
}
|
|
85560
|
-
get highlights() {
|
|
85561
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
85562
|
-
return this.props.conditionalFormat.ranges.map((range) => ({
|
|
85563
|
-
range: this.env.model.getters.getRangeFromSheetXC(sheetId, range),
|
|
85564
|
-
color: HIGHLIGHT_COLOR,
|
|
85565
|
-
fillAlpha: 0.06,
|
|
85566
|
-
}));
|
|
85567
|
-
}
|
|
85568
|
-
}
|
|
85569
|
-
ConditionalFormatPreview.props = {
|
|
85570
|
-
conditionalFormat: Object,
|
|
85571
|
-
onPreviewClick: Function,
|
|
85572
|
-
onMouseDown: Function,
|
|
85573
|
-
class: String,
|
|
85574
|
-
};
|
|
85575
|
-
|
|
85576
|
-
class ConditionalFormatPreviewList extends Component {
|
|
85577
|
-
static template = "o-spreadsheet-ConditionalFormatPreviewList";
|
|
85578
|
-
static props = {
|
|
85579
|
-
conditionalFormats: Array,
|
|
85580
|
-
onPreviewClick: Function,
|
|
85581
|
-
onAddConditionalFormat: Function,
|
|
85582
|
-
};
|
|
85583
|
-
static components = { ConditionalFormatPreview };
|
|
85584
|
-
icons = ICONS;
|
|
85585
|
-
dragAndDrop = useDragAndDropListItems();
|
|
85586
|
-
cfListRef = useRef("cfList");
|
|
85587
|
-
setup() {
|
|
85588
|
-
onWillUpdateProps((nextProps) => {
|
|
85589
|
-
if (!deepEquals(this.props.conditionalFormats, nextProps.conditionalFormats)) {
|
|
85590
|
-
this.dragAndDrop.cancel();
|
|
85591
|
-
}
|
|
85592
|
-
});
|
|
85593
|
-
}
|
|
85594
|
-
getPreviewDivStyle(cf) {
|
|
85595
|
-
return this.dragAndDrop.itemsStyle[cf.id] || "";
|
|
85596
|
-
}
|
|
85597
|
-
onPreviewMouseDown(cf, event) {
|
|
85598
|
-
if (event.button !== 0)
|
|
85599
|
-
return;
|
|
85600
|
-
const previewRects = Array.from(this.cfListRef.el.children).map((previewEl) => getBoundingRectAsPOJO(previewEl));
|
|
85601
|
-
const items = this.props.conditionalFormats.map((cf, index) => ({
|
|
85602
|
-
id: cf.id,
|
|
85603
|
-
size: previewRects[index].height,
|
|
85604
|
-
position: previewRects[index].y,
|
|
85605
|
-
}));
|
|
85606
|
-
this.dragAndDrop.start("vertical", {
|
|
85607
|
-
draggedItemId: cf.id,
|
|
85608
|
-
initialMousePosition: event.clientY,
|
|
85609
|
-
items: items,
|
|
85610
|
-
scrollableContainerEl: this.cfListRef.el,
|
|
85611
|
-
onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
|
|
85612
|
-
});
|
|
85613
|
-
}
|
|
85614
|
-
onDragEnd(cfId, finalIndex) {
|
|
85615
|
-
const originalIndex = this.props.conditionalFormats.findIndex((sheet) => sheet.id === cfId);
|
|
85616
|
-
const delta = originalIndex - finalIndex;
|
|
85617
|
-
if (delta !== 0) {
|
|
85618
|
-
this.env.model.dispatch("CHANGE_CONDITIONAL_FORMAT_PRIORITY", {
|
|
85619
|
-
cfId,
|
|
85620
|
-
delta,
|
|
85621
|
-
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
85622
|
-
});
|
|
85623
|
-
}
|
|
85624
|
-
}
|
|
85625
|
-
}
|
|
85626
|
-
|
|
85627
|
-
class ConditionalFormattingEditor extends Component {
|
|
85628
|
-
static template = "o-spreadsheet-ConditionalFormattingEditor";
|
|
85629
|
-
static props = {
|
|
85630
|
-
editedCf: Object,
|
|
85631
|
-
onCancel: Function,
|
|
85632
|
-
onExit: Function,
|
|
85633
|
-
isNewCf: Boolean,
|
|
85634
|
-
};
|
|
85635
|
-
static components = {
|
|
85636
|
-
SelectionInput,
|
|
85637
|
-
IconPicker,
|
|
85638
|
-
ColorPickerWidget,
|
|
85639
|
-
ConditionalFormatPreviewList,
|
|
85640
|
-
Section,
|
|
85641
|
-
RoundColorPicker,
|
|
85642
|
-
StandaloneComposer,
|
|
85643
|
-
BadgeSelection,
|
|
85644
|
-
ValidationMessages,
|
|
85645
|
-
SelectMenu,
|
|
85646
|
-
};
|
|
85636
|
+
class ConditionalFormattingEditorStore extends SpreadsheetStore {
|
|
85637
|
+
mutators = ["updateConditionalFormat", "closeMenus"];
|
|
85647
85638
|
icons = ICONS;
|
|
85648
85639
|
iconSets = ICON_SETS;
|
|
85649
|
-
getTextDecoration = getTextDecoration;
|
|
85650
|
-
colorNumberToHex = colorNumberToHex;
|
|
85651
85640
|
state;
|
|
85652
|
-
|
|
85641
|
+
cfId;
|
|
85642
|
+
constructor(get, cf, isNewCf) {
|
|
85643
|
+
super(get);
|
|
85644
|
+
this.cfId = cf.id;
|
|
85653
85645
|
this.state = useState({
|
|
85654
85646
|
errors: [],
|
|
85655
|
-
currentCFType:
|
|
85656
|
-
ranges:
|
|
85647
|
+
currentCFType: cf.rule.type,
|
|
85648
|
+
ranges: cf.ranges,
|
|
85657
85649
|
rules: this.getDefaultRules(),
|
|
85658
|
-
hasEditedCf:
|
|
85650
|
+
hasEditedCf: isNewCf,
|
|
85659
85651
|
});
|
|
85660
|
-
switch (
|
|
85652
|
+
switch (cf.rule.type) {
|
|
85661
85653
|
case "CellIsRule":
|
|
85662
|
-
this.state.rules.cellIs =
|
|
85654
|
+
this.state.rules.cellIs = cf.rule;
|
|
85663
85655
|
break;
|
|
85664
85656
|
case "ColorScaleRule":
|
|
85665
|
-
this.state.rules.colorScale =
|
|
85657
|
+
this.state.rules.colorScale = cf.rule;
|
|
85666
85658
|
break;
|
|
85667
85659
|
case "IconSetRule":
|
|
85668
|
-
this.state.rules.iconSet =
|
|
85660
|
+
this.state.rules.iconSet = cf.rule;
|
|
85669
85661
|
break;
|
|
85670
85662
|
case "DataBarRule":
|
|
85671
|
-
this.state.rules.dataBar =
|
|
85663
|
+
this.state.rules.dataBar = cf.rule;
|
|
85672
85664
|
break;
|
|
85673
85665
|
}
|
|
85674
|
-
useExternalListener(window, "click", this.closeMenus);
|
|
85675
|
-
}
|
|
85676
|
-
get isRangeValid() {
|
|
85677
|
-
return this.state.errors.includes("EmptyRange" /* CommandResult.EmptyRange */);
|
|
85678
|
-
}
|
|
85679
|
-
get errorMessages() {
|
|
85680
|
-
return this.state.errors.map((error) => CfTerms.Errors[error] || CfTerms.Errors.Unexpected);
|
|
85681
|
-
}
|
|
85682
|
-
get cfTypesValues() {
|
|
85683
|
-
return [
|
|
85684
|
-
{ value: "CellIsRule", label: _t("Single color") },
|
|
85685
|
-
{ value: "ColorScaleRule", label: _t("Color scale") },
|
|
85686
|
-
{ value: "IconSetRule", label: _t("Icon set") },
|
|
85687
|
-
{ value: "DataBarRule", label: _t("Data bar") },
|
|
85688
|
-
];
|
|
85689
85666
|
}
|
|
85690
85667
|
updateConditionalFormat(newCf) {
|
|
85691
85668
|
const ranges = newCf.ranges || this.state.ranges;
|
|
@@ -85694,17 +85671,17 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85694
85671
|
if (!newCf.suppressErrors) {
|
|
85695
85672
|
this.state.errors = ["InvalidRange" /* CommandResult.InvalidRange */];
|
|
85696
85673
|
}
|
|
85697
|
-
return
|
|
85674
|
+
return;
|
|
85698
85675
|
}
|
|
85699
|
-
const sheetId = this.
|
|
85700
|
-
const locale = this.
|
|
85676
|
+
const sheetId = this.model.getters.getActiveSheetId();
|
|
85677
|
+
const locale = this.model.getters.getLocale();
|
|
85701
85678
|
const rule = newCf.rule || this.getEditedRule(this.state.currentCFType);
|
|
85702
|
-
const result = this.
|
|
85679
|
+
const result = this.model.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
85703
85680
|
cf: {
|
|
85681
|
+
id: this.cfId,
|
|
85704
85682
|
rule: canonicalizeCFRule(rule, locale),
|
|
85705
|
-
id: this.props.editedCf.id,
|
|
85706
85683
|
},
|
|
85707
|
-
ranges: ranges.map((xc) => this.
|
|
85684
|
+
ranges: ranges.map((xc) => this.model.getters.getRangeDataFromXc(sheetId, xc)),
|
|
85708
85685
|
sheetId,
|
|
85709
85686
|
});
|
|
85710
85687
|
if (result.isSuccessful) {
|
|
@@ -85714,71 +85691,18 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85714
85691
|
if (!newCf.suppressErrors) {
|
|
85715
85692
|
this.state.errors = reasons;
|
|
85716
85693
|
}
|
|
85717
|
-
return reasons;
|
|
85718
85694
|
}
|
|
85719
|
-
|
|
85720
|
-
|
|
85721
|
-
case "CellIsRule":
|
|
85722
|
-
return this.state.rules.cellIs;
|
|
85723
|
-
case "ColorScaleRule":
|
|
85724
|
-
return this.state.rules.colorScale;
|
|
85725
|
-
case "IconSetRule":
|
|
85726
|
-
return this.state.rules.iconSet;
|
|
85727
|
-
case "DataBarRule":
|
|
85728
|
-
return this.state.rules.dataBar;
|
|
85729
|
-
}
|
|
85695
|
+
get isRangeValid() {
|
|
85696
|
+
return this.state.errors.includes("EmptyRange" /* CommandResult.EmptyRange */);
|
|
85730
85697
|
}
|
|
85731
|
-
|
|
85732
|
-
|
|
85733
|
-
if (result.length === 0) {
|
|
85734
|
-
this.props.onExit();
|
|
85735
|
-
}
|
|
85698
|
+
get errorMessages() {
|
|
85699
|
+
return this.state.errors.map((error) => CfTerms.Errors[error] || CfTerms.Errors.Unexpected);
|
|
85736
85700
|
}
|
|
85737
|
-
|
|
85738
|
-
|
|
85739
|
-
this.props.onCancel();
|
|
85740
|
-
}
|
|
85741
|
-
else {
|
|
85742
|
-
this.props.onExit();
|
|
85743
|
-
}
|
|
85701
|
+
onRangeUpdate(ranges) {
|
|
85702
|
+
this.state.ranges = ranges;
|
|
85744
85703
|
}
|
|
85745
|
-
|
|
85746
|
-
|
|
85747
|
-
cellIs: {
|
|
85748
|
-
type: "CellIsRule",
|
|
85749
|
-
operator: "isNotEmpty",
|
|
85750
|
-
values: [],
|
|
85751
|
-
style: { fillColor: "#b6d7a8" },
|
|
85752
|
-
},
|
|
85753
|
-
colorScale: {
|
|
85754
|
-
type: "ColorScaleRule",
|
|
85755
|
-
minimum: { type: "value", color: hexaToInt("EFF7FF") },
|
|
85756
|
-
midpoint: undefined,
|
|
85757
|
-
maximum: { type: "value", color: 0x6aa84f },
|
|
85758
|
-
},
|
|
85759
|
-
iconSet: {
|
|
85760
|
-
type: "IconSetRule",
|
|
85761
|
-
icons: {
|
|
85762
|
-
upper: "arrowGood",
|
|
85763
|
-
middle: "arrowNeutral",
|
|
85764
|
-
lower: "arrowBad",
|
|
85765
|
-
},
|
|
85766
|
-
upperInflectionPoint: {
|
|
85767
|
-
type: "percentage",
|
|
85768
|
-
value: "66",
|
|
85769
|
-
operator: "gt",
|
|
85770
|
-
},
|
|
85771
|
-
lowerInflectionPoint: {
|
|
85772
|
-
type: "percentage",
|
|
85773
|
-
value: "33",
|
|
85774
|
-
operator: "gt",
|
|
85775
|
-
},
|
|
85776
|
-
},
|
|
85777
|
-
dataBar: {
|
|
85778
|
-
type: "DataBarRule",
|
|
85779
|
-
color: 0xd9ead3,
|
|
85780
|
-
},
|
|
85781
|
-
};
|
|
85704
|
+
onRangeConfirmed() {
|
|
85705
|
+
this.updateConditionalFormat({ ranges: this.state.ranges });
|
|
85782
85706
|
}
|
|
85783
85707
|
changeRuleType(ruleType) {
|
|
85784
85708
|
if (this.state.currentCFType === ruleType) {
|
|
@@ -85788,34 +85712,45 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85788
85712
|
this.state.currentCFType = ruleType;
|
|
85789
85713
|
this.updateConditionalFormat({ rule: this.getEditedRule(ruleType), suppressErrors: true });
|
|
85790
85714
|
}
|
|
85791
|
-
|
|
85792
|
-
|
|
85793
|
-
|
|
85794
|
-
|
|
85795
|
-
|
|
85796
|
-
|
|
85797
|
-
|
|
85798
|
-
|
|
85799
|
-
|
|
85800
|
-
|
|
85801
|
-
const isSelected = this.state.openedMenu === menu;
|
|
85802
|
-
this.closeMenus();
|
|
85803
|
-
if (!isSelected) {
|
|
85804
|
-
this.state.openedMenu = menu;
|
|
85715
|
+
getEditedRule(ruleType) {
|
|
85716
|
+
switch (ruleType) {
|
|
85717
|
+
case "CellIsRule":
|
|
85718
|
+
return this.state.rules.cellIs;
|
|
85719
|
+
case "ColorScaleRule":
|
|
85720
|
+
return this.state.rules.colorScale;
|
|
85721
|
+
case "IconSetRule":
|
|
85722
|
+
return this.state.rules.iconSet;
|
|
85723
|
+
case "DataBarRule":
|
|
85724
|
+
return this.state.rules.dataBar;
|
|
85805
85725
|
}
|
|
85806
85726
|
}
|
|
85807
|
-
closeMenus() {
|
|
85808
|
-
this.state.openedMenu = undefined;
|
|
85809
|
-
}
|
|
85810
85727
|
/*****************************************************************************
|
|
85811
85728
|
* Cell Is Rule
|
|
85812
85729
|
****************************************************************************/
|
|
85813
|
-
get
|
|
85814
|
-
return (
|
|
85815
|
-
this.state.errors.includes("ValueCellIsInvalidFormula" /* CommandResult.ValueCellIsInvalidFormula */));
|
|
85730
|
+
get cfCriterionMenuItems() {
|
|
85731
|
+
return getCriterionMenuItems((type) => this.editOperator(type), availableConditionalFormatOperators);
|
|
85816
85732
|
}
|
|
85817
|
-
get
|
|
85818
|
-
return this.state.
|
|
85733
|
+
get selectedCriterionName() {
|
|
85734
|
+
return criterionEvaluatorRegistry.get(this.state.rules.cellIs.operator).name;
|
|
85735
|
+
}
|
|
85736
|
+
get criterionComponent() {
|
|
85737
|
+
return criterionComponentRegistry.get(this.state.rules.cellIs.operator).component;
|
|
85738
|
+
}
|
|
85739
|
+
get genericCriterion() {
|
|
85740
|
+
return {
|
|
85741
|
+
...this.state.rules.cellIs,
|
|
85742
|
+
type: this.state.rules.cellIs.operator,
|
|
85743
|
+
};
|
|
85744
|
+
}
|
|
85745
|
+
onRuleValuesChanged(criterion) {
|
|
85746
|
+
const newRule = {
|
|
85747
|
+
...criterion,
|
|
85748
|
+
operator: criterion.type,
|
|
85749
|
+
type: "CellIsRule",
|
|
85750
|
+
style: this.state.rules.cellIs.style,
|
|
85751
|
+
};
|
|
85752
|
+
this.state.rules.cellIs = newRule;
|
|
85753
|
+
this.updateConditionalFormat({ rule: newRule });
|
|
85819
85754
|
}
|
|
85820
85755
|
toggleStyle(tool) {
|
|
85821
85756
|
const style = this.state.rules.cellIs.style;
|
|
@@ -85823,18 +85758,6 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85823
85758
|
this.updateConditionalFormat({ rule: this.state.rules.cellIs });
|
|
85824
85759
|
this.closeMenus();
|
|
85825
85760
|
}
|
|
85826
|
-
onKeydown(event) {
|
|
85827
|
-
if (event.key === "F4") {
|
|
85828
|
-
const target = event.target;
|
|
85829
|
-
const update = cycleFixedReference({ start: target.selectionStart ?? 0, end: target.selectionEnd ?? 0 }, target.value, this.env.model.getters.getLocale());
|
|
85830
|
-
if (!update) {
|
|
85831
|
-
return;
|
|
85832
|
-
}
|
|
85833
|
-
target.value = update.content;
|
|
85834
|
-
target.setSelectionRange(update.selection.start, update.selection.end);
|
|
85835
|
-
target.dispatchEvent(new Event("input"));
|
|
85836
|
-
}
|
|
85837
|
-
}
|
|
85838
85761
|
setColor(target, color) {
|
|
85839
85762
|
this.state.rules.cellIs.style[target] = color;
|
|
85840
85763
|
this.updateConditionalFormat({ rule: this.state.rules.cellIs });
|
|
@@ -85848,62 +85771,10 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85848
85771
|
this.updateConditionalFormat({ rule: this.state.rules.cellIs, suppressErrors: true });
|
|
85849
85772
|
this.closeMenus();
|
|
85850
85773
|
}
|
|
85851
|
-
get cfCriterionMenuItems() {
|
|
85852
|
-
return getCriterionMenuItems((type) => this.editOperator(type), availableConditionalFormatOperators);
|
|
85853
|
-
}
|
|
85854
|
-
get selectedCriterionName() {
|
|
85855
|
-
return criterionEvaluatorRegistry.get(this.state.rules.cellIs.operator).name;
|
|
85856
|
-
}
|
|
85857
|
-
get criterionComponent() {
|
|
85858
|
-
return criterionComponentRegistry.get(this.state.rules.cellIs.operator).component;
|
|
85859
|
-
}
|
|
85860
|
-
get genericCriterion() {
|
|
85861
|
-
return {
|
|
85862
|
-
type: this.state.rules.cellIs.operator,
|
|
85863
|
-
values: this.state.rules.cellIs.values,
|
|
85864
|
-
dateValue: this.state.rules.cellIs.dateValue,
|
|
85865
|
-
};
|
|
85866
|
-
}
|
|
85867
|
-
onRuleValuesChanged(rule) {
|
|
85868
|
-
this.state.rules.cellIs.values = rule.values;
|
|
85869
|
-
this.state.rules.cellIs.dateValue = rule.dateValue;
|
|
85870
|
-
this.updateConditionalFormat({
|
|
85871
|
-
rule: { ...this.state.rules.cellIs, values: rule.values, dateValue: rule.dateValue },
|
|
85872
|
-
});
|
|
85873
|
-
}
|
|
85874
85774
|
/*****************************************************************************
|
|
85875
85775
|
* Color Scale Rule
|
|
85876
85776
|
****************************************************************************/
|
|
85877
|
-
|
|
85878
|
-
switch (threshold) {
|
|
85879
|
-
case "minimum":
|
|
85880
|
-
return (this.state.errors.includes("MinInvalidFormula" /* CommandResult.MinInvalidFormula */) ||
|
|
85881
|
-
this.state.errors.includes("MinBiggerThanMid" /* CommandResult.MinBiggerThanMid */) ||
|
|
85882
|
-
this.state.errors.includes("MinBiggerThanMax" /* CommandResult.MinBiggerThanMax */) ||
|
|
85883
|
-
this.state.errors.includes("MinNaN" /* CommandResult.MinNaN */));
|
|
85884
|
-
case "midpoint":
|
|
85885
|
-
return (this.state.errors.includes("MidInvalidFormula" /* CommandResult.MidInvalidFormula */) ||
|
|
85886
|
-
this.state.errors.includes("MidNaN" /* CommandResult.MidNaN */) ||
|
|
85887
|
-
this.state.errors.includes("MidBiggerThanMax" /* CommandResult.MidBiggerThanMax */));
|
|
85888
|
-
case "maximum":
|
|
85889
|
-
return (this.state.errors.includes("MaxInvalidFormula" /* CommandResult.MaxInvalidFormula */) ||
|
|
85890
|
-
this.state.errors.includes("MaxNaN" /* CommandResult.MaxNaN */));
|
|
85891
|
-
default:
|
|
85892
|
-
return false;
|
|
85893
|
-
}
|
|
85894
|
-
}
|
|
85895
|
-
setColorScaleColor(target, color) {
|
|
85896
|
-
if (!isColorValid(color)) {
|
|
85897
|
-
return;
|
|
85898
|
-
}
|
|
85899
|
-
const point = this.state.rules.colorScale[target];
|
|
85900
|
-
if (point) {
|
|
85901
|
-
point.color = colorToNumber(color);
|
|
85902
|
-
}
|
|
85903
|
-
this.updateConditionalFormat({ rule: this.state.rules.colorScale });
|
|
85904
|
-
this.closeMenus();
|
|
85905
|
-
}
|
|
85906
|
-
getColorScalePreviewStyle() {
|
|
85777
|
+
get previewGradient() {
|
|
85907
85778
|
const rule = this.state.rules.colorScale;
|
|
85908
85779
|
const minColor = colorNumberToHex(rule.minimum.color);
|
|
85909
85780
|
const midColor = colorNumberToHex(rule.midpoint?.color || DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
|
|
@@ -85917,13 +85788,7 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85917
85788
|
color: "#000",
|
|
85918
85789
|
});
|
|
85919
85790
|
}
|
|
85920
|
-
|
|
85921
|
-
return threshold
|
|
85922
|
-
? colorNumberToHex(threshold.color)
|
|
85923
|
-
: colorNumberToHex(DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
|
|
85924
|
-
}
|
|
85925
|
-
onMidpointChange(ev) {
|
|
85926
|
-
const type = ev.target.value;
|
|
85791
|
+
onMidpointChange(type) {
|
|
85927
85792
|
const rule = this.state.rules.colorScale;
|
|
85928
85793
|
if (type === "none") {
|
|
85929
85794
|
rule.midpoint = undefined;
|
|
@@ -85946,23 +85811,20 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85946
85811
|
this.state.rules.colorScale[threshold].value = value;
|
|
85947
85812
|
this.updateConditionalFormat({ rule: this.state.rules.colorScale });
|
|
85948
85813
|
}
|
|
85814
|
+
setColorScaleColor(target, color) {
|
|
85815
|
+
if (!isColorValid(color)) {
|
|
85816
|
+
return;
|
|
85817
|
+
}
|
|
85818
|
+
const point = this.state.rules.colorScale[target];
|
|
85819
|
+
if (point) {
|
|
85820
|
+
point.color = colorToNumber(color);
|
|
85821
|
+
}
|
|
85822
|
+
this.updateConditionalFormat({ rule: this.state.rules.colorScale });
|
|
85823
|
+
this.closeMenus();
|
|
85824
|
+
}
|
|
85949
85825
|
/*****************************************************************************
|
|
85950
85826
|
* Icon Set
|
|
85951
85827
|
****************************************************************************/
|
|
85952
|
-
isInflectionPointInvalid(inflectionPoint) {
|
|
85953
|
-
switch (inflectionPoint) {
|
|
85954
|
-
case "lowerInflectionPoint":
|
|
85955
|
-
return (this.state.errors.includes("ValueLowerInflectionNaN" /* CommandResult.ValueLowerInflectionNaN */) ||
|
|
85956
|
-
this.state.errors.includes("ValueLowerInvalidFormula" /* CommandResult.ValueLowerInvalidFormula */) ||
|
|
85957
|
-
this.state.errors.includes("LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */));
|
|
85958
|
-
case "upperInflectionPoint":
|
|
85959
|
-
return (this.state.errors.includes("ValueUpperInflectionNaN" /* CommandResult.ValueUpperInflectionNaN */) ||
|
|
85960
|
-
this.state.errors.includes("ValueUpperInvalidFormula" /* CommandResult.ValueUpperInvalidFormula */) ||
|
|
85961
|
-
this.state.errors.includes("LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */));
|
|
85962
|
-
default:
|
|
85963
|
-
return true;
|
|
85964
|
-
}
|
|
85965
|
-
}
|
|
85966
85828
|
reverseIcons() {
|
|
85967
85829
|
const icons = this.state.rules.iconSet.icons;
|
|
85968
85830
|
const upper = icons.upper;
|
|
@@ -85989,12 +85851,176 @@ class ConditionalFormattingEditor extends Component {
|
|
|
85989
85851
|
this.state.rules.iconSet[inflectionPoint].value = value;
|
|
85990
85852
|
this.updateConditionalFormat({ rule: this.state.rules.iconSet });
|
|
85991
85853
|
}
|
|
85992
|
-
setInflectionType(inflectionPoint, type
|
|
85854
|
+
setInflectionType(inflectionPoint, type) {
|
|
85993
85855
|
this.state.rules.iconSet[inflectionPoint].type = type;
|
|
85994
85856
|
this.updateConditionalFormat({ rule: this.state.rules.iconSet, suppressErrors: true });
|
|
85995
85857
|
}
|
|
85858
|
+
/*****************************************************************************
|
|
85859
|
+
* DataBar
|
|
85860
|
+
****************************************************************************/
|
|
85861
|
+
get rangeValues() {
|
|
85862
|
+
return [this.state.rules.dataBar.rangeValues || ""];
|
|
85863
|
+
}
|
|
85864
|
+
updateDataBarColor(color) {
|
|
85865
|
+
if (!isColorValid(color)) {
|
|
85866
|
+
return;
|
|
85867
|
+
}
|
|
85868
|
+
this.state.rules.dataBar.color = Number.parseInt(color.slice(1), 16);
|
|
85869
|
+
this.updateConditionalFormat({ rule: this.state.rules.dataBar });
|
|
85870
|
+
}
|
|
85871
|
+
onDataBarRangeUpdate(ranges) {
|
|
85872
|
+
this.state.rules.dataBar.rangeValues = ranges[0];
|
|
85873
|
+
}
|
|
85874
|
+
onDataBarRangeChange() {
|
|
85875
|
+
this.updateConditionalFormat({ rule: this.state.rules.dataBar });
|
|
85876
|
+
}
|
|
85877
|
+
/*****************************************************************************
|
|
85878
|
+
* Common
|
|
85879
|
+
****************************************************************************/
|
|
85880
|
+
toggleMenu(menu) {
|
|
85881
|
+
const isSelected = this.state.openedMenu === menu;
|
|
85882
|
+
this.closeMenus();
|
|
85883
|
+
if (!isSelected) {
|
|
85884
|
+
this.state.openedMenu = menu;
|
|
85885
|
+
}
|
|
85886
|
+
}
|
|
85887
|
+
closeMenus() {
|
|
85888
|
+
this.state.openedMenu = undefined;
|
|
85889
|
+
}
|
|
85890
|
+
getDefaultRules() {
|
|
85891
|
+
return {
|
|
85892
|
+
cellIs: {
|
|
85893
|
+
type: "CellIsRule",
|
|
85894
|
+
operator: "isNotEmpty",
|
|
85895
|
+
values: [],
|
|
85896
|
+
style: { fillColor: "#b6d7a8" },
|
|
85897
|
+
},
|
|
85898
|
+
colorScale: {
|
|
85899
|
+
type: "ColorScaleRule",
|
|
85900
|
+
minimum: { type: "value", color: hexaToInt("EFF7FF") },
|
|
85901
|
+
midpoint: undefined,
|
|
85902
|
+
maximum: { type: "value", color: 0x6aa84f },
|
|
85903
|
+
},
|
|
85904
|
+
iconSet: {
|
|
85905
|
+
type: "IconSetRule",
|
|
85906
|
+
icons: {
|
|
85907
|
+
upper: "arrowGood",
|
|
85908
|
+
middle: "arrowNeutral",
|
|
85909
|
+
lower: "arrowBad",
|
|
85910
|
+
},
|
|
85911
|
+
upperInflectionPoint: {
|
|
85912
|
+
type: "percentage",
|
|
85913
|
+
value: "66",
|
|
85914
|
+
operator: "gt",
|
|
85915
|
+
},
|
|
85916
|
+
lowerInflectionPoint: {
|
|
85917
|
+
type: "percentage",
|
|
85918
|
+
value: "33",
|
|
85919
|
+
operator: "gt",
|
|
85920
|
+
},
|
|
85921
|
+
},
|
|
85922
|
+
dataBar: {
|
|
85923
|
+
type: "DataBarRule",
|
|
85924
|
+
color: 0xd9ead3,
|
|
85925
|
+
},
|
|
85926
|
+
};
|
|
85927
|
+
}
|
|
85928
|
+
}
|
|
85929
|
+
|
|
85930
|
+
class ConditionalFormattingEditor extends Component {
|
|
85931
|
+
static template = "o-spreadsheet-ConditionalFormattingEditor";
|
|
85932
|
+
static components = {
|
|
85933
|
+
SelectionInput,
|
|
85934
|
+
IconPicker,
|
|
85935
|
+
ColorPickerWidget,
|
|
85936
|
+
Section,
|
|
85937
|
+
RoundColorPicker,
|
|
85938
|
+
StandaloneComposer,
|
|
85939
|
+
BadgeSelection,
|
|
85940
|
+
ValidationMessages,
|
|
85941
|
+
SelectMenu,
|
|
85942
|
+
};
|
|
85943
|
+
static props = { cf: Object, isNewCf: Boolean, onCloseSidePanel: Function };
|
|
85944
|
+
getTextDecoration = getTextDecoration;
|
|
85945
|
+
colorNumberToHex = colorNumberToHex;
|
|
85946
|
+
activeSheetId;
|
|
85947
|
+
store;
|
|
85948
|
+
setup() {
|
|
85949
|
+
this.activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
85950
|
+
this.store = useLocalStore(ConditionalFormattingEditorStore, deepCopy(this.props.cf), this.props.isNewCf);
|
|
85951
|
+
useEffect((sheetId, isCfRemoved) => {
|
|
85952
|
+
if (this.activeSheetId !== sheetId || isCfRemoved) {
|
|
85953
|
+
this.env.replaceSidePanel("ConditionalFormatting", `ConditionalFormattingEditor_${this.props.cf.id}`);
|
|
85954
|
+
}
|
|
85955
|
+
}, () => [this.env.model.getters.getActiveSheetId(), this.isEditedCfRemoved]);
|
|
85956
|
+
useExternalListener(window, "click", () => this.store.closeMenus());
|
|
85957
|
+
}
|
|
85958
|
+
get isEditedCfRemoved() {
|
|
85959
|
+
return !Boolean(this.env.model.getters
|
|
85960
|
+
.getConditionalFormats(this.activeSheetId)
|
|
85961
|
+
.find((cf) => cf.id === this.props.cf.id));
|
|
85962
|
+
}
|
|
85963
|
+
get cfTypesValues() {
|
|
85964
|
+
return [
|
|
85965
|
+
{ value: "CellIsRule", label: _t("Single color") },
|
|
85966
|
+
{ value: "ColorScaleRule", label: _t("Color scale") },
|
|
85967
|
+
{ value: "IconSetRule", label: _t("Icon set") },
|
|
85968
|
+
{ value: "DataBarRule", label: _t("Data bar") },
|
|
85969
|
+
];
|
|
85970
|
+
}
|
|
85971
|
+
onSave() {
|
|
85972
|
+
this.store.updateConditionalFormat({});
|
|
85973
|
+
const isSuccessful = this.store.state.errors.length === 0;
|
|
85974
|
+
if (isSuccessful) {
|
|
85975
|
+
this.env.replaceSidePanel("ConditionalFormatting", `ConditionalFormattingEditor_${this.props.cf.id}`);
|
|
85976
|
+
}
|
|
85977
|
+
}
|
|
85978
|
+
onCancel() {
|
|
85979
|
+
if (this.store.state.hasEditedCf) {
|
|
85980
|
+
if (this.props.isNewCf) {
|
|
85981
|
+
this.env.model.dispatch("REMOVE_CONDITIONAL_FORMAT", {
|
|
85982
|
+
sheetId: this.activeSheetId,
|
|
85983
|
+
id: this.props.cf.id,
|
|
85984
|
+
});
|
|
85985
|
+
}
|
|
85986
|
+
else {
|
|
85987
|
+
this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
85988
|
+
cf: this.props.cf,
|
|
85989
|
+
ranges: this.props.cf.ranges.map((range) => this.env.model.getters.getRangeDataFromXc(this.activeSheetId, range)),
|
|
85990
|
+
sheetId: this.activeSheetId,
|
|
85991
|
+
});
|
|
85992
|
+
}
|
|
85993
|
+
}
|
|
85994
|
+
this.env.replaceSidePanel("ConditionalFormatting", `ConditionalFormattingEditor_${this.props.cf.id}`);
|
|
85995
|
+
}
|
|
85996
|
+
/*****************************************************************************
|
|
85997
|
+
* Color Scale Rule
|
|
85998
|
+
****************************************************************************/
|
|
85999
|
+
getThresholdColor(threshold) {
|
|
86000
|
+
return threshold
|
|
86001
|
+
? colorNumberToHex(threshold.color)
|
|
86002
|
+
: colorNumberToHex(DEFAULT_COLOR_SCALE_MIDPOINT_COLOR);
|
|
86003
|
+
}
|
|
86004
|
+
isValueInvalid(threshold) {
|
|
86005
|
+
const errors = this.store.state.errors;
|
|
86006
|
+
switch (threshold) {
|
|
86007
|
+
case "minimum":
|
|
86008
|
+
return (errors.includes("MinInvalidFormula" /* CommandResult.MinInvalidFormula */) ||
|
|
86009
|
+
errors.includes("MinBiggerThanMid" /* CommandResult.MinBiggerThanMid */) ||
|
|
86010
|
+
errors.includes("MinBiggerThanMax" /* CommandResult.MinBiggerThanMax */) ||
|
|
86011
|
+
errors.includes("MinNaN" /* CommandResult.MinNaN */));
|
|
86012
|
+
case "midpoint":
|
|
86013
|
+
return (errors.includes("MidInvalidFormula" /* CommandResult.MidInvalidFormula */) ||
|
|
86014
|
+
errors.includes("MidNaN" /* CommandResult.MidNaN */) ||
|
|
86015
|
+
errors.includes("MidBiggerThanMax" /* CommandResult.MidBiggerThanMax */));
|
|
86016
|
+
case "maximum":
|
|
86017
|
+
return (errors.includes("MaxInvalidFormula" /* CommandResult.MaxInvalidFormula */) || errors.includes("MaxNaN" /* CommandResult.MaxNaN */));
|
|
86018
|
+
default:
|
|
86019
|
+
return false;
|
|
86020
|
+
}
|
|
86021
|
+
}
|
|
85996
86022
|
getColorScaleComposerProps(thresholdType) {
|
|
85997
|
-
const threshold = this.state.rules.colorScale[thresholdType];
|
|
86023
|
+
const threshold = this.store.state.rules.colorScale[thresholdType];
|
|
85998
86024
|
if (!threshold) {
|
|
85999
86025
|
throw new Error("Threshold not found");
|
|
86000
86026
|
}
|
|
@@ -86002,103 +86028,153 @@ class ConditionalFormattingEditor extends Component {
|
|
|
86002
86028
|
return {
|
|
86003
86029
|
onConfirm: (str) => {
|
|
86004
86030
|
threshold.value = str;
|
|
86005
|
-
this.updateConditionalFormat({ rule: this.state.rules.colorScale });
|
|
86031
|
+
this.store.updateConditionalFormat({ rule: this.store.state.rules.colorScale });
|
|
86006
86032
|
},
|
|
86007
86033
|
composerContent: threshold.value || "",
|
|
86008
86034
|
placeholder: _t("Formula"),
|
|
86009
86035
|
defaultStatic: true,
|
|
86010
86036
|
invalid: isInvalid,
|
|
86011
86037
|
class: "o-sidePanel-composer",
|
|
86012
|
-
defaultRangeSheetId: this.
|
|
86038
|
+
defaultRangeSheetId: this.activeSheetId,
|
|
86013
86039
|
};
|
|
86014
86040
|
}
|
|
86041
|
+
/*****************************************************************************
|
|
86042
|
+
* Icon Set
|
|
86043
|
+
****************************************************************************/
|
|
86044
|
+
isInflectionPointInvalid(inflectionPoint) {
|
|
86045
|
+
const errors = this.store.state.errors;
|
|
86046
|
+
switch (inflectionPoint) {
|
|
86047
|
+
case "lowerInflectionPoint":
|
|
86048
|
+
return (errors.includes("ValueLowerInflectionNaN" /* CommandResult.ValueLowerInflectionNaN */) ||
|
|
86049
|
+
errors.includes("ValueLowerInvalidFormula" /* CommandResult.ValueLowerInvalidFormula */) ||
|
|
86050
|
+
errors.includes("LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */));
|
|
86051
|
+
case "upperInflectionPoint":
|
|
86052
|
+
return (errors.includes("ValueUpperInflectionNaN" /* CommandResult.ValueUpperInflectionNaN */) ||
|
|
86053
|
+
errors.includes("ValueUpperInvalidFormula" /* CommandResult.ValueUpperInvalidFormula */) ||
|
|
86054
|
+
errors.includes("LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */));
|
|
86055
|
+
default:
|
|
86056
|
+
return true;
|
|
86057
|
+
}
|
|
86058
|
+
}
|
|
86015
86059
|
getColorIconSetComposerProps(inflectionPoint) {
|
|
86016
|
-
const inflection = this.state.rules.iconSet[inflectionPoint];
|
|
86060
|
+
const inflection = this.store.state.rules.iconSet[inflectionPoint];
|
|
86017
86061
|
const isInvalid = this.isInflectionPointInvalid(inflectionPoint);
|
|
86018
86062
|
return {
|
|
86019
86063
|
onConfirm: (str) => {
|
|
86020
86064
|
inflection.value = str;
|
|
86021
|
-
this.updateConditionalFormat({ rule: this.state.rules.iconSet });
|
|
86065
|
+
this.store.updateConditionalFormat({ rule: this.store.state.rules.iconSet });
|
|
86022
86066
|
},
|
|
86023
86067
|
composerContent: inflection.value || "",
|
|
86024
86068
|
placeholder: _t("Formula"),
|
|
86025
86069
|
defaultStatic: true,
|
|
86026
86070
|
invalid: isInvalid,
|
|
86027
86071
|
class: "o-sidePanel-composer",
|
|
86028
|
-
defaultRangeSheetId: this.
|
|
86072
|
+
defaultRangeSheetId: this.activeSheetId,
|
|
86029
86073
|
};
|
|
86030
86074
|
}
|
|
86031
|
-
|
|
86032
|
-
|
|
86033
|
-
|
|
86034
|
-
|
|
86035
|
-
|
|
86075
|
+
}
|
|
86076
|
+
|
|
86077
|
+
function useHighlightsOnHover(ref, highlightProvider) {
|
|
86078
|
+
const hoverState = useHoveredElement(ref);
|
|
86079
|
+
useHighlights({
|
|
86080
|
+
get highlights() {
|
|
86081
|
+
return hoverState.hovered ? highlightProvider.highlights : [];
|
|
86082
|
+
},
|
|
86083
|
+
});
|
|
86084
|
+
}
|
|
86085
|
+
function useHighlights(highlightProvider) {
|
|
86086
|
+
const stores = useStoreProvider();
|
|
86087
|
+
const store = useLocalStore(HighlightStore);
|
|
86088
|
+
onMounted(() => {
|
|
86089
|
+
store.register(highlightProvider);
|
|
86090
|
+
});
|
|
86091
|
+
let currentHighlights = highlightProvider.highlights;
|
|
86092
|
+
useEffect((highlights) => {
|
|
86093
|
+
if (!deepEquals(highlights, currentHighlights)) {
|
|
86094
|
+
currentHighlights = highlights;
|
|
86095
|
+
stores.trigger("store-updated");
|
|
86096
|
+
}
|
|
86097
|
+
}, () => [highlightProvider.highlights]);
|
|
86098
|
+
}
|
|
86099
|
+
|
|
86100
|
+
class ConditionalFormatPreview extends Component {
|
|
86101
|
+
static template = "o-spreadsheet-ConditionalFormatPreview";
|
|
86102
|
+
static props = {
|
|
86103
|
+
conditionalFormat: Object,
|
|
86104
|
+
onMouseDown: Function,
|
|
86105
|
+
class: String,
|
|
86106
|
+
};
|
|
86107
|
+
icons = ICONS;
|
|
86108
|
+
ref = useRef("cfPreview");
|
|
86109
|
+
setup() {
|
|
86110
|
+
useHighlightsOnHover(this.ref, this);
|
|
86036
86111
|
}
|
|
86037
|
-
|
|
86038
|
-
|
|
86039
|
-
|
|
86112
|
+
get previewImageStyle() {
|
|
86113
|
+
const rule = this.props.conditionalFormat.rule;
|
|
86114
|
+
if (rule.type === "CellIsRule") {
|
|
86115
|
+
return cssPropertiesToCss(cellStyleToCss(rule.style));
|
|
86040
86116
|
}
|
|
86041
|
-
|
|
86042
|
-
|
|
86117
|
+
else if (rule.type === "ColorScaleRule") {
|
|
86118
|
+
const minColor = colorNumberToHex(rule.minimum.color);
|
|
86119
|
+
const midColor = rule.midpoint ? colorNumberToHex(rule.midpoint.color) : null;
|
|
86120
|
+
const maxColor = colorNumberToHex(rule.maximum.color);
|
|
86121
|
+
const baseString = "background-image: linear-gradient(to right, ";
|
|
86122
|
+
return midColor
|
|
86123
|
+
? baseString + minColor + ", " + midColor + ", " + maxColor + ")"
|
|
86124
|
+
: baseString + minColor + ", " + maxColor + ")";
|
|
86125
|
+
}
|
|
86126
|
+
else if (rule.type === "DataBarRule") {
|
|
86127
|
+
const barColor = colorNumberToHex(rule.color);
|
|
86128
|
+
const gradient = `background-image: linear-gradient(to right, ${barColor} 50%, white 50%)`;
|
|
86129
|
+
return `${gradient}; color: ${TEXT_BODY};`;
|
|
86130
|
+
}
|
|
86131
|
+
return "";
|
|
86043
86132
|
}
|
|
86044
|
-
|
|
86045
|
-
this.
|
|
86133
|
+
get description() {
|
|
86134
|
+
const cf = this.props.conditionalFormat;
|
|
86135
|
+
switch (cf.rule.type) {
|
|
86136
|
+
case "CellIsRule":
|
|
86137
|
+
return criterionEvaluatorRegistry
|
|
86138
|
+
.get(cf.rule.operator)
|
|
86139
|
+
.getPreview({ ...cf.rule, type: cf.rule.operator }, this.env.model.getters);
|
|
86140
|
+
case "ColorScaleRule":
|
|
86141
|
+
return CfTerms.ColorScale;
|
|
86142
|
+
case "IconSetRule":
|
|
86143
|
+
return CfTerms.IconSet;
|
|
86144
|
+
case "DataBarRule":
|
|
86145
|
+
return CfTerms.DataBar;
|
|
86146
|
+
}
|
|
86046
86147
|
}
|
|
86047
|
-
|
|
86048
|
-
|
|
86148
|
+
get highlights() {
|
|
86149
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86150
|
+
return this.props.conditionalFormat.ranges.map((range) => ({
|
|
86151
|
+
range: this.env.model.getters.getRangeFromSheetXC(sheetId, range),
|
|
86152
|
+
color: HIGHLIGHT_COLOR,
|
|
86153
|
+
fillAlpha: 0.06,
|
|
86154
|
+
}));
|
|
86155
|
+
}
|
|
86156
|
+
editConditionalFormat() {
|
|
86157
|
+
this.env.replaceSidePanel("ConditionalFormattingEditor", "ConditionalFormatting", {
|
|
86158
|
+
cf: this.props.conditionalFormat,
|
|
86159
|
+
isNewCf: false,
|
|
86160
|
+
});
|
|
86161
|
+
}
|
|
86162
|
+
deleteConditionalFormat() {
|
|
86163
|
+
this.env.model.dispatch("REMOVE_CONDITIONAL_FORMAT", {
|
|
86164
|
+
id: this.props.conditionalFormat.id,
|
|
86165
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
86166
|
+
});
|
|
86049
86167
|
}
|
|
86050
86168
|
}
|
|
86051
86169
|
|
|
86052
|
-
class
|
|
86053
|
-
static template = "o-spreadsheet-
|
|
86170
|
+
class ConditionalFormatPreviewList extends Component {
|
|
86171
|
+
static template = "o-spreadsheet-ConditionalFormatPreviewList";
|
|
86054
86172
|
static props = {
|
|
86055
|
-
selection: { type: Object, optional: true },
|
|
86056
86173
|
onCloseSidePanel: Function,
|
|
86057
86174
|
};
|
|
86058
|
-
static components = {
|
|
86059
|
-
|
|
86060
|
-
|
|
86061
|
-
Section,
|
|
86062
|
-
};
|
|
86063
|
-
activeSheetId;
|
|
86064
|
-
originalEditedCf = undefined;
|
|
86065
|
-
state = useState({
|
|
86066
|
-
mode: "list",
|
|
86067
|
-
});
|
|
86068
|
-
setup() {
|
|
86069
|
-
this.activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
86070
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86071
|
-
const rules = this.env.model.getters.getRulesSelection(sheetId, this.props.selection || []);
|
|
86072
|
-
if (rules.length === 1) {
|
|
86073
|
-
const cf = this.conditionalFormats.find((c) => c.id === rules[0]);
|
|
86074
|
-
if (cf) {
|
|
86075
|
-
this.editConditionalFormat(cf);
|
|
86076
|
-
}
|
|
86077
|
-
}
|
|
86078
|
-
onWillUpdateProps((nextProps) => {
|
|
86079
|
-
const newActiveSheetId = this.env.model.getters.getActiveSheetId();
|
|
86080
|
-
if (newActiveSheetId !== this.activeSheetId) {
|
|
86081
|
-
this.activeSheetId = newActiveSheetId;
|
|
86082
|
-
this.switchToList();
|
|
86083
|
-
}
|
|
86084
|
-
else if (nextProps.selection !== this.props.selection) {
|
|
86085
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86086
|
-
const rules = this.env.model.getters.getRulesSelection(sheetId, nextProps.selection || []);
|
|
86087
|
-
if (rules.length === 1) {
|
|
86088
|
-
const cf = this.conditionalFormats.find((c) => c.id === rules[0]);
|
|
86089
|
-
if (cf) {
|
|
86090
|
-
this.editConditionalFormat(cf);
|
|
86091
|
-
}
|
|
86092
|
-
}
|
|
86093
|
-
else {
|
|
86094
|
-
this.switchToList();
|
|
86095
|
-
}
|
|
86096
|
-
}
|
|
86097
|
-
else if (!this.editedCF) {
|
|
86098
|
-
this.switchToList();
|
|
86099
|
-
}
|
|
86100
|
-
});
|
|
86101
|
-
}
|
|
86175
|
+
static components = { ConditionalFormatPreview };
|
|
86176
|
+
dragAndDrop = useDragAndDropListItems();
|
|
86177
|
+
cfListRef = useRef("cfList");
|
|
86102
86178
|
get conditionalFormats() {
|
|
86103
86179
|
const cfs = this.env.model.getters.getConditionalFormats(this.env.model.getters.getActiveSheetId());
|
|
86104
86180
|
return cfs.map((cf) => ({
|
|
@@ -86106,66 +86182,129 @@ class ConditionalFormattingPanel extends Component {
|
|
|
86106
86182
|
rule: localizeCFRule(cf.rule, this.env.model.getters.getLocale()),
|
|
86107
86183
|
}));
|
|
86108
86184
|
}
|
|
86109
|
-
|
|
86110
|
-
this.
|
|
86111
|
-
|
|
86112
|
-
|
|
86185
|
+
getPreviewDivStyle(cf) {
|
|
86186
|
+
return this.dragAndDrop.itemsStyle[cf.id] || "";
|
|
86187
|
+
}
|
|
86188
|
+
onPreviewMouseDown(cf, event) {
|
|
86189
|
+
if (event.button !== 0)
|
|
86190
|
+
return;
|
|
86191
|
+
const previewRects = Array.from(this.cfListRef.el.children).map((previewEl) => getBoundingRectAsPOJO(previewEl));
|
|
86192
|
+
const items = this.conditionalFormats.map((cf, index) => ({
|
|
86193
|
+
id: cf.id,
|
|
86194
|
+
size: previewRects[index].height,
|
|
86195
|
+
position: previewRects[index].y,
|
|
86196
|
+
}));
|
|
86197
|
+
this.dragAndDrop.start("vertical", {
|
|
86198
|
+
draggedItemId: cf.id,
|
|
86199
|
+
initialMousePosition: event.clientY,
|
|
86200
|
+
items: items,
|
|
86201
|
+
scrollableContainerEl: this.cfListRef.el,
|
|
86202
|
+
onDragEnd: (cfId, finalIndex) => this.onDragEnd(cfId, finalIndex),
|
|
86203
|
+
});
|
|
86113
86204
|
}
|
|
86114
|
-
|
|
86115
|
-
const
|
|
86205
|
+
onAddConditionalFormat() {
|
|
86206
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86207
|
+
const zones = this.env.model.getters.getSelectedZones();
|
|
86208
|
+
const cf = {
|
|
86209
|
+
id: this.env.model.uuidGenerator.smallUuid(),
|
|
86210
|
+
rule: {
|
|
86211
|
+
type: "CellIsRule",
|
|
86212
|
+
operator: "isNotEmpty",
|
|
86213
|
+
style: { fillColor: "#b6d7a8" },
|
|
86214
|
+
values: [],
|
|
86215
|
+
},
|
|
86216
|
+
};
|
|
86116
86217
|
this.env.model.dispatch("ADD_CONDITIONAL_FORMAT", {
|
|
86117
|
-
|
|
86118
|
-
ranges: this.env.model.getters
|
|
86119
|
-
|
|
86120
|
-
|
|
86218
|
+
cf,
|
|
86219
|
+
ranges: zones.map((zone) => this.env.model.getters.getRangeDataFromZone(sheetId, zone)),
|
|
86220
|
+
sheetId,
|
|
86221
|
+
});
|
|
86222
|
+
return this.env.replaceSidePanel("ConditionalFormattingEditor", "ConditionalFormatting", {
|
|
86121
86223
|
cf: {
|
|
86122
|
-
|
|
86123
|
-
|
|
86124
|
-
type: "CellIsRule",
|
|
86125
|
-
operator: "isNotEmpty",
|
|
86126
|
-
style: { fillColor: "#b6d7a8" },
|
|
86127
|
-
values: [],
|
|
86128
|
-
},
|
|
86224
|
+
...cf,
|
|
86225
|
+
ranges: zones.map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone))),
|
|
86129
86226
|
},
|
|
86227
|
+
isNewCf: true,
|
|
86130
86228
|
});
|
|
86131
|
-
this.state.editedCfId = cfId;
|
|
86132
|
-
this.state.mode = "edit";
|
|
86133
|
-
this.originalEditedCf = undefined;
|
|
86134
86229
|
}
|
|
86135
|
-
|
|
86136
|
-
this.
|
|
86137
|
-
|
|
86138
|
-
|
|
86139
|
-
|
|
86140
|
-
|
|
86141
|
-
|
|
86142
|
-
|
|
86143
|
-
sheetId: this.activeSheetId,
|
|
86144
|
-
ranges: this.originalEditedCf.ranges.map((range) => this.env.model.getters.getRangeDataFromXc(this.activeSheetId, range)),
|
|
86145
|
-
cf: this.originalEditedCf,
|
|
86146
|
-
});
|
|
86147
|
-
}
|
|
86148
|
-
else if (this.state.editedCfId) {
|
|
86149
|
-
this.env.model.dispatch("REMOVE_CONDITIONAL_FORMAT", {
|
|
86150
|
-
sheetId: this.activeSheetId,
|
|
86151
|
-
id: this.state.editedCfId,
|
|
86230
|
+
onDragEnd(cfId, finalIndex) {
|
|
86231
|
+
const originalIndex = this.conditionalFormats.findIndex((sheet) => sheet.id === cfId);
|
|
86232
|
+
const delta = originalIndex - finalIndex;
|
|
86233
|
+
if (delta !== 0) {
|
|
86234
|
+
this.env.model.dispatch("CHANGE_CONDITIONAL_FORMAT_PRIORITY", {
|
|
86235
|
+
cfId,
|
|
86236
|
+
delta,
|
|
86237
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
86152
86238
|
});
|
|
86153
86239
|
}
|
|
86154
|
-
this.switchToList();
|
|
86155
86240
|
}
|
|
86156
|
-
|
|
86157
|
-
|
|
86241
|
+
}
|
|
86242
|
+
|
|
86243
|
+
class DataValidationPreview extends Component {
|
|
86244
|
+
static template = "o-spreadsheet-DataValidationPreview";
|
|
86245
|
+
static props = {
|
|
86246
|
+
rule: Object,
|
|
86247
|
+
};
|
|
86248
|
+
ref = useRef("dvPreview");
|
|
86249
|
+
setup() {
|
|
86250
|
+
useHighlightsOnHover(this.ref, this);
|
|
86251
|
+
}
|
|
86252
|
+
onPreviewClick() {
|
|
86253
|
+
this.env.replaceSidePanel("DataValidationEditor", "DataValidation", {
|
|
86254
|
+
ruleId: this.props.rule.id,
|
|
86255
|
+
});
|
|
86256
|
+
}
|
|
86257
|
+
deleteDataValidation() {
|
|
86258
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86259
|
+
this.env.model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: this.props.rule.id });
|
|
86260
|
+
}
|
|
86261
|
+
get highlights() {
|
|
86262
|
+
return this.props.rule.ranges.map((range) => ({
|
|
86263
|
+
range,
|
|
86264
|
+
color: HIGHLIGHT_COLOR,
|
|
86265
|
+
fillAlpha: 0.06,
|
|
86266
|
+
}));
|
|
86267
|
+
}
|
|
86268
|
+
get rangesString() {
|
|
86269
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86270
|
+
return this.props.rule.ranges
|
|
86271
|
+
.map((range) => this.env.model.getters.getRangeString(range, sheetId))
|
|
86272
|
+
.join(", ");
|
|
86273
|
+
}
|
|
86274
|
+
get descriptionString() {
|
|
86275
|
+
return criterionEvaluatorRegistry
|
|
86276
|
+
.get(this.props.rule.criterion.type)
|
|
86277
|
+
.getPreview(this.props.rule.criterion, this.env.model.getters);
|
|
86278
|
+
}
|
|
86279
|
+
}
|
|
86280
|
+
|
|
86281
|
+
class DataValidationPanel extends Component {
|
|
86282
|
+
static template = "o-spreadsheet-DataValidationPanel";
|
|
86283
|
+
static props = {
|
|
86284
|
+
onCloseSidePanel: Function,
|
|
86285
|
+
};
|
|
86286
|
+
static components = { DataValidationPreview };
|
|
86287
|
+
addDataValidationRule() {
|
|
86288
|
+
this.env.replaceSidePanel("DataValidationEditor", "DataValidation", {
|
|
86289
|
+
ruleId: this.env.model.uuidGenerator.smallUuid(),
|
|
86290
|
+
});
|
|
86291
|
+
}
|
|
86292
|
+
localizeDVRule(rule) {
|
|
86293
|
+
if (!rule)
|
|
86294
|
+
return rule;
|
|
86295
|
+
const locale = this.env.model.getters.getLocale();
|
|
86296
|
+
return localizeDataValidationRule(rule, locale);
|
|
86297
|
+
}
|
|
86298
|
+
get validationRules() {
|
|
86299
|
+
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86300
|
+
return this.env.model.getters.getDataValidationRules(sheetId);
|
|
86158
86301
|
}
|
|
86159
86302
|
}
|
|
86160
86303
|
|
|
86161
86304
|
class DataValidationEditor extends Component {
|
|
86162
86305
|
static template = "o-spreadsheet-DataValidationEditor";
|
|
86163
86306
|
static components = { SelectionInput, SelectMenu, Section, ValidationMessages };
|
|
86164
|
-
static props = {
|
|
86165
|
-
rule: { type: Object, optional: true },
|
|
86166
|
-
onExit: Function,
|
|
86167
|
-
onCloseSidePanel: { type: Function, optional: true },
|
|
86168
|
-
};
|
|
86307
|
+
static props = { ruleId: String, onCloseSidePanel: Function };
|
|
86169
86308
|
state = useState({
|
|
86170
86309
|
rule: this.defaultDataValidationRule,
|
|
86171
86310
|
errors: [],
|
|
@@ -86174,12 +86313,13 @@ class DataValidationEditor extends Component {
|
|
|
86174
86313
|
editingSheetId;
|
|
86175
86314
|
setup() {
|
|
86176
86315
|
this.editingSheetId = this.env.model.getters.getActiveSheetId();
|
|
86177
|
-
|
|
86316
|
+
const rule = this.env.model.getters.getDataValidationRule(this.editingSheetId, this.props.ruleId);
|
|
86317
|
+
if (rule) {
|
|
86318
|
+
const locale = this.env.model.getters.getLocale();
|
|
86178
86319
|
this.state.rule = {
|
|
86179
|
-
...
|
|
86180
|
-
ranges:
|
|
86320
|
+
...localizeDataValidationRule(rule, locale),
|
|
86321
|
+
ranges: rule.ranges.map((range) => this.env.model.getters.getRangeString(range, this.editingSheetId)),
|
|
86181
86322
|
};
|
|
86182
|
-
this.state.rule.criterion.type = this.props.rule.criterion.type;
|
|
86183
86323
|
}
|
|
86184
86324
|
}
|
|
86185
86325
|
onCriterionTypeChanged(type) {
|
|
@@ -86196,16 +86336,16 @@ class DataValidationEditor extends Component {
|
|
|
86196
86336
|
const isBlocking = ev.target.value;
|
|
86197
86337
|
this.state.rule.isBlocking = isBlocking === "true";
|
|
86198
86338
|
}
|
|
86339
|
+
onCancel() {
|
|
86340
|
+
this.env.replaceSidePanel("DataValidation", `DataValidationEditor_${this.props.ruleId}`);
|
|
86341
|
+
}
|
|
86199
86342
|
onSave() {
|
|
86200
|
-
|
|
86201
|
-
|
|
86202
|
-
|
|
86203
|
-
|
|
86204
|
-
}
|
|
86205
|
-
else {
|
|
86206
|
-
this.props.onExit();
|
|
86207
|
-
}
|
|
86343
|
+
const result = this.env.model.dispatch("ADD_DATA_VALIDATION_RULE", this.dispatchPayload);
|
|
86344
|
+
if (!result.isSuccessful) {
|
|
86345
|
+
this.state.errors = result.reasons;
|
|
86346
|
+
return;
|
|
86208
86347
|
}
|
|
86348
|
+
this.env.replaceSidePanel("DataValidation", `DataValidationEditor_${this.props.ruleId}`);
|
|
86209
86349
|
}
|
|
86210
86350
|
get dispatchPayload() {
|
|
86211
86351
|
const rule = { ...this.state.rule, ranges: undefined };
|
|
@@ -86237,7 +86377,7 @@ class DataValidationEditor extends Component {
|
|
|
86237
86377
|
.getSelectedZones()
|
|
86238
86378
|
.map((zone) => zoneToXc(this.env.model.getters.getUnboundedZone(sheetId, zone)));
|
|
86239
86379
|
return {
|
|
86240
|
-
id: this.
|
|
86380
|
+
id: this.props.ruleId,
|
|
86241
86381
|
criterion: { type: "containsText", values: [""] },
|
|
86242
86382
|
ranges,
|
|
86243
86383
|
};
|
|
@@ -86250,75 +86390,6 @@ class DataValidationEditor extends Component {
|
|
|
86250
86390
|
}
|
|
86251
86391
|
}
|
|
86252
86392
|
|
|
86253
|
-
class DataValidationPreview extends Component {
|
|
86254
|
-
static template = "o-spreadsheet-DataValidationPreview";
|
|
86255
|
-
static props = {
|
|
86256
|
-
onClick: Function,
|
|
86257
|
-
rule: Object,
|
|
86258
|
-
};
|
|
86259
|
-
ref = useRef("dvPreview");
|
|
86260
|
-
setup() {
|
|
86261
|
-
useHighlightsOnHover(this.ref, this);
|
|
86262
|
-
}
|
|
86263
|
-
deleteDataValidation() {
|
|
86264
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86265
|
-
this.env.model.dispatch("REMOVE_DATA_VALIDATION_RULE", { sheetId, id: this.props.rule.id });
|
|
86266
|
-
}
|
|
86267
|
-
get highlights() {
|
|
86268
|
-
return this.props.rule.ranges.map((range) => ({
|
|
86269
|
-
range,
|
|
86270
|
-
color: HIGHLIGHT_COLOR,
|
|
86271
|
-
fillAlpha: 0.06,
|
|
86272
|
-
}));
|
|
86273
|
-
}
|
|
86274
|
-
get rangesString() {
|
|
86275
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86276
|
-
return this.props.rule.ranges
|
|
86277
|
-
.map((range) => this.env.model.getters.getRangeString(range, sheetId))
|
|
86278
|
-
.join(", ");
|
|
86279
|
-
}
|
|
86280
|
-
get descriptionString() {
|
|
86281
|
-
return criterionEvaluatorRegistry
|
|
86282
|
-
.get(this.props.rule.criterion.type)
|
|
86283
|
-
.getPreview(this.props.rule.criterion, this.env.model.getters);
|
|
86284
|
-
}
|
|
86285
|
-
}
|
|
86286
|
-
|
|
86287
|
-
class DataValidationPanel extends Component {
|
|
86288
|
-
static template = "o-spreadsheet-DataValidationPanel";
|
|
86289
|
-
static props = {
|
|
86290
|
-
onCloseSidePanel: Function,
|
|
86291
|
-
};
|
|
86292
|
-
static components = { DataValidationPreview, DataValidationEditor };
|
|
86293
|
-
state = useState({ mode: "list", activeRule: undefined });
|
|
86294
|
-
onPreviewClick(id) {
|
|
86295
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86296
|
-
const rule = this.env.model.getters.getDataValidationRule(sheetId, id);
|
|
86297
|
-
if (rule) {
|
|
86298
|
-
this.state.mode = "edit";
|
|
86299
|
-
this.state.activeRule = rule;
|
|
86300
|
-
}
|
|
86301
|
-
}
|
|
86302
|
-
addDataValidationRule() {
|
|
86303
|
-
this.state.mode = "edit";
|
|
86304
|
-
this.state.activeRule = undefined;
|
|
86305
|
-
}
|
|
86306
|
-
onExitEditMode() {
|
|
86307
|
-
this.state.mode = "list";
|
|
86308
|
-
this.state.activeRule = undefined;
|
|
86309
|
-
}
|
|
86310
|
-
localizeDVRule(rule) {
|
|
86311
|
-
if (!rule)
|
|
86312
|
-
return rule;
|
|
86313
|
-
const locale = this.env.model.getters.getLocale();
|
|
86314
|
-
return localizeDataValidationRule(rule, locale);
|
|
86315
|
-
}
|
|
86316
|
-
get validationRules() {
|
|
86317
|
-
const sheetId = this.env.model.getters.getActiveSheetId();
|
|
86318
|
-
return this.env.model.getters.getDataValidationRules(sheetId);
|
|
86319
|
-
}
|
|
86320
|
-
}
|
|
86321
|
-
|
|
86322
86393
|
const FIND_AND_REPLACE_HIGHLIGHT_COLOR = "#8B008B";
|
|
86323
86394
|
var Direction;
|
|
86324
86395
|
(function (Direction) {
|
|
@@ -89196,7 +89267,18 @@ class TableStyleEditorPanel extends Component {
|
|
|
89196
89267
|
const sidePanelRegistry = new Registry$1();
|
|
89197
89268
|
sidePanelRegistry.add("ConditionalFormatting", {
|
|
89198
89269
|
title: _t("Conditional formatting"),
|
|
89199
|
-
Body:
|
|
89270
|
+
Body: ConditionalFormatPreviewList,
|
|
89271
|
+
});
|
|
89272
|
+
sidePanelRegistry.add("ConditionalFormattingEditor", {
|
|
89273
|
+
title: _t("Conditional formatting"),
|
|
89274
|
+
Body: ConditionalFormattingEditor,
|
|
89275
|
+
computeState: (getters, props) => {
|
|
89276
|
+
return {
|
|
89277
|
+
isOpen: true,
|
|
89278
|
+
props,
|
|
89279
|
+
key: `ConditionalFormattingEditor_${props.cf.id}`,
|
|
89280
|
+
};
|
|
89281
|
+
},
|
|
89200
89282
|
});
|
|
89201
89283
|
sidePanelRegistry.add("ChartPanel", {
|
|
89202
89284
|
title: _t("Chart"),
|
|
@@ -89233,6 +89315,13 @@ sidePanelRegistry.add("DataValidation", {
|
|
|
89233
89315
|
sidePanelRegistry.add("DataValidationEditor", {
|
|
89234
89316
|
title: _t("Data validation"),
|
|
89235
89317
|
Body: DataValidationEditor,
|
|
89318
|
+
computeState: (getters, props) => {
|
|
89319
|
+
return {
|
|
89320
|
+
isOpen: true,
|
|
89321
|
+
props,
|
|
89322
|
+
key: `DataValidationEditor_${props.ruleId}`,
|
|
89323
|
+
};
|
|
89324
|
+
},
|
|
89236
89325
|
});
|
|
89237
89326
|
sidePanelRegistry.add("MoreFormats", {
|
|
89238
89327
|
title: _t("More formats"),
|
|
@@ -97930,6 +98019,6 @@ const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
|
97930
98019
|
export { AbstractCellClipboardHandler, AbstractChart, AbstractFigureClipboardHandler, CellErrorType, ClientDisconnectedError, CommandResult, CorePlugin, CoreViewPlugin, DEFAULT_LOCALE, DEFAULT_LOCALES, DispatchResult, EvaluationError, LocalTransportService, Model, PivotRuntimeDefinition, Registry$1 as Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, SpreadsheetPivotTable, UIPlugin, __info__, addFunction, addRenderingLayer, astToFormula, categories, chartHelpers, compile, compileTokens, components, constants, convertAstNodes, coreTypes, createAutocompleteArgumentsProvider, findCellInNewZone, functionCache, getCaretDownSvg, getCaretUpSvg, helpers, hooks, invalidateCFEvaluationCommands, invalidateChartEvaluationCommands, invalidateDependenciesCommands, invalidateEvaluationCommands, iterateAstNodes, links, load, parse$1 as parse, parseTokens, readonlyAllowedCommands, registries, setDefaultSheetViewSize, setTranslationMethod, stores, tokenColors, tokenize };
|
|
97931
98020
|
|
|
97932
98021
|
|
|
97933
|
-
__info__.version = "19.
|
|
97934
|
-
__info__.date = "2026-01-07T16:21:
|
|
97935
|
-
__info__.hash = "
|
|
98022
|
+
__info__.version = "19.2.0-alpha.2";
|
|
98023
|
+
__info__.date = "2026-01-07T16:21:35.251Z";
|
|
98024
|
+
__info__.hash = "ac2fa3e";
|