improve pending visibility, allow multiple users to have pending changes against locos.

This commit is contained in:
2026-01-12 16:16:36 +00:00
parent 45042b5001
commit e9b328e7e6

View File

@@ -716,9 +716,14 @@ bool _isOverlappingStart(LocoAttrVersion entry, Set<int> approvedStartKeys) {
List<_ValueSegment> _segmentsForEntries( List<_ValueSegment> _segmentsForEntries(
List<LocoAttrVersion> items, List<LocoAttrVersion> items,
DateTime now, DateTime now, {
) { bool? clampToNextStart,
}) {
if (items.isEmpty) return const []; if (items.isEmpty) return const [];
final hasPending = items.any((e) => e.isPending);
final hasApproved = items.any((e) => !e.isPending);
final shouldClamp =
clampToNextStart ?? (hasPending && hasApproved);
final sorted = [...items]; final sorted = [...items];
sorted.sort( sorted.sort(
(a, b) => (_effectiveStart(a) ?? now) (a, b) => (_effectiveStart(a) ?? now)
@@ -731,7 +736,13 @@ List<_ValueSegment> _segmentsForEntries(
final nextStart = i < sorted.length - 1 final nextStart = i < sorted.length - 1
? _effectiveStart(sorted[i + 1]) ? _effectiveStart(sorted[i + 1])
: null; : null;
final rawEnd = entry.validTo ?? nextStart ?? now; DateTime? rawEnd = entry.validTo;
if (nextStart != null) {
if (rawEnd == null || (shouldClamp && nextStart.isBefore(rawEnd))) {
rawEnd = nextStart;
}
}
rawEnd ??= now;
final end = _safeEnd(start, rawEnd); final end = _safeEnd(start, rawEnd);
segments.add( segments.add(
_ValueSegment( _ValueSegment(
@@ -745,6 +756,53 @@ List<_ValueSegment> _segmentsForEntries(
return segments; return segments;
} }
List<LocoAttrVersion> _applyPendingOverrides(
List<LocoAttrVersion> approved,
List<LocoAttrVersion> pending,
) {
if (pending.isEmpty) return approved;
final pendingByStart = <int, LocoAttrVersion>{};
final extraPending = <LocoAttrVersion>[];
for (final entry in pending) {
final start = _effectiveStart(entry);
if (start == null) continue;
final key = _startKey(start);
pendingByStart[key] = entry;
}
final applied = <LocoAttrVersion>[];
final seenKeys = <int>{};
for (final entry in approved) {
final start = _effectiveStart(entry);
if (start == null) continue;
final key = _startKey(start);
if (pendingByStart.containsKey(key)) {
if (!seenKeys.contains(key)) {
applied.add(pendingByStart[key]!);
seenKeys.add(key);
}
} else {
applied.add(entry);
seenKeys.add(key);
}
}
for (final entry in pendingByStart.values) {
final start = _effectiveStart(entry);
if (start == null) continue;
final key = _startKey(start);
if (!seenKeys.contains(key)) {
extraPending.add(entry);
seenKeys.add(key);
}
}
if (extraPending.isNotEmpty) {
applied.addAll(extraPending);
}
return applied;
}
List<DateTime> _buildBoundaries( List<DateTime> _buildBoundaries(
List<_ValueSegment> segments, List<_ValueSegment> segments,
DateTime now, DateTime now,
@@ -904,14 +962,17 @@ class _TimelineModel {
} }
final hasOverlap = overlapByUser.isNotEmpty; final hasOverlap = overlapByUser.isNotEmpty;
final canToggle = pending.length > 1 && !hasOverlap; final canToggle = pending.isNotEmpty && !hasOverlap;
final isExpanded = expandedAttrCodes.contains(attr); final isExpanded = expandedAttrCodes.contains(attr);
final shouldShowPendingRows = isExpanded || hasOverlap;
final nonOverlapPending = final nonOverlapPending =
pending.where((e) => !_isOverlappingStart(e, approvedStartKeys)).toList(); pending.where((e) => !_isOverlappingStart(e, approvedStartKeys)).toList();
final baseEntries = isExpanded ? approved : [...approved, ...nonOverlapPending]; final baseEntries =
final baseSegments = shouldShowPendingRows ? approved : [...approved, ...nonOverlapPending];
isExpanded ? approvedSegments : _segmentsForEntries(baseEntries, now); final baseSegments = shouldShowPendingRows
? approvedSegments
: _segmentsForEntries(baseEntries, now);
rowSpecs.add( rowSpecs.add(
_TimelineRowSpec.primary( _TimelineRowSpec.primary(
@@ -923,7 +984,6 @@ class _TimelineModel {
); );
allSegments.addAll(baseSegments); allSegments.addAll(baseSegments);
final shouldShowPendingRows = isExpanded || hasOverlap;
if (shouldShowPendingRows) { if (shouldShowPendingRows) {
final users = isExpanded final users = isExpanded
? pendingByUser.keys.toList() ? pendingByUser.keys.toList()
@@ -934,11 +994,9 @@ class _TimelineModel {
? (pendingByUser[user] ?? const []) ? (pendingByUser[user] ?? const [])
: (overlapByUser[user] ?? const []); : (overlapByUser[user] ?? const []);
if (pendingEntries.isEmpty) continue; if (pendingEntries.isEmpty) continue;
final userPendingSegments = _segmentsForEntries(pendingEntries, now); final appliedEntries =
final combinedSegments = [ _applyPendingOverrides(approved, pendingEntries);
...approvedSegments, final combinedSegments = _segmentsForEntries(appliedEntries, now);
...userPendingSegments,
];
rowSpecs.add( rowSpecs.add(
_TimelineRowSpec.pending( _TimelineRowSpec.pending(
attrCode: attr, attrCode: attr,