@odoo/o-spreadsheet 16.4.0-alpha.1 → 16.4.0-alpha.3
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 +638 -466
- package/dist/o-spreadsheet.d.ts +57 -35
- package/dist/o-spreadsheet.esm.js +637 -467
- package/dist/o-spreadsheet.iife.js +638 -466
- package/dist/o-spreadsheet.iife.min.js +249 -245
- package/package.json +1 -1
|
@@ -2215,249 +2215,6 @@
|
|
|
2215
2215
|
return { sheetName, xc };
|
|
2216
2216
|
}
|
|
2217
2217
|
|
|
2218
|
-
class RangeImpl {
|
|
2219
|
-
getSheetSize;
|
|
2220
|
-
_zone;
|
|
2221
|
-
parts;
|
|
2222
|
-
invalidXc;
|
|
2223
|
-
prefixSheet = false;
|
|
2224
|
-
sheetId; // the sheet on which the range is defined
|
|
2225
|
-
invalidSheetName; // the name of any sheet that is invalid
|
|
2226
|
-
constructor(args, getSheetSize) {
|
|
2227
|
-
this.getSheetSize = getSheetSize;
|
|
2228
|
-
this._zone = args.zone;
|
|
2229
|
-
this.parts = args.parts;
|
|
2230
|
-
this.prefixSheet = args.prefixSheet;
|
|
2231
|
-
this.invalidXc = args.invalidXc;
|
|
2232
|
-
this.sheetId = args.sheetId;
|
|
2233
|
-
this.invalidSheetName = args.invalidSheetName;
|
|
2234
|
-
}
|
|
2235
|
-
static fromRange(range, getters) {
|
|
2236
|
-
if (range instanceof RangeImpl) {
|
|
2237
|
-
return range;
|
|
2238
|
-
}
|
|
2239
|
-
return new RangeImpl(range, getters.getSheetSize);
|
|
2240
|
-
}
|
|
2241
|
-
get unboundedZone() {
|
|
2242
|
-
return this._zone;
|
|
2243
|
-
}
|
|
2244
|
-
get zone() {
|
|
2245
|
-
const { left, top, bottom, right } = this._zone;
|
|
2246
|
-
if (right !== undefined && bottom !== undefined)
|
|
2247
|
-
return { left, top, right, bottom };
|
|
2248
|
-
else if (bottom === undefined && right !== undefined) {
|
|
2249
|
-
return { right, top, left, bottom: this.getSheetSize(this.sheetId).numberOfRows - 1 };
|
|
2250
|
-
}
|
|
2251
|
-
else if (right === undefined && bottom !== undefined) {
|
|
2252
|
-
return { bottom, left, top, right: this.getSheetSize(this.sheetId).numberOfCols - 1 };
|
|
2253
|
-
}
|
|
2254
|
-
throw new Error(_lt("Bad zone format"));
|
|
2255
|
-
}
|
|
2256
|
-
static getRangeParts(xc, zone) {
|
|
2257
|
-
const parts = xc.split(":").map((p) => {
|
|
2258
|
-
const isFullRow = isRowReference(p);
|
|
2259
|
-
return {
|
|
2260
|
-
colFixed: isFullRow ? false : p.startsWith("$"),
|
|
2261
|
-
rowFixed: isFullRow ? p.startsWith("$") : p.includes("$", 1),
|
|
2262
|
-
};
|
|
2263
|
-
});
|
|
2264
|
-
const isFullCol = zone.bottom === undefined;
|
|
2265
|
-
const isFullRow = zone.right === undefined;
|
|
2266
|
-
if (isFullCol) {
|
|
2267
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2268
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2269
|
-
if (zone.left === zone.right) {
|
|
2270
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2271
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
if (isFullRow) {
|
|
2275
|
-
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2276
|
-
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2277
|
-
if (zone.top === zone.bottom) {
|
|
2278
|
-
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2279
|
-
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2280
|
-
}
|
|
2281
|
-
}
|
|
2282
|
-
return parts;
|
|
2283
|
-
}
|
|
2284
|
-
get isFullCol() {
|
|
2285
|
-
return this._zone.bottom === undefined;
|
|
2286
|
-
}
|
|
2287
|
-
get isFullRow() {
|
|
2288
|
-
return this._zone.right === undefined;
|
|
2289
|
-
}
|
|
2290
|
-
get rangeData() {
|
|
2291
|
-
return {
|
|
2292
|
-
_zone: this._zone,
|
|
2293
|
-
_sheetId: this.sheetId,
|
|
2294
|
-
};
|
|
2295
|
-
}
|
|
2296
|
-
/**
|
|
2297
|
-
* Check that a zone is valid regarding the order of top-bottom and left-right.
|
|
2298
|
-
* Left should be smaller than right, top should be smaller than bottom.
|
|
2299
|
-
* If it's not the case, simply invert them, and invert the linked parts
|
|
2300
|
-
*/
|
|
2301
|
-
orderZone() {
|
|
2302
|
-
const zone = { ...this._zone };
|
|
2303
|
-
let parts = this.parts;
|
|
2304
|
-
if (zone.right !== undefined && zone.right < zone.left) {
|
|
2305
|
-
let right = zone.right;
|
|
2306
|
-
zone.right = zone.left;
|
|
2307
|
-
zone.left = right;
|
|
2308
|
-
parts = [
|
|
2309
|
-
{
|
|
2310
|
-
colFixed: parts[1]?.colFixed || false,
|
|
2311
|
-
rowFixed: parts[0]?.rowFixed || false,
|
|
2312
|
-
},
|
|
2313
|
-
{
|
|
2314
|
-
colFixed: parts[0]?.colFixed || false,
|
|
2315
|
-
rowFixed: parts[1]?.rowFixed || false,
|
|
2316
|
-
},
|
|
2317
|
-
];
|
|
2318
|
-
}
|
|
2319
|
-
if (zone.bottom !== undefined && zone.bottom < zone.top) {
|
|
2320
|
-
let bottom = zone.bottom;
|
|
2321
|
-
zone.bottom = zone.top;
|
|
2322
|
-
zone.top = bottom;
|
|
2323
|
-
parts = [
|
|
2324
|
-
{
|
|
2325
|
-
colFixed: parts[0]?.colFixed || false,
|
|
2326
|
-
rowFixed: parts[1]?.rowFixed || false,
|
|
2327
|
-
},
|
|
2328
|
-
{
|
|
2329
|
-
colFixed: parts[1]?.colFixed || false,
|
|
2330
|
-
rowFixed: parts[0]?.rowFixed || false,
|
|
2331
|
-
},
|
|
2332
|
-
];
|
|
2333
|
-
}
|
|
2334
|
-
return this.clone({ zone, parts });
|
|
2335
|
-
}
|
|
2336
|
-
/**
|
|
2337
|
-
*
|
|
2338
|
-
* @param rangeParams optional, values to put in the cloned range instead of the current values of the range
|
|
2339
|
-
*/
|
|
2340
|
-
clone(rangeParams) {
|
|
2341
|
-
return new RangeImpl({
|
|
2342
|
-
zone: rangeParams?.zone ? rangeParams.zone : { ...this._zone },
|
|
2343
|
-
sheetId: rangeParams?.sheetId ? rangeParams.sheetId : this.sheetId,
|
|
2344
|
-
invalidSheetName: rangeParams && "invalidSheetName" in rangeParams // 'attr in obj' instead of just 'obj.attr' because we accept undefined values
|
|
2345
|
-
? rangeParams.invalidSheetName
|
|
2346
|
-
: this.invalidSheetName,
|
|
2347
|
-
invalidXc: rangeParams && "invalidXc" in rangeParams ? rangeParams.invalidXc : this.invalidXc,
|
|
2348
|
-
parts: rangeParams?.parts
|
|
2349
|
-
? rangeParams.parts
|
|
2350
|
-
: this.parts.map((part) => {
|
|
2351
|
-
return { rowFixed: part.rowFixed, colFixed: part.colFixed };
|
|
2352
|
-
}),
|
|
2353
|
-
prefixSheet: rangeParams?.prefixSheet ? rangeParams.prefixSheet : this.prefixSheet,
|
|
2354
|
-
}, this.getSheetSize);
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
/**
|
|
2358
|
-
* Copy a range. If the range is on the sheetIdFrom, the range will target
|
|
2359
|
-
* sheetIdTo.
|
|
2360
|
-
*/
|
|
2361
|
-
function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
|
|
2362
|
-
const sheetId = range.sheetId === sheetIdFrom ? sheetIdTo : range.sheetId;
|
|
2363
|
-
return range.clone({ sheetId });
|
|
2364
|
-
}
|
|
2365
|
-
/**
|
|
2366
|
-
* Create a range from a xc. If the xc is empty, this function returns undefined.
|
|
2367
|
-
*/
|
|
2368
|
-
function createRange(getters, sheetId, range) {
|
|
2369
|
-
return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
|
|
2370
|
-
}
|
|
2371
|
-
|
|
2372
|
-
/** Methods from Odoo Web Utils */
|
|
2373
|
-
/**
|
|
2374
|
-
* This function computes a score that represent the fact that the
|
|
2375
|
-
* string contains the pattern, or not
|
|
2376
|
-
*
|
|
2377
|
-
* - If the score is 0, the string does not contain the letters of the pattern in
|
|
2378
|
-
* the correct order.
|
|
2379
|
-
* - if the score is > 0, it actually contains the letters.
|
|
2380
|
-
*
|
|
2381
|
-
* Better matches will get a higher score: consecutive letters are better,
|
|
2382
|
-
* and a match closer to the beginning of the string is also scored higher.
|
|
2383
|
-
*/
|
|
2384
|
-
function fuzzyMatch(pattern, str) {
|
|
2385
|
-
pattern = pattern.toLocaleLowerCase();
|
|
2386
|
-
str = str.toLocaleLowerCase();
|
|
2387
|
-
let totalScore = 0;
|
|
2388
|
-
let currentScore = 0;
|
|
2389
|
-
let len = str.length;
|
|
2390
|
-
let patternIndex = 0;
|
|
2391
|
-
for (let i = 0; i < len; i++) {
|
|
2392
|
-
if (str[i] === pattern[patternIndex]) {
|
|
2393
|
-
patternIndex++;
|
|
2394
|
-
currentScore += 100 + currentScore - i / 200;
|
|
2395
|
-
}
|
|
2396
|
-
else {
|
|
2397
|
-
currentScore = 0;
|
|
2398
|
-
}
|
|
2399
|
-
totalScore = totalScore + currentScore;
|
|
2400
|
-
}
|
|
2401
|
-
return patternIndex === pattern.length ? totalScore : 0;
|
|
2402
|
-
}
|
|
2403
|
-
/**
|
|
2404
|
-
* Return a list of things that matches a pattern, ordered by their 'score' (
|
|
2405
|
-
* higher score first). An higher score means that the match is better. For
|
|
2406
|
-
* example, consecutive letters are considered a better match.
|
|
2407
|
-
*/
|
|
2408
|
-
function fuzzyLookup(pattern, list, fn) {
|
|
2409
|
-
const results = [];
|
|
2410
|
-
list.forEach((data) => {
|
|
2411
|
-
const score = fuzzyMatch(pattern, fn(data));
|
|
2412
|
-
if (score > 0) {
|
|
2413
|
-
results.push({ score, elem: data });
|
|
2414
|
-
}
|
|
2415
|
-
});
|
|
2416
|
-
// we want better matches first
|
|
2417
|
-
results.sort((a, b) => b.score - a.score);
|
|
2418
|
-
return results.map((r) => r.elem);
|
|
2419
|
-
}
|
|
2420
|
-
|
|
2421
|
-
function createDefaultRows(rowNumber) {
|
|
2422
|
-
const rows = [];
|
|
2423
|
-
for (let i = 0; i < rowNumber; i++) {
|
|
2424
|
-
const row = {
|
|
2425
|
-
cells: {},
|
|
2426
|
-
};
|
|
2427
|
-
rows.push(row);
|
|
2428
|
-
}
|
|
2429
|
-
return rows;
|
|
2430
|
-
}
|
|
2431
|
-
|
|
2432
|
-
/*
|
|
2433
|
-
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
2434
|
-
* */
|
|
2435
|
-
class UuidGenerator {
|
|
2436
|
-
isFastIdStrategy = false;
|
|
2437
|
-
fastIdStart = 0;
|
|
2438
|
-
setIsFastStrategy(isFast) {
|
|
2439
|
-
this.isFastIdStrategy = isFast;
|
|
2440
|
-
}
|
|
2441
|
-
uuidv4() {
|
|
2442
|
-
if (this.isFastIdStrategy) {
|
|
2443
|
-
this.fastIdStart++;
|
|
2444
|
-
return String(this.fastIdStart);
|
|
2445
|
-
//@ts-ignore
|
|
2446
|
-
}
|
|
2447
|
-
else if (window.crypto && window.crypto.getRandomValues) {
|
|
2448
|
-
//@ts-ignore
|
|
2449
|
-
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
|
|
2450
|
-
}
|
|
2451
|
-
else {
|
|
2452
|
-
// mainly for jest and other browsers that do not have the crypto functionality
|
|
2453
|
-
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
2454
|
-
var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
2455
|
-
return v.toString(16);
|
|
2456
|
-
});
|
|
2457
|
-
}
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
2218
|
/**
|
|
2462
2219
|
* Convert from a cartesian reference to a Zone
|
|
2463
2220
|
* The range boundaries will be kept in the same order as the
|
|
@@ -3064,6 +2821,287 @@
|
|
|
3064
2821
|
return set;
|
|
3065
2822
|
}
|
|
3066
2823
|
|
|
2824
|
+
class RangeImpl {
|
|
2825
|
+
getSheetSize;
|
|
2826
|
+
_zone;
|
|
2827
|
+
parts;
|
|
2828
|
+
invalidXc;
|
|
2829
|
+
prefixSheet = false;
|
|
2830
|
+
sheetId; // the sheet on which the range is defined
|
|
2831
|
+
invalidSheetName; // the name of any sheet that is invalid
|
|
2832
|
+
constructor(args, getSheetSize) {
|
|
2833
|
+
this.getSheetSize = getSheetSize;
|
|
2834
|
+
this._zone = args.zone;
|
|
2835
|
+
this.parts = args.parts;
|
|
2836
|
+
this.prefixSheet = args.prefixSheet;
|
|
2837
|
+
this.invalidXc = args.invalidXc;
|
|
2838
|
+
this.sheetId = args.sheetId;
|
|
2839
|
+
this.invalidSheetName = args.invalidSheetName;
|
|
2840
|
+
}
|
|
2841
|
+
static fromRange(range, getters) {
|
|
2842
|
+
if (range instanceof RangeImpl) {
|
|
2843
|
+
return range;
|
|
2844
|
+
}
|
|
2845
|
+
return new RangeImpl(range, getters.getSheetSize);
|
|
2846
|
+
}
|
|
2847
|
+
get unboundedZone() {
|
|
2848
|
+
return this._zone;
|
|
2849
|
+
}
|
|
2850
|
+
get zone() {
|
|
2851
|
+
const { left, top, bottom, right } = this._zone;
|
|
2852
|
+
if (right !== undefined && bottom !== undefined)
|
|
2853
|
+
return { left, top, right, bottom };
|
|
2854
|
+
else if (bottom === undefined && right !== undefined) {
|
|
2855
|
+
return { right, top, left, bottom: this.getSheetSize(this.sheetId).numberOfRows - 1 };
|
|
2856
|
+
}
|
|
2857
|
+
else if (right === undefined && bottom !== undefined) {
|
|
2858
|
+
return { bottom, left, top, right: this.getSheetSize(this.sheetId).numberOfCols - 1 };
|
|
2859
|
+
}
|
|
2860
|
+
throw new Error(_lt("Bad zone format"));
|
|
2861
|
+
}
|
|
2862
|
+
static getRangeParts(xc, zone) {
|
|
2863
|
+
const parts = xc.split(":").map((p) => {
|
|
2864
|
+
const isFullRow = isRowReference(p);
|
|
2865
|
+
return {
|
|
2866
|
+
colFixed: isFullRow ? false : p.startsWith("$"),
|
|
2867
|
+
rowFixed: isFullRow ? p.startsWith("$") : p.includes("$", 1),
|
|
2868
|
+
};
|
|
2869
|
+
});
|
|
2870
|
+
const isFullCol = zone.bottom === undefined;
|
|
2871
|
+
const isFullRow = zone.right === undefined;
|
|
2872
|
+
if (isFullCol) {
|
|
2873
|
+
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2874
|
+
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2875
|
+
if (zone.left === zone.right) {
|
|
2876
|
+
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2877
|
+
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
if (isFullRow) {
|
|
2881
|
+
parts[0].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2882
|
+
parts[1].colFixed = parts[0].colFixed || parts[1].colFixed;
|
|
2883
|
+
if (zone.top === zone.bottom) {
|
|
2884
|
+
parts[0].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2885
|
+
parts[1].rowFixed = parts[0].rowFixed || parts[1].rowFixed;
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
return parts;
|
|
2889
|
+
}
|
|
2890
|
+
get isFullCol() {
|
|
2891
|
+
return this._zone.bottom === undefined;
|
|
2892
|
+
}
|
|
2893
|
+
get isFullRow() {
|
|
2894
|
+
return this._zone.right === undefined;
|
|
2895
|
+
}
|
|
2896
|
+
get rangeData() {
|
|
2897
|
+
return {
|
|
2898
|
+
_zone: this._zone,
|
|
2899
|
+
_sheetId: this.sheetId,
|
|
2900
|
+
};
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Check that a zone is valid regarding the order of top-bottom and left-right.
|
|
2904
|
+
* Left should be smaller than right, top should be smaller than bottom.
|
|
2905
|
+
* If it's not the case, simply invert them, and invert the linked parts
|
|
2906
|
+
*/
|
|
2907
|
+
orderZone() {
|
|
2908
|
+
const zone = { ...this._zone };
|
|
2909
|
+
let parts = this.parts;
|
|
2910
|
+
if (zone.right !== undefined && zone.right < zone.left) {
|
|
2911
|
+
let right = zone.right;
|
|
2912
|
+
zone.right = zone.left;
|
|
2913
|
+
zone.left = right;
|
|
2914
|
+
parts = [
|
|
2915
|
+
{
|
|
2916
|
+
colFixed: parts[1]?.colFixed || false,
|
|
2917
|
+
rowFixed: parts[0]?.rowFixed || false,
|
|
2918
|
+
},
|
|
2919
|
+
{
|
|
2920
|
+
colFixed: parts[0]?.colFixed || false,
|
|
2921
|
+
rowFixed: parts[1]?.rowFixed || false,
|
|
2922
|
+
},
|
|
2923
|
+
];
|
|
2924
|
+
}
|
|
2925
|
+
if (zone.bottom !== undefined && zone.bottom < zone.top) {
|
|
2926
|
+
let bottom = zone.bottom;
|
|
2927
|
+
zone.bottom = zone.top;
|
|
2928
|
+
zone.top = bottom;
|
|
2929
|
+
parts = [
|
|
2930
|
+
{
|
|
2931
|
+
colFixed: parts[0]?.colFixed || false,
|
|
2932
|
+
rowFixed: parts[1]?.rowFixed || false,
|
|
2933
|
+
},
|
|
2934
|
+
{
|
|
2935
|
+
colFixed: parts[1]?.colFixed || false,
|
|
2936
|
+
rowFixed: parts[0]?.rowFixed || false,
|
|
2937
|
+
},
|
|
2938
|
+
];
|
|
2939
|
+
}
|
|
2940
|
+
return this.clone({ zone, parts });
|
|
2941
|
+
}
|
|
2942
|
+
/**
|
|
2943
|
+
*
|
|
2944
|
+
* @param rangeParams optional, values to put in the cloned range instead of the current values of the range
|
|
2945
|
+
*/
|
|
2946
|
+
clone(rangeParams) {
|
|
2947
|
+
return new RangeImpl({
|
|
2948
|
+
zone: rangeParams?.zone ? rangeParams.zone : { ...this._zone },
|
|
2949
|
+
sheetId: rangeParams?.sheetId ? rangeParams.sheetId : this.sheetId,
|
|
2950
|
+
invalidSheetName: rangeParams && "invalidSheetName" in rangeParams // 'attr in obj' instead of just 'obj.attr' because we accept undefined values
|
|
2951
|
+
? rangeParams.invalidSheetName
|
|
2952
|
+
: this.invalidSheetName,
|
|
2953
|
+
invalidXc: rangeParams && "invalidXc" in rangeParams ? rangeParams.invalidXc : this.invalidXc,
|
|
2954
|
+
parts: rangeParams?.parts
|
|
2955
|
+
? rangeParams.parts
|
|
2956
|
+
: this.parts.map((part) => {
|
|
2957
|
+
return { rowFixed: part.rowFixed, colFixed: part.colFixed };
|
|
2958
|
+
}),
|
|
2959
|
+
prefixSheet: rangeParams?.prefixSheet ? rangeParams.prefixSheet : this.prefixSheet,
|
|
2960
|
+
}, this.getSheetSize);
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
/**
|
|
2964
|
+
* Copy a range. If the range is on the sheetIdFrom, the range will target
|
|
2965
|
+
* sheetIdTo.
|
|
2966
|
+
*/
|
|
2967
|
+
function copyRangeWithNewSheetId(sheetIdFrom, sheetIdTo, range) {
|
|
2968
|
+
const sheetId = range.sheetId === sheetIdFrom ? sheetIdTo : range.sheetId;
|
|
2969
|
+
return range.clone({ sheetId });
|
|
2970
|
+
}
|
|
2971
|
+
/**
|
|
2972
|
+
* Create a range from a xc. If the xc is empty, this function returns undefined.
|
|
2973
|
+
*/
|
|
2974
|
+
function createRange(getters, sheetId, range) {
|
|
2975
|
+
return range ? getters.getRangeFromSheetXC(sheetId, range) : undefined;
|
|
2976
|
+
}
|
|
2977
|
+
/**
|
|
2978
|
+
* Spread multiple colrows zone to one row/col zone and add a many new input range as needed.
|
|
2979
|
+
* For example, A1:B4 will become [A1:A4, B1:B4]
|
|
2980
|
+
*/
|
|
2981
|
+
function spreadRange(ranges) {
|
|
2982
|
+
const postProcessedRanges = [];
|
|
2983
|
+
for (const range of ranges) {
|
|
2984
|
+
const { sheetName } = splitReference(range);
|
|
2985
|
+
const sheetPrefix = sheetName ? `${sheetName}!` : "";
|
|
2986
|
+
const zone = toUnboundedZone(range);
|
|
2987
|
+
if (zone.bottom !== zone.top && zone.left != zone.right) {
|
|
2988
|
+
if (zone.right) {
|
|
2989
|
+
for (let j = zone.left; j <= zone.right; ++j) {
|
|
2990
|
+
postProcessedRanges.push(`${sheetPrefix}${zoneToXc({
|
|
2991
|
+
left: j,
|
|
2992
|
+
right: j,
|
|
2993
|
+
top: zone.top,
|
|
2994
|
+
bottom: zone.bottom,
|
|
2995
|
+
})}`);
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
else {
|
|
2999
|
+
for (let j = zone.top; j <= zone.bottom; ++j) {
|
|
3000
|
+
postProcessedRanges.push(`${sheetPrefix}${zoneToXc({
|
|
3001
|
+
left: zone.left,
|
|
3002
|
+
right: zone.right,
|
|
3003
|
+
top: j,
|
|
3004
|
+
bottom: j,
|
|
3005
|
+
})}`);
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
else {
|
|
3010
|
+
postProcessedRanges.push(range);
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
return postProcessedRanges;
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
/** Methods from Odoo Web Utils */
|
|
3017
|
+
/**
|
|
3018
|
+
* This function computes a score that represent the fact that the
|
|
3019
|
+
* string contains the pattern, or not
|
|
3020
|
+
*
|
|
3021
|
+
* - If the score is 0, the string does not contain the letters of the pattern in
|
|
3022
|
+
* the correct order.
|
|
3023
|
+
* - if the score is > 0, it actually contains the letters.
|
|
3024
|
+
*
|
|
3025
|
+
* Better matches will get a higher score: consecutive letters are better,
|
|
3026
|
+
* and a match closer to the beginning of the string is also scored higher.
|
|
3027
|
+
*/
|
|
3028
|
+
function fuzzyMatch(pattern, str) {
|
|
3029
|
+
pattern = pattern.toLocaleLowerCase();
|
|
3030
|
+
str = str.toLocaleLowerCase();
|
|
3031
|
+
let totalScore = 0;
|
|
3032
|
+
let currentScore = 0;
|
|
3033
|
+
let len = str.length;
|
|
3034
|
+
let patternIndex = 0;
|
|
3035
|
+
for (let i = 0; i < len; i++) {
|
|
3036
|
+
if (str[i] === pattern[patternIndex]) {
|
|
3037
|
+
patternIndex++;
|
|
3038
|
+
currentScore += 100 + currentScore - i / 200;
|
|
3039
|
+
}
|
|
3040
|
+
else {
|
|
3041
|
+
currentScore = 0;
|
|
3042
|
+
}
|
|
3043
|
+
totalScore = totalScore + currentScore;
|
|
3044
|
+
}
|
|
3045
|
+
return patternIndex === pattern.length ? totalScore : 0;
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Return a list of things that matches a pattern, ordered by their 'score' (
|
|
3049
|
+
* higher score first). An higher score means that the match is better. For
|
|
3050
|
+
* example, consecutive letters are considered a better match.
|
|
3051
|
+
*/
|
|
3052
|
+
function fuzzyLookup(pattern, list, fn) {
|
|
3053
|
+
const results = [];
|
|
3054
|
+
list.forEach((data) => {
|
|
3055
|
+
const score = fuzzyMatch(pattern, fn(data));
|
|
3056
|
+
if (score > 0) {
|
|
3057
|
+
results.push({ score, elem: data });
|
|
3058
|
+
}
|
|
3059
|
+
});
|
|
3060
|
+
// we want better matches first
|
|
3061
|
+
results.sort((a, b) => b.score - a.score);
|
|
3062
|
+
return results.map((r) => r.elem);
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
function createDefaultRows(rowNumber) {
|
|
3066
|
+
const rows = [];
|
|
3067
|
+
for (let i = 0; i < rowNumber; i++) {
|
|
3068
|
+
const row = {
|
|
3069
|
+
cells: {},
|
|
3070
|
+
};
|
|
3071
|
+
rows.push(row);
|
|
3072
|
+
}
|
|
3073
|
+
return rows;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
/*
|
|
3077
|
+
* https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
|
|
3078
|
+
* */
|
|
3079
|
+
class UuidGenerator {
|
|
3080
|
+
isFastIdStrategy = false;
|
|
3081
|
+
fastIdStart = 0;
|
|
3082
|
+
setIsFastStrategy(isFast) {
|
|
3083
|
+
this.isFastIdStrategy = isFast;
|
|
3084
|
+
}
|
|
3085
|
+
uuidv4() {
|
|
3086
|
+
if (this.isFastIdStrategy) {
|
|
3087
|
+
this.fastIdStart++;
|
|
3088
|
+
return String(this.fastIdStart);
|
|
3089
|
+
//@ts-ignore
|
|
3090
|
+
}
|
|
3091
|
+
else if (window.crypto && window.crypto.getRandomValues) {
|
|
3092
|
+
//@ts-ignore
|
|
3093
|
+
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) => (c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16));
|
|
3094
|
+
}
|
|
3095
|
+
else {
|
|
3096
|
+
// mainly for jest and other browsers that do not have the crypto functionality
|
|
3097
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
3098
|
+
var r = (Math.random() * 16) | 0, v = c == "x" ? r : (r & 0x3) | 0x8;
|
|
3099
|
+
return v.toString(16);
|
|
3100
|
+
});
|
|
3101
|
+
}
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3067
3105
|
class ChartJsComponent extends owl.Component {
|
|
3068
3106
|
static template = "o-spreadsheet-ChartJsComponent";
|
|
3069
3107
|
canvas = owl.useRef("graphContainer");
|
|
@@ -5181,14 +5219,6 @@
|
|
|
5181
5219
|
}
|
|
5182
5220
|
}
|
|
5183
5221
|
}
|
|
5184
|
-
function getElementScrollTop(el) {
|
|
5185
|
-
return el?.scrollTop || 0;
|
|
5186
|
-
}
|
|
5187
|
-
function setElementScrollTop(el, scroll) {
|
|
5188
|
-
if (!el)
|
|
5189
|
-
return;
|
|
5190
|
-
el.scrollTop = scroll;
|
|
5191
|
-
}
|
|
5192
5222
|
function getOpenedMenus() {
|
|
5193
5223
|
return Array.from(document.querySelectorAll(".o-spreadsheet .o-menu"));
|
|
5194
5224
|
}
|
|
@@ -17643,50 +17673,51 @@
|
|
|
17643
17673
|
css /* scss */ `
|
|
17644
17674
|
.o-selection {
|
|
17645
17675
|
.o-selection-input {
|
|
17646
|
-
|
|
17647
|
-
flex-direction: row;
|
|
17676
|
+
padding: 2px 0px;
|
|
17648
17677
|
|
|
17649
17678
|
input {
|
|
17650
17679
|
padding: 4px 6px;
|
|
17651
17680
|
border-radius: 4px;
|
|
17652
17681
|
box-sizing: border-box;
|
|
17653
|
-
flex-grow: 2;
|
|
17654
17682
|
}
|
|
17655
17683
|
input:focus {
|
|
17656
17684
|
outline: none;
|
|
17657
17685
|
}
|
|
17658
17686
|
input.o-required,
|
|
17659
17687
|
input.o-focused {
|
|
17660
|
-
border
|
|
17661
|
-
padding: 3px 5px;
|
|
17688
|
+
border: 1px solid;
|
|
17662
17689
|
}
|
|
17663
17690
|
input.o-focused {
|
|
17664
|
-
border-
|
|
17691
|
+
border-width: 2px;
|
|
17692
|
+
padding: 3px 5px;
|
|
17665
17693
|
}
|
|
17666
17694
|
input.o-invalid {
|
|
17667
|
-
|
|
17695
|
+
/* The background-color is similar to the bootstrap alert-danger class but, because of the commit 0358a76d,
|
|
17696
|
+
* which avoids being parasitized by the dark-mode in spreadsheet, we cannot use this class.
|
|
17697
|
+
* TODO: Replace with the bootstrap alert-danger class when we support dark mode
|
|
17698
|
+
*/
|
|
17699
|
+
background-color: #ffdddd;
|
|
17700
|
+
border-width: 2px;
|
|
17668
17701
|
}
|
|
17669
17702
|
button.o-btn {
|
|
17670
|
-
background: transparent;
|
|
17671
|
-
border: none;
|
|
17672
17703
|
color: #333;
|
|
17673
|
-
cursor: pointer;
|
|
17674
17704
|
}
|
|
17675
17705
|
button.o-btn-action {
|
|
17676
17706
|
margin: 8px 1px;
|
|
17677
17707
|
border-radius: 4px;
|
|
17678
|
-
background: transparent;
|
|
17679
17708
|
border: 1px solid #dadce0;
|
|
17680
17709
|
color: #188038;
|
|
17681
|
-
font-weight: bold;
|
|
17682
17710
|
font-size: 14px;
|
|
17683
17711
|
height: 25px;
|
|
17684
17712
|
}
|
|
17713
|
+
.error-icon {
|
|
17714
|
+
right: 7px;
|
|
17715
|
+
top: 7px;
|
|
17716
|
+
}
|
|
17685
17717
|
}
|
|
17686
17718
|
/** Make the character a bit bigger
|
|
17687
17719
|
compared to its neighbor INPUT box */
|
|
17688
17720
|
.o-remove-selection {
|
|
17689
|
-
font-weight: bold;
|
|
17690
17721
|
font-size: calc(100% + 4px);
|
|
17691
17722
|
}
|
|
17692
17723
|
}
|
|
@@ -17702,7 +17733,7 @@
|
|
|
17702
17733
|
class SelectionInput extends owl.Component {
|
|
17703
17734
|
static template = "o-spreadsheet-SelectionInput";
|
|
17704
17735
|
id = uuidGenerator$1.uuidv4();
|
|
17705
|
-
previousRanges = this.props.ranges || [];
|
|
17736
|
+
previousRanges = this.props.ranges() || [];
|
|
17706
17737
|
originSheet = this.env.model.getters.getActiveSheetId();
|
|
17707
17738
|
state = owl.useState({
|
|
17708
17739
|
isMissing: false,
|
|
@@ -17710,11 +17741,11 @@
|
|
|
17710
17741
|
});
|
|
17711
17742
|
focusedInput = owl.useRef("focusedInput");
|
|
17712
17743
|
get ranges() {
|
|
17713
|
-
const
|
|
17714
|
-
const ranges =
|
|
17715
|
-
?
|
|
17716
|
-
: this.props.ranges
|
|
17717
|
-
? this.props.ranges.map((xc, id) => ({
|
|
17744
|
+
const existingSelectionRanges = this.env.model.getters.getSelectionInput(this.id);
|
|
17745
|
+
const ranges = existingSelectionRanges.length
|
|
17746
|
+
? existingSelectionRanges
|
|
17747
|
+
: this.props.ranges()
|
|
17748
|
+
? this.props.ranges().map((xc, id) => ({
|
|
17718
17749
|
xc,
|
|
17719
17750
|
id,
|
|
17720
17751
|
isFocused: false,
|
|
@@ -17734,6 +17765,12 @@
|
|
|
17734
17765
|
get isInvalid() {
|
|
17735
17766
|
return this.props.isInvalid || this.state.isMissing;
|
|
17736
17767
|
}
|
|
17768
|
+
get isConfirmable() {
|
|
17769
|
+
return this.hasFocus && this.ranges.every((range) => range.isValidRange);
|
|
17770
|
+
}
|
|
17771
|
+
get isResettable() {
|
|
17772
|
+
return this.previousRanges.join() !== this.ranges.map((r) => r.xc).join();
|
|
17773
|
+
}
|
|
17737
17774
|
setup() {
|
|
17738
17775
|
owl.useEffect(() => this.focusedInput.el?.focus(), () => [this.focusedInput.el]);
|
|
17739
17776
|
owl.onMounted(() => this.enableNewSelectionInput());
|
|
@@ -17743,7 +17780,7 @@
|
|
|
17743
17780
|
enableNewSelectionInput() {
|
|
17744
17781
|
this.env.model.dispatch("ENABLE_NEW_SELECTION_INPUT", {
|
|
17745
17782
|
id: this.id,
|
|
17746
|
-
initialRanges: this.props.ranges,
|
|
17783
|
+
initialRanges: this.props.ranges(),
|
|
17747
17784
|
hasSingleRange: this.props.hasSingleRange,
|
|
17748
17785
|
});
|
|
17749
17786
|
}
|
|
@@ -17752,7 +17789,8 @@
|
|
|
17752
17789
|
}
|
|
17753
17790
|
checkChange() {
|
|
17754
17791
|
const value = this.env.model.getters.getSelectionInputValue(this.id);
|
|
17755
|
-
|
|
17792
|
+
const valid = !this.isInvalid && this.ranges.every((range) => range.isValidRange);
|
|
17793
|
+
if (valid && this.previousRanges.join() !== value.join()) {
|
|
17756
17794
|
this.triggerChange();
|
|
17757
17795
|
}
|
|
17758
17796
|
}
|
|
@@ -17763,7 +17801,6 @@
|
|
|
17763
17801
|
triggerChange() {
|
|
17764
17802
|
const ranges = this.env.model.getters.getSelectionInputValue(this.id);
|
|
17765
17803
|
this.props.onSelectionChanged?.(ranges);
|
|
17766
|
-
this.previousRanges = ranges;
|
|
17767
17804
|
}
|
|
17768
17805
|
onKeydown(ev) {
|
|
17769
17806
|
if (ev.key === "F2") {
|
|
@@ -17813,10 +17850,37 @@
|
|
|
17813
17850
|
});
|
|
17814
17851
|
this.triggerChange();
|
|
17815
17852
|
}
|
|
17853
|
+
reset() {
|
|
17854
|
+
const existingSelectionRanges = this.env.model.getters.getSelectionInput(this.id);
|
|
17855
|
+
for (const range of existingSelectionRanges) {
|
|
17856
|
+
this.env.model.dispatch("REMOVE_RANGE", {
|
|
17857
|
+
id: this.id,
|
|
17858
|
+
rangeId: range.id,
|
|
17859
|
+
});
|
|
17860
|
+
}
|
|
17861
|
+
for (const range of this.previousRanges) {
|
|
17862
|
+
this.env.model.dispatch("ADD_RANGE", { id: this.id, value: range });
|
|
17863
|
+
}
|
|
17864
|
+
this.confirm();
|
|
17865
|
+
}
|
|
17816
17866
|
confirm() {
|
|
17817
|
-
|
|
17818
|
-
const
|
|
17819
|
-
|
|
17867
|
+
let anyValidInput = false;
|
|
17868
|
+
const existingSelectionRanges = this.env.model.getters.getSelectionInput(this.id);
|
|
17869
|
+
const existingSelectionXcs = [];
|
|
17870
|
+
for (const range of existingSelectionRanges) {
|
|
17871
|
+
if (range.xc === "") {
|
|
17872
|
+
this.env.model.dispatch("REMOVE_RANGE", {
|
|
17873
|
+
id: this.id,
|
|
17874
|
+
rangeId: range.id,
|
|
17875
|
+
});
|
|
17876
|
+
continue;
|
|
17877
|
+
}
|
|
17878
|
+
existingSelectionXcs.push(range.xc);
|
|
17879
|
+
if (this.env.model.getters.isRangeValid(range.xc)) {
|
|
17880
|
+
anyValidInput = true;
|
|
17881
|
+
}
|
|
17882
|
+
}
|
|
17883
|
+
if (this.props.required && !anyValidInput) {
|
|
17820
17884
|
this.state.isMissing = true;
|
|
17821
17885
|
}
|
|
17822
17886
|
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
@@ -17826,11 +17890,17 @@
|
|
|
17826
17890
|
sheetIdTo: this.originSheet,
|
|
17827
17891
|
});
|
|
17828
17892
|
}
|
|
17893
|
+
this.props.onSelectionChanged?.(existingSelectionXcs);
|
|
17829
17894
|
this.props.onSelectionConfirmed?.();
|
|
17895
|
+
this.previousRanges = this.props.ranges();
|
|
17896
|
+
if (existingSelectionXcs.join() !== this.previousRanges.join()) {
|
|
17897
|
+
this.enableNewSelectionInput();
|
|
17898
|
+
}
|
|
17899
|
+
this.env.model.dispatch("UNFOCUS_SELECTION_INPUT");
|
|
17830
17900
|
}
|
|
17831
17901
|
}
|
|
17832
17902
|
SelectionInput.props = {
|
|
17833
|
-
ranges:
|
|
17903
|
+
ranges: Function,
|
|
17834
17904
|
hasSingleRange: { type: Boolean, optional: true },
|
|
17835
17905
|
required: { type: Boolean, optional: true },
|
|
17836
17906
|
isInvalid: { type: Boolean, optional: true },
|
|
@@ -17866,7 +17936,7 @@
|
|
|
17866
17936
|
return !!this.state.labelsDispatchResult?.isCancelledBecause(33 /* CommandResult.InvalidLabelRange */);
|
|
17867
17937
|
}
|
|
17868
17938
|
onUpdateDataSetsHaveTitle(ev) {
|
|
17869
|
-
this.props.updateChart({
|
|
17939
|
+
this.props.updateChart(this.props.figureId, {
|
|
17870
17940
|
dataSetsHaveTitle: ev.target.checked,
|
|
17871
17941
|
});
|
|
17872
17942
|
}
|
|
@@ -17878,10 +17948,14 @@
|
|
|
17878
17948
|
this.dataSeriesRanges = ranges;
|
|
17879
17949
|
}
|
|
17880
17950
|
onDataSeriesConfirmed() {
|
|
17881
|
-
this.
|
|
17951
|
+
this.dataSeriesRanges = spreadRange(this.dataSeriesRanges);
|
|
17952
|
+
this.state.datasetDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
17882
17953
|
dataSets: this.dataSeriesRanges,
|
|
17883
17954
|
});
|
|
17884
17955
|
}
|
|
17956
|
+
getDataSeriesRanges() {
|
|
17957
|
+
return this.dataSeriesRanges;
|
|
17958
|
+
}
|
|
17885
17959
|
/**
|
|
17886
17960
|
* Change the local labelRange. The model should be updated when the
|
|
17887
17961
|
* button "confirm" is clicked
|
|
@@ -17890,12 +17964,15 @@
|
|
|
17890
17964
|
this.labelRange = ranges[0];
|
|
17891
17965
|
}
|
|
17892
17966
|
onLabelRangeConfirmed() {
|
|
17893
|
-
this.state.labelsDispatchResult = this.props.updateChart({
|
|
17967
|
+
this.state.labelsDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
17894
17968
|
labelRange: this.labelRange,
|
|
17895
17969
|
});
|
|
17896
17970
|
}
|
|
17971
|
+
getLabelRange() {
|
|
17972
|
+
return this.labelRange || "";
|
|
17973
|
+
}
|
|
17897
17974
|
onUpdateAggregated(ev) {
|
|
17898
|
-
this.props.updateChart({
|
|
17975
|
+
this.props.updateChart(this.props.figureId, {
|
|
17899
17976
|
aggregated: ev.target.checked,
|
|
17900
17977
|
});
|
|
17901
17978
|
}
|
|
@@ -17925,12 +18002,12 @@
|
|
|
17925
18002
|
class BarConfigPanel extends LineBarPieConfigPanel {
|
|
17926
18003
|
static template = "o-spreadsheet-BarConfigPanel";
|
|
17927
18004
|
onUpdateStacked(ev) {
|
|
17928
|
-
this.props.updateChart({
|
|
18005
|
+
this.props.updateChart(this.props.figureId, {
|
|
17929
18006
|
stacked: ev.target.checked,
|
|
17930
18007
|
});
|
|
17931
18008
|
}
|
|
17932
18009
|
onUpdateAggregated(ev) {
|
|
17933
|
-
this.props.updateChart({
|
|
18010
|
+
this.props.updateChart(this.props.figureId, {
|
|
17934
18011
|
aggregated: ev.target.checked,
|
|
17935
18012
|
});
|
|
17936
18013
|
}
|
|
@@ -18267,17 +18344,17 @@
|
|
|
18267
18344
|
this.state.fillColorTool = !this.state.fillColorTool;
|
|
18268
18345
|
}
|
|
18269
18346
|
updateBackgroundColor(color) {
|
|
18270
|
-
this.props.updateChart({
|
|
18347
|
+
this.props.updateChart(this.props.figureId, {
|
|
18271
18348
|
background: color,
|
|
18272
18349
|
});
|
|
18273
18350
|
}
|
|
18274
18351
|
updateTitle(ev) {
|
|
18275
|
-
this.props.updateChart({
|
|
18352
|
+
this.props.updateChart(this.props.figureId, {
|
|
18276
18353
|
title: ev.target.value,
|
|
18277
18354
|
});
|
|
18278
18355
|
}
|
|
18279
18356
|
updateSelect(attr, ev) {
|
|
18280
|
-
this.props.updateChart({
|
|
18357
|
+
this.props.updateChart(this.props.figureId, {
|
|
18281
18358
|
[attr]: ev.target.value,
|
|
18282
18359
|
});
|
|
18283
18360
|
}
|
|
@@ -18310,10 +18387,13 @@
|
|
|
18310
18387
|
this.dataRange = ranges[0];
|
|
18311
18388
|
}
|
|
18312
18389
|
updateDataRange() {
|
|
18313
|
-
this.state.dataRangeDispatchResult = this.props.updateChart({
|
|
18390
|
+
this.state.dataRangeDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
18314
18391
|
dataRange: this.dataRange,
|
|
18315
18392
|
});
|
|
18316
18393
|
}
|
|
18394
|
+
getDataRange() {
|
|
18395
|
+
return this.dataRange || "";
|
|
18396
|
+
}
|
|
18317
18397
|
}
|
|
18318
18398
|
GaugeChartConfigPanel.props = {
|
|
18319
18399
|
figureId: String,
|
|
@@ -18368,12 +18448,12 @@
|
|
|
18368
18448
|
}
|
|
18369
18449
|
updateBackgroundColor(color) {
|
|
18370
18450
|
this.state.openedMenu = undefined;
|
|
18371
|
-
this.props.updateChart({
|
|
18451
|
+
this.props.updateChart(this.props.figureId, {
|
|
18372
18452
|
background: color,
|
|
18373
18453
|
});
|
|
18374
18454
|
}
|
|
18375
18455
|
updateTitle(ev) {
|
|
18376
|
-
this.props.updateChart({
|
|
18456
|
+
this.props.updateChart(this.props.figureId, {
|
|
18377
18457
|
title: ev.target.value,
|
|
18378
18458
|
});
|
|
18379
18459
|
}
|
|
@@ -18438,7 +18518,7 @@
|
|
|
18438
18518
|
}
|
|
18439
18519
|
}
|
|
18440
18520
|
updateSectionRule(sectionRule) {
|
|
18441
|
-
this.state.sectionRuleDispatchResult = this.props.updateChart({
|
|
18521
|
+
this.state.sectionRuleDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
18442
18522
|
sectionRule,
|
|
18443
18523
|
});
|
|
18444
18524
|
}
|
|
@@ -18462,17 +18542,17 @@
|
|
|
18462
18542
|
return false;
|
|
18463
18543
|
}
|
|
18464
18544
|
onUpdateLabelsAsText(ev) {
|
|
18465
|
-
this.props.updateChart({
|
|
18545
|
+
this.props.updateChart(this.props.figureId, {
|
|
18466
18546
|
labelsAsText: ev.target.checked,
|
|
18467
18547
|
});
|
|
18468
18548
|
}
|
|
18469
18549
|
onUpdateStacked(ev) {
|
|
18470
|
-
this.props.updateChart({
|
|
18550
|
+
this.props.updateChart(this.props.figureId, {
|
|
18471
18551
|
stacked: ev.target.checked,
|
|
18472
18552
|
});
|
|
18473
18553
|
}
|
|
18474
18554
|
onUpdateAggregated(ev) {
|
|
18475
|
-
this.props.updateChart({
|
|
18555
|
+
this.props.updateChart(this.props.figureId, {
|
|
18476
18556
|
aggregated: ev.target.checked,
|
|
18477
18557
|
});
|
|
18478
18558
|
}
|
|
@@ -18508,20 +18588,26 @@
|
|
|
18508
18588
|
this.keyValue = ranges[0];
|
|
18509
18589
|
}
|
|
18510
18590
|
updateKeyValueRange() {
|
|
18511
|
-
this.state.keyValueDispatchResult = this.props.updateChart({
|
|
18591
|
+
this.state.keyValueDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
18512
18592
|
keyValue: this.keyValue,
|
|
18513
18593
|
});
|
|
18514
18594
|
}
|
|
18595
|
+
getKeyValueRange() {
|
|
18596
|
+
return this.keyValue || "";
|
|
18597
|
+
}
|
|
18515
18598
|
onBaselineRangeChanged(ranges) {
|
|
18516
18599
|
this.baseline = ranges[0];
|
|
18517
18600
|
}
|
|
18518
18601
|
updateBaselineRange() {
|
|
18519
|
-
this.state.baselineDispatchResult = this.props.updateChart({
|
|
18602
|
+
this.state.baselineDispatchResult = this.props.updateChart(this.props.figureId, {
|
|
18520
18603
|
baseline: this.baseline,
|
|
18521
18604
|
});
|
|
18522
18605
|
}
|
|
18606
|
+
getBaselineRange() {
|
|
18607
|
+
return this.baseline || "";
|
|
18608
|
+
}
|
|
18523
18609
|
updateBaselineMode(ev) {
|
|
18524
|
-
this.props.updateChart({ baselineMode: ev.target.value });
|
|
18610
|
+
this.props.updateChart(this.props.figureId, { baselineMode: ev.target.value });
|
|
18525
18611
|
}
|
|
18526
18612
|
}
|
|
18527
18613
|
ScorecardChartConfigPanel.props = {
|
|
@@ -18540,12 +18626,12 @@
|
|
|
18540
18626
|
owl.useExternalListener(window, "click", this.closeMenus);
|
|
18541
18627
|
}
|
|
18542
18628
|
updateTitle(ev) {
|
|
18543
|
-
this.props.updateChart({
|
|
18629
|
+
this.props.updateChart(this.props.figureId, {
|
|
18544
18630
|
title: ev.target.value,
|
|
18545
18631
|
});
|
|
18546
18632
|
}
|
|
18547
18633
|
updateBaselineDescr(ev) {
|
|
18548
|
-
this.props.updateChart({ baselineDescr: ev.target.value });
|
|
18634
|
+
this.props.updateChart(this.props.figureId, { baselineDescr: ev.target.value });
|
|
18549
18635
|
}
|
|
18550
18636
|
toggleColorPicker(colorPickerId) {
|
|
18551
18637
|
if (this.state.openedColorPicker === colorPickerId) {
|
|
@@ -18558,13 +18644,13 @@
|
|
|
18558
18644
|
setColor(color, colorPickerId) {
|
|
18559
18645
|
switch (colorPickerId) {
|
|
18560
18646
|
case "backgroundColor":
|
|
18561
|
-
this.props.updateChart({ background: color });
|
|
18647
|
+
this.props.updateChart(this.props.figureId, { background: color });
|
|
18562
18648
|
break;
|
|
18563
18649
|
case "baselineColorDown":
|
|
18564
|
-
this.props.updateChart({ baselineColorDown: color });
|
|
18650
|
+
this.props.updateChart(this.props.figureId, { baselineColorDown: color });
|
|
18565
18651
|
break;
|
|
18566
18652
|
case "baselineColorUp":
|
|
18567
|
-
this.props.updateChart({ baselineColorUp: color });
|
|
18653
|
+
this.props.updateChart(this.props.figureId, { baselineColorUp: color });
|
|
18568
18654
|
break;
|
|
18569
18655
|
}
|
|
18570
18656
|
this.closeMenus();
|
|
@@ -18629,13 +18715,9 @@
|
|
|
18629
18715
|
class ChartPanel extends owl.Component {
|
|
18630
18716
|
static template = "o-spreadsheet-ChartPanel";
|
|
18631
18717
|
state;
|
|
18632
|
-
shouldUpdateChart = true;
|
|
18633
18718
|
get figureId() {
|
|
18634
18719
|
return this.state.figureId;
|
|
18635
18720
|
}
|
|
18636
|
-
get sheetId() {
|
|
18637
|
-
return this.state.sheetId;
|
|
18638
|
-
}
|
|
18639
18721
|
setup() {
|
|
18640
18722
|
const selectedFigureId = this.env.model.getters.getSelectedFigureId();
|
|
18641
18723
|
if (!selectedFigureId) {
|
|
@@ -18645,17 +18727,11 @@
|
|
|
18645
18727
|
this.state = owl.useState({
|
|
18646
18728
|
panel: "configuration",
|
|
18647
18729
|
figureId: selectedFigureId,
|
|
18648
|
-
sheetId: this.env.model.getters.getActiveSheetId(),
|
|
18649
18730
|
});
|
|
18650
18731
|
owl.onWillUpdateProps(() => {
|
|
18651
18732
|
const selectedFigureId = this.env.model.getters.getSelectedFigureId();
|
|
18652
18733
|
if (selectedFigureId && selectedFigureId !== this.state.figureId) {
|
|
18653
18734
|
this.state.figureId = selectedFigureId;
|
|
18654
|
-
this.state.sheetId = this.env.model.getters.getActiveSheetId();
|
|
18655
|
-
this.shouldUpdateChart = false;
|
|
18656
|
-
}
|
|
18657
|
-
else {
|
|
18658
|
-
this.shouldUpdateChart = true;
|
|
18659
18735
|
}
|
|
18660
18736
|
if (!this.env.model.getters.isChartDefined(this.figureId)) {
|
|
18661
18737
|
this.props.onCloseSidePanel();
|
|
@@ -18663,8 +18739,8 @@
|
|
|
18663
18739
|
}
|
|
18664
18740
|
});
|
|
18665
18741
|
}
|
|
18666
|
-
updateChart(updateDefinition) {
|
|
18667
|
-
if (
|
|
18742
|
+
updateChart(figureId, updateDefinition) {
|
|
18743
|
+
if (figureId !== this.figureId) {
|
|
18668
18744
|
return;
|
|
18669
18745
|
}
|
|
18670
18746
|
const definition = {
|
|
@@ -18673,8 +18749,8 @@
|
|
|
18673
18749
|
};
|
|
18674
18750
|
return this.env.model.dispatch("UPDATE_CHART", {
|
|
18675
18751
|
definition,
|
|
18676
|
-
id:
|
|
18677
|
-
sheetId: this.
|
|
18752
|
+
id: figureId,
|
|
18753
|
+
sheetId: this.env.model.getters.getFigureSheetId(figureId),
|
|
18678
18754
|
});
|
|
18679
18755
|
}
|
|
18680
18756
|
onTypeChange(type) {
|
|
@@ -18686,7 +18762,7 @@
|
|
|
18686
18762
|
this.env.model.dispatch("UPDATE_CHART", {
|
|
18687
18763
|
definition,
|
|
18688
18764
|
id: this.figureId,
|
|
18689
|
-
sheetId: this.
|
|
18765
|
+
sheetId: this.env.model.getters.getFigureSheetId(this.figureId),
|
|
18690
18766
|
});
|
|
18691
18767
|
}
|
|
18692
18768
|
get chartPanel() {
|
|
@@ -20482,12 +20558,23 @@
|
|
|
20482
20558
|
*/
|
|
20483
20559
|
selectRange(start, end) {
|
|
20484
20560
|
let selection = window.getSelection();
|
|
20485
|
-
this.
|
|
20486
|
-
|
|
20561
|
+
const { start: currentStart, end: currentEnd } = this.getCurrentSelection();
|
|
20562
|
+
if (currentStart === start && currentEnd === end) {
|
|
20563
|
+
return;
|
|
20564
|
+
}
|
|
20565
|
+
const currentRange = selection.getRangeAt(0);
|
|
20566
|
+
let range;
|
|
20567
|
+
if (this.el.contains(currentRange.startContainer)) {
|
|
20568
|
+
range = currentRange;
|
|
20569
|
+
}
|
|
20570
|
+
else {
|
|
20571
|
+
range = document.createRange();
|
|
20572
|
+
selection.removeAllRanges();
|
|
20573
|
+
selection.addRange(range);
|
|
20574
|
+
}
|
|
20487
20575
|
if (start == end && start === 0) {
|
|
20488
20576
|
range.setStart(this.el, 0);
|
|
20489
20577
|
range.setEnd(this.el, 0);
|
|
20490
|
-
selection.addRange(range);
|
|
20491
20578
|
}
|
|
20492
20579
|
else {
|
|
20493
20580
|
const textLength = this.getText().length;
|
|
@@ -20503,7 +20590,6 @@
|
|
|
20503
20590
|
let startNode = this.findChildAtCharacterIndex(start);
|
|
20504
20591
|
let endNode = this.findChildAtCharacterIndex(end);
|
|
20505
20592
|
range.setStart(startNode.node, startNode.offset);
|
|
20506
|
-
selection.addRange(range);
|
|
20507
20593
|
selection.extend(endNode.node, endNode.offset);
|
|
20508
20594
|
}
|
|
20509
20595
|
}
|
|
@@ -20543,26 +20629,54 @@
|
|
|
20543
20629
|
return { node: previous, offset: usedCharacters };
|
|
20544
20630
|
}
|
|
20545
20631
|
/**
|
|
20546
|
-
* Sets (or Replaces all) the text inside the root element in the form of distinctive
|
|
20632
|
+
* Sets (or Replaces all) the text inside the root element in the form of distinctive paragraphs and
|
|
20547
20633
|
* span for each element provided in `contents`.
|
|
20548
20634
|
*
|
|
20635
|
+
* The function will apply the diff between the current content and the new content to avoid the systematic
|
|
20636
|
+
* destruction of DOM elements which interferes with IME[1]
|
|
20637
|
+
*
|
|
20638
|
+
* Each line of text will be encapsulated in a paragraph element.
|
|
20549
20639
|
* Each span will have its own fontcolor and specific class if provided in the HtmlContent object.
|
|
20640
|
+
*
|
|
20641
|
+
* [1] https://developer.mozilla.org/en-US/docs/Glossary/Input_method_editor
|
|
20550
20642
|
*/
|
|
20551
20643
|
setText(contents) {
|
|
20552
|
-
this.el.innerHTML = "";
|
|
20553
20644
|
if (contents.length === 0) {
|
|
20645
|
+
this.removeAll();
|
|
20554
20646
|
return;
|
|
20555
20647
|
}
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
|
|
20560
|
-
|
|
20561
|
-
|
|
20562
|
-
|
|
20648
|
+
const childElements = Array.from(this.el.childNodes);
|
|
20649
|
+
const contentLength = contents.length;
|
|
20650
|
+
for (let i = 0; i < contentLength; i++) {
|
|
20651
|
+
const line = contents[i];
|
|
20652
|
+
const childElement = childElements[i];
|
|
20653
|
+
let newChild = false;
|
|
20654
|
+
let p;
|
|
20655
|
+
if (childElement && childElement.nodeName === "P") {
|
|
20656
|
+
p = childElement;
|
|
20563
20657
|
}
|
|
20564
|
-
|
|
20658
|
+
else {
|
|
20659
|
+
newChild = true;
|
|
20660
|
+
p = document.createElement("p");
|
|
20661
|
+
}
|
|
20662
|
+
const lineLength = line.length;
|
|
20663
|
+
const existingChildren = Array.from(p.childNodes);
|
|
20664
|
+
for (let j = 0; j < lineLength; j++) {
|
|
20665
|
+
const content = line[j];
|
|
20666
|
+
const child = existingChildren[j];
|
|
20667
|
+
// child nodes can be multiple types of nodes: Span, Text, Div, etc...
|
|
20668
|
+
// We can only modify a node in place if it has the same type as the content
|
|
20669
|
+
// that we would insert, which are spans.
|
|
20670
|
+
// Otherwise, it means that the node has been input by the user, through the keyboard or a copy/paste
|
|
20671
|
+
// @ts-ignore (somehow required because jest does not like child.tagName despite the prior check)
|
|
20672
|
+
const childIsSpan = child && "tagName" in child && child.tagName === "SPAN";
|
|
20673
|
+
if (childIsSpan && compareContentToSpanElement(content, child)) {
|
|
20674
|
+
continue;
|
|
20675
|
+
}
|
|
20676
|
+
// this is an empty line in the content
|
|
20565
20677
|
if (!content.value && !content.class) {
|
|
20678
|
+
if (child)
|
|
20679
|
+
p.removeChild(child);
|
|
20566
20680
|
continue;
|
|
20567
20681
|
}
|
|
20568
20682
|
const span = document.createElement("span");
|
|
@@ -20571,9 +20685,38 @@
|
|
|
20571
20685
|
if (content.class) {
|
|
20572
20686
|
span.classList.add(content.class);
|
|
20573
20687
|
}
|
|
20688
|
+
if (child) {
|
|
20689
|
+
p.replaceChild(span, child);
|
|
20690
|
+
}
|
|
20691
|
+
else {
|
|
20692
|
+
p.appendChild(span);
|
|
20693
|
+
}
|
|
20694
|
+
}
|
|
20695
|
+
if (existingChildren.length > lineLength) {
|
|
20696
|
+
for (let i = lineLength; i < existingChildren.length; i++) {
|
|
20697
|
+
p.removeChild(existingChildren[i]);
|
|
20698
|
+
}
|
|
20699
|
+
}
|
|
20700
|
+
// Empty line
|
|
20701
|
+
if (!p.hasChildNodes()) {
|
|
20702
|
+
const span = document.createElement("span");
|
|
20703
|
+
span.appendChild(document.createElement("br"));
|
|
20574
20704
|
p.appendChild(span);
|
|
20575
20705
|
}
|
|
20576
|
-
|
|
20706
|
+
// replace p if necessary
|
|
20707
|
+
if (newChild) {
|
|
20708
|
+
if (childElement) {
|
|
20709
|
+
this.el.replaceChild(p, childElement);
|
|
20710
|
+
}
|
|
20711
|
+
else {
|
|
20712
|
+
this.el.appendChild(p);
|
|
20713
|
+
}
|
|
20714
|
+
}
|
|
20715
|
+
}
|
|
20716
|
+
if (childElements.length > contentLength) {
|
|
20717
|
+
for (let i = contentLength; i < childElements.length; i++) {
|
|
20718
|
+
this.el.removeChild(childElements[i]);
|
|
20719
|
+
}
|
|
20577
20720
|
}
|
|
20578
20721
|
}
|
|
20579
20722
|
scrollSelectionIntoView() {
|
|
@@ -20583,13 +20726,6 @@
|
|
|
20583
20726
|
const element = focusedNode instanceof HTMLElement ? focusedNode : focusedNode.parentElement;
|
|
20584
20727
|
element?.scrollIntoView({ block: "nearest" });
|
|
20585
20728
|
}
|
|
20586
|
-
/**
|
|
20587
|
-
* remove the current selection of the user
|
|
20588
|
-
* */
|
|
20589
|
-
removeSelection() {
|
|
20590
|
-
let selection = window.getSelection();
|
|
20591
|
-
selection.removeAllRanges();
|
|
20592
|
-
}
|
|
20593
20729
|
removeAll() {
|
|
20594
20730
|
if (this.el) {
|
|
20595
20731
|
while (this.el.firstChild) {
|
|
@@ -20719,6 +20855,14 @@
|
|
|
20719
20855
|
}
|
|
20720
20856
|
return text;
|
|
20721
20857
|
}
|
|
20858
|
+
}
|
|
20859
|
+
function compareContentToSpanElement(content, node) {
|
|
20860
|
+
const contentColor = content.color ? toHex(content.color) : "";
|
|
20861
|
+
const nodeColor = node.style?.color ? toHex(node.style.color) : "";
|
|
20862
|
+
const sameColor = contentColor === nodeColor;
|
|
20863
|
+
const sameClass = deepEquals([content.class], [...node.classList]);
|
|
20864
|
+
const sameContent = node.innerText === content.value;
|
|
20865
|
+
return sameColor && sameClass && sameContent;
|
|
20722
20866
|
}
|
|
20723
20867
|
|
|
20724
20868
|
// -----------------------------------------------------------------------------
|
|
@@ -20864,7 +21008,6 @@
|
|
|
20864
21008
|
functionDescription: {},
|
|
20865
21009
|
argToFocus: 0,
|
|
20866
21010
|
});
|
|
20867
|
-
isKeyStillDown = false;
|
|
20868
21011
|
compositionActive = false;
|
|
20869
21012
|
get assistantStyle() {
|
|
20870
21013
|
if (this.props.delimitation && this.props.rect) {
|
|
@@ -20899,21 +21042,18 @@
|
|
|
20899
21042
|
F2: () => console.warn("Not implemented"),
|
|
20900
21043
|
F4: this.processF4Key,
|
|
20901
21044
|
Tab: (ev) => this.processTabKey(ev),
|
|
21045
|
+
" ": (ev) => this.processSpaceKey(ev),
|
|
20902
21046
|
};
|
|
20903
21047
|
setup() {
|
|
20904
21048
|
owl.onMounted(() => {
|
|
20905
21049
|
const el = this.composerRef.el;
|
|
20906
21050
|
this.contentHelper.updateEl(el);
|
|
20907
|
-
this.processContent();
|
|
20908
|
-
this.contentHelper.scrollSelectionIntoView();
|
|
20909
21051
|
});
|
|
20910
21052
|
owl.onWillUnmount(() => {
|
|
20911
21053
|
this.props.onComposerUnmounted?.();
|
|
20912
21054
|
});
|
|
20913
|
-
owl.
|
|
20914
|
-
|
|
20915
|
-
this.processContent();
|
|
20916
|
-
}
|
|
21055
|
+
owl.useEffect(() => {
|
|
21056
|
+
this.processContent();
|
|
20917
21057
|
});
|
|
20918
21058
|
}
|
|
20919
21059
|
// ---------------------------------------------------------------------------
|
|
@@ -20966,32 +21106,25 @@
|
|
|
20966
21106
|
return;
|
|
20967
21107
|
}
|
|
20968
21108
|
}
|
|
20969
|
-
else {
|
|
20970
|
-
// when completing with tab, if there is no value to complete, the active cell will be moved to the right.
|
|
20971
|
-
// we can't let the model think that it is for a ref selection.
|
|
20972
|
-
// todo: check if this can be removed someday
|
|
20973
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
20974
|
-
}
|
|
20975
21109
|
const direction = ev.shiftKey ? "left" : "right";
|
|
20976
21110
|
this.env.model.dispatch("STOP_EDITION");
|
|
20977
21111
|
this.env.model.selection.moveAnchorCell(direction, 1);
|
|
20978
21112
|
}
|
|
21113
|
+
processSpaceKey(ev) {
|
|
21114
|
+
if (ev.ctrlKey) {
|
|
21115
|
+
ev.preventDefault();
|
|
21116
|
+
ev.stopPropagation();
|
|
21117
|
+
this.showAutocomplete("");
|
|
21118
|
+
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
21119
|
+
}
|
|
21120
|
+
}
|
|
20979
21121
|
processEnterKey(ev) {
|
|
20980
21122
|
ev.preventDefault();
|
|
20981
21123
|
ev.stopPropagation();
|
|
20982
21124
|
if (ev.altKey || ev.ctrlKey) {
|
|
20983
|
-
|
|
20984
|
-
const currentContent = this.env.model.getters.getCurrentContent();
|
|
20985
|
-
const content = currentContent.slice(0, selection.start) + NEWLINE + currentContent.slice(selection.end);
|
|
20986
|
-
this.env.model.dispatch("SET_CURRENT_CONTENT", {
|
|
20987
|
-
content,
|
|
20988
|
-
selection: { start: selection.start + 1, end: selection.start + 1 },
|
|
20989
|
-
});
|
|
20990
|
-
this.processContent();
|
|
20991
|
-
this.contentHelper.scrollSelectionIntoView();
|
|
21125
|
+
this.composerRef.el?.dispatchEvent(new InputEvent("input", { inputType: "insertParagraph", bubbles: true, isComposing: false }));
|
|
20992
21126
|
return;
|
|
20993
21127
|
}
|
|
20994
|
-
this.isKeyStillDown = false;
|
|
20995
21128
|
if (this.autoCompleteState.showProvider) {
|
|
20996
21129
|
const autoCompleteValue = this.autoCompleteState.values[this.autoCompleteState.selectedIndex]?.text;
|
|
20997
21130
|
if (autoCompleteValue) {
|
|
@@ -21024,56 +21157,42 @@
|
|
|
21024
21157
|
else {
|
|
21025
21158
|
ev.stopPropagation();
|
|
21026
21159
|
}
|
|
21027
|
-
const { start, end } = this.contentHelper.getCurrentSelection();
|
|
21028
|
-
if (!this.env.model.getters.isSelectingForComposer() &&
|
|
21029
|
-
!(ev.key === "Enter" && (ev.altKey || ev.ctrlKey))) {
|
|
21030
|
-
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
|
|
21031
|
-
this.isKeyStillDown = true;
|
|
21032
|
-
}
|
|
21033
21160
|
}
|
|
21034
21161
|
/*
|
|
21035
21162
|
* Triggered automatically by the content-editable between the keydown and key up
|
|
21036
21163
|
* */
|
|
21037
|
-
onInput() {
|
|
21164
|
+
onInput(ev) {
|
|
21038
21165
|
if (this.props.focus === "inactive" || !this.shouldProcessInputEvents) {
|
|
21039
21166
|
return;
|
|
21040
21167
|
}
|
|
21168
|
+
let content = this.contentHelper.getText();
|
|
21169
|
+
let selection = this.contentHelper.getCurrentSelection();
|
|
21170
|
+
if (ev.inputType === "insertParagraph") {
|
|
21171
|
+
const start = Math.min(selection.start, selection.end);
|
|
21172
|
+
const end = Math.max(selection.start, selection.end);
|
|
21173
|
+
content = content.slice(0, start) + NEWLINE + content.slice(end);
|
|
21174
|
+
selection = { start: start + 1, end: start + 1 };
|
|
21175
|
+
}
|
|
21041
21176
|
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
21042
21177
|
this.env.model.dispatch("SET_CURRENT_CONTENT", {
|
|
21043
|
-
content
|
|
21044
|
-
selection
|
|
21178
|
+
content,
|
|
21179
|
+
selection,
|
|
21045
21180
|
});
|
|
21181
|
+
this.processTokenAtCursor();
|
|
21046
21182
|
}
|
|
21047
|
-
onKeyup(
|
|
21048
|
-
this.
|
|
21049
|
-
|
|
21050
|
-
|
|
21051
|
-
|
|
21052
|
-
|
|
21053
|
-
|
|
21054
|
-
return; // already processed in keydown
|
|
21055
|
-
}
|
|
21056
|
-
if (this.env.model.getters.isSelectingForComposer() &&
|
|
21057
|
-
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(ev.key)) {
|
|
21058
|
-
return; // already processed in keydown
|
|
21059
|
-
}
|
|
21060
|
-
ev.preventDefault();
|
|
21061
|
-
ev.stopPropagation();
|
|
21062
|
-
this.autoCompleteState.showProvider = false;
|
|
21063
|
-
if (ev.ctrlKey && ev.key === " ") {
|
|
21064
|
-
this.showAutocomplete("");
|
|
21065
|
-
this.env.model.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
21066
|
-
return;
|
|
21067
|
-
}
|
|
21068
|
-
const { start: oldStart, end: oldEnd } = this.env.model.getters.getComposerSelection();
|
|
21069
|
-
const { start, end } = this.contentHelper.getCurrentSelection();
|
|
21070
|
-
if (start !== oldStart || end !== oldEnd) {
|
|
21071
|
-
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", this.contentHelper.getCurrentSelection());
|
|
21183
|
+
onKeyup() {
|
|
21184
|
+
if (this.contentHelper.el === document.activeElement) {
|
|
21185
|
+
const { start: oldStart, end: oldEnd } = this.env.model.getters.getComposerSelection();
|
|
21186
|
+
const { start, end } = this.contentHelper.getCurrentSelection();
|
|
21187
|
+
if (start !== oldStart || end !== oldEnd) {
|
|
21188
|
+
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", { start, end });
|
|
21189
|
+
}
|
|
21072
21190
|
}
|
|
21073
|
-
this.processTokenAtCursor();
|
|
21074
|
-
this.processContent();
|
|
21075
21191
|
}
|
|
21076
21192
|
showAutocomplete(searchTerm) {
|
|
21193
|
+
if (!this.env.model.getters.getCurrentContent().startsWith("=")) {
|
|
21194
|
+
return;
|
|
21195
|
+
}
|
|
21077
21196
|
this.autoCompleteState.showProvider = true;
|
|
21078
21197
|
let values = Object.entries(functionRegistry.content)
|
|
21079
21198
|
.filter(([_, { hidden }]) => !hidden)
|
|
@@ -21093,13 +21212,6 @@
|
|
|
21093
21212
|
this.autoCompleteState.values = values.slice(0, 10);
|
|
21094
21213
|
this.autoCompleteState.selectedIndex = 0;
|
|
21095
21214
|
}
|
|
21096
|
-
onMousedown(ev) {
|
|
21097
|
-
if (ev.button > 0) {
|
|
21098
|
-
// not main button, probably a context menu
|
|
21099
|
-
return;
|
|
21100
|
-
}
|
|
21101
|
-
this.contentHelper.removeSelection();
|
|
21102
|
-
}
|
|
21103
21215
|
onClick() {
|
|
21104
21216
|
if (this.env.model.getters.isReadonly()) {
|
|
21105
21217
|
return;
|
|
@@ -21112,9 +21224,6 @@
|
|
|
21112
21224
|
this.env.model.dispatch("CHANGE_COMPOSER_CURSOR_SELECTION", newSelection);
|
|
21113
21225
|
this.processTokenAtCursor();
|
|
21114
21226
|
}
|
|
21115
|
-
onBlur() {
|
|
21116
|
-
this.isKeyStillDown = false;
|
|
21117
|
-
}
|
|
21118
21227
|
// ---------------------------------------------------------------------------
|
|
21119
21228
|
// Private
|
|
21120
21229
|
// ---------------------------------------------------------------------------
|
|
@@ -21122,22 +21231,19 @@
|
|
|
21122
21231
|
if (this.compositionActive) {
|
|
21123
21232
|
return;
|
|
21124
21233
|
}
|
|
21125
|
-
const oldScroll = getElementScrollTop(this.composerRef.el);
|
|
21126
|
-
this.contentHelper.removeAll(); // removes the content of the composer, to be added just after
|
|
21127
21234
|
this.shouldProcessInputEvents = false;
|
|
21128
21235
|
if (this.props.focus !== "inactive") {
|
|
21129
21236
|
this.contentHelper.el.focus();
|
|
21130
|
-
this.contentHelper.selectRange(0, 0); // move the cursor inside the composer at 0 0.
|
|
21131
21237
|
}
|
|
21132
21238
|
const content = this.getContentLines();
|
|
21239
|
+
this.contentHelper.setText(content);
|
|
21133
21240
|
if (content.length !== 0 && content.length[0] !== 0) {
|
|
21134
|
-
this.contentHelper.setText(content);
|
|
21135
|
-
const { start, end } = this.env.model.getters.getComposerSelection();
|
|
21136
21241
|
if (this.props.focus !== "inactive") {
|
|
21137
21242
|
// Put the cursor back where it was before the rendering
|
|
21243
|
+
const { start, end } = this.env.model.getters.getComposerSelection();
|
|
21138
21244
|
this.contentHelper.selectRange(start, end);
|
|
21139
21245
|
}
|
|
21140
|
-
|
|
21246
|
+
this.contentHelper.scrollSelectionIntoView();
|
|
21141
21247
|
}
|
|
21142
21248
|
this.shouldProcessInputEvents = true;
|
|
21143
21249
|
}
|
|
@@ -21392,8 +21498,8 @@
|
|
|
21392
21498
|
height: el.clientHeight,
|
|
21393
21499
|
};
|
|
21394
21500
|
this.composerState.delimitation = {
|
|
21395
|
-
width:
|
|
21396
|
-
height:
|
|
21501
|
+
width: this.props.gridDims.width,
|
|
21502
|
+
height: this.props.gridDims.height,
|
|
21397
21503
|
};
|
|
21398
21504
|
});
|
|
21399
21505
|
owl.onWillUpdateProps(() => {
|
|
@@ -23111,7 +23217,7 @@
|
|
|
23111
23217
|
shiftingMode: "none",
|
|
23112
23218
|
});
|
|
23113
23219
|
onResizeHighlight(isLeft, isTop) {
|
|
23114
|
-
const
|
|
23220
|
+
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
23115
23221
|
this.highlightState.shiftingMode = "isResizing";
|
|
23116
23222
|
const z = this.props.zone;
|
|
23117
23223
|
const pivotCol = isLeft ? z.right : z.left;
|
|
@@ -23120,11 +23226,10 @@
|
|
|
23120
23226
|
let lastRow = isTop ? z.top : z.bottom;
|
|
23121
23227
|
let currentZone = z;
|
|
23122
23228
|
this.env.model.dispatch("START_CHANGE_HIGHLIGHT", {
|
|
23123
|
-
range: this.env.model.getters.getRangeDataFromZone(
|
|
23229
|
+
range: this.env.model.getters.getRangeDataFromZone(activeSheetId, currentZone),
|
|
23124
23230
|
});
|
|
23125
23231
|
const mouseMove = (col, row) => {
|
|
23126
23232
|
if (lastCol !== col || lastRow !== row) {
|
|
23127
|
-
const activeSheetId = this.env.model.getters.getActiveSheetId();
|
|
23128
23233
|
lastCol = clip(col === -1 ? lastCol : col, 0, this.env.model.getters.getNumberCols(activeSheetId) - 1);
|
|
23129
23234
|
lastRow = clip(row === -1 ? lastRow : row, 0, this.env.model.getters.getNumberRows(activeSheetId) - 1);
|
|
23130
23235
|
let newZone = {
|
|
@@ -23136,7 +23241,7 @@
|
|
|
23136
23241
|
newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
|
|
23137
23242
|
if (!isEqual(newZone, currentZone)) {
|
|
23138
23243
|
this.env.model.dispatch("CHANGE_HIGHLIGHT", {
|
|
23139
|
-
range: this.env.model.getters.
|
|
23244
|
+
range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
|
|
23140
23245
|
});
|
|
23141
23246
|
currentZone = newZone;
|
|
23142
23247
|
}
|
|
@@ -23183,7 +23288,7 @@
|
|
|
23183
23288
|
newZone = this.env.model.getters.expandZone(activeSheetId, newZone);
|
|
23184
23289
|
if (!isEqual(newZone, currentZone)) {
|
|
23185
23290
|
this.env.model.dispatch("CHANGE_HIGHLIGHT", {
|
|
23186
|
-
range: this.env.model.getters.
|
|
23291
|
+
range: this.env.model.getters.getRangeFromZone(activeSheetId, this.env.model.getters.getUnboundedZone(activeSheetId, newZone)).rangeData,
|
|
23187
23292
|
});
|
|
23188
23293
|
currentZone = newZone;
|
|
23189
23294
|
}
|
|
@@ -24505,6 +24610,16 @@
|
|
|
24505
24610
|
63: "333333",
|
|
24506
24611
|
64: "000000",
|
|
24507
24612
|
65: "FFFFFF", // system background
|
|
24613
|
+
};
|
|
24614
|
+
const IMAGE_MIMETYPE_EXTENSION_MAPPING = {
|
|
24615
|
+
"image/avif": "avif",
|
|
24616
|
+
"image/bmp": "bmp",
|
|
24617
|
+
"image/gif": "gif",
|
|
24618
|
+
"image/vnd.microsoft.icon": "ico",
|
|
24619
|
+
"image/jpeg": "jpeg",
|
|
24620
|
+
"image/png": "png",
|
|
24621
|
+
"image/tiff": "tiff",
|
|
24622
|
+
"image/webp": "webp",
|
|
24508
24623
|
};
|
|
24509
24624
|
|
|
24510
24625
|
/**
|
|
@@ -26987,6 +27102,11 @@
|
|
|
26987
27102
|
<Override ContentType="${contentType}" PartName="${partName}" />
|
|
26988
27103
|
`;
|
|
26989
27104
|
}
|
|
27105
|
+
function createDefaultXMLElement(extension, contentType) {
|
|
27106
|
+
return escapeXml /*xml*/ `
|
|
27107
|
+
<Default Extension="${extension}" ContentType="${contentType}" />
|
|
27108
|
+
`;
|
|
27109
|
+
}
|
|
26990
27110
|
function joinXmlNodes(xmlNodes) {
|
|
26991
27111
|
return new XMLString(xmlNodes.join("\n"));
|
|
26992
27112
|
}
|
|
@@ -28852,11 +28972,9 @@
|
|
|
28852
28972
|
*/
|
|
28853
28973
|
class CorePlugin extends BasePlugin {
|
|
28854
28974
|
getters;
|
|
28855
|
-
range;
|
|
28856
28975
|
uuidGenerator;
|
|
28857
28976
|
constructor({ getters, stateObserver, range, dispatch, uuidGenerator }) {
|
|
28858
28977
|
super(stateObserver, dispatch);
|
|
28859
|
-
this.range = range;
|
|
28860
28978
|
range.addRangeProvider(this.adaptRanges.bind(this));
|
|
28861
28979
|
this.getters = getters;
|
|
28862
28980
|
this.uuidGenerator = uuidGenerator;
|
|
@@ -31430,6 +31548,7 @@
|
|
|
31430
31548
|
"getMerge",
|
|
31431
31549
|
"getMergesInZone",
|
|
31432
31550
|
"isSingleCellOrMerge",
|
|
31551
|
+
"getSelectionRangeString",
|
|
31433
31552
|
];
|
|
31434
31553
|
nextId = 1;
|
|
31435
31554
|
merges = {};
|
|
@@ -31517,6 +31636,26 @@
|
|
|
31517
31636
|
.map((mergeId) => this.getMergeById(sheetId, mergeId))
|
|
31518
31637
|
.filter(isDefined$1);
|
|
31519
31638
|
}
|
|
31639
|
+
/**
|
|
31640
|
+
* Same as `getRangeString` but add all necessary merge to the range to make it a valid selection
|
|
31641
|
+
*/
|
|
31642
|
+
getSelectionRangeString(range, forSheetId) {
|
|
31643
|
+
const rangeImpl = RangeImpl.fromRange(range, this.getters);
|
|
31644
|
+
const expandedZone = this.getters.expandZone(rangeImpl.sheetId, rangeImpl.zone);
|
|
31645
|
+
const expandedRange = rangeImpl.clone({
|
|
31646
|
+
zone: {
|
|
31647
|
+
...expandedZone,
|
|
31648
|
+
bottom: rangeImpl.isFullCol ? undefined : expandedZone.bottom,
|
|
31649
|
+
right: rangeImpl.isFullRow ? undefined : expandedZone.right,
|
|
31650
|
+
},
|
|
31651
|
+
});
|
|
31652
|
+
const rangeString = this.getters.getRangeString(expandedRange, forSheetId);
|
|
31653
|
+
if (this.isSingleCellOrMerge(rangeImpl.sheetId, rangeImpl.zone)) {
|
|
31654
|
+
const { sheetName, xc } = splitReference(rangeString);
|
|
31655
|
+
return `${sheetName !== undefined ? getCanonicalSheetName(sheetName) + "!" : ""}${xc.split(":")[0]}`;
|
|
31656
|
+
}
|
|
31657
|
+
return rangeString;
|
|
31658
|
+
}
|
|
31520
31659
|
/**
|
|
31521
31660
|
* Return true if the zone intersects an existing merge:
|
|
31522
31661
|
* if they have at least a common cell
|
|
@@ -31849,12 +31988,12 @@
|
|
|
31849
31988
|
}
|
|
31850
31989
|
static getters = [
|
|
31851
31990
|
"getRangeString",
|
|
31852
|
-
"getSelectionRangeString",
|
|
31853
31991
|
"getRangeFromSheetXC",
|
|
31854
31992
|
"createAdaptedRanges",
|
|
31855
31993
|
"getRangeDataFromXc",
|
|
31856
31994
|
"getRangeDataFromZone",
|
|
31857
31995
|
"getRangeFromRangeData",
|
|
31996
|
+
"getRangeFromZone",
|
|
31858
31997
|
];
|
|
31859
31998
|
// ---------------------------------------------------------------------------
|
|
31860
31999
|
// Command Handling
|
|
@@ -32103,21 +32242,6 @@
|
|
|
32103
32242
|
const rangeInterface = { prefixSheet, zone, sheetId, invalidSheetName, parts };
|
|
32104
32243
|
return new RangeImpl(rangeInterface, this.getters.getSheetSize).orderZone();
|
|
32105
32244
|
}
|
|
32106
|
-
/**
|
|
32107
|
-
* Same as `getRangeString` but add all necessary merge to the range to make it a valid selection
|
|
32108
|
-
*/
|
|
32109
|
-
getSelectionRangeString(range, forSheetId) {
|
|
32110
|
-
const rangeImpl = RangeImpl.fromRange(range, this.getters);
|
|
32111
|
-
const expandedZone = this.getters.expandZone(rangeImpl.sheetId, rangeImpl.zone);
|
|
32112
|
-
const expandedRange = rangeImpl.clone({
|
|
32113
|
-
zone: {
|
|
32114
|
-
...expandedZone,
|
|
32115
|
-
bottom: rangeImpl.isFullCol ? undefined : expandedZone.bottom,
|
|
32116
|
-
right: rangeImpl.isFullRow ? undefined : expandedZone.right,
|
|
32117
|
-
},
|
|
32118
|
-
});
|
|
32119
|
-
return this.getRangeString(expandedRange, forSheetId);
|
|
32120
|
-
}
|
|
32121
32245
|
/**
|
|
32122
32246
|
* Gets the string that represents the range as it is at the moment of the call.
|
|
32123
32247
|
* The string will be prefixed with the sheet name if the call specified a sheet id in `forSheetId`
|
|
@@ -32174,6 +32298,17 @@
|
|
|
32174
32298
|
getRangeDataFromZone(sheetId, zone) {
|
|
32175
32299
|
return { _sheetId: sheetId, _zone: zone };
|
|
32176
32300
|
}
|
|
32301
|
+
getRangeFromZone(sheetId, zone) {
|
|
32302
|
+
return new RangeImpl({
|
|
32303
|
+
sheetId,
|
|
32304
|
+
zone,
|
|
32305
|
+
parts: [
|
|
32306
|
+
{ colFixed: false, rowFixed: false },
|
|
32307
|
+
{ colFixed: false, rowFixed: false },
|
|
32308
|
+
],
|
|
32309
|
+
prefixSheet: false,
|
|
32310
|
+
}, this.getters.getSheetSize);
|
|
32311
|
+
}
|
|
32177
32312
|
getRangeFromRangeData(data) {
|
|
32178
32313
|
const rangeInterface = {
|
|
32179
32314
|
prefixSheet: false,
|
|
@@ -32259,6 +32394,7 @@
|
|
|
32259
32394
|
"getPaneDivisions",
|
|
32260
32395
|
"checkZonesExistInSheet",
|
|
32261
32396
|
"getCommandZones",
|
|
32397
|
+
"getUnboundedZone",
|
|
32262
32398
|
];
|
|
32263
32399
|
sheetIdsMapName = {};
|
|
32264
32400
|
orderedSheetIds = [];
|
|
@@ -32584,6 +32720,16 @@
|
|
|
32584
32720
|
right: this.getNumberCols(sheetId) - 1,
|
|
32585
32721
|
};
|
|
32586
32722
|
}
|
|
32723
|
+
getUnboundedZone(sheetId, zone) {
|
|
32724
|
+
const isFullRow = zone.left === 0 && zone.right === this.getNumberCols(sheetId) - 1;
|
|
32725
|
+
const isFullCol = zone.top === 0 && zone.bottom === this.getNumberRows(sheetId) - 1;
|
|
32726
|
+
return {
|
|
32727
|
+
...zone,
|
|
32728
|
+
bottom: isFullCol ? undefined : zone.bottom,
|
|
32729
|
+
// cannot be unbounded in the 2 dimensions at once
|
|
32730
|
+
right: isFullRow && !isFullCol ? undefined : zone.right,
|
|
32731
|
+
};
|
|
32732
|
+
}
|
|
32587
32733
|
getPaneDivisions(sheetId) {
|
|
32588
32734
|
return this.getSheet(sheetId).panes;
|
|
32589
32735
|
}
|
|
@@ -38619,6 +38765,7 @@
|
|
|
38619
38765
|
// ---------------------------------------------------------------------------
|
|
38620
38766
|
allowDispatch(cmd) {
|
|
38621
38767
|
switch (cmd.type) {
|
|
38768
|
+
case "ADD_RANGE":
|
|
38622
38769
|
case "ADD_EMPTY_RANGE":
|
|
38623
38770
|
if (this.inputHasSingleRange && this.ranges.length === 1) {
|
|
38624
38771
|
return 30 /* CommandResult.MaximumRangesReached */;
|
|
@@ -38633,11 +38780,11 @@
|
|
|
38633
38780
|
return 0 /* CommandResult.Success */;
|
|
38634
38781
|
}
|
|
38635
38782
|
handleEvent(event) {
|
|
38636
|
-
const xc = zoneToXc(event.anchor.zone);
|
|
38637
38783
|
const inputSheetId = this.activeSheet;
|
|
38638
38784
|
const sheetId = this.getters.getActiveSheetId();
|
|
38639
|
-
const
|
|
38640
|
-
this.
|
|
38785
|
+
const zone = event.anchor.zone;
|
|
38786
|
+
const range = this.getters.getRangeFromZone(sheetId, event.type === "HeadersSelected" ? this.getters.getUnboundedZone(sheetId, zone) : zone);
|
|
38787
|
+
this.add([this.getters.getSelectionRangeString(range, inputSheetId)]);
|
|
38641
38788
|
}
|
|
38642
38789
|
handle(cmd) {
|
|
38643
38790
|
switch (cmd.type) {
|
|
@@ -38663,6 +38810,10 @@
|
|
|
38663
38810
|
this.insertNewRange(this.ranges.length, [""]);
|
|
38664
38811
|
this.focusLast();
|
|
38665
38812
|
break;
|
|
38813
|
+
case "ADD_RANGE":
|
|
38814
|
+
this.insertNewRange(this.ranges.length, [cmd.value]);
|
|
38815
|
+
this.focusLast();
|
|
38816
|
+
break;
|
|
38666
38817
|
case "REMOVE_RANGE":
|
|
38667
38818
|
const index = this.getIndex(cmd.rangeId);
|
|
38668
38819
|
if (index !== null) {
|
|
@@ -38874,6 +39025,7 @@
|
|
|
38874
39025
|
case "UNFOCUS_SELECTION_INPUT":
|
|
38875
39026
|
this.unfocus();
|
|
38876
39027
|
break;
|
|
39028
|
+
case "ADD_RANGE":
|
|
38877
39029
|
case "ADD_EMPTY_RANGE":
|
|
38878
39030
|
case "REMOVE_RANGE":
|
|
38879
39031
|
if (cmd.id !== this.focusedInputId) {
|
|
@@ -38887,9 +39039,11 @@
|
|
|
38887
39039
|
if (cmd.id !== this.focusedInputId) {
|
|
38888
39040
|
const input = this.inputs[cmd.id];
|
|
38889
39041
|
const range = input.ranges.find((range) => range.id === cmd.rangeId);
|
|
38890
|
-
|
|
38891
|
-
|
|
38892
|
-
|
|
39042
|
+
if (this.isRangeValid(range?.xc || "A1")) {
|
|
39043
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
39044
|
+
const zone = this.getters.getRangeFromSheetXC(sheetId, range?.xc || "A1").zone;
|
|
39045
|
+
this.selection.capture(input, { cell: { col: zone.left, row: zone.top }, zone }, { handleEvent: input.handleEvent.bind(input) });
|
|
39046
|
+
}
|
|
38893
39047
|
this.focusedInputId = cmd.id;
|
|
38894
39048
|
}
|
|
38895
39049
|
break;
|
|
@@ -41088,12 +41242,20 @@
|
|
|
41088
41242
|
if (this.mode !== "selecting") {
|
|
41089
41243
|
return;
|
|
41090
41244
|
}
|
|
41245
|
+
const sheetId = this.getters.getActiveSheetId();
|
|
41246
|
+
let unboundedZone;
|
|
41247
|
+
if (event.type === "HeadersSelected") {
|
|
41248
|
+
unboundedZone = this.getters.getUnboundedZone(sheetId, event.anchor.zone);
|
|
41249
|
+
}
|
|
41250
|
+
else {
|
|
41251
|
+
unboundedZone = event.anchor.zone;
|
|
41252
|
+
}
|
|
41091
41253
|
switch (event.mode) {
|
|
41092
41254
|
case "newAnchor":
|
|
41093
|
-
this.insertSelectedRange(
|
|
41255
|
+
this.insertSelectedRange(unboundedZone);
|
|
41094
41256
|
break;
|
|
41095
41257
|
default:
|
|
41096
|
-
this.replaceSelectedRanges(
|
|
41258
|
+
this.replaceSelectedRanges(unboundedZone);
|
|
41097
41259
|
break;
|
|
41098
41260
|
}
|
|
41099
41261
|
}
|
|
@@ -41150,7 +41312,9 @@
|
|
|
41150
41312
|
}
|
|
41151
41313
|
break;
|
|
41152
41314
|
case "START_CHANGE_HIGHLIGHT":
|
|
41315
|
+
// FIXME: thiws whole ordeal could be handled with the Selection Processor which would extend the feature to selection inputs
|
|
41153
41316
|
this.dispatch("STOP_COMPOSER_RANGE_SELECTION");
|
|
41317
|
+
// FIXME: we should check range SheetId compared to this.activeSheetId r maybe not have a sheetId in the payload ??
|
|
41154
41318
|
const range = this.getters.getRangeFromRangeData(cmd.range);
|
|
41155
41319
|
const previousRefToken = this.currentTokens
|
|
41156
41320
|
.filter((token) => token.type === "REFERENCE")
|
|
@@ -41504,14 +41668,11 @@
|
|
|
41504
41668
|
const ref = this.getZoneReference(zone);
|
|
41505
41669
|
this.replaceText(ref, this.selectionInitialStart, this.selectionEnd);
|
|
41506
41670
|
}
|
|
41507
|
-
getZoneReference(zone
|
|
41671
|
+
getZoneReference(zone) {
|
|
41672
|
+
const inputSheetId = this.getters.getCurrentEditedCell().sheetId;
|
|
41508
41673
|
const sheetId = this.getters.getActiveSheetId();
|
|
41509
|
-
|
|
41510
|
-
|
|
41511
|
-
const sheetName = getCanonicalSheetName(this.getters.getSheetName(this.getters.getActiveSheetId()));
|
|
41512
|
-
selectedXc = `${sheetName}!${selectedXc}`;
|
|
41513
|
-
}
|
|
41514
|
-
return selectedXc;
|
|
41674
|
+
const range = this.getters.getRangeFromZone(sheetId, zone);
|
|
41675
|
+
return this.getters.getSelectionRangeString(range, inputSheetId);
|
|
41515
41676
|
}
|
|
41516
41677
|
getRangeReference(range, fixedParts = [{ colFixed: false, rowFixed: false }]) {
|
|
41517
41678
|
let _fixedParts = [...fixedParts];
|
|
@@ -42365,7 +42526,7 @@
|
|
|
42365
42526
|
const file = await this.getImageFromUser();
|
|
42366
42527
|
const path = await this.fileStore.upload(file);
|
|
42367
42528
|
const size = await this.getImageSize(path);
|
|
42368
|
-
return { path, size };
|
|
42529
|
+
return { path, size, mimetype: file.type };
|
|
42369
42530
|
}
|
|
42370
42531
|
getImageFromUser() {
|
|
42371
42532
|
return new Promise((resolve, reject) => {
|
|
@@ -47432,8 +47593,7 @@
|
|
|
47432
47593
|
// Figures and Charts
|
|
47433
47594
|
let drawingNode = escapeXml ``;
|
|
47434
47595
|
const drawingRelIds = [];
|
|
47435
|
-
const
|
|
47436
|
-
for (const chart of charts) {
|
|
47596
|
+
for (const chart of sheet.charts) {
|
|
47437
47597
|
const xlsxChartId = convertChartId(chart.id);
|
|
47438
47598
|
const chartRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
|
|
47439
47599
|
target: `../charts/chart${xlsxChartId}.xml`,
|
|
@@ -47442,20 +47602,27 @@
|
|
|
47442
47602
|
drawingRelIds.push(chartRelId);
|
|
47443
47603
|
files.push(createXMLFile(createChart(chart, sheetIndex, data), `xl/charts/chart${xlsxChartId}.xml`, "chart"));
|
|
47444
47604
|
}
|
|
47445
|
-
const
|
|
47446
|
-
|
|
47605
|
+
for (const image of sheet.images) {
|
|
47606
|
+
const mimeType = image.data.mimetype;
|
|
47607
|
+
if (mimeType === undefined)
|
|
47608
|
+
continue;
|
|
47609
|
+
const extension = IMAGE_MIMETYPE_EXTENSION_MAPPING[mimeType];
|
|
47610
|
+
// only support exporting images with mimetypes specified in the mapping
|
|
47611
|
+
if (extension === undefined)
|
|
47612
|
+
continue;
|
|
47447
47613
|
const xlsxImageId = convertImageId(image.id);
|
|
47614
|
+
let imageFileName = `image${xlsxImageId}.${extension}`;
|
|
47448
47615
|
const imageRelId = addRelsToFile(construct.relsFiles, `xl/drawings/_rels/drawing${sheetIndex}.xml.rels`, {
|
|
47449
|
-
target: `../media
|
|
47616
|
+
target: `../media/${imageFileName}`,
|
|
47450
47617
|
type: XLSX_RELATION_TYPE.image,
|
|
47451
47618
|
});
|
|
47452
47619
|
drawingRelIds.push(imageRelId);
|
|
47453
47620
|
files.push({
|
|
47454
|
-
path: `xl/media
|
|
47455
|
-
|
|
47621
|
+
path: `xl/media/${imageFileName}`,
|
|
47622
|
+
imageSrc: image.data.path,
|
|
47456
47623
|
});
|
|
47457
47624
|
}
|
|
47458
|
-
const drawings = [...charts, ...images];
|
|
47625
|
+
const drawings = [...sheet.charts, ...sheet.images];
|
|
47459
47626
|
if (drawings.length) {
|
|
47460
47627
|
const drawingRelId = addRelsToFile(construct.relsFiles, `xl/worksheets/_rels/sheet${sheetIndex}.xml.rels`, {
|
|
47461
47628
|
target: `../drawings/drawing${sheetIndex}.xml`,
|
|
@@ -47574,6 +47741,8 @@
|
|
|
47574
47741
|
}
|
|
47575
47742
|
function createContentTypes(files) {
|
|
47576
47743
|
const overrideNodes = [];
|
|
47744
|
+
// hard-code supported image mimetypes
|
|
47745
|
+
const imageDefaultNodes = Object.entries(IMAGE_MIMETYPE_EXTENSION_MAPPING).map(([mimetype, extension]) => createDefaultXMLElement(extension, mimetype));
|
|
47577
47746
|
for (const file of files) {
|
|
47578
47747
|
if ("contentType" in file && file.contentType) {
|
|
47579
47748
|
overrideNodes.push(createOverride("/" + file.path, CONTENT_TYPES[file.contentType]));
|
|
@@ -47589,6 +47758,7 @@
|
|
|
47589
47758
|
];
|
|
47590
47759
|
const xml = escapeXml /*xml*/ `
|
|
47591
47760
|
<Types xmlns="${NAMESPACE["Types"]}">
|
|
47761
|
+
${joinXmlNodes(Object.values(imageDefaultNodes))}
|
|
47592
47762
|
<Default ${formatAttributes(relsAttributes)} />
|
|
47593
47763
|
<Default ${formatAttributes(xmlAttributes)} />
|
|
47594
47764
|
${joinXmlNodes(overrideNodes)}
|
|
@@ -47680,7 +47850,7 @@
|
|
|
47680
47850
|
this.coreGetters.getRangeDataFromXc = this.range.getRangeDataFromXc.bind(this.range);
|
|
47681
47851
|
this.coreGetters.getRangeDataFromZone = this.range.getRangeDataFromZone.bind(this.range);
|
|
47682
47852
|
this.coreGetters.getRangeFromRangeData = this.range.getRangeFromRangeData.bind(this.range);
|
|
47683
|
-
this.coreGetters.
|
|
47853
|
+
this.coreGetters.getRangeFromZone = this.range.getRangeFromZone.bind(this.range);
|
|
47684
47854
|
this.getters = {
|
|
47685
47855
|
isReadonly: () => this.config.mode === "readonly" || this.config.mode === "dashboard",
|
|
47686
47856
|
isDashboard: () => this.config.mode === "dashboard",
|
|
@@ -48188,6 +48358,8 @@
|
|
|
48188
48358
|
exports.findCellInNewZone = findCellInNewZone;
|
|
48189
48359
|
exports.functionCache = functionCache;
|
|
48190
48360
|
exports.helpers = helpers;
|
|
48361
|
+
exports.invalidateCFEvaluationCommands = invalidateCFEvaluationCommands;
|
|
48362
|
+
exports.invalidateDependenciesCommands = invalidateDependenciesCommands;
|
|
48191
48363
|
exports.invalidateEvaluationCommands = invalidateEvaluationCommands;
|
|
48192
48364
|
exports.links = links;
|
|
48193
48365
|
exports.load = load;
|
|
@@ -48201,9 +48373,9 @@
|
|
|
48201
48373
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
48202
48374
|
|
|
48203
48375
|
|
|
48204
|
-
__info__.version = '16.4.0-alpha.
|
|
48205
|
-
__info__.date = '2023-
|
|
48206
|
-
__info__.hash = '
|
|
48376
|
+
__info__.version = '16.4.0-alpha.3';
|
|
48377
|
+
__info__.date = '2023-06-02T10:13:30.127Z';
|
|
48378
|
+
__info__.hash = '059d66a';
|
|
48207
48379
|
|
|
48208
48380
|
|
|
48209
48381
|
})(this.o_spreadsheet = this.o_spreadsheet || {}, owl);
|