@outbuild-company/schedule-core 1.35.3 → 1.37.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.
package/dist/index.cjs CHANGED
@@ -2306,24 +2306,37 @@ function toLevelWindow(input) {
2306
2306
  return { startLevel, depth: input.depth };
2307
2307
  }
2308
2308
  var INVALID_CRITERION = /* @__PURE__ */ Symbol("invalid-group-criterion");
2309
- function toSecondaryCriterion(input) {
2310
- const secondary = input.secondary;
2311
- if (secondary === void 0 || secondary === null) return null;
2312
- if (typeof secondary !== "object") return INVALID_CRITERION;
2313
- if (typeof secondary.attributeKey !== "string" || secondary.attributeKey.length === 0) {
2309
+ var MAX_NESTED_GROUP_CRITERIA = 3;
2310
+ function toNestedCriterion(input, usedKeys) {
2311
+ if (typeof input !== "object" || input === null) return INVALID_CRITERION;
2312
+ if (typeof input.attributeKey !== "string" || input.attributeKey.length === 0) {
2314
2313
  return INVALID_CRITERION;
2315
2314
  }
2316
- if (secondary.attributeKey === input.attributeKey) return INVALID_CRITERION;
2317
- const window2 = toLevelWindow(secondary);
2315
+ if (usedKeys.has(input.attributeKey)) return INVALID_CRITERION;
2316
+ const window2 = toLevelWindow(input);
2318
2317
  if (window2 === null) return INVALID_CRITERION;
2319
- if (!isValidDirection(secondary.direction)) return INVALID_CRITERION;
2318
+ if (!isValidDirection(input.direction)) return INVALID_CRITERION;
2320
2319
  return {
2321
- attributeKey: secondary.attributeKey,
2320
+ attributeKey: input.attributeKey,
2322
2321
  startLevel: window2.startLevel,
2323
2322
  depth: window2.depth,
2324
- direction: secondary.direction
2323
+ direction: input.direction
2325
2324
  };
2326
2325
  }
2326
+ function toNestedCriteria(input, primaryKey) {
2327
+ const rawNested = input.nested ?? (input.secondary == null ? [] : [input.secondary]);
2328
+ if (!Array.isArray(rawNested)) return INVALID_CRITERION;
2329
+ if (rawNested.length > MAX_NESTED_GROUP_CRITERIA) return INVALID_CRITERION;
2330
+ const usedKeys = /* @__PURE__ */ new Set([primaryKey]);
2331
+ const nested = [];
2332
+ for (const rawCriterion of rawNested) {
2333
+ const criterion = toNestedCriterion(rawCriterion, usedKeys);
2334
+ if (criterion === INVALID_CRITERION) return INVALID_CRITERION;
2335
+ usedKeys.add(criterion.attributeKey);
2336
+ nested.push(criterion);
2337
+ }
2338
+ return nested;
2339
+ }
2327
2340
  function toGroupState(input) {
2328
2341
  if (typeof input.attributeKey !== "string" || input.attributeKey.length === 0) {
2329
2342
  return null;
@@ -2337,8 +2350,8 @@ function toGroupState(input) {
2337
2350
  if (!Array.isArray(input.collapsedIds) || input.collapsedIds.some((id) => typeof id !== "string")) {
2338
2351
  return null;
2339
2352
  }
2340
- const secondary = toSecondaryCriterion(input);
2341
- if (secondary === INVALID_CRITERION) return null;
2353
+ const nested = toNestedCriteria(input, input.attributeKey);
2354
+ if (nested === INVALID_CRITERION) return null;
2342
2355
  return {
2343
2356
  attributeKey: input.attributeKey,
2344
2357
  startLevel: window2.startLevel,
@@ -2346,7 +2359,7 @@ function toGroupState(input) {
2346
2359
  direction: input.direction,
2347
2360
  includeWbs: input.includeWbs,
2348
2361
  collapsedIds: new Set(input.collapsedIds),
2349
- secondary
2362
+ nested
2350
2363
  };
2351
2364
  }
2352
2365
  function emptyViewChanges(action) {
@@ -8212,25 +8225,39 @@ function getVisibleBaseline(activity) {
8212
8225
  return points.find((point) => point.isVisibleVersion) ?? null;
8213
8226
  }
8214
8227
 
8215
- // src/columns/baseline-variance/compute.ts
8228
+ // src/columns/baseline-variance/baseline-variance-days.ts
8216
8229
  var VARIANCE_DECIMAL_SCALE = 100;
8217
8230
  var roundToVariancePrecision = (days) => Math.round(days * VARIANCE_DECIMAL_SCALE) / VARIANCE_DECIMAL_SCALE;
8218
- function varianceDaysForBaselineEnd(activity, baselineEnd, calendars, hoursPerDay) {
8219
- if (hoursPerDay <= 0) return null;
8220
- const activityEnd = activity.endDate;
8221
- if (!baselineEnd || !activityEnd) return null;
8222
- const finishesLate = activityEnd.getTime() > baselineEnd.getTime();
8223
- const finishesEarly = baselineEnd.getTime() > activityEnd.getTime();
8231
+ function baselineVarianceDays(input) {
8232
+ const { endDate, baselineEnd, calendar, hoursPerDay } = input;
8233
+ const hasUsableHoursPerDay = Number.isFinite(hoursPerDay) && hoursPerDay > 0;
8234
+ if (!hasUsableHoursPerDay) return null;
8235
+ if (!baselineEnd || !endDate) return null;
8236
+ const hasValidDates = Number.isFinite(endDate.getTime()) && Number.isFinite(baselineEnd.getTime());
8237
+ if (!hasValidDates) return null;
8238
+ const finishesLate = endDate.getTime() > baselineEnd.getTime();
8239
+ const finishesEarly = baselineEnd.getTime() > endDate.getTime();
8224
8240
  if (!finishesLate && !finishesEarly) return 0;
8225
- const durationHours = calendars.calculateDuration({
8226
- startDate: finishesLate ? baselineEnd : activityEnd,
8227
- endDate: finishesLate ? activityEnd : baselineEnd,
8228
- task: activity
8229
- });
8241
+ const durationHours = calendar.calculateDuration(
8242
+ finishesLate ? baselineEnd : endDate,
8243
+ finishesLate ? endDate : baselineEnd
8244
+ );
8230
8245
  const magnitude = roundToVariancePrecision(durationHours / hoursPerDay);
8231
8246
  if (magnitude === 0) return 0;
8232
8247
  return finishesLate ? magnitude : -magnitude;
8233
8248
  }
8249
+
8250
+ // src/columns/baseline-variance/compute.ts
8251
+ function varianceDaysForBaselineEnd(activity, baselineEnd, calendars, hoursPerDay) {
8252
+ return baselineVarianceDays({
8253
+ endDate: activity.endDate,
8254
+ baselineEnd,
8255
+ calendar: {
8256
+ calculateDuration: (startDate, endDate) => calendars.calculateDuration({ startDate, endDate, task: activity })
8257
+ },
8258
+ hoursPerDay
8259
+ });
8260
+ }
8234
8261
  function computeBaselineVarianceDays(activity, calendars, hoursPerDay) {
8235
8262
  return varianceDaysForBaselineEnd(
8236
8263
  activity,
@@ -25888,7 +25915,7 @@ function emitActivities(node, context) {
25888
25915
  });
25889
25916
  }
25890
25917
  }
25891
- function emitNode(node, childDirection, allowSecondary, context) {
25918
+ function emitNode(node, childDirection, nextNestedIndex, context) {
25892
25919
  const { group, rows } = context;
25893
25920
  rows.push({
25894
25921
  kind: VISUAL_ROW_KIND.GROUP,
@@ -25900,20 +25927,24 @@ function emitNode(node, childDirection, allowSecondary, context) {
25900
25927
  });
25901
25928
  if (group.collapsedIds.has(node.id)) return;
25902
25929
  for (const child of sortedChildNodes(node, childDirection)) {
25903
- emitNode(child, childDirection, allowSecondary, context);
25930
+ emitNode(child, childDirection, nextNestedIndex, context);
25904
25931
  }
25905
25932
  if (node.activities.length === 0) return;
25906
- const secondary = group.secondary;
25907
- if (allowSecondary && secondary != null && context.secondaryCatalog != null) {
25908
- const secondaryRoot = buildGroupTree(
25933
+ const nestedCriterion = group.nested[nextNestedIndex];
25934
+ const nestedCatalog = context.nestedCatalogs[nextNestedIndex] ?? null;
25935
+ if (nestedCriterion != null && nestedCatalog != null) {
25936
+ const nestedRoot = buildGroupTree(
25909
25937
  node.activities,
25910
- secondary,
25911
- context.secondaryCatalog,
25938
+ nestedCriterion,
25939
+ nestedCatalog,
25912
25940
  createNode(node.id, "", "", null, node.level, 0),
25913
25941
  true
25914
25942
  );
25915
- for (const child of sortedChildNodes(secondaryRoot, secondary.direction)) {
25916
- emitNode(child, secondary.direction, false, context);
25943
+ for (const child of sortedChildNodes(
25944
+ nestedRoot,
25945
+ nestedCriterion.direction
25946
+ )) {
25947
+ emitNode(child, nestedCriterion.direction, nextNestedIndex + 1, context);
25917
25948
  }
25918
25949
  return;
25919
25950
  }
@@ -25956,11 +25987,11 @@ function projectVisualRows(input) {
25956
25987
  comparator: input.comparator,
25957
25988
  orderMode: input.orderMode,
25958
25989
  wbsDepth: input.wbsDepth,
25959
- secondaryCatalog: input.secondaryCatalog,
25990
+ nestedCatalogs: input.nestedCatalogs,
25960
25991
  rows
25961
25992
  };
25962
25993
  for (const child of sortedChildNodes(root, group.direction)) {
25963
- emitNode(child, group.direction, true, context);
25994
+ emitNode(child, group.direction, 0, context);
25964
25995
  }
25965
25996
  return rows;
25966
25997
  }
@@ -26366,7 +26397,9 @@ var ScheduleState = class _ScheduleState {
26366
26397
  if (this._cache.visualRows) return this._cache.visualRows;
26367
26398
  const group = this._viewAttributes.getGroup();
26368
26399
  const catalog = group === null ? null : this._viewAttributes.getCatalog(group.attributeKey);
26369
- const secondaryCatalog = group?.secondary == null ? null : this._viewAttributes.getCatalog(group.secondary.attributeKey);
26400
+ const nestedCatalogs = group === null ? [] : group.nested.map(
26401
+ (criterion) => this._viewAttributes.getCatalog(criterion.attributeKey)
26402
+ );
26370
26403
  const activitiesInVisualOrder = [];
26371
26404
  for (const activityId of this.getVisualOrderIds()) {
26372
26405
  const activity = this.getActivity(activityId);
@@ -26379,7 +26412,7 @@ var ScheduleState = class _ScheduleState {
26379
26412
  hasChildren: (activityId) => this.hasChildren(activityId),
26380
26413
  group,
26381
26414
  catalog,
26382
- secondaryCatalog,
26415
+ nestedCatalogs,
26383
26416
  comparator: this.getOrderComparator(),
26384
26417
  orderMode: this.getOrderMode(),
26385
26418
  wbsDepth: this._viewAttributes.getWbsDepth()
@@ -38168,6 +38201,7 @@ exports.WORK_TIME_DIRECTION = WORK_TIME_DIRECTION;
38168
38201
  exports.activityBackendRow = activityBackendRow;
38169
38202
  exports.allowedSecondaryConstraintTypes = allowedSecondaryConstraintTypes;
38170
38203
  exports.appendGroupRowId = appendGroupRowId;
38204
+ exports.baselineVarianceDays = baselineVarianceDays;
38171
38205
  exports.buildGroupRowId = buildGroupRowId;
38172
38206
  exports.checkNoUpdatedLinks = checkNoUpdatedLinks;
38173
38207
  exports.computeExpectedProgress = computeExpectedProgress;
@@ -38182,6 +38216,7 @@ exports.expectedProgressFromBaseline = expectedProgressFromBaseline;
38182
38216
  exports.formatUtcAsP6WallDate = formatUtcAsP6WallDate;
38183
38217
  exports.getActiveBaseline = getActiveBaseline;
38184
38218
  exports.getUnsavedActivities = getUnsavedActivities;
38219
+ exports.getVisibleBaseline = getVisibleBaseline;
38185
38220
  exports.hostScheduleInput = hostScheduleInput;
38186
38221
  exports.isRestorableActivityField = isRestorableActivityField;
38187
38222
  exports.isRevertibleActivityField = isRevertibleActivityField;