@odoo/o-spreadsheet 17.3.0-alpha.9 → 17.3.0
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.cjs.js +1600 -603
- package/dist/o-spreadsheet.d.ts +425 -199
- package/dist/o-spreadsheet.esm.js +1600 -603
- package/dist/o-spreadsheet.iife.js +1600 -603
- package/dist/o-spreadsheet.iife.min.js +550 -392
- package/dist/o_spreadsheet.xml +479 -381
- package/package.json +2 -2
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
5
5
|
* @see https://github.com/odoo/o-spreadsheet
|
|
6
|
-
* @version 17.3.0
|
|
7
|
-
* @date 2024-05-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.3.0
|
|
7
|
+
* @date 2024-05-31T14:21:26.547Z
|
|
8
|
+
* @hash 271202e
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
(function (exports, owl) {
|
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
const CHART_WATERFALL_POSITIVE_COLOR = "#006FBE";
|
|
42
42
|
const CHART_WATERFALL_NEGATIVE_COLOR = "#E40000";
|
|
43
43
|
const CHART_WATERFALL_SUBTOTAL_COLOR = "#AAAAAA";
|
|
44
|
+
const DEFAULT_CHART_PADDING = 20;
|
|
45
|
+
const DEFAULT_CHART_FONT_SIZE = 22;
|
|
44
46
|
// Color picker defaults as upper case HEX to match `toHex`helper
|
|
45
47
|
const COLOR_PICKER_DEFAULTS = [
|
|
46
48
|
"#000000",
|
|
@@ -1089,6 +1091,44 @@
|
|
|
1089
1091
|
hsla.l = hsla.l - percentage * hsla.l;
|
|
1090
1092
|
return hslaToHex(hsla);
|
|
1091
1093
|
}
|
|
1094
|
+
const ColorsList = [
|
|
1095
|
+
// the same colors as those used in odoo reporting
|
|
1096
|
+
"rgb(31,119,180)",
|
|
1097
|
+
"rgb(255,127,14)",
|
|
1098
|
+
"rgb(174,199,232)",
|
|
1099
|
+
"rgb(255,187,120)",
|
|
1100
|
+
"rgb(44,160,44)",
|
|
1101
|
+
"rgb(152,223,138)",
|
|
1102
|
+
"rgb(214,39,40)",
|
|
1103
|
+
"rgb(255,152,150)",
|
|
1104
|
+
"rgb(148,103,189)",
|
|
1105
|
+
"rgb(197,176,213)",
|
|
1106
|
+
"rgb(140,86,75)",
|
|
1107
|
+
"rgb(196,156,148)",
|
|
1108
|
+
"rgb(227,119,194)",
|
|
1109
|
+
"rgb(247,182,210)",
|
|
1110
|
+
"rgb(127,127,127)",
|
|
1111
|
+
"rgb(199,199,199)",
|
|
1112
|
+
"rgb(188,189,34)",
|
|
1113
|
+
"rgb(219,219,141)",
|
|
1114
|
+
"rgb(23,190,207)",
|
|
1115
|
+
"rgb(158,218,229)",
|
|
1116
|
+
];
|
|
1117
|
+
function getNthColor(index) {
|
|
1118
|
+
return ColorsList[index % ColorsList.length];
|
|
1119
|
+
}
|
|
1120
|
+
class ColorGenerator {
|
|
1121
|
+
currentColorIndex = 0;
|
|
1122
|
+
colors;
|
|
1123
|
+
constructor(colors = []) {
|
|
1124
|
+
this.colors = colors;
|
|
1125
|
+
}
|
|
1126
|
+
next() {
|
|
1127
|
+
return this.colors?.[this.currentColorIndex]
|
|
1128
|
+
? this.colors[this.currentColorIndex++]
|
|
1129
|
+
: getNthColor(this.currentColorIndex++);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1092
1132
|
|
|
1093
1133
|
//------------------------------------------------------------------------------
|
|
1094
1134
|
// Coordinate
|
|
@@ -1934,11 +1974,13 @@
|
|
|
1934
1974
|
"RENAME_SHEET",
|
|
1935
1975
|
"DELETE_SHEET",
|
|
1936
1976
|
"CREATE_SHEET",
|
|
1977
|
+
"DUPLICATE_SHEET",
|
|
1937
1978
|
"ADD_COLUMNS_ROWS",
|
|
1938
1979
|
"REMOVE_COLUMNS_ROWS",
|
|
1939
1980
|
"UNDO",
|
|
1940
1981
|
"REDO",
|
|
1941
1982
|
"ADD_MERGE",
|
|
1983
|
+
"REMOVE_MERGE",
|
|
1942
1984
|
"UPDATE_LOCALE",
|
|
1943
1985
|
"ADD_PIVOT",
|
|
1944
1986
|
"UPDATE_PIVOT",
|
|
@@ -4877,18 +4919,22 @@
|
|
|
4877
4919
|
/**
|
|
4878
4920
|
* Create a range from a xc. If the xc is empty, this function returns undefined.
|
|
4879
4921
|
*/
|
|
4880
|
-
function
|
|
4881
|
-
|
|
4922
|
+
function createValidRange(getters, sheetId, xc) {
|
|
4923
|
+
if (!xc)
|
|
4924
|
+
return;
|
|
4925
|
+
const range = getters.getRangeFromSheetXC(sheetId, xc);
|
|
4926
|
+
return !(range.invalidSheetName || range.invalidXc) ? range : undefined;
|
|
4882
4927
|
}
|
|
4883
4928
|
/**
|
|
4884
4929
|
* Spread multiple colrows zone to one row/col zone and add a many new input range as needed.
|
|
4885
4930
|
* For example, A1:B4 will become [A1:A4, B1:B4]
|
|
4886
4931
|
*/
|
|
4887
|
-
function spreadRange(getters,
|
|
4932
|
+
function spreadRange(getters, dataSets) {
|
|
4888
4933
|
const postProcessedRanges = [];
|
|
4889
|
-
for (const
|
|
4934
|
+
for (const dataSet of dataSets) {
|
|
4935
|
+
const range = dataSet.dataRange;
|
|
4890
4936
|
if (!getters.isRangeValid(range)) {
|
|
4891
|
-
postProcessedRanges.push(
|
|
4937
|
+
postProcessedRanges.push(dataSet); // ignore invalid range
|
|
4892
4938
|
continue;
|
|
4893
4939
|
}
|
|
4894
4940
|
const { sheetName } = splitReference(range);
|
|
@@ -4897,27 +4943,33 @@
|
|
|
4897
4943
|
if (zone.bottom !== zone.top && zone.left != zone.right) {
|
|
4898
4944
|
if (zone.right) {
|
|
4899
4945
|
for (let j = zone.left; j <= zone.right; ++j) {
|
|
4900
|
-
postProcessedRanges.push(
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4946
|
+
postProcessedRanges.push({
|
|
4947
|
+
...dataSet,
|
|
4948
|
+
dataRange: `${sheetPrefix}${zoneToXc({
|
|
4949
|
+
left: j,
|
|
4950
|
+
right: j,
|
|
4951
|
+
top: zone.top,
|
|
4952
|
+
bottom: zone.bottom,
|
|
4953
|
+
})}`,
|
|
4954
|
+
});
|
|
4906
4955
|
}
|
|
4907
4956
|
}
|
|
4908
4957
|
else {
|
|
4909
4958
|
for (let j = zone.top; j <= zone.bottom; ++j) {
|
|
4910
|
-
postProcessedRanges.push(
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4915
|
-
|
|
4959
|
+
postProcessedRanges.push({
|
|
4960
|
+
...dataSet,
|
|
4961
|
+
dataRange: `${sheetPrefix}${zoneToXc({
|
|
4962
|
+
left: zone.left,
|
|
4963
|
+
right: zone.right,
|
|
4964
|
+
top: j,
|
|
4965
|
+
bottom: j,
|
|
4966
|
+
})}`,
|
|
4967
|
+
});
|
|
4916
4968
|
}
|
|
4917
4969
|
}
|
|
4918
4970
|
}
|
|
4919
4971
|
else {
|
|
4920
|
-
postProcessedRanges.push(
|
|
4972
|
+
postProcessedRanges.push(dataSet);
|
|
4921
4973
|
}
|
|
4922
4974
|
}
|
|
4923
4975
|
return postProcessedRanges;
|
|
@@ -5036,6 +5088,11 @@
|
|
|
5036
5088
|
const fontSize = computeTextFontSizeInPixels(cell.style);
|
|
5037
5089
|
return computeTextLinesHeight(fontSize, numberOfLines) + 2 * PADDING_AUTORESIZE_VERTICAL;
|
|
5038
5090
|
}
|
|
5091
|
+
function getDefaultContextFont(fontSize, bold = false, italic = false) {
|
|
5092
|
+
const italicStr = italic ? "italic" : "";
|
|
5093
|
+
const weight = bold ? "bold" : "";
|
|
5094
|
+
return `${italicStr} ${weight} ${fontSize}px ${DEFAULT_FONT}`;
|
|
5095
|
+
}
|
|
5039
5096
|
const textWidthCache = {};
|
|
5040
5097
|
function computeTextWidth(context, text, style, fontUnit = "pt") {
|
|
5041
5098
|
const font = computeTextFont(style, fontUnit);
|
|
@@ -5056,6 +5113,28 @@
|
|
|
5056
5113
|
}
|
|
5057
5114
|
return textWidthCache[font][text];
|
|
5058
5115
|
}
|
|
5116
|
+
const textDimensionsCache = {};
|
|
5117
|
+
function computeTextDimension(context, text, style, fontUnit = "pt") {
|
|
5118
|
+
const font = computeTextFont(style, fontUnit);
|
|
5119
|
+
context.save();
|
|
5120
|
+
context.font = font;
|
|
5121
|
+
const dimensions = computeCachedTextDimension(context, text);
|
|
5122
|
+
context.restore();
|
|
5123
|
+
return dimensions;
|
|
5124
|
+
}
|
|
5125
|
+
function computeCachedTextDimension(context, text) {
|
|
5126
|
+
const font = context.font;
|
|
5127
|
+
if (!textDimensionsCache[font]) {
|
|
5128
|
+
textDimensionsCache[font] = {};
|
|
5129
|
+
}
|
|
5130
|
+
if (textDimensionsCache[font][text] === undefined) {
|
|
5131
|
+
const measure = context.measureText(text);
|
|
5132
|
+
const width = measure.width;
|
|
5133
|
+
const height = measure.fontBoundingBoxAscent + measure.fontBoundingBoxDescent;
|
|
5134
|
+
textDimensionsCache[font][text] = { width, height };
|
|
5135
|
+
}
|
|
5136
|
+
return textDimensionsCache[font][text];
|
|
5137
|
+
}
|
|
5059
5138
|
function fontSizeInPixels(fontSize) {
|
|
5060
5139
|
return Math.round((fontSize * 96) / 72);
|
|
5061
5140
|
}
|
|
@@ -8825,7 +8904,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
8825
8904
|
}
|
|
8826
8905
|
}
|
|
8827
8906
|
if (!highlight.noFill) {
|
|
8828
|
-
ctx.fillStyle = setColorAlpha(color, highlight.fillAlpha ?? 0.12);
|
|
8907
|
+
ctx.fillStyle = setColorAlpha(toHex(color), highlight.fillAlpha ?? 0.12);
|
|
8829
8908
|
ctx.fillRect(x, y, width, height);
|
|
8830
8909
|
}
|
|
8831
8910
|
}
|
|
@@ -8874,7 +8953,32 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
8874
8953
|
}
|
|
8875
8954
|
}
|
|
8876
8955
|
|
|
8877
|
-
|
|
8956
|
+
class NotificationStore {
|
|
8957
|
+
mutators = [
|
|
8958
|
+
"notifyUser",
|
|
8959
|
+
"raiseError",
|
|
8960
|
+
"askConfirmation",
|
|
8961
|
+
"updateNotificationCallbacks",
|
|
8962
|
+
];
|
|
8963
|
+
notifyUser = (notification) => window.alert(notification);
|
|
8964
|
+
askConfirmation = (content, confirm, cancel) => {
|
|
8965
|
+
if (window.confirm(content)) {
|
|
8966
|
+
confirm();
|
|
8967
|
+
}
|
|
8968
|
+
else {
|
|
8969
|
+
cancel?.();
|
|
8970
|
+
}
|
|
8971
|
+
};
|
|
8972
|
+
raiseError = (text, callback) => {
|
|
8973
|
+
window.alert(text);
|
|
8974
|
+
callback?.();
|
|
8975
|
+
};
|
|
8976
|
+
updateNotificationCallbacks(methods) {
|
|
8977
|
+
this.notifyUser = methods.notifyUser || this.notifyUser;
|
|
8978
|
+
this.raiseError = methods.raiseError || this.raiseError;
|
|
8979
|
+
this.askConfirmation = methods.askConfirmation || this.askConfirmation;
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8878
8982
|
|
|
8879
8983
|
const CELL_DELETED_MESSAGE = _t("The cell you are trying to edit has been deleted.");
|
|
8880
8984
|
class ComposerStore extends SpreadsheetStore {
|
|
@@ -9895,10 +9999,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9895
9999
|
/**
|
|
9896
10000
|
* Create the dataSet objects from xcs
|
|
9897
10001
|
*/
|
|
9898
|
-
function createDataSets(getters,
|
|
10002
|
+
function createDataSets(getters, customizedDataSets, sheetId, dataSetsHaveTitle) {
|
|
9899
10003
|
const dataSets = [];
|
|
9900
|
-
for (const
|
|
9901
|
-
const dataRange = getters.getRangeFromSheetXC(sheetId,
|
|
10004
|
+
for (const dataSet of customizedDataSets) {
|
|
10005
|
+
const dataRange = getters.getRangeFromSheetXC(sheetId, dataSet.dataRange);
|
|
9902
10006
|
const { unboundedZone: zone, sheetId: dataSetSheetId, invalidSheetName, invalidXc } = dataRange;
|
|
9903
10007
|
if (invalidSheetName || invalidXc) {
|
|
9904
10008
|
continue;
|
|
@@ -9915,26 +10019,36 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9915
10019
|
left: column,
|
|
9916
10020
|
right: column,
|
|
9917
10021
|
};
|
|
9918
|
-
dataSets.push(
|
|
9919
|
-
|
|
9920
|
-
|
|
9921
|
-
|
|
9922
|
-
|
|
9923
|
-
|
|
9924
|
-
|
|
9925
|
-
|
|
10022
|
+
dataSets.push({
|
|
10023
|
+
...createDataSet(getters, dataSetSheetId, columnZone, dataSetsHaveTitle
|
|
10024
|
+
? {
|
|
10025
|
+
top: columnZone.top,
|
|
10026
|
+
bottom: columnZone.top,
|
|
10027
|
+
left: columnZone.left,
|
|
10028
|
+
right: columnZone.left,
|
|
10029
|
+
}
|
|
10030
|
+
: undefined),
|
|
10031
|
+
backgroundColor: dataSet.backgroundColor,
|
|
10032
|
+
rightYAxis: dataSet.yAxisId === "y1",
|
|
10033
|
+
customLabel: dataSet.label,
|
|
10034
|
+
});
|
|
9926
10035
|
}
|
|
9927
10036
|
}
|
|
9928
10037
|
else {
|
|
9929
10038
|
/* 1 cell, 1 row or 1 column */
|
|
9930
|
-
dataSets.push(
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
10039
|
+
dataSets.push({
|
|
10040
|
+
...createDataSet(getters, dataSetSheetId, zone, dataSetsHaveTitle
|
|
10041
|
+
? {
|
|
10042
|
+
top: zone.top,
|
|
10043
|
+
bottom: zone.top,
|
|
10044
|
+
left: zone.left,
|
|
10045
|
+
right: zone.left,
|
|
10046
|
+
}
|
|
10047
|
+
: undefined),
|
|
10048
|
+
backgroundColor: dataSet.backgroundColor,
|
|
10049
|
+
rightYAxis: dataSet.yAxisId === "y1",
|
|
10050
|
+
customLabel: dataSet.label,
|
|
10051
|
+
});
|
|
9938
10052
|
}
|
|
9939
10053
|
}
|
|
9940
10054
|
return dataSets;
|
|
@@ -9974,11 +10088,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
9974
10088
|
}
|
|
9975
10089
|
}
|
|
9976
10090
|
const dataRange = ds.dataRange.clone({ zone: dataZone });
|
|
10091
|
+
let label = {};
|
|
10092
|
+
if (ds.customLabel) {
|
|
10093
|
+
label = {
|
|
10094
|
+
text: ds.customLabel,
|
|
10095
|
+
};
|
|
10096
|
+
}
|
|
10097
|
+
else if (ds.labelCell) {
|
|
10098
|
+
label = {
|
|
10099
|
+
reference: getters.getRangeString(ds.labelCell, "forceSheetReference", {
|
|
10100
|
+
useFixedReference: true,
|
|
10101
|
+
}),
|
|
10102
|
+
};
|
|
10103
|
+
}
|
|
9977
10104
|
return {
|
|
9978
|
-
label
|
|
9979
|
-
? getters.getRangeString(ds.labelCell, "forceSheetReference", { useFixedReference: true })
|
|
9980
|
-
: undefined,
|
|
10105
|
+
label,
|
|
9981
10106
|
range: getters.getRangeString(dataRange, "forceSheetReference", { useFixedReference: true }),
|
|
10107
|
+
backgroundColor: ds.backgroundColor,
|
|
10108
|
+
rightYAxis: ds.rightYAxis,
|
|
9982
10109
|
};
|
|
9983
10110
|
}
|
|
9984
10111
|
function toExcelLabelRange(getters, labelRange, shouldRemoveFirstLabel) {
|
|
@@ -10004,45 +10131,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10004
10131
|
labelRange = labelZone ? zoneToXc(labelZone) : undefined;
|
|
10005
10132
|
}
|
|
10006
10133
|
const dataSets = definition.dataSets
|
|
10007
|
-
.map(toUnboundedZone)
|
|
10134
|
+
.map((ds) => toUnboundedZone(ds.dataRange))
|
|
10008
10135
|
.map((zone) => transformZone(zone, executed))
|
|
10009
10136
|
.filter(isDefined)
|
|
10010
|
-
.map(zoneToXc);
|
|
10137
|
+
.map((xc) => ({ dataRange: zoneToXc(xc) }));
|
|
10011
10138
|
return {
|
|
10012
10139
|
...definition,
|
|
10013
10140
|
labelRange,
|
|
10014
10141
|
dataSets,
|
|
10015
10142
|
};
|
|
10016
10143
|
}
|
|
10017
|
-
const GraphColors = [
|
|
10018
|
-
// the same colors as those used in odoo reporting
|
|
10019
|
-
"rgb(31,119,180)",
|
|
10020
|
-
"rgb(255,127,14)",
|
|
10021
|
-
"rgb(174,199,232)",
|
|
10022
|
-
"rgb(255,187,120)",
|
|
10023
|
-
"rgb(44,160,44)",
|
|
10024
|
-
"rgb(152,223,138)",
|
|
10025
|
-
"rgb(214,39,40)",
|
|
10026
|
-
"rgb(255,152,150)",
|
|
10027
|
-
"rgb(148,103,189)",
|
|
10028
|
-
"rgb(197,176,213)",
|
|
10029
|
-
"rgb(140,86,75)",
|
|
10030
|
-
"rgb(196,156,148)",
|
|
10031
|
-
"rgb(227,119,194)",
|
|
10032
|
-
"rgb(247,182,210)",
|
|
10033
|
-
"rgb(127,127,127)",
|
|
10034
|
-
"rgb(199,199,199)",
|
|
10035
|
-
"rgb(188,189,34)",
|
|
10036
|
-
"rgb(219,219,141)",
|
|
10037
|
-
"rgb(23,190,207)",
|
|
10038
|
-
"rgb(158,218,229)",
|
|
10039
|
-
];
|
|
10040
|
-
class ChartColors {
|
|
10041
|
-
graphColorIndex = 0;
|
|
10042
|
-
next() {
|
|
10043
|
-
return GraphColors[this.graphColorIndex++ % GraphColors.length];
|
|
10044
|
-
}
|
|
10045
|
-
}
|
|
10046
10144
|
/**
|
|
10047
10145
|
* Choose a font color based on a background color.
|
|
10048
10146
|
* The font is white with a dark background.
|
|
@@ -10055,11 +10153,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10055
10153
|
}
|
|
10056
10154
|
function checkDataset(definition) {
|
|
10057
10155
|
if (definition.dataSets) {
|
|
10058
|
-
const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range)) !== undefined;
|
|
10156
|
+
const invalidRanges = definition.dataSets.find((range) => !rangeReference.test(range.dataRange)) !== undefined;
|
|
10059
10157
|
if (invalidRanges) {
|
|
10060
10158
|
return "InvalidDataSet" /* CommandResult.InvalidDataSet */;
|
|
10061
10159
|
}
|
|
10062
|
-
const zones = definition.dataSets.map(toUnboundedZone);
|
|
10160
|
+
const zones = definition.dataSets.map((ds) => toUnboundedZone(ds.dataRange));
|
|
10063
10161
|
if (zones.some((zone) => zone.top !== zone.bottom && isFullRow(zone))) {
|
|
10064
10162
|
return "InvalidDataSet" /* CommandResult.InvalidDataSet */;
|
|
10065
10163
|
}
|
|
@@ -10099,6 +10197,35 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10099
10197
|
}; // Position at the center of the scrollable viewport
|
|
10100
10198
|
return position;
|
|
10101
10199
|
}
|
|
10200
|
+
function getChartAxisTitleRuntime(design) {
|
|
10201
|
+
if (design?.title?.text) {
|
|
10202
|
+
const { text, color, align, italic, bold } = design.title;
|
|
10203
|
+
return {
|
|
10204
|
+
display: true,
|
|
10205
|
+
text,
|
|
10206
|
+
color,
|
|
10207
|
+
font: {
|
|
10208
|
+
style: italic ? "italic" : "normal",
|
|
10209
|
+
weight: bold ? "bold" : "normal",
|
|
10210
|
+
},
|
|
10211
|
+
align: align === "left" ? "start" : align === "right" ? "end" : "center",
|
|
10212
|
+
};
|
|
10213
|
+
}
|
|
10214
|
+
return;
|
|
10215
|
+
}
|
|
10216
|
+
function getDefinedAxis(definition) {
|
|
10217
|
+
let useLeftAxis = false, useRightAxis = false;
|
|
10218
|
+
for (const design of definition.dataSets || []) {
|
|
10219
|
+
if (design.yAxisId === "y1") {
|
|
10220
|
+
useRightAxis = true;
|
|
10221
|
+
}
|
|
10222
|
+
else {
|
|
10223
|
+
useLeftAxis = true;
|
|
10224
|
+
}
|
|
10225
|
+
}
|
|
10226
|
+
useLeftAxis ||= !useRightAxis;
|
|
10227
|
+
return { useLeftAxis, useRightAxis };
|
|
10228
|
+
}
|
|
10102
10229
|
|
|
10103
10230
|
function getBaselineText(baseline, keyValue, baselineMode, humanize, locale) {
|
|
10104
10231
|
if (!baseline) {
|
|
@@ -10200,8 +10327,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10200
10327
|
type = "scorecard";
|
|
10201
10328
|
constructor(definition, sheetId, getters) {
|
|
10202
10329
|
super(definition, sheetId, getters);
|
|
10203
|
-
this.keyValue =
|
|
10204
|
-
this.baseline =
|
|
10330
|
+
this.keyValue = createValidRange(getters, sheetId, definition.keyValue);
|
|
10331
|
+
this.baseline = createValidRange(getters, sheetId, definition.baseline);
|
|
10205
10332
|
this.baselineMode = definition.baselineMode;
|
|
10206
10333
|
this.baselineDescr = definition.baselineDescr;
|
|
10207
10334
|
this.background = definition.background;
|
|
@@ -10216,8 +10343,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10216
10343
|
return {
|
|
10217
10344
|
background: context.background,
|
|
10218
10345
|
type: "scorecard",
|
|
10219
|
-
keyValue: context.range ? context.range[0] : undefined,
|
|
10220
|
-
title: context.title || "",
|
|
10346
|
+
keyValue: context.range ? context.range[0].dataRange : undefined,
|
|
10347
|
+
title: context.title || { text: "" },
|
|
10221
10348
|
baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
|
|
10222
10349
|
baselineColorUp: DEFAULT_SCORECARD_BASELINE_COLOR_UP,
|
|
10223
10350
|
baselineColorDown: DEFAULT_SCORECARD_BASELINE_COLOR_DOWN,
|
|
@@ -10255,7 +10382,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10255
10382
|
getContextCreation() {
|
|
10256
10383
|
return {
|
|
10257
10384
|
...this,
|
|
10258
|
-
range: this.keyValue
|
|
10385
|
+
range: this.keyValue
|
|
10386
|
+
? [{ dataRange: this.getters.getRangeString(this.keyValue, this.sheetId) }]
|
|
10387
|
+
: undefined,
|
|
10259
10388
|
auxiliaryRange: this.baseline
|
|
10260
10389
|
? this.getters.getRangeString(this.baseline, this.sheetId)
|
|
10261
10390
|
: undefined,
|
|
@@ -10302,7 +10431,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10302
10431
|
if (structure.title) {
|
|
10303
10432
|
ctx.font = structure.title.style.font;
|
|
10304
10433
|
ctx.fillStyle = structure.title.style.color;
|
|
10434
|
+
const baseline = ctx.textBaseline;
|
|
10435
|
+
ctx.textBaseline = "middle";
|
|
10305
10436
|
ctx.fillText(clipTextWithEllipsis(ctx, structure.title.text, canvas.width - structure.title.position.x), structure.title.position.x, structure.title.position.y);
|
|
10437
|
+
ctx.textBaseline = baseline;
|
|
10306
10438
|
}
|
|
10307
10439
|
if (structure.baseline) {
|
|
10308
10440
|
ctx.font = structure.baseline.style.font;
|
|
@@ -10389,7 +10521,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10389
10521
|
? toNumber(baselineDisplay, locale)
|
|
10390
10522
|
: 0;
|
|
10391
10523
|
return {
|
|
10392
|
-
title:
|
|
10524
|
+
title: {
|
|
10525
|
+
...chart.title,
|
|
10526
|
+
text: _t(chart.title.text ?? ""),
|
|
10527
|
+
},
|
|
10393
10528
|
keyValue: formattedKeyValue,
|
|
10394
10529
|
baselineDisplay,
|
|
10395
10530
|
baselineArrow: getBaselineArrowDirection(baselineCell, keyValueCell, chart.baselineMode),
|
|
@@ -10421,10 +10556,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10421
10556
|
}
|
|
10422
10557
|
|
|
10423
10558
|
/* Sizes of boxes containing the texts, in percentage of the Chart size */
|
|
10424
|
-
const TITLE_FONT_SIZE = 18;
|
|
10425
10559
|
const KEY_BOX_HEIGHT_RATIO = 0.8;
|
|
10426
10560
|
/* Padding at the border of the chart */
|
|
10427
|
-
const CHART_PADDING =
|
|
10561
|
+
const CHART_PADDING = DEFAULT_CHART_PADDING;
|
|
10428
10562
|
const BOTTOM_PADDING_RATIO = 0.05;
|
|
10429
10563
|
/**
|
|
10430
10564
|
* Line height (in em)
|
|
@@ -10435,11 +10569,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10435
10569
|
const _baselineDescr = baselineDescr || "";
|
|
10436
10570
|
return baseline && _baselineDescr ? " " + _baselineDescr : _baselineDescr;
|
|
10437
10571
|
}
|
|
10438
|
-
function getDefaultContextFont(fontSize, bold = false, italic = false) {
|
|
10439
|
-
const italicStr = italic ? "italic" : "";
|
|
10440
|
-
const weight = bold ? "bold" : "";
|
|
10441
|
-
return `${italicStr} ${weight} ${fontSize}px ${DEFAULT_FONT}`;
|
|
10442
|
-
}
|
|
10443
10572
|
function getScorecardConfiguration({ width, height }, runtime) {
|
|
10444
10573
|
const designer = new ScorecardChartConfigBuilder({ width, height }, runtime);
|
|
10445
10574
|
return designer.computeDesign();
|
|
@@ -10467,13 +10596,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10467
10596
|
const style = this.getTextStyles();
|
|
10468
10597
|
let titleHeight = 0;
|
|
10469
10598
|
if (this.title) {
|
|
10470
|
-
|
|
10599
|
+
let x, titleWidth;
|
|
10600
|
+
({ height: titleHeight, width: titleWidth } = this.getFullTextDimensions(this.title, style.title.font));
|
|
10601
|
+
switch (this.runtime.title.align) {
|
|
10602
|
+
case "center":
|
|
10603
|
+
x = (this.width - titleWidth) / 2;
|
|
10604
|
+
break;
|
|
10605
|
+
case "right":
|
|
10606
|
+
x = this.width - titleWidth - CHART_PADDING;
|
|
10607
|
+
break;
|
|
10608
|
+
case "left":
|
|
10609
|
+
default:
|
|
10610
|
+
x = CHART_PADDING;
|
|
10611
|
+
}
|
|
10471
10612
|
structure.title = {
|
|
10472
10613
|
text: this.title,
|
|
10473
10614
|
style: style.title,
|
|
10474
10615
|
position: {
|
|
10475
|
-
x
|
|
10476
|
-
y: CHART_PADDING / 2
|
|
10616
|
+
x,
|
|
10617
|
+
y: CHART_PADDING + titleHeight / 2,
|
|
10477
10618
|
},
|
|
10478
10619
|
};
|
|
10479
10620
|
}
|
|
@@ -10574,7 +10715,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10574
10715
|
return structure;
|
|
10575
10716
|
}
|
|
10576
10717
|
get title() {
|
|
10577
|
-
return this.runtime.title;
|
|
10718
|
+
return this.runtime.title.text ?? "";
|
|
10578
10719
|
}
|
|
10579
10720
|
get keyValue() {
|
|
10580
10721
|
return this.runtime.keyValue;
|
|
@@ -10642,8 +10783,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10642
10783
|
}
|
|
10643
10784
|
return {
|
|
10644
10785
|
title: {
|
|
10645
|
-
font: getDefaultContextFont(
|
|
10646
|
-
color: this.secondaryFontColor,
|
|
10786
|
+
font: getDefaultContextFont(DEFAULT_CHART_FONT_SIZE, this.runtime.title.bold, this.runtime.title.italic),
|
|
10787
|
+
color: this.runtime.title.color ?? this.secondaryFontColor,
|
|
10647
10788
|
},
|
|
10648
10789
|
keyValue: {
|
|
10649
10790
|
color: this.runtime.keyValueStyle?.textColor || this.runtime.fontColor,
|
|
@@ -10676,7 +10817,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
10676
10817
|
getDrawableHeight() {
|
|
10677
10818
|
const verticalPadding = CHART_PADDING + this.height * BOTTOM_PADDING_RATIO;
|
|
10678
10819
|
let availableHeight = this.height - 2 * verticalPadding;
|
|
10679
|
-
availableHeight -= this.title ?
|
|
10820
|
+
availableHeight -= this.title ? DEFAULT_CHART_FONT_SIZE * LINE_HEIGHT : 0;
|
|
10680
10821
|
return availableHeight;
|
|
10681
10822
|
}
|
|
10682
10823
|
}
|
|
@@ -12026,7 +12167,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
12026
12167
|
compute: function (range, ...args) {
|
|
12027
12168
|
let uniqueValues = new Set();
|
|
12028
12169
|
visitMatchingRanges(args, (i, j) => {
|
|
12029
|
-
const data = range[i][j];
|
|
12170
|
+
const data = range[i]?.[j];
|
|
12030
12171
|
if (isDataNonEmpty(data)) {
|
|
12031
12172
|
uniqueValues.add(data.value);
|
|
12032
12173
|
}
|
|
@@ -12656,7 +12797,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
12656
12797
|
}
|
|
12657
12798
|
let sum = 0;
|
|
12658
12799
|
visitMatchingRanges([criteriaRange, criterion], (i, j) => {
|
|
12659
|
-
const value = sumRange[i][j]
|
|
12800
|
+
const value = sumRange[i]?.[j]?.value;
|
|
12660
12801
|
if (typeof value === "number") {
|
|
12661
12802
|
sum += value;
|
|
12662
12803
|
}
|
|
@@ -12681,7 +12822,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
12681
12822
|
compute: function (sumRange, ...criters) {
|
|
12682
12823
|
let sum = 0;
|
|
12683
12824
|
visitMatchingRanges(criters, (i, j) => {
|
|
12684
|
-
const value = sumRange[i][j]
|
|
12825
|
+
const value = sumRange[i]?.[j]?.value;
|
|
12685
12826
|
if (typeof value === "number") {
|
|
12686
12827
|
sum += value;
|
|
12687
12828
|
}
|
|
@@ -13228,7 +13369,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13228
13369
|
let count = 0;
|
|
13229
13370
|
let sum = 0;
|
|
13230
13371
|
visitMatchingRanges([criteriaRange, criterion], (i, j) => {
|
|
13231
|
-
const value = _averageRange[i][j]
|
|
13372
|
+
const value = _averageRange[i]?.[j]?.value;
|
|
13232
13373
|
if (typeof value === "number") {
|
|
13233
13374
|
count += 1;
|
|
13234
13375
|
sum += value;
|
|
@@ -13257,7 +13398,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13257
13398
|
let count = 0;
|
|
13258
13399
|
let sum = 0;
|
|
13259
13400
|
visitMatchingRanges(args, (i, j) => {
|
|
13260
|
-
const value = _averageRange[i][j]
|
|
13401
|
+
const value = _averageRange[i]?.[j]?.value;
|
|
13261
13402
|
if (typeof value === "number") {
|
|
13262
13403
|
count += 1;
|
|
13263
13404
|
sum += value;
|
|
@@ -13562,7 +13703,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13562
13703
|
compute: function (range, ...args) {
|
|
13563
13704
|
let result = -Infinity;
|
|
13564
13705
|
visitMatchingRanges(args, (i, j) => {
|
|
13565
|
-
const value = range[i][j]
|
|
13706
|
+
const value = range[i]?.[j]?.value;
|
|
13566
13707
|
if (typeof value === "number") {
|
|
13567
13708
|
result = result < value ? value : result;
|
|
13568
13709
|
}
|
|
@@ -13645,7 +13786,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
13645
13786
|
compute: function (range, ...args) {
|
|
13646
13787
|
let result = Infinity;
|
|
13647
13788
|
visitMatchingRanges(args, (i, j) => {
|
|
13648
|
-
const value = range[i][j]
|
|
13789
|
+
const value = range[i]?.[j]?.value;
|
|
13649
13790
|
if (typeof value === "number") {
|
|
13650
13791
|
result = result > value ? value : result;
|
|
13651
13792
|
}
|
|
@@ -22102,9 +22243,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22102
22243
|
const GAUGE_INFLECTION_MARKER_COLOR = "#666666aa";
|
|
22103
22244
|
const GAUGE_INFLECTION_LABEL_BOTTOM_MARGIN = 6;
|
|
22104
22245
|
const GAUGE_TITLE_SECTION_HEIGHT = 25;
|
|
22105
|
-
const GAUGE_TITLE_FONT_SIZE =
|
|
22106
|
-
const GAUGE_TITLE_PADDING_LEFT =
|
|
22107
|
-
const GAUGE_TITLE_PADDING_TOP =
|
|
22246
|
+
const GAUGE_TITLE_FONT_SIZE = DEFAULT_CHART_FONT_SIZE;
|
|
22247
|
+
const GAUGE_TITLE_PADDING_LEFT = DEFAULT_CHART_PADDING;
|
|
22248
|
+
const GAUGE_TITLE_PADDING_TOP = DEFAULT_CHART_PADDING;
|
|
22108
22249
|
function drawGaugeChart(canvas, runtime) {
|
|
22109
22250
|
const canvasBoundingRect = canvas.getBoundingClientRect();
|
|
22110
22251
|
canvas.width = canvasBoundingRect.width;
|
|
@@ -22179,7 +22320,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22179
22320
|
function drawTitle(ctx, config) {
|
|
22180
22321
|
ctx.save();
|
|
22181
22322
|
const title = config.title;
|
|
22182
|
-
ctx.font =
|
|
22323
|
+
ctx.font = getDefaultContextFont(title.fontSize, title.bold, title.italic);
|
|
22324
|
+
ctx.textBaseline = "middle";
|
|
22183
22325
|
ctx.fillStyle = title.color;
|
|
22184
22326
|
ctx.fillText(title.label, title.textPosition.x, title.textPosition.y);
|
|
22185
22327
|
ctx.restore();
|
|
@@ -22188,7 +22330,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22188
22330
|
const maxValue = runtime.maxValue;
|
|
22189
22331
|
const minValue = runtime.minValue;
|
|
22190
22332
|
const gaugeValue = runtime.gaugeValue;
|
|
22191
|
-
const gaugeRect = getGaugeRect(boundingRect, runtime.title);
|
|
22333
|
+
const gaugeRect = getGaugeRect(boundingRect, runtime.title.text);
|
|
22192
22334
|
const gaugeArcWidth = gaugeRect.width / 6;
|
|
22193
22335
|
const gaugePercentage = gaugeValue
|
|
22194
22336
|
? (gaugeValue.value - minValue.value) / (maxValue.value - minValue.value)
|
|
@@ -22218,17 +22360,35 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22218
22360
|
};
|
|
22219
22361
|
const textColor = getContrastedTextColor(runtime.background);
|
|
22220
22362
|
const inflectionValues = getInflectionValues(runtime, gaugeRect, textColor, ctx);
|
|
22363
|
+
let x = 0, titleWidth = 0, titleHeight = 0;
|
|
22364
|
+
if (runtime.title.text) {
|
|
22365
|
+
({ width: titleWidth, height: titleHeight } = computeTextDimension(ctx, runtime.title.text, { ...runtime.title, fontSize: GAUGE_TITLE_FONT_SIZE }, "px"));
|
|
22366
|
+
}
|
|
22367
|
+
switch (runtime.title.align) {
|
|
22368
|
+
case "right":
|
|
22369
|
+
x = boundingRect.width - titleWidth - GAUGE_TITLE_PADDING_LEFT;
|
|
22370
|
+
break;
|
|
22371
|
+
case "center":
|
|
22372
|
+
x = (boundingRect.width - titleWidth) / 2;
|
|
22373
|
+
break;
|
|
22374
|
+
case "left":
|
|
22375
|
+
default:
|
|
22376
|
+
x = GAUGE_TITLE_PADDING_LEFT;
|
|
22377
|
+
break;
|
|
22378
|
+
}
|
|
22221
22379
|
return {
|
|
22222
22380
|
width: boundingRect.width,
|
|
22223
22381
|
height: boundingRect.height,
|
|
22224
22382
|
title: {
|
|
22225
|
-
label: runtime.title,
|
|
22383
|
+
label: runtime.title.text ?? "",
|
|
22226
22384
|
fontSize: GAUGE_TITLE_FONT_SIZE,
|
|
22227
22385
|
textPosition: {
|
|
22228
|
-
x
|
|
22229
|
-
y: GAUGE_TITLE_PADDING_TOP +
|
|
22386
|
+
x,
|
|
22387
|
+
y: GAUGE_TITLE_PADDING_TOP + titleHeight / 2,
|
|
22230
22388
|
},
|
|
22231
|
-
color: textColor,
|
|
22389
|
+
color: runtime.title.color ?? textColor,
|
|
22390
|
+
bold: runtime.title.bold,
|
|
22391
|
+
italic: runtime.title.italic,
|
|
22232
22392
|
},
|
|
22233
22393
|
backgroundColor: runtime.background,
|
|
22234
22394
|
gauge: {
|
|
@@ -22518,12 +22678,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22518
22678
|
* Get a default chart js configuration
|
|
22519
22679
|
*/
|
|
22520
22680
|
function getDefaultChartJsRuntime(chart, labels, fontColor, { format, locale, truncateLabels }) {
|
|
22681
|
+
const chartTitle = chart.title.text ? chart.title : { ...chart.title, content: "" };
|
|
22521
22682
|
const options = {
|
|
22522
22683
|
// https://www.chartjs.org/docs/latest/general/responsive.html
|
|
22523
22684
|
responsive: true, // will resize when its container is resized
|
|
22524
22685
|
maintainAspectRatio: false, // doesn't maintain the aspect ration (width/height =2 by default) so the user has the choice of the exact layout
|
|
22525
22686
|
layout: {
|
|
22526
|
-
padding: {
|
|
22687
|
+
padding: {
|
|
22688
|
+
left: DEFAULT_CHART_PADDING,
|
|
22689
|
+
right: DEFAULT_CHART_PADDING,
|
|
22690
|
+
top: chartTitle.text ? DEFAULT_CHART_PADDING / 2 : DEFAULT_CHART_PADDING + 5,
|
|
22691
|
+
bottom: DEFAULT_CHART_PADDING,
|
|
22692
|
+
},
|
|
22527
22693
|
},
|
|
22528
22694
|
elements: {
|
|
22529
22695
|
line: {
|
|
@@ -22536,10 +22702,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22536
22702
|
animation: false,
|
|
22537
22703
|
plugins: {
|
|
22538
22704
|
title: {
|
|
22539
|
-
display: !!
|
|
22540
|
-
text: _t(
|
|
22541
|
-
color: fontColor,
|
|
22542
|
-
|
|
22705
|
+
display: !!chartTitle.text,
|
|
22706
|
+
text: _t(chartTitle.text),
|
|
22707
|
+
color: chartTitle?.color ?? fontColor,
|
|
22708
|
+
align: chartTitle.align === "center" ? "center" : chartTitle.align === "right" ? "end" : "start",
|
|
22709
|
+
font: {
|
|
22710
|
+
size: DEFAULT_CHART_FONT_SIZE,
|
|
22711
|
+
weight: chartTitle.bold ? "bold" : "normal",
|
|
22712
|
+
style: chartTitle.italic ? "italic" : "normal",
|
|
22713
|
+
},
|
|
22543
22714
|
},
|
|
22544
22715
|
legend: {
|
|
22545
22716
|
// Disable default legend onClick (show/hide dataset), to allow us to set a global onClick on the chart container.
|
|
@@ -22674,9 +22845,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22674
22845
|
// we have to add the canvas to the DOM otherwise it won't be rendered
|
|
22675
22846
|
document.body.append(div);
|
|
22676
22847
|
if ("chartJsConfig" in runtime) {
|
|
22677
|
-
runtime.chartJsConfig
|
|
22848
|
+
const config = deepCopy(runtime.chartJsConfig);
|
|
22849
|
+
config.plugins = [backgroundColorChartJSPlugin];
|
|
22678
22850
|
// @ts-ignore
|
|
22679
|
-
const chart = new window.Chart(canvas,
|
|
22851
|
+
const chart = new window.Chart(canvas, config);
|
|
22680
22852
|
const imgContent = chart.toBase64Image();
|
|
22681
22853
|
chart.destroy();
|
|
22682
22854
|
div.remove();
|
|
@@ -22717,22 +22889,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22717
22889
|
dataSets;
|
|
22718
22890
|
labelRange;
|
|
22719
22891
|
background;
|
|
22720
|
-
verticalAxisPosition;
|
|
22721
22892
|
legendPosition;
|
|
22722
22893
|
stacked;
|
|
22723
22894
|
aggregated;
|
|
22724
22895
|
type = "bar";
|
|
22725
22896
|
dataSetsHaveTitle;
|
|
22897
|
+
dataSetDesign;
|
|
22898
|
+
axesDesign;
|
|
22726
22899
|
constructor(definition, sheetId, getters) {
|
|
22727
22900
|
super(definition, sheetId, getters);
|
|
22728
22901
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
22729
|
-
this.labelRange =
|
|
22902
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
22730
22903
|
this.background = definition.background;
|
|
22731
|
-
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
22732
22904
|
this.legendPosition = definition.legendPosition;
|
|
22733
22905
|
this.stacked = definition.stacked;
|
|
22734
22906
|
this.aggregated = definition.aggregated;
|
|
22735
22907
|
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
22908
|
+
this.dataSetDesign = definition.dataSets;
|
|
22909
|
+
this.axesDesign = definition.axesDesign;
|
|
22736
22910
|
}
|
|
22737
22911
|
static transformDefinition(definition, executed) {
|
|
22738
22912
|
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
@@ -22743,21 +22917,28 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22743
22917
|
static getDefinitionFromContextCreation(context) {
|
|
22744
22918
|
return {
|
|
22745
22919
|
background: context.background,
|
|
22746
|
-
dataSets: context.range
|
|
22920
|
+
dataSets: context.range ?? [],
|
|
22747
22921
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
22748
22922
|
stacked: context.stacked ?? false,
|
|
22749
22923
|
aggregated: context.aggregated ?? false,
|
|
22750
22924
|
legendPosition: context.legendPosition ?? "top",
|
|
22751
|
-
title: context.title || "",
|
|
22925
|
+
title: context.title || { text: "" },
|
|
22752
22926
|
type: "bar",
|
|
22753
|
-
verticalAxisPosition: context.verticalAxisPosition ?? "left",
|
|
22754
22927
|
labelRange: context.auxiliaryRange || undefined,
|
|
22928
|
+
axesDesign: context.axesDesign,
|
|
22755
22929
|
};
|
|
22756
22930
|
}
|
|
22757
22931
|
getContextCreation() {
|
|
22932
|
+
const range = [];
|
|
22933
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
22934
|
+
range.push({
|
|
22935
|
+
...this.dataSetDesign?.[i],
|
|
22936
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
22937
|
+
});
|
|
22938
|
+
}
|
|
22758
22939
|
return {
|
|
22759
22940
|
...this,
|
|
22760
|
-
range
|
|
22941
|
+
range,
|
|
22761
22942
|
auxiliaryRange: this.labelRange
|
|
22762
22943
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
22763
22944
|
: undefined,
|
|
@@ -22777,19 +22958,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22777
22958
|
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
22778
22959
|
}
|
|
22779
22960
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
22961
|
+
const ranges = [];
|
|
22962
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
22963
|
+
ranges.push({
|
|
22964
|
+
...this.dataSetDesign?.[i],
|
|
22965
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
22966
|
+
});
|
|
22967
|
+
}
|
|
22780
22968
|
return {
|
|
22781
22969
|
type: "bar",
|
|
22782
22970
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
22783
22971
|
background: this.background,
|
|
22784
|
-
dataSets:
|
|
22972
|
+
dataSets: ranges,
|
|
22785
22973
|
legendPosition: this.legendPosition,
|
|
22786
|
-
verticalAxisPosition: this.verticalAxisPosition,
|
|
22787
22974
|
labelRange: labelRange
|
|
22788
22975
|
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
22789
22976
|
: undefined,
|
|
22790
22977
|
title: this.title,
|
|
22791
22978
|
stacked: this.stacked,
|
|
22792
22979
|
aggregated: this.aggregated,
|
|
22980
|
+
axesDesign: this.axesDesign,
|
|
22793
22981
|
};
|
|
22794
22982
|
}
|
|
22795
22983
|
getDefinitionForExcel() {
|
|
@@ -22800,12 +22988,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22800
22988
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
22801
22989
|
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
22802
22990
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
22991
|
+
const definition = this.getDefinition();
|
|
22803
22992
|
return {
|
|
22804
|
-
...
|
|
22993
|
+
...definition,
|
|
22805
22994
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
22806
22995
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
22807
22996
|
dataSets,
|
|
22808
22997
|
labelRange,
|
|
22998
|
+
verticalAxis: getDefinedAxis(definition),
|
|
22809
22999
|
};
|
|
22810
23000
|
}
|
|
22811
23001
|
updateRanges(applyChange) {
|
|
@@ -22839,30 +23029,51 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22839
23029
|
padding: 5,
|
|
22840
23030
|
color: fontColor,
|
|
22841
23031
|
},
|
|
23032
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
22842
23033
|
},
|
|
22843
|
-
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
22850
|
-
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
|
|
22854
|
-
|
|
22855
|
-
|
|
22856
|
-
|
|
22857
|
-
},
|
|
23034
|
+
};
|
|
23035
|
+
const yAxis = {
|
|
23036
|
+
beginAtZero: true, // the origin of the y axis is always zero
|
|
23037
|
+
ticks: {
|
|
23038
|
+
color: fontColor,
|
|
23039
|
+
callback: (value) => {
|
|
23040
|
+
value = Number(value);
|
|
23041
|
+
if (isNaN(value))
|
|
23042
|
+
return value;
|
|
23043
|
+
const { locale, format } = localeFormat;
|
|
23044
|
+
return formatValue(value, {
|
|
23045
|
+
locale,
|
|
23046
|
+
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
23047
|
+
});
|
|
22858
23048
|
},
|
|
22859
23049
|
},
|
|
22860
23050
|
};
|
|
23051
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
|
|
23052
|
+
if (useLeftAxis) {
|
|
23053
|
+
config.options.scales.y = {
|
|
23054
|
+
...yAxis,
|
|
23055
|
+
position: "left",
|
|
23056
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
23057
|
+
};
|
|
23058
|
+
}
|
|
23059
|
+
if (useRightAxis) {
|
|
23060
|
+
config.options.scales.y1 = {
|
|
23061
|
+
...yAxis,
|
|
23062
|
+
position: "right",
|
|
23063
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
23064
|
+
};
|
|
23065
|
+
}
|
|
22861
23066
|
if (chart.stacked) {
|
|
22862
23067
|
// @ts-ignore chart.js type is broken
|
|
22863
23068
|
config.options.scales.x.stacked = true;
|
|
22864
|
-
|
|
22865
|
-
|
|
23069
|
+
if (useLeftAxis) {
|
|
23070
|
+
// @ts-ignore chart.js type is broken
|
|
23071
|
+
config.options.scales.y.stacked = true;
|
|
23072
|
+
}
|
|
23073
|
+
if (useRightAxis) {
|
|
23074
|
+
// @ts-ignore chart.js type is broken
|
|
23075
|
+
config.options.scales.y1.stacked = true;
|
|
23076
|
+
}
|
|
22866
23077
|
}
|
|
22867
23078
|
return config;
|
|
22868
23079
|
}
|
|
@@ -22882,8 +23093,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22882
23093
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
22883
23094
|
const locale = getters.getLocale();
|
|
22884
23095
|
const config = getBarConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
22885
|
-
const colors = new
|
|
22886
|
-
|
|
23096
|
+
const colors = new ColorGenerator();
|
|
23097
|
+
const definition = chart.getDefinition();
|
|
23098
|
+
for (const { label, data } of dataSetsValues) {
|
|
22887
23099
|
const color = colors.next();
|
|
22888
23100
|
const dataset = {
|
|
22889
23101
|
label,
|
|
@@ -22893,29 +23105,43 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22893
23105
|
};
|
|
22894
23106
|
config.data.datasets.push(dataset);
|
|
22895
23107
|
}
|
|
23108
|
+
for (const [index, dataset] of config.data.datasets.entries()) {
|
|
23109
|
+
if (definition.dataSets?.[index]?.backgroundColor) {
|
|
23110
|
+
const color = definition.dataSets[index].backgroundColor;
|
|
23111
|
+
dataset.backgroundColor = color;
|
|
23112
|
+
dataset.borderColor = color;
|
|
23113
|
+
}
|
|
23114
|
+
if (definition.dataSets?.[index]?.label) {
|
|
23115
|
+
const label = definition.dataSets[index].label;
|
|
23116
|
+
dataset.label = label;
|
|
23117
|
+
}
|
|
23118
|
+
if (definition.dataSets?.[index]?.yAxisId) {
|
|
23119
|
+
dataset["yAxisID"] = definition.dataSets[index].yAxisId;
|
|
23120
|
+
}
|
|
23121
|
+
}
|
|
22896
23122
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
22897
23123
|
}
|
|
22898
23124
|
|
|
22899
23125
|
class ComboChart extends AbstractChart {
|
|
22900
|
-
useBothYAxis;
|
|
22901
23126
|
dataSets;
|
|
22902
23127
|
labelRange;
|
|
22903
23128
|
background;
|
|
22904
|
-
verticalAxisPosition;
|
|
22905
23129
|
legendPosition;
|
|
22906
23130
|
aggregated;
|
|
22907
23131
|
dataSetsHaveTitle;
|
|
23132
|
+
dataSetDesign;
|
|
23133
|
+
axesDesign;
|
|
22908
23134
|
type = "combo";
|
|
22909
23135
|
constructor(definition, sheetId, getters) {
|
|
22910
23136
|
super(definition, sheetId, getters);
|
|
22911
23137
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
22912
|
-
this.labelRange =
|
|
23138
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
22913
23139
|
this.background = definition.background;
|
|
22914
|
-
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
22915
23140
|
this.legendPosition = definition.legendPosition;
|
|
22916
23141
|
this.aggregated = definition.aggregated;
|
|
22917
23142
|
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
22918
|
-
this.
|
|
23143
|
+
this.dataSetDesign = definition.dataSets;
|
|
23144
|
+
this.axesDesign = definition.axesDesign;
|
|
22919
23145
|
}
|
|
22920
23146
|
static transformDefinition(definition, executed) {
|
|
22921
23147
|
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
@@ -22924,9 +23150,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22924
23150
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
22925
23151
|
}
|
|
22926
23152
|
getContextCreation() {
|
|
23153
|
+
const range = [];
|
|
23154
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
23155
|
+
range.push({
|
|
23156
|
+
...this.dataSetDesign?.[i],
|
|
23157
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
23158
|
+
});
|
|
23159
|
+
}
|
|
22927
23160
|
return {
|
|
22928
23161
|
...this,
|
|
22929
|
-
range
|
|
23162
|
+
range,
|
|
22930
23163
|
auxiliaryRange: this.labelRange
|
|
22931
23164
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
22932
23165
|
: undefined,
|
|
@@ -22936,19 +23169,25 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22936
23169
|
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
22937
23170
|
}
|
|
22938
23171
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
23172
|
+
const ranges = [];
|
|
23173
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
23174
|
+
ranges.push({
|
|
23175
|
+
...this.dataSetDesign?.[i],
|
|
23176
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
23177
|
+
});
|
|
23178
|
+
}
|
|
22939
23179
|
return {
|
|
22940
23180
|
type: "combo",
|
|
22941
23181
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
22942
23182
|
background: this.background,
|
|
22943
|
-
dataSets:
|
|
23183
|
+
dataSets: ranges,
|
|
22944
23184
|
legendPosition: this.legendPosition,
|
|
22945
|
-
verticalAxisPosition: this.verticalAxisPosition,
|
|
22946
23185
|
labelRange: labelRange
|
|
22947
23186
|
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
22948
23187
|
: undefined,
|
|
22949
23188
|
title: this.title,
|
|
22950
23189
|
aggregated: this.aggregated,
|
|
22951
|
-
|
|
23190
|
+
axesDesign: this.axesDesign,
|
|
22952
23191
|
};
|
|
22953
23192
|
}
|
|
22954
23193
|
getDefinitionForExcel() {
|
|
@@ -22960,12 +23199,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22960
23199
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
22961
23200
|
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
22962
23201
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
23202
|
+
const definition = this.getDefinition();
|
|
22963
23203
|
return {
|
|
22964
|
-
...
|
|
23204
|
+
...definition,
|
|
22965
23205
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
22966
23206
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
22967
23207
|
dataSets,
|
|
22968
23208
|
labelRange,
|
|
23209
|
+
verticalAxis: getDefinedAxis(definition),
|
|
22969
23210
|
};
|
|
22970
23211
|
}
|
|
22971
23212
|
updateRanges(applyChange) {
|
|
@@ -22983,11 +23224,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22983
23224
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
22984
23225
|
aggregated: context.aggregated,
|
|
22985
23226
|
legendPosition: context.legendPosition ?? "top",
|
|
22986
|
-
title: context.title || "",
|
|
22987
|
-
verticalAxisPosition: context.verticalAxisPosition ?? "left",
|
|
23227
|
+
title: context.title || { text: "" },
|
|
22988
23228
|
labelRange: context.auxiliaryRange || undefined,
|
|
22989
23229
|
type: "combo",
|
|
22990
|
-
|
|
23230
|
+
axesDesign: context.axesDesign,
|
|
22991
23231
|
};
|
|
22992
23232
|
}
|
|
22993
23233
|
copyForSheetId(sheetId) {
|
|
@@ -23002,7 +23242,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23002
23242
|
}
|
|
23003
23243
|
}
|
|
23004
23244
|
function createComboChartRuntime(chart, getters) {
|
|
23005
|
-
const
|
|
23245
|
+
const mainDataSetFormat = chart.dataSets.length
|
|
23246
|
+
? getChartDatasetFormat(getters, [chart.dataSets[0]])
|
|
23247
|
+
: undefined;
|
|
23248
|
+
const lineDataSetsFormat = getChartDatasetFormat(getters, chart.dataSets.slice(1));
|
|
23006
23249
|
const locale = getters.getLocale();
|
|
23007
23250
|
const labelValues = getChartLabelValues(getters, chart.dataSets, chart.labelRange);
|
|
23008
23251
|
let labels = labelValues.formattedValues;
|
|
@@ -23016,11 +23259,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23016
23259
|
if (chart.aggregated) {
|
|
23017
23260
|
({ labels, dataSetsValues } = aggregateDataForLabels(labels, dataSetsValues));
|
|
23018
23261
|
}
|
|
23019
|
-
const localeFormat = { format:
|
|
23262
|
+
const localeFormat = { format: mainDataSetFormat, locale };
|
|
23020
23263
|
const fontColor = chartFontColor(chart.background);
|
|
23021
23264
|
const config = getDefaultChartJsRuntime(chart, labels, fontColor, localeFormat);
|
|
23022
23265
|
const legend = {
|
|
23023
23266
|
labels: { color: fontColor },
|
|
23267
|
+
reverse: true,
|
|
23024
23268
|
};
|
|
23025
23269
|
if ((!chart.labelRange && chart.dataSets.length === 1) || chart.legendPosition === "none") {
|
|
23026
23270
|
legend.display = false;
|
|
@@ -23038,52 +23282,64 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23038
23282
|
padding: 5,
|
|
23039
23283
|
color: fontColor,
|
|
23040
23284
|
},
|
|
23285
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
23041
23286
|
},
|
|
23042
23287
|
};
|
|
23043
|
-
const
|
|
23288
|
+
const formatCallback = (format) => {
|
|
23289
|
+
return (value) => {
|
|
23290
|
+
value = Number(value);
|
|
23291
|
+
if (isNaN(value))
|
|
23292
|
+
return value;
|
|
23293
|
+
const { locale } = localeFormat;
|
|
23294
|
+
return formatValue(value, {
|
|
23295
|
+
locale,
|
|
23296
|
+
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
23297
|
+
});
|
|
23298
|
+
};
|
|
23299
|
+
};
|
|
23300
|
+
const leftVerticalAxis = {
|
|
23044
23301
|
beginAtZero: true, // the origin of the y axis is always zero
|
|
23045
23302
|
ticks: {
|
|
23046
23303
|
color: fontColor,
|
|
23047
|
-
callback: (
|
|
23048
|
-
|
|
23049
|
-
|
|
23050
|
-
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
});
|
|
23056
|
-
},
|
|
23304
|
+
callback: formatCallback(mainDataSetFormat),
|
|
23305
|
+
},
|
|
23306
|
+
};
|
|
23307
|
+
const rightVerticalAxis = {
|
|
23308
|
+
beginAtZero: true, // the origin of the y axis is always zero
|
|
23309
|
+
ticks: {
|
|
23310
|
+
color: fontColor,
|
|
23311
|
+
callback: formatCallback(lineDataSetsFormat),
|
|
23057
23312
|
},
|
|
23058
23313
|
};
|
|
23059
|
-
|
|
23314
|
+
const definition = chart.getDefinition();
|
|
23315
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(definition);
|
|
23316
|
+
if (useLeftAxis) {
|
|
23060
23317
|
config.options.scales.y = {
|
|
23061
|
-
...
|
|
23318
|
+
...leftVerticalAxis,
|
|
23062
23319
|
position: "left",
|
|
23320
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
23063
23321
|
};
|
|
23322
|
+
}
|
|
23323
|
+
if (useRightAxis) {
|
|
23064
23324
|
config.options.scales.y1 = {
|
|
23065
|
-
...
|
|
23325
|
+
...rightVerticalAxis,
|
|
23066
23326
|
position: "right",
|
|
23067
23327
|
grid: {
|
|
23068
23328
|
display: false,
|
|
23069
23329
|
},
|
|
23330
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
23070
23331
|
};
|
|
23071
23332
|
}
|
|
23072
|
-
|
|
23073
|
-
config.options.scales.y = {
|
|
23074
|
-
...verticalAxis,
|
|
23075
|
-
position: chart.verticalAxisPosition,
|
|
23076
|
-
};
|
|
23077
|
-
}
|
|
23078
|
-
const colors = new ChartColors();
|
|
23333
|
+
const colors = new ColorGenerator();
|
|
23079
23334
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
23335
|
+
const design = definition.dataSets[index];
|
|
23080
23336
|
const color = colors.next();
|
|
23081
23337
|
const dataset = {
|
|
23082
|
-
label,
|
|
23338
|
+
label: design?.label ?? label,
|
|
23083
23339
|
data,
|
|
23084
|
-
borderColor: color,
|
|
23085
|
-
backgroundColor: color,
|
|
23086
|
-
yAxisID:
|
|
23340
|
+
borderColor: design?.backgroundColor ?? color,
|
|
23341
|
+
backgroundColor: design.backgroundColor ?? color,
|
|
23342
|
+
yAxisID: design?.yAxisId ?? "y",
|
|
23087
23343
|
type: index === 0 ? "bar" : "line",
|
|
23088
23344
|
order: -index,
|
|
23089
23345
|
};
|
|
@@ -23164,7 +23420,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23164
23420
|
type = "gauge";
|
|
23165
23421
|
constructor(definition, sheetId, getters) {
|
|
23166
23422
|
super(definition, sheetId, getters);
|
|
23167
|
-
this.dataRange =
|
|
23423
|
+
this.dataRange = createValidRange(this.getters, this.sheetId, definition.dataRange);
|
|
23168
23424
|
this.sectionRule = definition.sectionRule;
|
|
23169
23425
|
this.background = definition.background;
|
|
23170
23426
|
}
|
|
@@ -23184,9 +23440,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23184
23440
|
static getDefinitionFromContextCreation(context) {
|
|
23185
23441
|
return {
|
|
23186
23442
|
background: context.background,
|
|
23187
|
-
title: context.title || "",
|
|
23443
|
+
title: context.title || { text: "" },
|
|
23188
23444
|
type: "gauge",
|
|
23189
|
-
dataRange: context.range ? context.range[0] : undefined,
|
|
23445
|
+
dataRange: context.range ? context.range[0].dataRange : undefined,
|
|
23190
23446
|
sectionRule: {
|
|
23191
23447
|
colors: {
|
|
23192
23448
|
lowerColor: DEFAULT_GAUGE_LOWER_COLOR,
|
|
@@ -23237,7 +23493,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23237
23493
|
return {
|
|
23238
23494
|
...this,
|
|
23239
23495
|
range: this.dataRange
|
|
23240
|
-
? [this.getters.getRangeString(this.dataRange, this.sheetId)]
|
|
23496
|
+
? [{ dataRange: this.getters.getRangeString(this.dataRange, this.sheetId) }]
|
|
23241
23497
|
: undefined,
|
|
23242
23498
|
};
|
|
23243
23499
|
}
|
|
@@ -23300,7 +23556,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23300
23556
|
colors.push(chartColors.upperColor);
|
|
23301
23557
|
return {
|
|
23302
23558
|
background: getters.getStyleOfSingleCellChart(chart.background, dataRange).background,
|
|
23303
|
-
title: chart.title,
|
|
23559
|
+
title: chart.title ?? { text: "" },
|
|
23304
23560
|
minValue: {
|
|
23305
23561
|
value: minValue,
|
|
23306
23562
|
label: formatValue(minValue, { locale, format }),
|
|
@@ -23558,28 +23814,49 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23558
23814
|
padding: 5,
|
|
23559
23815
|
color: fontColor,
|
|
23560
23816
|
},
|
|
23817
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
23561
23818
|
},
|
|
23562
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
|
|
23575
|
-
|
|
23576
|
-
},
|
|
23819
|
+
};
|
|
23820
|
+
const yAxis = {
|
|
23821
|
+
beginAtZero: true, // the origin of the y axis is always zero
|
|
23822
|
+
ticks: {
|
|
23823
|
+
color: fontColor,
|
|
23824
|
+
callback: (value) => {
|
|
23825
|
+
value = Number(value);
|
|
23826
|
+
if (isNaN(value))
|
|
23827
|
+
return value;
|
|
23828
|
+
const { locale, format } = options;
|
|
23829
|
+
return formatValue(value, {
|
|
23830
|
+
locale,
|
|
23831
|
+
format: !format && Math.abs(value) >= 1000 ? "#,##" : format,
|
|
23832
|
+
});
|
|
23577
23833
|
},
|
|
23578
23834
|
},
|
|
23579
23835
|
};
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
config.options.scales.y
|
|
23836
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(chart.getDefinition());
|
|
23837
|
+
if (useLeftAxis) {
|
|
23838
|
+
config.options.scales.y = {
|
|
23839
|
+
...yAxis,
|
|
23840
|
+
position: "left",
|
|
23841
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
23842
|
+
};
|
|
23843
|
+
}
|
|
23844
|
+
if (useRightAxis) {
|
|
23845
|
+
config.options.scales.y1 = {
|
|
23846
|
+
...yAxis,
|
|
23847
|
+
position: "right",
|
|
23848
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y1),
|
|
23849
|
+
};
|
|
23850
|
+
}
|
|
23851
|
+
if ("stacked" in chart && chart.stacked) {
|
|
23852
|
+
if (useLeftAxis) {
|
|
23853
|
+
// @ts-ignore chart.js type is broken
|
|
23854
|
+
config.options.scales.y.stacked = true;
|
|
23855
|
+
}
|
|
23856
|
+
if (useRightAxis) {
|
|
23857
|
+
// @ts-ignore chart.js type is broken
|
|
23858
|
+
config.options.scales.y1.stacked = true;
|
|
23859
|
+
}
|
|
23583
23860
|
}
|
|
23584
23861
|
return config;
|
|
23585
23862
|
}
|
|
@@ -23626,7 +23903,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23626
23903
|
}
|
|
23627
23904
|
const stacked = "stacked" in chart ? chart.stacked : false;
|
|
23628
23905
|
const cumulative = "cumulative" in chart ? chart.cumulative : false;
|
|
23629
|
-
const colors = new
|
|
23906
|
+
const colors = new ColorGenerator();
|
|
23907
|
+
const definition = chart.getDefinition();
|
|
23630
23908
|
for (let [index, { label, data }] of dataSetsValues.entries()) {
|
|
23631
23909
|
if (["linear", "time"].includes(axisType)) {
|
|
23632
23910
|
// Replace empty string labels by undefined to make sure chartJS doesn't decide that "" is the same as 0
|
|
@@ -23659,6 +23937,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23659
23937
|
};
|
|
23660
23938
|
config.data.datasets.push(dataset);
|
|
23661
23939
|
}
|
|
23940
|
+
for (const [index, dataset] of config.data.datasets.entries()) {
|
|
23941
|
+
if (definition.dataSets?.[index]?.backgroundColor) {
|
|
23942
|
+
const color = definition.dataSets[index].backgroundColor;
|
|
23943
|
+
dataset.backgroundColor = color;
|
|
23944
|
+
dataset.borderColor = color;
|
|
23945
|
+
//@ts-ignore
|
|
23946
|
+
dataset.pointBackgroundColor = color;
|
|
23947
|
+
}
|
|
23948
|
+
if (definition.dataSets?.[index]?.label) {
|
|
23949
|
+
const label = definition.dataSets[index].label;
|
|
23950
|
+
dataset.label = label;
|
|
23951
|
+
}
|
|
23952
|
+
if (definition.dataSets?.[index]?.yAxisId) {
|
|
23953
|
+
dataset["yAxisID"] = definition.dataSets[index].yAxisId;
|
|
23954
|
+
}
|
|
23955
|
+
}
|
|
23662
23956
|
return {
|
|
23663
23957
|
chartJsConfig: config,
|
|
23664
23958
|
background: chart.background || BACKGROUND_CHART_COLOR,
|
|
@@ -23673,7 +23967,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23673
23967
|
dataSets;
|
|
23674
23968
|
labelRange;
|
|
23675
23969
|
background;
|
|
23676
|
-
verticalAxisPosition;
|
|
23677
23970
|
legendPosition;
|
|
23678
23971
|
labelsAsText;
|
|
23679
23972
|
stacked;
|
|
@@ -23681,18 +23974,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23681
23974
|
type = "line";
|
|
23682
23975
|
dataSetsHaveTitle;
|
|
23683
23976
|
cumulative;
|
|
23977
|
+
dataSetDesign;
|
|
23978
|
+
axesDesign;
|
|
23684
23979
|
constructor(definition, sheetId, getters) {
|
|
23685
23980
|
super(definition, sheetId, getters);
|
|
23686
23981
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
23687
|
-
this.labelRange =
|
|
23982
|
+
this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
|
|
23688
23983
|
this.background = definition.background;
|
|
23689
|
-
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
23690
23984
|
this.legendPosition = definition.legendPosition;
|
|
23691
23985
|
this.labelsAsText = definition.labelsAsText;
|
|
23692
23986
|
this.stacked = definition.stacked;
|
|
23693
23987
|
this.aggregated = definition.aggregated;
|
|
23694
23988
|
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
23695
23989
|
this.cumulative = definition.cumulative;
|
|
23990
|
+
this.dataSetDesign = definition.dataSets;
|
|
23991
|
+
this.axesDesign = definition.axesDesign;
|
|
23696
23992
|
}
|
|
23697
23993
|
static validateChartDefinition(validator, definition) {
|
|
23698
23994
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
@@ -23703,30 +23999,36 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23703
23999
|
static getDefinitionFromContextCreation(context) {
|
|
23704
24000
|
return {
|
|
23705
24001
|
background: context.background,
|
|
23706
|
-
dataSets: context.range
|
|
24002
|
+
dataSets: context.range ?? [],
|
|
23707
24003
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
23708
24004
|
labelsAsText: context.labelsAsText ?? false,
|
|
23709
24005
|
legendPosition: context.legendPosition ?? "top",
|
|
23710
|
-
title: context.title || "",
|
|
24006
|
+
title: context.title || { text: "" },
|
|
23711
24007
|
type: "line",
|
|
23712
|
-
verticalAxisPosition: context.verticalAxisPosition ?? "left",
|
|
23713
24008
|
labelRange: context.auxiliaryRange || undefined,
|
|
23714
24009
|
stacked: context.stacked ?? false,
|
|
23715
24010
|
aggregated: context.aggregated ?? false,
|
|
23716
24011
|
cumulative: context.cumulative ?? false,
|
|
24012
|
+
axesDesign: context.axesDesign,
|
|
23717
24013
|
};
|
|
23718
24014
|
}
|
|
23719
24015
|
getDefinition() {
|
|
23720
24016
|
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
23721
24017
|
}
|
|
23722
24018
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
24019
|
+
const ranges = [];
|
|
24020
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
24021
|
+
ranges.push({
|
|
24022
|
+
...this.dataSetDesign?.[i],
|
|
24023
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
24024
|
+
});
|
|
24025
|
+
}
|
|
23723
24026
|
return {
|
|
23724
24027
|
type: "line",
|
|
23725
24028
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
23726
24029
|
background: this.background,
|
|
23727
|
-
dataSets:
|
|
24030
|
+
dataSets: ranges,
|
|
23728
24031
|
legendPosition: this.legendPosition,
|
|
23729
|
-
verticalAxisPosition: this.verticalAxisPosition,
|
|
23730
24032
|
labelRange: labelRange
|
|
23731
24033
|
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
23732
24034
|
: undefined,
|
|
@@ -23735,12 +24037,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23735
24037
|
stacked: this.stacked,
|
|
23736
24038
|
aggregated: this.aggregated,
|
|
23737
24039
|
cumulative: this.cumulative,
|
|
24040
|
+
axesDesign: this.axesDesign,
|
|
23738
24041
|
};
|
|
23739
24042
|
}
|
|
23740
24043
|
getContextCreation() {
|
|
24044
|
+
const range = [];
|
|
24045
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
24046
|
+
range.push({
|
|
24047
|
+
...this.dataSetDesign?.[i],
|
|
24048
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
24049
|
+
});
|
|
24050
|
+
}
|
|
23741
24051
|
return {
|
|
23742
24052
|
...this,
|
|
23743
|
-
range
|
|
24053
|
+
range,
|
|
23744
24054
|
auxiliaryRange: this.labelRange
|
|
23745
24055
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
23746
24056
|
: undefined,
|
|
@@ -23762,12 +24072,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23762
24072
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
23763
24073
|
.filter((ds) => ds.range !== "" && ds.range !== CellErrorType.InvalidReference);
|
|
23764
24074
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
24075
|
+
const definition = this.getDefinition();
|
|
23765
24076
|
return {
|
|
23766
|
-
...
|
|
24077
|
+
...definition,
|
|
23767
24078
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
23768
24079
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
23769
24080
|
dataSets,
|
|
23770
24081
|
labelRange,
|
|
24082
|
+
verticalAxis: getDefinedAxis(definition),
|
|
23771
24083
|
};
|
|
23772
24084
|
}
|
|
23773
24085
|
copyForSheetId(sheetId) {
|
|
@@ -23797,7 +24109,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23797
24109
|
constructor(definition, sheetId, getters) {
|
|
23798
24110
|
super(definition, sheetId, getters);
|
|
23799
24111
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
23800
|
-
this.labelRange =
|
|
24112
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
23801
24113
|
this.background = definition.background;
|
|
23802
24114
|
this.legendPosition = definition.legendPosition;
|
|
23803
24115
|
this.aggregated = definition.aggregated;
|
|
@@ -23812,10 +24124,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23812
24124
|
static getDefinitionFromContextCreation(context) {
|
|
23813
24125
|
return {
|
|
23814
24126
|
background: context.background,
|
|
23815
|
-
dataSets: context.range
|
|
24127
|
+
dataSets: context.range ?? [],
|
|
23816
24128
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
23817
24129
|
legendPosition: context.legendPosition ?? "top",
|
|
23818
|
-
title: context.title || "",
|
|
24130
|
+
title: context.title || { text: "" },
|
|
23819
24131
|
type: "pie",
|
|
23820
24132
|
labelRange: context.auxiliaryRange || undefined,
|
|
23821
24133
|
aggregated: context.aggregated ?? false,
|
|
@@ -23827,7 +24139,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23827
24139
|
getContextCreation() {
|
|
23828
24140
|
return {
|
|
23829
24141
|
...this,
|
|
23830
|
-
range: this.dataSets.map((ds) =>
|
|
24142
|
+
range: this.dataSets.map((ds) => ({
|
|
24143
|
+
dataRange: this.getters.getRangeString(ds.dataRange, this.sheetId),
|
|
24144
|
+
})),
|
|
23831
24145
|
auxiliaryRange: this.labelRange
|
|
23832
24146
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
23833
24147
|
: undefined,
|
|
@@ -23838,7 +24152,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23838
24152
|
type: "pie",
|
|
23839
24153
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
23840
24154
|
background: this.background,
|
|
23841
|
-
dataSets: dataSets.map((ds) =>
|
|
24155
|
+
dataSets: dataSets.map((ds) => ({
|
|
24156
|
+
dataRange: this.getters.getRangeString(ds.dataRange, targetSheetId || this.sheetId),
|
|
24157
|
+
})),
|
|
23842
24158
|
legendPosition: this.legendPosition,
|
|
23843
24159
|
labelRange: labelRange
|
|
23844
24160
|
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
@@ -23869,7 +24185,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23869
24185
|
...this.getDefinition(),
|
|
23870
24186
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
23871
24187
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
23872
|
-
verticalAxisPosition: "left", //TODO ExcelChartDefinition should be adapted, but can be done later
|
|
23873
24188
|
dataSets,
|
|
23874
24189
|
labelRange,
|
|
23875
24190
|
};
|
|
@@ -23970,9 +24285,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23970
24285
|
const dataSetFormat = getChartDatasetFormat(getters, chart.dataSets);
|
|
23971
24286
|
const locale = getters.getLocale();
|
|
23972
24287
|
const config = getPieConfiguration(chart, labels, { format: dataSetFormat, locale });
|
|
23973
|
-
const
|
|
23974
|
-
for (
|
|
23975
|
-
const backgroundColor = getPieColors(colors, dataSetsValues);
|
|
24288
|
+
const backgroundColor = getPieColors(new ColorGenerator(), dataSetsValues);
|
|
24289
|
+
for (const { label, data } of dataSetsValues) {
|
|
23976
24290
|
const dataset = {
|
|
23977
24291
|
label,
|
|
23978
24292
|
data,
|
|
@@ -23988,22 +24302,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23988
24302
|
dataSets;
|
|
23989
24303
|
labelRange;
|
|
23990
24304
|
background;
|
|
23991
|
-
verticalAxisPosition;
|
|
23992
24305
|
legendPosition;
|
|
23993
24306
|
labelsAsText;
|
|
23994
24307
|
aggregated;
|
|
23995
24308
|
type = "scatter";
|
|
23996
24309
|
dataSetsHaveTitle;
|
|
24310
|
+
dataSetDesign;
|
|
24311
|
+
axesDesign;
|
|
23997
24312
|
constructor(definition, sheetId, getters) {
|
|
23998
24313
|
super(definition, sheetId, getters);
|
|
23999
24314
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
24000
|
-
this.labelRange =
|
|
24315
|
+
this.labelRange = createValidRange(this.getters, sheetId, definition.labelRange);
|
|
24001
24316
|
this.background = definition.background;
|
|
24002
|
-
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
24003
24317
|
this.legendPosition = definition.legendPosition;
|
|
24004
24318
|
this.labelsAsText = definition.labelsAsText;
|
|
24005
24319
|
this.aggregated = definition.aggregated;
|
|
24006
24320
|
this.dataSetsHaveTitle = definition.dataSetsHaveTitle;
|
|
24321
|
+
this.dataSetDesign = definition.dataSets;
|
|
24322
|
+
this.axesDesign = definition.axesDesign;
|
|
24007
24323
|
}
|
|
24008
24324
|
static validateChartDefinition(validator, definition) {
|
|
24009
24325
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
@@ -24014,40 +24330,54 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24014
24330
|
static getDefinitionFromContextCreation(context) {
|
|
24015
24331
|
return {
|
|
24016
24332
|
background: context.background,
|
|
24017
|
-
dataSets: context.range
|
|
24333
|
+
dataSets: context.range ?? [],
|
|
24018
24334
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
24019
24335
|
labelsAsText: context.labelsAsText ?? false,
|
|
24020
24336
|
legendPosition: context.legendPosition ?? "top",
|
|
24021
|
-
title: context.title || "",
|
|
24337
|
+
title: context.title || { text: "" },
|
|
24022
24338
|
type: "scatter",
|
|
24023
|
-
verticalAxisPosition: context.verticalAxisPosition ?? "left",
|
|
24024
24339
|
labelRange: context.auxiliaryRange || undefined,
|
|
24025
24340
|
aggregated: context.aggregated ?? false,
|
|
24341
|
+
axesDesign: context.axesDesign,
|
|
24026
24342
|
};
|
|
24027
24343
|
}
|
|
24028
24344
|
getDefinition() {
|
|
24029
24345
|
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
24030
24346
|
}
|
|
24031
24347
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
24348
|
+
const ranges = [];
|
|
24349
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
24350
|
+
ranges.push({
|
|
24351
|
+
...this.dataSetDesign?.[i],
|
|
24352
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
24353
|
+
});
|
|
24354
|
+
}
|
|
24032
24355
|
return {
|
|
24033
24356
|
type: "scatter",
|
|
24034
24357
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
24035
24358
|
background: this.background,
|
|
24036
|
-
dataSets:
|
|
24359
|
+
dataSets: ranges,
|
|
24037
24360
|
legendPosition: this.legendPosition,
|
|
24038
|
-
verticalAxisPosition: this.verticalAxisPosition,
|
|
24039
24361
|
labelRange: labelRange
|
|
24040
24362
|
? this.getters.getRangeString(labelRange, targetSheetId || this.sheetId)
|
|
24041
24363
|
: undefined,
|
|
24042
24364
|
title: this.title,
|
|
24043
24365
|
labelsAsText: this.labelsAsText,
|
|
24044
24366
|
aggregated: this.aggregated,
|
|
24367
|
+
axesDesign: this.axesDesign,
|
|
24045
24368
|
};
|
|
24046
24369
|
}
|
|
24047
24370
|
getContextCreation() {
|
|
24371
|
+
const range = [];
|
|
24372
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
24373
|
+
range.push({
|
|
24374
|
+
...this.dataSetDesign?.[i],
|
|
24375
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
24376
|
+
});
|
|
24377
|
+
}
|
|
24048
24378
|
return {
|
|
24049
24379
|
...this,
|
|
24050
|
-
range
|
|
24380
|
+
range,
|
|
24051
24381
|
auxiliaryRange: this.labelRange
|
|
24052
24382
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
24053
24383
|
: undefined,
|
|
@@ -24070,12 +24400,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24070
24400
|
.map((ds) => toExcelDataset(this.getters, ds))
|
|
24071
24401
|
.filter((ds) => ds.range !== "");
|
|
24072
24402
|
const labelRange = toExcelLabelRange(this.getters, this.labelRange, shouldRemoveFirstLabel(this.labelRange, this.dataSets[0], this.dataSetsHaveTitle));
|
|
24403
|
+
const definition = this.getDefinition();
|
|
24073
24404
|
return {
|
|
24074
|
-
...
|
|
24405
|
+
...definition,
|
|
24075
24406
|
backgroundColor: toXlsxHexColor(this.background || BACKGROUND_CHART_COLOR),
|
|
24076
24407
|
fontColor: toXlsxHexColor(chartFontColor(this.background)),
|
|
24077
24408
|
dataSets,
|
|
24078
24409
|
labelRange,
|
|
24410
|
+
verticalAxis: getDefinedAxis(definition),
|
|
24079
24411
|
};
|
|
24080
24412
|
}
|
|
24081
24413
|
copyForSheetId(sheetId) {
|
|
@@ -24095,13 +24427,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24095
24427
|
// have less options than the line chart (it only works with linear labels)
|
|
24096
24428
|
chartJsConfig.type = "line";
|
|
24097
24429
|
const configOptions = chartJsConfig.options;
|
|
24098
|
-
configOptions.elements = {
|
|
24099
|
-
point: {
|
|
24100
|
-
radius: 3,
|
|
24101
|
-
hoverRadius: 3, // chartJS seems bugged, the point starts with the "hoverRadius" value
|
|
24102
|
-
hitRadius: 8,
|
|
24103
|
-
},
|
|
24104
|
-
};
|
|
24105
24430
|
const locale = getters.getLocale();
|
|
24106
24431
|
configOptions.plugins.tooltip.callbacks.title = () => "";
|
|
24107
24432
|
configOptions.plugins.tooltip.callbacks.label = (tooltipItem) => {
|
|
@@ -24138,10 +24463,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24138
24463
|
positiveValuesColor;
|
|
24139
24464
|
negativeValuesColor;
|
|
24140
24465
|
subTotalValuesColor;
|
|
24466
|
+
dataSetDesign;
|
|
24467
|
+
axesDesign;
|
|
24141
24468
|
constructor(definition, sheetId, getters) {
|
|
24142
24469
|
super(definition, sheetId, getters);
|
|
24143
24470
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
24144
|
-
this.labelRange =
|
|
24471
|
+
this.labelRange = createValidRange(getters, sheetId, definition.labelRange);
|
|
24145
24472
|
this.background = definition.background;
|
|
24146
24473
|
this.verticalAxisPosition = definition.verticalAxisPosition;
|
|
24147
24474
|
this.legendPosition = definition.legendPosition;
|
|
@@ -24153,6 +24480,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24153
24480
|
this.negativeValuesColor = definition.negativeValuesColor;
|
|
24154
24481
|
this.subTotalValuesColor = definition.subTotalValuesColor;
|
|
24155
24482
|
this.firstValueAsSubtotal = definition.firstValueAsSubtotal;
|
|
24483
|
+
this.dataSetDesign = definition.dataSets;
|
|
24484
|
+
this.axesDesign = definition.axesDesign;
|
|
24156
24485
|
}
|
|
24157
24486
|
static transformDefinition(definition, executed) {
|
|
24158
24487
|
return transformChartDefinitionWithDataSetsWithZone(definition, executed);
|
|
@@ -24167,19 +24496,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24167
24496
|
dataSetsHaveTitle: context.dataSetsHaveTitle ?? false,
|
|
24168
24497
|
aggregated: context.aggregated ?? false,
|
|
24169
24498
|
legendPosition: context.legendPosition ?? "top",
|
|
24170
|
-
title: context.title || "",
|
|
24499
|
+
title: context.title || { text: "" },
|
|
24171
24500
|
type: "waterfall",
|
|
24172
|
-
verticalAxisPosition:
|
|
24501
|
+
verticalAxisPosition: "left",
|
|
24173
24502
|
labelRange: context.auxiliaryRange || undefined,
|
|
24174
24503
|
showSubTotals: context.showSubTotals ?? false,
|
|
24175
24504
|
showConnectorLines: context.showConnectorLines ?? true,
|
|
24176
24505
|
firstValueAsSubtotal: context.firstValueAsSubtotal ?? false,
|
|
24506
|
+
axesDesign: context.axesDesign,
|
|
24177
24507
|
};
|
|
24178
24508
|
}
|
|
24179
24509
|
getContextCreation() {
|
|
24510
|
+
const range = [];
|
|
24511
|
+
for (const [i, dataSet] of this.dataSets.entries()) {
|
|
24512
|
+
range.push({
|
|
24513
|
+
...this.dataSetDesign?.[i],
|
|
24514
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, this.sheetId),
|
|
24515
|
+
});
|
|
24516
|
+
}
|
|
24180
24517
|
return {
|
|
24181
24518
|
...this,
|
|
24182
|
-
range
|
|
24519
|
+
range,
|
|
24183
24520
|
auxiliaryRange: this.labelRange
|
|
24184
24521
|
? this.getters.getRangeString(this.labelRange, this.sheetId)
|
|
24185
24522
|
: undefined,
|
|
@@ -24199,11 +24536,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24199
24536
|
return this.getDefinitionWithSpecificDataSets(this.dataSets, this.labelRange);
|
|
24200
24537
|
}
|
|
24201
24538
|
getDefinitionWithSpecificDataSets(dataSets, labelRange, targetSheetId) {
|
|
24539
|
+
const ranges = [];
|
|
24540
|
+
for (const [i, dataSet] of dataSets.entries()) {
|
|
24541
|
+
ranges.push({
|
|
24542
|
+
...this.dataSetDesign?.[i],
|
|
24543
|
+
dataRange: this.getters.getRangeString(dataSet.dataRange, targetSheetId || this.sheetId),
|
|
24544
|
+
});
|
|
24545
|
+
}
|
|
24202
24546
|
return {
|
|
24203
24547
|
type: "waterfall",
|
|
24204
24548
|
dataSetsHaveTitle: dataSets.length ? Boolean(dataSets[0].labelCell) : false,
|
|
24205
24549
|
background: this.background,
|
|
24206
|
-
dataSets:
|
|
24550
|
+
dataSets: ranges,
|
|
24207
24551
|
legendPosition: this.legendPosition,
|
|
24208
24552
|
verticalAxisPosition: this.verticalAxisPosition,
|
|
24209
24553
|
labelRange: labelRange
|
|
@@ -24217,6 +24561,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24217
24561
|
negativeValuesColor: this.negativeValuesColor,
|
|
24218
24562
|
subTotalValuesColor: this.subTotalValuesColor,
|
|
24219
24563
|
firstValueAsSubtotal: this.firstValueAsSubtotal,
|
|
24564
|
+
axesDesign: this.axesDesign,
|
|
24220
24565
|
};
|
|
24221
24566
|
}
|
|
24222
24567
|
getDefinitionForExcel() {
|
|
@@ -24276,6 +24621,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24276
24621
|
grid: {
|
|
24277
24622
|
display: false,
|
|
24278
24623
|
},
|
|
24624
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.x),
|
|
24279
24625
|
},
|
|
24280
24626
|
y: {
|
|
24281
24627
|
position: chart.verticalAxisPosition,
|
|
@@ -24296,6 +24642,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24296
24642
|
return context.tick.value === 0 ? 2 : 1;
|
|
24297
24643
|
},
|
|
24298
24644
|
},
|
|
24645
|
+
title: getChartAxisTitleRuntime(chart.axesDesign?.y),
|
|
24299
24646
|
},
|
|
24300
24647
|
};
|
|
24301
24648
|
config.options.plugins.tooltip = {
|
|
@@ -26355,13 +26702,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26355
26702
|
if (!singleColumn) {
|
|
26356
26703
|
dataSetZone = { ...zone, left: zone.left + 1 };
|
|
26357
26704
|
}
|
|
26358
|
-
const
|
|
26705
|
+
const dataRange = zoneToXc(dataSetZone);
|
|
26706
|
+
const dataSets = [{ dataRange, yAxisId: "y" }];
|
|
26359
26707
|
const sheetId = getters.getActiveSheetId();
|
|
26360
26708
|
const topLeftCell = getters.getCell({ sheetId, col: zone.left, row: zone.top });
|
|
26361
26709
|
if (getZoneArea(zone) === 1 && topLeftCell?.content) {
|
|
26362
26710
|
return {
|
|
26363
26711
|
type: "scorecard",
|
|
26364
|
-
title: "",
|
|
26712
|
+
title: { text: "" },
|
|
26365
26713
|
background: topLeftCell.style?.fillColor || undefined,
|
|
26366
26714
|
keyValue: zoneToXc(zone),
|
|
26367
26715
|
baselineMode: DEFAULT_SCORECARD_BASELINE_MODE,
|
|
@@ -26397,7 +26745,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26397
26745
|
const labelRange = labelRangeXc ? getters.getRangeFromSheetXC(sheetId, labelRangeXc) : undefined;
|
|
26398
26746
|
if (canChartParseLabels(labelRange, getters)) {
|
|
26399
26747
|
return {
|
|
26400
|
-
title,
|
|
26748
|
+
title: { text: title },
|
|
26401
26749
|
dataSets,
|
|
26402
26750
|
labelsAsText: false,
|
|
26403
26751
|
stacked: false,
|
|
@@ -26406,7 +26754,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26406
26754
|
labelRange: labelRangeXc,
|
|
26407
26755
|
type: "line",
|
|
26408
26756
|
dataSetsHaveTitle,
|
|
26409
|
-
verticalAxisPosition: "left",
|
|
26410
26757
|
legendPosition: newLegendPos,
|
|
26411
26758
|
};
|
|
26412
26759
|
}
|
|
@@ -26414,24 +26761,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26414
26761
|
if (singleColumn &&
|
|
26415
26762
|
getData(getters, _dataSets[0]).every((e) => typeof e === "string" && !isEvaluationError(e))) {
|
|
26416
26763
|
return {
|
|
26417
|
-
title: "",
|
|
26418
|
-
dataSets,
|
|
26764
|
+
title: { text: "" },
|
|
26765
|
+
dataSets: [{ dataRange }],
|
|
26419
26766
|
aggregated: true,
|
|
26420
|
-
labelRange:
|
|
26767
|
+
labelRange: dataRange,
|
|
26421
26768
|
type: "pie",
|
|
26422
26769
|
legendPosition: "top",
|
|
26423
26770
|
dataSetsHaveTitle: false,
|
|
26424
26771
|
};
|
|
26425
26772
|
}
|
|
26426
26773
|
return {
|
|
26427
|
-
title,
|
|
26774
|
+
title: { text: title },
|
|
26428
26775
|
dataSets,
|
|
26429
26776
|
labelRange: labelRangeXc,
|
|
26430
26777
|
type: "bar",
|
|
26431
26778
|
stacked: false,
|
|
26432
26779
|
aggregated: false,
|
|
26433
26780
|
dataSetsHaveTitle,
|
|
26434
|
-
verticalAxisPosition: "left",
|
|
26435
26781
|
legendPosition: newLegendPos,
|
|
26436
26782
|
};
|
|
26437
26783
|
}
|
|
@@ -29472,6 +29818,41 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29472
29818
|
}
|
|
29473
29819
|
const otRegistry = new OTRegistry();
|
|
29474
29820
|
|
|
29821
|
+
css /* scss */ `
|
|
29822
|
+
.o-checkbox {
|
|
29823
|
+
display: flex;
|
|
29824
|
+
justify-items: center;
|
|
29825
|
+
input {
|
|
29826
|
+
margin-right: 5px;
|
|
29827
|
+
}
|
|
29828
|
+
}
|
|
29829
|
+
`;
|
|
29830
|
+
class Checkbox extends owl.Component {
|
|
29831
|
+
static template = "o-spreadsheet.Checkbox";
|
|
29832
|
+
static props = {
|
|
29833
|
+
label: { type: String, optional: true },
|
|
29834
|
+
value: { type: Boolean, optional: true },
|
|
29835
|
+
className: { type: String, optional: true },
|
|
29836
|
+
name: { type: String, optional: true },
|
|
29837
|
+
title: { type: String, optional: true },
|
|
29838
|
+
disabled: { type: Boolean, optional: true },
|
|
29839
|
+
onChange: Function,
|
|
29840
|
+
};
|
|
29841
|
+
static defaultProps = { value: false };
|
|
29842
|
+
onChange(ev) {
|
|
29843
|
+
const value = ev.target.checked;
|
|
29844
|
+
this.props.onChange(value);
|
|
29845
|
+
}
|
|
29846
|
+
}
|
|
29847
|
+
|
|
29848
|
+
class Section extends owl.Component {
|
|
29849
|
+
static template = "o_spreadsheet.Section";
|
|
29850
|
+
static props = {
|
|
29851
|
+
class: { type: String, optional: true },
|
|
29852
|
+
slots: Object,
|
|
29853
|
+
};
|
|
29854
|
+
}
|
|
29855
|
+
|
|
29475
29856
|
// The name is misleading and can be confused with the DOM focus.
|
|
29476
29857
|
class FocusStore {
|
|
29477
29858
|
mutators = ["focus", "unfocus"];
|
|
@@ -29496,6 +29877,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29496
29877
|
class SelectionInputStore extends SpreadsheetStore {
|
|
29497
29878
|
initialRanges;
|
|
29498
29879
|
inputHasSingleRange;
|
|
29880
|
+
colors;
|
|
29499
29881
|
mutators = [
|
|
29500
29882
|
"resetWithRanges",
|
|
29501
29883
|
"focusById",
|
|
@@ -29511,10 +29893,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29511
29893
|
inputSheetId;
|
|
29512
29894
|
focusStore = this.get(FocusStore);
|
|
29513
29895
|
highlightStore = this.get(HighlightStore);
|
|
29514
|
-
constructor(get, initialRanges = [], inputHasSingleRange = false) {
|
|
29896
|
+
constructor(get, initialRanges = [], inputHasSingleRange = false, colors = []) {
|
|
29515
29897
|
super(get);
|
|
29516
29898
|
this.initialRanges = initialRanges;
|
|
29517
29899
|
this.inputHasSingleRange = inputHasSingleRange;
|
|
29900
|
+
this.colors = colors;
|
|
29518
29901
|
if (inputHasSingleRange && initialRanges.length > 1) {
|
|
29519
29902
|
throw new Error("Input with a single range cannot be instantiated with several range references.");
|
|
29520
29903
|
}
|
|
@@ -29656,11 +30039,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29656
30039
|
* e.g. ["A1", "Sheet2!B3", "E12"]
|
|
29657
30040
|
*/
|
|
29658
30041
|
get selectionInputs() {
|
|
30042
|
+
const generator = new ColorGenerator(this.colors);
|
|
29659
30043
|
return this.ranges.map((input, index) => Object.assign({}, input, {
|
|
29660
30044
|
color: this.hasMainFocus &&
|
|
29661
30045
|
this.focusedRangeIndex !== null &&
|
|
29662
30046
|
this.getters.isRangeValid(input.xc)
|
|
29663
|
-
?
|
|
30047
|
+
? generator.next()
|
|
29664
30048
|
: null,
|
|
29665
30049
|
isFocused: this.hasMainFocus && this.focusedRangeIndex === index,
|
|
29666
30050
|
isValidRange: input.xc === "" || this.getters.isRangeValid(input.xc),
|
|
@@ -29737,10 +30121,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29737
30121
|
*/
|
|
29738
30122
|
insertNewRange(index, values) {
|
|
29739
30123
|
const currentMaxId = Math.max(0, ...this.ranges.map((range) => Number(range.id)));
|
|
30124
|
+
const colors = new ColorGenerator(this.colors);
|
|
30125
|
+
for (let i = 0; i < index; i++) {
|
|
30126
|
+
colors.next();
|
|
30127
|
+
}
|
|
29740
30128
|
this.ranges.splice(index, 0, ...values.map((xc, i) => ({
|
|
29741
30129
|
xc,
|
|
29742
30130
|
id: currentMaxId + i + 1,
|
|
29743
|
-
color: colors
|
|
30131
|
+
color: colors.next(),
|
|
29744
30132
|
})));
|
|
29745
30133
|
}
|
|
29746
30134
|
/**
|
|
@@ -29884,6 +30272,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29884
30272
|
class: { type: String, optional: true },
|
|
29885
30273
|
onSelectionChanged: { type: Function, optional: true },
|
|
29886
30274
|
onSelectionConfirmed: { type: Function, optional: true },
|
|
30275
|
+
colors: { type: Array, optional: true, default: [] },
|
|
29887
30276
|
};
|
|
29888
30277
|
state = owl.useState({
|
|
29889
30278
|
isMissing: false,
|
|
@@ -29908,7 +30297,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29908
30297
|
}
|
|
29909
30298
|
setup() {
|
|
29910
30299
|
owl.useEffect(() => this.focusedInput.el?.focus(), () => [this.focusedInput.el]);
|
|
29911
|
-
this.store = useLocalStore(SelectionInputStore, this.props.ranges, this.props.hasSingleRange || false);
|
|
30300
|
+
this.store = useLocalStore(SelectionInputStore, this.props.ranges, this.props.hasSingleRange || false, this.props.colors);
|
|
29912
30301
|
owl.onWillUpdateProps((nextProps) => {
|
|
29913
30302
|
if (nextProps.ranges.join() !== this.store.selectionInputValues.join()) {
|
|
29914
30303
|
this.triggerChange();
|
|
@@ -29983,6 +30372,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29983
30372
|
}
|
|
29984
30373
|
}
|
|
29985
30374
|
|
|
30375
|
+
class ChartDataSeries extends owl.Component {
|
|
30376
|
+
static template = "o-spreadsheet.ChartDataSeries";
|
|
30377
|
+
static components = { SelectionInput, Section };
|
|
30378
|
+
static props = {
|
|
30379
|
+
ranges: Array,
|
|
30380
|
+
hasSingleRange: { type: Boolean, optional: true },
|
|
30381
|
+
onSelectionChanged: Function,
|
|
30382
|
+
onSelectionConfirmed: Function,
|
|
30383
|
+
};
|
|
30384
|
+
get ranges() {
|
|
30385
|
+
return this.props.ranges.map((r) => r.dataRange);
|
|
30386
|
+
}
|
|
30387
|
+
get colors() {
|
|
30388
|
+
return this.props.ranges.map((r) => r.backgroundColor);
|
|
30389
|
+
}
|
|
30390
|
+
get title() {
|
|
30391
|
+
return this.props.hasSingleRange ? _t("Data range") : _t("Data series");
|
|
30392
|
+
}
|
|
30393
|
+
}
|
|
30394
|
+
|
|
29986
30395
|
css /* scss */ `
|
|
29987
30396
|
.o-validation-error,
|
|
29988
30397
|
.o-validation-warning {
|
|
@@ -30009,55 +30418,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30009
30418
|
}
|
|
30010
30419
|
}
|
|
30011
30420
|
|
|
30012
|
-
css /* scss */ `
|
|
30013
|
-
.o-checkbox {
|
|
30014
|
-
display: flex;
|
|
30015
|
-
justify-items: center;
|
|
30016
|
-
input {
|
|
30017
|
-
margin-right: 5px;
|
|
30018
|
-
}
|
|
30019
|
-
}
|
|
30020
|
-
`;
|
|
30021
|
-
class Checkbox extends owl.Component {
|
|
30022
|
-
static template = "o-spreadsheet.Checkbox";
|
|
30023
|
-
static props = {
|
|
30024
|
-
label: { type: String, optional: true },
|
|
30025
|
-
value: { type: Boolean, optional: true },
|
|
30026
|
-
className: { type: String, optional: true },
|
|
30027
|
-
name: { type: String, optional: true },
|
|
30028
|
-
title: { type: String, optional: true },
|
|
30029
|
-
disabled: { type: Boolean, optional: true },
|
|
30030
|
-
onChange: Function,
|
|
30031
|
-
};
|
|
30032
|
-
static defaultProps = { value: false };
|
|
30033
|
-
onChange(ev) {
|
|
30034
|
-
const value = ev.target.checked;
|
|
30035
|
-
this.props.onChange(value);
|
|
30036
|
-
}
|
|
30037
|
-
}
|
|
30038
|
-
|
|
30039
|
-
class Section extends owl.Component {
|
|
30040
|
-
static template = "o_spreadsheet.Section";
|
|
30041
|
-
static props = {
|
|
30042
|
-
class: { type: String, optional: true },
|
|
30043
|
-
slots: Object,
|
|
30044
|
-
};
|
|
30045
|
-
}
|
|
30046
|
-
|
|
30047
|
-
class ChartDataSeries extends owl.Component {
|
|
30048
|
-
static template = "o-spreadsheet.ChartDataSeries";
|
|
30049
|
-
static components = { SelectionInput, Section };
|
|
30050
|
-
static props = {
|
|
30051
|
-
ranges: Array,
|
|
30052
|
-
hasSingleRange: { type: Boolean, optional: true },
|
|
30053
|
-
onSelectionChanged: Function,
|
|
30054
|
-
onSelectionConfirmed: Function,
|
|
30055
|
-
};
|
|
30056
|
-
get title() {
|
|
30057
|
-
return this.props.hasSingleRange ? _t("Data range") : _t("Data series");
|
|
30058
|
-
}
|
|
30059
|
-
}
|
|
30060
|
-
|
|
30061
30421
|
class ChartErrorSection extends owl.Component {
|
|
30062
30422
|
static template = "o-spreadsheet.ChartErrorSection";
|
|
30063
30423
|
static components = { Section, ValidationMessages };
|
|
@@ -30086,8 +30446,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30086
30446
|
class GenericChartConfigPanel extends owl.Component {
|
|
30087
30447
|
static template = "o-spreadsheet-GenericChartConfigPanel";
|
|
30088
30448
|
static components = {
|
|
30089
|
-
SelectionInput,
|
|
30090
|
-
ValidationMessages,
|
|
30091
30449
|
ChartDataSeries,
|
|
30092
30450
|
ChartLabelRange,
|
|
30093
30451
|
Section,
|
|
@@ -30146,7 +30504,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30146
30504
|
* button "confirm" is clicked
|
|
30147
30505
|
*/
|
|
30148
30506
|
onDataSeriesRangesChanged(ranges) {
|
|
30149
|
-
this.dataSeriesRanges = ranges
|
|
30507
|
+
this.dataSeriesRanges = ranges.map((dataRange, i) => ({
|
|
30508
|
+
...this.dataSeriesRanges?.[i],
|
|
30509
|
+
dataRange,
|
|
30510
|
+
}));
|
|
30150
30511
|
this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.figureId, {
|
|
30151
30512
|
dataSets: this.dataSeriesRanges,
|
|
30152
30513
|
});
|
|
@@ -30189,7 +30550,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30189
30550
|
}
|
|
30190
30551
|
const getters = this.env.model.getters;
|
|
30191
30552
|
const sheetId = getters.getActiveSheetId();
|
|
30192
|
-
const labelRange =
|
|
30553
|
+
const labelRange = createValidRange(getters, sheetId, this.labelRange);
|
|
30193
30554
|
const dataSets = createDataSets(getters, this.dataSeriesRanges, sheetId, this.props.definition.dataSetsHaveTitle);
|
|
30194
30555
|
if (dataSets.length) {
|
|
30195
30556
|
return dataSets[0].dataRange.zone.top + 1;
|
|
@@ -30218,15 +30579,102 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30218
30579
|
}
|
|
30219
30580
|
}
|
|
30220
30581
|
|
|
30582
|
+
const ANGLE_DOWN = /*xml*/ `
|
|
30583
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 224 256">
|
|
30584
|
+
<path d="M201.4 342.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 274.7 86.6 137.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z" transform="translate(0, 9) scale(0.5,0.5)"/>
|
|
30585
|
+
</svg>
|
|
30586
|
+
`;
|
|
30587
|
+
const BACKGROUND_COLOR = "#fdfdfd";
|
|
30588
|
+
const BORDER_COLOR = "#8b8b8b";
|
|
30589
|
+
css /* scss */ `
|
|
30590
|
+
.o_side_panel_collapsible_title {
|
|
30591
|
+
font-size: 16px;
|
|
30592
|
+
font-weight: bold;
|
|
30593
|
+
cursor: pointer;
|
|
30594
|
+
padding: 6px 0px 6px 6px !important;
|
|
30595
|
+
|
|
30596
|
+
.collapsor:before {
|
|
30597
|
+
transform: rotate(-90deg);
|
|
30598
|
+
content: url("data:image/svg+xml,${encodeURIComponent(ANGLE_DOWN)}");
|
|
30599
|
+
width: 12px;
|
|
30600
|
+
display: inline-block;
|
|
30601
|
+
margin: 0 5px 0px 2px;
|
|
30602
|
+
height: 22px;
|
|
30603
|
+
transform-origin: 7px 10px;
|
|
30604
|
+
transition: transform 0.2s ease-in-out;
|
|
30605
|
+
}
|
|
30606
|
+
.collapsor:not(.collapsed):before {
|
|
30607
|
+
transform: rotate(0);
|
|
30608
|
+
}
|
|
30609
|
+
|
|
30610
|
+
.collapsor:not(.collapsed) {
|
|
30611
|
+
background-color: ${BACKGROUND_COLOR};
|
|
30612
|
+
border: solid ${BORDER_COLOR} 1px;
|
|
30613
|
+
margin: -3px 1px -6px -5px;
|
|
30614
|
+
border-radius: 5px 5px 0px 0px;
|
|
30615
|
+
border-bottom: 0px;
|
|
30616
|
+
transition-delay: 0s;
|
|
30617
|
+
}
|
|
30618
|
+
|
|
30619
|
+
.collapsor {
|
|
30620
|
+
width: 100%;
|
|
30621
|
+
margin: -2px 2px -5px -4px;
|
|
30622
|
+
padding: 2px 0 6px 4px;
|
|
30623
|
+
background-color: transparent;
|
|
30624
|
+
border: solid ${BORDER_COLOR} 0px;
|
|
30625
|
+
transition-delay: 0.35s;
|
|
30626
|
+
transition-property: all;
|
|
30627
|
+
}
|
|
30628
|
+
|
|
30629
|
+
.collapsor.collapsed {
|
|
30630
|
+
}
|
|
30631
|
+
}
|
|
30632
|
+
|
|
30633
|
+
.collapsible_section {
|
|
30634
|
+
background-color: #fff;
|
|
30635
|
+
border: solid ${BORDER_COLOR} 1px;
|
|
30636
|
+
border-top: 0;
|
|
30637
|
+
border-radius: 0 0 5px 5px;
|
|
30638
|
+
margin: 0px 1px 0px 1px;
|
|
30639
|
+
|
|
30640
|
+
&.collapsing,
|
|
30641
|
+
&.show {
|
|
30642
|
+
background-color: ${BACKGROUND_COLOR};
|
|
30643
|
+
}
|
|
30644
|
+
|
|
30645
|
+
&.collapsing {
|
|
30646
|
+
transition: height 0.35s, background-color 0.35s !important;
|
|
30647
|
+
}
|
|
30648
|
+
}
|
|
30649
|
+
`;
|
|
30650
|
+
let CURRENT_COLLAPSIBLE_ID = 0;
|
|
30651
|
+
class SidePanelCollapsible extends owl.Component {
|
|
30652
|
+
static template = "o-spreadsheet-SidePanelCollapsible";
|
|
30653
|
+
static props = {
|
|
30654
|
+
slots: Object,
|
|
30655
|
+
collapsedAtInit: { type: Boolean, optional: true },
|
|
30656
|
+
class: { type: String, optional: true },
|
|
30657
|
+
};
|
|
30658
|
+
currentId = (CURRENT_COLLAPSIBLE_ID++).toString();
|
|
30659
|
+
}
|
|
30660
|
+
|
|
30661
|
+
/**
|
|
30662
|
+
* Start listening to pointer events and apply the given callbacks.
|
|
30663
|
+
*
|
|
30664
|
+
* @returns A function to remove the listeners.
|
|
30665
|
+
*/
|
|
30221
30666
|
function startDnd(onMouseMove, onMouseUp, onMouseDown = () => { }) {
|
|
30222
|
-
const
|
|
30223
|
-
onMouseUp(ev);
|
|
30667
|
+
const removeListeners = () => {
|
|
30224
30668
|
window.removeEventListener("pointerdown", onMouseDown);
|
|
30225
30669
|
window.removeEventListener("pointerup", _onMouseUp);
|
|
30226
30670
|
window.removeEventListener("dragstart", _onDragStart);
|
|
30227
30671
|
window.removeEventListener("pointermove", onMouseMove);
|
|
30228
30672
|
window.removeEventListener("wheel", onMouseMove);
|
|
30229
30673
|
};
|
|
30674
|
+
const _onMouseUp = (ev) => {
|
|
30675
|
+
onMouseUp(ev);
|
|
30676
|
+
removeListeners();
|
|
30677
|
+
};
|
|
30230
30678
|
function _onDragStart(ev) {
|
|
30231
30679
|
ev.preventDefault();
|
|
30232
30680
|
}
|
|
@@ -30238,6 +30686,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30238
30686
|
// preventDefault() is not allowed in passive event handler.
|
|
30239
30687
|
// https://chromestatus.com/feature/6662647093133312
|
|
30240
30688
|
window.addEventListener("wheel", onMouseMove, { passive: false });
|
|
30689
|
+
return removeListeners;
|
|
30241
30690
|
}
|
|
30242
30691
|
/**
|
|
30243
30692
|
* Function to be used during a pointerdown event, this function allows to
|
|
@@ -30799,63 +31248,325 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30799
31248
|
}
|
|
30800
31249
|
}
|
|
30801
31250
|
|
|
31251
|
+
css /* scss */ `
|
|
31252
|
+
.o-chart-title-designer {
|
|
31253
|
+
> span {
|
|
31254
|
+
height: 30px;
|
|
31255
|
+
}
|
|
31256
|
+
|
|
31257
|
+
.o-menu-item-button.active {
|
|
31258
|
+
background-color: #e6f4ea;
|
|
31259
|
+
color: #188038;
|
|
31260
|
+
}
|
|
31261
|
+
|
|
31262
|
+
.o-dropdown-content {
|
|
31263
|
+
overflow-y: auto;
|
|
31264
|
+
overflow-x: hidden;
|
|
31265
|
+
padding: 2px;
|
|
31266
|
+
z-index: 100;
|
|
31267
|
+
box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15);
|
|
31268
|
+
|
|
31269
|
+
.o-dropdown-line {
|
|
31270
|
+
> span {
|
|
31271
|
+
padding: 4px;
|
|
31272
|
+
}
|
|
31273
|
+
}
|
|
31274
|
+
}
|
|
31275
|
+
}
|
|
31276
|
+
`;
|
|
30802
31277
|
class ChartTitle extends owl.Component {
|
|
30803
31278
|
static template = "o-spreadsheet.ChartTitle";
|
|
30804
|
-
static components = { Section };
|
|
30805
|
-
static props = {
|
|
31279
|
+
static components = { Section, ColorPickerWidget };
|
|
31280
|
+
static props = {
|
|
31281
|
+
title: String,
|
|
31282
|
+
updateTitle: Function,
|
|
31283
|
+
name: { type: String, optional: true },
|
|
31284
|
+
toggleItalic: { type: Function, optional: true },
|
|
31285
|
+
toggleBold: { type: Function, optional: true },
|
|
31286
|
+
updateAlignment: { type: Function, optional: true },
|
|
31287
|
+
updateColor: { type: Function, optional: true },
|
|
31288
|
+
style: { type: Object, optional: true },
|
|
31289
|
+
};
|
|
31290
|
+
openedEl = null;
|
|
31291
|
+
setup() {
|
|
31292
|
+
owl.useExternalListener(window, "click", this.onExternalClick);
|
|
31293
|
+
}
|
|
31294
|
+
state = owl.useState({
|
|
31295
|
+
activeTool: "",
|
|
31296
|
+
});
|
|
30806
31297
|
updateTitle(ev) {
|
|
30807
|
-
this.props.
|
|
31298
|
+
this.props.updateTitle(ev.target.value);
|
|
31299
|
+
}
|
|
31300
|
+
toggleDropdownTool(tool, ev) {
|
|
31301
|
+
const isOpen = this.state.activeTool === tool;
|
|
31302
|
+
this.closeMenus();
|
|
31303
|
+
this.state.activeTool = isOpen ? "" : tool;
|
|
31304
|
+
this.openedEl = isOpen ? null : ev.target;
|
|
31305
|
+
}
|
|
31306
|
+
/**
|
|
31307
|
+
* TODO: This is clearly not a goot way to handle external click, but
|
|
31308
|
+
* we currently have no other way to do it ... Should be done in
|
|
31309
|
+
* another task to handle the fact we want only one menu opened at a
|
|
31310
|
+
* time with something like a menuStore ?
|
|
31311
|
+
*/
|
|
31312
|
+
onExternalClick(ev) {
|
|
31313
|
+
if (this.openedEl === ev.target) {
|
|
31314
|
+
return;
|
|
31315
|
+
}
|
|
31316
|
+
this.closeMenus();
|
|
31317
|
+
}
|
|
31318
|
+
onColorPicked(color) {
|
|
31319
|
+
this.props.updateColor?.(color);
|
|
31320
|
+
this.closeMenus();
|
|
31321
|
+
}
|
|
31322
|
+
updateAlignment(aligment) {
|
|
31323
|
+
this.props.updateAlignment?.(aligment);
|
|
31324
|
+
this.closeMenus();
|
|
31325
|
+
}
|
|
31326
|
+
closeMenus() {
|
|
31327
|
+
this.state.activeTool = "";
|
|
31328
|
+
this.openedEl = null;
|
|
30808
31329
|
}
|
|
30809
31330
|
}
|
|
30810
31331
|
|
|
30811
|
-
class
|
|
30812
|
-
static template = "o-spreadsheet-
|
|
30813
|
-
static components = {
|
|
31332
|
+
class AxisDesignEditor extends owl.Component {
|
|
31333
|
+
static template = "o-spreadsheet-AxisDesignEditor";
|
|
31334
|
+
static components = {
|
|
31335
|
+
Section,
|
|
31336
|
+
ChartTitle,
|
|
31337
|
+
};
|
|
31338
|
+
state = owl.useState({ currentAxis: "x" });
|
|
31339
|
+
get axisTitleStyle() {
|
|
31340
|
+
const axisDesign = this.props.definition.axesDesign?.[this.state.currentAxis] ?? {};
|
|
31341
|
+
return {
|
|
31342
|
+
color: "",
|
|
31343
|
+
align: "center",
|
|
31344
|
+
...axisDesign.title,
|
|
31345
|
+
};
|
|
31346
|
+
}
|
|
31347
|
+
updateAxisTitleColor(color) {
|
|
31348
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31349
|
+
axesDesign[this.state.currentAxis] = {
|
|
31350
|
+
...axesDesign[this.state.currentAxis],
|
|
31351
|
+
title: {
|
|
31352
|
+
...(axesDesign[this.state.currentAxis]?.title ?? {}),
|
|
31353
|
+
color,
|
|
31354
|
+
},
|
|
31355
|
+
};
|
|
31356
|
+
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
31357
|
+
}
|
|
31358
|
+
toggleBoldAxisTitle() {
|
|
31359
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31360
|
+
const title = axesDesign[this.state.currentAxis]?.title ?? {};
|
|
31361
|
+
axesDesign[this.state.currentAxis] = {
|
|
31362
|
+
...axesDesign[this.state.currentAxis],
|
|
31363
|
+
title: {
|
|
31364
|
+
...title,
|
|
31365
|
+
bold: !title?.bold,
|
|
31366
|
+
},
|
|
31367
|
+
};
|
|
31368
|
+
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
31369
|
+
}
|
|
31370
|
+
toggleItalicAxisTitle() {
|
|
31371
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31372
|
+
const title = axesDesign[this.state.currentAxis]?.title ?? {};
|
|
31373
|
+
axesDesign[this.state.currentAxis] = {
|
|
31374
|
+
...axesDesign[this.state.currentAxis],
|
|
31375
|
+
title: {
|
|
31376
|
+
...title,
|
|
31377
|
+
italic: !title?.italic,
|
|
31378
|
+
},
|
|
31379
|
+
};
|
|
31380
|
+
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
31381
|
+
}
|
|
31382
|
+
updateAxisTitleAlignment(align) {
|
|
31383
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31384
|
+
const title = axesDesign[this.state.currentAxis]?.title ?? {};
|
|
31385
|
+
axesDesign[this.state.currentAxis] = {
|
|
31386
|
+
...axesDesign[this.state.currentAxis],
|
|
31387
|
+
title: {
|
|
31388
|
+
...title,
|
|
31389
|
+
align,
|
|
31390
|
+
},
|
|
31391
|
+
};
|
|
31392
|
+
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
31393
|
+
}
|
|
31394
|
+
updateAxisEditor(ev) {
|
|
31395
|
+
const axis = ev.target.value;
|
|
31396
|
+
this.state.currentAxis = axis;
|
|
31397
|
+
}
|
|
31398
|
+
getAxisTitle() {
|
|
31399
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31400
|
+
return axesDesign[this.state.currentAxis]?.title.text || "";
|
|
31401
|
+
}
|
|
31402
|
+
updateAxisTitle(text) {
|
|
31403
|
+
const axesDesign = this.props.definition.axesDesign ?? {};
|
|
31404
|
+
axesDesign[this.state.currentAxis] = {
|
|
31405
|
+
...axesDesign[this.state.currentAxis],
|
|
31406
|
+
title: {
|
|
31407
|
+
...axesDesign?.[this.state.currentAxis]?.title,
|
|
31408
|
+
text,
|
|
31409
|
+
},
|
|
31410
|
+
};
|
|
31411
|
+
this.props.updateChart(this.props.figureId, { axesDesign });
|
|
31412
|
+
}
|
|
31413
|
+
}
|
|
31414
|
+
|
|
31415
|
+
class GeneralDesignEditor extends owl.Component {
|
|
31416
|
+
static template = "o-spreadsheet-GeneralDesignEditor";
|
|
31417
|
+
static components = {
|
|
31418
|
+
RoundColorPicker,
|
|
31419
|
+
ChartTitle,
|
|
31420
|
+
Section,
|
|
31421
|
+
SidePanelCollapsible,
|
|
31422
|
+
};
|
|
30814
31423
|
static props = {
|
|
30815
31424
|
figureId: String,
|
|
30816
31425
|
definition: Object,
|
|
30817
31426
|
updateChart: Function,
|
|
30818
|
-
|
|
31427
|
+
slots: { type: Object, optional: true },
|
|
30819
31428
|
};
|
|
31429
|
+
state;
|
|
31430
|
+
setup() {
|
|
31431
|
+
this.state = owl.useState({
|
|
31432
|
+
activeTool: "",
|
|
31433
|
+
});
|
|
31434
|
+
}
|
|
30820
31435
|
get title() {
|
|
30821
|
-
return
|
|
31436
|
+
return this.props.definition.title;
|
|
31437
|
+
}
|
|
31438
|
+
toggleDropdownTool(tool, ev) {
|
|
31439
|
+
const isOpen = this.state.activeTool === tool;
|
|
31440
|
+
this.state.activeTool = isOpen ? "" : tool;
|
|
30822
31441
|
}
|
|
30823
31442
|
updateBackgroundColor(color) {
|
|
30824
31443
|
this.props.updateChart(this.props.figureId, {
|
|
30825
31444
|
background: color,
|
|
30826
31445
|
});
|
|
30827
31446
|
}
|
|
30828
|
-
updateTitle(
|
|
31447
|
+
updateTitle(newTitle) {
|
|
31448
|
+
const title = { ...this.title, text: newTitle };
|
|
30829
31449
|
this.props.updateChart(this.props.figureId, { title });
|
|
30830
31450
|
}
|
|
30831
|
-
|
|
30832
|
-
|
|
30833
|
-
|
|
30834
|
-
|
|
31451
|
+
get titleStyle() {
|
|
31452
|
+
return {
|
|
31453
|
+
align: "left",
|
|
31454
|
+
...this.title,
|
|
31455
|
+
};
|
|
30835
31456
|
}
|
|
30836
|
-
|
|
30837
|
-
|
|
31457
|
+
updateChartTitleColor(color) {
|
|
31458
|
+
const title = { ...this.title, color };
|
|
31459
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
31460
|
+
this.state.activeTool = "";
|
|
31461
|
+
}
|
|
31462
|
+
toggleBoldChartTitle() {
|
|
31463
|
+
let title = this.title;
|
|
31464
|
+
title = { ...title, bold: !title.bold };
|
|
31465
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
31466
|
+
}
|
|
31467
|
+
toggleItalicChartTitle() {
|
|
31468
|
+
let title = this.title;
|
|
31469
|
+
title = { ...title, italic: !title.italic };
|
|
31470
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
31471
|
+
}
|
|
31472
|
+
updateChartTitleAlignment(align) {
|
|
31473
|
+
const title = { ...this.title, align };
|
|
31474
|
+
this.props.updateChart(this.props.figureId, { title });
|
|
31475
|
+
this.state.activeTool = "";
|
|
30838
31476
|
}
|
|
30839
31477
|
}
|
|
30840
31478
|
|
|
30841
|
-
class
|
|
30842
|
-
static template = "o-spreadsheet-
|
|
30843
|
-
|
|
30844
|
-
|
|
30845
|
-
|
|
30846
|
-
|
|
30847
|
-
|
|
30848
|
-
|
|
31479
|
+
class ChartWithAxisDesignPanel extends owl.Component {
|
|
31480
|
+
static template = "o-spreadsheet-ChartWithAxisDesignPanel";
|
|
31481
|
+
static components = {
|
|
31482
|
+
GeneralDesignEditor,
|
|
31483
|
+
SidePanelCollapsible,
|
|
31484
|
+
Section,
|
|
31485
|
+
AxisDesignEditor,
|
|
31486
|
+
RoundColorPicker,
|
|
31487
|
+
};
|
|
31488
|
+
state = owl.useState({ index: 0 });
|
|
31489
|
+
get axesList() {
|
|
31490
|
+
const { useLeftAxis, useRightAxis } = getDefinedAxis(this.props.definition);
|
|
31491
|
+
let axes = [{ id: "x", name: _t("Horizontal axis") }];
|
|
31492
|
+
if (useLeftAxis) {
|
|
31493
|
+
axes.push({ id: "y", name: _t("Vertical (left) axis") });
|
|
31494
|
+
}
|
|
31495
|
+
if (useRightAxis) {
|
|
31496
|
+
axes.push({ id: "y1", name: _t("Vertical (right) axis") });
|
|
31497
|
+
}
|
|
31498
|
+
return axes;
|
|
30849
31499
|
}
|
|
30850
|
-
|
|
31500
|
+
updateLegendPosition(ev) {
|
|
30851
31501
|
this.props.updateChart(this.props.figureId, {
|
|
30852
|
-
|
|
31502
|
+
legendPosition: ev.target.value,
|
|
30853
31503
|
});
|
|
30854
31504
|
}
|
|
30855
|
-
|
|
30856
|
-
|
|
30857
|
-
|
|
30858
|
-
|
|
31505
|
+
getDataSeries() {
|
|
31506
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.figureId);
|
|
31507
|
+
if (!runtime || !("chartJsConfig" in runtime)) {
|
|
31508
|
+
return [];
|
|
31509
|
+
}
|
|
31510
|
+
return runtime.chartJsConfig.data.datasets.map((d) => d.label);
|
|
31511
|
+
}
|
|
31512
|
+
updateSerieEditor(ev) {
|
|
31513
|
+
const chartId = this.props.figureId;
|
|
31514
|
+
const selectedIndex = ev.target.selectedIndex;
|
|
31515
|
+
const runtime = this.env.model.getters.getChartRuntime(chartId);
|
|
31516
|
+
if (!runtime) {
|
|
31517
|
+
return;
|
|
31518
|
+
}
|
|
31519
|
+
this.state.index = selectedIndex;
|
|
31520
|
+
}
|
|
31521
|
+
updateDataSeriesColor(color) {
|
|
31522
|
+
const dataSets = this.props.definition.dataSets;
|
|
31523
|
+
if (!dataSets?.[this.state.index])
|
|
31524
|
+
return;
|
|
31525
|
+
dataSets[this.state.index] = {
|
|
31526
|
+
...dataSets[this.state.index],
|
|
31527
|
+
backgroundColor: color,
|
|
31528
|
+
};
|
|
31529
|
+
this.props.updateChart(this.props.figureId, { dataSets });
|
|
31530
|
+
}
|
|
31531
|
+
getDataSerieColor() {
|
|
31532
|
+
const dataSets = this.props.definition.dataSets;
|
|
31533
|
+
if (!dataSets?.[this.state.index])
|
|
31534
|
+
return "";
|
|
31535
|
+
const color = dataSets[this.state.index].backgroundColor;
|
|
31536
|
+
return color ? toHex(color) : getNthColor(this.state.index);
|
|
31537
|
+
}
|
|
31538
|
+
updateDataSeriesAxis(ev) {
|
|
31539
|
+
const axis = ev.target.value;
|
|
31540
|
+
const dataSets = this.props.definition.dataSets;
|
|
31541
|
+
if (!dataSets?.[this.state.index])
|
|
31542
|
+
return;
|
|
31543
|
+
dataSets[this.state.index] = {
|
|
31544
|
+
...dataSets[this.state.index],
|
|
31545
|
+
yAxisId: axis === "left" ? "y" : "y1",
|
|
31546
|
+
};
|
|
31547
|
+
this.props.updateChart(this.props.figureId, { dataSets });
|
|
31548
|
+
}
|
|
31549
|
+
getDataSerieAxis() {
|
|
31550
|
+
const dataSets = this.props.definition.dataSets;
|
|
31551
|
+
if (!dataSets?.[this.state.index])
|
|
31552
|
+
return "left";
|
|
31553
|
+
return dataSets[this.state.index].yAxisId === "y1" ? "right" : "left";
|
|
31554
|
+
}
|
|
31555
|
+
updateDataSeriesLabel(ev) {
|
|
31556
|
+
const label = ev.target.value;
|
|
31557
|
+
const dataSets = this.props.definition.dataSets;
|
|
31558
|
+
if (!dataSets?.[this.state.index])
|
|
31559
|
+
return;
|
|
31560
|
+
dataSets[this.state.index] = {
|
|
31561
|
+
...dataSets[this.state.index],
|
|
31562
|
+
label,
|
|
31563
|
+
};
|
|
31564
|
+
this.props.updateChart(this.props.figureId, { dataSets });
|
|
31565
|
+
}
|
|
31566
|
+
getDataSerieLabel() {
|
|
31567
|
+
const dataSets = this.props.definition.dataSets;
|
|
31568
|
+
return dataSets[this.state.index]?.label || this.getDataSeries()[this.state.index];
|
|
31569
|
+
}
|
|
30859
31570
|
}
|
|
30860
31571
|
|
|
30861
31572
|
class GaugeChartConfigPanel extends owl.Component {
|
|
@@ -30890,7 +31601,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30890
31601
|
});
|
|
30891
31602
|
}
|
|
30892
31603
|
getDataRange() {
|
|
30893
|
-
return this.dataRange || "";
|
|
31604
|
+
return { dataRange: this.dataRange || "" };
|
|
30894
31605
|
}
|
|
30895
31606
|
}
|
|
30896
31607
|
|
|
@@ -30932,24 +31643,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30932
31643
|
class GaugeChartDesignPanel extends owl.Component {
|
|
30933
31644
|
static template = "o-spreadsheet-GaugeChartDesignPanel";
|
|
30934
31645
|
static components = {
|
|
30935
|
-
|
|
30936
|
-
RoundColorPicker,
|
|
30937
|
-
ChartTitle,
|
|
31646
|
+
SidePanelCollapsible,
|
|
30938
31647
|
Section,
|
|
31648
|
+
RoundColorPicker,
|
|
31649
|
+
GeneralDesignEditor,
|
|
31650
|
+
ChartErrorSection,
|
|
30939
31651
|
};
|
|
30940
31652
|
static props = {
|
|
30941
31653
|
figureId: String,
|
|
30942
31654
|
definition: Object,
|
|
30943
31655
|
updateChart: Function,
|
|
30944
|
-
canUpdateChart: Function,
|
|
31656
|
+
canUpdateChart: { type: Function, optional: true },
|
|
30945
31657
|
};
|
|
30946
|
-
state
|
|
30947
|
-
|
|
30948
|
-
|
|
30949
|
-
|
|
30950
|
-
|
|
30951
|
-
|
|
30952
|
-
return _t(this.props.definition.title);
|
|
31658
|
+
state;
|
|
31659
|
+
setup() {
|
|
31660
|
+
this.state = owl.useState({
|
|
31661
|
+
sectionRuleDispatchResult: undefined,
|
|
31662
|
+
sectionRule: deepCopy(this.props.definition.sectionRule),
|
|
31663
|
+
});
|
|
30953
31664
|
}
|
|
30954
31665
|
get designErrorMessages() {
|
|
30955
31666
|
const cancelledReasons = [...(this.state.sectionRuleDispatchResult?.reasons || [])];
|
|
@@ -30960,8 +31671,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30960
31671
|
background: color,
|
|
30961
31672
|
});
|
|
30962
31673
|
}
|
|
30963
|
-
updateTitle(
|
|
30964
|
-
this.props.updateChart(this.props.figureId, { title });
|
|
31674
|
+
updateTitle(content) {
|
|
31675
|
+
this.props.updateChart(this.props.figureId, { title: { text: content } });
|
|
30965
31676
|
}
|
|
30966
31677
|
isRangeMinInvalid() {
|
|
30967
31678
|
return !!(this.state.sectionRuleDispatchResult?.isCancelledBecause("EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */) ||
|
|
@@ -31056,8 +31767,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31056
31767
|
}
|
|
31057
31768
|
}
|
|
31058
31769
|
|
|
31059
|
-
class
|
|
31060
|
-
static template = "o-spreadsheet-
|
|
31770
|
+
class PieChartDesignPanel extends owl.Component {
|
|
31771
|
+
static template = "o-spreadsheet-PieChartDesignPanel";
|
|
31772
|
+
static components = {
|
|
31773
|
+
GeneralDesignEditor,
|
|
31774
|
+
Section,
|
|
31775
|
+
};
|
|
31776
|
+
static props = {
|
|
31777
|
+
figureId: String,
|
|
31778
|
+
definition: Object,
|
|
31779
|
+
updateChart: Function,
|
|
31780
|
+
canUpdateChart: { type: Function, optional: true },
|
|
31781
|
+
};
|
|
31782
|
+
updateLegendPosition(ev) {
|
|
31783
|
+
this.props.updateChart(this.props.figureId, {
|
|
31784
|
+
legendPosition: ev.target.value,
|
|
31785
|
+
});
|
|
31786
|
+
}
|
|
31061
31787
|
}
|
|
31062
31788
|
|
|
31063
31789
|
class ScatterConfigPanel extends GenericChartConfigPanel {
|
|
@@ -31151,16 +31877,19 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31151
31877
|
|
|
31152
31878
|
class ScorecardChartDesignPanel extends owl.Component {
|
|
31153
31879
|
static template = "o-spreadsheet-ScorecardChartDesignPanel";
|
|
31154
|
-
static components = {
|
|
31880
|
+
static components = {
|
|
31881
|
+
GeneralDesignEditor,
|
|
31882
|
+
RoundColorPicker,
|
|
31883
|
+
SidePanelCollapsible,
|
|
31884
|
+
Section,
|
|
31885
|
+
Checkbox,
|
|
31886
|
+
};
|
|
31155
31887
|
static props = {
|
|
31156
31888
|
figureId: String,
|
|
31157
31889
|
definition: Object,
|
|
31158
31890
|
updateChart: Function,
|
|
31159
|
-
canUpdateChart: Function,
|
|
31891
|
+
canUpdateChart: { type: Function, optional: true },
|
|
31160
31892
|
};
|
|
31161
|
-
get title() {
|
|
31162
|
-
return _t(this.props.definition.title);
|
|
31163
|
-
}
|
|
31164
31893
|
get colorsSectionTitle() {
|
|
31165
31894
|
return this.props.definition.baselineMode === "progress"
|
|
31166
31895
|
? _t("Progress bar colors")
|
|
@@ -31169,8 +31898,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31169
31898
|
get humanizeNumbersLabel() {
|
|
31170
31899
|
return _t("Humanize numbers");
|
|
31171
31900
|
}
|
|
31172
|
-
updateTitle(
|
|
31173
|
-
this.props.updateChart(this.props.figureId, { title });
|
|
31901
|
+
updateTitle(content) {
|
|
31902
|
+
this.props.updateChart(this.props.figureId, { title: { text: content } });
|
|
31174
31903
|
}
|
|
31175
31904
|
updateHumanizeNumbers(humanize) {
|
|
31176
31905
|
this.props.updateChart(this.props.figureId, { humanize });
|
|
@@ -31199,14 +31928,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31199
31928
|
}
|
|
31200
31929
|
}
|
|
31201
31930
|
|
|
31202
|
-
class WaterfallChartDesignPanel extends
|
|
31931
|
+
class WaterfallChartDesignPanel extends owl.Component {
|
|
31203
31932
|
static template = "o-spreadsheet-WaterfallChartDesignPanel";
|
|
31204
|
-
static components = {
|
|
31205
|
-
|
|
31206
|
-
|
|
31207
|
-
|
|
31208
|
-
|
|
31209
|
-
|
|
31933
|
+
static components = {
|
|
31934
|
+
GeneralDesignEditor,
|
|
31935
|
+
Checkbox,
|
|
31936
|
+
SidePanelCollapsible,
|
|
31937
|
+
Section,
|
|
31938
|
+
RoundColorPicker,
|
|
31939
|
+
AxisDesignEditor,
|
|
31940
|
+
};
|
|
31941
|
+
static props = {
|
|
31942
|
+
figureId: String,
|
|
31943
|
+
definition: Object,
|
|
31944
|
+
updateChart: Function,
|
|
31945
|
+
canUpdateChart: { type: Function, optional: true },
|
|
31946
|
+
};
|
|
31210
31947
|
onUpdateShowSubTotals(showSubTotals) {
|
|
31211
31948
|
this.props.updateChart(this.props.figureId, { showSubTotals });
|
|
31212
31949
|
}
|
|
@@ -31219,11 +31956,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31219
31956
|
updateColor(colorName, color) {
|
|
31220
31957
|
this.props.updateChart(this.props.figureId, { [colorName]: color });
|
|
31221
31958
|
}
|
|
31222
|
-
|
|
31223
|
-
|
|
31224
|
-
|
|
31225
|
-
|
|
31226
|
-
|
|
31959
|
+
get axesList() {
|
|
31960
|
+
return [
|
|
31961
|
+
{ id: "x", name: _t("Horizontal axis") },
|
|
31962
|
+
{ id: "y", name: _t("Vertical axis") },
|
|
31963
|
+
];
|
|
31227
31964
|
}
|
|
31228
31965
|
get positiveValuesColor() {
|
|
31229
31966
|
return (this.props.definition.positiveValuesColor ||
|
|
@@ -31237,29 +31974,39 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31237
31974
|
return (this.props.definition.subTotalValuesColor ||
|
|
31238
31975
|
CHART_WATERFALL_SUBTOTAL_COLOR);
|
|
31239
31976
|
}
|
|
31977
|
+
updateLegendPosition(ev) {
|
|
31978
|
+
this.props.updateChart(this.props.figureId, {
|
|
31979
|
+
legendPosition: ev.target.value,
|
|
31980
|
+
});
|
|
31981
|
+
}
|
|
31982
|
+
updateVerticalAxisPosition(ev) {
|
|
31983
|
+
this.props.updateChart(this.props.figureId, {
|
|
31984
|
+
verticalAxisPosition: ev.target.value,
|
|
31985
|
+
});
|
|
31986
|
+
}
|
|
31240
31987
|
}
|
|
31241
31988
|
|
|
31242
31989
|
const chartSidePanelComponentRegistry = new Registry();
|
|
31243
31990
|
chartSidePanelComponentRegistry
|
|
31244
31991
|
.add("line", {
|
|
31245
31992
|
configuration: LineConfigPanel,
|
|
31246
|
-
design:
|
|
31993
|
+
design: ChartWithAxisDesignPanel,
|
|
31247
31994
|
})
|
|
31248
31995
|
.add("scatter", {
|
|
31249
31996
|
configuration: ScatterConfigPanel,
|
|
31250
|
-
design:
|
|
31997
|
+
design: ChartWithAxisDesignPanel,
|
|
31251
31998
|
})
|
|
31252
31999
|
.add("bar", {
|
|
31253
32000
|
configuration: BarConfigPanel,
|
|
31254
|
-
design:
|
|
32001
|
+
design: ChartWithAxisDesignPanel,
|
|
31255
32002
|
})
|
|
31256
32003
|
.add("combo", {
|
|
31257
|
-
configuration:
|
|
31258
|
-
design:
|
|
32004
|
+
configuration: GenericChartConfigPanel,
|
|
32005
|
+
design: ChartWithAxisDesignPanel,
|
|
31259
32006
|
})
|
|
31260
32007
|
.add("pie", {
|
|
31261
32008
|
configuration: GenericChartConfigPanel,
|
|
31262
|
-
design:
|
|
32009
|
+
design: PieChartDesignPanel,
|
|
31263
32010
|
})
|
|
31264
32011
|
.add("gauge", {
|
|
31265
32012
|
configuration: GaugeChartConfigPanel,
|
|
@@ -31545,6 +32292,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31545
32292
|
state.itemsStyle = {};
|
|
31546
32293
|
document.body.style.cursor = previousCursor;
|
|
31547
32294
|
args.onCancel?.();
|
|
32295
|
+
cleanUp();
|
|
31548
32296
|
};
|
|
31549
32297
|
const onDragEnd = (itemId, indexAtEnd) => {
|
|
31550
32298
|
state.draggedItemId = undefined;
|
|
@@ -31565,7 +32313,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31565
32313
|
onDragEnd,
|
|
31566
32314
|
onCancel: state.cancel,
|
|
31567
32315
|
});
|
|
31568
|
-
startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
32316
|
+
const stopListening = startDnd(dndHelper.onMouseMove.bind(dndHelper), dndHelper.onMouseUp.bind(dndHelper));
|
|
32317
|
+
cleanupFns.push(stopListening);
|
|
31569
32318
|
const onScroll = dndHelper.onScroll.bind(dndHelper);
|
|
31570
32319
|
args.containerEl.addEventListener("scroll", onScroll);
|
|
31571
32320
|
cleanupFns.push(() => args.containerEl.removeEventListener("scroll", onScroll));
|
|
@@ -31642,7 +32391,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31642
32391
|
this.moveDraggedItemToPosition(this.currentMousePosition + this.scrollOffset);
|
|
31643
32392
|
}
|
|
31644
32393
|
onMouseMove(ev) {
|
|
31645
|
-
if (ev.button
|
|
32394
|
+
if (ev.button > 1) {
|
|
31646
32395
|
this.onCancel();
|
|
31647
32396
|
return;
|
|
31648
32397
|
}
|
|
@@ -34385,7 +35134,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34385
35134
|
* This function converts a list of data entry into a spreadsheet pivot table.
|
|
34386
35135
|
*/
|
|
34387
35136
|
function dataEntriesToSpreadsheetPivotTable(dataEntries, definition) {
|
|
34388
|
-
const columnsTree =
|
|
35137
|
+
const columnsTree = dataEntriesToColumnsTree(dataEntries, definition.columns, 0);
|
|
34389
35138
|
computeWidthOfColumnsNodes(columnsTree, definition.measures.length);
|
|
34390
35139
|
const cols = columnsTreeToColumns(columnsTree, definition);
|
|
34391
35140
|
const rows = dataEntriesToRows(dataEntries, 0, definition.rows, [], []);
|
|
@@ -34436,7 +35185,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34436
35185
|
/**
|
|
34437
35186
|
* Create the columns tree from data entries.
|
|
34438
35187
|
*/
|
|
34439
|
-
function
|
|
35188
|
+
function dataEntriesToColumnsTree(dataEntries, columns, index) {
|
|
34440
35189
|
if (index >= columns.length) {
|
|
34441
35190
|
return [];
|
|
34442
35191
|
}
|
|
@@ -34448,7 +35197,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34448
35197
|
return {
|
|
34449
35198
|
value,
|
|
34450
35199
|
field: colName,
|
|
34451
|
-
children:
|
|
35200
|
+
children: dataEntriesToColumnsTree(groups[value] || [], columns, index + 1),
|
|
34452
35201
|
width: 0,
|
|
34453
35202
|
};
|
|
34454
35203
|
});
|
|
@@ -34955,7 +35704,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34955
35704
|
if (!field) {
|
|
34956
35705
|
throw new Error(`Field ${this.fieldKeys[index]} does not exist`);
|
|
34957
35706
|
}
|
|
34958
|
-
|
|
35707
|
+
if (cell.value === "") {
|
|
35708
|
+
entry[field.name] = { value: null, type: CellValueType.empty };
|
|
35709
|
+
}
|
|
35710
|
+
else {
|
|
35711
|
+
entry[field.name] = cell;
|
|
35712
|
+
}
|
|
34959
35713
|
}
|
|
34960
35714
|
entry["__count"] = { value: 1, type: CellValueType.number };
|
|
34961
35715
|
dataEntries.push(entry);
|
|
@@ -36711,14 +37465,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36711
37465
|
}
|
|
36712
37466
|
onKeyDown(ev) {
|
|
36713
37467
|
const figure = this.props.figure;
|
|
36714
|
-
|
|
37468
|
+
const keyDownShortcut = keyboardEventToShortcutString(ev);
|
|
37469
|
+
switch (keyDownShortcut) {
|
|
36715
37470
|
case "Delete":
|
|
37471
|
+
case "Backspace":
|
|
36716
37472
|
this.env.model.dispatch("DELETE_FIGURE", {
|
|
36717
37473
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
36718
37474
|
id: figure.id,
|
|
36719
37475
|
});
|
|
36720
37476
|
this.props.onFigureDeleted();
|
|
36721
|
-
ev.stopPropagation();
|
|
36722
37477
|
ev.preventDefault();
|
|
36723
37478
|
ev.stopPropagation();
|
|
36724
37479
|
break;
|
|
@@ -36739,7 +37494,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36739
37494
|
x: figure.x + delta[0],
|
|
36740
37495
|
y: figure.y + delta[1],
|
|
36741
37496
|
});
|
|
37497
|
+
ev.preventDefault();
|
|
36742
37498
|
ev.stopPropagation();
|
|
37499
|
+
break;
|
|
37500
|
+
case "Ctrl+A":
|
|
37501
|
+
// Maybe in the future we will implement a way to select all figures
|
|
37502
|
+
ev.preventDefault();
|
|
37503
|
+
ev.stopPropagation();
|
|
37504
|
+
break;
|
|
37505
|
+
case "Ctrl+Y":
|
|
37506
|
+
case "Ctrl+Z":
|
|
37507
|
+
if (keyDownShortcut === "Ctrl+Y") {
|
|
37508
|
+
this.env.model.dispatch("REQUEST_REDO");
|
|
37509
|
+
}
|
|
37510
|
+
else if (keyDownShortcut === "Ctrl+Z") {
|
|
37511
|
+
this.env.model.dispatch("REQUEST_UNDO");
|
|
37512
|
+
}
|
|
36743
37513
|
ev.preventDefault();
|
|
36744
37514
|
ev.stopPropagation();
|
|
36745
37515
|
break;
|
|
@@ -38019,9 +38789,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38019
38789
|
|
|
38020
38790
|
class FilterIconsOverlay extends owl.Component {
|
|
38021
38791
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
38022
|
-
static props = {
|
|
38023
|
-
onMouseDown: Function,
|
|
38024
|
-
};
|
|
38025
38792
|
static components = {
|
|
38026
38793
|
GridCellIcon,
|
|
38027
38794
|
FilterIcon,
|
|
@@ -38261,6 +39028,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38261
39028
|
};
|
|
38262
39029
|
gridOverlay = owl.useRef("gridOverlay");
|
|
38263
39030
|
gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
|
|
39031
|
+
cellPopovers;
|
|
38264
39032
|
setup() {
|
|
38265
39033
|
useCellHovered(this.env, this.gridOverlay, this.props.onCellHovered);
|
|
38266
39034
|
const resizeObserver = new ResizeObserver(() => {
|
|
@@ -38282,6 +39050,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38282
39050
|
const { scrollY } = this.env.model.getters.getActiveSheetDOMScrollInfo();
|
|
38283
39051
|
return scrollY > 0;
|
|
38284
39052
|
});
|
|
39053
|
+
this.cellPopovers = useStore(CellPopoverStore);
|
|
38285
39054
|
}
|
|
38286
39055
|
get gridOverlayEl() {
|
|
38287
39056
|
if (!this.gridOverlay.el) {
|
|
@@ -38295,16 +39064,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38295
39064
|
get isPaintingFormat() {
|
|
38296
39065
|
return this.env.model.getters.isPaintingFormat();
|
|
38297
39066
|
}
|
|
38298
|
-
onMouseDown(ev
|
|
39067
|
+
onMouseDown(ev) {
|
|
38299
39068
|
if (ev.button > 0) {
|
|
38300
39069
|
// not main button, probably a context menu
|
|
38301
39070
|
return;
|
|
38302
39071
|
}
|
|
39072
|
+
if (ev.target === this.gridOverlay.el && this.cellPopovers.isOpen) {
|
|
39073
|
+
this.cellPopovers.close();
|
|
39074
|
+
}
|
|
38303
39075
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
38304
39076
|
this.props.onCellClicked(col, row, {
|
|
38305
39077
|
expandZone: ev.shiftKey,
|
|
38306
39078
|
addZone: isCtrlKey(ev),
|
|
38307
|
-
closePopover: modifiers?.closePopover ?? true,
|
|
38308
39079
|
});
|
|
38309
39080
|
}
|
|
38310
39081
|
onDoubleClick(ev) {
|
|
@@ -40448,9 +41219,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40448
41219
|
// Zone selection with mouse
|
|
40449
41220
|
// ---------------------------------------------------------------------------
|
|
40450
41221
|
onCellClicked(col, row, modifiers) {
|
|
40451
|
-
if (modifiers.closePopover && this.cellPopovers.isOpen) {
|
|
40452
|
-
this.cellPopovers.close();
|
|
40453
|
-
}
|
|
40454
41222
|
if (this.composerStore.editionMode === "editing") {
|
|
40455
41223
|
this.composerStore.stopEdition();
|
|
40456
41224
|
}
|
|
@@ -42323,11 +43091,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42323
43091
|
return "imageSrc" in data;
|
|
42324
43092
|
}
|
|
42325
43093
|
function convertChartData(chartData) {
|
|
42326
|
-
const dataSetsHaveTitle = chartData.dataSets
|
|
43094
|
+
const dataSetsHaveTitle = chartData.dataSets.some((ds) => "reference" in (ds.label ?? {}));
|
|
42327
43095
|
const labelRange = chartData.labelRange
|
|
42328
43096
|
? convertExcelRangeToSheetXC(chartData.labelRange, dataSetsHaveTitle)
|
|
42329
43097
|
: undefined;
|
|
42330
|
-
|
|
43098
|
+
const dataSets = chartData.dataSets.map((data) => {
|
|
43099
|
+
let label = undefined;
|
|
43100
|
+
if (data.label && "text" in data.label) {
|
|
43101
|
+
label = data.label.text;
|
|
43102
|
+
}
|
|
43103
|
+
return {
|
|
43104
|
+
dataRange: convertExcelRangeToSheetXC(data.range, dataSetsHaveTitle),
|
|
43105
|
+
label,
|
|
43106
|
+
};
|
|
43107
|
+
});
|
|
42331
43108
|
// For doughnut charts, in chartJS first dataset = outer dataset, in excel first dataset = inner dataset
|
|
42332
43109
|
if (chartData.type === "pie") {
|
|
42333
43110
|
dataSets.reverse();
|
|
@@ -42336,10 +43113,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42336
43113
|
dataSets,
|
|
42337
43114
|
dataSetsHaveTitle,
|
|
42338
43115
|
labelRange,
|
|
42339
|
-
title: chartData.title
|
|
43116
|
+
title: chartData.title ?? { text: "" },
|
|
42340
43117
|
type: chartData.type,
|
|
42341
43118
|
background: convertColor({ rgb: chartData.backgroundColor }) || "#FFFFFF",
|
|
42342
|
-
verticalAxisPosition: chartData.verticalAxisPosition,
|
|
42343
43119
|
legendPosition: chartData.legendPosition,
|
|
42344
43120
|
stacked: chartData.stacked || false,
|
|
42345
43121
|
aggregated: false,
|
|
@@ -43454,25 +44230,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43454
44230
|
return this.extractComboChart(rootChartElement);
|
|
43455
44231
|
}
|
|
43456
44232
|
// Title can be separated into multiple xml elements (for styling and such), we only import the text
|
|
43457
|
-
const chartTitle = this.mapOnElements({ parent: rootChartElement, query: "c:title a:t" }, (textElement) => {
|
|
44233
|
+
const chartTitle = this.mapOnElements({ parent: rootChartElement, query: "c:chart > c:title a:t" }, (textElement) => {
|
|
43458
44234
|
return textElement.textContent || "";
|
|
43459
44235
|
}).join("");
|
|
43460
44236
|
const barChartGrouping = this.extractChildAttr(rootChartElement, "c:grouping", "val", {
|
|
43461
44237
|
default: "clustered",
|
|
43462
44238
|
}).asString();
|
|
43463
44239
|
return {
|
|
43464
|
-
title: chartTitle,
|
|
44240
|
+
title: { text: chartTitle },
|
|
43465
44241
|
type: CHART_TYPE_CONVERSION_MAP[chartType],
|
|
43466
|
-
dataSets: this.extractChartDatasets(this.
|
|
44242
|
+
dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
|
|
43467
44243
|
labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
|
|
43468
44244
|
backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
|
|
43469
44245
|
default: "ffffff",
|
|
43470
44246
|
}).asString(),
|
|
43471
|
-
verticalAxisPosition: this.extractChildAttr(rootChartElement, "c:valAx > c:axPos", "val", {
|
|
43472
|
-
default: "l",
|
|
43473
|
-
}).asString() === "r"
|
|
43474
|
-
? "right"
|
|
43475
|
-
: "left",
|
|
43476
44247
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
|
|
43477
44248
|
default: "b",
|
|
43478
44249
|
}).asString()],
|
|
@@ -43490,21 +44261,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43490
44261
|
default: "clustered",
|
|
43491
44262
|
}).asString();
|
|
43492
44263
|
return {
|
|
43493
|
-
title: chartTitle,
|
|
44264
|
+
title: { text: chartTitle },
|
|
43494
44265
|
type: "combo",
|
|
43495
44266
|
dataSets: [
|
|
43496
|
-
...this.extractChartDatasets(this.
|
|
43497
|
-
...this.extractChartDatasets(this.
|
|
44267
|
+
...this.extractChartDatasets(this.querySelectorAll(chartElement, `c:barChart`), "comboChart"),
|
|
44268
|
+
...this.extractChartDatasets(this.querySelectorAll(chartElement, `c:lineChart`), "comboChart"),
|
|
43498
44269
|
],
|
|
43499
44270
|
labelRange: this.extractChildTextContent(chartElement, "c:ser c:cat c:f"),
|
|
43500
44271
|
backgroundColor: this.extractChildAttr(chartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
|
|
43501
44272
|
default: "ffffff",
|
|
43502
44273
|
}).asString(),
|
|
43503
|
-
verticalAxisPosition: this.extractChildAttr(chartElement, "c:valAx > c:axPos", "val", {
|
|
43504
|
-
default: "l",
|
|
43505
|
-
}).asString() === "r"
|
|
43506
|
-
? "right"
|
|
43507
|
-
: "left",
|
|
43508
44274
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
|
|
43509
44275
|
default: "b",
|
|
43510
44276
|
}).asString()],
|
|
@@ -43512,21 +44278,49 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43512
44278
|
fontColor: "000000",
|
|
43513
44279
|
};
|
|
43514
44280
|
}
|
|
43515
|
-
extractChartDatasets(
|
|
43516
|
-
|
|
43517
|
-
|
|
43518
|
-
|
|
43519
|
-
|
|
43520
|
-
|
|
43521
|
-
|
|
43522
|
-
|
|
43523
|
-
|
|
43524
|
-
|
|
44281
|
+
extractChartDatasets(chartElements, chartType) {
|
|
44282
|
+
return Array.from(chartElements)
|
|
44283
|
+
.map((element) => {
|
|
44284
|
+
if (chartType === "scatterChart") {
|
|
44285
|
+
return this.extractScatterChartDatasets(element);
|
|
44286
|
+
}
|
|
44287
|
+
return this.mapOnElements({ parent: element, query: "c:ser" }, (chartDataElement) => {
|
|
44288
|
+
let label = {};
|
|
44289
|
+
const reference = this.extractChildTextContent(chartDataElement, "c:tx c:f");
|
|
44290
|
+
if (reference) {
|
|
44291
|
+
label = { reference };
|
|
44292
|
+
}
|
|
44293
|
+
else {
|
|
44294
|
+
const text = this.extractChildTextContent(chartDataElement, "c:tx c:v");
|
|
44295
|
+
if (text) {
|
|
44296
|
+
label = { text };
|
|
44297
|
+
}
|
|
44298
|
+
}
|
|
44299
|
+
return {
|
|
44300
|
+
label,
|
|
44301
|
+
range: this.extractChildTextContent(chartDataElement, "c:val c:f", {
|
|
44302
|
+
required: true,
|
|
44303
|
+
}),
|
|
44304
|
+
};
|
|
44305
|
+
});
|
|
44306
|
+
})
|
|
44307
|
+
.flat();
|
|
43525
44308
|
}
|
|
43526
44309
|
extractScatterChartDatasets(chartElement) {
|
|
43527
44310
|
return this.mapOnElements({ parent: chartElement, query: "c:ser" }, (chartDataElement) => {
|
|
44311
|
+
let label = {};
|
|
44312
|
+
const reference = this.extractChildTextContent(chartDataElement, "c:tx c:f");
|
|
44313
|
+
if (reference) {
|
|
44314
|
+
label = { reference };
|
|
44315
|
+
}
|
|
44316
|
+
else {
|
|
44317
|
+
const text = this.extractChildTextContent(chartDataElement, "c:tx c:v");
|
|
44318
|
+
if (text) {
|
|
44319
|
+
label = { text };
|
|
44320
|
+
}
|
|
44321
|
+
}
|
|
43528
44322
|
return {
|
|
43529
|
-
label
|
|
44323
|
+
label,
|
|
43530
44324
|
range: this.extractChildTextContent(chartDataElement, "c:yVal c:f", { required: true }),
|
|
43531
44325
|
};
|
|
43532
44326
|
});
|
|
@@ -44258,7 +45052,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44258
45052
|
return relsFile;
|
|
44259
45053
|
}
|
|
44260
45054
|
|
|
44261
|
-
const EXCEL_IMPORT_VERSION =
|
|
45055
|
+
const EXCEL_IMPORT_VERSION = 16;
|
|
44262
45056
|
class XlsxReader {
|
|
44263
45057
|
warningManager;
|
|
44264
45058
|
xmls;
|
|
@@ -44736,6 +45530,30 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44736
45530
|
return data;
|
|
44737
45531
|
},
|
|
44738
45532
|
},
|
|
45533
|
+
{
|
|
45534
|
+
description: "transform chart data structure (2)",
|
|
45535
|
+
from: 16,
|
|
45536
|
+
to: 17,
|
|
45537
|
+
applyMigration(data) {
|
|
45538
|
+
for (const sheet of data.sheets || []) {
|
|
45539
|
+
for (const f in sheet.figures || []) {
|
|
45540
|
+
const figure = sheet.figures[f];
|
|
45541
|
+
if ("title" in figure.data && typeof figure.data.title === "string") {
|
|
45542
|
+
figure.data.title = { text: figure.data.title };
|
|
45543
|
+
}
|
|
45544
|
+
const figureType = figure.data.type;
|
|
45545
|
+
if (!["line", "bar", "pie", "scatter", "waterfall", "combo"].includes(figureType)) {
|
|
45546
|
+
continue;
|
|
45547
|
+
}
|
|
45548
|
+
const { dataSets, ...newData } = sheet.figures[f].data;
|
|
45549
|
+
const newDataSets = dataSets.map((dataRange) => ({ dataRange }));
|
|
45550
|
+
newData.dataSets = newDataSets;
|
|
45551
|
+
sheet.figures[f].data = newData;
|
|
45552
|
+
}
|
|
45553
|
+
}
|
|
45554
|
+
return data;
|
|
45555
|
+
},
|
|
45556
|
+
},
|
|
44739
45557
|
];
|
|
44740
45558
|
/**
|
|
44741
45559
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -48347,6 +49165,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48347
49165
|
if (range.invalidXc) {
|
|
48348
49166
|
return range.invalidXc;
|
|
48349
49167
|
}
|
|
49168
|
+
if (!this.getters.tryGetSheet(range.sheetId)) {
|
|
49169
|
+
return CellErrorType.InvalidReference;
|
|
49170
|
+
}
|
|
48350
49171
|
if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
|
|
48351
49172
|
return CellErrorType.InvalidReference;
|
|
48352
49173
|
}
|
|
@@ -51765,7 +52586,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51765
52586
|
*
|
|
51766
52587
|
*/
|
|
51767
52588
|
class SpreadingRelation {
|
|
51768
|
-
createEmptyPositionSet;
|
|
51769
52589
|
/**
|
|
51770
52590
|
* Internal structure:
|
|
51771
52591
|
* For something like
|
|
@@ -51796,9 +52616,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51796
52616
|
*/
|
|
51797
52617
|
resultsToArrayFormulas = new PositionMap();
|
|
51798
52618
|
arrayFormulasToResults = new PositionMap();
|
|
51799
|
-
constructor(createEmptyPositionSet) {
|
|
51800
|
-
this.createEmptyPositionSet = createEmptyPositionSet;
|
|
51801
|
-
}
|
|
51802
52619
|
getFormulaPositionsSpreadingOn(resultPosition) {
|
|
51803
52620
|
return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
|
|
51804
52621
|
}
|
|
@@ -51817,13 +52634,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51817
52634
|
*/
|
|
51818
52635
|
addRelation({ arrayFormulaPosition, resultPosition, }) {
|
|
51819
52636
|
if (!this.resultsToArrayFormulas.has(resultPosition)) {
|
|
51820
|
-
this.resultsToArrayFormulas.set(resultPosition,
|
|
52637
|
+
this.resultsToArrayFormulas.set(resultPosition, []);
|
|
51821
52638
|
}
|
|
51822
|
-
this.resultsToArrayFormulas.get(resultPosition)?.
|
|
52639
|
+
this.resultsToArrayFormulas.get(resultPosition)?.push(arrayFormulaPosition);
|
|
51823
52640
|
if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
|
|
51824
|
-
this.arrayFormulasToResults.set(arrayFormulaPosition,
|
|
52641
|
+
this.arrayFormulasToResults.set(arrayFormulaPosition, []);
|
|
51825
52642
|
}
|
|
51826
|
-
this.arrayFormulasToResults.get(arrayFormulaPosition)?.
|
|
52643
|
+
this.arrayFormulasToResults.get(arrayFormulaPosition)?.push(resultPosition);
|
|
51827
52644
|
}
|
|
51828
52645
|
hasArrayFormulaResult(position) {
|
|
51829
52646
|
return this.resultsToArrayFormulas.has(position);
|
|
@@ -51844,7 +52661,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51844
52661
|
evaluatedCells = new PositionMap();
|
|
51845
52662
|
formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
|
|
51846
52663
|
blockedArrayFormulas = new PositionSet({});
|
|
51847
|
-
spreadingRelations = new SpreadingRelation(
|
|
52664
|
+
spreadingRelations = new SpreadingRelation();
|
|
51848
52665
|
constructor(context, getters) {
|
|
51849
52666
|
this.context = context;
|
|
51850
52667
|
this.getters = getters;
|
|
@@ -51938,7 +52755,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51938
52755
|
}
|
|
51939
52756
|
buildDependencyGraph() {
|
|
51940
52757
|
this.blockedArrayFormulas = this.createEmptyPositionSet();
|
|
51941
|
-
this.spreadingRelations = new SpreadingRelation(
|
|
52758
|
+
this.spreadingRelations = new SpreadingRelation();
|
|
51942
52759
|
this.formulaDependencies = lazy(() => {
|
|
51943
52760
|
const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position)
|
|
51944
52761
|
.filter((range) => !range.invalidSheetName && !range.invalidXc)
|
|
@@ -52070,6 +52887,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52070
52887
|
const nbColumns = formulaReturn.length;
|
|
52071
52888
|
const nbRows = formulaReturn[0].length;
|
|
52072
52889
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.updateSpreadRelation(formulaPosition));
|
|
52890
|
+
this.assertNoMergedCellsInSpreadZone(formulaPosition, formulaReturn);
|
|
52073
52891
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.checkCollision(formulaPosition));
|
|
52074
52892
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
52075
52893
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
@@ -52092,6 +52910,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52092
52910
|
}
|
|
52093
52911
|
throw new SplillBlockedError(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
|
|
52094
52912
|
}
|
|
52913
|
+
assertNoMergedCellsInSpreadZone({ sheetId, col, row }, matrixResult) {
|
|
52914
|
+
const mergedCells = this.getters.getMergesInZone(sheetId, {
|
|
52915
|
+
top: row,
|
|
52916
|
+
bottom: row + matrixResult.length,
|
|
52917
|
+
left: col,
|
|
52918
|
+
right: col + matrixResult[0].length,
|
|
52919
|
+
});
|
|
52920
|
+
if (mergedCells.length === 0) {
|
|
52921
|
+
return;
|
|
52922
|
+
}
|
|
52923
|
+
throw new SplillBlockedError(_t("Merged cells found in the spill zone. Please unmerge cells before using array formulas."));
|
|
52924
|
+
}
|
|
52095
52925
|
updateSpreadRelation({ sheetId, col, row, }) {
|
|
52096
52926
|
const arrayFormulaPosition = { sheetId, col, row };
|
|
52097
52927
|
return (i, j) => {
|
|
@@ -52329,10 +53159,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52329
53159
|
this.evaluator.updateDependencies(cmd);
|
|
52330
53160
|
}
|
|
52331
53161
|
break;
|
|
52332
|
-
case "DUPLICATE_SHEET":
|
|
52333
|
-
case "CREATE_SHEET":
|
|
52334
|
-
this.shouldRebuildDependenciesGraph = true;
|
|
52335
|
-
break;
|
|
52336
53162
|
case "EVALUATE_CELLS":
|
|
52337
53163
|
this.evaluator.evaluateAllCells();
|
|
52338
53164
|
break;
|
|
@@ -52433,16 +53259,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52433
53259
|
let newContent = undefined;
|
|
52434
53260
|
let newFormat = undefined;
|
|
52435
53261
|
let isExported = true;
|
|
53262
|
+
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
52436
53263
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
52437
53264
|
if (formulaCell) {
|
|
52438
53265
|
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
52439
53266
|
isFormula = isExported;
|
|
52440
53267
|
if (!isExported) {
|
|
52441
|
-
|
|
52442
|
-
|
|
53268
|
+
// If the cell contains a non-exported formula and that is evaluates to
|
|
53269
|
+
// nothing* ,we don't export it.
|
|
53270
|
+
// * non-falsy value are relevant and so are 0 and FALSE, which only leaves
|
|
53271
|
+
// the empty string.
|
|
53272
|
+
if (value !== "") {
|
|
53273
|
+
newContent = (value ?? "").toString();
|
|
53274
|
+
newFormat = evaluatedCell.format;
|
|
53275
|
+
}
|
|
52443
53276
|
}
|
|
52444
53277
|
}
|
|
52445
|
-
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
52446
53278
|
const exportedCellData = exportedSheetData.cells[xc] || {};
|
|
52447
53279
|
const format = newFormat
|
|
52448
53280
|
? getItemId(newFormat, data.formats)
|
|
@@ -57065,7 +57897,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57065
57897
|
paintFormatStatus = "inactive";
|
|
57066
57898
|
originSheetId;
|
|
57067
57899
|
copiedData;
|
|
57068
|
-
_isCutOperation;
|
|
57900
|
+
_isCutOperation = false;
|
|
57069
57901
|
// ---------------------------------------------------------------------------
|
|
57070
57902
|
// Command Handling
|
|
57071
57903
|
// ---------------------------------------------------------------------------
|
|
@@ -57077,14 +57909,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57077
57909
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
57078
57910
|
const copiedData = this.convertOSClipboardData(cmd.text);
|
|
57079
57911
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57080
|
-
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption });
|
|
57912
|
+
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption, isCutOperation: false });
|
|
57081
57913
|
}
|
|
57082
57914
|
case "PASTE": {
|
|
57083
57915
|
if (!this.copiedData) {
|
|
57084
57916
|
return "EmptyClipboard" /* CommandResult.EmptyClipboard */;
|
|
57085
57917
|
}
|
|
57086
57918
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57087
|
-
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
57919
|
+
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
57920
|
+
pasteOption: pasteOption,
|
|
57921
|
+
isCutOperation: this._isCutOperation,
|
|
57922
|
+
});
|
|
57088
57923
|
}
|
|
57089
57924
|
case "COPY_PASTE_CELLS_ABOVE": {
|
|
57090
57925
|
const zones = this.getters.getSelectedZones();
|
|
@@ -57102,13 +57937,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57102
57937
|
}
|
|
57103
57938
|
case "INSERT_CELL": {
|
|
57104
57939
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57105
|
-
const copiedData = this.copy(
|
|
57106
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
57940
|
+
const copiedData = this.copy(cut);
|
|
57941
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
57107
57942
|
}
|
|
57108
57943
|
case "DELETE_CELL": {
|
|
57109
57944
|
const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57110
|
-
const copiedData = this.copy(
|
|
57111
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
57945
|
+
const copiedData = this.copy(cut);
|
|
57946
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
57112
57947
|
}
|
|
57113
57948
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
57114
57949
|
if (this.paintFormatStatus !== "inactive") {
|
|
@@ -57126,23 +57961,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57126
57961
|
const zones = this.getters.getSelectedZones();
|
|
57127
57962
|
this.status = "visible";
|
|
57128
57963
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57129
|
-
this.copiedData = this.copy(
|
|
57964
|
+
this.copiedData = this.copy(zones);
|
|
57965
|
+
this._isCutOperation = cmd.type === "CUT";
|
|
57130
57966
|
break;
|
|
57131
57967
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
57968
|
+
this._isCutOperation = false;
|
|
57132
57969
|
this.copiedData = this.convertOSClipboardData(cmd.text);
|
|
57133
57970
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57134
|
-
this.paste(cmd.target, {
|
|
57971
|
+
this.paste(cmd.target, this.copiedData, {
|
|
57135
57972
|
pasteOption,
|
|
57136
57973
|
selectTarget: true,
|
|
57974
|
+
isCutOperation: false,
|
|
57137
57975
|
});
|
|
57138
57976
|
this.status = "invisible";
|
|
57139
57977
|
break;
|
|
57140
57978
|
}
|
|
57141
57979
|
case "PASTE": {
|
|
57142
57980
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57143
|
-
this.paste(cmd.target, {
|
|
57981
|
+
this.paste(cmd.target, this.copiedData, {
|
|
57144
57982
|
pasteOption,
|
|
57145
57983
|
selectTarget: true,
|
|
57984
|
+
isCutOperation: this._isCutOperation,
|
|
57146
57985
|
});
|
|
57147
57986
|
if (this.paintFormatStatus === "oneOff") {
|
|
57148
57987
|
this.paintFormatStatus = "inactive";
|
|
@@ -57163,9 +58002,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57163
58002
|
top: multipleRowsInSelection ? zone.top : zone.top - 1,
|
|
57164
58003
|
};
|
|
57165
58004
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57166
|
-
|
|
57167
|
-
this.paste([zone], {
|
|
57168
|
-
|
|
58005
|
+
const copiedData = this.copy([copyTarget]);
|
|
58006
|
+
this.paste([zone], copiedData, {
|
|
58007
|
+
isCutOperation: false,
|
|
57169
58008
|
selectTarget: true,
|
|
57170
58009
|
});
|
|
57171
58010
|
}
|
|
@@ -57180,9 +58019,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57180
58019
|
left: multipleColsInSelection ? zone.left : zone.left - 1,
|
|
57181
58020
|
};
|
|
57182
58021
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57183
|
-
|
|
57184
|
-
this.paste([zone], {
|
|
57185
|
-
|
|
58022
|
+
const copiedData = this.copy([copyTarget]);
|
|
58023
|
+
this.paste([zone], copiedData, {
|
|
58024
|
+
isCutOperation: false,
|
|
57186
58025
|
selectTarget: true,
|
|
57187
58026
|
});
|
|
57188
58027
|
}
|
|
@@ -57198,14 +58037,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57198
58037
|
}
|
|
57199
58038
|
break;
|
|
57200
58039
|
}
|
|
57201
|
-
|
|
57202
|
-
this.paste(paste, {});
|
|
58040
|
+
const copiedData = this.copy(cut);
|
|
58041
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
57203
58042
|
break;
|
|
57204
58043
|
}
|
|
57205
58044
|
case "INSERT_CELL": {
|
|
57206
58045
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57207
|
-
|
|
57208
|
-
this.paste(paste, {});
|
|
58046
|
+
const copiedData = this.copy(cut);
|
|
58047
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
57209
58048
|
break;
|
|
57210
58049
|
}
|
|
57211
58050
|
case "ADD_COLUMNS_ROWS": {
|
|
@@ -57237,7 +58076,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57237
58076
|
break;
|
|
57238
58077
|
}
|
|
57239
58078
|
case "REPEAT_PASTE": {
|
|
57240
|
-
this.paste(cmd.target, {
|
|
58079
|
+
this.paste(cmd.target, this.copiedData, {
|
|
58080
|
+
isCutOperation: false,
|
|
57241
58081
|
pasteOption: cmd.pasteOption,
|
|
57242
58082
|
selectTarget: true,
|
|
57243
58083
|
});
|
|
@@ -57245,7 +58085,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57245
58085
|
}
|
|
57246
58086
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
57247
58087
|
const zones = this.getters.getSelectedZones();
|
|
57248
|
-
this.copiedData = this.copy(
|
|
58088
|
+
this.copiedData = this.copy(zones);
|
|
57249
58089
|
this.status = "visible";
|
|
57250
58090
|
if (cmd.persistent) {
|
|
57251
58091
|
this.paintFormatStatus = "persistent";
|
|
@@ -57276,7 +58116,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57276
58116
|
}
|
|
57277
58117
|
}
|
|
57278
58118
|
convertOSClipboardData(clipboardData) {
|
|
57279
|
-
this._isCutOperation = false;
|
|
57280
58119
|
const handlers = clipboardHandlersRegistries.figureHandlers
|
|
57281
58120
|
.getAll()
|
|
57282
58121
|
.map((handler) => new handler(this.getters, this.dispatch));
|
|
@@ -57314,7 +58153,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57314
58153
|
for (const handler of this.selectClipboardHandlers(copiedData)) {
|
|
57315
58154
|
const result = handler.isPasteAllowed(this.getters.getActiveSheetId(), target, copiedData, {
|
|
57316
58155
|
...options,
|
|
57317
|
-
isCutOperation: this.isCutOperation(),
|
|
57318
58156
|
});
|
|
57319
58157
|
if (result !== "Success" /* CommandResult.Success */) {
|
|
57320
58158
|
return result;
|
|
@@ -57337,9 +58175,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57337
58175
|
}
|
|
57338
58176
|
return false;
|
|
57339
58177
|
}
|
|
57340
|
-
copy(
|
|
58178
|
+
copy(zones) {
|
|
57341
58179
|
let copiedData = {};
|
|
57342
|
-
this._isCutOperation = operation === "CUT";
|
|
57343
58180
|
const clipboardData = this.getClipboardData(zones);
|
|
57344
58181
|
for (const handler of this.selectClipboardHandlers(clipboardData)) {
|
|
57345
58182
|
const data = handler.copy(clipboardData);
|
|
@@ -57347,8 +58184,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57347
58184
|
}
|
|
57348
58185
|
return copiedData;
|
|
57349
58186
|
}
|
|
57350
|
-
paste(zones, options) {
|
|
57351
|
-
if (!
|
|
58187
|
+
paste(zones, copiedData, options) {
|
|
58188
|
+
if (!copiedData) {
|
|
57352
58189
|
return;
|
|
57353
58190
|
}
|
|
57354
58191
|
let zone = undefined;
|
|
@@ -57356,12 +58193,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57356
58193
|
let target = {
|
|
57357
58194
|
zones,
|
|
57358
58195
|
};
|
|
57359
|
-
const handlers = this.selectClipboardHandlers(
|
|
58196
|
+
const handlers = this.selectClipboardHandlers(copiedData);
|
|
57360
58197
|
for (const handler of handlers) {
|
|
57361
|
-
const currentTarget = handler.getPasteTarget(zones,
|
|
57362
|
-
...options,
|
|
57363
|
-
isCutOperation: this.isCutOperation(),
|
|
57364
|
-
});
|
|
58198
|
+
const currentTarget = handler.getPasteTarget(zones, copiedData, options);
|
|
57365
58199
|
if (currentTarget.figureId) {
|
|
57366
58200
|
target.figureId = currentTarget.figureId;
|
|
57367
58201
|
}
|
|
@@ -57377,7 +58211,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57377
58211
|
if (zone !== undefined) {
|
|
57378
58212
|
this.addMissingDimensions(this.getters.getActiveSheetId(), zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
|
|
57379
58213
|
}
|
|
57380
|
-
handlers.forEach((handler) => handler.paste(target,
|
|
58214
|
+
handlers.forEach((handler) => handler.paste(target, copiedData, options));
|
|
57381
58215
|
if (!options?.selectTarget) {
|
|
57382
58216
|
return;
|
|
57383
58217
|
}
|
|
@@ -59763,6 +60597,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59763
60597
|
sheetDivRef = owl.useRef("sheetDiv");
|
|
59764
60598
|
sheetNameRef = owl.useRef("sheetNameSpan");
|
|
59765
60599
|
editionState = "initializing";
|
|
60600
|
+
DOMFocusableElementStore;
|
|
59766
60601
|
setup() {
|
|
59767
60602
|
owl.onMounted(() => {
|
|
59768
60603
|
if (this.isSheetActive) {
|
|
@@ -59775,6 +60610,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59775
60610
|
this.focusInputAndSelectContent();
|
|
59776
60611
|
}
|
|
59777
60612
|
});
|
|
60613
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
59778
60614
|
}
|
|
59779
60615
|
focusInputAndSelectContent() {
|
|
59780
60616
|
if (!this.state.isEditing || !this.sheetNameRef.el)
|
|
@@ -59816,9 +60652,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59816
60652
|
if (ev.key === "Enter") {
|
|
59817
60653
|
ev.preventDefault();
|
|
59818
60654
|
this.stopEdition();
|
|
60655
|
+
this.DOMFocusableElementStore.focus();
|
|
59819
60656
|
}
|
|
59820
60657
|
if (ev.key === "Escape") {
|
|
59821
60658
|
this.cancelEdition();
|
|
60659
|
+
this.DOMFocusableElementStore.focus();
|
|
59822
60660
|
}
|
|
59823
60661
|
}
|
|
59824
60662
|
onClickSheetName(ev) {
|
|
@@ -61867,6 +62705,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61867
62705
|
static template = "o-spreadsheet-Spreadsheet";
|
|
61868
62706
|
static props = {
|
|
61869
62707
|
model: Object,
|
|
62708
|
+
notifyUser: { type: Function, optional: true },
|
|
62709
|
+
raiseError: { type: Function, optional: true },
|
|
62710
|
+
askConfirmation: { type: Function, optional: true },
|
|
61870
62711
|
};
|
|
61871
62712
|
static components = {
|
|
61872
62713
|
TopBar,
|
|
@@ -61913,7 +62754,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61913
62754
|
toggleSidePanel: this.sidePanel.toggle.bind(this.sidePanel),
|
|
61914
62755
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
61915
62756
|
startCellEdition: (content) => this.composerFocusStore.focusGridComposerCell(content),
|
|
62757
|
+
notifyUser: (notification) => this.notificationStore.notifyUser(notification),
|
|
62758
|
+
askConfirmation: (text, confirm, cancel) => this.notificationStore.askConfirmation(text, confirm, cancel),
|
|
62759
|
+
raiseError: (text, cb) => this.notificationStore.raiseError(text, cb),
|
|
61916
62760
|
});
|
|
62761
|
+
this.notificationStore.updateNotificationCallbacks({ ...this.props });
|
|
61917
62762
|
owl.useEffect(() => {
|
|
61918
62763
|
/**
|
|
61919
62764
|
* Only refocus the grid if the active element is not a child of the spreadsheet
|
|
@@ -61936,6 +62781,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61936
62781
|
if (nextProps.model !== this.props.model) {
|
|
61937
62782
|
throw new Error("Changing the props model is not supported at the moment.");
|
|
61938
62783
|
}
|
|
62784
|
+
if (!deepEquals(nextProps, this.props)) {
|
|
62785
|
+
this.notificationStore.updateNotificationCallbacks({ ...nextProps });
|
|
62786
|
+
}
|
|
61939
62787
|
});
|
|
61940
62788
|
const render = batched(this.render.bind(this, true));
|
|
61941
62789
|
owl.onMounted(() => {
|
|
@@ -61953,7 +62801,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61953
62801
|
bindModelEvents() {
|
|
61954
62802
|
this.model.on("update", this, () => this.render(true));
|
|
61955
62803
|
this.model.on("notify-ui", this, (notification) => this.notificationStore.notifyUser(notification));
|
|
61956
|
-
this.model.on("raise-error-ui", this, ({ text }) => this.
|
|
62804
|
+
this.model.on("raise-error-ui", this, ({ text }) => this.notificationStore.raiseError(text));
|
|
61957
62805
|
}
|
|
61958
62806
|
unbindModelEvents() {
|
|
61959
62807
|
this.model.off("update", this);
|
|
@@ -63508,10 +64356,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63508
64356
|
});
|
|
63509
64357
|
// <manualLayout/> to manually position the chart in the figure container
|
|
63510
64358
|
let title = escapeXml ``;
|
|
63511
|
-
if (chart.data.title) {
|
|
64359
|
+
if (chart.data.title?.text) {
|
|
64360
|
+
const color = chart.data.title.color
|
|
64361
|
+
? toXlsxHexColor(chart.data.title.color)
|
|
64362
|
+
: chart.data.fontColor;
|
|
63512
64363
|
title = escapeXml /*xml*/ `
|
|
63513
64364
|
<c:title>
|
|
63514
|
-
${insertText(chart.data.title, chart.data.
|
|
64365
|
+
${insertText(chart.data.title.text, color, DEFAULT_CHART_FONT_SIZE, chart.data.title)}
|
|
63515
64366
|
<c:overlay val="0" />
|
|
63516
64367
|
</c:title>
|
|
63517
64368
|
`;
|
|
@@ -63599,7 +64450,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63599
64450
|
</a:ln>
|
|
63600
64451
|
`;
|
|
63601
64452
|
}
|
|
63602
|
-
function insertText(text, fontColor = "000000", fontsize =
|
|
64453
|
+
function insertText(text, fontColor = "000000", fontsize = DEFAULT_CHART_FONT_SIZE, style = {}) {
|
|
63603
64454
|
return escapeXml /*xml*/ `
|
|
63604
64455
|
<c:tx>
|
|
63605
64456
|
<c:rich>
|
|
@@ -63607,13 +64458,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63607
64458
|
<a:lstStyle />
|
|
63608
64459
|
<a:p>
|
|
63609
64460
|
<a:pPr lvl="0">
|
|
63610
|
-
<a:defRPr b="0">
|
|
64461
|
+
<a:defRPr b="${style?.bold ? 1 : 0}" i="${style?.italic ? 1 : 0}">
|
|
63611
64462
|
${solidFill(fontColor)}
|
|
63612
64463
|
<a:latin typeface="+mn-lt"/>
|
|
63613
64464
|
</a:defRPr>
|
|
63614
64465
|
</a:pPr>
|
|
63615
64466
|
<a:r> <!-- Runs -->
|
|
63616
|
-
<a:rPr sz="${fontsize * 100}"/>
|
|
64467
|
+
<a:rPr b="${style?.bold ? 1 : 0}" i="${style?.italic ? 1 : 0}" sz="${fontsize * 100}"/>
|
|
63617
64468
|
<a:t>${text}</a:t>
|
|
63618
64469
|
</a:r>
|
|
63619
64470
|
</a:p>
|
|
@@ -63642,6 +64493,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63642
64493
|
</c:txPr>
|
|
63643
64494
|
`;
|
|
63644
64495
|
}
|
|
64496
|
+
function extractDataSetLabel(label) {
|
|
64497
|
+
if (!label) {
|
|
64498
|
+
return escapeXml /*xml*/ ``;
|
|
64499
|
+
}
|
|
64500
|
+
if ("text" in label && label.text) {
|
|
64501
|
+
return escapeXml /*xml*/ `
|
|
64502
|
+
<c:tx><c:v>${label.text}</c:v></c:tx>
|
|
64503
|
+
`;
|
|
64504
|
+
}
|
|
64505
|
+
if ("reference" in label && label.reference) {
|
|
64506
|
+
return escapeXml /*xml*/ `
|
|
64507
|
+
<c:tx>
|
|
64508
|
+
${stringRef(label.reference)}
|
|
64509
|
+
</c:tx>
|
|
64510
|
+
`;
|
|
64511
|
+
}
|
|
64512
|
+
return escapeXml /*xml*/ ``;
|
|
64513
|
+
}
|
|
63645
64514
|
function addBarChart(chart) {
|
|
63646
64515
|
// gapWitdh and overlap that define the space between clusters (in %) and the overlap between datasets (from -100: completely scattered to 100, completely overlapped)
|
|
63647
64516
|
// see gapWidth : https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_gapWidth_topic_ID0EFVEQB.html#topic_ID0EFVEQB
|
|
@@ -63649,46 +64518,72 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63649
64518
|
//
|
|
63650
64519
|
// overlap and gapWitdh seems to be by default at -20 and 20 in chart.js.
|
|
63651
64520
|
// See https://www.chartjs.org/docs/latest/charts/bar.html and https://www.chartjs.org/docs/latest/charts/bar.html#barpercentage-vs-categorypercentage
|
|
63652
|
-
const
|
|
63653
|
-
const
|
|
64521
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64522
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64523
|
+
const leftDataSetsNodes = [];
|
|
64524
|
+
const rightDataSetsNodes = [];
|
|
63654
64525
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
63655
64526
|
const color = toXlsxHexColor(colors.next());
|
|
63656
64527
|
const dataShapeProperty = shapeProperty({
|
|
63657
64528
|
backgroundColor: color,
|
|
63658
64529
|
line: { color },
|
|
63659
64530
|
});
|
|
63660
|
-
|
|
64531
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63661
64532
|
<c:ser>
|
|
63662
64533
|
<c:idx val="${dsIndex}"/>
|
|
63663
64534
|
<c:order val="${dsIndex}"/>
|
|
63664
|
-
${
|
|
64535
|
+
${extractDataSetLabel(dataset.label)}
|
|
63665
64536
|
${dataShapeProperty}
|
|
63666
64537
|
${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
63667
64538
|
<c:val> <!-- x-coordinate values -->
|
|
63668
64539
|
${numberRef(dataset.range)}
|
|
63669
64540
|
</c:val>
|
|
63670
64541
|
</c:ser>
|
|
63671
|
-
|
|
64542
|
+
`;
|
|
64543
|
+
if (dataset.rightYAxis) {
|
|
64544
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64545
|
+
}
|
|
64546
|
+
else {
|
|
64547
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64548
|
+
}
|
|
63672
64549
|
}
|
|
63673
|
-
// Excel does not support this feature
|
|
63674
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63675
64550
|
const grouping = chart.stacked ? "stacked" : "clustered";
|
|
63676
64551
|
const overlap = chart.stacked ? 100 : -20;
|
|
63677
64552
|
return escapeXml /*xml*/ `
|
|
63678
|
-
|
|
63679
|
-
|
|
63680
|
-
|
|
63681
|
-
|
|
63682
|
-
|
|
63683
|
-
|
|
63684
|
-
|
|
63685
|
-
|
|
63686
|
-
|
|
63687
|
-
|
|
63688
|
-
|
|
63689
|
-
|
|
63690
|
-
|
|
63691
|
-
|
|
64553
|
+
${leftDataSetsNodes.length
|
|
64554
|
+
? escapeXml /*xml*/ `
|
|
64555
|
+
<c:barChart>
|
|
64556
|
+
<c:barDir val="col"/>
|
|
64557
|
+
<c:grouping val="${grouping}"/>
|
|
64558
|
+
<c:overlap val="${overlap}"/>
|
|
64559
|
+
<c:gapWidth val="70"/>
|
|
64560
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64561
|
+
<c:varyColors val="0"/>
|
|
64562
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64563
|
+
<c:axId val="${catAxId}" />
|
|
64564
|
+
<c:axId val="${valAxId}" />
|
|
64565
|
+
</c:barChart>
|
|
64566
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64567
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64568
|
+
`
|
|
64569
|
+
: ""}
|
|
64570
|
+
${rightDataSetsNodes.length
|
|
64571
|
+
? escapeXml /*xml*/ `
|
|
64572
|
+
<c:barChart>
|
|
64573
|
+
<c:barDir val="col"/>
|
|
64574
|
+
<c:grouping val="${grouping}"/>
|
|
64575
|
+
<c:overlap val="${overlap}"/>
|
|
64576
|
+
<c:gapWidth val="70"/>
|
|
64577
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64578
|
+
<c:varyColors val="0"/>
|
|
64579
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64580
|
+
<c:axId val="${catAxId + 1}" />
|
|
64581
|
+
<c:axId val="${valAxId + 1}" />
|
|
64582
|
+
</c:barChart>
|
|
64583
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64584
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64585
|
+
`
|
|
64586
|
+
: ""}`;
|
|
63692
64587
|
}
|
|
63693
64588
|
function addComboChart(chart) {
|
|
63694
64589
|
// gapWitdh and overlap that define the space between clusters (in %) and the overlap between datasets (from -100: completely scattered to 100, completely overlapped)
|
|
@@ -63697,28 +64592,38 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63697
64592
|
//
|
|
63698
64593
|
// overlap and gapWitdh seems to be by default at -20 and 20 in chart.js.
|
|
63699
64594
|
// See https://www.chartjs.org/docs/latest/charts/bar.html and https://www.chartjs.org/docs/latest/charts/bar.html#barpercentage-vs-categorypercentage
|
|
63700
|
-
const
|
|
63701
|
-
const
|
|
63702
|
-
|
|
64595
|
+
const dataSets = chart.dataSets;
|
|
64596
|
+
const dataSetsColors = dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64597
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64598
|
+
let dataSet = dataSets[0];
|
|
64599
|
+
const firstColor = toXlsxHexColor(colors.next());
|
|
64600
|
+
const useRightAxisForBarSerie = dataSet.rightYAxis ?? false;
|
|
64601
|
+
const barDataSetNode = escapeXml /*xml*/ `
|
|
64602
|
+
<c:ser>
|
|
64603
|
+
<c:idx val="0"/>
|
|
64604
|
+
<c:order val="0"/>
|
|
64605
|
+
${extractDataSetLabel(dataSet.label)}
|
|
64606
|
+
${shapeProperty({
|
|
64607
|
+
backgroundColor: firstColor,
|
|
64608
|
+
line: { color: firstColor },
|
|
64609
|
+
})}
|
|
64610
|
+
${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
64611
|
+
<!-- x-coordinate values -->
|
|
64612
|
+
<c:val>
|
|
64613
|
+
${numberRef(dataSet.range)}
|
|
64614
|
+
</c:val>
|
|
64615
|
+
</c:ser>
|
|
64616
|
+
`;
|
|
64617
|
+
const leftDataSetsNodes = [];
|
|
64618
|
+
const rightDataSetsNodes = [];
|
|
64619
|
+
for (let dsIndex = 1; dsIndex < dataSets.length; dsIndex++) {
|
|
64620
|
+
dataSet = dataSets[dsIndex];
|
|
63703
64621
|
const color = toXlsxHexColor(colors.next());
|
|
63704
64622
|
const dataShapeProperty = shapeProperty({
|
|
63705
64623
|
backgroundColor: color,
|
|
63706
64624
|
line: { color },
|
|
63707
64625
|
});
|
|
63708
|
-
|
|
63709
|
-
? escapeXml /*xml*/ `
|
|
63710
|
-
<c:ser>
|
|
63711
|
-
<c:idx val="${dsIndex}"/>
|
|
63712
|
-
<c:order val="${dsIndex}"/>
|
|
63713
|
-
${dataset.label ? escapeXml /*xml*/ `<c:tx>${stringRef(dataset.label)}</c:tx>` : ""}
|
|
63714
|
-
${dataShapeProperty}
|
|
63715
|
-
${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
63716
|
-
<c:val> <!-- x-coordinate values -->
|
|
63717
|
-
${numberRef(dataset.range)}
|
|
63718
|
-
</c:val>
|
|
63719
|
-
</c:ser>
|
|
63720
|
-
`
|
|
63721
|
-
: escapeXml /*xml*/ `
|
|
64626
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63722
64627
|
<c:ser>
|
|
63723
64628
|
<c:idx val="${dsIndex}"/>
|
|
63724
64629
|
<c:order val="${dsIndex}"/>
|
|
@@ -63726,18 +64631,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63726
64631
|
<c:marker>
|
|
63727
64632
|
<c:symbol val="circle" />
|
|
63728
64633
|
<c:size val="5"/>
|
|
64634
|
+
${dataShapeProperty}
|
|
63729
64635
|
</c:marker>
|
|
63730
|
-
${
|
|
64636
|
+
${extractDataSetLabel(dataSet.label)}
|
|
63731
64637
|
${dataShapeProperty}
|
|
63732
|
-
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
63733
|
-
|
|
63734
|
-
|
|
64638
|
+
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
64639
|
+
<!-- x-coordinate values -->
|
|
64640
|
+
<c:val>
|
|
64641
|
+
${numberRef(dataSet.range)}
|
|
63735
64642
|
</c:val>
|
|
63736
64643
|
</c:ser>
|
|
63737
|
-
|
|
64644
|
+
`;
|
|
64645
|
+
if (dataSet.rightYAxis) {
|
|
64646
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64647
|
+
}
|
|
64648
|
+
else {
|
|
64649
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64650
|
+
}
|
|
63738
64651
|
}
|
|
63739
|
-
// Excel does not support this feature
|
|
63740
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63741
64652
|
const overlap = chart.stacked ? 100 : -20;
|
|
63742
64653
|
return escapeXml /*xml*/ `
|
|
63743
64654
|
<c:barChart>
|
|
@@ -63747,34 +64658,63 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63747
64658
|
<c:gapWidth val="70"/>
|
|
63748
64659
|
<!-- each data marker in the series does not have a different color -->
|
|
63749
64660
|
<c:varyColors val="0"/>
|
|
63750
|
-
${
|
|
63751
|
-
<c:axId val="${catAxId}" />
|
|
63752
|
-
<c:axId val="${valAxId}" />
|
|
64661
|
+
${barDataSetNode}
|
|
64662
|
+
<c:axId val="${catAxId + (useRightAxisForBarSerie ? 1 : 0)}" />
|
|
64663
|
+
<c:axId val="${valAxId + (useRightAxisForBarSerie ? 1 : 0)}" />
|
|
63753
64664
|
</c:barChart>
|
|
63754
|
-
|
|
63755
|
-
|
|
63756
|
-
|
|
63757
|
-
|
|
63758
|
-
|
|
63759
|
-
|
|
63760
|
-
|
|
63761
|
-
|
|
63762
|
-
|
|
63763
|
-
|
|
64665
|
+
${leftDataSetsNodes.length
|
|
64666
|
+
? escapeXml /*xml*/ `
|
|
64667
|
+
<c:lineChart>
|
|
64668
|
+
<c:grouping val="standard"/>
|
|
64669
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64670
|
+
<c:varyColors val="0"/>
|
|
64671
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64672
|
+
<c:axId val="${catAxId}" />
|
|
64673
|
+
<c:axId val="${valAxId}" />
|
|
64674
|
+
</c:lineChart>
|
|
64675
|
+
`
|
|
64676
|
+
: ""}
|
|
64677
|
+
${rightDataSetsNodes.length
|
|
64678
|
+
? escapeXml /*xml*/ `
|
|
64679
|
+
<c:lineChart>
|
|
64680
|
+
<c:grouping val="standard"/>
|
|
64681
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64682
|
+
<c:varyColors val="0"/>
|
|
64683
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64684
|
+
<c:axId val="${catAxId + 1}" />
|
|
64685
|
+
<c:axId val="${valAxId + 1}" />
|
|
64686
|
+
</c:lineChart>
|
|
64687
|
+
`
|
|
64688
|
+
: ""}
|
|
64689
|
+
${!useRightAxisForBarSerie || leftDataSetsNodes.length
|
|
64690
|
+
? escapeXml /*xml*/ `
|
|
64691
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64692
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64693
|
+
`
|
|
64694
|
+
: ""}
|
|
64695
|
+
${useRightAxisForBarSerie || rightDataSetsNodes.length
|
|
64696
|
+
? escapeXml /*xml*/ `
|
|
64697
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length || !useRightAxisForBarSerie ? 1 : 0)}
|
|
64698
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64699
|
+
`
|
|
64700
|
+
: ""}
|
|
63764
64701
|
`;
|
|
63765
64702
|
}
|
|
63766
64703
|
function addLineChart(chart) {
|
|
63767
|
-
const
|
|
63768
|
-
const
|
|
64704
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64705
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64706
|
+
const leftDataSetsNodes = [];
|
|
64707
|
+
const rightDataSetsNodes = [];
|
|
63769
64708
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
64709
|
+
const color = toXlsxHexColor(colors.next());
|
|
63770
64710
|
const dataShapeProperty = shapeProperty({
|
|
63771
64711
|
line: {
|
|
63772
64712
|
width: 2.5,
|
|
63773
64713
|
style: "solid",
|
|
63774
|
-
color
|
|
64714
|
+
color,
|
|
63775
64715
|
},
|
|
63776
64716
|
});
|
|
63777
|
-
|
|
64717
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63778
64718
|
<c:ser>
|
|
63779
64719
|
<c:idx val="${dsIndex}"/>
|
|
63780
64720
|
<c:order val="${dsIndex}"/>
|
|
@@ -63782,37 +64722,63 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63782
64722
|
<c:marker>
|
|
63783
64723
|
<c:symbol val="circle" />
|
|
63784
64724
|
<c:size val="5"/>
|
|
64725
|
+
${shapeProperty({ backgroundColor: color, line: { color } })}
|
|
63785
64726
|
</c:marker>
|
|
63786
|
-
${
|
|
64727
|
+
${extractDataSetLabel(dataset.label)}
|
|
63787
64728
|
${dataShapeProperty}
|
|
63788
64729
|
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
63789
64730
|
<c:val> <!-- x-coordinate values -->
|
|
63790
64731
|
${numberRef(dataset.range)}
|
|
63791
64732
|
</c:val>
|
|
63792
64733
|
</c:ser>
|
|
63793
|
-
|
|
64734
|
+
`;
|
|
64735
|
+
if (dataset.rightYAxis) {
|
|
64736
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64737
|
+
}
|
|
64738
|
+
else {
|
|
64739
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64740
|
+
}
|
|
63794
64741
|
}
|
|
63795
|
-
// Excel does not support this feature
|
|
63796
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63797
64742
|
const grouping = chart.stacked ? "stacked" : "standard";
|
|
63798
64743
|
return escapeXml /*xml*/ `
|
|
63799
|
-
|
|
63800
|
-
|
|
63801
|
-
|
|
63802
|
-
|
|
63803
|
-
|
|
63804
|
-
|
|
63805
|
-
|
|
63806
|
-
|
|
63807
|
-
|
|
63808
|
-
|
|
64744
|
+
${leftDataSetsNodes.length
|
|
64745
|
+
? escapeXml /*xml*/ `
|
|
64746
|
+
<c:lineChart>
|
|
64747
|
+
<c:grouping val="${grouping}"/>
|
|
64748
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64749
|
+
<c:varyColors val="0"/>
|
|
64750
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64751
|
+
<c:axId val="${catAxId}" />
|
|
64752
|
+
<c:axId val="${valAxId}" />
|
|
64753
|
+
</c:lineChart>
|
|
64754
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64755
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64756
|
+
`
|
|
64757
|
+
: ""}
|
|
64758
|
+
${rightDataSetsNodes.length
|
|
64759
|
+
? escapeXml /*xml*/ `
|
|
64760
|
+
<c:lineChart>
|
|
64761
|
+
<c:grouping val="${grouping}"/>
|
|
64762
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64763
|
+
<c:varyColors val="0"/>
|
|
64764
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64765
|
+
<c:axId val="${catAxId + 1}" />
|
|
64766
|
+
<c:axId val="${valAxId + 1}" />
|
|
64767
|
+
</c:lineChart>
|
|
64768
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64769
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64770
|
+
`
|
|
64771
|
+
: ""}
|
|
63809
64772
|
`;
|
|
63810
64773
|
}
|
|
63811
64774
|
function addScatterChart(chart) {
|
|
63812
|
-
const
|
|
63813
|
-
const
|
|
64775
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64776
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64777
|
+
const leftDataSetsNodes = [];
|
|
64778
|
+
const rightDataSetsNodes = [];
|
|
63814
64779
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
63815
|
-
|
|
64780
|
+
const color = toXlsxHexColor(colors.next());
|
|
64781
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63816
64782
|
<c:ser>
|
|
63817
64783
|
<c:idx val="${dsIndex}"/>
|
|
63818
64784
|
<c:order val="${dsIndex}"/>
|
|
@@ -63827,8 +64793,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63827
64793
|
<c:marker>
|
|
63828
64794
|
<c:symbol val="circle" />
|
|
63829
64795
|
<c:size val="5"/>
|
|
63830
|
-
${shapeProperty({ backgroundColor:
|
|
64796
|
+
${shapeProperty({ backgroundColor: color, line: { color } })}
|
|
63831
64797
|
</c:marker>
|
|
64798
|
+
${extractDataSetLabel(dataset.label)}
|
|
63832
64799
|
${chart.labelRange
|
|
63833
64800
|
? escapeXml /*xml*/ `<c:xVal> <!-- x-coordinate values -->
|
|
63834
64801
|
${numberRef(chart.labelRange)}
|
|
@@ -63838,24 +64805,46 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63838
64805
|
${numberRef(dataset.range)}
|
|
63839
64806
|
</c:yVal>
|
|
63840
64807
|
</c:ser>
|
|
63841
|
-
|
|
64808
|
+
`;
|
|
64809
|
+
if (dataset.rightYAxis) {
|
|
64810
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64811
|
+
}
|
|
64812
|
+
else {
|
|
64813
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64814
|
+
}
|
|
63842
64815
|
}
|
|
63843
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63844
64816
|
return escapeXml /*xml*/ `
|
|
63845
|
-
|
|
63846
|
-
|
|
63847
|
-
<c:
|
|
63848
|
-
|
|
63849
|
-
|
|
63850
|
-
|
|
63851
|
-
|
|
63852
|
-
|
|
63853
|
-
|
|
63854
|
-
|
|
63855
|
-
|
|
64817
|
+
${leftDataSetsNodes.length
|
|
64818
|
+
? escapeXml /*xml*/ `
|
|
64819
|
+
<c:scatterChart>
|
|
64820
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64821
|
+
<c:varyColors val="0"/>
|
|
64822
|
+
<c:scatterStyle val="lineMarker"/>
|
|
64823
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64824
|
+
<c:axId val="${catAxId}" />
|
|
64825
|
+
<c:axId val="${valAxId}" />
|
|
64826
|
+
</c:scatterChart>
|
|
64827
|
+
${addAx("b", "c:valAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64828
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64829
|
+
`
|
|
64830
|
+
: ""}
|
|
64831
|
+
${rightDataSetsNodes.length
|
|
64832
|
+
? escapeXml /*xml*/ `
|
|
64833
|
+
<c:scatterChart>
|
|
64834
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64835
|
+
<c:varyColors val="0"/>
|
|
64836
|
+
<c:scatterStyle val="lineMarker"/>
|
|
64837
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64838
|
+
<c:axId val="${catAxId + 1}" />
|
|
64839
|
+
<c:axId val="${valAxId + 1}" />
|
|
64840
|
+
</c:scatterChart>
|
|
64841
|
+
${addAx("b", "c:valAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64842
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64843
|
+
`
|
|
64844
|
+
: ""}`;
|
|
63856
64845
|
}
|
|
63857
64846
|
function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
|
|
63858
|
-
const colors = new
|
|
64847
|
+
const colors = new ColorGenerator();
|
|
63859
64848
|
const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
|
|
63860
64849
|
const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
|
|
63861
64850
|
const dataSetsNodes = [];
|
|
@@ -63879,7 +64868,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63879
64868
|
<c:ser>
|
|
63880
64869
|
<c:idx val="${dsIndex}"/>
|
|
63881
64870
|
<c:order val="${dsIndex}"/>
|
|
63882
|
-
${
|
|
64871
|
+
${extractDataSetLabel(dataset.label)}
|
|
63883
64872
|
${joinXmlNodes(dataPoints)}
|
|
63884
64873
|
${insertDataLabels({ showLeaderLines: true })}
|
|
63885
64874
|
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
@@ -63911,14 +64900,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63911
64900
|
</dLbls>
|
|
63912
64901
|
`;
|
|
63913
64902
|
}
|
|
63914
|
-
function addAx(position, axisName, axId, crossAxId,
|
|
64903
|
+
function addAx(position, axisName, axId, crossAxId, title, defaultFontColor, deleteAxis = 0) {
|
|
63915
64904
|
// Each Axis present inside a graph needs to be identified by an unsigned integer in order to be referenced by its crossAxis.
|
|
63916
64905
|
// I.e. x-axis, will reference y-axis and vice-versa.
|
|
64906
|
+
const color = title?.color ? toXlsxHexColor(title.color) : defaultFontColor;
|
|
63917
64907
|
return escapeXml /*xml*/ `
|
|
63918
64908
|
<${axisName}>
|
|
63919
64909
|
<c:axId val="${axId}"/>
|
|
63920
64910
|
<c:crossAx val="${crossAxId}"/> <!-- reference to the other axe of the chart -->
|
|
63921
|
-
<c:
|
|
64911
|
+
<c:crosses val="${position === "b" || position === "l" ? "min" : "max"}"/>
|
|
64912
|
+
<c:delete val="${deleteAxis}"/> <!-- by default, axis are not displayed -->
|
|
63922
64913
|
<c:scaling>
|
|
63923
64914
|
<c:orientation val="minMax" />
|
|
63924
64915
|
</c:scaling>
|
|
@@ -63928,9 +64919,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63928
64919
|
<c:minorTickMark val="none" />
|
|
63929
64920
|
<c:numFmt formatCode="General" sourceLinked="1" />
|
|
63930
64921
|
<c:title>
|
|
63931
|
-
${insertText("")}
|
|
64922
|
+
${insertText(title?.text ?? "", color, 10, title)}
|
|
63932
64923
|
</c:title>
|
|
63933
|
-
${insertTextProperties(10,
|
|
64924
|
+
${insertTextProperties(10, defaultFontColor)}
|
|
63934
64925
|
</${axisName}>
|
|
63935
64926
|
<!-- <tickLblPos/> omitted -->
|
|
63936
64927
|
`;
|
|
@@ -64811,7 +65802,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64811
65802
|
let cellNode = escapeXml ``;
|
|
64812
65803
|
// Either formula or static value inside the cell
|
|
64813
65804
|
if (cell.isFormula) {
|
|
64814
|
-
|
|
65805
|
+
const res = addFormula(cell);
|
|
65806
|
+
if (!res) {
|
|
65807
|
+
continue;
|
|
65808
|
+
}
|
|
65809
|
+
({ attrs: additionalAttrs, node: cellNode } = res);
|
|
64815
65810
|
}
|
|
64816
65811
|
else if (cell.content && isMarkdownLink(cell.content)) {
|
|
64817
65812
|
const { label } = parseMarkdownLink(cell.content);
|
|
@@ -65817,13 +66812,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65817
66812
|
UuidGenerator,
|
|
65818
66813
|
formatValue,
|
|
65819
66814
|
createCurrencyFormat,
|
|
66815
|
+
ColorGenerator,
|
|
65820
66816
|
computeTextWidth,
|
|
65821
66817
|
createEmptyWorkbookData,
|
|
65822
66818
|
createEmptySheet,
|
|
65823
66819
|
createEmptyExcelSheet,
|
|
65824
66820
|
getDefaultChartJsRuntime,
|
|
65825
66821
|
chartFontColor,
|
|
65826
|
-
|
|
66822
|
+
getChartAxisTitleRuntime,
|
|
65827
66823
|
getFillingMode,
|
|
65828
66824
|
rgbaToHex,
|
|
65829
66825
|
colorToRGBA,
|
|
@@ -65880,9 +66876,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65880
66876
|
GridOverlay,
|
|
65881
66877
|
ScorecardChart,
|
|
65882
66878
|
LineConfigPanel,
|
|
65883
|
-
GenericChartDesignPanel,
|
|
65884
66879
|
BarConfigPanel,
|
|
66880
|
+
PieChartDesignPanel,
|
|
65885
66881
|
GenericChartConfigPanel,
|
|
66882
|
+
ChartWithAxisDesignPanel,
|
|
65886
66883
|
GaugeChartConfigPanel,
|
|
65887
66884
|
GaugeChartDesignPanel,
|
|
65888
66885
|
ScorecardChartConfigPanel,
|
|
@@ -65981,9 +66978,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65981
66978
|
exports.tokenize = tokenize;
|
|
65982
66979
|
|
|
65983
66980
|
|
|
65984
|
-
__info__.version = "17.3.0
|
|
65985
|
-
__info__.date = "2024-05-
|
|
65986
|
-
__info__.hash = "
|
|
66981
|
+
__info__.version = "17.3.0";
|
|
66982
|
+
__info__.date = "2024-05-31T14:21:26.547Z";
|
|
66983
|
+
__info__.hash = "271202e";
|
|
65987
66984
|
|
|
65988
66985
|
|
|
65989
66986
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|