@odoo/o-spreadsheet 18.5.0-alpha.6 → 18.5.0-alpha.8
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 +2145 -623
- package/dist/o-spreadsheet.d.ts +486 -291
- package/dist/o-spreadsheet.esm.js +2145 -623
- package/dist/o-spreadsheet.iife.js +2145 -623
- package/dist/o-spreadsheet.iife.min.js +491 -490
- package/dist/o_spreadsheet.xml +229 -41
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file is generated by o-spreadsheet build tools. Do not edit it.
|
|
4
4
|
* @see https://github.com/odoo/o-spreadsheet
|
|
5
|
-
* @version 18.5.0-alpha.
|
|
6
|
-
* @date 2025-08-
|
|
7
|
-
* @hash
|
|
5
|
+
* @version 18.5.0-alpha.8
|
|
6
|
+
* @date 2025-08-18T08:17:58.775Z
|
|
7
|
+
* @hash 994f1cb
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
(function (exports, owl) {
|
|
@@ -199,6 +199,7 @@
|
|
|
199
199
|
const CHART_PADDING_TOP = 15;
|
|
200
200
|
const CHART_TITLE_FONT_SIZE = 16;
|
|
201
201
|
const CHART_AXIS_TITLE_FONT_SIZE = 12;
|
|
202
|
+
const MASTER_CHART_HEIGHT = 60;
|
|
202
203
|
const SCORECARD_CHART_TITLE_FONT_SIZE = 14;
|
|
203
204
|
const PIVOT_TOKEN_COLOR = "#F28C28";
|
|
204
205
|
// Color picker defaults as upper case HEX to match `toHex`helper
|
|
@@ -414,6 +415,7 @@
|
|
|
414
415
|
};
|
|
415
416
|
const PIVOT_INDENT = 15;
|
|
416
417
|
const PIVOT_COLLAPSE_ICON_SIZE = 12;
|
|
418
|
+
const PIVOT_MAX_NUMBER_OF_CELLS = 1e5;
|
|
417
419
|
const DEFAULT_CURRENCY = {
|
|
418
420
|
symbol: "$",
|
|
419
421
|
position: "before",
|
|
@@ -2656,6 +2658,7 @@
|
|
|
2656
2658
|
"SET_FORMULA_VISIBILITY",
|
|
2657
2659
|
"UPDATE_FILTER",
|
|
2658
2660
|
"UPDATE_CHART",
|
|
2661
|
+
"UPDATE_CAROUSEL_ACTIVE_ITEM",
|
|
2659
2662
|
]);
|
|
2660
2663
|
const coreTypes = new Set([
|
|
2661
2664
|
/** CELLS */
|
|
@@ -2698,6 +2701,8 @@
|
|
|
2698
2701
|
"CREATE_FIGURE",
|
|
2699
2702
|
"DELETE_FIGURE",
|
|
2700
2703
|
"UPDATE_FIGURE",
|
|
2704
|
+
"CREATE_CAROUSEL",
|
|
2705
|
+
"UPDATE_CAROUSEL",
|
|
2701
2706
|
/** FORMATTING */
|
|
2702
2707
|
"SET_FORMATTING",
|
|
2703
2708
|
"CLEAR_FORMATTING",
|
|
@@ -2707,6 +2712,7 @@
|
|
|
2707
2712
|
/** CHART */
|
|
2708
2713
|
"CREATE_CHART",
|
|
2709
2714
|
"UPDATE_CHART",
|
|
2715
|
+
"DELETE_CHART",
|
|
2710
2716
|
/** FILTERS */
|
|
2711
2717
|
"CREATE_TABLE",
|
|
2712
2718
|
"REMOVE_TABLE",
|
|
@@ -2901,6 +2907,7 @@
|
|
|
2901
2907
|
CommandResult["InvalidColor"] = "InvalidColor";
|
|
2902
2908
|
CommandResult["InvalidPivotDataSet"] = "InvalidPivotDataSet";
|
|
2903
2909
|
CommandResult["InvalidPivotCustomField"] = "InvalidPivotCustomField";
|
|
2910
|
+
CommandResult["MissingFigureArguments"] = "MissingFigureArguments";
|
|
2904
2911
|
})(exports.CommandResult || (exports.CommandResult = {}));
|
|
2905
2912
|
|
|
2906
2913
|
const availableConditionalFormatOperators = new Set([
|
|
@@ -9221,7 +9228,7 @@
|
|
|
9221
9228
|
return;
|
|
9222
9229
|
}
|
|
9223
9230
|
const copiedFigure = { ...figure };
|
|
9224
|
-
const chart = this.getters.
|
|
9231
|
+
const chart = this.getters.getChartFromFigureId(data.figureId);
|
|
9225
9232
|
if (!chart) {
|
|
9226
9233
|
throw new Error(`No chart for the given id: ${data.figureId}`);
|
|
9227
9234
|
}
|
|
@@ -9257,6 +9264,7 @@
|
|
|
9257
9264
|
}
|
|
9258
9265
|
this.dispatch("CREATE_CHART", {
|
|
9259
9266
|
figureId,
|
|
9267
|
+
chartId: figureId,
|
|
9260
9268
|
sheetId,
|
|
9261
9269
|
definition: copy.getDefinition(),
|
|
9262
9270
|
col,
|
|
@@ -19029,6 +19037,211 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19029
19037
|
XOR: XOR
|
|
19030
19038
|
});
|
|
19031
19039
|
|
|
19040
|
+
const CfTerms = {
|
|
19041
|
+
Errors: {
|
|
19042
|
+
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid"),
|
|
19043
|
+
["FirstArgMissing" /* CommandResult.FirstArgMissing */]: _t("The argument is missing. Please provide a value"),
|
|
19044
|
+
["SecondArgMissing" /* CommandResult.SecondArgMissing */]: _t("The second argument is missing. Please provide a value"),
|
|
19045
|
+
["MinNaN" /* CommandResult.MinNaN */]: _t("The minpoint must be a number"),
|
|
19046
|
+
["MidNaN" /* CommandResult.MidNaN */]: _t("The midpoint must be a number"),
|
|
19047
|
+
["MaxNaN" /* CommandResult.MaxNaN */]: _t("The maxpoint must be a number"),
|
|
19048
|
+
["ValueUpperInflectionNaN" /* CommandResult.ValueUpperInflectionNaN */]: _t("The first value must be a number"),
|
|
19049
|
+
["ValueLowerInflectionNaN" /* CommandResult.ValueLowerInflectionNaN */]: _t("The second value must be a number"),
|
|
19050
|
+
["MinBiggerThanMax" /* CommandResult.MinBiggerThanMax */]: _t("Minimum must be smaller then Maximum"),
|
|
19051
|
+
["MinBiggerThanMid" /* CommandResult.MinBiggerThanMid */]: _t("Minimum must be smaller then Midpoint"),
|
|
19052
|
+
["MidBiggerThanMax" /* CommandResult.MidBiggerThanMax */]: _t("Midpoint must be smaller then Maximum"),
|
|
19053
|
+
["LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */]: _t("Lower inflection point must be smaller than upper inflection point"),
|
|
19054
|
+
["MinInvalidFormula" /* CommandResult.MinInvalidFormula */]: _t("Invalid Minpoint formula"),
|
|
19055
|
+
["MaxInvalidFormula" /* CommandResult.MaxInvalidFormula */]: _t("Invalid Maxpoint formula"),
|
|
19056
|
+
["MidInvalidFormula" /* CommandResult.MidInvalidFormula */]: _t("Invalid Midpoint formula"),
|
|
19057
|
+
["ValueUpperInvalidFormula" /* CommandResult.ValueUpperInvalidFormula */]: _t("Invalid upper inflection point formula"),
|
|
19058
|
+
["ValueLowerInvalidFormula" /* CommandResult.ValueLowerInvalidFormula */]: _t("Invalid lower inflection point formula"),
|
|
19059
|
+
["EmptyRange" /* CommandResult.EmptyRange */]: _t("A range needs to be defined"),
|
|
19060
|
+
["ValueCellIsInvalidFormula" /* CommandResult.ValueCellIsInvalidFormula */]: _t("At least one of the provided values is an invalid formula"),
|
|
19061
|
+
Unexpected: _t("The rule is invalid for an unknown reason"),
|
|
19062
|
+
},
|
|
19063
|
+
ColorScale: _t("Color scale"),
|
|
19064
|
+
IconSet: _t("Icon set"),
|
|
19065
|
+
DataBar: _t("Data bar"),
|
|
19066
|
+
};
|
|
19067
|
+
const ChartTerms = {
|
|
19068
|
+
Series: _t("Series"),
|
|
19069
|
+
BackgroundColor: _t("Background color"),
|
|
19070
|
+
StackedBarChart: _t("Stacked bar chart"),
|
|
19071
|
+
StackedLineChart: _t("Stacked line chart"),
|
|
19072
|
+
StackedAreaChart: _t("Stacked area chart"),
|
|
19073
|
+
StackedColumnChart: _t("Stacked column chart"),
|
|
19074
|
+
CumulativeData: _t("Cumulative data"),
|
|
19075
|
+
TreatLabelsAsText: _t("Treat labels as text"),
|
|
19076
|
+
AggregatedChart: _t("Aggregate"),
|
|
19077
|
+
Errors: {
|
|
19078
|
+
Unexpected: _t("The chart definition is invalid for an unknown reason"),
|
|
19079
|
+
// BASIC CHART ERRORS (LINE | BAR | PIE)
|
|
19080
|
+
["InvalidDataSet" /* CommandResult.InvalidDataSet */]: _t("The dataset is invalid"),
|
|
19081
|
+
["InvalidLabelRange" /* CommandResult.InvalidLabelRange */]: _t("Labels are invalid"),
|
|
19082
|
+
// SCORECARD CHART ERRORS
|
|
19083
|
+
["InvalidScorecardKeyValue" /* CommandResult.InvalidScorecardKeyValue */]: _t("The key value is invalid"),
|
|
19084
|
+
["InvalidScorecardBaseline" /* CommandResult.InvalidScorecardBaseline */]: _t("The baseline value is invalid"),
|
|
19085
|
+
// GAUGE CHART ERRORS
|
|
19086
|
+
["InvalidGaugeDataRange" /* CommandResult.InvalidGaugeDataRange */]: _t("The data range is invalid"),
|
|
19087
|
+
["EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */]: _t("A minimum range limit value is needed"),
|
|
19088
|
+
["GaugeRangeMinNaN" /* CommandResult.GaugeRangeMinNaN */]: _t("The minimum range limit value must be a number"),
|
|
19089
|
+
["EmptyGaugeRangeMax" /* CommandResult.EmptyGaugeRangeMax */]: _t("A maximum range limit value is needed"),
|
|
19090
|
+
["GaugeRangeMaxNaN" /* CommandResult.GaugeRangeMaxNaN */]: _t("The maximum range limit value must be a number"),
|
|
19091
|
+
["GaugeLowerInflectionPointNaN" /* CommandResult.GaugeLowerInflectionPointNaN */]: _t("The lower inflection point value must be a number"),
|
|
19092
|
+
["GaugeUpperInflectionPointNaN" /* CommandResult.GaugeUpperInflectionPointNaN */]: _t("The upper inflection point value must be a number"),
|
|
19093
|
+
},
|
|
19094
|
+
GeoChart: {
|
|
19095
|
+
ColorScales: {
|
|
19096
|
+
blues: _t("Blues"),
|
|
19097
|
+
cividis: _t("Cividis"),
|
|
19098
|
+
greens: _t("Greens"),
|
|
19099
|
+
greys: _t("Greys"),
|
|
19100
|
+
oranges: _t("Oranges"),
|
|
19101
|
+
purples: _t("Purples"),
|
|
19102
|
+
rainbow: _t("Rainbow"),
|
|
19103
|
+
reds: _t("Reds"),
|
|
19104
|
+
viridis: _t("Viridis"),
|
|
19105
|
+
},
|
|
19106
|
+
},
|
|
19107
|
+
};
|
|
19108
|
+
const CustomCurrencyTerms = {
|
|
19109
|
+
Custom: _t("Custom"),
|
|
19110
|
+
};
|
|
19111
|
+
const MergeErrorMessage = _t("Merged cells are preventing this operation. Unmerge those cells and try again.");
|
|
19112
|
+
const SplitToColumnsTerms = {
|
|
19113
|
+
Errors: {
|
|
19114
|
+
Unexpected: _t("Cannot split the selection for an unknown reason"),
|
|
19115
|
+
["NoSplitSeparatorInSelection" /* CommandResult.NoSplitSeparatorInSelection */]: _t("There is no match for the selected separator in the selection"),
|
|
19116
|
+
["MoreThanOneColumnSelected" /* CommandResult.MoreThanOneColumnSelected */]: _t("Only a selection from a single column can be split"),
|
|
19117
|
+
["SplitWillOverwriteContent" /* CommandResult.SplitWillOverwriteContent */]: _t("Splitting will overwrite existing content"),
|
|
19118
|
+
},
|
|
19119
|
+
};
|
|
19120
|
+
const RemoveDuplicateTerms = {
|
|
19121
|
+
Errors: {
|
|
19122
|
+
Unexpected: _t("Cannot remove duplicates for an unknown reason"),
|
|
19123
|
+
["MoreThanOneRangeSelected" /* CommandResult.MoreThanOneRangeSelected */]: _t("Please select only one range of cells"),
|
|
19124
|
+
["EmptyTarget" /* CommandResult.EmptyTarget */]: _t("Please select a range of cells containing values."),
|
|
19125
|
+
["NoColumnsProvided" /* CommandResult.NoColumnsProvided */]: _t("Please select at latest one column to analyze."),
|
|
19126
|
+
//TODO: Remove it when accept to copy and paste merge cells
|
|
19127
|
+
["WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */]: _t("This operation is not possible due to a merge. Please remove the merges first than try again."),
|
|
19128
|
+
},
|
|
19129
|
+
};
|
|
19130
|
+
const DVTerms = {
|
|
19131
|
+
DateIs: {
|
|
19132
|
+
today: _t("today"),
|
|
19133
|
+
yesterday: _t("yesterday"),
|
|
19134
|
+
tomorrow: _t("tomorrow"),
|
|
19135
|
+
lastWeek: _t("in the past week"),
|
|
19136
|
+
lastMonth: _t("in the past month"),
|
|
19137
|
+
lastYear: _t("in the past year"),
|
|
19138
|
+
},
|
|
19139
|
+
DateIsBefore: {
|
|
19140
|
+
today: _t("today"),
|
|
19141
|
+
yesterday: _t("yesterday"),
|
|
19142
|
+
tomorrow: _t("tomorrow"),
|
|
19143
|
+
lastWeek: _t("one week ago"),
|
|
19144
|
+
lastMonth: _t("one month ago"),
|
|
19145
|
+
lastYear: _t("one year ago"),
|
|
19146
|
+
},
|
|
19147
|
+
CriterionError: {
|
|
19148
|
+
notEmptyValue: _t("The value must not be empty"),
|
|
19149
|
+
numberValue: _t("The value must be a number"),
|
|
19150
|
+
dateValue: _t("The value must be a date"),
|
|
19151
|
+
validRange: _t("The value must be a valid range"),
|
|
19152
|
+
validFormula: _t("The formula must be valid"),
|
|
19153
|
+
},
|
|
19154
|
+
Errors: {
|
|
19155
|
+
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid."),
|
|
19156
|
+
["InvalidDataValidationCriterionValue" /* CommandResult.InvalidDataValidationCriterionValue */]: _t("One or more of the provided criteria values are invalid. Please review and correct them."),
|
|
19157
|
+
["InvalidNumberOfCriterionValues" /* CommandResult.InvalidNumberOfCriterionValues */]: _t("One or more of the provided criteria values are missing."),
|
|
19158
|
+
Unexpected: _t("The rule is invalid for an unknown reason."),
|
|
19159
|
+
},
|
|
19160
|
+
};
|
|
19161
|
+
const TableTerms = {
|
|
19162
|
+
Errors: {
|
|
19163
|
+
Unexpected: _t("The table zone is invalid for an unknown reason"),
|
|
19164
|
+
["TableOverlap" /* CommandResult.TableOverlap */]: _t("You cannot create overlapping tables."),
|
|
19165
|
+
["NonContinuousTargets" /* CommandResult.NonContinuousTargets */]: _t("A table can only be created on a continuous selection."),
|
|
19166
|
+
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid"),
|
|
19167
|
+
["TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */]: _t("The range is out of the sheet"),
|
|
19168
|
+
},
|
|
19169
|
+
Checkboxes: {
|
|
19170
|
+
hasFilters: _t("Filter button"),
|
|
19171
|
+
headerRow: _t("Header row(s)"),
|
|
19172
|
+
bandedRows: _t("Banded rows"),
|
|
19173
|
+
firstColumn: _t("First column"),
|
|
19174
|
+
lastColumn: _t("Last column"),
|
|
19175
|
+
bandedColumns: _t("Banded columns"),
|
|
19176
|
+
automaticAutofill: _t("Automatically autofill formulas"),
|
|
19177
|
+
totalRow: _t("Total row"),
|
|
19178
|
+
isDynamic: _t("Auto-adjust to formula result"),
|
|
19179
|
+
},
|
|
19180
|
+
Tooltips: {
|
|
19181
|
+
filterWithoutHeader: _t("Cannot have filters without a header row"),
|
|
19182
|
+
isDynamic: _t("For tables based on array formulas only"),
|
|
19183
|
+
},
|
|
19184
|
+
};
|
|
19185
|
+
const measureDisplayTerms = {
|
|
19186
|
+
labels: {
|
|
19187
|
+
no_calculations: _t("No calculations"),
|
|
19188
|
+
"%_of_grand_total": _t("% of grand total"),
|
|
19189
|
+
"%_of_col_total": _t("% of column total"),
|
|
19190
|
+
"%_of_row_total": _t("% of row total"),
|
|
19191
|
+
"%_of": _t("% of"),
|
|
19192
|
+
"%_of_parent_row_total": _t("% of parent row total"),
|
|
19193
|
+
"%_of_parent_col_total": _t("% of parent column total"),
|
|
19194
|
+
"%_of_parent_total": _t("% of parent total"),
|
|
19195
|
+
difference_from: _t("Difference from"),
|
|
19196
|
+
"%_difference_from": _t("% difference from"),
|
|
19197
|
+
running_total: _t("Running total"),
|
|
19198
|
+
"%_running_total": _t("% Running total"),
|
|
19199
|
+
rank_asc: _t("Rank smallest to largest"),
|
|
19200
|
+
rank_desc: _t("Rank largest to smallest"),
|
|
19201
|
+
index: _t("Index"),
|
|
19202
|
+
},
|
|
19203
|
+
descriptions: {
|
|
19204
|
+
"%_of_grand_total": () => _t("Displayed as % of grand total"),
|
|
19205
|
+
"%_of_col_total": () => _t("Displayed as % of column total"),
|
|
19206
|
+
"%_of_row_total": () => _t("Displayed as % of row total"),
|
|
19207
|
+
"%_of": (field) => _t('Displayed as % of "%s"', field),
|
|
19208
|
+
"%_of_parent_row_total": (field) => _t('Displayed as % of parent row total of "%s"', field),
|
|
19209
|
+
"%_of_parent_col_total": () => _t("Displayed as % of parent column total"),
|
|
19210
|
+
"%_of_parent_total": (field) => _t('Displayed as % of parent "%s" total', field),
|
|
19211
|
+
difference_from: (field) => _t('Displayed as difference from "%s"', field),
|
|
19212
|
+
"%_difference_from": (field) => _t('Displayed as % difference from "%s"', field),
|
|
19213
|
+
running_total: (field) => _t('Displayed as running total based on "%s"', field),
|
|
19214
|
+
"%_running_total": (field) => _t('Displayed as % running total based on "%s"', field),
|
|
19215
|
+
rank_asc: (field) => _t('Displayed as rank from smallest to largest based on "%s"', field),
|
|
19216
|
+
rank_desc: (field) => _t('Displayed as rank largest to smallest based on "%s"', field),
|
|
19217
|
+
index: () => _t("Displayed as index"),
|
|
19218
|
+
},
|
|
19219
|
+
documentation: {
|
|
19220
|
+
no_calculations: _t("Displays the value that is entered in the field."),
|
|
19221
|
+
"%_of_grand_total": _t("Displays values as a percentage of the grand total of all the values or data points in the report."),
|
|
19222
|
+
"%_of_col_total": _t("Displays all the values in each column or series as a percentage of the total for the column or series."),
|
|
19223
|
+
"%_of_row_total": _t("Displays the value in each row or category as a percentage of the total for the row or category."),
|
|
19224
|
+
"%_of": _t("Displays values as a percentage of the value of the Base item in the Base field."),
|
|
19225
|
+
"%_of_parent_row_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item on rows)"),
|
|
19226
|
+
"%_of_parent_col_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item on columns)"),
|
|
19227
|
+
"%_of_parent_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item of the selected Base field)"),
|
|
19228
|
+
difference_from: _t("Displays values as the difference from the value of the Base item in the Base field."),
|
|
19229
|
+
"%_difference_from": _t("Displays values as the percentage difference from the value of the Base item in the Base field."),
|
|
19230
|
+
running_total: _t("Displays the value for successive items in the Base field as a running total."),
|
|
19231
|
+
"%_running_total": _t("Calculates the value as a percentage for successive items in the Base field that are displayed as a running total."),
|
|
19232
|
+
rank_asc: _t("Displays the rank of selected values in a specific field, listing the smallest item in the field as 1, and each larger value with a higher rank value."),
|
|
19233
|
+
rank_desc: _t("Displays the rank of selected values in a specific field, listing the largest item in the field as 1, and each smaller value with a higher rank value."),
|
|
19234
|
+
index: _t("Calculates values as follows:\n((value in cell) x (Grand Total of Grand Totals)) / ((Grand Row Total) x (Grand Column Total))"),
|
|
19235
|
+
},
|
|
19236
|
+
};
|
|
19237
|
+
function getPivotTooBigErrorMessage(numberOfCells, locale) {
|
|
19238
|
+
const formattedNumber = formatValue(numberOfCells, {
|
|
19239
|
+
format: "0,00",
|
|
19240
|
+
locale: locale,
|
|
19241
|
+
});
|
|
19242
|
+
return _t("Oops—this pivot table is quite large (%s cells). Try simplifying it using the side panel.", formattedNumber);
|
|
19243
|
+
}
|
|
19244
|
+
|
|
19032
19245
|
/**
|
|
19033
19246
|
* Get the pivot ID from the formula pivot ID.
|
|
19034
19247
|
*/
|
|
@@ -19639,6 +19852,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19639
19852
|
return error;
|
|
19640
19853
|
}
|
|
19641
19854
|
const table = pivot.getCollapsedTableStructure();
|
|
19855
|
+
if (table.numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) {
|
|
19856
|
+
return new EvaluationError(getPivotTooBigErrorMessage(table.numberOfCells, this.locale));
|
|
19857
|
+
}
|
|
19642
19858
|
const cells = table.getPivotCells(visibilityOptions);
|
|
19643
19859
|
let headerRows = 0;
|
|
19644
19860
|
if (visibilityOptions.displayColumnHeaders) {
|
|
@@ -19737,7 +19953,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
19737
19953
|
right: startingCol + offsetWidth - 1,
|
|
19738
19954
|
bottom: startingRow + offsetHeight - 1,
|
|
19739
19955
|
};
|
|
19740
|
-
const range = this.getters.getRangeFromZone(
|
|
19956
|
+
const range = this.getters.getRangeFromZone(sheetId, dependencyZone);
|
|
19741
19957
|
if (range.invalidXc || range.invalidSheetName) {
|
|
19742
19958
|
return new InvalidReferenceError();
|
|
19743
19959
|
}
|
|
@@ -22020,12 +22236,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22020
22236
|
}
|
|
22021
22237
|
return pieColors;
|
|
22022
22238
|
}
|
|
22023
|
-
function truncateLabel(label) {
|
|
22239
|
+
function truncateLabel(label, maxLen = MAX_CHAR_LABEL) {
|
|
22024
22240
|
if (!label) {
|
|
22025
22241
|
return "";
|
|
22026
22242
|
}
|
|
22027
|
-
if (label.length >
|
|
22028
|
-
return label.substring(0,
|
|
22243
|
+
if (label.length > maxLen) {
|
|
22244
|
+
return label.substring(0, maxLen) + "…";
|
|
22029
22245
|
}
|
|
22030
22246
|
return label;
|
|
22031
22247
|
}
|
|
@@ -22997,7 +23213,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
22997
23213
|
class ChartJsComponent extends owl.Component {
|
|
22998
23214
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
22999
23215
|
static props = {
|
|
23000
|
-
|
|
23216
|
+
chartId: String,
|
|
23001
23217
|
isFullScreen: { type: Boolean, optional: true },
|
|
23002
23218
|
};
|
|
23003
23219
|
canvas = owl.useRef("graphContainer");
|
|
@@ -23012,7 +23228,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23012
23228
|
return `background-color: ${this.background}`;
|
|
23013
23229
|
}
|
|
23014
23230
|
get chartRuntime() {
|
|
23015
|
-
const runtime = this.env.model.getters.getChartRuntime(this.props.
|
|
23231
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
23016
23232
|
if (!("chartJsConfig" in runtime)) {
|
|
23017
23233
|
throw new Error("Unsupported chart runtime");
|
|
23018
23234
|
}
|
|
@@ -23027,30 +23243,37 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23027
23243
|
const runtime = this.chartRuntime;
|
|
23028
23244
|
this.currentRuntime = runtime;
|
|
23029
23245
|
// Note: chartJS modify the runtime in place, so it's important to give it a copy
|
|
23030
|
-
this.createChart(deepCopy(runtime
|
|
23246
|
+
this.createChart(deepCopy(runtime));
|
|
23031
23247
|
});
|
|
23032
|
-
owl.onWillUnmount(
|
|
23248
|
+
owl.onWillUnmount(this.unmount.bind(this));
|
|
23033
23249
|
owl.useEffect(() => {
|
|
23034
23250
|
const runtime = this.chartRuntime;
|
|
23035
23251
|
if (runtime !== this.currentRuntime) {
|
|
23036
23252
|
if (runtime.chartJsConfig.type !== this.currentRuntime.chartJsConfig.type) {
|
|
23037
23253
|
this.chart?.destroy();
|
|
23038
|
-
this.createChart(deepCopy(runtime
|
|
23254
|
+
this.createChart(deepCopy(runtime));
|
|
23039
23255
|
}
|
|
23040
23256
|
else {
|
|
23041
|
-
this.updateChartJs(deepCopy(runtime
|
|
23257
|
+
this.updateChartJs(deepCopy(runtime));
|
|
23042
23258
|
}
|
|
23043
23259
|
this.currentRuntime = runtime;
|
|
23044
23260
|
}
|
|
23045
23261
|
else if (this.currentDevicePixelRatio !== window.devicePixelRatio) {
|
|
23046
23262
|
this.currentDevicePixelRatio = window.devicePixelRatio;
|
|
23047
|
-
this.updateChartJs(deepCopy(this.currentRuntime
|
|
23263
|
+
this.updateChartJs(deepCopy(this.currentRuntime));
|
|
23048
23264
|
}
|
|
23049
23265
|
});
|
|
23050
23266
|
}
|
|
23051
|
-
|
|
23052
|
-
|
|
23053
|
-
|
|
23267
|
+
unmount() {
|
|
23268
|
+
this.chart?.destroy();
|
|
23269
|
+
}
|
|
23270
|
+
get shouldAnimate() {
|
|
23271
|
+
return this.env.model.getters.isDashboard();
|
|
23272
|
+
}
|
|
23273
|
+
createChart(chartRuntime) {
|
|
23274
|
+
let chartData = chartRuntime.chartJsConfig;
|
|
23275
|
+
if (this.shouldAnimate && this.animationStore) {
|
|
23276
|
+
const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
|
|
23054
23277
|
if (chartType && this.animationStore.animationPlayed[this.animationFigureId] !== chartType) {
|
|
23055
23278
|
chartData = this.enableAnimationInChartData(chartData);
|
|
23056
23279
|
this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
|
|
@@ -23060,9 +23283,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23060
23283
|
const ctx = canvas.getContext("2d");
|
|
23061
23284
|
this.chart = new window.Chart(ctx, chartData);
|
|
23062
23285
|
}
|
|
23063
|
-
updateChartJs(
|
|
23064
|
-
|
|
23065
|
-
|
|
23286
|
+
updateChartJs(chartRuntime) {
|
|
23287
|
+
let chartData = chartRuntime.chartJsConfig;
|
|
23288
|
+
if (this.shouldAnimate) {
|
|
23289
|
+
const chartType = this.env.model.getters.getChart(this.props.chartId)?.type;
|
|
23066
23290
|
if (chartType && this.hasChartDataChanged() && this.animationStore) {
|
|
23067
23291
|
chartData = this.enableAnimationInChartData(chartData);
|
|
23068
23292
|
this.animationStore.disableAnimationForChart(this.animationFigureId, chartType);
|
|
@@ -23090,9 +23314,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23090
23314
|
};
|
|
23091
23315
|
}
|
|
23092
23316
|
get animationFigureId() {
|
|
23093
|
-
return this.props.isFullScreen
|
|
23094
|
-
? this.props.figureUI.id + "-fullscreen"
|
|
23095
|
-
: this.props.figureUI.id;
|
|
23317
|
+
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
23096
23318
|
}
|
|
23097
23319
|
}
|
|
23098
23320
|
|
|
@@ -23757,14 +23979,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
23757
23979
|
class ScorecardChart extends owl.Component {
|
|
23758
23980
|
static template = "o-spreadsheet-ScorecardChart";
|
|
23759
23981
|
static props = {
|
|
23760
|
-
|
|
23982
|
+
chartId: String,
|
|
23761
23983
|
};
|
|
23762
23984
|
canvas = owl.useRef("chartContainer");
|
|
23763
23985
|
get runtime() {
|
|
23764
|
-
return this.env.model.getters.getChartRuntime(this.props.
|
|
23986
|
+
return this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
23765
23987
|
}
|
|
23766
23988
|
get title() {
|
|
23767
|
-
const title = this.env.model.getters.getChartDefinition(this.props.
|
|
23989
|
+
const title = this.env.model.getters.getChartDefinition(this.props.chartId).title.text ?? "";
|
|
23768
23990
|
// chart titles are extracted from .json files and they are translated at runtime here
|
|
23769
23991
|
return _t(title);
|
|
23770
23992
|
}
|
|
@@ -24470,204 +24692,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
24470
24692
|
},
|
|
24471
24693
|
};
|
|
24472
24694
|
|
|
24473
|
-
const CfTerms = {
|
|
24474
|
-
Errors: {
|
|
24475
|
-
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid"),
|
|
24476
|
-
["FirstArgMissing" /* CommandResult.FirstArgMissing */]: _t("The argument is missing. Please provide a value"),
|
|
24477
|
-
["SecondArgMissing" /* CommandResult.SecondArgMissing */]: _t("The second argument is missing. Please provide a value"),
|
|
24478
|
-
["MinNaN" /* CommandResult.MinNaN */]: _t("The minpoint must be a number"),
|
|
24479
|
-
["MidNaN" /* CommandResult.MidNaN */]: _t("The midpoint must be a number"),
|
|
24480
|
-
["MaxNaN" /* CommandResult.MaxNaN */]: _t("The maxpoint must be a number"),
|
|
24481
|
-
["ValueUpperInflectionNaN" /* CommandResult.ValueUpperInflectionNaN */]: _t("The first value must be a number"),
|
|
24482
|
-
["ValueLowerInflectionNaN" /* CommandResult.ValueLowerInflectionNaN */]: _t("The second value must be a number"),
|
|
24483
|
-
["MinBiggerThanMax" /* CommandResult.MinBiggerThanMax */]: _t("Minimum must be smaller then Maximum"),
|
|
24484
|
-
["MinBiggerThanMid" /* CommandResult.MinBiggerThanMid */]: _t("Minimum must be smaller then Midpoint"),
|
|
24485
|
-
["MidBiggerThanMax" /* CommandResult.MidBiggerThanMax */]: _t("Midpoint must be smaller then Maximum"),
|
|
24486
|
-
["LowerBiggerThanUpper" /* CommandResult.LowerBiggerThanUpper */]: _t("Lower inflection point must be smaller than upper inflection point"),
|
|
24487
|
-
["MinInvalidFormula" /* CommandResult.MinInvalidFormula */]: _t("Invalid Minpoint formula"),
|
|
24488
|
-
["MaxInvalidFormula" /* CommandResult.MaxInvalidFormula */]: _t("Invalid Maxpoint formula"),
|
|
24489
|
-
["MidInvalidFormula" /* CommandResult.MidInvalidFormula */]: _t("Invalid Midpoint formula"),
|
|
24490
|
-
["ValueUpperInvalidFormula" /* CommandResult.ValueUpperInvalidFormula */]: _t("Invalid upper inflection point formula"),
|
|
24491
|
-
["ValueLowerInvalidFormula" /* CommandResult.ValueLowerInvalidFormula */]: _t("Invalid lower inflection point formula"),
|
|
24492
|
-
["EmptyRange" /* CommandResult.EmptyRange */]: _t("A range needs to be defined"),
|
|
24493
|
-
["ValueCellIsInvalidFormula" /* CommandResult.ValueCellIsInvalidFormula */]: _t("At least one of the provided values is an invalid formula"),
|
|
24494
|
-
Unexpected: _t("The rule is invalid for an unknown reason"),
|
|
24495
|
-
},
|
|
24496
|
-
ColorScale: _t("Color scale"),
|
|
24497
|
-
IconSet: _t("Icon set"),
|
|
24498
|
-
DataBar: _t("Data bar"),
|
|
24499
|
-
};
|
|
24500
|
-
const ChartTerms = {
|
|
24501
|
-
Series: _t("Series"),
|
|
24502
|
-
BackgroundColor: _t("Background color"),
|
|
24503
|
-
StackedBarChart: _t("Stacked bar chart"),
|
|
24504
|
-
StackedLineChart: _t("Stacked line chart"),
|
|
24505
|
-
StackedAreaChart: _t("Stacked area chart"),
|
|
24506
|
-
StackedColumnChart: _t("Stacked column chart"),
|
|
24507
|
-
CumulativeData: _t("Cumulative data"),
|
|
24508
|
-
TreatLabelsAsText: _t("Treat labels as text"),
|
|
24509
|
-
AggregatedChart: _t("Aggregate"),
|
|
24510
|
-
Errors: {
|
|
24511
|
-
Unexpected: _t("The chart definition is invalid for an unknown reason"),
|
|
24512
|
-
// BASIC CHART ERRORS (LINE | BAR | PIE)
|
|
24513
|
-
["InvalidDataSet" /* CommandResult.InvalidDataSet */]: _t("The dataset is invalid"),
|
|
24514
|
-
["InvalidLabelRange" /* CommandResult.InvalidLabelRange */]: _t("Labels are invalid"),
|
|
24515
|
-
// SCORECARD CHART ERRORS
|
|
24516
|
-
["InvalidScorecardKeyValue" /* CommandResult.InvalidScorecardKeyValue */]: _t("The key value is invalid"),
|
|
24517
|
-
["InvalidScorecardBaseline" /* CommandResult.InvalidScorecardBaseline */]: _t("The baseline value is invalid"),
|
|
24518
|
-
// GAUGE CHART ERRORS
|
|
24519
|
-
["InvalidGaugeDataRange" /* CommandResult.InvalidGaugeDataRange */]: _t("The data range is invalid"),
|
|
24520
|
-
["EmptyGaugeRangeMin" /* CommandResult.EmptyGaugeRangeMin */]: _t("A minimum range limit value is needed"),
|
|
24521
|
-
["GaugeRangeMinNaN" /* CommandResult.GaugeRangeMinNaN */]: _t("The minimum range limit value must be a number"),
|
|
24522
|
-
["EmptyGaugeRangeMax" /* CommandResult.EmptyGaugeRangeMax */]: _t("A maximum range limit value is needed"),
|
|
24523
|
-
["GaugeRangeMaxNaN" /* CommandResult.GaugeRangeMaxNaN */]: _t("The maximum range limit value must be a number"),
|
|
24524
|
-
["GaugeLowerInflectionPointNaN" /* CommandResult.GaugeLowerInflectionPointNaN */]: _t("The lower inflection point value must be a number"),
|
|
24525
|
-
["GaugeUpperInflectionPointNaN" /* CommandResult.GaugeUpperInflectionPointNaN */]: _t("The upper inflection point value must be a number"),
|
|
24526
|
-
},
|
|
24527
|
-
GeoChart: {
|
|
24528
|
-
ColorScales: {
|
|
24529
|
-
blues: _t("Blues"),
|
|
24530
|
-
cividis: _t("Cividis"),
|
|
24531
|
-
greens: _t("Greens"),
|
|
24532
|
-
greys: _t("Greys"),
|
|
24533
|
-
oranges: _t("Oranges"),
|
|
24534
|
-
purples: _t("Purples"),
|
|
24535
|
-
rainbow: _t("Rainbow"),
|
|
24536
|
-
reds: _t("Reds"),
|
|
24537
|
-
viridis: _t("Viridis"),
|
|
24538
|
-
},
|
|
24539
|
-
},
|
|
24540
|
-
};
|
|
24541
|
-
const CustomCurrencyTerms = {
|
|
24542
|
-
Custom: _t("Custom"),
|
|
24543
|
-
};
|
|
24544
|
-
const MergeErrorMessage = _t("Merged cells are preventing this operation. Unmerge those cells and try again.");
|
|
24545
|
-
const SplitToColumnsTerms = {
|
|
24546
|
-
Errors: {
|
|
24547
|
-
Unexpected: _t("Cannot split the selection for an unknown reason"),
|
|
24548
|
-
["NoSplitSeparatorInSelection" /* CommandResult.NoSplitSeparatorInSelection */]: _t("There is no match for the selected separator in the selection"),
|
|
24549
|
-
["MoreThanOneColumnSelected" /* CommandResult.MoreThanOneColumnSelected */]: _t("Only a selection from a single column can be split"),
|
|
24550
|
-
["SplitWillOverwriteContent" /* CommandResult.SplitWillOverwriteContent */]: _t("Splitting will overwrite existing content"),
|
|
24551
|
-
},
|
|
24552
|
-
};
|
|
24553
|
-
const RemoveDuplicateTerms = {
|
|
24554
|
-
Errors: {
|
|
24555
|
-
Unexpected: _t("Cannot remove duplicates for an unknown reason"),
|
|
24556
|
-
["MoreThanOneRangeSelected" /* CommandResult.MoreThanOneRangeSelected */]: _t("Please select only one range of cells"),
|
|
24557
|
-
["EmptyTarget" /* CommandResult.EmptyTarget */]: _t("Please select a range of cells containing values."),
|
|
24558
|
-
["NoColumnsProvided" /* CommandResult.NoColumnsProvided */]: _t("Please select at latest one column to analyze."),
|
|
24559
|
-
//TODO: Remove it when accept to copy and paste merge cells
|
|
24560
|
-
["WillRemoveExistingMerge" /* CommandResult.WillRemoveExistingMerge */]: _t("This operation is not possible due to a merge. Please remove the merges first than try again."),
|
|
24561
|
-
},
|
|
24562
|
-
};
|
|
24563
|
-
const DVTerms = {
|
|
24564
|
-
DateIs: {
|
|
24565
|
-
today: _t("today"),
|
|
24566
|
-
yesterday: _t("yesterday"),
|
|
24567
|
-
tomorrow: _t("tomorrow"),
|
|
24568
|
-
lastWeek: _t("in the past week"),
|
|
24569
|
-
lastMonth: _t("in the past month"),
|
|
24570
|
-
lastYear: _t("in the past year"),
|
|
24571
|
-
},
|
|
24572
|
-
DateIsBefore: {
|
|
24573
|
-
today: _t("today"),
|
|
24574
|
-
yesterday: _t("yesterday"),
|
|
24575
|
-
tomorrow: _t("tomorrow"),
|
|
24576
|
-
lastWeek: _t("one week ago"),
|
|
24577
|
-
lastMonth: _t("one month ago"),
|
|
24578
|
-
lastYear: _t("one year ago"),
|
|
24579
|
-
},
|
|
24580
|
-
CriterionError: {
|
|
24581
|
-
notEmptyValue: _t("The value must not be empty"),
|
|
24582
|
-
numberValue: _t("The value must be a number"),
|
|
24583
|
-
dateValue: _t("The value must be a date"),
|
|
24584
|
-
validRange: _t("The value must be a valid range"),
|
|
24585
|
-
validFormula: _t("The formula must be valid"),
|
|
24586
|
-
},
|
|
24587
|
-
Errors: {
|
|
24588
|
-
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid."),
|
|
24589
|
-
["InvalidDataValidationCriterionValue" /* CommandResult.InvalidDataValidationCriterionValue */]: _t("One or more of the provided criteria values are invalid. Please review and correct them."),
|
|
24590
|
-
["InvalidNumberOfCriterionValues" /* CommandResult.InvalidNumberOfCriterionValues */]: _t("One or more of the provided criteria values are missing."),
|
|
24591
|
-
Unexpected: _t("The rule is invalid for an unknown reason."),
|
|
24592
|
-
},
|
|
24593
|
-
};
|
|
24594
|
-
const TableTerms = {
|
|
24595
|
-
Errors: {
|
|
24596
|
-
Unexpected: _t("The table zone is invalid for an unknown reason"),
|
|
24597
|
-
["TableOverlap" /* CommandResult.TableOverlap */]: _t("You cannot create overlapping tables."),
|
|
24598
|
-
["NonContinuousTargets" /* CommandResult.NonContinuousTargets */]: _t("A table can only be created on a continuous selection."),
|
|
24599
|
-
["InvalidRange" /* CommandResult.InvalidRange */]: _t("The range is invalid"),
|
|
24600
|
-
["TargetOutOfSheet" /* CommandResult.TargetOutOfSheet */]: _t("The range is out of the sheet"),
|
|
24601
|
-
},
|
|
24602
|
-
Checkboxes: {
|
|
24603
|
-
hasFilters: _t("Filter button"),
|
|
24604
|
-
headerRow: _t("Header row(s)"),
|
|
24605
|
-
bandedRows: _t("Banded rows"),
|
|
24606
|
-
firstColumn: _t("First column"),
|
|
24607
|
-
lastColumn: _t("Last column"),
|
|
24608
|
-
bandedColumns: _t("Banded columns"),
|
|
24609
|
-
automaticAutofill: _t("Automatically autofill formulas"),
|
|
24610
|
-
totalRow: _t("Total row"),
|
|
24611
|
-
isDynamic: _t("Auto-adjust to formula result"),
|
|
24612
|
-
},
|
|
24613
|
-
Tooltips: {
|
|
24614
|
-
filterWithoutHeader: _t("Cannot have filters without a header row"),
|
|
24615
|
-
isDynamic: _t("For tables based on array formulas only"),
|
|
24616
|
-
},
|
|
24617
|
-
};
|
|
24618
|
-
const measureDisplayTerms = {
|
|
24619
|
-
labels: {
|
|
24620
|
-
no_calculations: _t("No calculations"),
|
|
24621
|
-
"%_of_grand_total": _t("% of grand total"),
|
|
24622
|
-
"%_of_col_total": _t("% of column total"),
|
|
24623
|
-
"%_of_row_total": _t("% of row total"),
|
|
24624
|
-
"%_of": _t("% of"),
|
|
24625
|
-
"%_of_parent_row_total": _t("% of parent row total"),
|
|
24626
|
-
"%_of_parent_col_total": _t("% of parent column total"),
|
|
24627
|
-
"%_of_parent_total": _t("% of parent total"),
|
|
24628
|
-
difference_from: _t("Difference from"),
|
|
24629
|
-
"%_difference_from": _t("% difference from"),
|
|
24630
|
-
running_total: _t("Running total"),
|
|
24631
|
-
"%_running_total": _t("% Running total"),
|
|
24632
|
-
rank_asc: _t("Rank smallest to largest"),
|
|
24633
|
-
rank_desc: _t("Rank largest to smallest"),
|
|
24634
|
-
index: _t("Index"),
|
|
24635
|
-
},
|
|
24636
|
-
descriptions: {
|
|
24637
|
-
"%_of_grand_total": () => _t("Displayed as % of grand total"),
|
|
24638
|
-
"%_of_col_total": () => _t("Displayed as % of column total"),
|
|
24639
|
-
"%_of_row_total": () => _t("Displayed as % of row total"),
|
|
24640
|
-
"%_of": (field) => _t('Displayed as % of "%s"', field),
|
|
24641
|
-
"%_of_parent_row_total": (field) => _t('Displayed as % of parent row total of "%s"', field),
|
|
24642
|
-
"%_of_parent_col_total": () => _t("Displayed as % of parent column total"),
|
|
24643
|
-
"%_of_parent_total": (field) => _t('Displayed as % of parent "%s" total', field),
|
|
24644
|
-
difference_from: (field) => _t('Displayed as difference from "%s"', field),
|
|
24645
|
-
"%_difference_from": (field) => _t('Displayed as % difference from "%s"', field),
|
|
24646
|
-
running_total: (field) => _t('Displayed as running total based on "%s"', field),
|
|
24647
|
-
"%_running_total": (field) => _t('Displayed as % running total based on "%s"', field),
|
|
24648
|
-
rank_asc: (field) => _t('Displayed as rank from smallest to largest based on "%s"', field),
|
|
24649
|
-
rank_desc: (field) => _t('Displayed as rank largest to smallest based on "%s"', field),
|
|
24650
|
-
index: () => _t("Displayed as index"),
|
|
24651
|
-
},
|
|
24652
|
-
documentation: {
|
|
24653
|
-
no_calculations: _t("Displays the value that is entered in the field."),
|
|
24654
|
-
"%_of_grand_total": _t("Displays values as a percentage of the grand total of all the values or data points in the report."),
|
|
24655
|
-
"%_of_col_total": _t("Displays all the values in each column or series as a percentage of the total for the column or series."),
|
|
24656
|
-
"%_of_row_total": _t("Displays the value in each row or category as a percentage of the total for the row or category."),
|
|
24657
|
-
"%_of": _t("Displays values as a percentage of the value of the Base item in the Base field."),
|
|
24658
|
-
"%_of_parent_row_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item on rows)"),
|
|
24659
|
-
"%_of_parent_col_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item on columns)"),
|
|
24660
|
-
"%_of_parent_total": _t("Calculates values as follows:\n(value for the item) / (value for the parent item of the selected Base field)"),
|
|
24661
|
-
difference_from: _t("Displays values as the difference from the value of the Base item in the Base field."),
|
|
24662
|
-
"%_difference_from": _t("Displays values as the percentage difference from the value of the Base item in the Base field."),
|
|
24663
|
-
running_total: _t("Displays the value for successive items in the Base field as a running total."),
|
|
24664
|
-
"%_running_total": _t("Calculates the value as a percentage for successive items in the Base field that are displayed as a running total."),
|
|
24665
|
-
rank_asc: _t("Displays the rank of selected values in a specific field, listing the smallest item in the field as 1, and each larger value with a higher rank value."),
|
|
24666
|
-
rank_desc: _t("Displays the rank of selected values in a specific field, listing the largest item in the field as 1, and each smaller value with a higher rank value."),
|
|
24667
|
-
index: _t("Calculates values as follows:\n((value in cell) x (Grand Total of Grand Totals)) / ((Grand Row Total) x (Grand Column Total))"),
|
|
24668
|
-
},
|
|
24669
|
-
};
|
|
24670
|
-
|
|
24671
24695
|
const UNIT_LENGTH = {
|
|
24672
24696
|
second: 1000,
|
|
24673
24697
|
minute: 1000 * 60,
|
|
@@ -26016,7 +26040,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26016
26040
|
ticks: {
|
|
26017
26041
|
padding: 5,
|
|
26018
26042
|
color: fontColor,
|
|
26019
|
-
callback: function (tickValue) {
|
|
26043
|
+
callback: function (tickValue, index, ticks) {
|
|
26020
26044
|
// Category axis callback's internal tick value is the index of the label
|
|
26021
26045
|
// https://www.chartjs.org/docs/latest/axes/labelling.html#creating-custom-tick-formats
|
|
26022
26046
|
return truncateLabel(this.getLabelForValue(tickValue));
|
|
@@ -26588,6 +26612,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26588
26612
|
axesDesign;
|
|
26589
26613
|
horizontal;
|
|
26590
26614
|
showValues;
|
|
26615
|
+
zoomable;
|
|
26591
26616
|
constructor(definition, sheetId, getters) {
|
|
26592
26617
|
super(definition, sheetId, getters);
|
|
26593
26618
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
@@ -26601,6 +26626,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26601
26626
|
this.axesDesign = definition.axesDesign;
|
|
26602
26627
|
this.horizontal = definition.horizontal;
|
|
26603
26628
|
this.showValues = definition.showValues;
|
|
26629
|
+
this.zoomable = definition.zoomable;
|
|
26604
26630
|
}
|
|
26605
26631
|
static transformDefinition(chartSheetId, definition, applyChange) {
|
|
26606
26632
|
return transformChartDefinitionWithDataSetsWithZone(chartSheetId, definition, applyChange);
|
|
@@ -26622,6 +26648,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26622
26648
|
axesDesign: context.axesDesign,
|
|
26623
26649
|
showValues: context.showValues,
|
|
26624
26650
|
horizontal: context.horizontal,
|
|
26651
|
+
zoomable: context.zoomable,
|
|
26625
26652
|
};
|
|
26626
26653
|
}
|
|
26627
26654
|
getContextCreation() {
|
|
@@ -26676,6 +26703,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26676
26703
|
axesDesign: this.axesDesign,
|
|
26677
26704
|
horizontal: this.horizontal,
|
|
26678
26705
|
showValues: this.showValues,
|
|
26706
|
+
zoomable: this.horizontal ? undefined : this.zoomable,
|
|
26679
26707
|
};
|
|
26680
26708
|
}
|
|
26681
26709
|
getDefinitionForExcel() {
|
|
@@ -26724,6 +26752,621 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
26724
26752
|
return { chartJsConfig: config, background: chart.background || BACKGROUND_CHART_COLOR };
|
|
26725
26753
|
}
|
|
26726
26754
|
|
|
26755
|
+
class FullScreenChartStore extends SpreadsheetStore {
|
|
26756
|
+
mutators = ["toggleFullScreenChart"];
|
|
26757
|
+
fullScreenFigure = undefined;
|
|
26758
|
+
toggleFullScreenChart(figureId) {
|
|
26759
|
+
if (this.fullScreenFigure?.id === figureId) {
|
|
26760
|
+
this.fullScreenFigure = undefined;
|
|
26761
|
+
}
|
|
26762
|
+
else {
|
|
26763
|
+
this.makeFullScreen(figureId);
|
|
26764
|
+
}
|
|
26765
|
+
}
|
|
26766
|
+
makeFullScreen(figureId) {
|
|
26767
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
26768
|
+
const figure = this.getters.getFigure(sheetId, figureId);
|
|
26769
|
+
if (figure) {
|
|
26770
|
+
this.fullScreenFigure = { ...figure, x: 0, y: 0, width: 0, height: 0 };
|
|
26771
|
+
}
|
|
26772
|
+
}
|
|
26773
|
+
}
|
|
26774
|
+
|
|
26775
|
+
const TREND_LINE_AXES_IDS = [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID];
|
|
26776
|
+
const ZOOMABLE_AXIS_IDS = ["x", ...TREND_LINE_AXES_IDS];
|
|
26777
|
+
class ZoomableChartStore extends SpreadsheetStore {
|
|
26778
|
+
mutators = [
|
|
26779
|
+
"resetAxisLimits",
|
|
26780
|
+
"updateAxisLimits",
|
|
26781
|
+
"updateTrendLineConfiguration",
|
|
26782
|
+
"clearAxisLimits",
|
|
26783
|
+
];
|
|
26784
|
+
originalAxisLimits = {};
|
|
26785
|
+
currentAxesLimits = {};
|
|
26786
|
+
idConversion = {};
|
|
26787
|
+
handle(cmd) {
|
|
26788
|
+
switch (cmd.type) {
|
|
26789
|
+
case "DELETE_FIGURE":
|
|
26790
|
+
if (cmd.figureId && this.idConversion[cmd.figureId]) {
|
|
26791
|
+
for (const chartId of this.idConversion[cmd.figureId]) {
|
|
26792
|
+
delete this.originalAxisLimits[chartId];
|
|
26793
|
+
delete this.currentAxesLimits[chartId];
|
|
26794
|
+
}
|
|
26795
|
+
}
|
|
26796
|
+
break;
|
|
26797
|
+
case "UPDATE_CHART":
|
|
26798
|
+
const type = cmd.definition.type;
|
|
26799
|
+
const chartId = `${type}-${cmd.figureId}`;
|
|
26800
|
+
if (!this.idConversion[cmd.figureId]) {
|
|
26801
|
+
this.idConversion[cmd.figureId] = new Set();
|
|
26802
|
+
}
|
|
26803
|
+
this.idConversion[cmd.figureId].add(chartId);
|
|
26804
|
+
if (!("zoomable" in cmd.definition && cmd.definition.zoomable)) {
|
|
26805
|
+
this.clearAxisLimits(chartId);
|
|
26806
|
+
}
|
|
26807
|
+
break;
|
|
26808
|
+
}
|
|
26809
|
+
}
|
|
26810
|
+
clearAxisLimits(chartId) {
|
|
26811
|
+
delete this.originalAxisLimits[chartId];
|
|
26812
|
+
delete this.currentAxesLimits[chartId];
|
|
26813
|
+
return "noStateChange";
|
|
26814
|
+
}
|
|
26815
|
+
resetAxisLimits(chartId, limits) {
|
|
26816
|
+
for (const axisId of ZOOMABLE_AXIS_IDS) {
|
|
26817
|
+
if (limits?.[axisId]) {
|
|
26818
|
+
if (!this.originalAxisLimits[chartId]?.[axisId]) {
|
|
26819
|
+
this.originalAxisLimits[chartId] = {
|
|
26820
|
+
...this.originalAxisLimits[chartId],
|
|
26821
|
+
[axisId]: {},
|
|
26822
|
+
};
|
|
26823
|
+
}
|
|
26824
|
+
this.originalAxisLimits[chartId][axisId]["min"] = limits[axisId].min;
|
|
26825
|
+
this.originalAxisLimits[chartId][axisId]["max"] = limits[axisId].max;
|
|
26826
|
+
}
|
|
26827
|
+
else {
|
|
26828
|
+
if (this.originalAxisLimits[chartId]?.[axisId]) {
|
|
26829
|
+
delete this.originalAxisLimits[chartId][axisId];
|
|
26830
|
+
}
|
|
26831
|
+
}
|
|
26832
|
+
}
|
|
26833
|
+
return "noStateChange";
|
|
26834
|
+
}
|
|
26835
|
+
updateAxisLimits(chartId, limits) {
|
|
26836
|
+
if (limits === undefined) {
|
|
26837
|
+
delete this.currentAxesLimits[chartId];
|
|
26838
|
+
return "noStateChange";
|
|
26839
|
+
}
|
|
26840
|
+
let { min, max } = limits;
|
|
26841
|
+
if (min > max) {
|
|
26842
|
+
[min, max] = [max, min];
|
|
26843
|
+
}
|
|
26844
|
+
this.currentAxesLimits[chartId] = { x: { min, max } };
|
|
26845
|
+
return "noStateChange";
|
|
26846
|
+
}
|
|
26847
|
+
/* Update the trend line axis configuration based on the current axis limits.
|
|
26848
|
+
* This function calculates the new limits for the trend line axes based on the current x-axis
|
|
26849
|
+
* limits and the original limits of the trend line axes.
|
|
26850
|
+
* It assumes that the origininal trend line axes are linear transformations of the original x-axis
|
|
26851
|
+
* limits and applies the same transformation to the current x-axis limits to get the new limits
|
|
26852
|
+
* for the current trend line axes.
|
|
26853
|
+
*/
|
|
26854
|
+
updateTrendLineConfiguration(chartId) {
|
|
26855
|
+
if (!this.originalAxisLimits[chartId]) {
|
|
26856
|
+
return "noStateChange";
|
|
26857
|
+
}
|
|
26858
|
+
const chartLimits = this.originalAxisLimits[chartId].x;
|
|
26859
|
+
if (chartLimits === undefined) {
|
|
26860
|
+
return "noStateChange";
|
|
26861
|
+
}
|
|
26862
|
+
for (const axisId of TREND_LINE_AXES_IDS) {
|
|
26863
|
+
if (!this.originalAxisLimits[chartId][axisId]) {
|
|
26864
|
+
continue;
|
|
26865
|
+
}
|
|
26866
|
+
if (!this.currentAxesLimits[chartId]?.[axisId]) {
|
|
26867
|
+
this.currentAxesLimits[chartId] = {
|
|
26868
|
+
...this.currentAxesLimits[chartId],
|
|
26869
|
+
[axisId]: {},
|
|
26870
|
+
};
|
|
26871
|
+
}
|
|
26872
|
+
if (this.currentAxesLimits[chartId]?.x === undefined) {
|
|
26873
|
+
return "noStateChange";
|
|
26874
|
+
}
|
|
26875
|
+
const realRange = chartLimits.max - chartLimits.min;
|
|
26876
|
+
const trendingLimits = this.originalAxisLimits[chartId][axisId];
|
|
26877
|
+
const trendingRange = trendingLimits.max - trendingLimits.min;
|
|
26878
|
+
const slope = trendingRange / realRange;
|
|
26879
|
+
const intercept = trendingLimits.min - chartLimits.min * slope;
|
|
26880
|
+
const newXMin = this.currentAxesLimits[chartId].x.min;
|
|
26881
|
+
const newXMax = this.currentAxesLimits[chartId].x.max;
|
|
26882
|
+
this.currentAxesLimits[chartId][axisId].min = newXMin * slope + intercept;
|
|
26883
|
+
this.currentAxesLimits[chartId][axisId].max = newXMax * slope + intercept;
|
|
26884
|
+
}
|
|
26885
|
+
return "noStateChange";
|
|
26886
|
+
}
|
|
26887
|
+
}
|
|
26888
|
+
|
|
26889
|
+
const zoomWindowPlugin = {
|
|
26890
|
+
id: "zoomWindowPlugin",
|
|
26891
|
+
afterDatasetsDraw: function (chart, args, options) {
|
|
26892
|
+
if (!options.getLowerBound || !options.getUpperBound) {
|
|
26893
|
+
return;
|
|
26894
|
+
}
|
|
26895
|
+
const { ctx, chartArea: { left, right, top, bottom }, } = chart;
|
|
26896
|
+
let lowerBound = options.getLowerBound() ?? left;
|
|
26897
|
+
let upperBound = options.getUpperBound() ?? right;
|
|
26898
|
+
if (lowerBound > upperBound) {
|
|
26899
|
+
[lowerBound, upperBound] = [upperBound, lowerBound];
|
|
26900
|
+
}
|
|
26901
|
+
lowerBound = Math.max(left, lowerBound);
|
|
26902
|
+
upperBound = Math.min(right, upperBound);
|
|
26903
|
+
if (lowerBound === left) {
|
|
26904
|
+
lowerBound -= 1;
|
|
26905
|
+
}
|
|
26906
|
+
if (upperBound === right) {
|
|
26907
|
+
upperBound += 1;
|
|
26908
|
+
}
|
|
26909
|
+
ctx.save();
|
|
26910
|
+
ctx.fillStyle = "rgba(255,255,255,0.5)";
|
|
26911
|
+
ctx.beginPath();
|
|
26912
|
+
ctx.rect(left, bottom, lowerBound - left, top - bottom);
|
|
26913
|
+
ctx.rect(upperBound, bottom, right - upperBound, top - bottom);
|
|
26914
|
+
ctx.fill();
|
|
26915
|
+
ctx.beginPath();
|
|
26916
|
+
ctx.strokeStyle = "#bbb";
|
|
26917
|
+
ctx.rect(lowerBound, bottom, upperBound - lowerBound, top - bottom);
|
|
26918
|
+
ctx.stroke();
|
|
26919
|
+
ctx.lineWidth = 2;
|
|
26920
|
+
ctx.beginPath();
|
|
26921
|
+
ctx.moveTo(lowerBound - 3, (top + bottom) / 2 - 7);
|
|
26922
|
+
ctx.lineTo(lowerBound - 3, (top + bottom) / 2 + 7);
|
|
26923
|
+
ctx.stroke();
|
|
26924
|
+
ctx.beginPath();
|
|
26925
|
+
ctx.moveTo(upperBound + 3, (top + bottom) / 2 - 7);
|
|
26926
|
+
ctx.lineTo(upperBound + 3, (top + bottom) / 2 + 7);
|
|
26927
|
+
ctx.stroke();
|
|
26928
|
+
ctx.restore();
|
|
26929
|
+
},
|
|
26930
|
+
};
|
|
26931
|
+
|
|
26932
|
+
css /* scss */ `
|
|
26933
|
+
.o-spreadsheet {
|
|
26934
|
+
.o-master-chart-container {
|
|
26935
|
+
height: ${MASTER_CHART_HEIGHT}px;
|
|
26936
|
+
}
|
|
26937
|
+
}
|
|
26938
|
+
`;
|
|
26939
|
+
chartJsExtensionRegistry.add("zoomWindowPlugin", {
|
|
26940
|
+
register: (Chart) => Chart.register(zoomWindowPlugin),
|
|
26941
|
+
unregister: (Chart) => Chart.unregister(zoomWindowPlugin),
|
|
26942
|
+
});
|
|
26943
|
+
class ZoomableChartJsComponent extends ChartJsComponent {
|
|
26944
|
+
static template = "o-spreadsheet-ZoomableChartJsComponent";
|
|
26945
|
+
store;
|
|
26946
|
+
fullScreenChartStore;
|
|
26947
|
+
masterChartCanvas = owl.useRef("masterChartCanvas");
|
|
26948
|
+
masterChart;
|
|
26949
|
+
mode;
|
|
26950
|
+
hasLinearScale;
|
|
26951
|
+
isBarChart;
|
|
26952
|
+
chartId = "";
|
|
26953
|
+
datasetBoundaries = { xMin: 0, xMax: 0 };
|
|
26954
|
+
removeEventListeners = () => { };
|
|
26955
|
+
setup() {
|
|
26956
|
+
this.store = useStore(ZoomableChartStore);
|
|
26957
|
+
this.fullScreenChartStore = useStore(FullScreenChartStore);
|
|
26958
|
+
super.setup();
|
|
26959
|
+
}
|
|
26960
|
+
unmount() {
|
|
26961
|
+
super.unmount();
|
|
26962
|
+
this.masterChart?.destroy();
|
|
26963
|
+
this.removeEventListeners();
|
|
26964
|
+
}
|
|
26965
|
+
get containerStyle() {
|
|
26966
|
+
const height = this.sliceable ? `calc(100% - ${MASTER_CHART_HEIGHT}px)` : "100%";
|
|
26967
|
+
return `
|
|
26968
|
+
height:${height};
|
|
26969
|
+
`;
|
|
26970
|
+
}
|
|
26971
|
+
get sliceable() {
|
|
26972
|
+
if (this.env.isDashboard()) {
|
|
26973
|
+
const fullScreenFigureId = this.fullScreenChartStore.fullScreenFigure?.id;
|
|
26974
|
+
const chartFigureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
26975
|
+
if (fullScreenFigureId === chartFigureId) {
|
|
26976
|
+
return true;
|
|
26977
|
+
}
|
|
26978
|
+
}
|
|
26979
|
+
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
26980
|
+
return ("zoomable" in definition && definition?.zoomable) ?? false;
|
|
26981
|
+
}
|
|
26982
|
+
get axisOffset() {
|
|
26983
|
+
return !this.hasLinearScale && this.isBarChart ? 0.5 : 0;
|
|
26984
|
+
}
|
|
26985
|
+
getMasterChartConfiguration(chartData) {
|
|
26986
|
+
const config = chartData;
|
|
26987
|
+
return {
|
|
26988
|
+
...config,
|
|
26989
|
+
options: {
|
|
26990
|
+
...config.options,
|
|
26991
|
+
plugins: {
|
|
26992
|
+
...config.options.plugins,
|
|
26993
|
+
zoomWindowPlugin: {
|
|
26994
|
+
getLowerBound: () => this.lowerBound,
|
|
26995
|
+
getUpperBound: () => this.upperBound,
|
|
26996
|
+
},
|
|
26997
|
+
},
|
|
26998
|
+
},
|
|
26999
|
+
};
|
|
27000
|
+
}
|
|
27001
|
+
getDetailChartConfiguration(chartData) {
|
|
27002
|
+
if (!this.sliceable) {
|
|
27003
|
+
return chartData;
|
|
27004
|
+
}
|
|
27005
|
+
const xAxis = this.store.currentAxesLimits[this.chartId]?.x;
|
|
27006
|
+
const xScale = {
|
|
27007
|
+
...chartData.options.scales?.x,
|
|
27008
|
+
};
|
|
27009
|
+
if (xAxis?.min !== undefined) {
|
|
27010
|
+
xScale.min = this.hasLinearScale ? xAxis.min : Math.ceil(xAxis.min) - this.axisOffset;
|
|
27011
|
+
}
|
|
27012
|
+
if (xAxis?.max !== undefined) {
|
|
27013
|
+
xScale.max = this.hasLinearScale ? xAxis.max : Math.floor(xAxis.max) - this.axisOffset;
|
|
27014
|
+
}
|
|
27015
|
+
return {
|
|
27016
|
+
...chartData,
|
|
27017
|
+
options: {
|
|
27018
|
+
...chartData.options,
|
|
27019
|
+
scales: {
|
|
27020
|
+
...chartData.options.scales,
|
|
27021
|
+
x: xScale,
|
|
27022
|
+
},
|
|
27023
|
+
layout: {
|
|
27024
|
+
...chartData.options.layout,
|
|
27025
|
+
padding: {
|
|
27026
|
+
...chartData.options.layout?.padding,
|
|
27027
|
+
bottom: 5,
|
|
27028
|
+
},
|
|
27029
|
+
},
|
|
27030
|
+
},
|
|
27031
|
+
};
|
|
27032
|
+
}
|
|
27033
|
+
getAxisLimitsFromDataset(chartData) {
|
|
27034
|
+
const data = chartData.data.datasets.map((ds) => ds.data).flat();
|
|
27035
|
+
const xValues = data.map((d, i) => (typeof d === "object" && d !== null ? d.x : i));
|
|
27036
|
+
const xMin = Math.min(...xValues);
|
|
27037
|
+
const xMax = Math.max(...xValues);
|
|
27038
|
+
return { xMin, xMax };
|
|
27039
|
+
}
|
|
27040
|
+
get shouldAnimate() {
|
|
27041
|
+
return this.env.model.getters.isDashboard() && !this.sliceable;
|
|
27042
|
+
}
|
|
27043
|
+
createChart(chartRuntime) {
|
|
27044
|
+
const chartData = chartRuntime.chartJsConfig;
|
|
27045
|
+
this.isBarChart = chartData.type === "bar";
|
|
27046
|
+
this.chartId = `${chartData.type}-${this.props.chartId}`;
|
|
27047
|
+
this.datasetBoundaries = this.getAxisLimitsFromDataset(chartData);
|
|
27048
|
+
if (this.sliceable) {
|
|
27049
|
+
const updatedData = this.getDetailChartConfiguration(chartData);
|
|
27050
|
+
chartRuntime.chartJsConfig = updatedData;
|
|
27051
|
+
}
|
|
27052
|
+
super.createChart(chartRuntime);
|
|
27053
|
+
this.hasLinearScale = this.chart?.scales?.x.type === "linear";
|
|
27054
|
+
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27055
|
+
return;
|
|
27056
|
+
}
|
|
27057
|
+
this.masterChart?.destroy();
|
|
27058
|
+
const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
|
|
27059
|
+
this.masterChart = new window.Chart(masterChartCtx, this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]));
|
|
27060
|
+
this.resetAxesLimits();
|
|
27061
|
+
}
|
|
27062
|
+
updateChartJs(chartRuntime) {
|
|
27063
|
+
const chartData = chartRuntime.chartJsConfig;
|
|
27064
|
+
const newDatasetBoundaries = this.getAxisLimitsFromDataset(chartData);
|
|
27065
|
+
if (this.datasetBoundaries.xMin !== newDatasetBoundaries.xMin ||
|
|
27066
|
+
this.datasetBoundaries.xMax !== newDatasetBoundaries.xMax) {
|
|
27067
|
+
this.store.clearAxisLimits(this.chartId);
|
|
27068
|
+
this.datasetBoundaries = newDatasetBoundaries;
|
|
27069
|
+
}
|
|
27070
|
+
this.isBarChart = chartData?.type === "bar";
|
|
27071
|
+
this.chartId = `${chartData.type}-${this.props.chartId}`;
|
|
27072
|
+
if (this.sliceable) {
|
|
27073
|
+
const updatedData = this.getDetailChartConfiguration(chartData);
|
|
27074
|
+
chartRuntime.chartJsConfig = updatedData;
|
|
27075
|
+
}
|
|
27076
|
+
super.updateChartJs(chartRuntime);
|
|
27077
|
+
this.hasLinearScale = this.chart?.scales?.x.type === "linear";
|
|
27078
|
+
if (!this.sliceable || !("masterChartConfig" in chartRuntime)) {
|
|
27079
|
+
this.masterChart = undefined;
|
|
27080
|
+
}
|
|
27081
|
+
else {
|
|
27082
|
+
const masterChartConfig = this.getMasterChartConfiguration(chartRuntime["masterChartConfig"]);
|
|
27083
|
+
if (!this.masterChart) {
|
|
27084
|
+
const masterChartCtx = this.masterChartCanvas.el.getContext("2d");
|
|
27085
|
+
this.masterChart = new window.Chart(masterChartCtx, masterChartConfig);
|
|
27086
|
+
}
|
|
27087
|
+
else {
|
|
27088
|
+
this.masterChart.data = masterChartConfig.data;
|
|
27089
|
+
this.masterChart.config.options = masterChartConfig.options;
|
|
27090
|
+
this.masterChart.update();
|
|
27091
|
+
}
|
|
27092
|
+
}
|
|
27093
|
+
this.resetAxesLimits();
|
|
27094
|
+
}
|
|
27095
|
+
resetAxesLimits() {
|
|
27096
|
+
if (!this.chart) {
|
|
27097
|
+
return;
|
|
27098
|
+
}
|
|
27099
|
+
const previousAxisLimits = this.store.originalAxisLimits[this.chartId];
|
|
27100
|
+
if (previousAxisLimits?.x?.min === undefined && previousAxisLimits?.x?.max === undefined) {
|
|
27101
|
+
let scales = this.masterChart
|
|
27102
|
+
? this.masterChart.scales
|
|
27103
|
+
: this.chart.scales;
|
|
27104
|
+
if (!this.hasLinearScale && scales?.x) {
|
|
27105
|
+
scales = {
|
|
27106
|
+
...scales,
|
|
27107
|
+
x: {
|
|
27108
|
+
min: Math.ceil(scales.x.min) - this.axisOffset,
|
|
27109
|
+
max: Math.floor(scales.x.max) + this.axisOffset,
|
|
27110
|
+
},
|
|
27111
|
+
};
|
|
27112
|
+
}
|
|
27113
|
+
this.store.resetAxisLimits(this.chartId, scales);
|
|
27114
|
+
return;
|
|
27115
|
+
}
|
|
27116
|
+
this.updateTrendingLineAxes();
|
|
27117
|
+
this.chart.update();
|
|
27118
|
+
if (!this.masterChart) {
|
|
27119
|
+
return;
|
|
27120
|
+
}
|
|
27121
|
+
this.masterChart.update();
|
|
27122
|
+
}
|
|
27123
|
+
updateTrendingLineAxes() {
|
|
27124
|
+
this.store.updateTrendLineConfiguration(this.chartId);
|
|
27125
|
+
const config = this.store.currentAxesLimits[this.chartId];
|
|
27126
|
+
for (const axisId of [TREND_LINE_XAXIS_ID, MOVING_AVERAGE_TREND_LINE_XAXIS_ID]) {
|
|
27127
|
+
if (!this.chart?.config.options?.scales?.[axisId] || !config?.[axisId]) {
|
|
27128
|
+
continue;
|
|
27129
|
+
}
|
|
27130
|
+
this.chart.config.options.scales[axisId].min = config[axisId].min;
|
|
27131
|
+
this.chart.config.options.scales[axisId].max = config[axisId].max;
|
|
27132
|
+
}
|
|
27133
|
+
}
|
|
27134
|
+
get upperBound() {
|
|
27135
|
+
return this.computePosition(this.store.currentAxesLimits[this.chartId]?.x?.max);
|
|
27136
|
+
}
|
|
27137
|
+
get lowerBound() {
|
|
27138
|
+
return this.computePosition(this.store.currentAxesLimits[this.chartId]?.x?.min);
|
|
27139
|
+
}
|
|
27140
|
+
computePosition(value) {
|
|
27141
|
+
if (value === undefined || !this.masterChart?.scales?.x) {
|
|
27142
|
+
return undefined;
|
|
27143
|
+
}
|
|
27144
|
+
const scale = this.masterChart.scales.x;
|
|
27145
|
+
if (this.hasLinearScale) {
|
|
27146
|
+
return scale.getPixelForValue(value);
|
|
27147
|
+
}
|
|
27148
|
+
if (!this.masterChart.chartArea) {
|
|
27149
|
+
return undefined;
|
|
27150
|
+
}
|
|
27151
|
+
const { left, right } = this.masterChart.chartArea;
|
|
27152
|
+
const { min, max } = scale;
|
|
27153
|
+
const offset = this.axisOffset;
|
|
27154
|
+
return left + ((right - left) * (offset + value - min)) / (2 * offset + max - min);
|
|
27155
|
+
}
|
|
27156
|
+
computeCoordinate(position) {
|
|
27157
|
+
if (!this.masterChart) {
|
|
27158
|
+
return undefined;
|
|
27159
|
+
}
|
|
27160
|
+
const scale = this.masterChart.scales.x;
|
|
27161
|
+
if (this.hasLinearScale) {
|
|
27162
|
+
const value = scale.getValueForPixel(position);
|
|
27163
|
+
if (value === undefined) {
|
|
27164
|
+
return undefined;
|
|
27165
|
+
}
|
|
27166
|
+
return Math.round(value * 100) / 100;
|
|
27167
|
+
}
|
|
27168
|
+
const { left, right } = this.masterChart.chartArea;
|
|
27169
|
+
const offset = this.axisOffset;
|
|
27170
|
+
return (scale.min -
|
|
27171
|
+
offset +
|
|
27172
|
+
((scale.max + 2 * offset - scale.min) * (position - left)) / (right - left));
|
|
27173
|
+
}
|
|
27174
|
+
updateAxisLimits(xMin, xMax) {
|
|
27175
|
+
if (!this.hasLinearScale) {
|
|
27176
|
+
this.chart.config.options.scales.x.min = Math.ceil(xMin);
|
|
27177
|
+
this.chart.config.options.scales.x.max = Math.floor(xMax);
|
|
27178
|
+
}
|
|
27179
|
+
else {
|
|
27180
|
+
this.chart.config.options.scales.x.min = xMin;
|
|
27181
|
+
this.chart.config.options.scales.x.max = xMax;
|
|
27182
|
+
}
|
|
27183
|
+
this.store.updateAxisLimits(this.chartId, { min: xMin, max: xMax });
|
|
27184
|
+
this.updateTrendingLineAxes();
|
|
27185
|
+
this.masterChart?.update();
|
|
27186
|
+
this.chart?.update();
|
|
27187
|
+
}
|
|
27188
|
+
onPointerDownInMasterChart(ev) {
|
|
27189
|
+
this.removeEventListeners();
|
|
27190
|
+
const position = ev.offsetX;
|
|
27191
|
+
if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
|
|
27192
|
+
return;
|
|
27193
|
+
}
|
|
27194
|
+
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
27195
|
+
const xMax = this.upperBound ?? right;
|
|
27196
|
+
const xMin = this.lowerBound ?? left;
|
|
27197
|
+
if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
|
|
27198
|
+
return;
|
|
27199
|
+
}
|
|
27200
|
+
ev.preventDefault();
|
|
27201
|
+
ev.stopPropagation();
|
|
27202
|
+
let startingPositionOnChart, windowSize, startX;
|
|
27203
|
+
const startingEventPosition = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
27204
|
+
if ((xMin !== left || xMax !== right) && position > xMin + 5 && position < xMax - 5) {
|
|
27205
|
+
startingPositionOnChart = ev.offsetX - xMin;
|
|
27206
|
+
this.mode = "moveInMaster";
|
|
27207
|
+
const currentLimits = this.store.currentAxesLimits[this.chartId]?.x;
|
|
27208
|
+
windowSize =
|
|
27209
|
+
(currentLimits?.max ?? this.chart.scales.x.max) -
|
|
27210
|
+
(currentLimits?.min ?? this.chart.scales.x.min);
|
|
27211
|
+
}
|
|
27212
|
+
else {
|
|
27213
|
+
this.mode = "selectInMaster";
|
|
27214
|
+
if (Math.abs(position - xMin) < 5) {
|
|
27215
|
+
startingPositionOnChart = xMax;
|
|
27216
|
+
}
|
|
27217
|
+
else if (Math.abs(position - xMax) < 5) {
|
|
27218
|
+
startingPositionOnChart = xMin;
|
|
27219
|
+
}
|
|
27220
|
+
else {
|
|
27221
|
+
startingPositionOnChart = clip(position, left, right);
|
|
27222
|
+
}
|
|
27223
|
+
startX = this.computeCoordinate(startingPositionOnChart);
|
|
27224
|
+
}
|
|
27225
|
+
const originalXMin = this.store.originalAxisLimits[this.chartId].x.min;
|
|
27226
|
+
const originalXMax = this.store.originalAxisLimits[this.chartId].x.max;
|
|
27227
|
+
const computeNewAxisLimits = (position) => {
|
|
27228
|
+
let xMin, xMax;
|
|
27229
|
+
const { left, right } = this.masterChart.chartArea;
|
|
27230
|
+
if (this.mode === "moveInMaster") {
|
|
27231
|
+
xMin = this.computeCoordinate(position - startingPositionOnChart);
|
|
27232
|
+
if (xMin < originalXMin) {
|
|
27233
|
+
xMin = originalXMin;
|
|
27234
|
+
}
|
|
27235
|
+
else if (xMin > originalXMax - windowSize) {
|
|
27236
|
+
xMin = originalXMax - windowSize;
|
|
27237
|
+
}
|
|
27238
|
+
xMax = xMin + windowSize;
|
|
27239
|
+
}
|
|
27240
|
+
else if (this.mode === "selectInMaster") {
|
|
27241
|
+
const upperBound = clip(position, left, right);
|
|
27242
|
+
if (Math.abs(startingPositionOnChart - upperBound) > 5) {
|
|
27243
|
+
const endX = this.computeCoordinate(upperBound);
|
|
27244
|
+
if (startX === undefined || endX === undefined) {
|
|
27245
|
+
return {};
|
|
27246
|
+
}
|
|
27247
|
+
xMin = Math.min(startX, endX);
|
|
27248
|
+
xMax = Math.max(startX, endX);
|
|
27249
|
+
}
|
|
27250
|
+
}
|
|
27251
|
+
return { min: xMin, max: xMax };
|
|
27252
|
+
};
|
|
27253
|
+
const onDragFromMasterChart = (ev) => {
|
|
27254
|
+
const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
27255
|
+
if (Math.abs(position - startingEventPosition) < 5) {
|
|
27256
|
+
return;
|
|
27257
|
+
}
|
|
27258
|
+
const { min: xMin, max: xMax } = computeNewAxisLimits(position);
|
|
27259
|
+
if (xMin !== undefined && xMax !== undefined) {
|
|
27260
|
+
this.updateAxisLimits(xMin, xMax);
|
|
27261
|
+
}
|
|
27262
|
+
};
|
|
27263
|
+
const onPointerUpInMasterChart = (ev) => {
|
|
27264
|
+
this.removeEventListeners();
|
|
27265
|
+
const position = ev.clientX - (this.masterChartCanvas.el?.getBoundingClientRect().left ?? 0);
|
|
27266
|
+
if (Math.abs(position - startingEventPosition) > 5) {
|
|
27267
|
+
let { min: xMin, max: xMax } = computeNewAxisLimits(position);
|
|
27268
|
+
if (xMin !== undefined && xMax !== undefined) {
|
|
27269
|
+
if (!this.hasLinearScale) {
|
|
27270
|
+
if (this.mode === "moveInMaster" && windowSize && !this.isBarChart) {
|
|
27271
|
+
xMin = Math.round(xMin) - this.axisOffset;
|
|
27272
|
+
xMax = xMin + windowSize;
|
|
27273
|
+
}
|
|
27274
|
+
else {
|
|
27275
|
+
xMin = Math.ceil(xMin) - this.axisOffset;
|
|
27276
|
+
xMax = Math.floor(xMax) + this.axisOffset;
|
|
27277
|
+
}
|
|
27278
|
+
}
|
|
27279
|
+
this.updateAxisLimits(xMin, xMax);
|
|
27280
|
+
}
|
|
27281
|
+
}
|
|
27282
|
+
this.mode = undefined;
|
|
27283
|
+
};
|
|
27284
|
+
this.removeEventListeners = () => {
|
|
27285
|
+
window.removeEventListener("pointermove", onDragFromMasterChart, true);
|
|
27286
|
+
window.removeEventListener("pointerup", onPointerUpInMasterChart, true);
|
|
27287
|
+
};
|
|
27288
|
+
window.addEventListener("pointermove", onDragFromMasterChart, true);
|
|
27289
|
+
window.addEventListener("pointerup", onPointerUpInMasterChart, true);
|
|
27290
|
+
}
|
|
27291
|
+
onPointerMoveInMasterChart(ev) {
|
|
27292
|
+
const { offsetX: x, offsetY: y } = ev;
|
|
27293
|
+
if (this.mode === undefined) {
|
|
27294
|
+
const target = ev.target;
|
|
27295
|
+
if (!this.masterChart?.chartArea) {
|
|
27296
|
+
target["style"].cursor = "default";
|
|
27297
|
+
return;
|
|
27298
|
+
}
|
|
27299
|
+
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
27300
|
+
const start = this.lowerBound ?? left;
|
|
27301
|
+
const end = this.upperBound ?? right;
|
|
27302
|
+
if (y < top || y > bottom) {
|
|
27303
|
+
target["style"].cursor = "default";
|
|
27304
|
+
}
|
|
27305
|
+
else if (Math.abs(start - x) < 5 || Math.abs(end - x) < 5) {
|
|
27306
|
+
target["style"].cursor = "ew-resize";
|
|
27307
|
+
}
|
|
27308
|
+
else if (start < x && x < end && (start !== left || end !== right)) {
|
|
27309
|
+
target["style"].cursor = "grab";
|
|
27310
|
+
}
|
|
27311
|
+
else {
|
|
27312
|
+
target["style"].cursor = "crosshair";
|
|
27313
|
+
}
|
|
27314
|
+
}
|
|
27315
|
+
}
|
|
27316
|
+
onMouseLeaveMasterChart(ev) {
|
|
27317
|
+
const target = ev.target;
|
|
27318
|
+
if (!target) {
|
|
27319
|
+
return;
|
|
27320
|
+
}
|
|
27321
|
+
target["style"].cursor = "default";
|
|
27322
|
+
}
|
|
27323
|
+
onDoubleClickInMasterChart(ev) {
|
|
27324
|
+
this.mode = undefined;
|
|
27325
|
+
const position = ev.offsetX;
|
|
27326
|
+
if (!this.masterChart?.chartArea || !this.chart?.scales.x) {
|
|
27327
|
+
return;
|
|
27328
|
+
}
|
|
27329
|
+
const { left, right, top, bottom } = this.masterChart.chartArea;
|
|
27330
|
+
let upperBound = this.upperBound ?? right;
|
|
27331
|
+
let lowerBound = this.lowerBound ?? left;
|
|
27332
|
+
if (upperBound < lowerBound) {
|
|
27333
|
+
[upperBound, lowerBound] = [lowerBound, upperBound];
|
|
27334
|
+
}
|
|
27335
|
+
if (position < left - 5 || position > right + 5 || ev.offsetY < top || ev.offsetY > bottom) {
|
|
27336
|
+
return;
|
|
27337
|
+
}
|
|
27338
|
+
ev.preventDefault();
|
|
27339
|
+
ev.stopPropagation();
|
|
27340
|
+
let { min: xMin, max: xMax } = this.store.currentAxesLimits[this.chartId]?.x ?? this.chart.scales.x;
|
|
27341
|
+
const originalAxisLimits = this.store.originalAxisLimits[this.chartId].x;
|
|
27342
|
+
if (!originalAxisLimits) {
|
|
27343
|
+
return;
|
|
27344
|
+
}
|
|
27345
|
+
let originalXMin = originalAxisLimits.min;
|
|
27346
|
+
let originalXMax = originalAxisLimits.max;
|
|
27347
|
+
if (this.hasLinearScale) {
|
|
27348
|
+
originalXMin = Math.ceil(originalXMin) - this.axisOffset;
|
|
27349
|
+
originalXMax = Math.floor(originalXMax) + this.axisOffset;
|
|
27350
|
+
}
|
|
27351
|
+
if (Math.abs(position - lowerBound) < 5) {
|
|
27352
|
+
// Reset to original min
|
|
27353
|
+
xMin = originalXMin;
|
|
27354
|
+
}
|
|
27355
|
+
else if (Math.abs(position - upperBound) < 5) {
|
|
27356
|
+
xMax = originalXMax;
|
|
27357
|
+
}
|
|
27358
|
+
else if (lowerBound < position && position < upperBound) {
|
|
27359
|
+
// Reset to original limits
|
|
27360
|
+
xMin = originalXMin;
|
|
27361
|
+
xMax = originalXMax;
|
|
27362
|
+
}
|
|
27363
|
+
else {
|
|
27364
|
+
return;
|
|
27365
|
+
}
|
|
27366
|
+
this.updateAxisLimits(xMin, xMax);
|
|
27367
|
+
}
|
|
27368
|
+
}
|
|
27369
|
+
|
|
26727
27370
|
const cellAnimationRegistry = new Registry();
|
|
26728
27371
|
cellAnimationRegistry.add("animatedBackgroundColorChange", {
|
|
26729
27372
|
id: "animatedBackgroundColorChange",
|
|
@@ -27086,13 +27729,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27086
27729
|
class GaugeChartComponent extends owl.Component {
|
|
27087
27730
|
static template = "o-spreadsheet-GaugeChartComponent";
|
|
27088
27731
|
static props = {
|
|
27089
|
-
|
|
27732
|
+
chartId: String,
|
|
27090
27733
|
isFullScreen: { type: Boolean, optional: true },
|
|
27091
27734
|
};
|
|
27092
27735
|
canvas = owl.useRef("chartContainer");
|
|
27093
27736
|
animationStore;
|
|
27094
27737
|
get runtime() {
|
|
27095
|
-
return this.env.model.getters.getChartRuntime(this.props.
|
|
27738
|
+
return this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
27096
27739
|
}
|
|
27097
27740
|
setup() {
|
|
27098
27741
|
if (this.env.model.getters.isDashboard()) {
|
|
@@ -27140,9 +27783,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27140
27783
|
return this.canvas.el;
|
|
27141
27784
|
}
|
|
27142
27785
|
get animationFigureId() {
|
|
27143
|
-
return this.props.isFullScreen
|
|
27144
|
-
? this.props.figureUI.id + "-fullscreen"
|
|
27145
|
-
: this.props.figureUI.id;
|
|
27786
|
+
return this.props.isFullScreen ? this.props.chartId + "-fullscreen" : this.props.chartId;
|
|
27146
27787
|
}
|
|
27147
27788
|
}
|
|
27148
27789
|
/**
|
|
@@ -27199,6 +27840,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27199
27840
|
type = "combo";
|
|
27200
27841
|
showValues;
|
|
27201
27842
|
hideDataMarkers;
|
|
27843
|
+
zoomable;
|
|
27202
27844
|
constructor(definition, sheetId, getters) {
|
|
27203
27845
|
super(definition, sheetId, getters);
|
|
27204
27846
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
@@ -27211,6 +27853,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27211
27853
|
this.axesDesign = definition.axesDesign;
|
|
27212
27854
|
this.showValues = definition.showValues;
|
|
27213
27855
|
this.hideDataMarkers = definition.hideDataMarkers;
|
|
27856
|
+
this.zoomable = definition.zoomable;
|
|
27214
27857
|
}
|
|
27215
27858
|
static transformDefinition(chartSheetId, definition, applyChange) {
|
|
27216
27859
|
return transformChartDefinitionWithDataSetsWithZone(chartSheetId, definition, applyChange);
|
|
@@ -27260,6 +27903,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27260
27903
|
axesDesign: this.axesDesign,
|
|
27261
27904
|
showValues: this.showValues,
|
|
27262
27905
|
hideDataMarkers: this.hideDataMarkers,
|
|
27906
|
+
zoomable: this.zoomable,
|
|
27263
27907
|
};
|
|
27264
27908
|
}
|
|
27265
27909
|
getDefinitionForExcel() {
|
|
@@ -27303,6 +27947,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27303
27947
|
axesDesign: context.axesDesign,
|
|
27304
27948
|
showValues: context.showValues,
|
|
27305
27949
|
hideDataMarkers: context.hideDataMarkers,
|
|
27950
|
+
zoomable: context.zoomable,
|
|
27306
27951
|
};
|
|
27307
27952
|
}
|
|
27308
27953
|
duplicateInDuplicatedSheet(newSheetId) {
|
|
@@ -27908,6 +28553,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27908
28553
|
fillArea;
|
|
27909
28554
|
showValues;
|
|
27910
28555
|
hideDataMarkers;
|
|
28556
|
+
zoomable;
|
|
27911
28557
|
constructor(definition, sheetId, getters) {
|
|
27912
28558
|
super(definition, sheetId, getters);
|
|
27913
28559
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
@@ -27924,6 +28570,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27924
28570
|
this.fillArea = definition.fillArea;
|
|
27925
28571
|
this.showValues = definition.showValues;
|
|
27926
28572
|
this.hideDataMarkers = definition.hideDataMarkers;
|
|
28573
|
+
this.zoomable = definition.zoomable;
|
|
27927
28574
|
}
|
|
27928
28575
|
static validateChartDefinition(validator, definition) {
|
|
27929
28576
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
@@ -27948,6 +28595,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27948
28595
|
fillArea: context.fillArea,
|
|
27949
28596
|
showValues: context.showValues,
|
|
27950
28597
|
hideDataMarkers: context.hideDataMarkers,
|
|
28598
|
+
zoomable: context.zoomable,
|
|
27951
28599
|
};
|
|
27952
28600
|
}
|
|
27953
28601
|
getDefinition() {
|
|
@@ -27979,6 +28627,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
27979
28627
|
fillArea: this.fillArea,
|
|
27980
28628
|
showValues: this.showValues,
|
|
27981
28629
|
hideDataMarkers: this.hideDataMarkers,
|
|
28630
|
+
zoomable: this.zoomable,
|
|
27982
28631
|
};
|
|
27983
28632
|
}
|
|
27984
28633
|
getContextCreation() {
|
|
@@ -28501,6 +29150,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28501
29150
|
dataSetDesign;
|
|
28502
29151
|
axesDesign;
|
|
28503
29152
|
showValues;
|
|
29153
|
+
zoomable;
|
|
28504
29154
|
constructor(definition, sheetId, getters) {
|
|
28505
29155
|
super(definition, sheetId, getters);
|
|
28506
29156
|
this.dataSets = createDataSets(this.getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
@@ -28513,6 +29163,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28513
29163
|
this.dataSetDesign = definition.dataSets;
|
|
28514
29164
|
this.axesDesign = definition.axesDesign;
|
|
28515
29165
|
this.showValues = definition.showValues;
|
|
29166
|
+
this.zoomable = definition.zoomable;
|
|
28516
29167
|
}
|
|
28517
29168
|
static validateChartDefinition(validator, definition) {
|
|
28518
29169
|
return validator.checkValidations(definition, checkDataset, checkLabelRange);
|
|
@@ -28533,6 +29184,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28533
29184
|
aggregated: context.aggregated ?? false,
|
|
28534
29185
|
axesDesign: context.axesDesign,
|
|
28535
29186
|
showValues: context.showValues,
|
|
29187
|
+
zoomable: context.zoomable,
|
|
28536
29188
|
};
|
|
28537
29189
|
}
|
|
28538
29190
|
getDefinition() {
|
|
@@ -28560,6 +29212,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28560
29212
|
aggregated: this.aggregated,
|
|
28561
29213
|
axesDesign: this.axesDesign,
|
|
28562
29214
|
showValues: this.showValues,
|
|
29215
|
+
zoomable: this.zoomable,
|
|
28563
29216
|
};
|
|
28564
29217
|
}
|
|
28565
29218
|
getContextCreation() {
|
|
@@ -28944,6 +29597,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28944
29597
|
dataSetDesign;
|
|
28945
29598
|
axesDesign;
|
|
28946
29599
|
showValues;
|
|
29600
|
+
zoomable;
|
|
28947
29601
|
constructor(definition, sheetId, getters) {
|
|
28948
29602
|
super(definition, sheetId, getters);
|
|
28949
29603
|
this.dataSets = createDataSets(getters, definition.dataSets, sheetId, definition.dataSetsHaveTitle);
|
|
@@ -28962,6 +29616,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28962
29616
|
this.dataSetDesign = definition.dataSets;
|
|
28963
29617
|
this.axesDesign = definition.axesDesign;
|
|
28964
29618
|
this.showValues = definition.showValues;
|
|
29619
|
+
this.zoomable = definition.zoomable;
|
|
28965
29620
|
}
|
|
28966
29621
|
static transformDefinition(chartSheetId, definition, applyChange) {
|
|
28967
29622
|
return transformChartDefinitionWithDataSetsWithZone(chartSheetId, definition, applyChange);
|
|
@@ -28985,6 +29640,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
28985
29640
|
firstValueAsSubtotal: context.firstValueAsSubtotal ?? false,
|
|
28986
29641
|
axesDesign: context.axesDesign,
|
|
28987
29642
|
showValues: context.showValues,
|
|
29643
|
+
zoomable: context.zoomable ?? false,
|
|
28988
29644
|
};
|
|
28989
29645
|
}
|
|
28990
29646
|
getContextCreation() {
|
|
@@ -29044,6 +29700,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29044
29700
|
firstValueAsSubtotal: this.firstValueAsSubtotal,
|
|
29045
29701
|
axesDesign: this.axesDesign,
|
|
29046
29702
|
showValues: this.showValues,
|
|
29703
|
+
zoomable: this.zoomable,
|
|
29047
29704
|
};
|
|
29048
29705
|
}
|
|
29049
29706
|
getDefinitionForExcel() {
|
|
@@ -29220,14 +29877,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29220
29877
|
sequence: 100,
|
|
29221
29878
|
});
|
|
29222
29879
|
const chartComponentRegistry = new Registry();
|
|
29223
|
-
chartComponentRegistry.add("line",
|
|
29224
|
-
chartComponentRegistry.add("bar",
|
|
29225
|
-
chartComponentRegistry.add("combo",
|
|
29880
|
+
chartComponentRegistry.add("line", ZoomableChartJsComponent);
|
|
29881
|
+
chartComponentRegistry.add("bar", ZoomableChartJsComponent);
|
|
29882
|
+
chartComponentRegistry.add("combo", ZoomableChartJsComponent);
|
|
29226
29883
|
chartComponentRegistry.add("pie", ChartJsComponent);
|
|
29227
29884
|
chartComponentRegistry.add("gauge", GaugeChartComponent);
|
|
29228
|
-
chartComponentRegistry.add("scatter",
|
|
29885
|
+
chartComponentRegistry.add("scatter", ZoomableChartJsComponent);
|
|
29229
29886
|
chartComponentRegistry.add("scorecard", ScorecardChart);
|
|
29230
|
-
chartComponentRegistry.add("waterfall",
|
|
29887
|
+
chartComponentRegistry.add("waterfall", ZoomableChartJsComponent);
|
|
29231
29888
|
chartComponentRegistry.add("pyramid", ChartJsComponent);
|
|
29232
29889
|
chartComponentRegistry.add("radar", ChartJsComponent);
|
|
29233
29890
|
chartComponentRegistry.add("geo", ChartJsComponent);
|
|
@@ -29426,12 +30083,70 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29426
30083
|
preview: "o-spreadsheet-ChartPreview.TREE_MAP_CHART",
|
|
29427
30084
|
});
|
|
29428
30085
|
|
|
30086
|
+
function generateMasterChartConfig(chartJsConfig) {
|
|
30087
|
+
return {
|
|
30088
|
+
...chartJsConfig,
|
|
30089
|
+
data: {
|
|
30090
|
+
...chartJsConfig.data,
|
|
30091
|
+
datasets: chartJsConfig.data.datasets
|
|
30092
|
+
.filter((ds) => !isTrendLineAxis(ds["xAxisID"]))
|
|
30093
|
+
.map((ds) => ({
|
|
30094
|
+
...ds,
|
|
30095
|
+
pointRadius: 0,
|
|
30096
|
+
showLine: true,
|
|
30097
|
+
})),
|
|
30098
|
+
},
|
|
30099
|
+
options: {
|
|
30100
|
+
...chartJsConfig.options,
|
|
30101
|
+
hover: { mode: null },
|
|
30102
|
+
plugins: {
|
|
30103
|
+
...chartJsConfig.options.plugins,
|
|
30104
|
+
title: { display: false },
|
|
30105
|
+
legend: { display: false },
|
|
30106
|
+
tooltip: { enabled: false },
|
|
30107
|
+
chartShowValuesPlugin: undefined,
|
|
30108
|
+
},
|
|
30109
|
+
layout: {
|
|
30110
|
+
padding: {
|
|
30111
|
+
...chartJsConfig.options.layout?.padding,
|
|
30112
|
+
top: 5,
|
|
30113
|
+
bottom: 10,
|
|
30114
|
+
},
|
|
30115
|
+
},
|
|
30116
|
+
scales: {
|
|
30117
|
+
y: {
|
|
30118
|
+
...chartJsConfig.options.scales?.y,
|
|
30119
|
+
display: false,
|
|
30120
|
+
},
|
|
30121
|
+
y1: {
|
|
30122
|
+
...chartJsConfig.options.scales?.y1,
|
|
30123
|
+
display: false,
|
|
30124
|
+
},
|
|
30125
|
+
x: {
|
|
30126
|
+
...chartJsConfig.options.scales?.x,
|
|
30127
|
+
title: undefined,
|
|
30128
|
+
ticks: {
|
|
30129
|
+
...chartJsConfig.options.scales?.x?.ticks,
|
|
30130
|
+
callback: function (value) {
|
|
30131
|
+
return truncateLabel(chartJsConfig.options.scales?.x?.ticks?.callback?.call(this, value), 5);
|
|
30132
|
+
},
|
|
30133
|
+
padding: 0,
|
|
30134
|
+
font: {
|
|
30135
|
+
size: 9,
|
|
30136
|
+
},
|
|
30137
|
+
},
|
|
30138
|
+
},
|
|
30139
|
+
},
|
|
30140
|
+
},
|
|
30141
|
+
};
|
|
30142
|
+
}
|
|
30143
|
+
|
|
29429
30144
|
/**
|
|
29430
30145
|
* Create a function used to create a Chart based on the definition
|
|
29431
30146
|
*/
|
|
29432
30147
|
function chartFactory(getters) {
|
|
29433
30148
|
const builders = chartRegistry.getAll().sort((a, b) => a.sequence - b.sequence);
|
|
29434
|
-
function createChart(
|
|
30149
|
+
function createChart(figureId, definition, sheetId) {
|
|
29435
30150
|
const builder = builders.find((builder) => builder.match(definition.type));
|
|
29436
30151
|
if (!builder) {
|
|
29437
30152
|
throw new Error(`No builder for this chart: ${definition.type}`);
|
|
@@ -29451,7 +30166,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29451
30166
|
if (!builder) {
|
|
29452
30167
|
throw new Error("No runtime builder for this chart.");
|
|
29453
30168
|
}
|
|
29454
|
-
|
|
30169
|
+
const runtime = builder.getChartRuntime(chart, getters);
|
|
30170
|
+
const definition = chart.getDefinition();
|
|
30171
|
+
if ("chartJsConfig" in runtime && /line|combo|bar|scatter|waterfall/.test(definition.type)) {
|
|
30172
|
+
const chartJsConfig = runtime.chartJsConfig;
|
|
30173
|
+
runtime["masterChartConfig"] = generateMasterChartConfig(chartJsConfig);
|
|
30174
|
+
}
|
|
30175
|
+
return runtime;
|
|
29455
30176
|
}
|
|
29456
30177
|
return createRuntimeChart;
|
|
29457
30178
|
}
|
|
@@ -29782,6 +30503,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29782
30503
|
return {
|
|
29783
30504
|
relsFiles: [],
|
|
29784
30505
|
sharedStrings: [],
|
|
30506
|
+
chartIds: [],
|
|
30507
|
+
imageIds: [],
|
|
29785
30508
|
// default Values that will always be part of the style sheet
|
|
29786
30509
|
styles: [
|
|
29787
30510
|
{
|
|
@@ -29859,6 +30582,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29859
30582
|
}
|
|
29860
30583
|
|
|
29861
30584
|
function getChartMenuActions(figureId, onFigureDeleted, env) {
|
|
30585
|
+
const chartId = env.model.getters.getChartIdFromFigureId(figureId);
|
|
30586
|
+
if (!chartId) {
|
|
30587
|
+
return [];
|
|
30588
|
+
}
|
|
29862
30589
|
const menuItemSpecs = [
|
|
29863
30590
|
{
|
|
29864
30591
|
id: "edit",
|
|
@@ -29881,8 +30608,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29881
30608
|
execute: async () => {
|
|
29882
30609
|
const figureSheetId = env.model.getters.getFigureSheetId(figureId);
|
|
29883
30610
|
const figure = env.model.getters.getFigure(figureSheetId, figureId);
|
|
29884
|
-
const chartType = env.model.getters.getChartType(
|
|
29885
|
-
const runtime = env.model.getters.getChartRuntime(
|
|
30611
|
+
const chartType = env.model.getters.getChartType(chartId);
|
|
30612
|
+
const runtime = env.model.getters.getChartRuntime(chartId);
|
|
29886
30613
|
const imageUrl = chartToImageUrl(runtime, figure, chartType);
|
|
29887
30614
|
const innerHTML = `<img src="${xmlEscape(imageUrl)}" />`;
|
|
29888
30615
|
const blob = await chartToImageFile(runtime, figure, chartType);
|
|
@@ -29902,8 +30629,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29902
30629
|
execute: async () => {
|
|
29903
30630
|
const figureSheetId = env.model.getters.getFigureSheetId(figureId);
|
|
29904
30631
|
const figure = env.model.getters.getFigure(figureSheetId, figureId);
|
|
29905
|
-
const chartType = env.model.getters.getChartType(
|
|
29906
|
-
const runtime = env.model.getters.getChartRuntime(
|
|
30632
|
+
const chartType = env.model.getters.getChartType(chartId);
|
|
30633
|
+
const runtime = env.model.getters.getChartRuntime(chartId);
|
|
29907
30634
|
const url = chartToImageUrl(runtime, figure, chartType);
|
|
29908
30635
|
downloadFile(url, "chart");
|
|
29909
30636
|
},
|
|
@@ -29962,6 +30689,35 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
29962
30689
|
];
|
|
29963
30690
|
return createActions(menuItemSpecs);
|
|
29964
30691
|
}
|
|
30692
|
+
function getCarouselMenuActions(figureId, onFigureDeleted, env) {
|
|
30693
|
+
const menuItemSpecs = [
|
|
30694
|
+
{
|
|
30695
|
+
id: "edit_carousel",
|
|
30696
|
+
name: _t("Edit carousel"),
|
|
30697
|
+
sequence: 1,
|
|
30698
|
+
execute: () => {
|
|
30699
|
+
env.model.dispatch("SELECT_FIGURE", { figureId });
|
|
30700
|
+
env.openSidePanel("CarouselPanel", { figureId });
|
|
30701
|
+
},
|
|
30702
|
+
icon: "o-spreadsheet-Icon.EDIT",
|
|
30703
|
+
isEnabled: (env) => !env.isSmall,
|
|
30704
|
+
},
|
|
30705
|
+
{
|
|
30706
|
+
id: "edit_chart",
|
|
30707
|
+
name: _t("Edit chart"),
|
|
30708
|
+
sequence: 1,
|
|
30709
|
+
execute: () => {
|
|
30710
|
+
env.model.dispatch("SELECT_FIGURE", { figureId });
|
|
30711
|
+
env.openSidePanel("ChartPanel", {});
|
|
30712
|
+
},
|
|
30713
|
+
icon: "o-spreadsheet-Icon.EDIT",
|
|
30714
|
+
isEnabled: (env) => !env.isSmall,
|
|
30715
|
+
isVisible: (env) => env.model.getters.getSelectedCarouselItem(figureId)?.type === "chart",
|
|
30716
|
+
},
|
|
30717
|
+
getDeleteMenuItem(figureId, onFigureDeleted, env),
|
|
30718
|
+
];
|
|
30719
|
+
return createActions(menuItemSpecs).filter((action) => env.model.getters.isReadonly() ? action.isReadonlyAllowed : true);
|
|
30720
|
+
}
|
|
29965
30721
|
function getCopyMenuItem(figureId, env, copiedNotificationMessage) {
|
|
29966
30722
|
return {
|
|
29967
30723
|
id: "copy",
|
|
@@ -30010,24 +30766,101 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30010
30766
|
};
|
|
30011
30767
|
}
|
|
30012
30768
|
|
|
30013
|
-
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
|
|
30017
|
-
|
|
30018
|
-
|
|
30769
|
+
const CAROUSEL_DEFAULT_CHART_DEFINITION = {
|
|
30770
|
+
type: "bar",
|
|
30771
|
+
title: {},
|
|
30772
|
+
stacked: false,
|
|
30773
|
+
dataSetsHaveTitle: false,
|
|
30774
|
+
dataSets: [],
|
|
30775
|
+
legendPosition: "top",
|
|
30776
|
+
};
|
|
30777
|
+
function getCarouselItemPreview(getters, item) {
|
|
30778
|
+
if (item.type === "carouselDataView") {
|
|
30779
|
+
return "o-spreadsheet-Icon.LIST";
|
|
30780
|
+
}
|
|
30781
|
+
const definition = getters.getChartDefinition(item.chartId);
|
|
30782
|
+
const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
|
|
30783
|
+
chartSubtypeRegistry.get(definition.type);
|
|
30784
|
+
return matchedChart.preview;
|
|
30785
|
+
}
|
|
30786
|
+
function getCarouselItemTitle(getters, item) {
|
|
30787
|
+
if (item.title) {
|
|
30788
|
+
return item.title;
|
|
30789
|
+
}
|
|
30790
|
+
if (item.type === "carouselDataView") {
|
|
30791
|
+
return _t("Data");
|
|
30792
|
+
}
|
|
30793
|
+
const definition = getters.getChartDefinition(item.chartId);
|
|
30794
|
+
const matchedChart = chartSubtypeRegistry.getAll().find((c) => c.matcher?.(definition)) ||
|
|
30795
|
+
chartSubtypeRegistry.get(definition.type);
|
|
30796
|
+
return matchedChart.displayName;
|
|
30797
|
+
}
|
|
30798
|
+
|
|
30799
|
+
class CarouselFigure extends owl.Component {
|
|
30800
|
+
static template = "o-spreadsheet-CarouselFigure";
|
|
30801
|
+
static props = {
|
|
30802
|
+
figureUI: Object,
|
|
30803
|
+
onFigureDeleted: Function,
|
|
30804
|
+
editFigureStyle: { type: Function, optional: true },
|
|
30805
|
+
};
|
|
30806
|
+
static components = {};
|
|
30807
|
+
setup() {
|
|
30808
|
+
owl.useEffect(() => {
|
|
30809
|
+
if (this.selectedCarouselItem?.type === "carouselDataView") {
|
|
30810
|
+
this.props.editFigureStyle?.({ "pointer-events": "none" });
|
|
30811
|
+
}
|
|
30812
|
+
else {
|
|
30813
|
+
this.props.editFigureStyle?.({ "pointer-events": "auto" });
|
|
30814
|
+
}
|
|
30815
|
+
});
|
|
30816
|
+
}
|
|
30817
|
+
get carousel() {
|
|
30818
|
+
return this.env.model.getters.getCarousel(this.props.figureUI.id);
|
|
30819
|
+
}
|
|
30820
|
+
get selectedCarouselItem() {
|
|
30821
|
+
return this.env.model.getters.getSelectedCarouselItem(this.props.figureUI.id);
|
|
30822
|
+
}
|
|
30823
|
+
get chartComponent() {
|
|
30824
|
+
const selectedItem = this.selectedCarouselItem;
|
|
30825
|
+
if (selectedItem?.type !== "chart") {
|
|
30826
|
+
throw new Error("Selected item is not a chart");
|
|
30019
30827
|
}
|
|
30020
|
-
|
|
30021
|
-
|
|
30828
|
+
const type = this.env.model.getters.getChartType(selectedItem.chartId);
|
|
30829
|
+
const component = chartComponentRegistry.get(type);
|
|
30830
|
+
if (!component) {
|
|
30831
|
+
throw new Error(`Component is not defined for type ${type}`);
|
|
30022
30832
|
}
|
|
30833
|
+
return component;
|
|
30023
30834
|
}
|
|
30024
|
-
|
|
30025
|
-
|
|
30026
|
-
|
|
30027
|
-
|
|
30028
|
-
|
|
30835
|
+
onCarouselDoubleClick() {
|
|
30836
|
+
this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureUI.id });
|
|
30837
|
+
this.env.openSidePanel("CarouselPanel", { figureId: this.props.figureUI.id });
|
|
30838
|
+
}
|
|
30839
|
+
isItemSelected(item) {
|
|
30840
|
+
const selectedItem = this.selectedCarouselItem;
|
|
30841
|
+
return deepEquals(selectedItem, item);
|
|
30842
|
+
}
|
|
30843
|
+
getItemTitle(item) {
|
|
30844
|
+
return getCarouselItemTitle(this.env.model.getters, item);
|
|
30845
|
+
}
|
|
30846
|
+
onCarouselTabClick(item) {
|
|
30847
|
+
this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
|
|
30848
|
+
figureId: this.props.figureUI.id,
|
|
30849
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
30850
|
+
item,
|
|
30851
|
+
});
|
|
30852
|
+
if (item.type === "carouselDataView" &&
|
|
30853
|
+
this.env.model.getters.getSelectedFigureId() === this.props.figureUI.id) {
|
|
30854
|
+
this.env.model.dispatch("SELECT_FIGURE", { figureId: null });
|
|
30029
30855
|
}
|
|
30030
30856
|
}
|
|
30857
|
+
get headerStyle() {
|
|
30858
|
+
const cssProperties = {};
|
|
30859
|
+
if (this.selectedCarouselItem?.type === "carouselDataView") {
|
|
30860
|
+
cssProperties["background-color"] = "#ffffff";
|
|
30861
|
+
}
|
|
30862
|
+
return cssPropertiesToCss(cssProperties);
|
|
30863
|
+
}
|
|
30031
30864
|
}
|
|
30032
30865
|
|
|
30033
30866
|
/**
|
|
@@ -30794,9 +31627,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30794
31627
|
this.originalChartDefinition = this.getters.getChartDefinition(chartId);
|
|
30795
31628
|
}
|
|
30796
31629
|
updateType(type) {
|
|
30797
|
-
const
|
|
30798
|
-
const currentDefinition = this.getters.getChartDefinition(
|
|
30799
|
-
if (currentDefinition
|
|
31630
|
+
const chartId = this.chartId;
|
|
31631
|
+
const currentDefinition = this.getters.getChartDefinition(chartId);
|
|
31632
|
+
if (currentDefinition?.type === type) {
|
|
30800
31633
|
return;
|
|
30801
31634
|
}
|
|
30802
31635
|
let definition;
|
|
@@ -30806,7 +31639,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30806
31639
|
else {
|
|
30807
31640
|
const newChartInfo = chartSubtypeRegistry.get(type);
|
|
30808
31641
|
const ChartClass = chartRegistry.get(newChartInfo.chartType);
|
|
30809
|
-
const chartCreationContext = this.getters.getContextCreationChart(
|
|
31642
|
+
const chartCreationContext = this.getters.getContextCreationChart(chartId);
|
|
30810
31643
|
if (!chartCreationContext)
|
|
30811
31644
|
return;
|
|
30812
31645
|
definition = {
|
|
@@ -30816,7 +31649,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30816
31649
|
}
|
|
30817
31650
|
this.model.dispatch("UPDATE_CHART", {
|
|
30818
31651
|
definition,
|
|
30819
|
-
|
|
31652
|
+
chartId,
|
|
31653
|
+
figureId: this.getters.getFigureIdFromChartId(chartId),
|
|
30820
31654
|
sheetId: this.getters.getActiveSheetId(),
|
|
30821
31655
|
});
|
|
30822
31656
|
}
|
|
@@ -30837,17 +31671,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30837
31671
|
class ChartDashboardMenu extends owl.Component {
|
|
30838
31672
|
static template = "o-spreadsheet-ChartDashboardMenu";
|
|
30839
31673
|
static components = { MenuPopover };
|
|
30840
|
-
static props = {
|
|
31674
|
+
static props = { chartId: String };
|
|
30841
31675
|
fullScreenFigureStore;
|
|
30842
31676
|
store;
|
|
30843
31677
|
menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
30844
31678
|
setup() {
|
|
30845
31679
|
super.setup();
|
|
30846
|
-
this.store = useLocalStore(ChartDashboardMenuStore, this.props.
|
|
31680
|
+
this.store = useLocalStore(ChartDashboardMenuStore, this.props.chartId);
|
|
30847
31681
|
this.fullScreenFigureStore = useStore(FullScreenChartStore);
|
|
30848
|
-
owl.onWillUpdateProps(({
|
|
30849
|
-
if (
|
|
30850
|
-
this.store.reset(
|
|
31682
|
+
owl.onWillUpdateProps(({ chartId }) => {
|
|
31683
|
+
if (chartId !== this.props.chartId) {
|
|
31684
|
+
this.store.reset(chartId);
|
|
30851
31685
|
}
|
|
30852
31686
|
});
|
|
30853
31687
|
}
|
|
@@ -30855,26 +31689,28 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30855
31689
|
return [this.fullScreenMenuItem, ...this.store.changeChartTypeMenuItems].filter(isDefined);
|
|
30856
31690
|
}
|
|
30857
31691
|
get backgroundColor() {
|
|
30858
|
-
const color = this.env.model.getters.getChartDefinition(this.props.
|
|
31692
|
+
const color = this.env.model.getters.getChartDefinition(this.props.chartId).background;
|
|
30859
31693
|
return "background-color: " + (color || BACKGROUND_CHART_COLOR);
|
|
30860
31694
|
}
|
|
30861
31695
|
openContextMenu(ev) {
|
|
30862
31696
|
this.menuState.isOpen = true;
|
|
30863
31697
|
this.menuState.anchorRect = { x: ev.clientX, y: ev.clientY, width: 0, height: 0 };
|
|
30864
|
-
|
|
31698
|
+
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
31699
|
+
this.menuState.menuItems = getChartMenuActions(figureId, () => { }, this.env);
|
|
30865
31700
|
}
|
|
30866
31701
|
get fullScreenMenuItem() {
|
|
30867
|
-
const definition = this.env.model.getters.getChartDefinition(this.props.
|
|
31702
|
+
const definition = this.env.model.getters.getChartDefinition(this.props.chartId);
|
|
31703
|
+
const figureId = this.env.model.getters.getFigureIdFromChartId(this.props.chartId);
|
|
30868
31704
|
if (definition.type === "scorecard") {
|
|
30869
31705
|
return undefined;
|
|
30870
31706
|
}
|
|
30871
|
-
if (this.props.
|
|
31707
|
+
if (this.props.chartId === this.fullScreenFigureStore.fullScreenFigure?.id) {
|
|
30872
31708
|
return {
|
|
30873
31709
|
id: "fullScreenChart",
|
|
30874
31710
|
label: _t("Exit Full Screen"),
|
|
30875
31711
|
iconClass: "fa fa-compress",
|
|
30876
31712
|
onClick: () => {
|
|
30877
|
-
this.fullScreenFigureStore.toggleFullScreenChart(
|
|
31713
|
+
this.fullScreenFigureStore.toggleFullScreenChart(figureId);
|
|
30878
31714
|
},
|
|
30879
31715
|
};
|
|
30880
31716
|
}
|
|
@@ -30883,27 +31719,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30883
31719
|
label: _t("Full Screen"),
|
|
30884
31720
|
iconClass: "fa fa-expand",
|
|
30885
31721
|
onClick: () => {
|
|
30886
|
-
this.fullScreenFigureStore.toggleFullScreenChart(
|
|
31722
|
+
this.fullScreenFigureStore.toggleFullScreenChart(figureId);
|
|
30887
31723
|
},
|
|
30888
31724
|
};
|
|
30889
31725
|
}
|
|
30890
31726
|
}
|
|
30891
31727
|
|
|
30892
|
-
// -----------------------------------------------------------------------------
|
|
30893
|
-
// STYLE
|
|
30894
|
-
// -----------------------------------------------------------------------------
|
|
30895
|
-
css /* scss */ `
|
|
30896
|
-
.o-chart-container {
|
|
30897
|
-
width: 100%;
|
|
30898
|
-
height: 100%;
|
|
30899
|
-
position: relative;
|
|
30900
|
-
}
|
|
30901
|
-
`;
|
|
30902
31728
|
class ChartFigure extends owl.Component {
|
|
30903
31729
|
static template = "o-spreadsheet-ChartFigure";
|
|
30904
31730
|
static props = {
|
|
30905
31731
|
figureUI: Object,
|
|
30906
31732
|
onFigureDeleted: Function,
|
|
31733
|
+
editFigureStyle: { type: Function, optional: true },
|
|
30907
31734
|
};
|
|
30908
31735
|
static components = { ChartDashboardMenu };
|
|
30909
31736
|
onDoubleClick() {
|
|
@@ -30911,7 +31738,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30911
31738
|
this.env.openSidePanel("ChartPanel");
|
|
30912
31739
|
}
|
|
30913
31740
|
get chartType() {
|
|
30914
|
-
return this.env.model.getters.getChartType(this.
|
|
31741
|
+
return this.env.model.getters.getChartType(this.chartId);
|
|
31742
|
+
}
|
|
31743
|
+
get chartId() {
|
|
31744
|
+
const chartId = this.env.model.getters.getChartIdFromFigureId(this.props.figureUI.id);
|
|
31745
|
+
if (!chartId) {
|
|
31746
|
+
throw new Error(`No chart found for figure ID: ${this.props.figureUI.id}`);
|
|
31747
|
+
}
|
|
31748
|
+
return chartId;
|
|
30915
31749
|
}
|
|
30916
31750
|
get chartComponent() {
|
|
30917
31751
|
const type = this.chartType;
|
|
@@ -30928,6 +31762,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30928
31762
|
static props = {
|
|
30929
31763
|
figureUI: Object,
|
|
30930
31764
|
onFigureDeleted: Function,
|
|
31765
|
+
editFigureStyle: { type: Function, optional: true },
|
|
30931
31766
|
};
|
|
30932
31767
|
static components = {};
|
|
30933
31768
|
// ---------------------------------------------------------------------------
|
|
@@ -30954,6 +31789,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30954
31789
|
borderWidth: 0,
|
|
30955
31790
|
menuBuilder: getImageMenuActions,
|
|
30956
31791
|
});
|
|
31792
|
+
figureRegistry.add("carousel", {
|
|
31793
|
+
Component: CarouselFigure,
|
|
31794
|
+
menuBuilder: getCarouselMenuActions,
|
|
31795
|
+
});
|
|
30957
31796
|
|
|
30958
31797
|
// -----------------------------------------------------------------------------
|
|
30959
31798
|
// STYLE
|
|
@@ -30980,6 +31819,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
30980
31819
|
.o-figure-wrapper {
|
|
30981
31820
|
position: absolute;
|
|
30982
31821
|
box-sizing: content-box;
|
|
31822
|
+
pointer-events: auto;
|
|
30983
31823
|
|
|
30984
31824
|
.o-fig-anchor {
|
|
30985
31825
|
z-index: ${ComponentsImportance.FigureAnchor};
|
|
@@ -31038,6 +31878,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31038
31878
|
static props = {
|
|
31039
31879
|
figureUI: Object,
|
|
31040
31880
|
style: { type: String, optional: true },
|
|
31881
|
+
class: { type: String, optional: true },
|
|
31041
31882
|
onFigureDeleted: { type: Function, optional: true },
|
|
31042
31883
|
onMouseDown: { type: Function, optional: true },
|
|
31043
31884
|
onClickAnchor: { type: Function, optional: true },
|
|
@@ -31050,6 +31891,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31050
31891
|
};
|
|
31051
31892
|
menuState = owl.useState({ isOpen: false, anchorRect: null, menuItems: [] });
|
|
31052
31893
|
figureRef = owl.useRef("figure");
|
|
31894
|
+
figureWrapperRef = owl.useRef("figureWrapper");
|
|
31053
31895
|
menuButtonRef = owl.useRef("menuButton");
|
|
31054
31896
|
borderWidth;
|
|
31055
31897
|
get isSelected() {
|
|
@@ -31242,6 +32084,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
31242
32084
|
.get(this.props.figureUI.tag)
|
|
31243
32085
|
.menuBuilder(this.props.figureUI.id, this.props.onFigureDeleted, this.env);
|
|
31244
32086
|
}
|
|
32087
|
+
editWrapperStyle(properties) {
|
|
32088
|
+
if (this.figureWrapperRef.el) {
|
|
32089
|
+
for (const property in properties) {
|
|
32090
|
+
this.figureWrapperRef.el.style.setProperty(property, properties[property] || null);
|
|
32091
|
+
}
|
|
32092
|
+
}
|
|
32093
|
+
}
|
|
31245
32094
|
}
|
|
31246
32095
|
|
|
31247
32096
|
class DelayedHoveredCellStore extends SpreadsheetStore {
|
|
@@ -38774,16 +39623,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
38774
39623
|
reverseLookup.set(canonical, maxId);
|
|
38775
39624
|
return maxId;
|
|
38776
39625
|
}
|
|
38777
|
-
const chartIds = [];
|
|
38778
39626
|
/**
|
|
38779
39627
|
* Convert a chart o-spreadsheet id to a xlsx id which
|
|
38780
39628
|
* are unsigned integers (starting from 1).
|
|
38781
39629
|
*/
|
|
38782
|
-
function convertChartId(chartId) {
|
|
38783
|
-
const xlsxId = chartIds.findIndex((id) => id === chartId);
|
|
39630
|
+
function convertChartId(chartId, construct) {
|
|
39631
|
+
const xlsxId = construct.chartIds.findIndex((id) => id === chartId);
|
|
38784
39632
|
if (xlsxId === -1) {
|
|
38785
|
-
chartIds.push(chartId);
|
|
38786
|
-
return chartIds.length;
|
|
39633
|
+
construct.chartIds.push(chartId);
|
|
39634
|
+
return construct.chartIds.length;
|
|
38787
39635
|
}
|
|
38788
39636
|
return xlsxId + 1;
|
|
38789
39637
|
}
|
|
@@ -41178,6 +42026,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41178
42026
|
sheets: sheets,
|
|
41179
42027
|
sharedStrings,
|
|
41180
42028
|
externalBooks,
|
|
42029
|
+
chartIds: [],
|
|
42030
|
+
imageIds: [],
|
|
41181
42031
|
};
|
|
41182
42032
|
}
|
|
41183
42033
|
buildXlsxFileStructure() {
|
|
@@ -41855,6 +42705,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
41855
42705
|
}
|
|
41856
42706
|
return data;
|
|
41857
42707
|
},
|
|
42708
|
+
})
|
|
42709
|
+
.add("18.5.1", {
|
|
42710
|
+
migrate(data) {
|
|
42711
|
+
for (const sheet of data.sheets || []) {
|
|
42712
|
+
for (const figure of sheet.figures || []) {
|
|
42713
|
+
if (figure.tag === "chart") {
|
|
42714
|
+
figure.data.chartId = figure.id;
|
|
42715
|
+
}
|
|
42716
|
+
}
|
|
42717
|
+
}
|
|
42718
|
+
return data;
|
|
42719
|
+
},
|
|
41858
42720
|
});
|
|
41859
42721
|
function fixOverlappingFilters(data) {
|
|
41860
42722
|
for (const sheet of data.sheets || []) {
|
|
@@ -42108,7 +42970,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42108
42970
|
sheet.figures?.forEach((figure) => {
|
|
42109
42971
|
if (figure.tag === "chart") {
|
|
42110
42972
|
// chart definition
|
|
42111
|
-
|
|
42973
|
+
if (data.version && compareVersions(String(data.version), "18.5.1") <= 0) {
|
|
42974
|
+
map[figure.data.chartId] = figure.data;
|
|
42975
|
+
}
|
|
42976
|
+
else {
|
|
42977
|
+
map[figure.id] = figure.data;
|
|
42978
|
+
}
|
|
42112
42979
|
}
|
|
42113
42980
|
});
|
|
42114
42981
|
}
|
|
@@ -42119,20 +42986,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42119
42986
|
let command = cmd;
|
|
42120
42987
|
switch (cmd.type) {
|
|
42121
42988
|
case "CREATE_CHART":
|
|
42122
|
-
map[cmd.
|
|
42989
|
+
map[cmd.chartId] = cmd.definition;
|
|
42123
42990
|
break;
|
|
42124
42991
|
case "UPDATE_CHART":
|
|
42125
|
-
if (!map[cmd.
|
|
42992
|
+
if (!map[cmd.chartId]) {
|
|
42126
42993
|
/** the chart does not exist on the map, it might have been created after a duplicate sheet.
|
|
42127
42994
|
* We don't have access to the definition, so we skip the command.
|
|
42128
42995
|
*/
|
|
42129
|
-
console.log(`Fix chart definition: chart with id ${cmd.
|
|
42996
|
+
console.log(`Fix chart definition: chart with id ${cmd.chartId} not found.`);
|
|
42130
42997
|
continue;
|
|
42131
42998
|
}
|
|
42132
|
-
const definition = map[cmd.
|
|
42999
|
+
const definition = map[cmd.chartId];
|
|
42133
43000
|
const newDefinition = { ...definition, ...cmd.definition };
|
|
42134
43001
|
command = { ...cmd, definition: newDefinition };
|
|
42135
|
-
map[cmd.
|
|
43002
|
+
map[cmd.chartId] = newDefinition;
|
|
42136
43003
|
break;
|
|
42137
43004
|
}
|
|
42138
43005
|
commands.push(command);
|
|
@@ -42705,6 +43572,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42705
43572
|
const result = env.model.dispatch("CREATE_CHART", {
|
|
42706
43573
|
sheetId,
|
|
42707
43574
|
figureId,
|
|
43575
|
+
chartId: figureId,
|
|
42708
43576
|
col,
|
|
42709
43577
|
row,
|
|
42710
43578
|
offset,
|
|
@@ -42716,6 +43584,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42716
43584
|
env.openSidePanel("ChartPanel");
|
|
42717
43585
|
}
|
|
42718
43586
|
};
|
|
43587
|
+
const CREATE_CAROUSEL = (env) => {
|
|
43588
|
+
const getters = env.model.getters;
|
|
43589
|
+
const figureId = env.model.uuidGenerator.smallUuid();
|
|
43590
|
+
const sheetId = getters.getActiveSheetId();
|
|
43591
|
+
const size = { width: DEFAULT_FIGURE_WIDTH, height: DEFAULT_FIGURE_HEIGHT };
|
|
43592
|
+
const { col, row, offset } = centerFigurePosition(getters, size);
|
|
43593
|
+
const result = env.model.dispatch("CREATE_CAROUSEL", {
|
|
43594
|
+
sheetId,
|
|
43595
|
+
figureId,
|
|
43596
|
+
col,
|
|
43597
|
+
row,
|
|
43598
|
+
offset,
|
|
43599
|
+
size,
|
|
43600
|
+
definition: { items: [] },
|
|
43601
|
+
});
|
|
43602
|
+
if (result.isSuccessful) {
|
|
43603
|
+
env.model.dispatch("SELECT_FIGURE", { figureId });
|
|
43604
|
+
env.openSidePanel("CarouselPanel", { figureId });
|
|
43605
|
+
}
|
|
43606
|
+
};
|
|
42719
43607
|
//------------------------------------------------------------------------------
|
|
42720
43608
|
// Pivots
|
|
42721
43609
|
//------------------------------------------------------------------------------
|
|
@@ -42752,10 +43640,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
42752
43640
|
sequence: index,
|
|
42753
43641
|
execute: (env) => {
|
|
42754
43642
|
const zone = env.model.getters.getSelectedZone();
|
|
42755
|
-
const table = env.model.getters.getPivot(pivotId).getExpandedTableStructure()
|
|
43643
|
+
const table = env.model.getters.getPivot(pivotId).getExpandedTableStructure();
|
|
43644
|
+
if (table.numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) {
|
|
43645
|
+
env.notifyUser({
|
|
43646
|
+
type: "warning",
|
|
43647
|
+
text: getPivotTooBigErrorMessage(table.numberOfCells, env.model.getters.getLocale()),
|
|
43648
|
+
sticky: true,
|
|
43649
|
+
});
|
|
43650
|
+
return;
|
|
43651
|
+
}
|
|
42756
43652
|
env.model.dispatch("INSERT_PIVOT_WITH_TABLE", {
|
|
42757
43653
|
pivotId,
|
|
42758
|
-
table,
|
|
43654
|
+
table: table.export(),
|
|
42759
43655
|
col: zone.left,
|
|
42760
43656
|
row: zone.top,
|
|
42761
43657
|
sheetId: env.model.getters.getActiveSheetId(),
|
|
@@ -43967,6 +44863,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
43967
44863
|
isEnabled: (env) => !env.isSmall,
|
|
43968
44864
|
icon: "o-spreadsheet-Icon.INSERT_CHART",
|
|
43969
44865
|
};
|
|
44866
|
+
const insertCarousel = {
|
|
44867
|
+
name: _t("Carousel"),
|
|
44868
|
+
execute: CREATE_CAROUSEL,
|
|
44869
|
+
isEnabled: (env) => !env.isSmall,
|
|
44870
|
+
icon: "o-spreadsheet-Icon.CAROUSEL",
|
|
44871
|
+
};
|
|
43970
44872
|
const insertPivot = {
|
|
43971
44873
|
name: _t("Pivot table"),
|
|
43972
44874
|
execute: CREATE_PIVOT,
|
|
@@ -44087,7 +44989,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44087
44989
|
env.openSidePanel("DataValidationEditor", {
|
|
44088
44990
|
rule: localizeDataValidationRule(rule, env.model.getters.getLocale()),
|
|
44089
44991
|
onExit: () => {
|
|
44090
|
-
env.
|
|
44992
|
+
env.replaceSidePanel("DataValidation", "DataValidationEditor");
|
|
44091
44993
|
},
|
|
44092
44994
|
});
|
|
44093
44995
|
},
|
|
@@ -44823,6 +45725,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
44823
45725
|
return [row, ...this.rowTreeToRows(node.children, row)];
|
|
44824
45726
|
});
|
|
44825
45727
|
}
|
|
45728
|
+
get numberOfCells() {
|
|
45729
|
+
return this.rows.length * this.getNumberOfDataColumns();
|
|
45730
|
+
}
|
|
44826
45731
|
}
|
|
44827
45732
|
const EMPTY_PIVOT_CELL = { type: "EMPTY" };
|
|
44828
45733
|
|
|
@@ -48057,6 +48962,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48057
48962
|
horizontalSnap: undefined,
|
|
48058
48963
|
verticalSnap: undefined,
|
|
48059
48964
|
cancelDnd: undefined,
|
|
48965
|
+
overlappingCarousel: undefined,
|
|
48060
48966
|
});
|
|
48061
48967
|
setup() {
|
|
48062
48968
|
owl.onMounted(() => {
|
|
@@ -48079,6 +48985,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48079
48985
|
this.dnd.draggedFigure = undefined;
|
|
48080
48986
|
this.dnd.horizontalSnap = undefined;
|
|
48081
48987
|
this.dnd.verticalSnap = undefined;
|
|
48988
|
+
this.dnd.overlappingCarousel = undefined;
|
|
48082
48989
|
this.dnd.cancelDnd = undefined;
|
|
48083
48990
|
}
|
|
48084
48991
|
});
|
|
@@ -48217,26 +49124,46 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48217
49124
|
const currentMousePosition = { x: ev.clientX, y: ev.clientY };
|
|
48218
49125
|
const draggedFigure = dragFigureForMove(currentMousePosition, initialMousePosition, initialFigure, maxDimensions, initialScrollPosition, getters.getActiveSheetScrollInfo());
|
|
48219
49126
|
const otherFigures = this.getOtherFigures(initialFigure.id);
|
|
48220
|
-
const
|
|
48221
|
-
this.dnd.
|
|
48222
|
-
|
|
48223
|
-
|
|
49127
|
+
const overlappingCarousel = this.getCarouselOverlappingChart(draggedFigure, otherFigures);
|
|
49128
|
+
this.dnd.overlappingCarousel = overlappingCarousel;
|
|
49129
|
+
if (!overlappingCarousel) {
|
|
49130
|
+
const snapResult = snapForMove(getters, draggedFigure, otherFigures);
|
|
49131
|
+
this.dnd.draggedFigure = snapResult.snappedFigure;
|
|
49132
|
+
this.dnd.horizontalSnap = this.getSnap(snapResult.horizontalSnapLine);
|
|
49133
|
+
this.dnd.verticalSnap = this.getSnap(snapResult.verticalSnapLine);
|
|
49134
|
+
}
|
|
49135
|
+
else {
|
|
49136
|
+
this.dnd.draggedFigure = draggedFigure;
|
|
49137
|
+
this.dnd.horizontalSnap = undefined;
|
|
49138
|
+
this.dnd.verticalSnap = undefined;
|
|
49139
|
+
}
|
|
48224
49140
|
};
|
|
48225
49141
|
const onMouseUp = (ev) => {
|
|
48226
49142
|
if (!this.dnd.draggedFigure) {
|
|
48227
49143
|
return;
|
|
48228
49144
|
}
|
|
48229
49145
|
const { col, row, offset } = this.env.model.getters.getPositionAnchorOffset(this.dnd.draggedFigure);
|
|
49146
|
+
if (!this.dnd.overlappingCarousel) {
|
|
49147
|
+
this.env.model.dispatch("UPDATE_FIGURE", {
|
|
49148
|
+
sheetId,
|
|
49149
|
+
figureId: figureUI.id,
|
|
49150
|
+
offset,
|
|
49151
|
+
col,
|
|
49152
|
+
row,
|
|
49153
|
+
});
|
|
49154
|
+
}
|
|
49155
|
+
else {
|
|
49156
|
+
this.env.model.dispatch("ADD_FIGURE_CHART_TO_CAROUSEL", {
|
|
49157
|
+
sheetId,
|
|
49158
|
+
carouselFigureId: this.dnd.overlappingCarousel.id,
|
|
49159
|
+
chartFigureId: figureUI.id,
|
|
49160
|
+
});
|
|
49161
|
+
this.props.onFigureDeleted();
|
|
49162
|
+
}
|
|
48230
49163
|
this.dnd.draggedFigure = undefined;
|
|
48231
49164
|
this.dnd.horizontalSnap = undefined;
|
|
48232
49165
|
this.dnd.verticalSnap = undefined;
|
|
48233
|
-
this.
|
|
48234
|
-
sheetId,
|
|
48235
|
-
figureId: figureUI.id,
|
|
48236
|
-
offset,
|
|
48237
|
-
col,
|
|
48238
|
-
row,
|
|
48239
|
-
});
|
|
49166
|
+
this.dnd.overlappingCarousel = undefined;
|
|
48240
49167
|
};
|
|
48241
49168
|
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
|
|
48242
49169
|
}
|
|
@@ -48288,6 +49215,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48288
49215
|
this.dnd.draggedFigure = undefined;
|
|
48289
49216
|
this.dnd.horizontalSnap = undefined;
|
|
48290
49217
|
this.dnd.verticalSnap = undefined;
|
|
49218
|
+
this.dnd.overlappingCarousel = undefined;
|
|
48291
49219
|
};
|
|
48292
49220
|
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
|
|
48293
49221
|
}
|
|
@@ -48304,10 +49232,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48304
49232
|
if (figureUI.id !== this.dnd.draggedFigure?.id)
|
|
48305
49233
|
return "";
|
|
48306
49234
|
return cssPropertiesToCss({
|
|
48307
|
-
opacity: "0.9",
|
|
49235
|
+
opacity: this.dnd.overlappingCarousel?.id ? "0.6" : "0.9",
|
|
48308
49236
|
cursor: "grabbing",
|
|
48309
49237
|
});
|
|
48310
49238
|
}
|
|
49239
|
+
getFigureClass(figureUI) {
|
|
49240
|
+
if (figureUI.id !== this.dnd.overlappingCarousel?.id)
|
|
49241
|
+
return "";
|
|
49242
|
+
return "o-add-to-carousel";
|
|
49243
|
+
}
|
|
48311
49244
|
getSnap(snapLine) {
|
|
48312
49245
|
if (!snapLine || !this.dnd.draggedFigure)
|
|
48313
49246
|
return undefined;
|
|
@@ -48354,6 +49287,20 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
48354
49287
|
});
|
|
48355
49288
|
}
|
|
48356
49289
|
}
|
|
49290
|
+
getCarouselOverlappingChart(figureUI, otherFigures) {
|
|
49291
|
+
if (figureUI.tag !== "chart") {
|
|
49292
|
+
return undefined;
|
|
49293
|
+
}
|
|
49294
|
+
const minimumOverlap = 20; // Minimum overlap in pixels to consider a carousel overlapping
|
|
49295
|
+
const carousels = otherFigures.filter((f) => f.tag === "carousel");
|
|
49296
|
+
return carousels.find((carousel) => {
|
|
49297
|
+
const xOverlap = Math.max(0, Math.min(figureUI.x + figureUI.width, carousel.x + carousel.width) -
|
|
49298
|
+
Math.max(figureUI.x, carousel.x));
|
|
49299
|
+
const yOverlap = Math.max(0, Math.min(figureUI.y + figureUI.height, carousel.y + carousel.height) -
|
|
49300
|
+
Math.max(figureUI.y, carousel.y));
|
|
49301
|
+
return xOverlap >= minimumOverlap && yOverlap >= minimumOverlap;
|
|
49302
|
+
});
|
|
49303
|
+
}
|
|
48357
49304
|
}
|
|
48358
49305
|
|
|
48359
49306
|
css /* scss */ `
|
|
@@ -51036,6 +51983,226 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51036
51983
|
}
|
|
51037
51984
|
}
|
|
51038
51985
|
|
|
51986
|
+
function useAutofocus({ refName }) {
|
|
51987
|
+
const ref = owl.useRef(refName);
|
|
51988
|
+
owl.useEffect((el) => {
|
|
51989
|
+
el?.focus();
|
|
51990
|
+
}, () => [ref.el]);
|
|
51991
|
+
}
|
|
51992
|
+
|
|
51993
|
+
css /* scss */ `
|
|
51994
|
+
.o-spreadsheet {
|
|
51995
|
+
.os-input {
|
|
51996
|
+
border-width: 0 0 1px 0;
|
|
51997
|
+
border-color: transparent;
|
|
51998
|
+
outline: none;
|
|
51999
|
+
text-overflow: ellipsis;
|
|
52000
|
+
color: ${TEXT_BODY};
|
|
52001
|
+
}
|
|
52002
|
+
.os-input:hover,
|
|
52003
|
+
.os-input:focus {
|
|
52004
|
+
border-color: ${GRAY_300};
|
|
52005
|
+
}
|
|
52006
|
+
}
|
|
52007
|
+
`;
|
|
52008
|
+
class TextInput extends owl.Component {
|
|
52009
|
+
static template = "o-spreadsheet-TextInput";
|
|
52010
|
+
static props = {
|
|
52011
|
+
value: String,
|
|
52012
|
+
onChange: Function,
|
|
52013
|
+
class: {
|
|
52014
|
+
type: String,
|
|
52015
|
+
optional: true,
|
|
52016
|
+
},
|
|
52017
|
+
id: {
|
|
52018
|
+
type: String,
|
|
52019
|
+
optional: true,
|
|
52020
|
+
},
|
|
52021
|
+
placeholder: {
|
|
52022
|
+
type: String,
|
|
52023
|
+
optional: true,
|
|
52024
|
+
},
|
|
52025
|
+
autofocus: {
|
|
52026
|
+
type: Boolean,
|
|
52027
|
+
optional: true,
|
|
52028
|
+
},
|
|
52029
|
+
};
|
|
52030
|
+
inputRef = owl.useRef("input");
|
|
52031
|
+
setup() {
|
|
52032
|
+
owl.useExternalListener(window, "click", (ev) => {
|
|
52033
|
+
if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
|
|
52034
|
+
this.save();
|
|
52035
|
+
}
|
|
52036
|
+
}, { capture: true });
|
|
52037
|
+
if (this.props.autofocus) {
|
|
52038
|
+
useAutofocus({ refName: "input" });
|
|
52039
|
+
}
|
|
52040
|
+
}
|
|
52041
|
+
onKeyDown(ev) {
|
|
52042
|
+
switch (ev.key) {
|
|
52043
|
+
case "Enter":
|
|
52044
|
+
this.save();
|
|
52045
|
+
ev.preventDefault();
|
|
52046
|
+
ev.stopPropagation();
|
|
52047
|
+
break;
|
|
52048
|
+
case "Escape":
|
|
52049
|
+
if (this.inputRef.el) {
|
|
52050
|
+
this.inputRef.el.value = this.props.value;
|
|
52051
|
+
this.inputRef.el.blur();
|
|
52052
|
+
}
|
|
52053
|
+
ev.preventDefault();
|
|
52054
|
+
ev.stopPropagation();
|
|
52055
|
+
break;
|
|
52056
|
+
}
|
|
52057
|
+
}
|
|
52058
|
+
save() {
|
|
52059
|
+
const currentValue = (this.inputRef.el?.value || "").trim();
|
|
52060
|
+
if (currentValue !== this.props.value) {
|
|
52061
|
+
this.props.onChange(currentValue);
|
|
52062
|
+
}
|
|
52063
|
+
this.inputRef.el?.blur();
|
|
52064
|
+
}
|
|
52065
|
+
onMouseDown(ev) {
|
|
52066
|
+
// Stop the event if the input is not focused, we handle everything in onMouseUp
|
|
52067
|
+
if (ev.target !== document.activeElement) {
|
|
52068
|
+
ev.preventDefault();
|
|
52069
|
+
ev.stopPropagation();
|
|
52070
|
+
}
|
|
52071
|
+
}
|
|
52072
|
+
onMouseUp(ev) {
|
|
52073
|
+
const target = ev.target;
|
|
52074
|
+
if (target !== document.activeElement) {
|
|
52075
|
+
target.focus();
|
|
52076
|
+
target.select();
|
|
52077
|
+
ev.preventDefault();
|
|
52078
|
+
ev.stopPropagation();
|
|
52079
|
+
}
|
|
52080
|
+
}
|
|
52081
|
+
}
|
|
52082
|
+
|
|
52083
|
+
class CarouselPanel extends owl.Component {
|
|
52084
|
+
static template = "o-spreadsheet-CarouselPanel";
|
|
52085
|
+
static props = { onCloseSidePanel: Function, figureId: String };
|
|
52086
|
+
static components = { TextInput };
|
|
52087
|
+
dragAndDrop = useDragAndDropListItems();
|
|
52088
|
+
previewListRef = owl.useRef("previewList");
|
|
52089
|
+
setup() {
|
|
52090
|
+
let lastCarouselItems = [...this.carouselItems];
|
|
52091
|
+
owl.onWillUpdateProps(() => {
|
|
52092
|
+
if (!deepEquals(this.carouselItems, lastCarouselItems)) {
|
|
52093
|
+
this.dragAndDrop.cancel();
|
|
52094
|
+
}
|
|
52095
|
+
lastCarouselItems = [...this.carouselItems];
|
|
52096
|
+
});
|
|
52097
|
+
}
|
|
52098
|
+
get carouselItems() {
|
|
52099
|
+
return this.env.model.getters.getCarousel(this.props.figureId).items;
|
|
52100
|
+
}
|
|
52101
|
+
getPreviewDivStyle(item) {
|
|
52102
|
+
return this.dragAndDrop.itemsStyle[this.getItemId(item)] || "";
|
|
52103
|
+
}
|
|
52104
|
+
getItemId(item) {
|
|
52105
|
+
return item.type === "chart" ? item.chartId : "transparent-carousel";
|
|
52106
|
+
}
|
|
52107
|
+
addNewChartToCarousel() {
|
|
52108
|
+
this.env.model.dispatch("ADD_NEW_CHART_TO_CAROUSEL", {
|
|
52109
|
+
figureId: this.props.figureId,
|
|
52110
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52111
|
+
});
|
|
52112
|
+
}
|
|
52113
|
+
get hasDataView() {
|
|
52114
|
+
return this.carouselItems.some((item) => item.type === "carouselDataView");
|
|
52115
|
+
}
|
|
52116
|
+
addDataViewToCarousel() {
|
|
52117
|
+
const carousel = this.env.model.getters.getCarousel(this.props.figureId);
|
|
52118
|
+
this.env.model.dispatch("UPDATE_CAROUSEL", {
|
|
52119
|
+
figureId: this.props.figureId,
|
|
52120
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52121
|
+
definition: { items: [...carousel.items, { type: "carouselDataView" }] },
|
|
52122
|
+
});
|
|
52123
|
+
}
|
|
52124
|
+
activateCarouselItem(item) {
|
|
52125
|
+
this.env.model.dispatch("UPDATE_CAROUSEL_ACTIVE_ITEM", {
|
|
52126
|
+
figureId: this.props.figureId,
|
|
52127
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52128
|
+
item,
|
|
52129
|
+
});
|
|
52130
|
+
}
|
|
52131
|
+
editCarouselItem(item) {
|
|
52132
|
+
if (item.type === "chart") {
|
|
52133
|
+
this.activateCarouselItem(item);
|
|
52134
|
+
this.env.model.dispatch("SELECT_FIGURE", { figureId: this.props.figureId });
|
|
52135
|
+
this.env.openSidePanel("ChartPanel", { chartId: item.chartId });
|
|
52136
|
+
}
|
|
52137
|
+
}
|
|
52138
|
+
renameCarouselItem(item, newName) {
|
|
52139
|
+
const trimmedName = newName.trim();
|
|
52140
|
+
if (!trimmedName || trimmedName === this.getItemTitle(item).toString()) {
|
|
52141
|
+
return;
|
|
52142
|
+
}
|
|
52143
|
+
const items = [...this.carouselItems];
|
|
52144
|
+
const itemIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
|
|
52145
|
+
if (itemIndex !== -1) {
|
|
52146
|
+
items[itemIndex] = { ...item, title: trimmedName };
|
|
52147
|
+
this.env.model.dispatch("UPDATE_CAROUSEL", {
|
|
52148
|
+
figureId: this.props.figureId,
|
|
52149
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52150
|
+
definition: { items },
|
|
52151
|
+
});
|
|
52152
|
+
}
|
|
52153
|
+
}
|
|
52154
|
+
deleteCarouselItem(item) {
|
|
52155
|
+
const carousel = this.env.model.getters.getCarousel(this.props.figureId);
|
|
52156
|
+
const items = carousel.items.filter((itm) => !deepEquals(itm, item));
|
|
52157
|
+
this.env.model.dispatch("UPDATE_CAROUSEL", {
|
|
52158
|
+
figureId: this.props.figureId,
|
|
52159
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52160
|
+
definition: { items },
|
|
52161
|
+
});
|
|
52162
|
+
}
|
|
52163
|
+
onDragHandleMouseDown(item, event) {
|
|
52164
|
+
if (event.button !== 0)
|
|
52165
|
+
return;
|
|
52166
|
+
const previewRects = Array.from(this.previewListRef.el.children).map((previewEl) => getBoundingRectAsPOJO(previewEl));
|
|
52167
|
+
const items = this.carouselItems.map((item, index) => ({
|
|
52168
|
+
id: this.getItemId(item),
|
|
52169
|
+
size: previewRects[index].height,
|
|
52170
|
+
position: previewRects[index].y,
|
|
52171
|
+
}));
|
|
52172
|
+
this.dragAndDrop.start("vertical", {
|
|
52173
|
+
draggedItemId: this.getItemId(item),
|
|
52174
|
+
initialMousePosition: event.clientY,
|
|
52175
|
+
items: items,
|
|
52176
|
+
scrollableContainerEl: this.previewListRef.el,
|
|
52177
|
+
onDragEnd: (itemId, finalIndex) => this.onDragEnd(item, finalIndex),
|
|
52178
|
+
});
|
|
52179
|
+
}
|
|
52180
|
+
onDragEnd(item, finalIndex) {
|
|
52181
|
+
const originalIndex = this.carouselItems.findIndex((itm) => deepEquals(itm, item));
|
|
52182
|
+
if (originalIndex === -1 || originalIndex === finalIndex) {
|
|
52183
|
+
return;
|
|
52184
|
+
}
|
|
52185
|
+
const carousel = this.env.model.getters.getCarousel(this.props.figureId);
|
|
52186
|
+
const items = [...carousel.items];
|
|
52187
|
+
items.splice(originalIndex, 1);
|
|
52188
|
+
items.splice(finalIndex, 0, item);
|
|
52189
|
+
this.env.model.dispatch("UPDATE_CAROUSEL", {
|
|
52190
|
+
figureId: this.props.figureId,
|
|
52191
|
+
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
52192
|
+
definition: { items },
|
|
52193
|
+
});
|
|
52194
|
+
}
|
|
52195
|
+
getItemTitle(item) {
|
|
52196
|
+
return getCarouselItemTitle(this.env.model.getters, item);
|
|
52197
|
+
}
|
|
52198
|
+
getItemPreview(item) {
|
|
52199
|
+
return getCarouselItemPreview(this.env.model.getters, item);
|
|
52200
|
+
}
|
|
52201
|
+
get carouselAddChartInfoMessage() {
|
|
52202
|
+
return _t("Add a chart to the carousel. You can also add a chart by dragging and dropping it over the carousel figure.");
|
|
52203
|
+
}
|
|
52204
|
+
}
|
|
52205
|
+
|
|
51039
52206
|
class ChartDataSeries extends owl.Component {
|
|
51040
52207
|
static template = "o-spreadsheet.ChartDataSeries";
|
|
51041
52208
|
static components = { SelectionInput, Section };
|
|
@@ -51102,7 +52269,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51102
52269
|
ChartErrorSection,
|
|
51103
52270
|
};
|
|
51104
52271
|
static props = {
|
|
51105
|
-
|
|
52272
|
+
chartId: String,
|
|
51106
52273
|
definition: Object,
|
|
51107
52274
|
updateChart: Function,
|
|
51108
52275
|
canUpdateChart: Function,
|
|
@@ -51160,7 +52327,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51160
52327
|
];
|
|
51161
52328
|
}
|
|
51162
52329
|
onUpdateDataSetsHaveTitle(dataSetsHaveTitle) {
|
|
51163
|
-
this.props.updateChart(this.props.
|
|
52330
|
+
this.props.updateChart(this.props.chartId, {
|
|
51164
52331
|
dataSetsHaveTitle,
|
|
51165
52332
|
});
|
|
51166
52333
|
}
|
|
@@ -51232,7 +52399,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51232
52399
|
return;
|
|
51233
52400
|
}
|
|
51234
52401
|
const labelRange = dataSets.length > 1 ? dataSets.shift().dataRange : "";
|
|
51235
|
-
this.props.updateChart(this.props.
|
|
52402
|
+
this.props.updateChart(this.props.chartId, {
|
|
51236
52403
|
labelRange,
|
|
51237
52404
|
dataSets,
|
|
51238
52405
|
});
|
|
@@ -51249,7 +52416,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51249
52416
|
...this.dataSets?.[i],
|
|
51250
52417
|
dataRange,
|
|
51251
52418
|
}));
|
|
51252
|
-
this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.
|
|
52419
|
+
this.state.datasetDispatchResult = this.props.canUpdateChart(this.props.chartId, {
|
|
51253
52420
|
dataSets: this.dataSets,
|
|
51254
52421
|
});
|
|
51255
52422
|
}
|
|
@@ -51261,7 +52428,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51261
52428
|
backgroundColor: colors[i],
|
|
51262
52429
|
...this.dataSets[i],
|
|
51263
52430
|
}));
|
|
51264
|
-
this.state.datasetDispatchResult = this.props.updateChart(this.props.
|
|
52431
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
51265
52432
|
dataSets: this.dataSets,
|
|
51266
52433
|
});
|
|
51267
52434
|
}
|
|
@@ -51274,18 +52441,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51274
52441
|
...ds,
|
|
51275
52442
|
}))
|
|
51276
52443
|
.filter((_, i) => i !== index);
|
|
51277
|
-
this.state.datasetDispatchResult = this.props.updateChart(this.props.
|
|
52444
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
51278
52445
|
dataSets: this.dataSets,
|
|
51279
52446
|
});
|
|
51280
52447
|
}
|
|
51281
52448
|
onDataSeriesConfirmed() {
|
|
51282
52449
|
this.dataSets = this.splitRanges;
|
|
51283
52450
|
this.datasetOrientation = this.computeDatasetOrientation();
|
|
51284
|
-
this.state.datasetDispatchResult = this.props.updateChart(this.props.
|
|
52451
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
51285
52452
|
dataSets: this.dataSets,
|
|
51286
52453
|
});
|
|
51287
52454
|
if (this.state.datasetDispatchResult.isSuccessful) {
|
|
51288
|
-
this.dataSets = this.env.model.getters.getChartDefinition(this.props.
|
|
52455
|
+
this.dataSets = this.env.model.getters.getChartDefinition(this.props.chartId).dataSets;
|
|
51289
52456
|
}
|
|
51290
52457
|
}
|
|
51291
52458
|
get splitRanges() {
|
|
@@ -51376,12 +52543,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51376
52543
|
*/
|
|
51377
52544
|
onLabelRangeChanged(ranges) {
|
|
51378
52545
|
this.labelRange = ranges[0];
|
|
51379
|
-
this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.
|
|
52546
|
+
this.state.labelsDispatchResult = this.props.canUpdateChart(this.props.chartId, {
|
|
51380
52547
|
labelRange: this.labelRange,
|
|
51381
52548
|
});
|
|
51382
52549
|
}
|
|
51383
52550
|
onLabelRangeConfirmed() {
|
|
51384
|
-
this.state.labelsDispatchResult = this.props.updateChart(this.props.
|
|
52551
|
+
this.state.labelsDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
51385
52552
|
labelRange: this.labelRange,
|
|
51386
52553
|
});
|
|
51387
52554
|
}
|
|
@@ -51389,7 +52556,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51389
52556
|
return this.labelRange || "";
|
|
51390
52557
|
}
|
|
51391
52558
|
onUpdateAggregated(aggregated) {
|
|
51392
|
-
this.props.updateChart(this.props.
|
|
52559
|
+
this.props.updateChart(this.props.chartId, {
|
|
51393
52560
|
aggregated,
|
|
51394
52561
|
});
|
|
51395
52562
|
}
|
|
@@ -51421,7 +52588,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51421
52588
|
}
|
|
51422
52589
|
const zonesBySheetName = {};
|
|
51423
52590
|
const transposedDatasets = [];
|
|
51424
|
-
const
|
|
52591
|
+
const figureId = getters.getFigureIdFromChartId(this.props.chartId);
|
|
52592
|
+
const figureSheetId = getters.getFigureSheetId(figureId);
|
|
51425
52593
|
let name = getters.getActiveSheet().name;
|
|
51426
52594
|
if (figureSheetId) {
|
|
51427
52595
|
name = getters.getSheet(figureSheetId).name;
|
|
@@ -51481,7 +52649,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51481
52649
|
: this.chartTerms.StackedColumnChart;
|
|
51482
52650
|
}
|
|
51483
52651
|
onUpdateStacked(stacked) {
|
|
51484
|
-
this.props.updateChart(this.props.
|
|
52652
|
+
this.props.updateChart(this.props.chartId, {
|
|
51485
52653
|
stacked,
|
|
51486
52654
|
});
|
|
51487
52655
|
}
|
|
@@ -51975,7 +53143,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
51975
53143
|
class AxisDesignEditor extends owl.Component {
|
|
51976
53144
|
static template = "o-spreadsheet-AxisDesignEditor";
|
|
51977
53145
|
static components = { Section, ChartTitle, BadgeSelection };
|
|
51978
|
-
static props = {
|
|
53146
|
+
static props = { chartId: String, definition: Object, updateChart: Function, axesList: Array };
|
|
51979
53147
|
state = owl.useState({ currentAxis: "x" });
|
|
51980
53148
|
defaultFontSize = CHART_AXIS_TITLE_FONT_SIZE;
|
|
51981
53149
|
get axisTitleStyle() {
|
|
@@ -52000,7 +53168,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52000
53168
|
text,
|
|
52001
53169
|
},
|
|
52002
53170
|
};
|
|
52003
|
-
this.props.updateChart(this.props.
|
|
53171
|
+
this.props.updateChart(this.props.chartId, { axesDesign });
|
|
52004
53172
|
}
|
|
52005
53173
|
updateAxisTitleStyle(style) {
|
|
52006
53174
|
const axesDesign = deepCopy(this.props.definition.axesDesign) ?? {};
|
|
@@ -52008,7 +53176,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52008
53176
|
...axesDesign[this.state.currentAxis],
|
|
52009
53177
|
title: style,
|
|
52010
53178
|
};
|
|
52011
|
-
this.props.updateChart(this.props.
|
|
53179
|
+
this.props.updateChart(this.props.chartId, { axesDesign });
|
|
52012
53180
|
}
|
|
52013
53181
|
}
|
|
52014
53182
|
|
|
@@ -52061,7 +53229,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52061
53229
|
RadioSelection,
|
|
52062
53230
|
};
|
|
52063
53231
|
static props = {
|
|
52064
|
-
|
|
53232
|
+
chartId: String,
|
|
52065
53233
|
definition: Object,
|
|
52066
53234
|
updateChart: Function,
|
|
52067
53235
|
canUpdateChart: Function,
|
|
@@ -52085,17 +53253,17 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52085
53253
|
this.state.activeTool = isOpen ? "" : tool;
|
|
52086
53254
|
}
|
|
52087
53255
|
updateBackgroundColor(color) {
|
|
52088
|
-
this.props.updateChart(this.props.
|
|
53256
|
+
this.props.updateChart(this.props.chartId, {
|
|
52089
53257
|
background: color,
|
|
52090
53258
|
});
|
|
52091
53259
|
}
|
|
52092
53260
|
updateTitle(newTitle) {
|
|
52093
53261
|
const title = { ...this.title, text: newTitle };
|
|
52094
|
-
this.props.updateChart(this.props.
|
|
53262
|
+
this.props.updateChart(this.props.chartId, { title });
|
|
52095
53263
|
}
|
|
52096
53264
|
updateChartTitleStyle(style) {
|
|
52097
53265
|
const title = { ...this.title, ...style };
|
|
52098
|
-
this.props.updateChart(this.props.
|
|
53266
|
+
this.props.updateChart(this.props.chartId, { title });
|
|
52099
53267
|
this.state.activeTool = "";
|
|
52100
53268
|
}
|
|
52101
53269
|
}
|
|
@@ -52106,13 +53274,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52106
53274
|
Section,
|
|
52107
53275
|
};
|
|
52108
53276
|
static props = {
|
|
52109
|
-
|
|
53277
|
+
chartId: String,
|
|
52110
53278
|
definition: Object,
|
|
52111
53279
|
updateChart: Function,
|
|
52112
53280
|
canUpdateChart: Function,
|
|
52113
53281
|
};
|
|
52114
53282
|
updateLegendPosition(ev) {
|
|
52115
|
-
this.props.updateChart(this.props.
|
|
53283
|
+
this.props.updateChart(this.props.chartId, {
|
|
52116
53284
|
legendPosition: ev.target.value,
|
|
52117
53285
|
});
|
|
52118
53286
|
}
|
|
@@ -52126,7 +53294,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52126
53294
|
RoundColorPicker,
|
|
52127
53295
|
};
|
|
52128
53296
|
static props = {
|
|
52129
|
-
|
|
53297
|
+
chartId: String,
|
|
52130
53298
|
definition: Object,
|
|
52131
53299
|
updateChart: Function,
|
|
52132
53300
|
canUpdateChart: Function,
|
|
@@ -52134,7 +53302,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52134
53302
|
};
|
|
52135
53303
|
state = owl.useState({ index: 0 });
|
|
52136
53304
|
getDataSeries() {
|
|
52137
|
-
const runtime = this.env.model.getters.getChartRuntime(this.props.
|
|
53305
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
52138
53306
|
if (!runtime || !("chartJsConfig" in runtime)) {
|
|
52139
53307
|
return [];
|
|
52140
53308
|
}
|
|
@@ -52153,7 +53321,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52153
53321
|
...dataSets[this.state.index],
|
|
52154
53322
|
backgroundColor: color,
|
|
52155
53323
|
};
|
|
52156
|
-
this.props.updateChart(this.props.
|
|
53324
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52157
53325
|
}
|
|
52158
53326
|
getDataSeriesColor() {
|
|
52159
53327
|
const dataSets = this.props.definition.dataSets;
|
|
@@ -52173,7 +53341,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52173
53341
|
...dataSets[this.state.index],
|
|
52174
53342
|
label,
|
|
52175
53343
|
};
|
|
52176
|
-
this.props.updateChart(this.props.
|
|
53344
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52177
53345
|
}
|
|
52178
53346
|
getDataSeriesLabel() {
|
|
52179
53347
|
const dataSets = this.props.definition.dataSets;
|
|
@@ -52191,7 +53359,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52191
53359
|
RoundColorPicker,
|
|
52192
53360
|
};
|
|
52193
53361
|
static props = {
|
|
52194
|
-
|
|
53362
|
+
chartId: String,
|
|
52195
53363
|
definition: Object,
|
|
52196
53364
|
canUpdateChart: Function,
|
|
52197
53365
|
updateChart: Function,
|
|
@@ -52207,7 +53375,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52207
53375
|
...dataSets[index],
|
|
52208
53376
|
yAxisId: axis === "left" ? "y" : "y1",
|
|
52209
53377
|
};
|
|
52210
|
-
this.props.updateChart(this.props.
|
|
53378
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52211
53379
|
}
|
|
52212
53380
|
getDataSerieAxis(index) {
|
|
52213
53381
|
const dataSets = this.props.definition.dataSets;
|
|
@@ -52233,7 +53401,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52233
53401
|
display,
|
|
52234
53402
|
},
|
|
52235
53403
|
};
|
|
52236
|
-
this.props.updateChart(this.props.
|
|
53404
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52237
53405
|
}
|
|
52238
53406
|
getTrendLineConfiguration(index) {
|
|
52239
53407
|
const dataSets = this.props.definition.dataSets;
|
|
@@ -52274,7 +53442,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52274
53442
|
this.updateTrendLineValue(index, { order: parseInt(element.value) });
|
|
52275
53443
|
}
|
|
52276
53444
|
getMaxPolynomialDegree(index) {
|
|
52277
|
-
const runtime = this.env.model.getters.getChartRuntime(this.props.
|
|
53445
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
52278
53446
|
return Math.min(10, runtime.chartJsConfig.data.datasets[index].data.length - 1);
|
|
52279
53447
|
}
|
|
52280
53448
|
get defaultWindowSize() {
|
|
@@ -52316,7 +53484,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52316
53484
|
...config,
|
|
52317
53485
|
},
|
|
52318
53486
|
};
|
|
52319
|
-
this.props.updateChart(this.props.
|
|
53487
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52320
53488
|
}
|
|
52321
53489
|
}
|
|
52322
53490
|
|
|
@@ -52326,7 +53494,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52326
53494
|
Checkbox,
|
|
52327
53495
|
};
|
|
52328
53496
|
static props = {
|
|
52329
|
-
|
|
53497
|
+
chartId: String,
|
|
52330
53498
|
definition: Object,
|
|
52331
53499
|
updateChart: Function,
|
|
52332
53500
|
canUpdateChart: Function,
|
|
@@ -52346,7 +53514,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52346
53514
|
ChartShowValues,
|
|
52347
53515
|
};
|
|
52348
53516
|
static props = {
|
|
52349
|
-
|
|
53517
|
+
chartId: String,
|
|
52350
53518
|
definition: Object,
|
|
52351
53519
|
canUpdateChart: Function,
|
|
52352
53520
|
updateChart: Function,
|
|
@@ -52370,17 +53538,30 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52370
53538
|
Checkbox,
|
|
52371
53539
|
};
|
|
52372
53540
|
static props = {
|
|
52373
|
-
|
|
53541
|
+
chartId: String,
|
|
52374
53542
|
definition: Object,
|
|
52375
53543
|
updateChart: Function,
|
|
52376
53544
|
canUpdateChart: Function,
|
|
52377
53545
|
};
|
|
52378
53546
|
}
|
|
52379
53547
|
|
|
52380
|
-
class
|
|
52381
|
-
static template = "o-spreadsheet-
|
|
53548
|
+
class GenericZoomableChartDesignPanel extends ChartWithAxisDesignPanel {
|
|
53549
|
+
static template = "o-spreadsheet-GenericZoomableChartDesignPanel";
|
|
52382
53550
|
static components = {
|
|
52383
53551
|
...ChartWithAxisDesignPanel.components,
|
|
53552
|
+
Checkbox,
|
|
53553
|
+
};
|
|
53554
|
+
onToggleZoom(zoomable) {
|
|
53555
|
+
this.props.updateChart(this.props.chartId, {
|
|
53556
|
+
zoomable,
|
|
53557
|
+
});
|
|
53558
|
+
}
|
|
53559
|
+
}
|
|
53560
|
+
|
|
53561
|
+
class ComboChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
53562
|
+
static template = "o-spreadsheet-ComboChartDesignPanel";
|
|
53563
|
+
static components = {
|
|
53564
|
+
...GenericZoomableChartDesignPanel.components,
|
|
52384
53565
|
ChartShowDataMarkers,
|
|
52385
53566
|
RadioSelection,
|
|
52386
53567
|
};
|
|
@@ -52397,7 +53578,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52397
53578
|
...dataSets[index],
|
|
52398
53579
|
type,
|
|
52399
53580
|
};
|
|
52400
|
-
this.props.updateChart(this.props.
|
|
53581
|
+
this.props.updateChart(this.props.chartId, { dataSets });
|
|
52401
53582
|
}
|
|
52402
53583
|
getDataSeriesType(index) {
|
|
52403
53584
|
const dataSets = this.props.definition.dataSets;
|
|
@@ -52433,7 +53614,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52433
53614
|
];
|
|
52434
53615
|
}
|
|
52435
53616
|
onUpdateCumulative(cumulative) {
|
|
52436
|
-
this.props.updateChart(this.props.
|
|
53617
|
+
this.props.updateChart(this.props.chartId, {
|
|
52437
53618
|
cumulative,
|
|
52438
53619
|
});
|
|
52439
53620
|
}
|
|
@@ -52449,13 +53630,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52449
53630
|
Section,
|
|
52450
53631
|
};
|
|
52451
53632
|
static props = {
|
|
52452
|
-
|
|
53633
|
+
chartId: String,
|
|
52453
53634
|
definition: Object,
|
|
52454
53635
|
updateChart: Function,
|
|
52455
53636
|
canUpdateChart: Function,
|
|
52456
53637
|
};
|
|
52457
53638
|
getFunnelColorItems() {
|
|
52458
|
-
const runtime = this.env.model.getters.getChartRuntime(this.props.
|
|
53639
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
52459
53640
|
const labels = (runtime.chartJsConfig.data.labels || []);
|
|
52460
53641
|
const colors = getFunnelLabelColors(labels, this.props.definition.funnelColors);
|
|
52461
53642
|
return labels.map((label, index) => ({
|
|
@@ -52465,7 +53646,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52465
53646
|
}
|
|
52466
53647
|
updateFunnelItemColor(index, color) {
|
|
52467
53648
|
const funnelColors = replaceItemAtIndex(this.props.definition.funnelColors || [], color, index);
|
|
52468
|
-
this.props.updateChart(this.props.
|
|
53649
|
+
this.props.updateChart(this.props.chartId, { funnelColors });
|
|
52469
53650
|
}
|
|
52470
53651
|
}
|
|
52471
53652
|
|
|
@@ -52473,7 +53654,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52473
53654
|
static template = "o-spreadsheet-GaugeChartConfigPanel";
|
|
52474
53655
|
static components = { ChartErrorSection, ChartDataSeries };
|
|
52475
53656
|
static props = {
|
|
52476
|
-
|
|
53657
|
+
chartId: String,
|
|
52477
53658
|
definition: Object,
|
|
52478
53659
|
updateChart: Function,
|
|
52479
53660
|
canUpdateChart: Function,
|
|
@@ -52491,12 +53672,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52491
53672
|
}
|
|
52492
53673
|
onDataRangeChanged(ranges) {
|
|
52493
53674
|
this.dataRange = ranges[0];
|
|
52494
|
-
this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.
|
|
53675
|
+
this.state.dataRangeDispatchResult = this.props.canUpdateChart(this.props.chartId, {
|
|
52495
53676
|
dataRange: this.dataRange,
|
|
52496
53677
|
});
|
|
52497
53678
|
}
|
|
52498
53679
|
updateDataRange() {
|
|
52499
|
-
this.state.dataRangeDispatchResult = this.props.updateChart(this.props.
|
|
53680
|
+
this.state.dataRangeDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
52500
53681
|
dataRange: this.dataRange,
|
|
52501
53682
|
});
|
|
52502
53683
|
}
|
|
@@ -52555,7 +53736,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52555
53736
|
StandaloneComposer,
|
|
52556
53737
|
};
|
|
52557
53738
|
static props = {
|
|
52558
|
-
|
|
53739
|
+
chartId: String,
|
|
52559
53740
|
definition: Object,
|
|
52560
53741
|
updateChart: Function,
|
|
52561
53742
|
canUpdateChart: { type: Function, optional: true },
|
|
@@ -52596,7 +53777,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52596
53777
|
updateSectionRule(sectionRule) {
|
|
52597
53778
|
this.state.sectionRuleCancelledReasons = [];
|
|
52598
53779
|
this.state.sectionRuleCancelledReasons.push(...this.checkSectionRuleFormulasAreValid(this.state.sectionRule));
|
|
52599
|
-
const dispatchResult = this.props.updateChart(this.props.
|
|
53780
|
+
const dispatchResult = this.props.updateChart(this.props.chartId, {
|
|
52600
53781
|
sectionRule,
|
|
52601
53782
|
});
|
|
52602
53783
|
if (dispatchResult.isSuccessful) {
|
|
@@ -52659,9 +53840,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52659
53840
|
return tryToNumber(toScalar(evaluatedValue), locale) !== undefined;
|
|
52660
53841
|
}
|
|
52661
53842
|
get sheetId() {
|
|
52662
|
-
const chart = this.env.model.getters.getChart(this.props.
|
|
53843
|
+
const chart = this.env.model.getters.getChart(this.props.chartId);
|
|
52663
53844
|
if (!chart) {
|
|
52664
|
-
throw new Error("Chart not found with id " + this.props.
|
|
53845
|
+
throw new Error("Chart not found with id " + this.props.chartId);
|
|
52665
53846
|
}
|
|
52666
53847
|
return chart.sheetId;
|
|
52667
53848
|
}
|
|
@@ -52671,13 +53852,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52671
53852
|
static template = "o-spreadsheet-GeoChartRegionSelectSection";
|
|
52672
53853
|
static components = { Section };
|
|
52673
53854
|
static props = {
|
|
52674
|
-
|
|
53855
|
+
chartId: String,
|
|
52675
53856
|
definition: Object,
|
|
52676
53857
|
updateChart: Function,
|
|
52677
53858
|
};
|
|
52678
53859
|
updateSelectedRegion(ev) {
|
|
52679
53860
|
const value = ev.target.value;
|
|
52680
|
-
this.props.updateChart(this.props.
|
|
53861
|
+
this.props.updateChart(this.props.chartId, { region: value });
|
|
52681
53862
|
}
|
|
52682
53863
|
get availableRegions() {
|
|
52683
53864
|
return this.env.model.getters.getGeoChartAvailableRegions();
|
|
@@ -52727,14 +53908,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52727
53908
|
: this.updateColorScale(value);
|
|
52728
53909
|
}
|
|
52729
53910
|
updateColorScale(colorScale) {
|
|
52730
|
-
this.props.updateChart(this.props.
|
|
53911
|
+
this.props.updateChart(this.props.chartId, { colorScale });
|
|
52731
53912
|
}
|
|
52732
53913
|
updateMissingValueColor(color) {
|
|
52733
|
-
this.props.updateChart(this.props.
|
|
53914
|
+
this.props.updateChart(this.props.chartId, { missingValueColor: color });
|
|
52734
53915
|
}
|
|
52735
53916
|
updateLegendPosition(ev) {
|
|
52736
53917
|
const value = ev.target.value;
|
|
52737
|
-
this.props.updateChart(this.props.
|
|
53918
|
+
this.props.updateChart(this.props.chartId, { legendPosition: value });
|
|
52738
53919
|
}
|
|
52739
53920
|
get selectedColorScale() {
|
|
52740
53921
|
return typeof this.props.definition.colorScale === "object"
|
|
@@ -52783,7 +53964,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52783
53964
|
class LineConfigPanel extends GenericChartConfigPanel {
|
|
52784
53965
|
static template = "o-spreadsheet-LineConfigPanel";
|
|
52785
53966
|
get canTreatLabelsAsText() {
|
|
52786
|
-
const chart = this.env.model.getters.getChart(this.props.
|
|
53967
|
+
const chart = this.env.model.getters.getChart(this.props.chartId);
|
|
52787
53968
|
if (chart && chart instanceof LineChart) {
|
|
52788
53969
|
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
52789
53970
|
}
|
|
@@ -52808,26 +53989,26 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52808
53989
|
return options;
|
|
52809
53990
|
}
|
|
52810
53991
|
onUpdateLabelsAsText(labelsAsText) {
|
|
52811
|
-
this.props.updateChart(this.props.
|
|
53992
|
+
this.props.updateChart(this.props.chartId, {
|
|
52812
53993
|
labelsAsText,
|
|
52813
53994
|
});
|
|
52814
53995
|
}
|
|
52815
53996
|
onUpdateStacked(stacked) {
|
|
52816
|
-
this.props.updateChart(this.props.
|
|
53997
|
+
this.props.updateChart(this.props.chartId, {
|
|
52817
53998
|
stacked,
|
|
52818
53999
|
});
|
|
52819
54000
|
}
|
|
52820
54001
|
onUpdateCumulative(cumulative) {
|
|
52821
|
-
this.props.updateChart(this.props.
|
|
54002
|
+
this.props.updateChart(this.props.chartId, {
|
|
52822
54003
|
cumulative,
|
|
52823
54004
|
});
|
|
52824
54005
|
}
|
|
52825
54006
|
}
|
|
52826
54007
|
|
|
52827
|
-
class LineChartDesignPanel extends
|
|
54008
|
+
class LineChartDesignPanel extends GenericZoomableChartDesignPanel {
|
|
52828
54009
|
static template = "o-spreadsheet-LineChartDesignPanel";
|
|
52829
54010
|
static components = {
|
|
52830
|
-
...
|
|
54011
|
+
...GenericZoomableChartDesignPanel.components,
|
|
52831
54012
|
ChartShowDataMarkers,
|
|
52832
54013
|
};
|
|
52833
54014
|
}
|
|
@@ -52855,13 +54036,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52855
54036
|
PieHoleSize,
|
|
52856
54037
|
};
|
|
52857
54038
|
static props = {
|
|
52858
|
-
|
|
54039
|
+
chartId: String,
|
|
52859
54040
|
definition: Object,
|
|
52860
54041
|
updateChart: Function,
|
|
52861
54042
|
canUpdateChart: { type: Function, optional: true },
|
|
52862
54043
|
};
|
|
52863
54044
|
onPieHoleSizeChange(pieHolePercentage) {
|
|
52864
|
-
this.props.updateChart(this.props.
|
|
54045
|
+
this.props.updateChart(this.props.chartId, {
|
|
52865
54046
|
...this.props.definition,
|
|
52866
54047
|
pieHolePercentage,
|
|
52867
54048
|
});
|
|
@@ -52882,7 +54063,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52882
54063
|
ChartShowDataMarkers,
|
|
52883
54064
|
};
|
|
52884
54065
|
static props = {
|
|
52885
|
-
|
|
54066
|
+
chartId: String,
|
|
52886
54067
|
definition: Object,
|
|
52887
54068
|
canUpdateChart: Function,
|
|
52888
54069
|
updateChart: Function,
|
|
@@ -52892,14 +54073,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52892
54073
|
class ScatterConfigPanel extends GenericChartConfigPanel {
|
|
52893
54074
|
static template = "o-spreadsheet-ScatterConfigPanel";
|
|
52894
54075
|
get canTreatLabelsAsText() {
|
|
52895
|
-
const chart = this.env.model.getters.getChart(this.props.
|
|
54076
|
+
const chart = this.env.model.getters.getChart(this.props.chartId);
|
|
52896
54077
|
if (chart && chart instanceof ScatterChart) {
|
|
52897
54078
|
return canChartParseLabels(chart.getDefinition(), chart.dataSets, chart.labelRange, this.env.model.getters);
|
|
52898
54079
|
}
|
|
52899
54080
|
return false;
|
|
52900
54081
|
}
|
|
52901
54082
|
onUpdateLabelsAsText(labelsAsText) {
|
|
52902
|
-
this.props.updateChart(this.props.
|
|
54083
|
+
this.props.updateChart(this.props.chartId, {
|
|
52903
54084
|
labelsAsText,
|
|
52904
54085
|
});
|
|
52905
54086
|
}
|
|
@@ -52921,7 +54102,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52921
54102
|
static template = "o-spreadsheet-ScorecardChartConfigPanel";
|
|
52922
54103
|
static components = { SelectionInput, ChartErrorSection, Section };
|
|
52923
54104
|
static props = {
|
|
52924
|
-
|
|
54105
|
+
chartId: String,
|
|
52925
54106
|
definition: Object,
|
|
52926
54107
|
updateChart: Function,
|
|
52927
54108
|
canUpdateChart: Function,
|
|
@@ -52947,12 +54128,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52947
54128
|
}
|
|
52948
54129
|
onKeyValueRangeChanged(ranges) {
|
|
52949
54130
|
this.keyValue = ranges[0];
|
|
52950
|
-
this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.
|
|
54131
|
+
this.state.keyValueDispatchResult = this.props.canUpdateChart(this.props.chartId, {
|
|
52951
54132
|
keyValue: this.keyValue,
|
|
52952
54133
|
});
|
|
52953
54134
|
}
|
|
52954
54135
|
updateKeyValueRange() {
|
|
52955
|
-
this.state.keyValueDispatchResult = this.props.updateChart(this.props.
|
|
54136
|
+
this.state.keyValueDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
52956
54137
|
keyValue: this.keyValue,
|
|
52957
54138
|
});
|
|
52958
54139
|
}
|
|
@@ -52961,12 +54142,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52961
54142
|
}
|
|
52962
54143
|
onBaselineRangeChanged(ranges) {
|
|
52963
54144
|
this.baseline = ranges[0];
|
|
52964
|
-
this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.
|
|
54145
|
+
this.state.baselineDispatchResult = this.props.canUpdateChart(this.props.chartId, {
|
|
52965
54146
|
baseline: this.baseline,
|
|
52966
54147
|
});
|
|
52967
54148
|
}
|
|
52968
54149
|
updateBaselineRange() {
|
|
52969
|
-
this.state.baselineDispatchResult = this.props.updateChart(this.props.
|
|
54150
|
+
this.state.baselineDispatchResult = this.props.updateChart(this.props.chartId, {
|
|
52970
54151
|
baseline: this.baseline,
|
|
52971
54152
|
});
|
|
52972
54153
|
}
|
|
@@ -52974,7 +54155,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52974
54155
|
return this.baseline || "";
|
|
52975
54156
|
}
|
|
52976
54157
|
updateBaselineMode(ev) {
|
|
52977
|
-
this.props.updateChart(this.props.
|
|
54158
|
+
this.props.updateChart(this.props.chartId, { baselineMode: ev.target.value });
|
|
52978
54159
|
}
|
|
52979
54160
|
}
|
|
52980
54161
|
|
|
@@ -52989,7 +54170,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
52989
54170
|
ChartTitle,
|
|
52990
54171
|
};
|
|
52991
54172
|
static props = {
|
|
52992
|
-
|
|
54173
|
+
chartId: String,
|
|
52993
54174
|
definition: Object,
|
|
52994
54175
|
updateChart: Function,
|
|
52995
54176
|
canUpdateChart: { type: Function, optional: true },
|
|
@@ -53006,7 +54187,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53006
54187
|
return SCORECARD_CHART_TITLE_FONT_SIZE;
|
|
53007
54188
|
}
|
|
53008
54189
|
updateHumanizeNumbers(humanize) {
|
|
53009
|
-
this.props.updateChart(this.props.
|
|
54190
|
+
this.props.updateChart(this.props.chartId, { humanize });
|
|
53010
54191
|
}
|
|
53011
54192
|
translate(term) {
|
|
53012
54193
|
return _t(term);
|
|
@@ -53014,13 +54195,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53014
54195
|
setColor(color, colorPickerId) {
|
|
53015
54196
|
switch (colorPickerId) {
|
|
53016
54197
|
case "backgroundColor":
|
|
53017
|
-
this.props.updateChart(this.props.
|
|
54198
|
+
this.props.updateChart(this.props.chartId, { background: color });
|
|
53018
54199
|
break;
|
|
53019
54200
|
case "baselineColorDown":
|
|
53020
|
-
this.props.updateChart(this.props.
|
|
54201
|
+
this.props.updateChart(this.props.chartId, { baselineColorDown: color });
|
|
53021
54202
|
break;
|
|
53022
54203
|
case "baselineColorUp":
|
|
53023
|
-
this.props.updateChart(this.props.
|
|
54204
|
+
this.props.updateChart(this.props.chartId, { baselineColorUp: color });
|
|
53024
54205
|
break;
|
|
53025
54206
|
}
|
|
53026
54207
|
}
|
|
@@ -53039,22 +54220,22 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53039
54220
|
};
|
|
53040
54221
|
}
|
|
53041
54222
|
setKeyText(text) {
|
|
53042
|
-
this.props.updateChart(this.props.
|
|
54223
|
+
this.props.updateChart(this.props.chartId, {
|
|
53043
54224
|
keyDescr: { ...this.props.definition.keyDescr, text },
|
|
53044
54225
|
});
|
|
53045
54226
|
}
|
|
53046
54227
|
updateKeyStyle(style) {
|
|
53047
54228
|
const keyDescr = { ...this.keyStyle, ...style };
|
|
53048
|
-
this.props.updateChart(this.props.
|
|
54229
|
+
this.props.updateChart(this.props.chartId, { keyDescr });
|
|
53049
54230
|
}
|
|
53050
54231
|
setBaselineText(text) {
|
|
53051
|
-
this.props.updateChart(this.props.
|
|
54232
|
+
this.props.updateChart(this.props.chartId, {
|
|
53052
54233
|
baselineDescr: { ...this.props.definition.baselineDescr, text },
|
|
53053
54234
|
});
|
|
53054
54235
|
}
|
|
53055
54236
|
updateBaselineStyle(style) {
|
|
53056
54237
|
const baselineDescr = { ...this.baselineStyle, ...style };
|
|
53057
|
-
this.props.updateChart(this.props.
|
|
54238
|
+
this.props.updateChart(this.props.chartId, { baselineDescr });
|
|
53058
54239
|
}
|
|
53059
54240
|
}
|
|
53060
54241
|
|
|
@@ -53072,7 +54253,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53072
54253
|
PieHoleSize,
|
|
53073
54254
|
};
|
|
53074
54255
|
static props = {
|
|
53075
|
-
|
|
54256
|
+
chartId: String,
|
|
53076
54257
|
definition: Object,
|
|
53077
54258
|
updateChart: Function,
|
|
53078
54259
|
canUpdateChart: { type: Function, optional: true },
|
|
@@ -53085,18 +54266,18 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53085
54266
|
return this.props.definition.showLabels ?? SunburstChartDefaults.showLabels;
|
|
53086
54267
|
}
|
|
53087
54268
|
get groupColors() {
|
|
53088
|
-
const
|
|
53089
|
-
const runtime = this.env.model.getters.getChartRuntime(
|
|
54269
|
+
const chartId = this.props.chartId;
|
|
54270
|
+
const runtime = this.env.model.getters.getChartRuntime(chartId);
|
|
53090
54271
|
const dataset = runtime.chartJsConfig.data.datasets[0];
|
|
53091
54272
|
return dataset?.groupColors || [];
|
|
53092
54273
|
}
|
|
53093
54274
|
onGroupColorChanged(index, color) {
|
|
53094
54275
|
const colors = deepCopy(this.props.definition.groupColors) ?? [];
|
|
53095
54276
|
colors[index] = color;
|
|
53096
|
-
this.props.updateChart(this.props.
|
|
54277
|
+
this.props.updateChart(this.props.chartId, { groupColors: colors });
|
|
53097
54278
|
}
|
|
53098
54279
|
onPieHoleSizeChange(pieHolePercentage) {
|
|
53099
|
-
this.props.updateChart(this.props.
|
|
54280
|
+
this.props.updateChart(this.props.chartId, {
|
|
53100
54281
|
...this.props.definition,
|
|
53101
54282
|
pieHolePercentage,
|
|
53102
54283
|
});
|
|
@@ -53110,7 +54291,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53110
54291
|
RoundColorPicker,
|
|
53111
54292
|
};
|
|
53112
54293
|
static props = {
|
|
53113
|
-
|
|
54294
|
+
chartId: String,
|
|
53114
54295
|
definition: Object,
|
|
53115
54296
|
onColorChanged: Function,
|
|
53116
54297
|
};
|
|
@@ -53122,7 +54303,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53122
54303
|
return coloringOptions;
|
|
53123
54304
|
}
|
|
53124
54305
|
getTreeGroupAndColors() {
|
|
53125
|
-
const runtime = this.env.model.getters.getChartRuntime(this.props.
|
|
54306
|
+
const runtime = this.env.model.getters.getChartRuntime(this.props.chartId);
|
|
53126
54307
|
const config = runtime.chartJsConfig;
|
|
53127
54308
|
return config.data.datasets[0]?.groupColors || [];
|
|
53128
54309
|
}
|
|
@@ -53143,7 +54324,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53143
54324
|
static template = "o-spreadsheet-TreeMapColorScale";
|
|
53144
54325
|
static components = { RoundColorPicker };
|
|
53145
54326
|
static props = {
|
|
53146
|
-
|
|
54327
|
+
chartId: String,
|
|
53147
54328
|
definition: Object,
|
|
53148
54329
|
onColorChanged: Function,
|
|
53149
54330
|
};
|
|
@@ -53185,7 +54366,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53185
54366
|
TreeMapColorScale,
|
|
53186
54367
|
};
|
|
53187
54368
|
static props = {
|
|
53188
|
-
|
|
54369
|
+
chartId: String,
|
|
53189
54370
|
definition: Object,
|
|
53190
54371
|
updateChart: Function,
|
|
53191
54372
|
canUpdateChart: { type: Function, optional: true },
|
|
@@ -53209,15 +54390,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53209
54390
|
}
|
|
53210
54391
|
changeColoringOption(option) {
|
|
53211
54392
|
const coloringOptions = option === "categoryColor" ? this.savedColors.categoryColors : this.savedColors.colorScale;
|
|
53212
|
-
this.props.updateChart(this.props.
|
|
54393
|
+
this.props.updateChart(this.props.chartId, { coloringOptions });
|
|
53213
54394
|
}
|
|
53214
54395
|
onCategoryColorChange(coloringOptions) {
|
|
53215
54396
|
this.savedColors.categoryColors = coloringOptions;
|
|
53216
|
-
this.props.updateChart(this.props.
|
|
54397
|
+
this.props.updateChart(this.props.chartId, { coloringOptions });
|
|
53217
54398
|
}
|
|
53218
54399
|
onColorScaleChange(coloringOptions) {
|
|
53219
54400
|
this.savedColors.colorScale = coloringOptions;
|
|
53220
|
-
this.props.updateChart(this.props.
|
|
54401
|
+
this.props.updateChart(this.props.chartId, { coloringOptions });
|
|
53221
54402
|
}
|
|
53222
54403
|
get coloringOptionChoices() {
|
|
53223
54404
|
return [
|
|
@@ -53241,23 +54422,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53241
54422
|
ChartLegend,
|
|
53242
54423
|
};
|
|
53243
54424
|
static props = {
|
|
53244
|
-
|
|
54425
|
+
chartId: String,
|
|
53245
54426
|
definition: Object,
|
|
53246
54427
|
updateChart: Function,
|
|
53247
54428
|
canUpdateChart: { type: Function, optional: true },
|
|
53248
54429
|
};
|
|
53249
54430
|
axisChoices = CHART_AXIS_CHOICES;
|
|
53250
54431
|
onUpdateShowSubTotals(showSubTotals) {
|
|
53251
|
-
this.props.updateChart(this.props.
|
|
54432
|
+
this.props.updateChart(this.props.chartId, { showSubTotals });
|
|
53252
54433
|
}
|
|
53253
54434
|
onUpdateShowConnectorLines(showConnectorLines) {
|
|
53254
|
-
this.props.updateChart(this.props.
|
|
54435
|
+
this.props.updateChart(this.props.chartId, { showConnectorLines });
|
|
53255
54436
|
}
|
|
53256
54437
|
onUpdateFirstValueAsSubtotal(firstValueAsSubtotal) {
|
|
53257
|
-
this.props.updateChart(this.props.
|
|
54438
|
+
this.props.updateChart(this.props.chartId, { firstValueAsSubtotal });
|
|
53258
54439
|
}
|
|
53259
54440
|
updateColor(colorName, color) {
|
|
53260
|
-
this.props.updateChart(this.props.
|
|
54441
|
+
this.props.updateChart(this.props.chartId, { [colorName]: color });
|
|
53261
54442
|
}
|
|
53262
54443
|
get axesList() {
|
|
53263
54444
|
return [
|
|
@@ -53278,10 +54459,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53278
54459
|
CHART_WATERFALL_SUBTOTAL_COLOR);
|
|
53279
54460
|
}
|
|
53280
54461
|
updateVerticalAxisPosition(value) {
|
|
53281
|
-
this.props.updateChart(this.props.
|
|
54462
|
+
this.props.updateChart(this.props.chartId, {
|
|
53282
54463
|
verticalAxisPosition: value,
|
|
53283
54464
|
});
|
|
53284
54465
|
}
|
|
54466
|
+
onToggleZoom(zoomable) {
|
|
54467
|
+
this.props.updateChart(this.props.chartId, {
|
|
54468
|
+
zoomable,
|
|
54469
|
+
});
|
|
54470
|
+
}
|
|
53285
54471
|
}
|
|
53286
54472
|
|
|
53287
54473
|
const chartSidePanelComponentRegistry = new Registry();
|
|
@@ -53292,11 +54478,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53292
54478
|
})
|
|
53293
54479
|
.add("scatter", {
|
|
53294
54480
|
configuration: ScatterConfigPanel,
|
|
53295
|
-
design:
|
|
54481
|
+
design: GenericZoomableChartDesignPanel,
|
|
53296
54482
|
})
|
|
53297
54483
|
.add("bar", {
|
|
53298
54484
|
configuration: BarConfigPanel,
|
|
53299
|
-
design:
|
|
54485
|
+
design: GenericZoomableChartDesignPanel,
|
|
53300
54486
|
})
|
|
53301
54487
|
.add("combo", {
|
|
53302
54488
|
configuration: GenericChartConfigPanel,
|
|
@@ -53380,7 +54566,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53380
54566
|
class ChartTypePicker extends owl.Component {
|
|
53381
54567
|
static template = "o-spreadsheet-ChartTypePicker";
|
|
53382
54568
|
static components = { Section, Popover };
|
|
53383
|
-
static props = {
|
|
54569
|
+
static props = { chartId: String, chartPanelStore: Object };
|
|
53384
54570
|
categories = chartCategories;
|
|
53385
54571
|
chartTypeByCategories = {};
|
|
53386
54572
|
popoverRef = owl.useRef("popoverRef");
|
|
@@ -53405,14 +54591,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53405
54591
|
this.closePopover();
|
|
53406
54592
|
}
|
|
53407
54593
|
onTypeChange(type) {
|
|
53408
|
-
this.props.chartPanelStore.changeChartType(this.props.
|
|
54594
|
+
this.props.chartPanelStore.changeChartType(this.props.chartId, type);
|
|
53409
54595
|
this.closePopover();
|
|
53410
54596
|
}
|
|
53411
|
-
getChartDefinition(
|
|
53412
|
-
return this.env.model.getters.getChartDefinition(
|
|
54597
|
+
getChartDefinition(chartId) {
|
|
54598
|
+
return this.env.model.getters.getChartDefinition(chartId);
|
|
53413
54599
|
}
|
|
53414
54600
|
getSelectedChartSubtypeProperties() {
|
|
53415
|
-
const definition = this.getChartDefinition(this.props.
|
|
54601
|
+
const definition = this.getChartDefinition(this.props.chartId);
|
|
53416
54602
|
const matchedChart = chartSubtypeRegistry
|
|
53417
54603
|
.getAll()
|
|
53418
54604
|
.find((c) => c.matcher?.(definition) || false);
|
|
@@ -53444,34 +54630,36 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53444
54630
|
activatePanel(panel) {
|
|
53445
54631
|
this.panel = panel;
|
|
53446
54632
|
}
|
|
53447
|
-
changeChartType(
|
|
53448
|
-
const currentCreationContext = this.getters.getContextCreationChart(
|
|
53449
|
-
const savedCreationContext = this.creationContexts[
|
|
54633
|
+
changeChartType(chartId, newDisplayType) {
|
|
54634
|
+
const currentCreationContext = this.getters.getContextCreationChart(chartId);
|
|
54635
|
+
const savedCreationContext = this.creationContexts[chartId] || {};
|
|
53450
54636
|
let newRanges = currentCreationContext?.range;
|
|
53451
54637
|
if (newRanges?.every((range, i) => deepEquals(range, savedCreationContext.range?.[i]))) {
|
|
53452
54638
|
newRanges = Object.assign([], savedCreationContext.range, currentCreationContext?.range);
|
|
53453
54639
|
}
|
|
53454
|
-
this.creationContexts[
|
|
54640
|
+
this.creationContexts[chartId] = {
|
|
53455
54641
|
...savedCreationContext,
|
|
53456
54642
|
...currentCreationContext,
|
|
53457
54643
|
range: newRanges,
|
|
53458
54644
|
};
|
|
54645
|
+
const figureId = this.getters.getFigureIdFromChartId(chartId);
|
|
53459
54646
|
const sheetId = this.getters.getFigureSheetId(figureId);
|
|
53460
54647
|
if (!sheetId) {
|
|
53461
54648
|
return;
|
|
53462
54649
|
}
|
|
53463
|
-
const definition = this.getChartDefinitionFromContextCreation(
|
|
54650
|
+
const definition = this.getChartDefinitionFromContextCreation(chartId, newDisplayType);
|
|
53464
54651
|
this.model.dispatch("UPDATE_CHART", {
|
|
53465
54652
|
definition,
|
|
54653
|
+
chartId,
|
|
53466
54654
|
figureId,
|
|
53467
54655
|
sheetId,
|
|
53468
54656
|
});
|
|
53469
54657
|
}
|
|
53470
|
-
getChartDefinitionFromContextCreation(
|
|
54658
|
+
getChartDefinitionFromContextCreation(chartId, newDisplayType) {
|
|
53471
54659
|
const newChartInfo = chartSubtypeRegistry.get(newDisplayType);
|
|
53472
54660
|
const ChartClass = chartRegistry.get(newChartInfo.chartType);
|
|
53473
54661
|
return {
|
|
53474
|
-
...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[
|
|
54662
|
+
...ChartClass.getChartDefinitionFromContextCreation(this.creationContexts[chartId]),
|
|
53475
54663
|
...newChartInfo.subtypeDefinition,
|
|
53476
54664
|
};
|
|
53477
54665
|
}
|
|
@@ -53512,15 +54700,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53512
54700
|
class ChartPanel extends owl.Component {
|
|
53513
54701
|
static template = "o-spreadsheet-ChartPanel";
|
|
53514
54702
|
static components = { Section, ChartTypePicker };
|
|
53515
|
-
static props = { onCloseSidePanel: Function,
|
|
54703
|
+
static props = { onCloseSidePanel: Function, chartId: String };
|
|
53516
54704
|
panelContentRef;
|
|
53517
54705
|
scrollPositions = {
|
|
53518
54706
|
configuration: 0,
|
|
53519
54707
|
design: 0,
|
|
53520
54708
|
};
|
|
53521
54709
|
store;
|
|
53522
|
-
get
|
|
53523
|
-
return this.props.
|
|
54710
|
+
get chartId() {
|
|
54711
|
+
return this.props.chartId;
|
|
53524
54712
|
}
|
|
53525
54713
|
setup() {
|
|
53526
54714
|
this.store = useLocalStore(MainChartPanelStore);
|
|
@@ -53540,45 +54728,49 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53540
54728
|
}
|
|
53541
54729
|
this.store.activatePanel(panel);
|
|
53542
54730
|
}
|
|
53543
|
-
updateChart(
|
|
53544
|
-
|
|
54731
|
+
updateChart(chartId, updateDefinition) {
|
|
54732
|
+
const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
|
|
54733
|
+
if (chartId !== this.chartId) {
|
|
53545
54734
|
return;
|
|
53546
54735
|
}
|
|
53547
54736
|
const definition = {
|
|
53548
|
-
...this.getChartDefinition(this.
|
|
54737
|
+
...this.getChartDefinition(this.chartId),
|
|
53549
54738
|
...updateDefinition,
|
|
53550
54739
|
};
|
|
53551
54740
|
return this.env.model.dispatch("UPDATE_CHART", {
|
|
53552
54741
|
definition,
|
|
54742
|
+
chartId,
|
|
53553
54743
|
figureId,
|
|
53554
54744
|
sheetId: this.env.model.getters.getFigureSheetId(figureId),
|
|
53555
54745
|
});
|
|
53556
54746
|
}
|
|
53557
|
-
canUpdateChart(
|
|
53558
|
-
|
|
54747
|
+
canUpdateChart(chartId, updateDefinition) {
|
|
54748
|
+
const figureId = this.env.model.getters.getFigureIdFromChartId(chartId);
|
|
54749
|
+
if (chartId !== this.chartId || !this.env.model.getters.isChartDefined(chartId)) {
|
|
53559
54750
|
return;
|
|
53560
54751
|
}
|
|
53561
54752
|
const definition = {
|
|
53562
|
-
...this.getChartDefinition(this.
|
|
54753
|
+
...this.getChartDefinition(this.chartId),
|
|
53563
54754
|
...updateDefinition,
|
|
53564
54755
|
};
|
|
53565
54756
|
return this.env.model.canDispatch("UPDATE_CHART", {
|
|
53566
54757
|
definition,
|
|
54758
|
+
chartId,
|
|
53567
54759
|
figureId,
|
|
53568
54760
|
sheetId: this.env.model.getters.getFigureSheetId(figureId),
|
|
53569
54761
|
});
|
|
53570
54762
|
}
|
|
53571
54763
|
onTypeChange(type) {
|
|
53572
|
-
if (!this.
|
|
54764
|
+
if (!this.chartId) {
|
|
53573
54765
|
return;
|
|
53574
54766
|
}
|
|
53575
|
-
this.store.changeChartType(this.
|
|
54767
|
+
this.store.changeChartType(this.chartId, type);
|
|
53576
54768
|
}
|
|
53577
54769
|
get chartPanel() {
|
|
53578
|
-
if (!this.
|
|
54770
|
+
if (!this.chartId) {
|
|
53579
54771
|
throw new Error("Chart not defined.");
|
|
53580
54772
|
}
|
|
53581
|
-
const type = this.env.model.getters.getChartType(this.
|
|
54773
|
+
const type = this.env.model.getters.getChartType(this.chartId);
|
|
53582
54774
|
if (!type) {
|
|
53583
54775
|
throw new Error("Chart not defined.");
|
|
53584
54776
|
}
|
|
@@ -53588,8 +54780,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
53588
54780
|
}
|
|
53589
54781
|
return chartPanel;
|
|
53590
54782
|
}
|
|
53591
|
-
getChartDefinition(
|
|
53592
|
-
return this.env.model.getters.getChartDefinition(
|
|
54783
|
+
getChartDefinition(chartId) {
|
|
54784
|
+
return this.env.model.getters.getChartDefinition(chartId);
|
|
53593
54785
|
}
|
|
53594
54786
|
}
|
|
53595
54787
|
|
|
@@ -55526,11 +56718,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55526
56718
|
this.store = useLocalStore(PivotMeasureDisplayPanelStore, this.props.pivotId, this.props.measure);
|
|
55527
56719
|
}
|
|
55528
56720
|
onSave() {
|
|
55529
|
-
this.env.
|
|
56721
|
+
this.env.replaceSidePanel("PivotSidePanel", `pivot_measure_display_${this.props.pivotId}_${this.props.measure.id}`, {
|
|
56722
|
+
pivotId: this.props.pivotId,
|
|
56723
|
+
});
|
|
55530
56724
|
}
|
|
55531
56725
|
onCancel() {
|
|
55532
56726
|
this.store.cancelMeasureDisplayEdition();
|
|
55533
|
-
this.env.
|
|
56727
|
+
this.env.replaceSidePanel("PivotSidePanel", `pivot_measure_display_${this.props.pivotId}_${this.props.measure.id}`, {
|
|
56728
|
+
pivotId: this.props.pivotId,
|
|
56729
|
+
});
|
|
55534
56730
|
}
|
|
55535
56731
|
get fieldChoices() {
|
|
55536
56732
|
return this.store.fields.map((field) => ({
|
|
@@ -55591,103 +56787,6 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
55591
56787
|
}
|
|
55592
56788
|
}
|
|
55593
56789
|
|
|
55594
|
-
function useAutofocus({ refName }) {
|
|
55595
|
-
const ref = owl.useRef(refName);
|
|
55596
|
-
owl.useEffect((el) => {
|
|
55597
|
-
el?.focus();
|
|
55598
|
-
}, () => [ref.el]);
|
|
55599
|
-
}
|
|
55600
|
-
|
|
55601
|
-
css /* scss */ `
|
|
55602
|
-
.o-spreadsheet {
|
|
55603
|
-
.os-input {
|
|
55604
|
-
border-width: 0 0 1px 0;
|
|
55605
|
-
border-color: transparent;
|
|
55606
|
-
outline: none;
|
|
55607
|
-
text-overflow: ellipsis;
|
|
55608
|
-
color: ${TEXT_BODY};
|
|
55609
|
-
}
|
|
55610
|
-
.os-input:hover,
|
|
55611
|
-
.os-input:focus {
|
|
55612
|
-
border-color: ${GRAY_300};
|
|
55613
|
-
}
|
|
55614
|
-
}
|
|
55615
|
-
`;
|
|
55616
|
-
class TextInput extends owl.Component {
|
|
55617
|
-
static template = "o-spreadsheet-TextInput";
|
|
55618
|
-
static props = {
|
|
55619
|
-
value: String,
|
|
55620
|
-
onChange: Function,
|
|
55621
|
-
class: {
|
|
55622
|
-
type: String,
|
|
55623
|
-
optional: true,
|
|
55624
|
-
},
|
|
55625
|
-
id: {
|
|
55626
|
-
type: String,
|
|
55627
|
-
optional: true,
|
|
55628
|
-
},
|
|
55629
|
-
placeholder: {
|
|
55630
|
-
type: String,
|
|
55631
|
-
optional: true,
|
|
55632
|
-
},
|
|
55633
|
-
autofocus: {
|
|
55634
|
-
type: Boolean,
|
|
55635
|
-
optional: true,
|
|
55636
|
-
},
|
|
55637
|
-
};
|
|
55638
|
-
inputRef = owl.useRef("input");
|
|
55639
|
-
setup() {
|
|
55640
|
-
owl.useExternalListener(window, "click", (ev) => {
|
|
55641
|
-
if (ev.target !== this.inputRef.el && this.inputRef.el?.value !== this.props.value) {
|
|
55642
|
-
this.save();
|
|
55643
|
-
}
|
|
55644
|
-
}, { capture: true });
|
|
55645
|
-
if (this.props.autofocus) {
|
|
55646
|
-
useAutofocus({ refName: "input" });
|
|
55647
|
-
}
|
|
55648
|
-
}
|
|
55649
|
-
onKeyDown(ev) {
|
|
55650
|
-
switch (ev.key) {
|
|
55651
|
-
case "Enter":
|
|
55652
|
-
this.save();
|
|
55653
|
-
ev.preventDefault();
|
|
55654
|
-
ev.stopPropagation();
|
|
55655
|
-
break;
|
|
55656
|
-
case "Escape":
|
|
55657
|
-
if (this.inputRef.el) {
|
|
55658
|
-
this.inputRef.el.value = this.props.value;
|
|
55659
|
-
this.inputRef.el.blur();
|
|
55660
|
-
}
|
|
55661
|
-
ev.preventDefault();
|
|
55662
|
-
ev.stopPropagation();
|
|
55663
|
-
break;
|
|
55664
|
-
}
|
|
55665
|
-
}
|
|
55666
|
-
save() {
|
|
55667
|
-
const currentValue = (this.inputRef.el?.value || "").trim();
|
|
55668
|
-
if (currentValue !== this.props.value) {
|
|
55669
|
-
this.props.onChange(currentValue);
|
|
55670
|
-
}
|
|
55671
|
-
this.inputRef.el?.blur();
|
|
55672
|
-
}
|
|
55673
|
-
onMouseDown(ev) {
|
|
55674
|
-
// Stop the event if the input is not focused, we handle everything in onMouseUp
|
|
55675
|
-
if (ev.target !== document.activeElement) {
|
|
55676
|
-
ev.preventDefault();
|
|
55677
|
-
ev.stopPropagation();
|
|
55678
|
-
}
|
|
55679
|
-
}
|
|
55680
|
-
onMouseUp(ev) {
|
|
55681
|
-
const target = ev.target;
|
|
55682
|
-
if (target !== document.activeElement) {
|
|
55683
|
-
target.focus();
|
|
55684
|
-
target.select();
|
|
55685
|
-
ev.preventDefault();
|
|
55686
|
-
ev.stopPropagation();
|
|
55687
|
-
}
|
|
55688
|
-
}
|
|
55689
|
-
}
|
|
55690
|
-
|
|
55691
56790
|
class PivotCustomGroupsCollapsible extends owl.Component {
|
|
55692
56791
|
static template = "o-spreadsheet-PivotCustomGroupsCollapsible";
|
|
55693
56792
|
static props = {
|
|
@@ -56044,7 +57143,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56044
57143
|
});
|
|
56045
57144
|
}
|
|
56046
57145
|
openShowValuesAs() {
|
|
56047
|
-
this.env.
|
|
57146
|
+
this.env.replaceSidePanel("PivotMeasureDisplayPanel", `pivot_key_${this.props.pivotId}`, {
|
|
56048
57147
|
pivotId: this.props.pivotId,
|
|
56049
57148
|
measure: this.props.measure,
|
|
56050
57149
|
});
|
|
@@ -56305,7 +57404,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56305
57404
|
this.props.onDimensionsUpdated(update);
|
|
56306
57405
|
}
|
|
56307
57406
|
getMeasureId(fieldName, aggregator) {
|
|
56308
|
-
const baseId = fieldName + (aggregator ? `:${aggregator}` : "");
|
|
57407
|
+
const baseId = fieldName.replaceAll("'", "") + (aggregator ? `:${aggregator}` : "");
|
|
56309
57408
|
let id = baseId;
|
|
56310
57409
|
let i = 2;
|
|
56311
57410
|
while (this.props.definition.measures.some((m) => m.id === id)) {
|
|
@@ -56383,6 +57482,13 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56383
57482
|
const fieldName = field ? getFieldDisplayName(field) : "";
|
|
56384
57483
|
return measureDisplayTerms.descriptions[measureDisplay.type](fieldName);
|
|
56385
57484
|
}
|
|
57485
|
+
getHugeDimensionErrorMessage(dimension) {
|
|
57486
|
+
const pivot = this.env.model.getters.getPivot(this.props.pivotId);
|
|
57487
|
+
const possibleValues = pivot.getPossibleFieldValues(dimension);
|
|
57488
|
+
return possibleValues.length > 100
|
|
57489
|
+
? _t("This dimension contains a lot of values (%s), and might slow down the pivot table.", possibleValues.length)
|
|
57490
|
+
: undefined;
|
|
57491
|
+
}
|
|
56386
57492
|
}
|
|
56387
57493
|
|
|
56388
57494
|
class PivotTitleSection extends owl.Component {
|
|
@@ -56556,6 +57662,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56556
57662
|
draft = null;
|
|
56557
57663
|
notification = this.get(NotificationStore);
|
|
56558
57664
|
alreadyNotified = false;
|
|
57665
|
+
alreadyNotifiedForPivotSize = false;
|
|
56559
57666
|
constructor(get, pivotId) {
|
|
56560
57667
|
super(get);
|
|
56561
57668
|
this.pivotId = pivotId;
|
|
@@ -56674,6 +57781,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
56674
57781
|
sticky: true,
|
|
56675
57782
|
});
|
|
56676
57783
|
}
|
|
57784
|
+
const pivot = this.getters.getPivot(this.pivotId);
|
|
57785
|
+
const numberOfCells = pivot.isValid() ? pivot.getExpandedTableStructure().numberOfCells : 0;
|
|
57786
|
+
if (!this.alreadyNotifiedForPivotSize && numberOfCells > PIVOT_MAX_NUMBER_OF_CELLS) {
|
|
57787
|
+
this.alreadyNotifiedForPivotSize = true;
|
|
57788
|
+
this.notification.notifyUser({
|
|
57789
|
+
type: "warning",
|
|
57790
|
+
text: getPivotTooBigErrorMessage(numberOfCells, this.getters.getLocale()),
|
|
57791
|
+
sticky: true,
|
|
57792
|
+
});
|
|
57793
|
+
}
|
|
56677
57794
|
}
|
|
56678
57795
|
}
|
|
56679
57796
|
discardPendingUpdate() {
|
|
@@ -57802,11 +58919,12 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57802
58919
|
title: _t("Chart"),
|
|
57803
58920
|
Body: ChartPanel,
|
|
57804
58921
|
computeState: (getters, initialProps) => {
|
|
57805
|
-
const figureId = getters.getSelectedFigureId()
|
|
57806
|
-
|
|
58922
|
+
const figureId = getters.getSelectedFigureId();
|
|
58923
|
+
const chartId = figureId ? getters.getChartIdFromFigureId(figureId) : initialProps.chartId;
|
|
58924
|
+
if (!chartId || !getters.isChartDefined(chartId)) {
|
|
57807
58925
|
return { isOpen: false };
|
|
57808
58926
|
}
|
|
57809
|
-
return { isOpen: true, props: {
|
|
58927
|
+
return { isOpen: true, props: { chartId } };
|
|
57810
58928
|
},
|
|
57811
58929
|
});
|
|
57812
58930
|
sidePanelRegistry.add("FindAndReplace", {
|
|
@@ -57887,13 +59005,28 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57887
59005
|
try {
|
|
57888
59006
|
// This will throw if the pivot or measure does not exist
|
|
57889
59007
|
getters.getPivot(props.pivotId).getMeasure(props.measure.id);
|
|
57890
|
-
return {
|
|
59008
|
+
return {
|
|
59009
|
+
isOpen: true,
|
|
59010
|
+
props,
|
|
59011
|
+
key: `pivot_measure_display_${props.pivotId}_${props.measure.id}`,
|
|
59012
|
+
};
|
|
57891
59013
|
}
|
|
57892
59014
|
catch (e) {
|
|
57893
59015
|
return { isOpen: false };
|
|
57894
59016
|
}
|
|
57895
59017
|
},
|
|
57896
59018
|
});
|
|
59019
|
+
sidePanelRegistry.add("CarouselPanel", {
|
|
59020
|
+
title: _t("Carousel"),
|
|
59021
|
+
Body: CarouselPanel,
|
|
59022
|
+
computeState: (getters, initialProps) => {
|
|
59023
|
+
const figureId = initialProps.figureId || getters.getSelectedFigureId();
|
|
59024
|
+
if (!figureId || !getters.doesCarouselExist(figureId)) {
|
|
59025
|
+
return { isOpen: false };
|
|
59026
|
+
}
|
|
59027
|
+
return { isOpen: true, props: { figureId } };
|
|
59028
|
+
},
|
|
59029
|
+
});
|
|
57897
59030
|
|
|
57898
59031
|
class ScreenWidthStore {
|
|
57899
59032
|
mutators = ["setSmallThreshhold"];
|
|
@@ -57912,6 +59045,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57912
59045
|
class SidePanelStore extends SpreadsheetStore {
|
|
57913
59046
|
mutators = [
|
|
57914
59047
|
"open",
|
|
59048
|
+
"replace",
|
|
57915
59049
|
"toggle",
|
|
57916
59050
|
"close",
|
|
57917
59051
|
"changePanelSize",
|
|
@@ -57973,8 +59107,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57973
59107
|
if (!state.isOpen) {
|
|
57974
59108
|
return;
|
|
57975
59109
|
}
|
|
57976
|
-
|
|
57977
|
-
if (!this.mainPanel || !this.mainPanel.isPinned || mainPanelKey === state.key) {
|
|
59110
|
+
if (!this.mainPanel || !this.mainPanel.isPinned || this.mainPanelKey === state.key) {
|
|
57978
59111
|
this._openPanel("mainPanel", newPanelInfo, state);
|
|
57979
59112
|
return;
|
|
57980
59113
|
}
|
|
@@ -57993,6 +59126,34 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
57993
59126
|
}
|
|
57994
59127
|
this._openPanel("secondaryPanel", newPanelInfo, state);
|
|
57995
59128
|
}
|
|
59129
|
+
replace(componentTag, currentPanelKey, initialPanelProps = {}) {
|
|
59130
|
+
const newPanelInfo = { initialPanelProps, componentTag, size: DEFAULT_SIDE_PANEL_SIZE };
|
|
59131
|
+
const state = this.computeState(newPanelInfo);
|
|
59132
|
+
if (!state.isOpen) {
|
|
59133
|
+
return;
|
|
59134
|
+
}
|
|
59135
|
+
const ensureMainPanelExpanded = () => {
|
|
59136
|
+
if (this.mainPanel?.isCollapsed) {
|
|
59137
|
+
this.toggleCollapsePanel("mainPanel");
|
|
59138
|
+
}
|
|
59139
|
+
};
|
|
59140
|
+
// Close the current panel if the target panel is already open
|
|
59141
|
+
const isMainPanel = this.mainPanelKey === state.key;
|
|
59142
|
+
const isSecondaryPanel = this.secondaryPanelKey === state.key;
|
|
59143
|
+
if (isMainPanel && this.secondaryPanel) {
|
|
59144
|
+
this.close();
|
|
59145
|
+
ensureMainPanelExpanded();
|
|
59146
|
+
return;
|
|
59147
|
+
}
|
|
59148
|
+
if (isSecondaryPanel) {
|
|
59149
|
+
this.closeMainPanel();
|
|
59150
|
+
this.togglePinPanel();
|
|
59151
|
+
ensureMainPanelExpanded();
|
|
59152
|
+
return;
|
|
59153
|
+
}
|
|
59154
|
+
const targetPanel = this.mainPanelKey === currentPanelKey ? "mainPanel" : "secondaryPanel";
|
|
59155
|
+
this._openPanel(targetPanel, newPanelInfo, state);
|
|
59156
|
+
}
|
|
57996
59157
|
_openPanel(panel, newPanel, state) {
|
|
57997
59158
|
const currentPanel = this[panel];
|
|
57998
59159
|
if (currentPanel && newPanel.componentTag !== currentPanel.componentTag) {
|
|
@@ -58052,11 +59213,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58052
59213
|
panelInfo.size = size;
|
|
58053
59214
|
}
|
|
58054
59215
|
resetPanelSize(panel) {
|
|
58055
|
-
|
|
58056
|
-
|
|
58057
|
-
return;
|
|
59216
|
+
if (this[panel]) {
|
|
59217
|
+
this[panel].size = DEFAULT_SIDE_PANEL_SIZE;
|
|
58058
59218
|
}
|
|
58059
|
-
panelInfo.size = DEFAULT_SIDE_PANEL_SIZE;
|
|
58060
59219
|
}
|
|
58061
59220
|
togglePinPanel() {
|
|
58062
59221
|
if (!this.mainPanel) {
|
|
@@ -58855,7 +60014,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58855
60014
|
let lastFigureId = undefined;
|
|
58856
60015
|
owl.onWillUpdateProps(() => {
|
|
58857
60016
|
if (lastFigureId !== this.figureUI?.id) {
|
|
58858
|
-
animationStore.enableAnimationForChart(this.
|
|
60017
|
+
animationStore.enableAnimationForChart(this.chartId + "-fullscreen");
|
|
58859
60018
|
}
|
|
58860
60019
|
lastFigureId = this.figureUI?.id;
|
|
58861
60020
|
});
|
|
@@ -58864,6 +60023,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58864
60023
|
get figureUI() {
|
|
58865
60024
|
return this.fullScreenChartStore.fullScreenFigure;
|
|
58866
60025
|
}
|
|
60026
|
+
get chartId() {
|
|
60027
|
+
if (!this.figureUI)
|
|
60028
|
+
return undefined;
|
|
60029
|
+
return this.env.model.getters.getChartIdFromFigureId(this.figureUI?.id);
|
|
60030
|
+
}
|
|
58867
60031
|
exitFullScreen() {
|
|
58868
60032
|
if (this.figureUI) {
|
|
58869
60033
|
this.fullScreenChartStore.toggleFullScreenChart(this.figureUI.id);
|
|
@@ -58875,9 +60039,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
58875
60039
|
}
|
|
58876
60040
|
}
|
|
58877
60041
|
get chartComponent() {
|
|
58878
|
-
if (!this.
|
|
60042
|
+
if (!this.chartId)
|
|
58879
60043
|
return undefined;
|
|
58880
|
-
const type = this.env.model.getters.getChartType(this.
|
|
60044
|
+
const type = this.env.model.getters.getChartType(this.chartId);
|
|
58881
60045
|
const component = chartComponentRegistry.get(type);
|
|
58882
60046
|
if (!component) {
|
|
58883
60047
|
throw new Error(`Component is not defined for type ${type}`);
|
|
@@ -60536,6 +61700,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60536
61700
|
"getChartType",
|
|
60537
61701
|
"getChartIds",
|
|
60538
61702
|
"getChart",
|
|
61703
|
+
"getFigureIdFromChartId",
|
|
60539
61704
|
"getContextCreationChart",
|
|
60540
61705
|
];
|
|
60541
61706
|
charts = {};
|
|
@@ -60543,7 +61708,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60543
61708
|
validateChartDefinition = (cmd) => validateChartDefinition(this, cmd.definition);
|
|
60544
61709
|
adaptRanges(applyChange) {
|
|
60545
61710
|
for (const [chartId, chart] of Object.entries(this.charts)) {
|
|
60546
|
-
|
|
61711
|
+
if (!chart) {
|
|
61712
|
+
continue;
|
|
61713
|
+
}
|
|
61714
|
+
const newChart = chart.chart.updateRanges(applyChange);
|
|
61715
|
+
this.history.update("charts", chartId, newChart ? { figureId: chart.figureId, chart: newChart } : undefined);
|
|
60547
61716
|
}
|
|
60548
61717
|
}
|
|
60549
61718
|
// ---------------------------------------------------------------------------
|
|
@@ -60552,9 +61721,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60552
61721
|
allowDispatch(cmd) {
|
|
60553
61722
|
switch (cmd.type) {
|
|
60554
61723
|
case "CREATE_CHART":
|
|
60555
|
-
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartDuplicate));
|
|
61724
|
+
return this.checkValidations(cmd, this.chainValidations(this.checkFigureArguments, this.validateChartDefinition, this.checkChartDuplicate));
|
|
60556
61725
|
case "UPDATE_CHART":
|
|
60557
61726
|
return this.checkValidations(cmd, this.chainValidations(this.validateChartDefinition, this.checkChartExists, this.checkChartChanged));
|
|
61727
|
+
case "DELETE_CHART":
|
|
61728
|
+
return this.checkChartExists(cmd);
|
|
60558
61729
|
default:
|
|
60559
61730
|
return "Success" /* CommandResult.Success */;
|
|
60560
61731
|
}
|
|
@@ -60562,37 +61733,61 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60562
61733
|
handle(cmd) {
|
|
60563
61734
|
switch (cmd.type) {
|
|
60564
61735
|
case "CREATE_CHART":
|
|
60565
|
-
|
|
60566
|
-
|
|
61736
|
+
const { col, row, offset, size, sheetId, figureId } = cmd;
|
|
61737
|
+
// If figure position is not defined, it means that the figure already exist (see allowDispatch)
|
|
61738
|
+
if (!this.getters.getFigure(sheetId, figureId) &&
|
|
61739
|
+
offset !== undefined &&
|
|
61740
|
+
col !== undefined &&
|
|
61741
|
+
row !== undefined) {
|
|
61742
|
+
this.addFigure(figureId, sheetId, col, row, offset, size);
|
|
61743
|
+
}
|
|
61744
|
+
this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
|
|
60567
61745
|
break;
|
|
60568
61746
|
case "UPDATE_CHART": {
|
|
60569
|
-
this.addChart(cmd.figureId, cmd.definition);
|
|
61747
|
+
this.addChart(cmd.figureId, cmd.chartId, cmd.definition);
|
|
60570
61748
|
break;
|
|
60571
61749
|
}
|
|
60572
61750
|
case "DUPLICATE_SHEET": {
|
|
60573
|
-
const
|
|
60574
|
-
|
|
60575
|
-
if (
|
|
60576
|
-
|
|
60577
|
-
|
|
60578
|
-
|
|
60579
|
-
|
|
60580
|
-
|
|
60581
|
-
|
|
60582
|
-
|
|
60583
|
-
|
|
60584
|
-
|
|
60585
|
-
|
|
60586
|
-
|
|
60587
|
-
|
|
60588
|
-
|
|
60589
|
-
|
|
61751
|
+
for (const chartId of this.getChartIds(cmd.sheetId)) {
|
|
61752
|
+
const { chart, figureId } = this.charts[chartId] || {};
|
|
61753
|
+
if (!chart || !figureId) {
|
|
61754
|
+
continue;
|
|
61755
|
+
}
|
|
61756
|
+
const fig = this.getters.getFigure(cmd.sheetId, figureId);
|
|
61757
|
+
if (!fig) {
|
|
61758
|
+
continue;
|
|
61759
|
+
}
|
|
61760
|
+
const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
|
|
61761
|
+
const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
|
|
61762
|
+
const chartIdBase = chartId.split(FIGURE_ID_SPLITTER).pop();
|
|
61763
|
+
const duplicatedChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
|
|
61764
|
+
const newChart = chart.duplicateInDuplicatedSheet(cmd.sheetIdTo);
|
|
61765
|
+
if (newChart) {
|
|
61766
|
+
this.dispatch("CREATE_CHART", {
|
|
61767
|
+
figureId: duplicatedFigureId,
|
|
61768
|
+
chartId: duplicatedChartId,
|
|
61769
|
+
col: fig.col,
|
|
61770
|
+
row: fig.row,
|
|
61771
|
+
offset: fig.offset,
|
|
61772
|
+
size: { width: fig.width, height: fig.height },
|
|
61773
|
+
definition: newChart.getDefinition(),
|
|
61774
|
+
sheetId: cmd.sheetIdTo,
|
|
61775
|
+
});
|
|
60590
61776
|
}
|
|
60591
61777
|
}
|
|
60592
61778
|
break;
|
|
60593
61779
|
}
|
|
60594
61780
|
case "DELETE_FIGURE":
|
|
60595
|
-
this.
|
|
61781
|
+
for (const chartId in this.charts) {
|
|
61782
|
+
if (this.charts[chartId]?.figureId === cmd.figureId) {
|
|
61783
|
+
this.dispatch("DELETE_CHART", { chartId, sheetId: cmd.sheetId });
|
|
61784
|
+
}
|
|
61785
|
+
}
|
|
61786
|
+
break;
|
|
61787
|
+
case "DELETE_CHART":
|
|
61788
|
+
if (this.isChartDefined(cmd.chartId)) {
|
|
61789
|
+
this.history.update("charts", cmd.chartId, undefined);
|
|
61790
|
+
}
|
|
60596
61791
|
break;
|
|
60597
61792
|
case "DELETE_SHEET":
|
|
60598
61793
|
for (const id of this.getChartIds(cmd.sheetId)) {
|
|
@@ -60604,31 +61799,37 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60604
61799
|
// ---------------------------------------------------------------------------
|
|
60605
61800
|
// Getters
|
|
60606
61801
|
// ---------------------------------------------------------------------------
|
|
60607
|
-
getContextCreationChart(
|
|
60608
|
-
return this.charts[
|
|
61802
|
+
getContextCreationChart(chartId) {
|
|
61803
|
+
return this.charts[chartId]?.chart.getContextCreation();
|
|
60609
61804
|
}
|
|
60610
|
-
getChart(
|
|
60611
|
-
return this.charts[
|
|
61805
|
+
getChart(chartId) {
|
|
61806
|
+
return this.charts[chartId]?.chart;
|
|
61807
|
+
}
|
|
61808
|
+
getFigureIdFromChartId(chartId) {
|
|
61809
|
+
if (!this.charts[chartId]) {
|
|
61810
|
+
throw new Error(`Chart with id ${chartId} does not exist.`);
|
|
61811
|
+
}
|
|
61812
|
+
return this.charts[chartId].figureId;
|
|
60612
61813
|
}
|
|
60613
|
-
getChartType(
|
|
60614
|
-
const type = this.charts[
|
|
61814
|
+
getChartType(chartId) {
|
|
61815
|
+
const type = this.charts[chartId]?.chart.type;
|
|
60615
61816
|
if (!type) {
|
|
60616
61817
|
throw new Error("Chart not defined.");
|
|
60617
61818
|
}
|
|
60618
61819
|
return type;
|
|
60619
61820
|
}
|
|
60620
|
-
isChartDefined(
|
|
60621
|
-
return
|
|
61821
|
+
isChartDefined(chartId) {
|
|
61822
|
+
return chartId in this.charts && this.charts !== undefined;
|
|
60622
61823
|
}
|
|
60623
61824
|
getChartIds(sheetId) {
|
|
60624
61825
|
return Object.entries(this.charts)
|
|
60625
|
-
.filter(([, chart]) => chart?.sheetId === sheetId)
|
|
61826
|
+
.filter(([, chart]) => chart?.chart.sheetId === sheetId)
|
|
60626
61827
|
.map(([id]) => id);
|
|
60627
61828
|
}
|
|
60628
|
-
getChartDefinition(
|
|
60629
|
-
const definition = this.charts[
|
|
61829
|
+
getChartDefinition(chartId) {
|
|
61830
|
+
const definition = this.charts[chartId]?.chart.getDefinition();
|
|
60630
61831
|
if (!definition) {
|
|
60631
|
-
throw new Error(`There is no chart with the given
|
|
61832
|
+
throw new Error(`There is no chart with the given id: ${chartId}`);
|
|
60632
61833
|
}
|
|
60633
61834
|
return definition;
|
|
60634
61835
|
}
|
|
@@ -60643,7 +61844,16 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60643
61844
|
// figure data should be external IMO => chart should be in sheet.chart
|
|
60644
61845
|
// instead of in figure.data
|
|
60645
61846
|
if (figure.tag === "chart") {
|
|
60646
|
-
|
|
61847
|
+
const chartId = figure.data.chartId;
|
|
61848
|
+
const chart = this.createChart(figure.id, figure.data, sheet.id);
|
|
61849
|
+
this.charts[chartId] = { chart, figureId: figure.id };
|
|
61850
|
+
}
|
|
61851
|
+
else if (figure.tag === "carousel") {
|
|
61852
|
+
for (const chartId in figure.data.chartDefinitions || {}) {
|
|
61853
|
+
const chartDefinition = figure.data.chartDefinitions[chartId];
|
|
61854
|
+
const chart = this.createChart(figure.id, chartDefinition, sheet.id);
|
|
61855
|
+
this.charts[chartId] = { chart, figureId: figure.id };
|
|
61856
|
+
}
|
|
60647
61857
|
}
|
|
60648
61858
|
}
|
|
60649
61859
|
}
|
|
@@ -60657,13 +61867,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60657
61867
|
const figures = [];
|
|
60658
61868
|
for (const sheetFigure of sheetFigures) {
|
|
60659
61869
|
const figure = sheetFigure;
|
|
60660
|
-
|
|
60661
|
-
|
|
61870
|
+
const chartId = Object.keys(this.charts).find((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
|
|
61871
|
+
if (figure && figure.tag === "chart" && chartId) {
|
|
61872
|
+
const data = this.charts[chartId]?.chart.getDefinition();
|
|
60662
61873
|
if (data) {
|
|
60663
|
-
figure.data = data;
|
|
61874
|
+
figure.data = { ...data, chartId };
|
|
60664
61875
|
figures.push(figure);
|
|
60665
61876
|
}
|
|
60666
61877
|
}
|
|
61878
|
+
else if (figure && figure.tag === "carousel") {
|
|
61879
|
+
const chartIds = Object.keys(this.charts).filter((chartId) => this.charts[chartId]?.figureId === sheetFigure.id);
|
|
61880
|
+
const data = {};
|
|
61881
|
+
for (const chartId of chartIds) {
|
|
61882
|
+
data[chartId] = this.charts[chartId]?.chart.getDefinition();
|
|
61883
|
+
}
|
|
61884
|
+
figure.data = { chartDefinitions: data };
|
|
61885
|
+
figures.push(figure);
|
|
61886
|
+
}
|
|
60667
61887
|
else {
|
|
60668
61888
|
figures.push(figure);
|
|
60669
61889
|
}
|
|
@@ -60696,27 +61916,40 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
60696
61916
|
* Add a chart in the local state. If a chart already exists, this chart is
|
|
60697
61917
|
* replaced
|
|
60698
61918
|
*/
|
|
60699
|
-
addChart(
|
|
60700
|
-
const sheetId = this.getters.getFigureSheetId(
|
|
61919
|
+
addChart(figureId, chartId, definition) {
|
|
61920
|
+
const sheetId = this.getters.getFigureSheetId(figureId);
|
|
60701
61921
|
if (sheetId) {
|
|
60702
|
-
|
|
61922
|
+
const chart = this.createChart(figureId, definition, sheetId);
|
|
61923
|
+
this.history.update("charts", chartId, { figureId, chart });
|
|
60703
61924
|
}
|
|
60704
61925
|
}
|
|
60705
61926
|
checkChartDuplicate(cmd) {
|
|
60706
|
-
return this.
|
|
61927
|
+
return this.isChartDefined(cmd.chartId)
|
|
60707
61928
|
? "DuplicatedChartId" /* CommandResult.DuplicatedChartId */
|
|
60708
61929
|
: "Success" /* CommandResult.Success */;
|
|
60709
61930
|
}
|
|
60710
61931
|
checkChartExists(cmd) {
|
|
60711
|
-
return this.isChartDefined(cmd.
|
|
61932
|
+
return this.isChartDefined(cmd.chartId)
|
|
60712
61933
|
? "Success" /* CommandResult.Success */
|
|
60713
61934
|
: "ChartDoesNotExist" /* CommandResult.ChartDoesNotExist */;
|
|
60714
61935
|
}
|
|
60715
61936
|
checkChartChanged(cmd) {
|
|
60716
|
-
|
|
61937
|
+
if (cmd.figureId !== this.charts[cmd.chartId]?.figureId) {
|
|
61938
|
+
return "Success" /* CommandResult.Success */;
|
|
61939
|
+
}
|
|
61940
|
+
return deepEquals(this.getChartDefinition(cmd.chartId), cmd.definition)
|
|
60717
61941
|
? "NoChanges" /* CommandResult.NoChanges */
|
|
60718
61942
|
: "Success" /* CommandResult.Success */;
|
|
60719
61943
|
}
|
|
61944
|
+
/** If the command would create a new figure, there need to be a position & offset defined in the command */
|
|
61945
|
+
checkFigureArguments(cmd) {
|
|
61946
|
+
if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
|
|
61947
|
+
return "Success" /* CommandResult.Success */;
|
|
61948
|
+
}
|
|
61949
|
+
return cmd.offset !== undefined && cmd.col !== undefined && cmd.row !== undefined
|
|
61950
|
+
? "Success" /* CommandResult.Success */
|
|
61951
|
+
: "MissingFigureArguments" /* CommandResult.MissingFigureArguments */;
|
|
61952
|
+
}
|
|
60720
61953
|
}
|
|
60721
61954
|
|
|
60722
61955
|
// -----------------------------------------------------------------------------
|
|
@@ -61570,6 +62803,23 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61570
62803
|
this.onRowRemove(cmd.sheetId);
|
|
61571
62804
|
}
|
|
61572
62805
|
break;
|
|
62806
|
+
case "DUPLICATE_SHEET": {
|
|
62807
|
+
for (const figureId in this.figures[cmd.sheetId]) {
|
|
62808
|
+
const fig = this.figures[cmd.sheetId]?.[figureId];
|
|
62809
|
+
if (!fig) {
|
|
62810
|
+
continue;
|
|
62811
|
+
}
|
|
62812
|
+
const figureIdBase = figureId.split(FIGURE_ID_SPLITTER).pop();
|
|
62813
|
+
const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
|
|
62814
|
+
this.dispatch("CREATE_FIGURE", {
|
|
62815
|
+
figureId: duplicatedFigureId,
|
|
62816
|
+
...fig,
|
|
62817
|
+
size: { width: fig.width, height: fig.height },
|
|
62818
|
+
sheetId: cmd.sheetIdTo,
|
|
62819
|
+
});
|
|
62820
|
+
}
|
|
62821
|
+
break;
|
|
62822
|
+
}
|
|
61573
62823
|
}
|
|
61574
62824
|
}
|
|
61575
62825
|
onColRemove(sheetId) {
|
|
@@ -61681,6 +62931,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
61681
62931
|
const figure = { ...this.getFigure(sheetId, figureId), ...update };
|
|
61682
62932
|
for (const [key, value] of Object.entries(update)) {
|
|
61683
62933
|
switch (key) {
|
|
62934
|
+
case "tag":
|
|
62935
|
+
this.history.update("figures", sheetId, figure.id, key, value);
|
|
62936
|
+
break;
|
|
61684
62937
|
case "offset":
|
|
61685
62938
|
this.history.update("figures", sheetId, figure.id, key, value);
|
|
61686
62939
|
break;
|
|
@@ -62108,7 +63361,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
62108
63361
|
handle(cmd) {
|
|
62109
63362
|
switch (cmd.type) {
|
|
62110
63363
|
case "CREATE_IMAGE":
|
|
62111
|
-
this.
|
|
63364
|
+
if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
|
|
63365
|
+
this.addFigure(cmd.figureId, cmd.sheetId, cmd.col, cmd.row, cmd.offset, cmd.size);
|
|
63366
|
+
}
|
|
62112
63367
|
this.history.update("images", cmd.sheetId, cmd.figureId, cmd.definition);
|
|
62113
63368
|
this.syncedImages.add(cmd.definition.path);
|
|
62114
63369
|
break;
|
|
@@ -64246,6 +65501,122 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
64246
65501
|
}
|
|
64247
65502
|
}
|
|
64248
65503
|
|
|
65504
|
+
class CarouselPlugin extends CorePlugin {
|
|
65505
|
+
static getters = ["getCarousel", "doesCarouselExist"];
|
|
65506
|
+
carousels = {};
|
|
65507
|
+
allowDispatch(cmd) {
|
|
65508
|
+
switch (cmd.type) {
|
|
65509
|
+
case "CREATE_CAROUSEL": {
|
|
65510
|
+
if (this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
|
|
65511
|
+
return "DuplicatedFigureId" /* CommandResult.DuplicatedFigureId */;
|
|
65512
|
+
}
|
|
65513
|
+
return "Success" /* CommandResult.Success */;
|
|
65514
|
+
}
|
|
65515
|
+
case "UPDATE_CAROUSEL": {
|
|
65516
|
+
if (!this.carousels[cmd.sheetId]?.[cmd.figureId]) {
|
|
65517
|
+
return "InvalidFigureId" /* CommandResult.InvalidFigureId */;
|
|
65518
|
+
}
|
|
65519
|
+
return "Success" /* CommandResult.Success */;
|
|
65520
|
+
}
|
|
65521
|
+
}
|
|
65522
|
+
return "Success" /* CommandResult.Success */;
|
|
65523
|
+
}
|
|
65524
|
+
handle(cmd) {
|
|
65525
|
+
switch (cmd.type) {
|
|
65526
|
+
case "CREATE_CAROUSEL":
|
|
65527
|
+
if (!this.getters.getFigure(cmd.sheetId, cmd.figureId)) {
|
|
65528
|
+
this.dispatch("CREATE_FIGURE", { ...cmd, tag: "carousel" });
|
|
65529
|
+
}
|
|
65530
|
+
this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
|
|
65531
|
+
break;
|
|
65532
|
+
case "UPDATE_CAROUSEL":
|
|
65533
|
+
this.removeDeletedCharts(cmd, this.getters.getCarousel(cmd.figureId).items);
|
|
65534
|
+
this.history.update("carousels", cmd.sheetId, cmd.figureId, cmd.definition);
|
|
65535
|
+
break;
|
|
65536
|
+
case "DUPLICATE_SHEET": {
|
|
65537
|
+
const sheetFiguresFrom = this.getters.getFigures(cmd.sheetId);
|
|
65538
|
+
for (const fig of sheetFiguresFrom) {
|
|
65539
|
+
if (fig.tag === "carousel") {
|
|
65540
|
+
const figureIdBase = fig.id.split(FIGURE_ID_SPLITTER).pop();
|
|
65541
|
+
const duplicatedFigureId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${figureIdBase}`;
|
|
65542
|
+
const carousel = this.getCarousel(fig.id);
|
|
65543
|
+
if (carousel) {
|
|
65544
|
+
const size = { width: fig.width, height: fig.height };
|
|
65545
|
+
this.dispatch("CREATE_CAROUSEL", {
|
|
65546
|
+
sheetId: cmd.sheetIdTo,
|
|
65547
|
+
figureId: duplicatedFigureId,
|
|
65548
|
+
offset: fig.offset,
|
|
65549
|
+
col: fig.col,
|
|
65550
|
+
row: fig.row,
|
|
65551
|
+
size,
|
|
65552
|
+
definition: {
|
|
65553
|
+
items: carousel.items.map((item) => {
|
|
65554
|
+
if (item.type === "carouselDataView") {
|
|
65555
|
+
return { type: "carouselDataView" };
|
|
65556
|
+
}
|
|
65557
|
+
const chartIdBase = item.chartId.split(FIGURE_ID_SPLITTER).pop();
|
|
65558
|
+
const newChartId = `${cmd.sheetIdTo}${FIGURE_ID_SPLITTER}${chartIdBase}`;
|
|
65559
|
+
return { type: "chart", chartId: newChartId };
|
|
65560
|
+
}),
|
|
65561
|
+
},
|
|
65562
|
+
});
|
|
65563
|
+
}
|
|
65564
|
+
}
|
|
65565
|
+
}
|
|
65566
|
+
break;
|
|
65567
|
+
}
|
|
65568
|
+
case "DELETE_FIGURE":
|
|
65569
|
+
this.history.update("carousels", cmd.sheetId, cmd.figureId, undefined);
|
|
65570
|
+
break;
|
|
65571
|
+
case "DELETE_SHEET":
|
|
65572
|
+
this.history.update("carousels", cmd.sheetId, undefined);
|
|
65573
|
+
break;
|
|
65574
|
+
}
|
|
65575
|
+
}
|
|
65576
|
+
doesCarouselExist(figureId) {
|
|
65577
|
+
for (const sheetId in this.carousels) {
|
|
65578
|
+
if (this.carousels[sheetId]?.[figureId]) {
|
|
65579
|
+
return true;
|
|
65580
|
+
}
|
|
65581
|
+
}
|
|
65582
|
+
throw false;
|
|
65583
|
+
}
|
|
65584
|
+
getCarousel(figureId) {
|
|
65585
|
+
for (const sheetId in this.carousels) {
|
|
65586
|
+
if (this.carousels[sheetId]?.[figureId]) {
|
|
65587
|
+
return this.carousels[sheetId][figureId];
|
|
65588
|
+
}
|
|
65589
|
+
}
|
|
65590
|
+
throw new Error(`There is no carousel with the given figureId: ${figureId}`);
|
|
65591
|
+
}
|
|
65592
|
+
removeDeletedCharts(cmd, oldItems) {
|
|
65593
|
+
const newChartIds = new Set(cmd.definition.items.filter((item) => item.type === "chart").map((item) => item.chartId));
|
|
65594
|
+
for (const item of oldItems) {
|
|
65595
|
+
if (item.type === "chart" && !newChartIds.has(item.chartId)) {
|
|
65596
|
+
this.dispatch("DELETE_CHART", { chartId: item.chartId, sheetId: cmd.sheetId });
|
|
65597
|
+
}
|
|
65598
|
+
}
|
|
65599
|
+
}
|
|
65600
|
+
import(data) {
|
|
65601
|
+
for (const sheet of data.sheets) {
|
|
65602
|
+
const carousels = (sheet.figures || []).filter((figure) => figure.tag === "carousel");
|
|
65603
|
+
for (const carousel of carousels) {
|
|
65604
|
+
this.history.update("carousels", sheet.id, carousel.id, { items: carousel.data.items });
|
|
65605
|
+
}
|
|
65606
|
+
}
|
|
65607
|
+
}
|
|
65608
|
+
export(data) {
|
|
65609
|
+
for (const sheet of data.sheets) {
|
|
65610
|
+
const carousels = sheet.figures.filter((figure) => figure.tag === "carousel");
|
|
65611
|
+
for (const carousel of carousels) {
|
|
65612
|
+
if (this.carousels[sheet.id]?.[carousel.id]) {
|
|
65613
|
+
carousel.data = { ...carousel.data, ...this.carousels[sheet.id]?.[carousel.id] };
|
|
65614
|
+
}
|
|
65615
|
+
}
|
|
65616
|
+
}
|
|
65617
|
+
}
|
|
65618
|
+
}
|
|
65619
|
+
|
|
64249
65620
|
class HeaderGroupingPlugin extends CorePlugin {
|
|
64250
65621
|
static getters = [
|
|
64251
65622
|
"getHeaderGroups",
|
|
@@ -67201,7 +68572,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67201
68572
|
break;
|
|
67202
68573
|
case "UPDATE_CHART":
|
|
67203
68574
|
case "CREATE_CHART":
|
|
67204
|
-
this.tryToAddColors(this.getChartColors(cmd.
|
|
68575
|
+
this.tryToAddColors(this.getChartColors(cmd.chartId));
|
|
67205
68576
|
break;
|
|
67206
68577
|
case "UPDATE_CELL":
|
|
67207
68578
|
case "ADD_CONDITIONAL_FORMAT":
|
|
@@ -67333,8 +68704,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67333
68704
|
switch (cmd.type) {
|
|
67334
68705
|
case "UPDATE_CHART":
|
|
67335
68706
|
case "CREATE_CHART":
|
|
67336
|
-
|
|
67337
|
-
|
|
68707
|
+
this.charts[cmd.chartId] = undefined;
|
|
68708
|
+
break;
|
|
68709
|
+
case "DELETE_CHART":
|
|
68710
|
+
this.charts[cmd.chartId] = undefined;
|
|
67338
68711
|
break;
|
|
67339
68712
|
case "DELETE_SHEET":
|
|
67340
68713
|
for (const chartId in this.charts) {
|
|
@@ -67345,15 +68718,15 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67345
68718
|
break;
|
|
67346
68719
|
}
|
|
67347
68720
|
}
|
|
67348
|
-
getChartRuntime(
|
|
67349
|
-
if (!this.charts[
|
|
67350
|
-
const chart = this.getters.getChart(
|
|
68721
|
+
getChartRuntime(chartId) {
|
|
68722
|
+
if (!this.charts[chartId]) {
|
|
68723
|
+
const chart = this.getters.getChart(chartId);
|
|
67351
68724
|
if (!chart) {
|
|
67352
|
-
throw new Error(`No chart for the given id: ${
|
|
68725
|
+
throw new Error(`No chart for the given id: ${chartId}`);
|
|
67353
68726
|
}
|
|
67354
|
-
this.charts[
|
|
68727
|
+
this.charts[chartId] = this.createRuntimeChart(chart);
|
|
67355
68728
|
}
|
|
67356
|
-
return this.charts[
|
|
68729
|
+
return this.charts[chartId];
|
|
67357
68730
|
}
|
|
67358
68731
|
/**
|
|
67359
68732
|
* Get the background and textColor of a chart based on the color of the first cell of the main range of the chart.
|
|
@@ -67388,8 +68761,14 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67388
68761
|
if (!figure || figure.tag !== "chart") {
|
|
67389
68762
|
continue;
|
|
67390
68763
|
}
|
|
67391
|
-
const
|
|
67392
|
-
|
|
68764
|
+
const chartId = this.getters
|
|
68765
|
+
.getChartIds(sheet.id)
|
|
68766
|
+
.find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figure.id);
|
|
68767
|
+
if (!chartId) {
|
|
68768
|
+
continue;
|
|
68769
|
+
}
|
|
68770
|
+
const chart = this.getters.getChart(chartId);
|
|
68771
|
+
const figureData = chart?.getDefinitionForExcel(this.getters);
|
|
67393
68772
|
if (figureData) {
|
|
67394
68773
|
figures.push({
|
|
67395
68774
|
...figure,
|
|
@@ -67397,12 +68776,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
67397
68776
|
});
|
|
67398
68777
|
}
|
|
67399
68778
|
else {
|
|
67400
|
-
const chart = this.getters.getChart(figureId);
|
|
67401
68779
|
if (!chart) {
|
|
67402
68780
|
continue;
|
|
67403
68781
|
}
|
|
67404
|
-
const type = this.getters.getChartType(
|
|
67405
|
-
const runtime = this.getters.getChartRuntime(
|
|
68782
|
+
const type = this.getters.getChartType(chartId);
|
|
68783
|
+
const runtime = this.getters.getChartRuntime(chartId);
|
|
67406
68784
|
const img = chartToImageUrl(runtime, figure, type);
|
|
67407
68785
|
if (img) {
|
|
67408
68786
|
sheet.images.push({
|
|
@@ -70536,7 +71914,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70536
71914
|
otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
|
|
70537
71915
|
otRegistry.addTransformation("REMOVE_COLUMNS_ROWS", ["ADD_COLUMNS_ROWS"], addHeadersTransformation);
|
|
70538
71916
|
otRegistry.addTransformation("DELETE_SHEET", ["MOVE_RANGES"], transformTargetSheetId);
|
|
70539
|
-
otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART"], updateChartFigure);
|
|
71917
|
+
otRegistry.addTransformation("DELETE_FIGURE", ["UPDATE_FIGURE", "UPDATE_CHART", "UPDATE_CAROUSEL"], updateChartFigure);
|
|
71918
|
+
otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CHART"], updateChartOnChartDelete);
|
|
71919
|
+
otRegistry.addTransformation("DELETE_CHART", ["UPDATE_CAROUSEL"], updateCarouselOnChartDelete);
|
|
70540
71920
|
otRegistry.addTransformation("CREATE_SHEET", ["CREATE_SHEET"], createSheetTransformation);
|
|
70541
71921
|
otRegistry.addTransformation("ADD_MERGE", ["ADD_MERGE", "REMOVE_MERGE"], mergeTransformation);
|
|
70542
71922
|
otRegistry.addTransformation("ADD_COLUMNS_ROWS", ["FREEZE_COLUMNS", "FREEZE_ROWS"], freezeTransformation);
|
|
@@ -70589,6 +71969,21 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
70589
71969
|
}
|
|
70590
71970
|
return toTransform;
|
|
70591
71971
|
}
|
|
71972
|
+
function updateChartOnChartDelete(toTransform, executed) {
|
|
71973
|
+
if (toTransform.chartId === executed.chartId) {
|
|
71974
|
+
return undefined;
|
|
71975
|
+
}
|
|
71976
|
+
return toTransform;
|
|
71977
|
+
}
|
|
71978
|
+
function updateCarouselOnChartDelete(toTransform, executed) {
|
|
71979
|
+
return {
|
|
71980
|
+
...toTransform,
|
|
71981
|
+
definition: {
|
|
71982
|
+
...toTransform.definition,
|
|
71983
|
+
items: toTransform.definition.items.filter((item) => !(item.type === "chart" && item.chartId === executed.chartId)),
|
|
71984
|
+
},
|
|
71985
|
+
};
|
|
71986
|
+
}
|
|
70592
71987
|
function createSheetTransformation(toTransform, executed) {
|
|
70593
71988
|
if (toTransform.sheetId === executed.sheetId) {
|
|
70594
71989
|
toTransform = { ...toTransform, sheetId: `${toTransform.sheetId}~` };
|
|
@@ -72983,9 +74378,11 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
72983
74378
|
|
|
72984
74379
|
const uuidGenerator = new UuidGenerator();
|
|
72985
74380
|
function repeatCreateChartCommand(getters, cmd) {
|
|
74381
|
+
const id = uuidGenerator.smallUuid();
|
|
72986
74382
|
return {
|
|
72987
74383
|
...repeatSheetDependantCommand(getters, cmd),
|
|
72988
|
-
figureId:
|
|
74384
|
+
figureId: id,
|
|
74385
|
+
chartId: id,
|
|
72989
74386
|
};
|
|
72990
74387
|
}
|
|
72991
74388
|
function repeatCreateImageCommand(getters, cmd) {
|
|
@@ -76195,6 +77592,123 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76195
77592
|
}
|
|
76196
77593
|
}
|
|
76197
77594
|
|
|
77595
|
+
class CarouselUIPlugin extends UIPlugin {
|
|
77596
|
+
static getters = [
|
|
77597
|
+
"getSelectedCarouselItem",
|
|
77598
|
+
"getChartFromFigureId",
|
|
77599
|
+
"getChartIdFromFigureId",
|
|
77600
|
+
];
|
|
77601
|
+
uuidGenerator = new UuidGenerator();
|
|
77602
|
+
carouselStates = {};
|
|
77603
|
+
handle(cmd) {
|
|
77604
|
+
switch (cmd.type) {
|
|
77605
|
+
case "ADD_NEW_CHART_TO_CAROUSEL":
|
|
77606
|
+
this.addNewChartToCarousel(cmd.figureId, cmd.sheetId);
|
|
77607
|
+
break;
|
|
77608
|
+
case "ADD_FIGURE_CHART_TO_CAROUSEL":
|
|
77609
|
+
this.addFigureChartToCarousel(cmd.carouselFigureId, cmd.chartFigureId, cmd.sheetId);
|
|
77610
|
+
break;
|
|
77611
|
+
case "UPDATE_CAROUSEL_ACTIVE_ITEM":
|
|
77612
|
+
this.carouselStates[cmd.figureId] = cmd.item;
|
|
77613
|
+
break;
|
|
77614
|
+
case "DELETE_FIGURE":
|
|
77615
|
+
delete this.carouselStates[cmd.figureId];
|
|
77616
|
+
break;
|
|
77617
|
+
case "UPDATE_CAROUSEL":
|
|
77618
|
+
this.fixWrongCarouselState(cmd.figureId);
|
|
77619
|
+
break;
|
|
77620
|
+
case "DELETE_CHART":
|
|
77621
|
+
case "UNDO":
|
|
77622
|
+
case "REDO":
|
|
77623
|
+
case "DELETE_SHEET":
|
|
77624
|
+
for (const figureId in this.carouselStates) {
|
|
77625
|
+
this.fixWrongCarouselState(figureId);
|
|
77626
|
+
}
|
|
77627
|
+
break;
|
|
77628
|
+
}
|
|
77629
|
+
}
|
|
77630
|
+
getSelectedCarouselItem(figureId) {
|
|
77631
|
+
const carousel = this.getters.getCarousel(figureId);
|
|
77632
|
+
if (!carousel.items.length) {
|
|
77633
|
+
return undefined;
|
|
77634
|
+
}
|
|
77635
|
+
return this.carouselStates[figureId] ? this.carouselStates[figureId] : carousel.items[0];
|
|
77636
|
+
}
|
|
77637
|
+
getChartFromFigureId(figureId) {
|
|
77638
|
+
const sheetId = this.getters.getFigureSheetId(figureId);
|
|
77639
|
+
if (!sheetId) {
|
|
77640
|
+
return undefined;
|
|
77641
|
+
}
|
|
77642
|
+
const chartId = this.getChartIdFromFigureId(figureId);
|
|
77643
|
+
return chartId ? this.getters.getChart(chartId) : undefined;
|
|
77644
|
+
}
|
|
77645
|
+
getChartIdFromFigureId(figureId) {
|
|
77646
|
+
const sheetId = this.getters.getFigureSheetId(figureId);
|
|
77647
|
+
if (!sheetId) {
|
|
77648
|
+
return undefined;
|
|
77649
|
+
}
|
|
77650
|
+
const figure = this.getters.getFigure(sheetId, figureId);
|
|
77651
|
+
if (!figure || (figure.tag !== "chart" && figure.tag !== "carousel")) {
|
|
77652
|
+
return undefined;
|
|
77653
|
+
}
|
|
77654
|
+
if (figure.tag === "carousel") {
|
|
77655
|
+
const carouselItem = this.getSelectedCarouselItem(figureId);
|
|
77656
|
+
return carouselItem?.type === "chart" ? carouselItem.chartId : undefined;
|
|
77657
|
+
}
|
|
77658
|
+
return this.getters
|
|
77659
|
+
.getChartIds(sheetId)
|
|
77660
|
+
.find((chartId) => this.getters.getFigureIdFromChartId(chartId) === figureId);
|
|
77661
|
+
}
|
|
77662
|
+
fixWrongCarouselState(figureId) {
|
|
77663
|
+
if (!this.getters.doesCarouselExist(figureId)) {
|
|
77664
|
+
delete this.carouselStates[figureId];
|
|
77665
|
+
return;
|
|
77666
|
+
}
|
|
77667
|
+
const carousel = this.getters.getCarousel(figureId);
|
|
77668
|
+
if (!carousel) {
|
|
77669
|
+
delete this.carouselStates[figureId];
|
|
77670
|
+
return;
|
|
77671
|
+
}
|
|
77672
|
+
if (!this.carouselStates[figureId]) {
|
|
77673
|
+
this.carouselStates[figureId] = carousel.items[0];
|
|
77674
|
+
}
|
|
77675
|
+
else if (carousel.items.length === 0) {
|
|
77676
|
+
delete this.carouselStates[figureId];
|
|
77677
|
+
}
|
|
77678
|
+
else if (!carousel.items.some((item) => deepEquals(item, this.carouselStates[figureId]))) {
|
|
77679
|
+
this.carouselStates[figureId] = carousel.items[0];
|
|
77680
|
+
}
|
|
77681
|
+
}
|
|
77682
|
+
addNewChartToCarousel(figureId, sheetId) {
|
|
77683
|
+
const carousel = this.getters.getCarousel(figureId);
|
|
77684
|
+
const chartId = this.uuidGenerator.smallUuid();
|
|
77685
|
+
this.dispatch("CREATE_CHART", {
|
|
77686
|
+
chartId,
|
|
77687
|
+
figureId,
|
|
77688
|
+
sheetId,
|
|
77689
|
+
definition: CAROUSEL_DEFAULT_CHART_DEFINITION,
|
|
77690
|
+
});
|
|
77691
|
+
const definition = { items: [...carousel.items, { type: "chart", chartId }] };
|
|
77692
|
+
this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
|
|
77693
|
+
}
|
|
77694
|
+
addFigureChartToCarousel(figureId, chartFigureId, sheetId) {
|
|
77695
|
+
const chartId = this.getChartIdFromFigureId(chartFigureId);
|
|
77696
|
+
if (!chartId) {
|
|
77697
|
+
return;
|
|
77698
|
+
}
|
|
77699
|
+
const carousel = this.getters.getCarousel(figureId);
|
|
77700
|
+
const definition = { items: [...carousel.items, { type: "chart", chartId }] };
|
|
77701
|
+
this.dispatch("UPDATE_CAROUSEL", { sheetId, figureId, definition });
|
|
77702
|
+
this.dispatch("UPDATE_CHART", {
|
|
77703
|
+
sheetId,
|
|
77704
|
+
chartId,
|
|
77705
|
+
figureId,
|
|
77706
|
+
definition: this.getters.getChartDefinition(chartId),
|
|
77707
|
+
});
|
|
77708
|
+
this.dispatch("DELETE_FIGURE", { sheetId, figureId: chartFigureId });
|
|
77709
|
+
}
|
|
77710
|
+
}
|
|
77711
|
+
|
|
76198
77712
|
class HeaderPositionsUIPlugin extends UIPlugin {
|
|
76199
77713
|
static getters = ["getColDimensions", "getRowDimensions", "getColRowOffset"];
|
|
76200
77714
|
headerPositions = {};
|
|
@@ -76326,6 +77840,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76326
77840
|
.add("conditional formatting", ConditionalFormatPlugin)
|
|
76327
77841
|
.add("figures", FigurePlugin)
|
|
76328
77842
|
.add("chart", ChartPlugin)
|
|
77843
|
+
.add("carousel", CarouselPlugin)
|
|
76329
77844
|
.add("image", ImagePlugin)
|
|
76330
77845
|
.add("pivot_core", PivotCorePlugin)
|
|
76331
77846
|
.add("spreadsheet_pivot_core", SpreadsheetPivotCorePlugin)
|
|
@@ -76358,7 +77873,8 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
76358
77873
|
.add("table_computed_style", TableComputedStylePlugin)
|
|
76359
77874
|
.add("header_positions", HeaderPositionsUIPlugin)
|
|
76360
77875
|
.add("viewport", SheetViewPlugin)
|
|
76361
|
-
.add("clipboard", ClipboardPlugin)
|
|
77876
|
+
.add("clipboard", ClipboardPlugin)
|
|
77877
|
+
.add("carousel_ui", CarouselUIPlugin);
|
|
76362
77878
|
// Plugins which have a derived state from core data
|
|
76363
77879
|
const coreViewsPluginRegistry = new Registry()
|
|
76364
77880
|
.add("evaluation", EvaluationPlugin)
|
|
@@ -77311,6 +78827,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
77311
78827
|
.addChild("insert_chart", ["insert"], {
|
|
77312
78828
|
...insertChart,
|
|
77313
78829
|
sequence: 50,
|
|
78830
|
+
})
|
|
78831
|
+
.addChild("insert_carousel", ["insert"], {
|
|
78832
|
+
...insertCarousel,
|
|
78833
|
+
sequence: 51,
|
|
77314
78834
|
})
|
|
77315
78835
|
.addChild("insert_pivot", ["insert"], {
|
|
77316
78836
|
...insertPivot,
|
|
@@ -78481,9 +80001,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
78481
80001
|
}
|
|
78482
80002
|
if (!(xc in clickableCells[sheetId])) {
|
|
78483
80003
|
const clickableCell = this.findClickableItem(position);
|
|
78484
|
-
|
|
78485
|
-
clickableCells[sheetId][xc] = clickableCell;
|
|
78486
|
-
}
|
|
80004
|
+
clickableCells[sheetId][xc] = clickableCell;
|
|
78487
80005
|
}
|
|
78488
80006
|
return clickableCells[sheetId][xc];
|
|
78489
80007
|
}
|
|
@@ -80725,6 +82243,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
80725
82243
|
loadLocales: this.model.config.external.loadLocales,
|
|
80726
82244
|
isDashboard: () => this.model.getters.isDashboard(),
|
|
80727
82245
|
openSidePanel: this.sidePanel.open.bind(this.sidePanel),
|
|
82246
|
+
replaceSidePanel: this.sidePanel.replace.bind(this.sidePanel),
|
|
80728
82247
|
toggleSidePanel: this.sidePanel.toggle.bind(this.sidePanel),
|
|
80729
82248
|
clipboard: this.env.clipboard || instantiateClipboard(),
|
|
80730
82249
|
startCellEdition: (content) => this.composerFocusStore.focusActiveComposer({ content }),
|
|
@@ -83693,7 +85212,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83693
85212
|
];
|
|
83694
85213
|
}
|
|
83695
85214
|
|
|
83696
|
-
function createDrawing(drawingRelIds, sheet, figures) {
|
|
85215
|
+
function createDrawing(drawingRelIds, sheet, figures, construct) {
|
|
83697
85216
|
const namespaces = [
|
|
83698
85217
|
["xmlns:xdr", NAMESPACE.drawing],
|
|
83699
85218
|
["xmlns:r", RELATIONSHIP_NSR],
|
|
@@ -83704,7 +85223,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83704
85223
|
for (const [figureIndex, figure] of Object.entries(figures)) {
|
|
83705
85224
|
switch (figure?.tag) {
|
|
83706
85225
|
case "chart":
|
|
83707
|
-
figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex]));
|
|
85226
|
+
figuresNodes.push(createChartDrawing(figure, sheet, drawingRelIds[figureIndex], construct));
|
|
83708
85227
|
break;
|
|
83709
85228
|
case "image":
|
|
83710
85229
|
figuresNodes.push(createImageDrawing(figure, sheet, drawingRelIds[figureIndex]));
|
|
@@ -83766,10 +85285,10 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
83766
85285
|
offset: convertDotValueToEMU(offset - currentPosition + FIGURE_BORDER_WIDTH),
|
|
83767
85286
|
};
|
|
83768
85287
|
}
|
|
83769
|
-
function createChartDrawing(figure, sheet, chartRelId) {
|
|
85288
|
+
function createChartDrawing(figure, sheet, chartRelId, construct) {
|
|
83770
85289
|
// position
|
|
83771
85290
|
const { from, to } = convertFigureData(figure, sheet);
|
|
83772
|
-
const chartId = convertChartId(figure.id);
|
|
85291
|
+
const chartId = convertChartId(figure.id, construct);
|
|
83773
85292
|
const cNvPrAttrs = [
|
|
83774
85293
|
["id", chartId],
|
|
83775
85294
|
["name", `Chart ${chartId}`],
|
|
@@ -84432,7 +85951,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84432
85951
|
let drawingNode = escapeXml ``;
|
|
84433
85952
|
const drawingRelIds = [];
|
|
84434
85953
|
for (const chart of sheet.charts) {
|
|
84435
|
-
const xlsxChartId = convertChartId(chart.id);
|
|
85954
|
+
const xlsxChartId = convertChartId(chart.id, construct);
|
|
84436
85955
|
const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
|
|
84437
85956
|
target: `../charts/chart${xlsxChartId}.xml`,
|
|
84438
85957
|
type: XLSX_RELATION_TYPE.chart,
|
|
@@ -84466,7 +85985,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
84466
85985
|
target: `../drawings/drawing${sheetIndex}.xml`,
|
|
84467
85986
|
type: XLSX_RELATION_TYPE.drawing,
|
|
84468
85987
|
});
|
|
84469
|
-
files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
|
|
85988
|
+
files.push(createXMLFile(createDrawing(drawingRelIds, sheet, drawings, construct), `xl/drawings/drawing${sheetIndex}.xml`, "drawing"));
|
|
84470
85989
|
drawingNode = escapeXml /*xml*/ `<drawing r:id="${drawingRelId}" />`;
|
|
84471
85990
|
}
|
|
84472
85991
|
const sheetXml = escapeXml /*xml*/ `
|
|
@@ -85367,6 +86886,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
85367
86886
|
ChartPanel,
|
|
85368
86887
|
ChartFigure,
|
|
85369
86888
|
ChartJsComponent,
|
|
86889
|
+
ZoomableChartJsComponent,
|
|
85370
86890
|
Grid,
|
|
85371
86891
|
GridOverlay,
|
|
85372
86892
|
ScorecardChart,
|
|
@@ -85375,6 +86895,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
85375
86895
|
PieChartDesignPanel,
|
|
85376
86896
|
GenericChartConfigPanel,
|
|
85377
86897
|
ChartWithAxisDesignPanel,
|
|
86898
|
+
GenericZoomableChartDesignPanel,
|
|
85378
86899
|
LineChartDesignPanel,
|
|
85379
86900
|
GaugeChartConfigPanel,
|
|
85380
86901
|
GaugeChartDesignPanel,
|
|
@@ -85449,6 +86970,7 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
85449
86970
|
HIGHLIGHT_COLOR,
|
|
85450
86971
|
PIVOT_TABLE_CONFIG,
|
|
85451
86972
|
ChartTerms,
|
|
86973
|
+
FIGURE_ID_SPLITTER,
|
|
85452
86974
|
};
|
|
85453
86975
|
const chartHelpers = { ...CHART_HELPERS, ...CHART_RUNTIME_HELPERS };
|
|
85454
86976
|
|
|
@@ -85503,9 +87025,9 @@ stores.inject(MyMetaStore, storeInstance);
|
|
|
85503
87025
|
exports.tokenize = tokenize;
|
|
85504
87026
|
|
|
85505
87027
|
|
|
85506
|
-
__info__.version = "18.5.0-alpha.
|
|
85507
|
-
__info__.date = "2025-08-
|
|
85508
|
-
__info__.hash = "
|
|
87028
|
+
__info__.version = "18.5.0-alpha.8";
|
|
87029
|
+
__info__.date = "2025-08-18T08:17:58.775Z";
|
|
87030
|
+
__info__.hash = "994f1cb";
|
|
85509
87031
|
|
|
85510
87032
|
|
|
85511
87033
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|