@odoo/o-spreadsheet 15.0.12 → 15.0.15

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.
@@ -126,14 +126,72 @@
126
126
  // -----------------------------------------------------------------------------
127
127
  // Date Type
128
128
  // -----------------------------------------------------------------------------
129
+ /**
130
+ * A DateTime object that can be used to manipulate spreadsheet dates.
131
+ * Conceptually, a spreadsheet date is simply a number with a date format,
132
+ * and it is timezone-agnostic.
133
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
134
+ */
135
+ class DateTime {
136
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
137
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
138
+ }
139
+ static fromTimestamp(timestamp) {
140
+ const date = new Date(timestamp);
141
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
142
+ }
143
+ static now() {
144
+ const now = new Date();
145
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
146
+ }
147
+ toString() {
148
+ return this.jsDate.toString();
149
+ }
150
+ getTime() {
151
+ return this.jsDate.getTime();
152
+ }
153
+ getFullYear() {
154
+ return this.jsDate.getUTCFullYear();
155
+ }
156
+ getMonth() {
157
+ return this.jsDate.getUTCMonth();
158
+ }
159
+ getDate() {
160
+ return this.jsDate.getUTCDate();
161
+ }
162
+ getDay() {
163
+ return this.jsDate.getUTCDay();
164
+ }
165
+ getHours() {
166
+ return this.jsDate.getUTCHours();
167
+ }
168
+ getMinutes() {
169
+ return this.jsDate.getUTCMinutes();
170
+ }
171
+ getSeconds() {
172
+ return this.jsDate.getUTCSeconds();
173
+ }
174
+ setDate(date) {
175
+ this.jsDate.setUTCDate(date);
176
+ }
177
+ setHours(hours) {
178
+ this.jsDate.setUTCHours(hours);
179
+ }
180
+ setMinutes(minutes) {
181
+ this.jsDate.setUTCMinutes(minutes);
182
+ }
183
+ setSeconds(seconds) {
184
+ this.jsDate.setUTCSeconds(seconds);
185
+ }
186
+ }
129
187
  // -----------------------------------------------------------------------------
130
188
  // Parsing
131
189
  // -----------------------------------------------------------------------------
132
190
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
133
- const CURRENT_YEAR = new Date().getFullYear();
134
- const INITIAL_1900_DAY$1 = new Date(1899, 11, 30);
135
- const INITIAL_JS_DAY = new Date(0);
136
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY$1;
191
+ const CURRENT_YEAR = DateTime.now().getFullYear();
192
+ const INITIAL_1900_DAY$1 = new DateTime(1899, 11, 30);
193
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
194
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY$1.getTime();
137
195
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
138
196
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
139
197
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -173,7 +231,7 @@
173
231
  return {
174
232
  value: date.value + time.value,
175
233
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
176
- jsDate: new Date(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
234
+ jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
177
235
  };
178
236
  }
179
237
  return date || time;
@@ -190,13 +248,13 @@
190
248
  const day = Number(parts[dayIndex]);
191
249
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
192
250
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
193
- const jsDate = new Date(year, month - 1, day);
251
+ const jsDate = new DateTime(year, month - 1, day);
194
252
  const sep = str.match(/\/|-|\s/)[0];
195
253
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
196
254
  // invalid date
197
255
  return null;
198
256
  }
199
- const delta = jsDate - INITIAL_1900_DAY$1;
257
+ const delta = jsDate.getTime() - INITIAL_1900_DAY$1.getTime();
200
258
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
201
259
  if (parts[yearIndex]) {
202
260
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -256,7 +314,7 @@
256
314
  if (hours >= 24) {
257
315
  format = "hhhh:mm:ss";
258
316
  }
259
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
317
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
260
318
  return {
261
319
  value: hours / 24 + minutes / 1440 + seconds / 86400,
262
320
  format: format,
@@ -270,7 +328,7 @@
270
328
  // -----------------------------------------------------------------------------
271
329
  function numberToJsDate(value) {
272
330
  const truncValue = Math.trunc(value);
273
- let date = new Date(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
331
+ let date = DateTime.fromTimestamp(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
274
332
  let time = value - truncValue;
275
333
  time = time < 0 ? 1 + time : time;
276
334
  const hours = Math.round(time * 24);
@@ -343,7 +401,7 @@
343
401
  .map((p) => {
344
402
  switch (p) {
345
403
  case "hhhh":
346
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1) / (60 * 60 * 1000));
404
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1.getTime()) / (60 * 60 * 1000));
347
405
  return helapsedHours.toString();
348
406
  case "hh":
349
407
  return hours.toString().padStart(2, "0");
@@ -2698,13 +2756,6 @@
2698
2756
  }
2699
2757
 
2700
2758
  //------------------------------------------------------------------------------
2701
- /**
2702
- * Stringify an object, like JSON.stringify, except that the first level of keys
2703
- * is ordered.
2704
- */
2705
- function stringify(obj) {
2706
- return JSON.stringify(obj, Object.keys(obj).sort());
2707
- }
2708
2759
  /**
2709
2760
  * Escapes a string to use as a literal string in a RegExp.
2710
2761
  * @url https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
@@ -2850,7 +2901,7 @@
2850
2901
  function isDateTime(str) {
2851
2902
  return parseDateTime(str) !== null;
2852
2903
  }
2853
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
2904
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
2854
2905
  //link must start with http or https
2855
2906
  //https://stackoverflow.com/a/3809435/4760614
2856
2907
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -4753,7 +4804,7 @@
4753
4804
  DVARP: DVARP
4754
4805
  });
4755
4806
 
4756
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
4807
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
4757
4808
  const DEFAULT_TYPE = 1;
4758
4809
  const DEFAULT_WEEKEND = 1;
4759
4810
  function isLeapYear(year) {
@@ -4782,7 +4833,7 @@
4782
4833
  if (_year < 1900) {
4783
4834
  _year += 1900;
4784
4835
  }
4785
- const jsDate = new Date(_year, _month - 1, _day);
4836
+ const jsDate = new DateTime(_year, _month - 1, _day);
4786
4837
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4787
4838
  assert(() => delta >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
4788
4839
  return Math.round(delta / 86400000);
@@ -4855,7 +4906,7 @@
4855
4906
  const yStart = _startDate.getFullYear();
4856
4907
  const mStart = _startDate.getMonth();
4857
4908
  const dStart = _startDate.getDate();
4858
- const jsDate = new Date(yStart, mStart + _months, dStart);
4909
+ const jsDate = new DateTime(yStart, mStart + _months, dStart);
4859
4910
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4860
4911
  return Math.round(delta / 86400000);
4861
4912
  },
@@ -4877,7 +4928,7 @@
4877
4928
  const _months = Math.trunc(toNumber(months));
4878
4929
  const yStart = _startDate.getFullYear();
4879
4930
  const mStart = _startDate.getMonth();
4880
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
4931
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
4881
4932
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4882
4933
  return Math.round(delta / 86400000);
4883
4934
  },
@@ -4917,17 +4968,17 @@
4917
4968
  // The first week of the year is the week that contains the first
4918
4969
  // Thursday of the year.
4919
4970
  let firstThursday = 1;
4920
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
4971
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
4921
4972
  firstThursday += 1;
4922
4973
  }
4923
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
4974
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
4924
4975
  // The last week of the year is the week that contains the last Thursday of
4925
4976
  // the year.
4926
4977
  let lastThursday = 31;
4927
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
4978
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
4928
4979
  lastThursday -= 1;
4929
4980
  }
4930
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
4981
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
4931
4982
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
4932
4983
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
4933
4984
  let offsetYear;
@@ -4953,17 +5004,17 @@
4953
5004
  case 1:
4954
5005
  // firstDay is the 1st day of the 1st week of the year after
4955
5006
  // firstDay = lastDayOfLastWeek + 1 Day
4956
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
5007
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
4957
5008
  break;
4958
5009
  case -1:
4959
5010
  // firstDay is the 1st day of the 1st week of the previous year.
4960
5011
  // The first week of the previous year is the week that contains the
4961
5012
  // first Thursday of the previous year.
4962
5013
  let firstThursdayPreviousYear = 1;
4963
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
5014
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
4964
5015
  firstThursdayPreviousYear += 1;
4965
5016
  }
4966
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
5017
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
4967
5018
  break;
4968
5019
  }
4969
5020
  const dif = (_date.getTime() - firstDay.getTime()) / 86400000;
@@ -5102,8 +5153,8 @@
5102
5153
  });
5103
5154
  }
5104
5155
  const invertDate = _startDate.getTime() > _endDate.getTime();
5105
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
5106
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
5156
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
5157
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
5107
5158
  const timeStopDate = stopDate.getTime();
5108
5159
  let timeStepDate = stepDate.getTime();
5109
5160
  let netWorkingDay = 0;
@@ -5127,8 +5178,7 @@
5127
5178
  returns: ["DATE"],
5128
5179
  returnFormat: { specificFormat: "m/d/yyyy hh:mm:ss" },
5129
5180
  compute: function () {
5130
- let today = new Date();
5131
- today.setMilliseconds(0);
5181
+ let today = DateTime.now();
5132
5182
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
5133
5183
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
5134
5184
  return Math.floor(delta / 86400000) + time;
@@ -5202,8 +5252,8 @@
5202
5252
  returns: ["DATE"],
5203
5253
  returnFormat: { specificFormat: "m/d/yyyy" },
5204
5254
  compute: function () {
5205
- const today = new Date();
5206
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
5255
+ const today = DateTime.now();
5256
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
5207
5257
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
5208
5258
  return Math.round(delta / 86400000);
5209
5259
  },
@@ -5259,10 +5309,10 @@
5259
5309
  }
5260
5310
  const y = _date.getFullYear();
5261
5311
  let dayStart = 1;
5262
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
5312
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5263
5313
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
5264
5314
  dayStart += 1;
5265
- startDayOfFirstWeek = new Date(y, 0, dayStart);
5315
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5266
5316
  }
5267
5317
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / 86400000;
5268
5318
  if (dif < 0) {
@@ -5316,7 +5366,7 @@
5316
5366
  timesHoliday.add(holiday.getTime());
5317
5367
  });
5318
5368
  }
5319
- let stepDate = new Date(_startDate.getTime());
5369
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
5320
5370
  let timeStepDate = stepDate.getTime();
5321
5371
  const unitDay = Math.sign(_numDays);
5322
5372
  let stepDay = Math.abs(_numDays);
@@ -9423,7 +9473,7 @@
9423
9473
  */
9424
9474
  function getBorderId(border) {
9425
9475
  for (let [key, value] of Object.entries(borders)) {
9426
- if (stringify(value) === stringify(border)) {
9476
+ if (deepEquals(value, border)) {
9427
9477
  return parseInt(key, 10);
9428
9478
  }
9429
9479
  }
@@ -9619,7 +9669,7 @@
9619
9669
  */
9620
9670
  function getStyleId(style) {
9621
9671
  for (let [key, value] of Object.entries(styles)) {
9622
- if (stringify(value) === stringify(style)) {
9672
+ if (deepEquals(value, style)) {
9623
9673
  return parseInt(key, 10);
9624
9674
  }
9625
9675
  }
@@ -9673,12 +9723,10 @@
9673
9723
  * starting an async evaluation even if it has been moved or re-allocated
9674
9724
  */
9675
9725
  getCellById(cellId) {
9676
- for (const sheet of Object.values(this.cells)) {
9677
- if (sheet[cellId]) {
9678
- return sheet[cellId];
9679
- }
9680
- }
9681
- return undefined;
9726
+ // this must be as fast as possible
9727
+ const position = this.getters.getCellPosition(cellId);
9728
+ const sheet = this.cells[position.sheetId];
9729
+ return sheet[cellId];
9682
9730
  }
9683
9731
  /**
9684
9732
  * Reconstructs the original formula string based on a normalized form and its dependencies
@@ -15847,7 +15895,7 @@
15847
15895
  }
15848
15896
  .o-input-count {
15849
15897
  width: fit-content;
15850
- padding: 4 0 4 4;
15898
+ padding: 4px 0 4px 4px;
15851
15899
  }
15852
15900
  }
15853
15901
  }
@@ -23499,9 +23547,9 @@
23499
23547
  * Apply the changes of the given HistoryChange to the state
23500
23548
  */
23501
23549
  function applyChange(change, target) {
23502
- let val = change.root;
23503
- let key = change.path[change.path.length - 1];
23504
- for (let pathIndex = 0; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
23550
+ let val = change.path[0];
23551
+ const key = change.path[change.path.length - 1];
23552
+ for (let pathIndex = 1; pathIndex < change.path.slice(0, -1).length; pathIndex++) {
23505
23553
  const p = change.path[pathIndex];
23506
23554
  if (val[p] === undefined) {
23507
23555
  const nextPath = change.path[pathIndex + 1];
@@ -23957,13 +24005,14 @@
23957
24005
  }
23958
24006
  addChange(...args) {
23959
24007
  const val = args.pop();
23960
- const [root, ...path] = args;
24008
+ const root = args[0];
23961
24009
  let value = root;
23962
- let key = path[path.length - 1];
23963
- for (let pathIndex = 0; pathIndex <= path.length - 2; pathIndex++) {
23964
- const p = path[pathIndex];
24010
+ let key = args[args.length - 1];
24011
+ const pathLength = args.length - 2;
24012
+ for (let pathIndex = 1; pathIndex <= pathLength; pathIndex++) {
24013
+ const p = args[pathIndex];
23965
24014
  if (value[p] === undefined) {
23966
- const nextPath = path[pathIndex + 1];
24015
+ const nextPath = args[pathIndex + 1];
23967
24016
  value[p] = createEmptyStructure(nextPath);
23968
24017
  }
23969
24018
  value = value[p];
@@ -23972,8 +24021,7 @@
23972
24021
  return;
23973
24022
  }
23974
24023
  this.changes.push({
23975
- root,
23976
- path,
24024
+ path: args,
23977
24025
  before: value[key],
23978
24026
  after: val,
23979
24027
  });
@@ -26031,7 +26079,10 @@
26031
26079
  */
26032
26080
  checkDispatchAllowed(command) {
26033
26081
  const results = this.handlers.map((handler) => handler.allowDispatch(command));
26034
- return new DispatchResult(results.flat());
26082
+ if (results.some((r) => r !== 0 /* Success */)) {
26083
+ return new DispatchResult(results.flat());
26084
+ }
26085
+ return DispatchResult.Success;
26035
26086
  }
26036
26087
  finalize() {
26037
26088
  this.status = 3 /* Finalizing */;
@@ -31455,9 +31506,9 @@
31455
31506
  Object.defineProperty(exports, '__esModule', { value: true });
31456
31507
 
31457
31508
 
31458
- __info__.version = '15.0.12';
31459
- __info__.date = '2023-11-02T09:28:12.777Z';
31460
- __info__.hash = 'e82bd99';
31509
+ __info__.version = '15.0.15';
31510
+ __info__.date = '2024-01-12T13:39:45.422Z';
31511
+ __info__.hash = 'c87764c';
31461
31512
 
31462
31513
 
31463
31514
  })(this.o_spreadsheet = this.o_spreadsheet || {}, owl);