@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.
@@ -2,7 +2,7 @@ this.af = this.af || {};
2
2
  this.af.common = (function(exports) {
3
3
 
4
4
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
5
- //#region ../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/dist/mitt.mjs
5
+ // ../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/dist/mitt.mjs
6
6
  function mitt_default(n) {
7
7
  return {
8
8
  all: n = n || /* @__PURE__ */ new Map(),
@@ -25,8 +25,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
25
25
  };
26
26
  }
27
27
 
28
- //#endregion
29
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/typeof.js
28
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/typeof.js
30
29
  function _typeof(o) {
31
30
  "@babel/helpers - typeof";
32
31
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -36,8 +35,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
36
35
  }, _typeof(o);
37
36
  }
38
37
 
39
- //#endregion
40
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPrimitive.js
38
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/toPrimitive.js
41
39
  function toPrimitive(t, r) {
42
40
  if ("object" != _typeof(t) || !t) return t;
43
41
  var e = t[Symbol.toPrimitive];
@@ -49,15 +47,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
49
47
  return ("string" === r ? String : Number)(t);
50
48
  }
51
49
 
52
- //#endregion
53
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/toPropertyKey.js
50
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/toPropertyKey.js
54
51
  function toPropertyKey(t) {
55
52
  var i = toPrimitive(t, "string");
56
53
  return "symbol" == _typeof(i) ? i : i + "";
57
54
  }
58
55
 
59
- //#endregion
60
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/defineProperty.js
56
+ // \0@oxc-project+runtime@0.155.0/helpers/esm/defineProperty.js
61
57
  function _defineProperty(e, r, t) {
62
58
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
63
59
  value: t,
@@ -67,8 +63,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
67
63
  }) : e[r] = t, e;
68
64
  }
69
65
 
70
- //#endregion
71
- //#region src/SessionHandler.ts
66
+ // src/SessionHandler.ts
72
67
  var SessionHandler = class {
73
68
  constructor() {
74
69
  _defineProperty(this, "eventHandler", mitt_default());
@@ -115,8 +110,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
115
110
  }
116
111
  };
117
112
 
118
- //#endregion
119
- //#region src/UserSession.ts
113
+ // src/UserSession.ts
120
114
  var UserSession = class extends SessionHandler {
121
115
  constructor(userData) {
122
116
  super();
@@ -188,8 +182,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
188
182
  }
189
183
  };
190
184
 
191
- //#endregion
192
- //#region src/log.ts
185
+ // src/log.ts
193
186
  const article = window.af?.article?.id ?? window.window?.location.pathname.substring(1).split("/")[0];
194
187
  /**
195
188
  * Logs an activity to the website activity log
@@ -267,6 +260,30 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
267
260
  function getSessionId() {
268
261
  return crypto.randomUUID?.();
269
262
  }
263
+ /** The version in the first URL served under `/lib/@olenbetong/<name>/<version>/`. */
264
+ function libVersion(name, urls) {
265
+ let pattern = new RegExp(`/lib/@olenbetong/${name}/([^/]+)/`);
266
+ for (let url of urls) {
267
+ let match = typeof url === "string" ? pattern.exec(url) : null;
268
+ if (match) return match[1];
269
+ }
270
+ }
271
+ /**
272
+ * The synergi-chrome and synergi-platform versions the page loads on the 2026 site templates,
273
+ * read from the chrome's script tag and the platform import map rather than from the chrome
274
+ * itself, so they are known even when the chrome failed to start. Empty on other pages.
275
+ */
276
+ function getPlatformVersions() {
277
+ let versions = {};
278
+ try {
279
+ let importMap = document.querySelector("script[type=\"importmap\"]");
280
+ let platform = importMap ? libVersion("synergi-platform", Object.values(JSON.parse(importMap.textContent ?? "{}").imports ?? {})) : void 0;
281
+ if (platform) versions["synergi-platform"] = platform;
282
+ } catch {}
283
+ let chrome = libVersion("synergi-chrome", Array.from(document.scripts, (script) => script.src)) ?? window.ob?.chrome?.version;
284
+ if (chrome) versions["synergi-chrome"] = chrome;
285
+ return versions;
286
+ }
270
287
  let sessionStart = Date.now();
271
288
  let sessionId = getSessionId();
272
289
  let deviceId = "";
@@ -275,7 +292,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
275
292
  let startSession = () => logActivity("AfSessionInit", {
276
293
  "appframe-core": window.af?.common?.version,
277
294
  "appframe-data": window.af?.data?.version,
278
- "app-version": window.af?.article?.version
295
+ "app-version": window.af?.article?.version,
296
+ ...getPlatformVersions()
279
297
  });
280
298
  document.addEventListener("DOMContentLoaded", () => {
281
299
  deviceId = localStorage.getItem("_afDeviceId");
@@ -309,15 +327,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
309
327
  };
310
328
  }
311
329
 
312
- //#endregion
313
- //#region src/errorHandler.ts
330
+ // src/errorHandler.ts
314
331
  window.window?.addEventListener("error", (event) => {
315
332
  if (typeof event === "object" && "error" in event) logError(event.error);
316
333
  else if (typeof event === "object" && "message" in event) logError(event);
317
334
  });
318
335
 
319
- //#endregion
320
- //#region src/localStorage.ts
336
+ // src/localStorage.ts
321
337
  function getLocalKey(key) {
322
338
  return [
323
339
  af?.article?.id || "",
@@ -354,8 +370,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
354
370
  };
355
371
  var localStorage_default = new LocalStorage();
356
372
 
357
- //#endregion
358
- //#region src/date.ts
373
+ // src/date.ts
359
374
  function toLocalISODate(date) {
360
375
  return date ? toLocalISODateTime(date).substring(0, 10) : null;
361
376
  }
@@ -378,8 +393,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
378
393
  return date ? date.toISOString().substring(0, 16) : "";
379
394
  }
380
395
 
381
- //#endregion
382
- //#region src/downloadBlob.ts
396
+ // src/downloadBlob.ts
383
397
  function downloadBlob(blob, fileName) {
384
398
  return new Promise((resolve, reject) => {
385
399
  try {
@@ -401,8 +415,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
401
415
  });
402
416
  }
403
417
 
404
- //#endregion
405
- //#region src/invariant.ts
418
+ // src/invariant.ts
406
419
  /**
407
420
  * Throws an error if the condition is falsy. The provided message is used as the error message.
408
421
  * A function can be provided to lazily generate the message.
@@ -417,8 +430,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
417
430
  throw new Error(provided ?? "Invariant failed");
418
431
  }
419
432
 
420
- //#endregion
421
- //#region src/downloadRequest.ts
433
+ // src/downloadRequest.ts
422
434
  async function downloadRequest(request, { fileName, signal, onProgress }) {
423
435
  let bytesReceived = 0;
424
436
  onProgress?.({ status: "requested" });
@@ -472,8 +484,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
472
484
  }
473
485
  }
474
486
 
475
- //#endregion
476
- //#region src/parseFunc.ts
487
+ // src/parseFunc.ts
477
488
  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)*)\}$/;
478
489
  const arrowBlockRegex = /^(?:\(([^)]*)\)|([a-zA-Z$_][a-zA-Z0-9$_]*))\s*=>\s*\{([\s\S]*)\}$/;
479
490
  const arrowExpressionRegex = /^(?:\(([^)]*)\)|([a-zA-Z$_][a-zA-Z0-9$_]*))\s*=>\s*([\s\S]+)$/;
@@ -507,13 +518,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
507
518
  };
508
519
  }
509
520
 
510
- //#endregion
511
- //#region src/Namespace.ts
521
+ // src/Namespace.ts
512
522
  function Namespace() {}
513
523
  Namespace.prototype = Object.create(null);
514
524
 
515
- //#endregion
516
- //#region src/requireNamespace.ts
525
+ // src/requireNamespace.ts
517
526
  function requireNamespace(root, namespace) {
518
527
  if (typeof root === "object") {
519
528
  if (typeof namespace === "string") return requireNamespace(root, namespace.split("."));
@@ -525,8 +534,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
525
534
  }
526
535
  }
527
536
 
528
- //#endregion
529
- //#region src/expose.ts
537
+ // src/expose.ts
530
538
  /**
531
539
  * Expose a value to a potentially deeply nested global variable
532
540
  * @param name {string | object} Either a dot-separated path to the global variable, or an object to expose the value on
@@ -556,8 +564,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
556
564
  }
557
565
  }
558
566
 
559
- //#endregion
560
- //#region src/getLocalizedString.ts
567
+ // src/getLocalizedString.ts
561
568
  async function fetchLocalizedString(text, project) {
562
569
  try {
563
570
  let response = await fetch(`/api/user/localize/new/${encodeURIComponent(project)}`, {
@@ -646,8 +653,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
646
653
  };
647
654
  }
648
655
 
649
- //#endregion
650
- //#region src/filter/operators.ts
656
+ // src/filter/operators.ts
651
657
  /**
652
658
  * Operators that take no value at all.
653
659
  *
@@ -661,6 +667,26 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
661
667
  "isblank",
662
668
  "isnotblank"
663
669
  ];
670
+ /**
671
+ * Whole-period checks for dates, such as "Is last week", in the order of the
672
+ * Windows filter editor. They take no value. The framework has no operator for
673
+ * them, so a filter using one is sent as a filter string (`needsFilterString`).
674
+ */
675
+ const PERIOD_OPERATORS = [
676
+ "isbeyondthisyear",
677
+ "islaterthisyear",
678
+ "islaterthismonth",
679
+ "isnextweek",
680
+ "islaterthisweek",
681
+ "istomorrow",
682
+ "istoday",
683
+ "isyesterday",
684
+ "isearlierthisweek",
685
+ "islastweek",
686
+ "isearlierthismonth",
687
+ "isearlierthisyear",
688
+ "ispriorthisyear"
689
+ ];
664
690
  /** Operators whose value is a two element `[from, to]` array. */
665
691
  const PAIR_OPERATORS = [
666
692
  "between",
@@ -671,7 +697,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
671
697
  /** Operators whose value is an array of values. */
672
698
  const LIST_OPERATORS = ["inlist", "notinlist"];
673
699
  function getOperatorArity(operator) {
674
- if (PARAMETERLESS_OPERATORS.includes(operator)) return "none";
700
+ if (PARAMETERLESS_OPERATORS.includes(operator) || PERIOD_OPERATORS.includes(operator)) return "none";
675
701
  if (PAIR_OPERATORS.includes(operator)) return "pair";
676
702
  if (LIST_OPERATORS.includes(operator)) return "list";
677
703
  return "single";
@@ -714,7 +740,20 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
714
740
  datelessthan: "Before",
715
741
  datelessthanorequal: "Up to",
716
742
  datebetween: "Between",
717
- datenotbetween: "Not between"
743
+ datenotbetween: "Not between",
744
+ isbeyondthisyear: "Is beyond this year",
745
+ islaterthisyear: "Is later this year",
746
+ islaterthismonth: "Is later this month",
747
+ isnextweek: "Is next week",
748
+ islaterthisweek: "Is later this week",
749
+ istomorrow: "Is tomorrow",
750
+ istoday: "Is today",
751
+ isyesterday: "Is yesterday",
752
+ isearlierthisweek: "Is earlier this week",
753
+ islastweek: "Is last week",
754
+ isearlierthismonth: "Is earlier this month",
755
+ isearlierthisyear: "Is earlier this year",
756
+ ispriorthisyear: "Is prior to this year"
718
757
  };
719
758
  /** Comparison operator labels used for date and time fields. */
720
759
  const DATE_OPERATOR_LABELS = {
@@ -759,13 +798,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
759
798
  ...EQUALITY,
760
799
  ...LIST_CHECKS,
761
800
  ...RANGE,
762
- ...COMPARISONS
801
+ ...COMPARISONS,
802
+ ...PERIOD_OPERATORS
763
803
  ],
764
804
  datetime: [
765
805
  ...EQUALITY,
766
806
  ...LIST_CHECKS,
767
807
  ...RANGE,
768
- ...COMPARISONS
808
+ ...COMPARISONS,
809
+ ...PERIOD_OPERATORS
769
810
  ],
770
811
  number: [
771
812
  ...EQUALITY,
@@ -838,7 +879,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
838
879
  const RELATIVE_DATE_VALUES = [
839
880
  "Yesterday",
840
881
  "Today",
882
+ "Now",
841
883
  "Tomorrow",
884
+ "DayAfterTomorrow",
885
+ "TwoWeeksAway",
842
886
  "ThisWeek",
843
887
  "ThisMonth",
844
888
  "ThisYear",
@@ -853,7 +897,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
853
897
  CurrentUser: "Current user",
854
898
  Yesterday: "Yesterday",
855
899
  Today: "Today",
900
+ Now: "Now",
856
901
  Tomorrow: "Tomorrow",
902
+ DayAfterTomorrow: "Day after tomorrow",
903
+ TwoWeeksAway: "Two weeks away",
857
904
  ThisWeek: "This week",
858
905
  ThisMonth: "This month",
859
906
  ThisYear: "This year",
@@ -889,6 +936,30 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
889
936
  if (field.type === "string") return ["CurrentUser"];
890
937
  return [];
891
938
  }
939
+ /** Operators that can compare a field with another column. */
940
+ const COLUMN_OPERATORS = [
941
+ ...EQUALITY,
942
+ ...RANGE,
943
+ ...COMPARISONS
944
+ ];
945
+ /** Whether an operator can take another column as its value. */
946
+ function supportsColumnValue(operator) {
947
+ return COLUMN_OPERATORS.includes(operator);
948
+ }
949
+ /** Dates and datetimes compare with each other; other types only with their own. */
950
+ function getComparableType(type) {
951
+ return type === "datetime" ? "date" : type;
952
+ }
953
+ /**
954
+ * The columns a field can be compared with: the other fields of the same type,
955
+ * as in the Windows filter editor. Booleans have only true and false checks,
956
+ * so they get none.
957
+ */
958
+ function getColumnsForField(field, fields) {
959
+ if (field.type === "boolean") return [];
960
+ let type = getComparableType(field.type);
961
+ return fields.filter((other) => other.name !== field.name && !other.excludeFromFilter && getComparableType(other.type) === type);
962
+ }
892
963
  /**
893
964
  * Aliases for names `eOperators.ToString()` can produce that are not operators
894
965
  * in their own right. `Not` is the bare negation flag (i.e. "not equal to"),
@@ -912,8 +983,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
912
983
  return OPERATOR_ALIASES[normalized] ?? normalized;
913
984
  }
914
985
 
915
- //#endregion
916
- //#region src/filter/tree.ts
986
+ // src/filter/tree.ts
917
987
  /**
918
988
  * Creates the default empty filter: a single `and` group with no conditions.
919
989
  */
@@ -1000,10 +1070,40 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1000
1070
  let arity = getOperatorArity(normalizeOperator(item.operator));
1001
1071
  if (arity === "none") return true;
1002
1072
  if (item.value === null || item.value === void 0 || item.value === "") return false;
1003
- if (arity === "pair") return Array.isArray(item.value) && item.value.length === 2 && item.value.every((v) => v !== "" && v != null);
1073
+ if (arity === "pair") return Array.isArray(item.value) && item.value.length === 2 && item.value.every((v) => {
1074
+ let end = isRangeEnd(v) ? v.value : v;
1075
+ return end !== "" && end != null;
1076
+ });
1004
1077
  if (arity === "list") return Array.isArray(item.value) && item.value.length > 0;
1005
1078
  return true;
1006
1079
  }
1080
+ /** Whether a range value end is a `FilterRangeEnd` rather than a plain value. */
1081
+ function isRangeEnd(value) {
1082
+ return typeof value === "object" && value !== null && !(value instanceof Date) && "valueType" in value;
1083
+ }
1084
+ /** Dynamic values the framework has no `eDynamicValue` member for. */
1085
+ const DYNAMIC_VALUES_WITHOUT_FRAMEWORK_SUPPORT = /* @__PURE__ */ new Set([
1086
+ "Now",
1087
+ "DayAfterTomorrow",
1088
+ "TwoWeeksAway"
1089
+ ]);
1090
+ function needsConversion(valueType, value) {
1091
+ if (valueType === "column") return true;
1092
+ return valueType === "special" && typeof value === "string" && DYNAMIC_VALUES_WITHOUT_FRAMEWORK_SUPPORT.has(value);
1093
+ }
1094
+ /**
1095
+ * True when the filter holds something the framework's data API cannot read
1096
+ * from a filter object: another column, a range end that is not a plain value,
1097
+ * one of the dates only the Windows editor offers, or a whole-period check. Such a filter must be
1098
+ * converted with `convertFilter` and sent as a filter string.
1099
+ */
1100
+ function needsFilterString(filter) {
1101
+ if (!filter) return false;
1102
+ if (isGroup(filter)) return filter.items.some(needsFilterString);
1103
+ if (PERIOD_OPERATORS.includes(normalizeOperator(filter.operator))) return true;
1104
+ if (needsConversion(filter.valueType, filter.value)) return true;
1105
+ return Array.isArray(filter.value) && filter.value.some((item) => isRangeEnd(item));
1106
+ }
1007
1107
  /**
1008
1108
  * Creates an expression for a field, using the field's default operator and an
1009
1109
  * empty value of the right shape.
@@ -1034,8 +1134,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1034
1134
  let previousArity = getOperatorArity(normalizeOperator(expression.operator));
1035
1135
  let arity = getOperatorArity(operator);
1036
1136
  let value = expression.value;
1037
- if (arity !== previousArity) value = createEmptyValue(operator);
1038
- let valueType = expression.valueType === "special" && arity === previousArity ? "special" : getValueType(field, operator);
1137
+ let holdsColumn = expression.valueType === "column" || Array.isArray(value) && value.some((item) => isRangeEnd(item) && item.valueType === "column");
1138
+ if (arity !== previousArity || holdsColumn && !supportsColumnValue(operator)) value = createEmptyValue(operator);
1139
+ let valueType = (expression.valueType === "special" || expression.valueType === "column") && value === expression.value ? expression.valueType : getValueType(field, operator);
1039
1140
  return {
1040
1141
  ...expression,
1041
1142
  operator,
@@ -1101,8 +1202,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1101
1202
  return insertNodeAtPath(filter, path, createEmptyGroup(parent && isGroup(parent) && parent.mode === "and" ? "or" : "and"));
1102
1203
  }
1103
1204
 
1104
- //#endregion
1105
- //#region src/filter/convertFilter.ts
1205
+ // src/filter/convertFilter.ts
1106
1206
  const CONVERT_URL = "/api/filter/convert";
1107
1207
  /**
1108
1208
  * Converts between a structured filter and a DevExpress filter string.
@@ -1127,8 +1227,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1127
1227
  };
1128
1228
  }
1129
1229
 
1130
- //#endregion
1131
- //#region src/filter/describeFilter.ts
1230
+ // src/filter/describeFilter.ts
1132
1231
  /**
1133
1232
  * Builds a human-readable description of a filter, without contacting the
1134
1233
  * server. Use this for read-only summaries; the authoritative filter string is
@@ -1156,18 +1255,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1156
1255
  let label = getOperatorLabel(operator, field?.type);
1157
1256
  let arity = getOperatorArity(operator);
1158
1257
  if (arity === "none") return `[${caption}] ${label}`;
1159
- return `[${caption}] ${label} ${formatValue(expression, arity)}`;
1258
+ return `[${caption}] ${label} ${formatValue(expression, arity, fields)}`;
1160
1259
  }
1161
- function formatValue(expression, arity) {
1260
+ function formatValue(expression, arity, fields) {
1162
1261
  let { value, valueType } = expression;
1163
- if (valueType === "special" && typeof value === "string") return getDynamicValueLabel(value);
1164
1262
  if (Array.isArray(value)) {
1165
- let formatted = value.map((item) => formatScalar(item, valueType));
1263
+ let formatted = value.map((item) => isRangeEnd(item) ? formatScalar(item.value, item.valueType, fields) : formatScalar(item, valueType, fields));
1166
1264
  return arity === "pair" ? formatted.join(" - ") : `(${formatted.join(", ")})`;
1167
1265
  }
1168
- return formatScalar(value, valueType);
1266
+ return formatScalar(value, valueType, fields);
1169
1267
  }
1170
- function formatScalar(value, valueType) {
1268
+ function formatScalar(value, valueType, fields) {
1269
+ if (valueType === "special" && typeof value === "string") return getDynamicValueLabel(value);
1270
+ if (valueType === "column" && typeof value === "string") return `[${fields.get(value.toLowerCase())?.caption ?? value}]`;
1171
1271
  if (value === null || value === void 0) return "";
1172
1272
  if (value instanceof Date) return value.toISOString().slice(0, 10);
1173
1273
  if (typeof value === "number" || typeof value === "boolean") return String(value);
@@ -1175,8 +1275,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1175
1275
  return `'${String(value)}'`;
1176
1276
  }
1177
1277
 
1178
- //#endregion
1179
- //#region src/filter/fields.ts
1278
+ // src/filter/fields.ts
1180
1279
  const FIELD_TYPES = [
1181
1280
  "string",
1182
1281
  "number",
@@ -1211,8 +1310,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1211
1310
  return records.map(toFieldMetadata).filter((field) => field.name !== "" && !field.excludeFromFilter).sort((a, b) => a.name.localeCompare(b.name));
1212
1311
  }
1213
1312
 
1214
- //#endregion
1215
- //#region src/filter/standardLayout.ts
1313
+ // src/filter/standardLayout.ts
1216
1314
  /**
1217
1315
  * The "standard layout" is the simplified shape the Windows filter editor can
1218
1316
  * render in its flow view: an outer `or` group whose items are `and` groups of
@@ -1294,8 +1392,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1294
1392
  for (let child of item.items) collectExpressions(child, into);
1295
1393
  }
1296
1394
 
1297
- //#endregion
1298
- //#region src/filter/savedFilters.ts
1395
+ // src/filter/savedFilters.ts
1299
1396
  /**
1300
1397
  * `sviw_Database_MyFilters` unions in a synthetic "No Filter" row so the Windows
1301
1398
  * tree can render a "no filter" entry. It is not a real filter and must be
@@ -1394,8 +1491,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1394
1491
  */
1395
1492
  const canSetCrossDomain = canRenameSavedFilter;
1396
1493
 
1397
- //#endregion
1398
- //#region src/getUserImage.ts
1494
+ // src/getUserImage.ts
1399
1495
  const sizeMap = {
1400
1496
  xs: 64,
1401
1497
  sm: 128,
@@ -1410,8 +1506,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1410
1506
  return `/api/data/blob/EmployeesLookup/${primKeyOrOptions}/Image/${encodeURIComponent(login ?? "")}${login ? "." : ""}${encodeURIComponent(hash)}.jpg${sizePx ? `?width=${sizePx}` : ""}`;
1411
1507
  }
1412
1508
 
1413
- //#endregion
1414
- //#region src/localize.ts
1509
+ // src/localize.ts
1415
1510
  /**
1416
1511
  * Localization function for tagged templates. Replaces the arguments
1417
1512
  * with $n, where n is the index, before asking Appframe to translate
@@ -1435,8 +1530,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1435
1530
  return localized;
1436
1531
  }
1437
1532
 
1438
- //#endregion
1439
- //#region src/report/recordSource.ts
1533
+ // src/report/recordSource.ts
1440
1534
  const XML_ENTITIES = {
1441
1535
  amp: "&",
1442
1536
  lt: "<",
@@ -1522,8 +1616,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1522
1616
  };
1523
1617
  }
1524
1618
 
1525
- //#endregion
1526
- //#region src/report/parameters.ts
1619
+ // src/report/parameters.ts
1527
1620
  /**
1528
1621
  * Report parameters: mapping the metadata records onto something renderable,
1529
1622
  * and the XML the parameter values are stored as on a saved filter.
@@ -1676,8 +1769,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1676
1769
  return values;
1677
1770
  }
1678
1771
 
1679
- //#endregion
1680
- //#region src/report/parameterDefaults.ts
1772
+ // src/report/parameterDefaults.ts
1681
1773
  /**
1682
1774
  * Resolving report parameter defaults that name a stored procedure.
1683
1775
  *
@@ -1739,8 +1831,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1739
1831
  return row;
1740
1832
  }
1741
1833
 
1742
- //#endregion
1743
- //#region src/report/render.ts
1834
+ // src/report/render.ts
1744
1835
  /**
1745
1836
  * Rendering a report through the framework's report route.
1746
1837
  *
@@ -1944,8 +2035,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1944
2035
  }));
1945
2036
  }
1946
2037
 
1947
- //#endregion
1948
- //#region src/report/report.ts
2038
+ // src/report/report.ts
1949
2039
  /**
1950
2040
  * Mapping a `sviw_WinClient_MyReports` record onto the report model, including
1951
2041
  * which output formats the report offers.
@@ -1989,8 +2079,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
1989
2079
  };
1990
2080
  }
1991
2081
 
1992
- //#endregion
1993
- //#region src/alert.ts
2082
+ // src/alert.ts
1994
2083
  const template = `
1995
2084
  <dialog class="alert-dialog">
1996
2085
  <form method="dialog">
@@ -2101,8 +2190,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2101
2190
  });
2102
2191
  }
2103
2192
 
2104
- //#endregion
2105
- //#region src/settings.ts
2193
+ // src/settings.ts
2106
2194
  function getKey(article) {
2107
2195
  return `${article ?? window.af?.article?.id ?? window.window?.location.pathname.substring(1).split("/")[0]}.${window.af?.userSession.login ?? "anonymous"}`;
2108
2196
  }
@@ -2122,13 +2210,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2122
2210
  localStorage.setItem(key, JSON.stringify(userSettings));
2123
2211
  }
2124
2212
 
2125
- //#endregion
2126
- //#region src/index.ts
2127
- const version = "2.15.1";
2213
+ // src/index.ts
2214
+ const version = "2.15.2";
2128
2215
 
2129
- //#endregion
2130
2216
  exports.ConfirmButtons = ConfirmButtons;
2131
2217
  exports.NO_FILTER_ID = NO_FILTER_ID;
2218
+ exports.PERIOD_OPERATORS = PERIOD_OPERATORS;
2132
2219
  exports.RELATIVE_DATE_VALUES = RELATIVE_DATE_VALUES;
2133
2220
  exports.SessionHandler = SessionHandler;
2134
2221
  exports.UserSession = UserSession;
@@ -2158,6 +2245,7 @@ exports.encodeXml = encodeXml;
2158
2245
  exports.expose = expose;
2159
2246
  exports.fetchParameterDefault = fetchParameterDefault;
2160
2247
  exports.findSavedFilter = findSavedFilter;
2248
+ exports.getColumnsForField = getColumnsForField;
2161
2249
  exports.getDefaultOperator = getDefaultOperator;
2162
2250
  exports.getDefaultParameterValues = getDefaultParameterValues;
2163
2251
  exports.getDynamicValueLabel = getDynamicValueLabel;
@@ -2183,12 +2271,14 @@ exports.isEmptyFilter = isEmptyFilter;
2183
2271
  exports.isExpression = isExpression;
2184
2272
  exports.isGroup = isGroup;
2185
2273
  exports.isProcedureDefault = isProcedureDefault;
2274
+ exports.isRangeEnd = isRangeEnd;
2186
2275
  exports.isStandardLayout = isStandardLayout;
2187
2276
  exports.localStorage = localStorage_default;
2188
2277
  exports.localize = localize;
2189
2278
  exports.logActivity = logActivity;
2190
2279
  exports.logError = logError;
2191
2280
  exports.mitt = mitt_default;
2281
+ exports.needsFilterString = needsFilterString;
2192
2282
  exports.normalizeOperator = normalizeOperator;
2193
2283
  exports.openAlertDialog = openAlertDialog;
2194
2284
  exports.openReport = openReport;
@@ -2208,6 +2298,7 @@ exports.saveSettings = saveSettings;
2208
2298
  exports.serializeParameters = serializeParameters;
2209
2299
  exports.setGroupMode = setGroupMode;
2210
2300
  exports.startActivity = startActivity;
2301
+ exports.supportsColumnValue = supportsColumnValue;
2211
2302
  exports.time = time;
2212
2303
  exports.toFieldMetadata = toFieldMetadata;
2213
2304
  exports.toFieldMetadataList = toFieldMetadataList;