Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions web/libs/editor/src/mixins/PersistentState.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const PersistentStateMixin = types

storeValues() {
const key = self.persistentValuesKey;
const obj = { ...self.persistentFingerprint, values: self.persistentValues };
const fingerprint = self.persistentFingerprint;

// no stable identity (e.g. preview without a task) — don't persist
if (!Object.values(fingerprint).every((value) => value !== undefined)) return;
const obj = { ...fingerprint, values: self.persistentValues };

localStorage.setItem(key, JSON.stringify(obj));
},
Expand All @@ -35,8 +39,10 @@ const PersistentStateMixin = types
const stored = JSON.parse(localStorage.getItem(self.persistentValuesKey) || "{}");

if (!stored) return;
if (!Object.keys(self.persistentFingerprint).every((key) => stored[key] === self.persistentFingerprint[key]))
return;
const fingerprint = self.persistentFingerprint;

if (!Object.values(fingerprint).every((value) => value !== undefined)) return;
if (!Object.keys(fingerprint).every((key) => stored[key] === fingerprint[key])) return;

const values = stored.values || {};

Expand Down
7 changes: 6 additions & 1 deletion web/libs/editor/src/tags/object/TimeSeries.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,12 @@ const Model = types
},

get persistentFingerprint() {
return { task: getRoot(self).task?.id };
// tag and overviewwidth invalidate the stored view on config change
return {
task: getRoot(self).task?.id,
tag: self.name,
overviewwidth: self.overviewwidth,
};
},

states() {
Expand Down
81 changes: 81 additions & 0 deletions web/libs/editor/src/tags/object/__tests__/TimeSeries.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,87 @@ describe("TimeSeries persistentValues, dataSlices, and panView no-op", () => {
expect(fp).toHaveProperty("task");
});

it("persistentFingerprint includes tag name and overviewwidth", () => {
const model = TimeSeriesModel.create(
{
name: "ts1",
value: "$timeseries",
timecolumn: "time",
overviewwidth: "50%",
children: [],
},
mockEnv,
);
const fp = model.persistentFingerprint;
expect(fp.tag).toBe("ts1");
expect(fp.overviewwidth).toBe("50%");
});

it("does not store values when there is no task id", () => {
localStorage.clear();
const model = TimeSeriesModel.create(
{
name: "timeseries",
value: "$timeseries",
timecolumn: "time",
children: [],
},
mockEnv,
);
model.setData({ time: [0, 100], value: [1, 2] });
model.updateTR([10, 90]);
model.storeValues();
expect(localStorage.getItem(model.persistentValuesKey)).toBeNull();
});

it("does not restore stored view when overviewwidth changed", () => {
localStorage.clear();
const MockStoreWithTask = types
.model({ timeseries: TimeSeriesModel })
.volatile(() => ({ task: { id: 1, dataObj: {} } }));

const m1 = TimeSeriesModel.create(
{ name: "ts", value: "$timeseries", timecolumn: "time", overviewwidth: "25%", children: [] },
mockEnv,
);
MockStoreWithTask.create({ timeseries: m1 }, mockEnv);
m1.setData({ time: [0, 100], value: [1, 2] });
m1.updateTR([0, 25]);
m1.storeValues();

const m2 = TimeSeriesModel.create(
{ name: "ts", value: "$timeseries", timecolumn: "time", overviewwidth: "100%", children: [] },
mockEnv,
);
MockStoreWithTask.create({ timeseries: m2 }, mockEnv);
m2.restoreValues();
expect(m2.brushRange.length).toBe(0);
});

it("restores stored view for the same task, tag and config", () => {
localStorage.clear();
const MockStoreWithTask = types
.model({ timeseries: TimeSeriesModel })
.volatile(() => ({ task: { id: 1, dataObj: {} } }));

const m1 = TimeSeriesModel.create(
{ name: "ts", value: "$timeseries", timecolumn: "time", overviewwidth: "25%", children: [] },
mockEnv,
);
MockStoreWithTask.create({ timeseries: m1 }, mockEnv);
m1.setData({ time: [0, 100], value: [1, 2] });
m1.updateTR([0, 25]);
m1.storeValues();

const m2 = TimeSeriesModel.create(
{ name: "ts", value: "$timeseries", timecolumn: "time", overviewwidth: "25%", children: [] },
mockEnv,
);
MockStoreWithTask.create({ timeseries: m2 }, mockEnv);
m2.restoreValues();
expect([...m2.brushRange]).toEqual([0, 25]);
});

it("dataSlices returns array of slices", () => {
const model = TimeSeriesModel.create(
{
Expand Down
Loading