@odoo/o-spreadsheet 17.3.0-alpha.9 → 17.3.1
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 +1611 -604
- package/dist/o-spreadsheet.d.ts +427 -200
- package/dist/o-spreadsheet.esm.js +1611 -604
- package/dist/o-spreadsheet.iife.js +1611 -604
- 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.
|
|
7
|
-
* @date 2024-
|
|
8
|
-
* @hash
|
|
6
|
+
* @version 17.3.1
|
|
7
|
+
* @date 2024-06-03T15:28:03.284Z
|
|
8
|
+
* @hash 605d098
|
|
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.text);
|
|
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);
|
|
@@ -34998,7 +35752,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
34998
35752
|
|
|
34999
35753
|
class PivotSidePanelStore extends SpreadsheetStore {
|
|
35000
35754
|
pivotId;
|
|
35001
|
-
mutators = [
|
|
35755
|
+
mutators = [
|
|
35756
|
+
"reset",
|
|
35757
|
+
"deferUpdates",
|
|
35758
|
+
"applyUpdate",
|
|
35759
|
+
"discardPendingUpdate",
|
|
35760
|
+
"renamePivot",
|
|
35761
|
+
"update",
|
|
35762
|
+
];
|
|
35002
35763
|
updatesAreDeferred = true;
|
|
35003
35764
|
draft = null;
|
|
35004
35765
|
constructor(get, pivotId) {
|
|
@@ -36711,14 +37472,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36711
37472
|
}
|
|
36712
37473
|
onKeyDown(ev) {
|
|
36713
37474
|
const figure = this.props.figure;
|
|
36714
|
-
|
|
37475
|
+
const keyDownShortcut = keyboardEventToShortcutString(ev);
|
|
37476
|
+
switch (keyDownShortcut) {
|
|
36715
37477
|
case "Delete":
|
|
37478
|
+
case "Backspace":
|
|
36716
37479
|
this.env.model.dispatch("DELETE_FIGURE", {
|
|
36717
37480
|
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
36718
37481
|
id: figure.id,
|
|
36719
37482
|
});
|
|
36720
37483
|
this.props.onFigureDeleted();
|
|
36721
|
-
ev.stopPropagation();
|
|
36722
37484
|
ev.preventDefault();
|
|
36723
37485
|
ev.stopPropagation();
|
|
36724
37486
|
break;
|
|
@@ -36739,7 +37501,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
36739
37501
|
x: figure.x + delta[0],
|
|
36740
37502
|
y: figure.y + delta[1],
|
|
36741
37503
|
});
|
|
37504
|
+
ev.preventDefault();
|
|
36742
37505
|
ev.stopPropagation();
|
|
37506
|
+
break;
|
|
37507
|
+
case "Ctrl+A":
|
|
37508
|
+
// Maybe in the future we will implement a way to select all figures
|
|
37509
|
+
ev.preventDefault();
|
|
37510
|
+
ev.stopPropagation();
|
|
37511
|
+
break;
|
|
37512
|
+
case "Ctrl+Y":
|
|
37513
|
+
case "Ctrl+Z":
|
|
37514
|
+
if (keyDownShortcut === "Ctrl+Y") {
|
|
37515
|
+
this.env.model.dispatch("REQUEST_REDO");
|
|
37516
|
+
}
|
|
37517
|
+
else if (keyDownShortcut === "Ctrl+Z") {
|
|
37518
|
+
this.env.model.dispatch("REQUEST_UNDO");
|
|
37519
|
+
}
|
|
36743
37520
|
ev.preventDefault();
|
|
36744
37521
|
ev.stopPropagation();
|
|
36745
37522
|
break;
|
|
@@ -38019,9 +38796,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38019
38796
|
|
|
38020
38797
|
class FilterIconsOverlay extends owl.Component {
|
|
38021
38798
|
static template = "o-spreadsheet-FilterIconsOverlay";
|
|
38022
|
-
static props = {
|
|
38023
|
-
onMouseDown: Function,
|
|
38024
|
-
};
|
|
38799
|
+
static props = {};
|
|
38025
38800
|
static components = {
|
|
38026
38801
|
GridCellIcon,
|
|
38027
38802
|
FilterIcon,
|
|
@@ -38261,6 +39036,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38261
39036
|
};
|
|
38262
39037
|
gridOverlay = owl.useRef("gridOverlay");
|
|
38263
39038
|
gridOverlayRect = useAbsoluteBoundingRect(this.gridOverlay);
|
|
39039
|
+
cellPopovers;
|
|
38264
39040
|
setup() {
|
|
38265
39041
|
useCellHovered(this.env, this.gridOverlay, this.props.onCellHovered);
|
|
38266
39042
|
const resizeObserver = new ResizeObserver(() => {
|
|
@@ -38282,6 +39058,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38282
39058
|
const { scrollY } = this.env.model.getters.getActiveSheetDOMScrollInfo();
|
|
38283
39059
|
return scrollY > 0;
|
|
38284
39060
|
});
|
|
39061
|
+
this.cellPopovers = useStore(CellPopoverStore);
|
|
38285
39062
|
}
|
|
38286
39063
|
get gridOverlayEl() {
|
|
38287
39064
|
if (!this.gridOverlay.el) {
|
|
@@ -38295,16 +39072,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38295
39072
|
get isPaintingFormat() {
|
|
38296
39073
|
return this.env.model.getters.isPaintingFormat();
|
|
38297
39074
|
}
|
|
38298
|
-
onMouseDown(ev
|
|
39075
|
+
onMouseDown(ev) {
|
|
38299
39076
|
if (ev.button > 0) {
|
|
38300
39077
|
// not main button, probably a context menu
|
|
38301
39078
|
return;
|
|
38302
39079
|
}
|
|
39080
|
+
if (ev.target === this.gridOverlay.el && this.cellPopovers.isOpen) {
|
|
39081
|
+
this.cellPopovers.close();
|
|
39082
|
+
}
|
|
38303
39083
|
const [col, row] = this.getCartesianCoordinates(ev);
|
|
38304
39084
|
this.props.onCellClicked(col, row, {
|
|
38305
39085
|
expandZone: ev.shiftKey,
|
|
38306
39086
|
addZone: isCtrlKey(ev),
|
|
38307
|
-
closePopover: modifiers?.closePopover ?? true,
|
|
38308
39087
|
});
|
|
38309
39088
|
}
|
|
38310
39089
|
onDoubleClick(ev) {
|
|
@@ -40448,9 +41227,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
40448
41227
|
// Zone selection with mouse
|
|
40449
41228
|
// ---------------------------------------------------------------------------
|
|
40450
41229
|
onCellClicked(col, row, modifiers) {
|
|
40451
|
-
if (modifiers.closePopover && this.cellPopovers.isOpen) {
|
|
40452
|
-
this.cellPopovers.close();
|
|
40453
|
-
}
|
|
40454
41230
|
if (this.composerStore.editionMode === "editing") {
|
|
40455
41231
|
this.composerStore.stopEdition();
|
|
40456
41232
|
}
|
|
@@ -42323,11 +43099,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42323
43099
|
return "imageSrc" in data;
|
|
42324
43100
|
}
|
|
42325
43101
|
function convertChartData(chartData) {
|
|
42326
|
-
const dataSetsHaveTitle = chartData.dataSets
|
|
43102
|
+
const dataSetsHaveTitle = chartData.dataSets.some((ds) => "reference" in (ds.label ?? {}));
|
|
42327
43103
|
const labelRange = chartData.labelRange
|
|
42328
43104
|
? convertExcelRangeToSheetXC(chartData.labelRange, dataSetsHaveTitle)
|
|
42329
43105
|
: undefined;
|
|
42330
|
-
|
|
43106
|
+
const dataSets = chartData.dataSets.map((data) => {
|
|
43107
|
+
let label = undefined;
|
|
43108
|
+
if (data.label && "text" in data.label) {
|
|
43109
|
+
label = data.label.text;
|
|
43110
|
+
}
|
|
43111
|
+
return {
|
|
43112
|
+
dataRange: convertExcelRangeToSheetXC(data.range, dataSetsHaveTitle),
|
|
43113
|
+
label,
|
|
43114
|
+
};
|
|
43115
|
+
});
|
|
42331
43116
|
// For doughnut charts, in chartJS first dataset = outer dataset, in excel first dataset = inner dataset
|
|
42332
43117
|
if (chartData.type === "pie") {
|
|
42333
43118
|
dataSets.reverse();
|
|
@@ -42336,10 +43121,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42336
43121
|
dataSets,
|
|
42337
43122
|
dataSetsHaveTitle,
|
|
42338
43123
|
labelRange,
|
|
42339
|
-
title: chartData.title
|
|
43124
|
+
title: chartData.title ?? { text: "" },
|
|
42340
43125
|
type: chartData.type,
|
|
42341
43126
|
background: convertColor({ rgb: chartData.backgroundColor }) || "#FFFFFF",
|
|
42342
|
-
verticalAxisPosition: chartData.verticalAxisPosition,
|
|
42343
43127
|
legendPosition: chartData.legendPosition,
|
|
42344
43128
|
stacked: chartData.stacked || false,
|
|
42345
43129
|
aggregated: false,
|
|
@@ -43454,25 +44238,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43454
44238
|
return this.extractComboChart(rootChartElement);
|
|
43455
44239
|
}
|
|
43456
44240
|
// 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) => {
|
|
44241
|
+
const chartTitle = this.mapOnElements({ parent: rootChartElement, query: "c:chart > c:title a:t" }, (textElement) => {
|
|
43458
44242
|
return textElement.textContent || "";
|
|
43459
44243
|
}).join("");
|
|
43460
44244
|
const barChartGrouping = this.extractChildAttr(rootChartElement, "c:grouping", "val", {
|
|
43461
44245
|
default: "clustered",
|
|
43462
44246
|
}).asString();
|
|
43463
44247
|
return {
|
|
43464
|
-
title: chartTitle,
|
|
44248
|
+
title: { text: chartTitle },
|
|
43465
44249
|
type: CHART_TYPE_CONVERSION_MAP[chartType],
|
|
43466
|
-
dataSets: this.extractChartDatasets(this.
|
|
44250
|
+
dataSets: this.extractChartDatasets(this.querySelectorAll(rootChartElement, `c:${chartType}`), chartType),
|
|
43467
44251
|
labelRange: this.extractChildTextContent(rootChartElement, `c:ser ${chartType === "scatterChart" ? "c:numRef" : "c:cat"} c:f`),
|
|
43468
44252
|
backgroundColor: this.extractChildAttr(rootChartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
|
|
43469
44253
|
default: "ffffff",
|
|
43470
44254
|
}).asString(),
|
|
43471
|
-
verticalAxisPosition: this.extractChildAttr(rootChartElement, "c:valAx > c:axPos", "val", {
|
|
43472
|
-
default: "l",
|
|
43473
|
-
}).asString() === "r"
|
|
43474
|
-
? "right"
|
|
43475
|
-
: "left",
|
|
43476
44255
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(rootChartElement, "c:legendPos", "val", {
|
|
43477
44256
|
default: "b",
|
|
43478
44257
|
}).asString()],
|
|
@@ -43490,21 +44269,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43490
44269
|
default: "clustered",
|
|
43491
44270
|
}).asString();
|
|
43492
44271
|
return {
|
|
43493
|
-
title: chartTitle,
|
|
44272
|
+
title: { text: chartTitle },
|
|
43494
44273
|
type: "combo",
|
|
43495
44274
|
dataSets: [
|
|
43496
|
-
...this.extractChartDatasets(this.
|
|
43497
|
-
...this.extractChartDatasets(this.
|
|
44275
|
+
...this.extractChartDatasets(this.querySelectorAll(chartElement, `c:barChart`), "comboChart"),
|
|
44276
|
+
...this.extractChartDatasets(this.querySelectorAll(chartElement, `c:lineChart`), "comboChart"),
|
|
43498
44277
|
],
|
|
43499
44278
|
labelRange: this.extractChildTextContent(chartElement, "c:ser c:cat c:f"),
|
|
43500
44279
|
backgroundColor: this.extractChildAttr(chartElement, "c:chartSpace > c:spPr a:srgbClr", "val", {
|
|
43501
44280
|
default: "ffffff",
|
|
43502
44281
|
}).asString(),
|
|
43503
|
-
verticalAxisPosition: this.extractChildAttr(chartElement, "c:valAx > c:axPos", "val", {
|
|
43504
|
-
default: "l",
|
|
43505
|
-
}).asString() === "r"
|
|
43506
|
-
? "right"
|
|
43507
|
-
: "left",
|
|
43508
44282
|
legendPosition: DRAWING_LEGEND_POSITION_CONVERSION_MAP[this.extractChildAttr(chartElement, "c:legendPos", "val", {
|
|
43509
44283
|
default: "b",
|
|
43510
44284
|
}).asString()],
|
|
@@ -43512,21 +44286,49 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43512
44286
|
fontColor: "000000",
|
|
43513
44287
|
};
|
|
43514
44288
|
}
|
|
43515
|
-
extractChartDatasets(
|
|
43516
|
-
|
|
43517
|
-
|
|
43518
|
-
|
|
43519
|
-
|
|
43520
|
-
|
|
43521
|
-
|
|
43522
|
-
|
|
43523
|
-
|
|
43524
|
-
|
|
44289
|
+
extractChartDatasets(chartElements, chartType) {
|
|
44290
|
+
return Array.from(chartElements)
|
|
44291
|
+
.map((element) => {
|
|
44292
|
+
if (chartType === "scatterChart") {
|
|
44293
|
+
return this.extractScatterChartDatasets(element);
|
|
44294
|
+
}
|
|
44295
|
+
return this.mapOnElements({ parent: element, query: "c:ser" }, (chartDataElement) => {
|
|
44296
|
+
let label = {};
|
|
44297
|
+
const reference = this.extractChildTextContent(chartDataElement, "c:tx c:f");
|
|
44298
|
+
if (reference) {
|
|
44299
|
+
label = { reference };
|
|
44300
|
+
}
|
|
44301
|
+
else {
|
|
44302
|
+
const text = this.extractChildTextContent(chartDataElement, "c:tx c:v");
|
|
44303
|
+
if (text) {
|
|
44304
|
+
label = { text };
|
|
44305
|
+
}
|
|
44306
|
+
}
|
|
44307
|
+
return {
|
|
44308
|
+
label,
|
|
44309
|
+
range: this.extractChildTextContent(chartDataElement, "c:val c:f", {
|
|
44310
|
+
required: true,
|
|
44311
|
+
}),
|
|
44312
|
+
};
|
|
44313
|
+
});
|
|
44314
|
+
})
|
|
44315
|
+
.flat();
|
|
43525
44316
|
}
|
|
43526
44317
|
extractScatterChartDatasets(chartElement) {
|
|
43527
44318
|
return this.mapOnElements({ parent: chartElement, query: "c:ser" }, (chartDataElement) => {
|
|
44319
|
+
let label = {};
|
|
44320
|
+
const reference = this.extractChildTextContent(chartDataElement, "c:tx c:f");
|
|
44321
|
+
if (reference) {
|
|
44322
|
+
label = { reference };
|
|
44323
|
+
}
|
|
44324
|
+
else {
|
|
44325
|
+
const text = this.extractChildTextContent(chartDataElement, "c:tx c:v");
|
|
44326
|
+
if (text) {
|
|
44327
|
+
label = { text };
|
|
44328
|
+
}
|
|
44329
|
+
}
|
|
43528
44330
|
return {
|
|
43529
|
-
label
|
|
44331
|
+
label,
|
|
43530
44332
|
range: this.extractChildTextContent(chartDataElement, "c:yVal c:f", { required: true }),
|
|
43531
44333
|
};
|
|
43532
44334
|
});
|
|
@@ -44258,7 +45060,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44258
45060
|
return relsFile;
|
|
44259
45061
|
}
|
|
44260
45062
|
|
|
44261
|
-
const EXCEL_IMPORT_VERSION =
|
|
45063
|
+
const EXCEL_IMPORT_VERSION = 16;
|
|
44262
45064
|
class XlsxReader {
|
|
44263
45065
|
warningManager;
|
|
44264
45066
|
xmls;
|
|
@@ -44736,6 +45538,30 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44736
45538
|
return data;
|
|
44737
45539
|
},
|
|
44738
45540
|
},
|
|
45541
|
+
{
|
|
45542
|
+
description: "transform chart data structure (2)",
|
|
45543
|
+
from: 16,
|
|
45544
|
+
to: 17,
|
|
45545
|
+
applyMigration(data) {
|
|
45546
|
+
for (const sheet of data.sheets || []) {
|
|
45547
|
+
for (const f in sheet.figures || []) {
|
|
45548
|
+
const figure = sheet.figures[f];
|
|
45549
|
+
if ("title" in figure.data && typeof figure.data.title === "string") {
|
|
45550
|
+
figure.data.title = { text: figure.data.title };
|
|
45551
|
+
}
|
|
45552
|
+
const figureType = figure.data.type;
|
|
45553
|
+
if (!["line", "bar", "pie", "scatter", "waterfall", "combo"].includes(figureType)) {
|
|
45554
|
+
continue;
|
|
45555
|
+
}
|
|
45556
|
+
const { dataSets, ...newData } = sheet.figures[f].data;
|
|
45557
|
+
const newDataSets = dataSets.map((dataRange) => ({ dataRange }));
|
|
45558
|
+
newData.dataSets = newDataSets;
|
|
45559
|
+
sheet.figures[f].data = newData;
|
|
45560
|
+
}
|
|
45561
|
+
}
|
|
45562
|
+
return data;
|
|
45563
|
+
},
|
|
45564
|
+
},
|
|
44739
45565
|
];
|
|
44740
45566
|
/**
|
|
44741
45567
|
* This function is used to repair faulty data independently of the migration.
|
|
@@ -48347,6 +49173,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48347
49173
|
if (range.invalidXc) {
|
|
48348
49174
|
return range.invalidXc;
|
|
48349
49175
|
}
|
|
49176
|
+
if (!this.getters.tryGetSheet(range.sheetId)) {
|
|
49177
|
+
return CellErrorType.InvalidReference;
|
|
49178
|
+
}
|
|
48350
49179
|
if (range.zone.bottom - range.zone.top < 0 || range.zone.right - range.zone.left < 0) {
|
|
48351
49180
|
return CellErrorType.InvalidReference;
|
|
48352
49181
|
}
|
|
@@ -51765,7 +52594,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51765
52594
|
*
|
|
51766
52595
|
*/
|
|
51767
52596
|
class SpreadingRelation {
|
|
51768
|
-
createEmptyPositionSet;
|
|
51769
52597
|
/**
|
|
51770
52598
|
* Internal structure:
|
|
51771
52599
|
* For something like
|
|
@@ -51796,9 +52624,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51796
52624
|
*/
|
|
51797
52625
|
resultsToArrayFormulas = new PositionMap();
|
|
51798
52626
|
arrayFormulasToResults = new PositionMap();
|
|
51799
|
-
constructor(createEmptyPositionSet) {
|
|
51800
|
-
this.createEmptyPositionSet = createEmptyPositionSet;
|
|
51801
|
-
}
|
|
51802
52627
|
getFormulaPositionsSpreadingOn(resultPosition) {
|
|
51803
52628
|
return this.resultsToArrayFormulas.get(resultPosition) || EMPTY_ARRAY;
|
|
51804
52629
|
}
|
|
@@ -51817,13 +52642,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51817
52642
|
*/
|
|
51818
52643
|
addRelation({ arrayFormulaPosition, resultPosition, }) {
|
|
51819
52644
|
if (!this.resultsToArrayFormulas.has(resultPosition)) {
|
|
51820
|
-
this.resultsToArrayFormulas.set(resultPosition,
|
|
52645
|
+
this.resultsToArrayFormulas.set(resultPosition, []);
|
|
51821
52646
|
}
|
|
51822
|
-
this.resultsToArrayFormulas.get(resultPosition)?.
|
|
52647
|
+
this.resultsToArrayFormulas.get(resultPosition)?.push(arrayFormulaPosition);
|
|
51823
52648
|
if (!this.arrayFormulasToResults.has(arrayFormulaPosition)) {
|
|
51824
|
-
this.arrayFormulasToResults.set(arrayFormulaPosition,
|
|
52649
|
+
this.arrayFormulasToResults.set(arrayFormulaPosition, []);
|
|
51825
52650
|
}
|
|
51826
|
-
this.arrayFormulasToResults.get(arrayFormulaPosition)?.
|
|
52651
|
+
this.arrayFormulasToResults.get(arrayFormulaPosition)?.push(resultPosition);
|
|
51827
52652
|
}
|
|
51828
52653
|
hasArrayFormulaResult(position) {
|
|
51829
52654
|
return this.resultsToArrayFormulas.has(position);
|
|
@@ -51844,7 +52669,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51844
52669
|
evaluatedCells = new PositionMap();
|
|
51845
52670
|
formulaDependencies = lazy(new FormulaDependencyGraph(this.createEmptyPositionSet.bind(this)));
|
|
51846
52671
|
blockedArrayFormulas = new PositionSet({});
|
|
51847
|
-
spreadingRelations = new SpreadingRelation(
|
|
52672
|
+
spreadingRelations = new SpreadingRelation();
|
|
51848
52673
|
constructor(context, getters) {
|
|
51849
52674
|
this.context = context;
|
|
51850
52675
|
this.getters = getters;
|
|
@@ -51938,7 +52763,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51938
52763
|
}
|
|
51939
52764
|
buildDependencyGraph() {
|
|
51940
52765
|
this.blockedArrayFormulas = this.createEmptyPositionSet();
|
|
51941
|
-
this.spreadingRelations = new SpreadingRelation(
|
|
52766
|
+
this.spreadingRelations = new SpreadingRelation();
|
|
51942
52767
|
this.formulaDependencies = lazy(() => {
|
|
51943
52768
|
const dependencies = [...this.getAllCells()].flatMap((position) => this.getDirectDependencies(position)
|
|
51944
52769
|
.filter((range) => !range.invalidSheetName && !range.invalidXc)
|
|
@@ -52070,6 +52895,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52070
52895
|
const nbColumns = formulaReturn.length;
|
|
52071
52896
|
const nbRows = formulaReturn[0].length;
|
|
52072
52897
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.updateSpreadRelation(formulaPosition));
|
|
52898
|
+
this.assertNoMergedCellsInSpreadZone(formulaPosition, formulaReturn);
|
|
52073
52899
|
forEachSpreadPositionInMatrix(nbColumns, nbRows, this.checkCollision(formulaPosition));
|
|
52074
52900
|
forEachSpreadPositionInMatrix(nbColumns, nbRows,
|
|
52075
52901
|
// thanks to the isMatrix check above, we know that formulaReturn is MatrixFunctionReturn
|
|
@@ -52092,6 +52918,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52092
52918
|
}
|
|
52093
52919
|
throw new SplillBlockedError(_t("Result couldn't be automatically expanded. Please insert more columns and rows."));
|
|
52094
52920
|
}
|
|
52921
|
+
assertNoMergedCellsInSpreadZone({ sheetId, col, row }, matrixResult) {
|
|
52922
|
+
const mergedCells = this.getters.getMergesInZone(sheetId, {
|
|
52923
|
+
top: row,
|
|
52924
|
+
bottom: row + matrixResult.length,
|
|
52925
|
+
left: col,
|
|
52926
|
+
right: col + matrixResult[0].length,
|
|
52927
|
+
});
|
|
52928
|
+
if (mergedCells.length === 0) {
|
|
52929
|
+
return;
|
|
52930
|
+
}
|
|
52931
|
+
throw new SplillBlockedError(_t("Merged cells found in the spill zone. Please unmerge cells before using array formulas."));
|
|
52932
|
+
}
|
|
52095
52933
|
updateSpreadRelation({ sheetId, col, row, }) {
|
|
52096
52934
|
const arrayFormulaPosition = { sheetId, col, row };
|
|
52097
52935
|
return (i, j) => {
|
|
@@ -52329,10 +53167,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52329
53167
|
this.evaluator.updateDependencies(cmd);
|
|
52330
53168
|
}
|
|
52331
53169
|
break;
|
|
52332
|
-
case "DUPLICATE_SHEET":
|
|
52333
|
-
case "CREATE_SHEET":
|
|
52334
|
-
this.shouldRebuildDependenciesGraph = true;
|
|
52335
|
-
break;
|
|
52336
53170
|
case "EVALUATE_CELLS":
|
|
52337
53171
|
this.evaluator.evaluateAllCells();
|
|
52338
53172
|
break;
|
|
@@ -52433,16 +53267,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52433
53267
|
let newContent = undefined;
|
|
52434
53268
|
let newFormat = undefined;
|
|
52435
53269
|
let isExported = true;
|
|
53270
|
+
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
52436
53271
|
const formulaCell = this.getCorrespondingFormulaCell(position);
|
|
52437
53272
|
if (formulaCell) {
|
|
52438
53273
|
isExported = isExportableToExcel(formulaCell.compiledFormula.tokens);
|
|
52439
53274
|
isFormula = isExported;
|
|
52440
53275
|
if (!isExported) {
|
|
52441
|
-
|
|
52442
|
-
|
|
53276
|
+
// If the cell contains a non-exported formula and that is evaluates to
|
|
53277
|
+
// nothing* ,we don't export it.
|
|
53278
|
+
// * non-falsy value are relevant and so are 0 and FALSE, which only leaves
|
|
53279
|
+
// the empty string.
|
|
53280
|
+
if (value !== "") {
|
|
53281
|
+
newContent = (value ?? "").toString();
|
|
53282
|
+
newFormat = evaluatedCell.format;
|
|
53283
|
+
}
|
|
52443
53284
|
}
|
|
52444
53285
|
}
|
|
52445
|
-
const exportedSheetData = data.sheets.find((sheet) => sheet.id === position.sheetId);
|
|
52446
53286
|
const exportedCellData = exportedSheetData.cells[xc] || {};
|
|
52447
53287
|
const format = newFormat
|
|
52448
53288
|
? getItemId(newFormat, data.formats)
|
|
@@ -57065,7 +57905,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57065
57905
|
paintFormatStatus = "inactive";
|
|
57066
57906
|
originSheetId;
|
|
57067
57907
|
copiedData;
|
|
57068
|
-
_isCutOperation;
|
|
57908
|
+
_isCutOperation = false;
|
|
57069
57909
|
// ---------------------------------------------------------------------------
|
|
57070
57910
|
// Command Handling
|
|
57071
57911
|
// ---------------------------------------------------------------------------
|
|
@@ -57077,14 +57917,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57077
57917
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
57078
57918
|
const copiedData = this.convertOSClipboardData(cmd.text);
|
|
57079
57919
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57080
|
-
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption });
|
|
57920
|
+
return this.isPasteAllowed(cmd.target, copiedData, { pasteOption, isCutOperation: false });
|
|
57081
57921
|
}
|
|
57082
57922
|
case "PASTE": {
|
|
57083
57923
|
if (!this.copiedData) {
|
|
57084
57924
|
return "EmptyClipboard" /* CommandResult.EmptyClipboard */;
|
|
57085
57925
|
}
|
|
57086
57926
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57087
|
-
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
57927
|
+
return this.isPasteAllowed(cmd.target, this.copiedData, {
|
|
57928
|
+
pasteOption: pasteOption,
|
|
57929
|
+
isCutOperation: this._isCutOperation,
|
|
57930
|
+
});
|
|
57088
57931
|
}
|
|
57089
57932
|
case "COPY_PASTE_CELLS_ABOVE": {
|
|
57090
57933
|
const zones = this.getters.getSelectedZones();
|
|
@@ -57102,13 +57945,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57102
57945
|
}
|
|
57103
57946
|
case "INSERT_CELL": {
|
|
57104
57947
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57105
|
-
const copiedData = this.copy(
|
|
57106
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
57948
|
+
const copiedData = this.copy(cut);
|
|
57949
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
57107
57950
|
}
|
|
57108
57951
|
case "DELETE_CELL": {
|
|
57109
57952
|
const { cut, paste } = this.getDeleteCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57110
|
-
const copiedData = this.copy(
|
|
57111
|
-
return this.isPasteAllowed(paste, copiedData, {});
|
|
57953
|
+
const copiedData = this.copy(cut);
|
|
57954
|
+
return this.isPasteAllowed(paste, copiedData, { isCutOperation: true });
|
|
57112
57955
|
}
|
|
57113
57956
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
57114
57957
|
if (this.paintFormatStatus !== "inactive") {
|
|
@@ -57126,23 +57969,27 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57126
57969
|
const zones = this.getters.getSelectedZones();
|
|
57127
57970
|
this.status = "visible";
|
|
57128
57971
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57129
|
-
this.copiedData = this.copy(
|
|
57972
|
+
this.copiedData = this.copy(zones);
|
|
57973
|
+
this._isCutOperation = cmd.type === "CUT";
|
|
57130
57974
|
break;
|
|
57131
57975
|
case "PASTE_FROM_OS_CLIPBOARD": {
|
|
57976
|
+
this._isCutOperation = false;
|
|
57132
57977
|
this.copiedData = this.convertOSClipboardData(cmd.text);
|
|
57133
57978
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57134
|
-
this.paste(cmd.target, {
|
|
57979
|
+
this.paste(cmd.target, this.copiedData, {
|
|
57135
57980
|
pasteOption,
|
|
57136
57981
|
selectTarget: true,
|
|
57982
|
+
isCutOperation: false,
|
|
57137
57983
|
});
|
|
57138
57984
|
this.status = "invisible";
|
|
57139
57985
|
break;
|
|
57140
57986
|
}
|
|
57141
57987
|
case "PASTE": {
|
|
57142
57988
|
const pasteOption = cmd.pasteOption || (this.paintFormatStatus !== "inactive" ? "onlyFormat" : undefined);
|
|
57143
|
-
this.paste(cmd.target, {
|
|
57989
|
+
this.paste(cmd.target, this.copiedData, {
|
|
57144
57990
|
pasteOption,
|
|
57145
57991
|
selectTarget: true,
|
|
57992
|
+
isCutOperation: this._isCutOperation,
|
|
57146
57993
|
});
|
|
57147
57994
|
if (this.paintFormatStatus === "oneOff") {
|
|
57148
57995
|
this.paintFormatStatus = "inactive";
|
|
@@ -57163,9 +58010,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57163
58010
|
top: multipleRowsInSelection ? zone.top : zone.top - 1,
|
|
57164
58011
|
};
|
|
57165
58012
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57166
|
-
|
|
57167
|
-
this.paste([zone], {
|
|
57168
|
-
|
|
58013
|
+
const copiedData = this.copy([copyTarget]);
|
|
58014
|
+
this.paste([zone], copiedData, {
|
|
58015
|
+
isCutOperation: false,
|
|
57169
58016
|
selectTarget: true,
|
|
57170
58017
|
});
|
|
57171
58018
|
}
|
|
@@ -57180,9 +58027,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57180
58027
|
left: multipleColsInSelection ? zone.left : zone.left - 1,
|
|
57181
58028
|
};
|
|
57182
58029
|
this.originSheetId = this.getters.getActiveSheetId();
|
|
57183
|
-
|
|
57184
|
-
this.paste([zone], {
|
|
57185
|
-
|
|
58030
|
+
const copiedData = this.copy([copyTarget]);
|
|
58031
|
+
this.paste([zone], copiedData, {
|
|
58032
|
+
isCutOperation: false,
|
|
57186
58033
|
selectTarget: true,
|
|
57187
58034
|
});
|
|
57188
58035
|
}
|
|
@@ -57198,14 +58045,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57198
58045
|
}
|
|
57199
58046
|
break;
|
|
57200
58047
|
}
|
|
57201
|
-
|
|
57202
|
-
this.paste(paste, {});
|
|
58048
|
+
const copiedData = this.copy(cut);
|
|
58049
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
57203
58050
|
break;
|
|
57204
58051
|
}
|
|
57205
58052
|
case "INSERT_CELL": {
|
|
57206
58053
|
const { cut, paste } = this.getInsertCellsTargets(cmd.zone, cmd.shiftDimension);
|
|
57207
|
-
|
|
57208
|
-
this.paste(paste, {});
|
|
58054
|
+
const copiedData = this.copy(cut);
|
|
58055
|
+
this.paste(paste, copiedData, { isCutOperation: true });
|
|
57209
58056
|
break;
|
|
57210
58057
|
}
|
|
57211
58058
|
case "ADD_COLUMNS_ROWS": {
|
|
@@ -57237,7 +58084,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57237
58084
|
break;
|
|
57238
58085
|
}
|
|
57239
58086
|
case "REPEAT_PASTE": {
|
|
57240
|
-
this.paste(cmd.target, {
|
|
58087
|
+
this.paste(cmd.target, this.copiedData, {
|
|
58088
|
+
isCutOperation: false,
|
|
57241
58089
|
pasteOption: cmd.pasteOption,
|
|
57242
58090
|
selectTarget: true,
|
|
57243
58091
|
});
|
|
@@ -57245,7 +58093,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57245
58093
|
}
|
|
57246
58094
|
case "ACTIVATE_PAINT_FORMAT": {
|
|
57247
58095
|
const zones = this.getters.getSelectedZones();
|
|
57248
|
-
this.copiedData = this.copy(
|
|
58096
|
+
this.copiedData = this.copy(zones);
|
|
57249
58097
|
this.status = "visible";
|
|
57250
58098
|
if (cmd.persistent) {
|
|
57251
58099
|
this.paintFormatStatus = "persistent";
|
|
@@ -57276,7 +58124,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57276
58124
|
}
|
|
57277
58125
|
}
|
|
57278
58126
|
convertOSClipboardData(clipboardData) {
|
|
57279
|
-
this._isCutOperation = false;
|
|
57280
58127
|
const handlers = clipboardHandlersRegistries.figureHandlers
|
|
57281
58128
|
.getAll()
|
|
57282
58129
|
.map((handler) => new handler(this.getters, this.dispatch));
|
|
@@ -57314,7 +58161,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57314
58161
|
for (const handler of this.selectClipboardHandlers(copiedData)) {
|
|
57315
58162
|
const result = handler.isPasteAllowed(this.getters.getActiveSheetId(), target, copiedData, {
|
|
57316
58163
|
...options,
|
|
57317
|
-
isCutOperation: this.isCutOperation(),
|
|
57318
58164
|
});
|
|
57319
58165
|
if (result !== "Success" /* CommandResult.Success */) {
|
|
57320
58166
|
return result;
|
|
@@ -57337,9 +58183,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57337
58183
|
}
|
|
57338
58184
|
return false;
|
|
57339
58185
|
}
|
|
57340
|
-
copy(
|
|
58186
|
+
copy(zones) {
|
|
57341
58187
|
let copiedData = {};
|
|
57342
|
-
this._isCutOperation = operation === "CUT";
|
|
57343
58188
|
const clipboardData = this.getClipboardData(zones);
|
|
57344
58189
|
for (const handler of this.selectClipboardHandlers(clipboardData)) {
|
|
57345
58190
|
const data = handler.copy(clipboardData);
|
|
@@ -57347,8 +58192,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57347
58192
|
}
|
|
57348
58193
|
return copiedData;
|
|
57349
58194
|
}
|
|
57350
|
-
paste(zones, options) {
|
|
57351
|
-
if (!
|
|
58195
|
+
paste(zones, copiedData, options) {
|
|
58196
|
+
if (!copiedData) {
|
|
57352
58197
|
return;
|
|
57353
58198
|
}
|
|
57354
58199
|
let zone = undefined;
|
|
@@ -57356,12 +58201,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57356
58201
|
let target = {
|
|
57357
58202
|
zones,
|
|
57358
58203
|
};
|
|
57359
|
-
const handlers = this.selectClipboardHandlers(
|
|
58204
|
+
const handlers = this.selectClipboardHandlers(copiedData);
|
|
57360
58205
|
for (const handler of handlers) {
|
|
57361
|
-
const currentTarget = handler.getPasteTarget(zones,
|
|
57362
|
-
...options,
|
|
57363
|
-
isCutOperation: this.isCutOperation(),
|
|
57364
|
-
});
|
|
58206
|
+
const currentTarget = handler.getPasteTarget(zones, copiedData, options);
|
|
57365
58207
|
if (currentTarget.figureId) {
|
|
57366
58208
|
target.figureId = currentTarget.figureId;
|
|
57367
58209
|
}
|
|
@@ -57377,7 +58219,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57377
58219
|
if (zone !== undefined) {
|
|
57378
58220
|
this.addMissingDimensions(this.getters.getActiveSheetId(), zone.right - zone.left + 1, zone.bottom - zone.top + 1, zone.left, zone.top);
|
|
57379
58221
|
}
|
|
57380
|
-
handlers.forEach((handler) => handler.paste(target,
|
|
58222
|
+
handlers.forEach((handler) => handler.paste(target, copiedData, options));
|
|
57381
58223
|
if (!options?.selectTarget) {
|
|
57382
58224
|
return;
|
|
57383
58225
|
}
|
|
@@ -59763,6 +60605,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59763
60605
|
sheetDivRef = owl.useRef("sheetDiv");
|
|
59764
60606
|
sheetNameRef = owl.useRef("sheetNameSpan");
|
|
59765
60607
|
editionState = "initializing";
|
|
60608
|
+
DOMFocusableElementStore;
|
|
59766
60609
|
setup() {
|
|
59767
60610
|
owl.onMounted(() => {
|
|
59768
60611
|
if (this.isSheetActive) {
|
|
@@ -59775,6 +60618,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59775
60618
|
this.focusInputAndSelectContent();
|
|
59776
60619
|
}
|
|
59777
60620
|
});
|
|
60621
|
+
this.DOMFocusableElementStore = useStore(DOMFocusableElementStore);
|
|
59778
60622
|
}
|
|
59779
60623
|
focusInputAndSelectContent() {
|
|
59780
60624
|
if (!this.state.isEditing || !this.sheetNameRef.el)
|
|
@@ -59816,9 +60660,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
59816
60660
|
if (ev.key === "Enter") {
|
|
59817
60661
|
ev.preventDefault();
|
|
59818
60662
|
this.stopEdition();
|
|
60663
|
+
this.DOMFocusableElementStore.focus();
|
|
59819
60664
|
}
|
|
59820
60665
|
if (ev.key === "Escape") {
|
|
59821
60666
|
this.cancelEdition();
|
|
60667
|
+
this.DOMFocusableElementStore.focus();
|
|
59822
60668
|
}
|
|
59823
60669
|
}
|
|
59824
60670
|
onClickSheetName(ev) {
|
|
@@ -61867,6 +62713,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61867
62713
|
static template = "o-spreadsheet-Spreadsheet";
|
|
61868
62714
|
static props = {
|
|
61869
62715
|
model: Object,
|
|
62716
|
+
notifyUser: { type: Function, optional: true },
|
|
62717
|
+
raiseError: { type: Function, optional: true },
|
|
62718
|
+
askConfirmation: { type: Function, optional: true },
|
|
61870
62719
|
};
|
|
61871
62720
|
static components = {
|
|
61872
62721
|
TopBar,
|
|
@@ -61913,7 +62762,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61913
62762
|
toggleSidePanel: this.sidePanel.toggle.bind(this.sidePanel),
|
|
61914
62763
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
61915
62764
|
startCellEdition: (content) => this.composerFocusStore.focusGridComposerCell(content),
|
|
62765
|
+
notifyUser: (notification) => this.notificationStore.notifyUser(notification),
|
|
62766
|
+
askConfirmation: (text, confirm, cancel) => this.notificationStore.askConfirmation(text, confirm, cancel),
|
|
62767
|
+
raiseError: (text, cb) => this.notificationStore.raiseError(text, cb),
|
|
61916
62768
|
});
|
|
62769
|
+
this.notificationStore.updateNotificationCallbacks({ ...this.props });
|
|
61917
62770
|
owl.useEffect(() => {
|
|
61918
62771
|
/**
|
|
61919
62772
|
* Only refocus the grid if the active element is not a child of the spreadsheet
|
|
@@ -61936,6 +62789,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61936
62789
|
if (nextProps.model !== this.props.model) {
|
|
61937
62790
|
throw new Error("Changing the props model is not supported at the moment.");
|
|
61938
62791
|
}
|
|
62792
|
+
if (nextProps.notifyUser !== this.props.notifyUser ||
|
|
62793
|
+
nextProps.askConfirmation !== this.props.askConfirmation ||
|
|
62794
|
+
nextProps.raiseError !== this.props.raiseError) {
|
|
62795
|
+
this.notificationStore.updateNotificationCallbacks({ ...nextProps });
|
|
62796
|
+
}
|
|
61939
62797
|
});
|
|
61940
62798
|
const render = batched(this.render.bind(this, true));
|
|
61941
62799
|
owl.onMounted(() => {
|
|
@@ -61953,7 +62811,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61953
62811
|
bindModelEvents() {
|
|
61954
62812
|
this.model.on("update", this, () => this.render(true));
|
|
61955
62813
|
this.model.on("notify-ui", this, (notification) => this.notificationStore.notifyUser(notification));
|
|
61956
|
-
this.model.on("raise-error-ui", this, ({ text }) => this.
|
|
62814
|
+
this.model.on("raise-error-ui", this, ({ text }) => this.notificationStore.raiseError(text));
|
|
61957
62815
|
}
|
|
61958
62816
|
unbindModelEvents() {
|
|
61959
62817
|
this.model.off("update", this);
|
|
@@ -63508,10 +64366,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63508
64366
|
});
|
|
63509
64367
|
// <manualLayout/> to manually position the chart in the figure container
|
|
63510
64368
|
let title = escapeXml ``;
|
|
63511
|
-
if (chart.data.title) {
|
|
64369
|
+
if (chart.data.title?.text) {
|
|
64370
|
+
const color = chart.data.title.color
|
|
64371
|
+
? toXlsxHexColor(chart.data.title.color)
|
|
64372
|
+
: chart.data.fontColor;
|
|
63512
64373
|
title = escapeXml /*xml*/ `
|
|
63513
64374
|
<c:title>
|
|
63514
|
-
${insertText(chart.data.title, chart.data.
|
|
64375
|
+
${insertText(chart.data.title.text, color, DEFAULT_CHART_FONT_SIZE, chart.data.title)}
|
|
63515
64376
|
<c:overlay val="0" />
|
|
63516
64377
|
</c:title>
|
|
63517
64378
|
`;
|
|
@@ -63599,7 +64460,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63599
64460
|
</a:ln>
|
|
63600
64461
|
`;
|
|
63601
64462
|
}
|
|
63602
|
-
function insertText(text, fontColor = "000000", fontsize =
|
|
64463
|
+
function insertText(text, fontColor = "000000", fontsize = DEFAULT_CHART_FONT_SIZE, style = {}) {
|
|
63603
64464
|
return escapeXml /*xml*/ `
|
|
63604
64465
|
<c:tx>
|
|
63605
64466
|
<c:rich>
|
|
@@ -63607,13 +64468,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63607
64468
|
<a:lstStyle />
|
|
63608
64469
|
<a:p>
|
|
63609
64470
|
<a:pPr lvl="0">
|
|
63610
|
-
<a:defRPr b="0">
|
|
64471
|
+
<a:defRPr b="${style?.bold ? 1 : 0}" i="${style?.italic ? 1 : 0}">
|
|
63611
64472
|
${solidFill(fontColor)}
|
|
63612
64473
|
<a:latin typeface="+mn-lt"/>
|
|
63613
64474
|
</a:defRPr>
|
|
63614
64475
|
</a:pPr>
|
|
63615
64476
|
<a:r> <!-- Runs -->
|
|
63616
|
-
<a:rPr sz="${fontsize * 100}"/>
|
|
64477
|
+
<a:rPr b="${style?.bold ? 1 : 0}" i="${style?.italic ? 1 : 0}" sz="${fontsize * 100}"/>
|
|
63617
64478
|
<a:t>${text}</a:t>
|
|
63618
64479
|
</a:r>
|
|
63619
64480
|
</a:p>
|
|
@@ -63642,6 +64503,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63642
64503
|
</c:txPr>
|
|
63643
64504
|
`;
|
|
63644
64505
|
}
|
|
64506
|
+
function extractDataSetLabel(label) {
|
|
64507
|
+
if (!label) {
|
|
64508
|
+
return escapeXml /*xml*/ ``;
|
|
64509
|
+
}
|
|
64510
|
+
if ("text" in label && label.text) {
|
|
64511
|
+
return escapeXml /*xml*/ `
|
|
64512
|
+
<c:tx><c:v>${label.text}</c:v></c:tx>
|
|
64513
|
+
`;
|
|
64514
|
+
}
|
|
64515
|
+
if ("reference" in label && label.reference) {
|
|
64516
|
+
return escapeXml /*xml*/ `
|
|
64517
|
+
<c:tx>
|
|
64518
|
+
${stringRef(label.reference)}
|
|
64519
|
+
</c:tx>
|
|
64520
|
+
`;
|
|
64521
|
+
}
|
|
64522
|
+
return escapeXml /*xml*/ ``;
|
|
64523
|
+
}
|
|
63645
64524
|
function addBarChart(chart) {
|
|
63646
64525
|
// gapWitdh and overlap that define the space between clusters (in %) and the overlap between datasets (from -100: completely scattered to 100, completely overlapped)
|
|
63647
64526
|
// see gapWidth : https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_gapWidth_topic_ID0EFVEQB.html#topic_ID0EFVEQB
|
|
@@ -63649,46 +64528,72 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63649
64528
|
//
|
|
63650
64529
|
// overlap and gapWitdh seems to be by default at -20 and 20 in chart.js.
|
|
63651
64530
|
// 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
|
|
64531
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64532
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64533
|
+
const leftDataSetsNodes = [];
|
|
64534
|
+
const rightDataSetsNodes = [];
|
|
63654
64535
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
63655
64536
|
const color = toXlsxHexColor(colors.next());
|
|
63656
64537
|
const dataShapeProperty = shapeProperty({
|
|
63657
64538
|
backgroundColor: color,
|
|
63658
64539
|
line: { color },
|
|
63659
64540
|
});
|
|
63660
|
-
|
|
64541
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63661
64542
|
<c:ser>
|
|
63662
64543
|
<c:idx val="${dsIndex}"/>
|
|
63663
64544
|
<c:order val="${dsIndex}"/>
|
|
63664
|
-
${
|
|
64545
|
+
${extractDataSetLabel(dataset.label)}
|
|
63665
64546
|
${dataShapeProperty}
|
|
63666
64547
|
${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
63667
64548
|
<c:val> <!-- x-coordinate values -->
|
|
63668
64549
|
${numberRef(dataset.range)}
|
|
63669
64550
|
</c:val>
|
|
63670
64551
|
</c:ser>
|
|
63671
|
-
|
|
64552
|
+
`;
|
|
64553
|
+
if (dataset.rightYAxis) {
|
|
64554
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64555
|
+
}
|
|
64556
|
+
else {
|
|
64557
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64558
|
+
}
|
|
63672
64559
|
}
|
|
63673
|
-
// Excel does not support this feature
|
|
63674
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63675
64560
|
const grouping = chart.stacked ? "stacked" : "clustered";
|
|
63676
64561
|
const overlap = chart.stacked ? 100 : -20;
|
|
63677
64562
|
return escapeXml /*xml*/ `
|
|
63678
|
-
|
|
63679
|
-
|
|
63680
|
-
|
|
63681
|
-
|
|
63682
|
-
|
|
63683
|
-
|
|
63684
|
-
|
|
63685
|
-
|
|
63686
|
-
|
|
63687
|
-
|
|
63688
|
-
|
|
63689
|
-
|
|
63690
|
-
|
|
63691
|
-
|
|
64563
|
+
${leftDataSetsNodes.length
|
|
64564
|
+
? escapeXml /*xml*/ `
|
|
64565
|
+
<c:barChart>
|
|
64566
|
+
<c:barDir val="col"/>
|
|
64567
|
+
<c:grouping val="${grouping}"/>
|
|
64568
|
+
<c:overlap val="${overlap}"/>
|
|
64569
|
+
<c:gapWidth val="70"/>
|
|
64570
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64571
|
+
<c:varyColors val="0"/>
|
|
64572
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64573
|
+
<c:axId val="${catAxId}" />
|
|
64574
|
+
<c:axId val="${valAxId}" />
|
|
64575
|
+
</c:barChart>
|
|
64576
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64577
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64578
|
+
`
|
|
64579
|
+
: ""}
|
|
64580
|
+
${rightDataSetsNodes.length
|
|
64581
|
+
? escapeXml /*xml*/ `
|
|
64582
|
+
<c:barChart>
|
|
64583
|
+
<c:barDir val="col"/>
|
|
64584
|
+
<c:grouping val="${grouping}"/>
|
|
64585
|
+
<c:overlap val="${overlap}"/>
|
|
64586
|
+
<c:gapWidth val="70"/>
|
|
64587
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64588
|
+
<c:varyColors val="0"/>
|
|
64589
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64590
|
+
<c:axId val="${catAxId + 1}" />
|
|
64591
|
+
<c:axId val="${valAxId + 1}" />
|
|
64592
|
+
</c:barChart>
|
|
64593
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64594
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64595
|
+
`
|
|
64596
|
+
: ""}`;
|
|
63692
64597
|
}
|
|
63693
64598
|
function addComboChart(chart) {
|
|
63694
64599
|
// 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 +64602,38 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63697
64602
|
//
|
|
63698
64603
|
// overlap and gapWitdh seems to be by default at -20 and 20 in chart.js.
|
|
63699
64604
|
// 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
|
-
|
|
64605
|
+
const dataSets = chart.dataSets;
|
|
64606
|
+
const dataSetsColors = dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64607
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64608
|
+
let dataSet = dataSets[0];
|
|
64609
|
+
const firstColor = toXlsxHexColor(colors.next());
|
|
64610
|
+
const useRightAxisForBarSerie = dataSet.rightYAxis ?? false;
|
|
64611
|
+
const barDataSetNode = escapeXml /*xml*/ `
|
|
64612
|
+
<c:ser>
|
|
64613
|
+
<c:idx val="0"/>
|
|
64614
|
+
<c:order val="0"/>
|
|
64615
|
+
${extractDataSetLabel(dataSet.label)}
|
|
64616
|
+
${shapeProperty({
|
|
64617
|
+
backgroundColor: firstColor,
|
|
64618
|
+
line: { color: firstColor },
|
|
64619
|
+
})}
|
|
64620
|
+
${chart.labelRange ? escapeXml /*xml*/ `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
64621
|
+
<!-- x-coordinate values -->
|
|
64622
|
+
<c:val>
|
|
64623
|
+
${numberRef(dataSet.range)}
|
|
64624
|
+
</c:val>
|
|
64625
|
+
</c:ser>
|
|
64626
|
+
`;
|
|
64627
|
+
const leftDataSetsNodes = [];
|
|
64628
|
+
const rightDataSetsNodes = [];
|
|
64629
|
+
for (let dsIndex = 1; dsIndex < dataSets.length; dsIndex++) {
|
|
64630
|
+
dataSet = dataSets[dsIndex];
|
|
63703
64631
|
const color = toXlsxHexColor(colors.next());
|
|
63704
64632
|
const dataShapeProperty = shapeProperty({
|
|
63705
64633
|
backgroundColor: color,
|
|
63706
64634
|
line: { color },
|
|
63707
64635
|
});
|
|
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*/ `
|
|
64636
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63722
64637
|
<c:ser>
|
|
63723
64638
|
<c:idx val="${dsIndex}"/>
|
|
63724
64639
|
<c:order val="${dsIndex}"/>
|
|
@@ -63726,18 +64641,24 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63726
64641
|
<c:marker>
|
|
63727
64642
|
<c:symbol val="circle" />
|
|
63728
64643
|
<c:size val="5"/>
|
|
64644
|
+
${dataShapeProperty}
|
|
63729
64645
|
</c:marker>
|
|
63730
|
-
${
|
|
64646
|
+
${extractDataSetLabel(dataSet.label)}
|
|
63731
64647
|
${dataShapeProperty}
|
|
63732
|
-
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
63733
|
-
|
|
63734
|
-
|
|
64648
|
+
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
64649
|
+
<!-- x-coordinate values -->
|
|
64650
|
+
<c:val>
|
|
64651
|
+
${numberRef(dataSet.range)}
|
|
63735
64652
|
</c:val>
|
|
63736
64653
|
</c:ser>
|
|
63737
|
-
|
|
64654
|
+
`;
|
|
64655
|
+
if (dataSet.rightYAxis) {
|
|
64656
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64657
|
+
}
|
|
64658
|
+
else {
|
|
64659
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64660
|
+
}
|
|
63738
64661
|
}
|
|
63739
|
-
// Excel does not support this feature
|
|
63740
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63741
64662
|
const overlap = chart.stacked ? 100 : -20;
|
|
63742
64663
|
return escapeXml /*xml*/ `
|
|
63743
64664
|
<c:barChart>
|
|
@@ -63747,34 +64668,63 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63747
64668
|
<c:gapWidth val="70"/>
|
|
63748
64669
|
<!-- each data marker in the series does not have a different color -->
|
|
63749
64670
|
<c:varyColors val="0"/>
|
|
63750
|
-
${
|
|
63751
|
-
<c:axId val="${catAxId}" />
|
|
63752
|
-
<c:axId val="${valAxId}" />
|
|
64671
|
+
${barDataSetNode}
|
|
64672
|
+
<c:axId val="${catAxId + (useRightAxisForBarSerie ? 1 : 0)}" />
|
|
64673
|
+
<c:axId val="${valAxId + (useRightAxisForBarSerie ? 1 : 0)}" />
|
|
63753
64674
|
</c:barChart>
|
|
63754
|
-
|
|
63755
|
-
|
|
63756
|
-
|
|
63757
|
-
|
|
63758
|
-
|
|
63759
|
-
|
|
63760
|
-
|
|
63761
|
-
|
|
63762
|
-
|
|
63763
|
-
|
|
64675
|
+
${leftDataSetsNodes.length
|
|
64676
|
+
? escapeXml /*xml*/ `
|
|
64677
|
+
<c:lineChart>
|
|
64678
|
+
<c:grouping val="standard"/>
|
|
64679
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64680
|
+
<c:varyColors val="0"/>
|
|
64681
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64682
|
+
<c:axId val="${catAxId}" />
|
|
64683
|
+
<c:axId val="${valAxId}" />
|
|
64684
|
+
</c:lineChart>
|
|
64685
|
+
`
|
|
64686
|
+
: ""}
|
|
64687
|
+
${rightDataSetsNodes.length
|
|
64688
|
+
? escapeXml /*xml*/ `
|
|
64689
|
+
<c:lineChart>
|
|
64690
|
+
<c:grouping val="standard"/>
|
|
64691
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64692
|
+
<c:varyColors val="0"/>
|
|
64693
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64694
|
+
<c:axId val="${catAxId + 1}" />
|
|
64695
|
+
<c:axId val="${valAxId + 1}" />
|
|
64696
|
+
</c:lineChart>
|
|
64697
|
+
`
|
|
64698
|
+
: ""}
|
|
64699
|
+
${!useRightAxisForBarSerie || leftDataSetsNodes.length
|
|
64700
|
+
? escapeXml /*xml*/ `
|
|
64701
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64702
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64703
|
+
`
|
|
64704
|
+
: ""}
|
|
64705
|
+
${useRightAxisForBarSerie || rightDataSetsNodes.length
|
|
64706
|
+
? escapeXml /*xml*/ `
|
|
64707
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length || !useRightAxisForBarSerie ? 1 : 0)}
|
|
64708
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64709
|
+
`
|
|
64710
|
+
: ""}
|
|
63764
64711
|
`;
|
|
63765
64712
|
}
|
|
63766
64713
|
function addLineChart(chart) {
|
|
63767
|
-
const
|
|
63768
|
-
const
|
|
64714
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64715
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64716
|
+
const leftDataSetsNodes = [];
|
|
64717
|
+
const rightDataSetsNodes = [];
|
|
63769
64718
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
64719
|
+
const color = toXlsxHexColor(colors.next());
|
|
63770
64720
|
const dataShapeProperty = shapeProperty({
|
|
63771
64721
|
line: {
|
|
63772
64722
|
width: 2.5,
|
|
63773
64723
|
style: "solid",
|
|
63774
|
-
color
|
|
64724
|
+
color,
|
|
63775
64725
|
},
|
|
63776
64726
|
});
|
|
63777
|
-
|
|
64727
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63778
64728
|
<c:ser>
|
|
63779
64729
|
<c:idx val="${dsIndex}"/>
|
|
63780
64730
|
<c:order val="${dsIndex}"/>
|
|
@@ -63782,37 +64732,63 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63782
64732
|
<c:marker>
|
|
63783
64733
|
<c:symbol val="circle" />
|
|
63784
64734
|
<c:size val="5"/>
|
|
64735
|
+
${shapeProperty({ backgroundColor: color, line: { color } })}
|
|
63785
64736
|
</c:marker>
|
|
63786
|
-
${
|
|
64737
|
+
${extractDataSetLabel(dataset.label)}
|
|
63787
64738
|
${dataShapeProperty}
|
|
63788
64739
|
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""} <!-- x-coordinate values -->
|
|
63789
64740
|
<c:val> <!-- x-coordinate values -->
|
|
63790
64741
|
${numberRef(dataset.range)}
|
|
63791
64742
|
</c:val>
|
|
63792
64743
|
</c:ser>
|
|
63793
|
-
|
|
64744
|
+
`;
|
|
64745
|
+
if (dataset.rightYAxis) {
|
|
64746
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64747
|
+
}
|
|
64748
|
+
else {
|
|
64749
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64750
|
+
}
|
|
63794
64751
|
}
|
|
63795
|
-
// Excel does not support this feature
|
|
63796
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63797
64752
|
const grouping = chart.stacked ? "stacked" : "standard";
|
|
63798
64753
|
return escapeXml /*xml*/ `
|
|
63799
|
-
|
|
63800
|
-
|
|
63801
|
-
|
|
63802
|
-
|
|
63803
|
-
|
|
63804
|
-
|
|
63805
|
-
|
|
63806
|
-
|
|
63807
|
-
|
|
63808
|
-
|
|
64754
|
+
${leftDataSetsNodes.length
|
|
64755
|
+
? escapeXml /*xml*/ `
|
|
64756
|
+
<c:lineChart>
|
|
64757
|
+
<c:grouping val="${grouping}"/>
|
|
64758
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64759
|
+
<c:varyColors val="0"/>
|
|
64760
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64761
|
+
<c:axId val="${catAxId}" />
|
|
64762
|
+
<c:axId val="${valAxId}" />
|
|
64763
|
+
</c:lineChart>
|
|
64764
|
+
${addAx("b", "c:catAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64765
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64766
|
+
`
|
|
64767
|
+
: ""}
|
|
64768
|
+
${rightDataSetsNodes.length
|
|
64769
|
+
? escapeXml /*xml*/ `
|
|
64770
|
+
<c:lineChart>
|
|
64771
|
+
<c:grouping val="${grouping}"/>
|
|
64772
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64773
|
+
<c:varyColors val="0"/>
|
|
64774
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64775
|
+
<c:axId val="${catAxId + 1}" />
|
|
64776
|
+
<c:axId val="${valAxId + 1}" />
|
|
64777
|
+
</c:lineChart>
|
|
64778
|
+
${addAx("b", "c:catAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64779
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64780
|
+
`
|
|
64781
|
+
: ""}
|
|
63809
64782
|
`;
|
|
63810
64783
|
}
|
|
63811
64784
|
function addScatterChart(chart) {
|
|
63812
|
-
const
|
|
63813
|
-
const
|
|
64785
|
+
const dataSetsColors = chart.dataSets.map((ds) => ds.backgroundColor ?? "");
|
|
64786
|
+
const colors = new ColorGenerator(dataSetsColors);
|
|
64787
|
+
const leftDataSetsNodes = [];
|
|
64788
|
+
const rightDataSetsNodes = [];
|
|
63814
64789
|
for (const [dsIndex, dataset] of Object.entries(chart.dataSets)) {
|
|
63815
|
-
|
|
64790
|
+
const color = toXlsxHexColor(colors.next());
|
|
64791
|
+
const dataSetNode = escapeXml /*xml*/ `
|
|
63816
64792
|
<c:ser>
|
|
63817
64793
|
<c:idx val="${dsIndex}"/>
|
|
63818
64794
|
<c:order val="${dsIndex}"/>
|
|
@@ -63827,8 +64803,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63827
64803
|
<c:marker>
|
|
63828
64804
|
<c:symbol val="circle" />
|
|
63829
64805
|
<c:size val="5"/>
|
|
63830
|
-
${shapeProperty({ backgroundColor:
|
|
64806
|
+
${shapeProperty({ backgroundColor: color, line: { color } })}
|
|
63831
64807
|
</c:marker>
|
|
64808
|
+
${extractDataSetLabel(dataset.label)}
|
|
63832
64809
|
${chart.labelRange
|
|
63833
64810
|
? escapeXml /*xml*/ `<c:xVal> <!-- x-coordinate values -->
|
|
63834
64811
|
${numberRef(chart.labelRange)}
|
|
@@ -63838,24 +64815,46 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63838
64815
|
${numberRef(dataset.range)}
|
|
63839
64816
|
</c:yVal>
|
|
63840
64817
|
</c:ser>
|
|
63841
|
-
|
|
64818
|
+
`;
|
|
64819
|
+
if (dataset.rightYAxis) {
|
|
64820
|
+
rightDataSetsNodes.push(dataSetNode);
|
|
64821
|
+
}
|
|
64822
|
+
else {
|
|
64823
|
+
leftDataSetsNodes.push(dataSetNode);
|
|
64824
|
+
}
|
|
63842
64825
|
}
|
|
63843
|
-
const axisPos = chart.verticalAxisPosition === "left" ? "l" : "r";
|
|
63844
64826
|
return escapeXml /*xml*/ `
|
|
63845
|
-
|
|
63846
|
-
|
|
63847
|
-
<c:
|
|
63848
|
-
|
|
63849
|
-
|
|
63850
|
-
|
|
63851
|
-
|
|
63852
|
-
|
|
63853
|
-
|
|
63854
|
-
|
|
63855
|
-
|
|
64827
|
+
${leftDataSetsNodes.length
|
|
64828
|
+
? escapeXml /*xml*/ `
|
|
64829
|
+
<c:scatterChart>
|
|
64830
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64831
|
+
<c:varyColors val="0"/>
|
|
64832
|
+
<c:scatterStyle val="lineMarker"/>
|
|
64833
|
+
${joinXmlNodes(leftDataSetsNodes)}
|
|
64834
|
+
<c:axId val="${catAxId}" />
|
|
64835
|
+
<c:axId val="${valAxId}" />
|
|
64836
|
+
</c:scatterChart>
|
|
64837
|
+
${addAx("b", "c:valAx", catAxId, valAxId, chart.axesDesign?.x?.title, chart.fontColor)}
|
|
64838
|
+
${addAx("l", "c:valAx", valAxId, catAxId, chart.axesDesign?.y?.title, chart.fontColor)}
|
|
64839
|
+
`
|
|
64840
|
+
: ""}
|
|
64841
|
+
${rightDataSetsNodes.length
|
|
64842
|
+
? escapeXml /*xml*/ `
|
|
64843
|
+
<c:scatterChart>
|
|
64844
|
+
<!-- each data marker in the series does not have a different color -->
|
|
64845
|
+
<c:varyColors val="0"/>
|
|
64846
|
+
<c:scatterStyle val="lineMarker"/>
|
|
64847
|
+
${joinXmlNodes(rightDataSetsNodes)}
|
|
64848
|
+
<c:axId val="${catAxId + 1}" />
|
|
64849
|
+
<c:axId val="${valAxId + 1}" />
|
|
64850
|
+
</c:scatterChart>
|
|
64851
|
+
${addAx("b", "c:valAx", catAxId + 1, valAxId + 1, chart.axesDesign?.x?.title, chart.fontColor, leftDataSetsNodes.length ? 1 : 0)}
|
|
64852
|
+
${addAx("r", "c:valAx", valAxId + 1, catAxId + 1, chart.axesDesign?.y1?.title, chart.fontColor)}
|
|
64853
|
+
`
|
|
64854
|
+
: ""}`;
|
|
63856
64855
|
}
|
|
63857
64856
|
function addDoughnutChart(chart, chartSheetIndex, data, { holeSize } = { holeSize: 50 }) {
|
|
63858
|
-
const colors = new
|
|
64857
|
+
const colors = new ColorGenerator();
|
|
63859
64858
|
const maxLength = largeMax(chart.dataSets.map((ds) => getRangeSize(ds.range, chartSheetIndex, data)));
|
|
63860
64859
|
const doughnutColors = range(0, maxLength).map(() => toXlsxHexColor(colors.next()));
|
|
63861
64860
|
const dataSetsNodes = [];
|
|
@@ -63879,7 +64878,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63879
64878
|
<c:ser>
|
|
63880
64879
|
<c:idx val="${dsIndex}"/>
|
|
63881
64880
|
<c:order val="${dsIndex}"/>
|
|
63882
|
-
${
|
|
64881
|
+
${extractDataSetLabel(dataset.label)}
|
|
63883
64882
|
${joinXmlNodes(dataPoints)}
|
|
63884
64883
|
${insertDataLabels({ showLeaderLines: true })}
|
|
63885
64884
|
${chart.labelRange ? escapeXml `<c:cat>${stringRef(chart.labelRange)}</c:cat>` : ""}
|
|
@@ -63911,14 +64910,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63911
64910
|
</dLbls>
|
|
63912
64911
|
`;
|
|
63913
64912
|
}
|
|
63914
|
-
function addAx(position, axisName, axId, crossAxId,
|
|
64913
|
+
function addAx(position, axisName, axId, crossAxId, title, defaultFontColor, deleteAxis = 0) {
|
|
63915
64914
|
// Each Axis present inside a graph needs to be identified by an unsigned integer in order to be referenced by its crossAxis.
|
|
63916
64915
|
// I.e. x-axis, will reference y-axis and vice-versa.
|
|
64916
|
+
const color = title?.color ? toXlsxHexColor(title.color) : defaultFontColor;
|
|
63917
64917
|
return escapeXml /*xml*/ `
|
|
63918
64918
|
<${axisName}>
|
|
63919
64919
|
<c:axId val="${axId}"/>
|
|
63920
64920
|
<c:crossAx val="${crossAxId}"/> <!-- reference to the other axe of the chart -->
|
|
63921
|
-
<c:
|
|
64921
|
+
<c:crosses val="${position === "b" || position === "l" ? "min" : "max"}"/>
|
|
64922
|
+
<c:delete val="${deleteAxis}"/> <!-- by default, axis are not displayed -->
|
|
63922
64923
|
<c:scaling>
|
|
63923
64924
|
<c:orientation val="minMax" />
|
|
63924
64925
|
</c:scaling>
|
|
@@ -63928,9 +64929,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
63928
64929
|
<c:minorTickMark val="none" />
|
|
63929
64930
|
<c:numFmt formatCode="General" sourceLinked="1" />
|
|
63930
64931
|
<c:title>
|
|
63931
|
-
${insertText("")}
|
|
64932
|
+
${insertText(title?.text ?? "", color, 10, title)}
|
|
63932
64933
|
</c:title>
|
|
63933
|
-
${insertTextProperties(10,
|
|
64934
|
+
${insertTextProperties(10, defaultFontColor)}
|
|
63934
64935
|
</${axisName}>
|
|
63935
64936
|
<!-- <tickLblPos/> omitted -->
|
|
63936
64937
|
`;
|
|
@@ -64811,7 +65812,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64811
65812
|
let cellNode = escapeXml ``;
|
|
64812
65813
|
// Either formula or static value inside the cell
|
|
64813
65814
|
if (cell.isFormula) {
|
|
64814
|
-
|
|
65815
|
+
const res = addFormula(cell);
|
|
65816
|
+
if (!res) {
|
|
65817
|
+
continue;
|
|
65818
|
+
}
|
|
65819
|
+
({ attrs: additionalAttrs, node: cellNode } = res);
|
|
64815
65820
|
}
|
|
64816
65821
|
else if (cell.content && isMarkdownLink(cell.content)) {
|
|
64817
65822
|
const { label } = parseMarkdownLink(cell.content);
|
|
@@ -65817,13 +66822,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65817
66822
|
UuidGenerator,
|
|
65818
66823
|
formatValue,
|
|
65819
66824
|
createCurrencyFormat,
|
|
66825
|
+
ColorGenerator,
|
|
65820
66826
|
computeTextWidth,
|
|
65821
66827
|
createEmptyWorkbookData,
|
|
65822
66828
|
createEmptySheet,
|
|
65823
66829
|
createEmptyExcelSheet,
|
|
65824
66830
|
getDefaultChartJsRuntime,
|
|
65825
66831
|
chartFontColor,
|
|
65826
|
-
|
|
66832
|
+
getChartAxisTitleRuntime,
|
|
65827
66833
|
getFillingMode,
|
|
65828
66834
|
rgbaToHex,
|
|
65829
66835
|
colorToRGBA,
|
|
@@ -65880,9 +66886,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65880
66886
|
GridOverlay,
|
|
65881
66887
|
ScorecardChart,
|
|
65882
66888
|
LineConfigPanel,
|
|
65883
|
-
GenericChartDesignPanel,
|
|
65884
66889
|
BarConfigPanel,
|
|
66890
|
+
PieChartDesignPanel,
|
|
65885
66891
|
GenericChartConfigPanel,
|
|
66892
|
+
ChartWithAxisDesignPanel,
|
|
65886
66893
|
GaugeChartConfigPanel,
|
|
65887
66894
|
GaugeChartDesignPanel,
|
|
65888
66895
|
ScorecardChartConfigPanel,
|
|
@@ -65981,9 +66988,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
65981
66988
|
exports.tokenize = tokenize;
|
|
65982
66989
|
|
|
65983
66990
|
|
|
65984
|
-
__info__.version = "17.3.
|
|
65985
|
-
__info__.date = "2024-
|
|
65986
|
-
__info__.hash = "
|
|
66991
|
+
__info__.version = "17.3.1";
|
|
66992
|
+
__info__.date = "2024-06-03T15:28:03.284Z";
|
|
66993
|
+
__info__.hash = "605d098";
|
|
65987
66994
|
|
|
65988
66995
|
|
|
65989
66996
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|