Skip to content

Commit 8bc8537

Browse files
committed
Addresses all remaining findings from the second review pass plus one issue found during live testing
1 parent 193d59c commit 8bc8537

9 files changed

Lines changed: 65 additions & 11 deletions

File tree

ui/modules/things/subDiff.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
~
1111
~ SPDX-License-Identifier: EPL-2.0
1212
-->
13-
<div class="tab-pane fade container no-margin" style="height: 100%; position: relative;">
13+
<div class="tab-pane container no-margin" style="height: 100%; position: relative;">
1414
<div class="sub-diff-container" style="position: absolute; top: 0; bottom: 0; left: 0; right: 0;"></div>
1515
</div>

ui/modules/things/thingUpdates.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ <h5 data-bs-toggle="collapse" data-bs-target="#collapseThingUpdates">
6666
<button class="btn btn-outline-secondary btn-sm rev-action-btn" id="buttonFromOldestTimestamp"
6767
data-bs-toggle="tooltip" title="Set to oldest available timestamp">Oldest</button>
6868
<label class="input-group-text rev-label">From</label>
69-
<input type="datetime-local" class="form-control form-control-sm" id="historicalFromTimestamp" step="1">
69+
<input type="datetime-local" class="form-control form-control-sm" id="historicalFromTimestamp" step="0.001">
7070
</div>
7171
<div class="input-group input-group-sm mb-1">
7272
<button class="btn btn-outline-secondary btn-sm rev-action-btn" id="buttonToMostRecentTimestamp"
7373
data-bs-toggle="tooltip" title="Set to most recent timestamp">Newest</button>
7474
<label class="input-group-text rev-label">To</label>
75-
<input type="datetime-local" class="form-control form-control-sm" id="historicalToTimestamp" step="1">
75+
<input type="datetime-local" class="form-control form-control-sm" id="historicalToTimestamp" step="0.001">
7676
</div>
7777
</div>
7878
<div class="input-group input-group-sm mb-1">

ui/modules/things/thingUpdates.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,17 @@ function onSelectContentChange() {
230230
function onLiveMessage(messageData) {
231231
if (isHistoricalMode) return;
232232

233+
while (messages.length >= MAX_MESSAGES) {
234+
messages.shift();
235+
}
236+
while (filteredMessages.length >= MAX_MESSAGES) {
237+
filteredMessages.shift();
238+
const tbody = dom.tbodyThingUpdates;
239+
if (tbody.rows.length > 0) {
240+
tbody.deleteRow(0);
241+
}
242+
}
243+
233244
messages.push(messageData);
234245

235246
const filteredMessage = dom.tableFilterThingUpdates.filterItems([messageData]);
@@ -494,6 +505,7 @@ function onHistoricalMessage(event) {
494505
if (messages.length >= MAX_MESSAGES) {
495506
onStopHistorical();
496507
Utils.showError(`Message limit reached (${MAX_MESSAGES}). Narrow your revision/time range for more detail.`);
508+
return;
497509
}
498510

499511
const filteredMessage = dom.tableFilterThingUpdates.filterItems([messageData]);

ui/modules/things/things.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export function isHistoryModeActive(): boolean {
2929
}
3030

3131
const observers = [];
32-
const historyModeObservers = [];
3332

3433
const dom = {
3534
collapseThings: null,
@@ -115,7 +114,6 @@ export function refreshThingAtTimestamp(thingId: string, timestamp: string): Pro
115114

116115
export function setHistoryMode(active: boolean) {
117116
_historyModeActive = active;
118-
historyModeObservers.forEach((observer) => observer.call(null, active));
119117
if (!active && theThing) {
120118
refreshThing(theThing.thingId);
121119
}

ui/modules/things/thingsDiff.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
~
1111
~ SPDX-License-Identifier: EPL-2.0
1212
-->
13-
<div class="tab-pane fade container no-margin" style="height: 100%; display: flex; flex-direction: column;">
13+
<div class="tab-pane container no-margin" style="height: 100%; display: flex; flex-direction: column;">
1414
<div class="input-group input-group-sm mb-1 mt-1">
1515
<label class="input-group-text rev-label">Left rev.</label>
1616
<span class="input-group-text" id="diffLeftMin" data-bs-toggle="tooltip"

ui/modules/things/thingsDiff.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Tab } from 'bootstrap';
1515
import * as ace from 'ace-builds/src-noconflict/ace';
1616
import AceDiff from 'ace-diff';
1717
import * as API from '../api.js';
18+
import * as Environments from '../environments/environments.js';
1819
import * as Utils from '../utils.js';
1920
import thingsDiffHTML from './thingsDiff.html';
2021
import * as Things from './things.js';
@@ -73,6 +74,8 @@ export function ThingsDiff(targetTab) {
7374
tabLink = document.querySelector(`a[data-bs-target="#${tabId}"]`);
7475
tabLink.addEventListener('shown.bs.tab', onTabActivated);
7576

77+
Environments.addChangeListener(onEnvironmentChanged);
78+
7679
Utils.getAllElementsById(dom);
7780

7881
// Left revision controls
@@ -129,13 +132,21 @@ export function ThingsDiff(targetTab) {
129132
cancelActiveProbe();
130133
probeOldestRevision(thing.thingId);
131134

132-
if (tabLink && tabLink.classList.contains('active')) {
135+
if (isAnyDiffTabActive()) {
133136
fetchAndDiff();
134137
} else {
135138
viewDirty = true;
136139
}
137140
};
138141

142+
function isAnyDiffTabActive(): boolean {
143+
if (tabLink && tabLink.classList.contains('active')) return true;
144+
return subDiffs.some((s) => {
145+
const link = s.subDiff.getTabLink();
146+
return link && link.classList.contains('active');
147+
});
148+
}
149+
139150
const addSubDiff = (subDiff, kind: 'attributes' | 'feature') => {
140151
subDiffs.push({ subDiff, kind });
141152
subDiff.setOnActivated((link) => syncTabs(link));
@@ -218,6 +229,20 @@ export function ThingsDiff(targetTab) {
218229
}
219230
}
220231

232+
function onEnvironmentChanged(modifiedField) {
233+
if (['pinnedThings', 'filterList', 'messageTemplates', 'recentPolicyIds'].includes(modifiedField)) {
234+
return;
235+
}
236+
cancelActiveProbe();
237+
destroyDiff();
238+
currentThingId = null;
239+
currentMinRevision = 1;
240+
currentMaxRevision = 1;
241+
lastLeftJson = null;
242+
lastRightJson = null;
243+
viewDirty = false;
244+
}
245+
221246
function probeOldestRevision(thingId: string) {
222247
const probe = Things.probeOldestRevision(thingId);
223248
activeProbe = probe;
@@ -293,6 +318,16 @@ export function ThingsDiff(targetTab) {
293318
]).then((results) => {
294319
if (token !== fetchToken) return; // stale response
295320

321+
if (results[0].status === 'rejected') {
322+
console.warn(`Diff: failed to fetch left revision ${leftRev}`, results[0].reason);
323+
}
324+
if (results[1].status === 'rejected') {
325+
console.warn(`Diff: failed to fetch right revision ${rightRev}`, results[1].reason);
326+
}
327+
if (results[0].status === 'rejected' && results[1].status === 'rejected') {
328+
Utils.showError(`Failed to fetch both revisions (${leftRev}, ${rightRev}) for diff`);
329+
}
330+
296331
const leftJson = results[0].status === 'fulfilled' ? results[0].value : {};
297332
const rightJson = results[1].status === 'fulfilled' ? results[1].value : {};
298333
lastLeftJson = leftJson;

ui/modules/things/thingsHistory.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
<div id="historyTimestampControls" hidden>
5454
<div class="input-group input-group-sm mb-1">
5555
<label class="input-group-text">Timestamp</label>
56-
<input type="datetime-local" class="form-control form-control-sm" id="historyTimestampInput" step="1">
56+
<input type="datetime-local" class="form-control form-control-sm" id="historyTimestampInput" step="0.001">
5757
</div>
5858
</div>
5959
<button class="btn btn-outline-secondary btn-sm" id="historyShowUpdates" data-bs-toggle="tooltip"

ui/modules/things/thingsHistory.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,15 @@ function fetchHistoricalState() {
312312
dom.historyBannerText.textContent = `Time travel to revision ${revision}`;
313313
Things.refreshThingAtRevision(currentThingId, revision)
314314
.catch(() => {
315-
dom.historyBannerText.textContent = `Time travel failed — revision ${revision} may not exist`;
315+
if (revision >= currentMinRevision && revision < currentMaxRevision) {
316+
currentMinRevision = revision + 1;
317+
updateRevisionRange();
318+
if (parseInt(dom.historyRevisionSlider.value, 10) < currentMinRevision) {
319+
dom.historyRevisionSlider.value = String(currentMinRevision);
320+
dom.historyRevisionInput.value = String(currentMinRevision);
321+
}
322+
}
323+
dom.historyBannerText.textContent = `Revision ${revision} has been pruned from history (retention). Oldest retrievable is now ${currentMinRevision}.`;
316324
});
317325
} else {
318326
const timestamp = dom.historyTimestampInput.value;
@@ -321,7 +329,7 @@ function fetchHistoricalState() {
321329
dom.historyBannerText.textContent = `Time travel to ${timestamp.replace('T', ' ')}`;
322330
Things.refreshThingAtTimestamp(currentThingId, isoTimestamp)
323331
.catch(() => {
324-
dom.historyBannerText.textContent = `Time travel failed — no data at ${timestamp.replace('T', ' ')}`;
332+
dom.historyBannerText.textContent = `Time travel failed — no data at ${timestamp.replace('T', ' ')} (may be before retention window)`;
325333
});
326334
}
327335
}

ui/modules/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,9 @@ export function formatDate(dateISOString: string, withMilliseconds = false): str
338338
export function toDatetimeLocalValue(isoString: string): string {
339339
if (!isoString) return '';
340340
const d = new Date(isoString);
341+
if (isNaN(d.getTime())) return '';
341342
const offset = d.getTimezoneOffset() * 60000;
342-
return new Date(d.getTime() - offset).toISOString().substring(0, 19);
343+
return new Date(d.getTime() - offset).toISOString().substring(0, 23);
343344
}
344345

345346
let modalConfirm;

0 commit comments

Comments
 (0)