@olenbetong/appframe-core 2.15.1 → 2.16.0

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.
@@ -1,4 +1,4 @@
1
- //#region ../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/dist/mitt.mjs
1
+ // ../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/dist/mitt.mjs
2
2
  function mitt_default(n) {
3
3
  return {
4
4
  all: n = n || /* @__PURE__ */ new Map(),
@@ -21,8 +21,7 @@ function mitt_default(n) {
21
21
  };
22
22
  }
23
23
 
24
- //#endregion
25
- //#region src/SessionHandler.ts
24
+ // src/SessionHandler.ts
26
25
  var SessionHandler = class {
27
26
  eventHandler = mitt_default();
28
27
  authenticated() {
@@ -67,8 +66,7 @@ var SessionHandler = class {
67
66
  }
68
67
  };
69
68
 
70
- //#endregion
71
- //#region src/UserSession.ts
69
+ // src/UserSession.ts
72
70
  var UserSession = class extends SessionHandler {
73
71
  amDesignator = "a.m.";
74
72
  dayNames = [
@@ -140,8 +138,7 @@ var UserSession = class extends SessionHandler {
140
138
  }
141
139
  };
142
140
 
143
- //#endregion
144
- //#region src/log.ts
141
+ // src/log.ts
145
142
  const article = window.af?.article?.id ?? window.window?.location.pathname.substring(1).split("/")[0];
146
143
  /**
147
144
  * Logs an activity to the website activity log
@@ -219,6 +216,30 @@ async function logError(error) {
219
216
  function getSessionId() {
220
217
  return crypto.randomUUID?.();
221
218
  }
219
+ /** The version in the first URL served under `/lib/@olenbetong/<name>/<version>/`. */
220
+ function libVersion(name, urls) {
221
+ let pattern = new RegExp(`/lib/@olenbetong/${name}/([^/]+)/`);
222
+ for (let url of urls) {
223
+ let match = typeof url === "string" ? pattern.exec(url) : null;
224
+ if (match) return match[1];
225
+ }
226
+ }
227
+ /**
228
+ * The synergi-chrome and synergi-platform versions the page loads on the 2026 site templates,
229
+ * read from the chrome's script tag and the platform import map rather than from the chrome
230
+ * itself, so they are known even when the chrome failed to start. Empty on other pages.
231
+ */
232
+ function getPlatformVersions() {
233
+ let versions = {};
234
+ try {
235
+ let importMap = document.querySelector("script[type=\"importmap\"]");
236
+ let platform = importMap ? libVersion("synergi-platform", Object.values(JSON.parse(importMap.textContent ?? "{}").imports ?? {})) : void 0;
237
+ if (platform) versions["synergi-platform"] = platform;
238
+ } catch {}
239
+ let chrome = libVersion("synergi-chrome", Array.from(document.scripts, (script) => script.src)) ?? window.ob?.chrome?.version;
240
+ if (chrome) versions["synergi-chrome"] = chrome;
241
+ return versions;
242
+ }
222
243
  let sessionStart = Date.now();
223
244
  let sessionId = getSessionId();
224
245
  let deviceId = "";
@@ -227,7 +248,8 @@ if ("document" in window) {
227
248
  let startSession = () => logActivity("AfSessionInit", {
228
249
  "appframe-core": window.af?.common?.version,
229
250
  "appframe-data": window.af?.data?.version,
230
- "app-version": window.af?.article?.version
251
+ "app-version": window.af?.article?.version,
252
+ ...getPlatformVersions()
231
253
  });
232
254
  document.addEventListener("DOMContentLoaded", () => {
233
255
  deviceId = localStorage.getItem("_afDeviceId");
@@ -261,15 +283,13 @@ function getSessionData() {
261
283
  };
262
284
  }
263
285
 
264
- //#endregion
265
- //#region src/errorHandler.ts
286
+ // src/errorHandler.ts
266
287
  window.window?.addEventListener("error", (event) => {
267
288
  if (typeof event === "object" && "error" in event) logError(event.error);
268
289
  else if (typeof event === "object" && "message" in event) logError(event);
269
290
  });
270
291
 
271
- //#endregion
272
- //#region src/localStorage.ts
292
+ // src/localStorage.ts
273
293
  function getLocalKey(key) {
274
294
  return [
275
295
  af?.article?.id || "",
@@ -304,8 +324,7 @@ var LocalStorage = class {
304
324
  };
305
325
  var localStorage_default = new LocalStorage();
306
326
 
307
- //#endregion
308
- //#region src/date.ts
327
+ // src/date.ts
309
328
  function toLocalISODate(date) {
310
329
  return date ? toLocalISODateTime(date).substring(0, 10) : null;
311
330
  }
@@ -328,8 +347,7 @@ function toLocalDateTime(date) {
328
347
  return date ? date.toISOString().substring(0, 16) : "";
329
348
  }
330
349
 
331
- //#endregion
332
- //#region src/downloadBlob.ts
350
+ // src/downloadBlob.ts
333
351
  function downloadBlob(blob, fileName) {
334
352
  return new Promise((resolve, reject) => {
335
353
  try {
@@ -351,8 +369,7 @@ function downloadBlob(blob, fileName) {
351
369
  });
352
370
  }
353
371
 
354
- //#endregion
355
- //#region src/invariant.ts
372
+ // src/invariant.ts
356
373
  /**
357
374
  * Throws an error if the condition is falsy. The provided message is used as the error message.
358
375
  * A function can be provided to lazily generate the message.
@@ -367,8 +384,7 @@ function invariant(condition, message) {
367
384
  throw new Error(provided ?? "Invariant failed");
368
385
  }
369
386
 
370
- //#endregion
371
- //#region src/downloadRequest.ts
387
+ // src/downloadRequest.ts
372
388
  async function downloadRequest(request, { fileName, signal, onProgress }) {
373
389
  let bytesReceived = 0;
374
390
  onProgress?.({ status: "requested" });
@@ -422,8 +438,7 @@ async function downloadRequest(request, { fileName, signal, onProgress }) {
422
438
  }
423
439
  }
424
440
 
425
- //#endregion
426
- //#region src/parseFunc.ts
441
+ // src/parseFunc.ts
427
442
  const funcRegex = /^function(?:\s+([a-zA-Z$_][a-zA-Z0-9$_]*))?\s*\(((?:(?:\s*[a-zA-Z$_][a-zA-Z0-9$_]*)(?:\s*,\s*[a-zA-Z$_][a-zA-Z0-9$_]*)*)?)\s*\)\s*\{((?:.|\n|\r)*)\}$/;
428
443
  const arrowBlockRegex = /^(?:\(([^)]*)\)|([a-zA-Z$_][a-zA-Z0-9$_]*))\s*=>\s*\{([\s\S]*)\}$/;
429
444
  const arrowExpressionRegex = /^(?:\(([^)]*)\)|([a-zA-Z$_][a-zA-Z0-9$_]*))\s*=>\s*([\s\S]+)$/;
@@ -457,13 +472,11 @@ function parseFunc(func) {
457
472
  };
458
473
  }
459
474
 
460
- //#endregion
461
- //#region src/Namespace.ts
475
+ // src/Namespace.ts
462
476
  function Namespace() {}
463
477
  Namespace.prototype = Object.create(null);
464
478
 
465
- //#endregion
466
- //#region src/requireNamespace.ts
479
+ // src/requireNamespace.ts
467
480
  function requireNamespace(root, namespace) {
468
481
  if (typeof root === "object") {
469
482
  if (typeof namespace === "string") return requireNamespace(root, namespace.split("."));
@@ -475,8 +488,7 @@ function requireNamespace(root, namespace) {
475
488
  }
476
489
  }
477
490
 
478
- //#endregion
479
- //#region src/expose.ts
491
+ // src/expose.ts
480
492
  /**
481
493
  * Expose a value to a potentially deeply nested global variable
482
494
  * @param name {string | object} Either a dot-separated path to the global variable, or an object to expose the value on
@@ -506,8 +518,7 @@ function expose(name, value, options = {}) {
506
518
  }
507
519
  }
508
520
 
509
- //#endregion
510
- //#region src/getLocalizedString.ts
521
+ // src/getLocalizedString.ts
511
522
  async function fetchLocalizedString(text, project) {
512
523
  try {
513
524
  let response = await fetch(`/api/user/localize/new/${encodeURIComponent(project)}`, {
@@ -596,8 +607,7 @@ function createLocalizer(project) {
596
607
  };
597
608
  }
598
609
 
599
- //#endregion
600
- //#region src/filter/operators.ts
610
+ // src/filter/operators.ts
601
611
  /**
602
612
  * Operators that take no value at all.
603
613
  *
@@ -611,6 +621,26 @@ const PARAMETERLESS_OPERATORS = [
611
621
  "isblank",
612
622
  "isnotblank"
613
623
  ];
624
+ /**
625
+ * Whole-period checks for dates, such as "Is last week", in the order of the
626
+ * Windows filter editor. They take no value. The framework has no operator for
627
+ * them, so a filter using one is sent as a filter string (`needsFilterString`).
628
+ */
629
+ const PERIOD_OPERATORS = [
630
+ "isbeyondthisyear",
631
+ "islaterthisyear",
632
+ "islaterthismonth",
633
+ "isnextweek",
634
+ "islaterthisweek",
635
+ "istomorrow",
636
+ "istoday",
637
+ "isyesterday",
638
+ "isearlierthisweek",
639
+ "islastweek",
640
+ "isearlierthismonth",
641
+ "isearlierthisyear",
642
+ "ispriorthisyear"
643
+ ];
614
644
  /** Operators whose value is a two element `[from, to]` array. */
615
645
  const PAIR_OPERATORS = [
616
646
  "between",
@@ -621,7 +651,7 @@ const PAIR_OPERATORS = [
621
651
  /** Operators whose value is an array of values. */
622
652
  const LIST_OPERATORS = ["inlist", "notinlist"];
623
653
  function getOperatorArity(operator) {
624
- if (PARAMETERLESS_OPERATORS.includes(operator)) return "none";
654
+ if (PARAMETERLESS_OPERATORS.includes(operator) || PERIOD_OPERATORS.includes(operator)) return "none";
625
655
  if (PAIR_OPERATORS.includes(operator)) return "pair";
626
656
  if (LIST_OPERATORS.includes(operator)) return "list";
627
657
  return "single";
@@ -664,7 +694,20 @@ const OPERATOR_LABELS = {
664
694
  datelessthan: "Before",
665
695
  datelessthanorequal: "Up to",
666
696
  datebetween: "Between",
667
- datenotbetween: "Not between"
697
+ datenotbetween: "Not between",
698
+ isbeyondthisyear: "Is beyond this year",
699
+ islaterthisyear: "Is later this year",
700
+ islaterthismonth: "Is later this month",
701
+ isnextweek: "Is next week",
702
+ islaterthisweek: "Is later this week",
703
+ istomorrow: "Is tomorrow",
704
+ istoday: "Is today",
705
+ isyesterday: "Is yesterday",
706
+ isearlierthisweek: "Is earlier this week",
707
+ islastweek: "Is last week",
708
+ isearlierthismonth: "Is earlier this month",
709
+ isearlierthisyear: "Is earlier this year",
710
+ ispriorthisyear: "Is prior to this year"
668
711
  };
669
712
  /** Comparison operator labels used for date and time fields. */
670
713
  const DATE_OPERATOR_LABELS = {
@@ -709,13 +752,15 @@ const OPERATORS_BY_TYPE = {
709
752
  ...EQUALITY,
710
753
  ...LIST_CHECKS,
711
754
  ...RANGE,
712
- ...COMPARISONS
755
+ ...COMPARISONS,
756
+ ...PERIOD_OPERATORS
713
757
  ],
714
758
  datetime: [
715
759
  ...EQUALITY,
716
760
  ...LIST_CHECKS,
717
761
  ...RANGE,
718
- ...COMPARISONS
762
+ ...COMPARISONS,
763
+ ...PERIOD_OPERATORS
719
764
  ],
720
765
  number: [
721
766
  ...EQUALITY,
@@ -788,7 +833,10 @@ function getValueType(field, operator) {
788
833
  const RELATIVE_DATE_VALUES = [
789
834
  "Yesterday",
790
835
  "Today",
836
+ "Now",
791
837
  "Tomorrow",
838
+ "DayAfterTomorrow",
839
+ "TwoWeeksAway",
792
840
  "ThisWeek",
793
841
  "ThisMonth",
794
842
  "ThisYear",
@@ -803,7 +851,10 @@ const DYNAMIC_VALUE_LABELS = {
803
851
  CurrentUser: "Current user",
804
852
  Yesterday: "Yesterday",
805
853
  Today: "Today",
854
+ Now: "Now",
806
855
  Tomorrow: "Tomorrow",
856
+ DayAfterTomorrow: "Day after tomorrow",
857
+ TwoWeeksAway: "Two weeks away",
807
858
  ThisWeek: "This week",
808
859
  ThisMonth: "This month",
809
860
  ThisYear: "This year",
@@ -839,6 +890,30 @@ function getDynamicValuesForField(field) {
839
890
  if (field.type === "string") return ["CurrentUser"];
840
891
  return [];
841
892
  }
893
+ /** Operators that can compare a field with another column. */
894
+ const COLUMN_OPERATORS = [
895
+ ...EQUALITY,
896
+ ...RANGE,
897
+ ...COMPARISONS
898
+ ];
899
+ /** Whether an operator can take another column as its value. */
900
+ function supportsColumnValue(operator) {
901
+ return COLUMN_OPERATORS.includes(operator);
902
+ }
903
+ /** Dates and datetimes compare with each other; other types only with their own. */
904
+ function getComparableType(type) {
905
+ return type === "datetime" ? "date" : type;
906
+ }
907
+ /**
908
+ * The columns a field can be compared with: the other fields of the same type,
909
+ * as in the Windows filter editor. Booleans have only true and false checks,
910
+ * so they get none.
911
+ */
912
+ function getColumnsForField(field, fields) {
913
+ if (field.type === "boolean") return [];
914
+ let type = getComparableType(field.type);
915
+ return fields.filter((other) => other.name !== field.name && !other.excludeFromFilter && getComparableType(other.type) === type);
916
+ }
842
917
  /**
843
918
  * Aliases for names `eOperators.ToString()` can produce that are not operators
844
919
  * in their own right. `Not` is the bare negation flag (i.e. "not equal to"),
@@ -862,8 +937,7 @@ function normalizeOperator(operator) {
862
937
  return OPERATOR_ALIASES[normalized] ?? normalized;
863
938
  }
864
939
 
865
- //#endregion
866
- //#region src/filter/tree.ts
940
+ // src/filter/tree.ts
867
941
  /**
868
942
  * Creates the default empty filter: a single `and` group with no conditions.
869
943
  */
@@ -950,10 +1024,40 @@ function isCompleteExpression(item) {
950
1024
  let arity = getOperatorArity(normalizeOperator(item.operator));
951
1025
  if (arity === "none") return true;
952
1026
  if (item.value === null || item.value === void 0 || item.value === "") return false;
953
- if (arity === "pair") return Array.isArray(item.value) && item.value.length === 2 && item.value.every((v) => v !== "" && v != null);
1027
+ if (arity === "pair") return Array.isArray(item.value) && item.value.length === 2 && item.value.every((v) => {
1028
+ let end = isRangeEnd(v) ? v.value : v;
1029
+ return end !== "" && end != null;
1030
+ });
954
1031
  if (arity === "list") return Array.isArray(item.value) && item.value.length > 0;
955
1032
  return true;
956
1033
  }
1034
+ /** Whether a range value end is a `FilterRangeEnd` rather than a plain value. */
1035
+ function isRangeEnd(value) {
1036
+ return typeof value === "object" && value !== null && !(value instanceof Date) && "valueType" in value;
1037
+ }
1038
+ /** Dynamic values the framework has no `eDynamicValue` member for. */
1039
+ const DYNAMIC_VALUES_WITHOUT_FRAMEWORK_SUPPORT = /* @__PURE__ */ new Set([
1040
+ "Now",
1041
+ "DayAfterTomorrow",
1042
+ "TwoWeeksAway"
1043
+ ]);
1044
+ function needsConversion(valueType, value) {
1045
+ if (valueType === "column") return true;
1046
+ return valueType === "special" && typeof value === "string" && DYNAMIC_VALUES_WITHOUT_FRAMEWORK_SUPPORT.has(value);
1047
+ }
1048
+ /**
1049
+ * True when the filter holds something the framework's data API cannot read
1050
+ * from a filter object: another column, a range end that is not a plain value,
1051
+ * one of the dates only the Windows editor offers, or a whole-period check. Such a filter must be
1052
+ * converted with `convertFilter` and sent as a filter string.
1053
+ */
1054
+ function needsFilterString(filter) {
1055
+ if (!filter) return false;
1056
+ if (isGroup(filter)) return filter.items.some(needsFilterString);
1057
+ if (PERIOD_OPERATORS.includes(normalizeOperator(filter.operator))) return true;
1058
+ if (needsConversion(filter.valueType, filter.value)) return true;
1059
+ return Array.isArray(filter.value) && filter.value.some((item) => isRangeEnd(item));
1060
+ }
957
1061
  /**
958
1062
  * Creates an expression for a field, using the field's default operator and an
959
1063
  * empty value of the right shape.
@@ -984,8 +1088,9 @@ function changeOperator(expression, operator, field) {
984
1088
  let previousArity = getOperatorArity(normalizeOperator(expression.operator));
985
1089
  let arity = getOperatorArity(operator);
986
1090
  let value = expression.value;
987
- if (arity !== previousArity) value = createEmptyValue(operator);
988
- let valueType = expression.valueType === "special" && arity === previousArity ? "special" : getValueType(field, operator);
1091
+ let holdsColumn = expression.valueType === "column" || Array.isArray(value) && value.some((item) => isRangeEnd(item) && item.valueType === "column");
1092
+ if (arity !== previousArity || holdsColumn && !supportsColumnValue(operator)) value = createEmptyValue(operator);
1093
+ let valueType = (expression.valueType === "special" || expression.valueType === "column") && value === expression.value ? expression.valueType : getValueType(field, operator);
989
1094
  return {
990
1095
  ...expression,
991
1096
  operator,
@@ -1051,8 +1156,7 @@ function addGroupAtPath(filter, path = []) {
1051
1156
  return insertNodeAtPath(filter, path, createEmptyGroup(parent && isGroup(parent) && parent.mode === "and" ? "or" : "and"));
1052
1157
  }
1053
1158
 
1054
- //#endregion
1055
- //#region src/filter/convertFilter.ts
1159
+ // src/filter/convertFilter.ts
1056
1160
  const CONVERT_URL = "/api/filter/convert";
1057
1161
  /**
1058
1162
  * Converts between a structured filter and a DevExpress filter string.
@@ -1077,8 +1181,7 @@ async function convertFilter(request, signal) {
1077
1181
  };
1078
1182
  }
1079
1183
 
1080
- //#endregion
1081
- //#region src/filter/describeFilter.ts
1184
+ // src/filter/describeFilter.ts
1082
1185
  /**
1083
1186
  * Builds a human-readable description of a filter, without contacting the
1084
1187
  * server. Use this for read-only summaries; the authoritative filter string is
@@ -1106,18 +1209,19 @@ function describeExpression(expression, fields) {
1106
1209
  let label = getOperatorLabel(operator, field?.type);
1107
1210
  let arity = getOperatorArity(operator);
1108
1211
  if (arity === "none") return `[${caption}] ${label}`;
1109
- return `[${caption}] ${label} ${formatValue(expression, arity)}`;
1212
+ return `[${caption}] ${label} ${formatValue(expression, arity, fields)}`;
1110
1213
  }
1111
- function formatValue(expression, arity) {
1214
+ function formatValue(expression, arity, fields) {
1112
1215
  let { value, valueType } = expression;
1113
- if (valueType === "special" && typeof value === "string") return getDynamicValueLabel(value);
1114
1216
  if (Array.isArray(value)) {
1115
- let formatted = value.map((item) => formatScalar(item, valueType));
1217
+ let formatted = value.map((item) => isRangeEnd(item) ? formatScalar(item.value, item.valueType, fields) : formatScalar(item, valueType, fields));
1116
1218
  return arity === "pair" ? formatted.join(" - ") : `(${formatted.join(", ")})`;
1117
1219
  }
1118
- return formatScalar(value, valueType);
1220
+ return formatScalar(value, valueType, fields);
1119
1221
  }
1120
- function formatScalar(value, valueType) {
1222
+ function formatScalar(value, valueType, fields) {
1223
+ if (valueType === "special" && typeof value === "string") return getDynamicValueLabel(value);
1224
+ if (valueType === "column" && typeof value === "string") return `[${fields.get(value.toLowerCase())?.caption ?? value}]`;
1121
1225
  if (value === null || value === void 0) return "";
1122
1226
  if (value instanceof Date) return value.toISOString().slice(0, 10);
1123
1227
  if (typeof value === "number" || typeof value === "boolean") return String(value);
@@ -1125,8 +1229,7 @@ function formatScalar(value, valueType) {
1125
1229
  return `'${String(value)}'`;
1126
1230
  }
1127
1231
 
1128
- //#endregion
1129
- //#region src/filter/fields.ts
1232
+ // src/filter/fields.ts
1130
1233
  const FIELD_TYPES = [
1131
1234
  "string",
1132
1235
  "number",
@@ -1161,8 +1264,7 @@ function toFieldMetadataList(records) {
1161
1264
  return records.map(toFieldMetadata).filter((field) => field.name !== "" && !field.excludeFromFilter).sort((a, b) => a.name.localeCompare(b.name));
1162
1265
  }
1163
1266
 
1164
- //#endregion
1165
- //#region src/filter/standardLayout.ts
1267
+ // src/filter/standardLayout.ts
1166
1268
  /**
1167
1269
  * The "standard layout" is the simplified shape the Windows filter editor can
1168
1270
  * render in its flow view: an outer `or` group whose items are `and` groups of
@@ -1244,8 +1346,7 @@ function collectExpressions(item, into) {
1244
1346
  for (let child of item.items) collectExpressions(child, into);
1245
1347
  }
1246
1348
 
1247
- //#endregion
1248
- //#region src/filter/savedFilters.ts
1349
+ // src/filter/savedFilters.ts
1249
1350
  /**
1250
1351
  * `sviw_Database_MyFilters` unions in a synthetic "No Filter" row so the Windows
1251
1352
  * tree can render a "no filter" entry. It is not a real filter and must be
@@ -1344,8 +1445,7 @@ const canDeleteSavedFilter = canRenameSavedFilter;
1344
1445
  */
1345
1446
  const canSetCrossDomain = canRenameSavedFilter;
1346
1447
 
1347
- //#endregion
1348
- //#region src/getUserImage.ts
1448
+ // src/getUserImage.ts
1349
1449
  const sizeMap = {
1350
1450
  xs: 64,
1351
1451
  sm: 128,
@@ -1360,8 +1460,7 @@ function getUserImage(primKeyOrOptions, login, hash, size = "xs") {
1360
1460
  return `/api/data/blob/EmployeesLookup/${primKeyOrOptions}/Image/${encodeURIComponent(login ?? "")}${login ? "." : ""}${encodeURIComponent(hash)}.jpg${sizePx ? `?width=${sizePx}` : ""}`;
1361
1461
  }
1362
1462
 
1363
- //#endregion
1364
- //#region src/localize.ts
1463
+ // src/localize.ts
1365
1464
  /**
1366
1465
  * Localization function for tagged templates. Replaces the arguments
1367
1466
  * with $n, where n is the index, before asking Appframe to translate
@@ -1385,8 +1484,7 @@ function localize(stringParts, ...args) {
1385
1484
  return localized;
1386
1485
  }
1387
1486
 
1388
- //#endregion
1389
- //#region src/report/recordSource.ts
1487
+ // src/report/recordSource.ts
1390
1488
  const XML_ENTITIES = {
1391
1489
  amp: "&",
1392
1490
  lt: "<",
@@ -1472,8 +1570,7 @@ function parseRecordSource(xml) {
1472
1570
  };
1473
1571
  }
1474
1572
 
1475
- //#endregion
1476
- //#region src/report/parameters.ts
1573
+ // src/report/parameters.ts
1477
1574
  /**
1478
1575
  * Report parameters: mapping the metadata records onto something renderable,
1479
1576
  * and the XML the parameter values are stored as on a saved filter.
@@ -1626,8 +1723,7 @@ function restoreParameterValues(parameters, xml) {
1626
1723
  return values;
1627
1724
  }
1628
1725
 
1629
- //#endregion
1630
- //#region src/report/parameterDefaults.ts
1726
+ // src/report/parameterDefaults.ts
1631
1727
  /**
1632
1728
  * Resolving report parameter defaults that name a stored procedure.
1633
1729
  *
@@ -1689,8 +1785,7 @@ function firstValue(result) {
1689
1785
  return row;
1690
1786
  }
1691
1787
 
1692
- //#endregion
1693
- //#region src/report/render.ts
1788
+ // src/report/render.ts
1694
1789
  /**
1695
1790
  * Rendering a report through the framework's report route.
1696
1791
  *
@@ -1894,8 +1989,7 @@ function toParameterEntries(parameters) {
1894
1989
  }));
1895
1990
  }
1896
1991
 
1897
- //#endregion
1898
- //#region src/report/report.ts
1992
+ // src/report/report.ts
1899
1993
  /**
1900
1994
  * Mapping a `sviw_WinClient_MyReports` record onto the report model, including
1901
1995
  * which output formats the report offers.
@@ -1939,8 +2033,7 @@ function toReport(record) {
1939
2033
  };
1940
2034
  }
1941
2035
 
1942
- //#endregion
1943
- //#region src/alert.ts
2036
+ // src/alert.ts
1944
2037
  const template = `
1945
2038
  <dialog class="alert-dialog">
1946
2039
  <form method="dialog">
@@ -2051,8 +2144,7 @@ async function alert(prompt, options = {}) {
2051
2144
  });
2052
2145
  }
2053
2146
 
2054
- //#endregion
2055
- //#region src/settings.ts
2147
+ // src/settings.ts
2056
2148
  function getKey(article) {
2057
2149
  return `${article ?? window.af?.article?.id ?? window.window?.location.pathname.substring(1).split("/")[0]}.${window.af?.userSession.login ?? "anonymous"}`;
2058
2150
  }
@@ -2072,9 +2164,7 @@ function saveSettings(setting, value, article) {
2072
2164
  localStorage.setItem(key, JSON.stringify(userSettings));
2073
2165
  }
2074
2166
 
2075
- //#endregion
2076
- //#region src/index.ts
2077
- const version = "2.15.1";
2167
+ // src/index.ts
2168
+ const version = "2.15.2";
2078
2169
 
2079
- //#endregion
2080
- export { ConfirmButtons, NO_FILTER_ID, RELATIVE_DATE_VALUES, SessionHandler, UserSession, addGroupAtPath, alert, canDeleteSavedFilter, canEditSavedFilter, canRenameSavedFilter, canSetCrossDomain, canShareSavedFilter, changeOperator, coerceParameterValue, coerceToStandardLayout, confirm, convertFilter, countExpressions, createEmptyFilter, createEmptyGroup, createExpression, createLocalizer, decodeXml, describeFilter, downloadBlob, downloadReport, downloadRequest, encodeXml, expose, fetchParameterDefault, findSavedFilter, getDefaultOperator, getDefaultParameterValues, getDynamicValueLabel, getDynamicValuesForField, getLocalizedString, getNodeAtPath, getOperatorArity, getOperatorLabel, getOperatorsForField, getReportExtension, getReportFileName, getReportFormats, getReportMediaType, getReportRequest, getSessionData, getSettings, getUserImage, getValueType, insertNodeAtPath, invariant, isCompleteExpression, isEmptyFilter, isExpression, isGroup, isProcedureDefault, isStandardLayout, localStorage_default as localStorage, localize, logActivity, logError, mitt_default as mitt, normalizeOperator, openAlertDialog, openReport, parseParameterItems, parseParameters, parseRecordSource, partitionSavedFilters, printReport, pruneFilter, readElement, readElements, removeNodeAtPath, renderReport, resolveParameterDefaults, restoreParameterValues, saveSettings, serializeParameters, setGroupMode, startActivity, time, toFieldMetadata, toFieldMetadataList, toFilterFieldType, toFilterTree, toLocalDateTime, toLocalISODate, toLocalISODateTime, toReport, toReportParameter, toReportParameters, toSavedFilter, toSavedFilters, unwrapSingleAndGroup, updateNodeAtPath, version, waitForDialog };
2170
+ export { ConfirmButtons, NO_FILTER_ID, PERIOD_OPERATORS, RELATIVE_DATE_VALUES, SessionHandler, UserSession, addGroupAtPath, alert, canDeleteSavedFilter, canEditSavedFilter, canRenameSavedFilter, canSetCrossDomain, canShareSavedFilter, changeOperator, coerceParameterValue, coerceToStandardLayout, confirm, convertFilter, countExpressions, createEmptyFilter, createEmptyGroup, createExpression, createLocalizer, decodeXml, describeFilter, downloadBlob, downloadReport, downloadRequest, encodeXml, expose, fetchParameterDefault, findSavedFilter, getColumnsForField, getDefaultOperator, getDefaultParameterValues, getDynamicValueLabel, getDynamicValuesForField, getLocalizedString, getNodeAtPath, getOperatorArity, getOperatorLabel, getOperatorsForField, getReportExtension, getReportFileName, getReportFormats, getReportMediaType, getReportRequest, getSessionData, getSettings, getUserImage, getValueType, insertNodeAtPath, invariant, isCompleteExpression, isEmptyFilter, isExpression, isGroup, isProcedureDefault, isRangeEnd, isStandardLayout, localStorage_default as localStorage, localize, logActivity, logError, mitt_default as mitt, needsFilterString, normalizeOperator, openAlertDialog, openReport, parseParameterItems, parseParameters, parseRecordSource, partitionSavedFilters, printReport, pruneFilter, readElement, readElements, removeNodeAtPath, renderReport, resolveParameterDefaults, restoreParameterValues, saveSettings, serializeParameters, setGroupMode, startActivity, supportsColumnValue, time, toFieldMetadata, toFieldMetadataList, toFilterFieldType, toFilterTree, toLocalDateTime, toLocalISODate, toLocalISODateTime, toReport, toReportParameter, toReportParameters, toSavedFilter, toSavedFilters, unwrapSingleAndGroup, updateNodeAtPath, version, waitForDialog };