improve pending visibility, allow multiple users to have pending changes against locos.
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user