feat(insights): add factual weekly and monthly reports
This commit is contained in:
1 parent
0d673a3b5a
commit
477e86f694
9 files changed
+138
-29
No files matched your search
+1
-1
@@ -8,7 +8,7 @@ const meta = new URL("../dist/.openai/", import.meta.url);
|
||||
await rm(dist, { recursive: true, force: true });
|
||||
await Promise.all([mkdir(server, { recursive: true }), mkdir(meta, { recursive: true })]);
|
||||
const [rawIndexHtml, addonsJs, bootGuardJs, i18nJs, tasksJs, calendarJs, i18nRenderersJs, manifest, serviceWorker, icon, localeEn, localeZh] = await Promise.all([text("index.html"), text("addons.js"), text("boot-guard.js"), text("i18n.js"), text("tasks.js"), text("calendar.js"), text("i18n-renderers.js"), text("manifest.webmanifest"), text("service-worker.js"), text("life-os-icon.svg"), readFile(new URL("../public/locales/en.json", import.meta.url), "utf8"), readFile(new URL("../public/locales/zh-CN.json", import.meta.url), "utf8")]);
|
||||
const release = "1.5.8";
|
||||
const release = "1.6.0";
|
||||
const localeEnJs = `window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales.en=${localeEn};`;
|
||||
const localeZhJs = `window.LifeOSLocales=window.LifeOSLocales||{};window.LifeOSLocales['zh-CN']=${localeZh};`;
|
||||
let indexHtml = rawIndexHtml.replace('src="addons.js"', `src="addons.js?v=${release}"`).replace('src="tasks.js"', `src="tasks.js?v=${release}"`).replace('src="calendar.js"', `src="calendar.js?v=${release}"`);
|
||||
|
||||
+37
-2
@@ -115,14 +115,15 @@ assert.match(assets.i18nRenderersJs, /onclick=\"window\.setLanguage\('zh'\)\"/);
|
||||
assert.doesNotMatch(assets.addonsJs, /lifeos_language_preference_v1/, "the device locale preference stays outside cloud-synced keys");
|
||||
const uiNodes = new Map();
|
||||
const uiNode = () => ({ innerHTML: "", textContent: "", style: {}, dataset: {}, classList: { add() {}, remove() {}, toggle() {}, contains: () => false }, remove() {}, append() {}, querySelector: () => null, querySelectorAll: () => [] });
|
||||
for (const id of ["icons", "tasks", "launcher", "calendar", "desktop", "boot", "modal", "windows", "clock", "date", "desktop-brand", "life-launcher", "content-system"]) uiNodes.set(`#${id}`, uiNode());
|
||||
for (const id of ["icons", "tasks", "launcher", "calendar", "desktop", "boot", "modal", "windows", "clock", "date", "desktop-brand", "life-launcher", "content-system", "content-insights"]) uiNodes.set(`#${id}`, uiNode());
|
||||
const uiDocument = {
|
||||
documentElement: { dataset: {}, lang: "en" }, title: "", head: { insertAdjacentHTML() {}, append() {} }, body: { append() {} },
|
||||
querySelector: selector => uiNodes.get(selector) || null, getElementById: id => uiNodes.get(`#${id}`) || null,
|
||||
createElement: uiNode, addEventListener() {}, querySelectorAll: () => []
|
||||
};
|
||||
const uiStorage = makeStorage();
|
||||
const uiContext = vm.createContext({
|
||||
document: uiDocument, navigator: { languages: ["en-US"], language: "en-US" }, localStorage: makeStorage(),
|
||||
document: uiDocument, navigator: { languages: ["en-US"], language: "en-US" }, localStorage: uiStorage,
|
||||
Blob, crypto: globalThis.crypto, innerWidth: 1000, innerHeight: 800,
|
||||
matchMedia: () => ({ matches: false }), setTimeout: () => 0, setInterval: () => 0,
|
||||
fetch: async () => ({ ok: false, json: async () => ({}) }), console,
|
||||
@@ -143,6 +144,40 @@ uiContext.navigator.languages = ["zh-CN"];
|
||||
uiContext.setLanguage("auto");
|
||||
assert.match(uiNodes.get("#content-system").innerHTML, /系统设置/);
|
||||
assert.equal(uiContext.LifeI18n.preference(), "auto");
|
||||
uiContext.setLanguage("en");
|
||||
const calendarKey = date => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
||||
const current = new Date(), previousWeek = new Date(current.getFullYear(), current.getMonth(), current.getDate() - 7, 12);
|
||||
const currentKey = calendarKey(current), previousKey = calendarKey(previousWeek), currentStamp = new Date(current.getFullYear(), current.getMonth(), current.getDate(), 12).toISOString();
|
||||
uiStorage.setItem("lifeos_memories", JSON.stringify([
|
||||
{ id: "current-highlight", date: currentKey, title: "Current highlight", text: "A real saved moment", mood: "clear", energy: 4, tags: ["高光"] },
|
||||
{ id: "previous-highlight", date: previousKey, title: "Previous highlight", text: "An older moment", mood: "rain", energy: 2, tags: [] }
|
||||
]));
|
||||
uiStorage.setItem("lifeos_museum", JSON.stringify([{ id: "artifact-prev", memoryId: "previous-highlight" }]));
|
||||
uiStorage.setItem("lifeos_system", JSON.stringify({ schemaVersion: 2, tasksBoard: {
|
||||
tasks: [{ id: "done-now", done: true, createdAt: currentStamp, completedAt: currentStamp }, { id: "done-before", done: true, createdAt: previousWeek.toISOString(), completedAt: previousWeek.toISOString() }],
|
||||
goals: [{ id: "goal-now", done: true, completedAt: currentStamp }]
|
||||
} }));
|
||||
uiContext.insights(uiNodes.get("#content-insights"));
|
||||
let report = uiNodes.get("#content-insights").innerHTML;
|
||||
assert.match(report, /Current highlight/);
|
||||
assert.doesNotMatch(report, /Previous highlight/);
|
||||
assert.match(report, /1 tasks created · 1 goals completed/);
|
||||
assert.match(report, /First entry|One energy entry/);
|
||||
uiContext.shiftInsights(-1);
|
||||
report = uiNodes.get("#content-insights").innerHTML;
|
||||
assert.match(report, /Previous highlight/);
|
||||
assert.doesNotMatch(report, /Current highlight/);
|
||||
assert.match(report, /SAVED/);
|
||||
uiContext.setInsightsView("month");
|
||||
report = uiNodes.get("#content-insights").innerHTML;
|
||||
assert.match(report, /Current highlight/);
|
||||
assert.match(report, /MONTH/);
|
||||
uiStorage.setItem("lifeos_memories", "[]");
|
||||
uiStorage.setItem("lifeos_museum", "[]");
|
||||
uiStorage.setItem("lifeos_system", JSON.stringify({ schemaVersion: 2, tasksBoard: { tasks: [], goals: [] } }));
|
||||
uiContext.insights(uiNodes.get("#content-insights"));
|
||||
assert.match(uiNodes.get("#content-insights").innerHTML, /No weather recorded in this period/);
|
||||
assert.match(uiNodes.get("#content-insights").innerHTML, /No saved or tagged memories in this period/);
|
||||
const zhLogin = await worker.default.fetch(new Request("https://life-os.test/", { headers: { "accept-language": "zh-CN,zh;q=0.9" } }), {});
|
||||
assert.match(await zhLogin.text(), /登录 ChatGPT/);
|
||||
const enLogin = await worker.default.fetch(new Request("https://life-os.test/", { headers: { "accept-language": "en-US,en;q=0.9" } }), {});
|
||||
|
||||
Reference in new issue
Block a user