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