Read legacy inbox and activity storage
This commit is contained in:
parent
b4ef3b38b0
commit
4a1550acf6
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
var PLUGIN_ID = 'verstak.activity';
|
var PLUGIN_ID = 'verstak.activity';
|
||||||
var MAX_EVENTS = 250;
|
var MAX_EVENTS = 250;
|
||||||
|
var LEGACY_KEY = 'events';
|
||||||
var GLOBAL_KEY = 'events:global';
|
var GLOBAL_KEY = 'events:global';
|
||||||
var WORKSPACE_PREFIX = 'events:workspace:';
|
var WORKSPACE_PREFIX = 'events:workspace:';
|
||||||
var ACTIVITY_EVENTS = [
|
var ACTIVITY_EVENTS = [
|
||||||
|
|
@ -197,7 +198,7 @@
|
||||||
occurredAt: text(item.occurredAt || item.timestamp || item.receivedAt),
|
occurredAt: text(item.occurredAt || item.timestamp || item.receivedAt),
|
||||||
receivedAt: text(item.receivedAt),
|
receivedAt: text(item.receivedAt),
|
||||||
sourcePluginId: text(item.sourcePluginId || item.pluginId),
|
sourcePluginId: text(item.sourcePluginId || item.pluginId),
|
||||||
workspaceRootPath: cleanWorkspace(item.workspaceRootPath || (item.payload && (item.payload.workspaceRootPath || item.payload.workspaceName))),
|
workspaceRootPath: cleanWorkspace(item.workspaceRootPath || workspaceFromPayload(item.payload || {})),
|
||||||
_storageKey: storageKey || '',
|
_storageKey: storageKey || '',
|
||||||
payload: item.payload && typeof item.payload === 'object' ? item.payload : {}
|
payload: item.payload && typeof item.payload === 'object' ? item.payload : {}
|
||||||
};
|
};
|
||||||
|
|
@ -221,13 +222,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortEvents(activityList) {
|
function sortEvents(activityList) {
|
||||||
return activityList.slice().sort(function (a, b) {
|
var seen = {};
|
||||||
|
return activityList.filter(function (item) {
|
||||||
|
var key = item && item.activityId;
|
||||||
|
if (!key) return false;
|
||||||
|
if (seen[key]) return false;
|
||||||
|
seen[key] = true;
|
||||||
|
return true;
|
||||||
|
}).slice().sort(function (a, b) {
|
||||||
return text(b.occurredAt || b.receivedAt).localeCompare(text(a.occurredAt || a.receivedAt));
|
return text(b.occurredAt || b.receivedAt).localeCompare(text(a.occurredAt || a.receivedAt));
|
||||||
}).slice(0, MAX_EVENTS);
|
}).slice(0, MAX_EVENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalEventKeys(settings) {
|
function globalEventKeys(settings) {
|
||||||
var keys = [GLOBAL_KEY];
|
var keys = [LEGACY_KEY, GLOBAL_KEY];
|
||||||
Object.keys(settings || {}).forEach(function (key) {
|
Object.keys(settings || {}).forEach(function (key) {
|
||||||
if (key.indexOf(WORKSPACE_PREFIX) === 0 && keys.indexOf(key) === -1) keys.push(key);
|
if (key.indexOf(WORKSPACE_PREFIX) === 0 && keys.indexOf(key) === -1) keys.push(key);
|
||||||
});
|
});
|
||||||
|
|
@ -377,8 +385,12 @@
|
||||||
statusClass = 'error';
|
statusClass = 'error';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return api.settings.read(scope.key).then(function (stored) {
|
return api.settings.read().then(function (settings) {
|
||||||
events = normalizeStoredEvents(stored, scope.key);
|
var scopedEvents = normalizeStoredEvents((settings || {})[scope.key], scope.key);
|
||||||
|
var legacyEvents = normalizeStoredEvents((settings || {})[LEGACY_KEY], LEGACY_KEY).filter(function (item) {
|
||||||
|
return item.workspaceRootPath === scope.workspaceRoot;
|
||||||
|
});
|
||||||
|
events = sortEvents(scopedEvents.concat(legacyEvents));
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
statusText = 'Could not load activity: ' + (err && err.message ? err.message : String(err));
|
statusText = 'Could not load activity: ' + (err && err.message ? err.message : String(err));
|
||||||
statusClass = 'error';
|
statusClass = 'error';
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
var PLUGIN_ID = 'verstak.browser-inbox';
|
var PLUGIN_ID = 'verstak.browser-inbox';
|
||||||
var CAPTURE_EVENTS = ['browser.capture.page', 'browser.capture.selection', 'browser.capture.link'];
|
var CAPTURE_EVENTS = ['browser.capture.page', 'browser.capture.selection', 'browser.capture.link'];
|
||||||
var MAX_CAPTURES = 100;
|
var MAX_CAPTURES = 100;
|
||||||
|
var LEGACY_KEY = 'captures';
|
||||||
var GLOBAL_KEY = 'captures:global';
|
var GLOBAL_KEY = 'captures:global';
|
||||||
var WORKSPACE_PREFIX = 'captures:workspace:';
|
var WORKSPACE_PREFIX = 'captures:workspace:';
|
||||||
|
|
||||||
|
|
@ -185,13 +186,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function sortCaptures(captureList) {
|
function sortCaptures(captureList) {
|
||||||
return captureList.slice().sort(function (a, b) {
|
var seen = {};
|
||||||
|
return captureList.filter(function (item) {
|
||||||
|
var key = item && item.captureId;
|
||||||
|
if (!key) return false;
|
||||||
|
if (seen[key]) return false;
|
||||||
|
seen[key] = true;
|
||||||
|
return true;
|
||||||
|
}).slice().sort(function (a, b) {
|
||||||
return text(b.capturedAt || b.receivedAt).localeCompare(text(a.capturedAt || a.receivedAt));
|
return text(b.capturedAt || b.receivedAt).localeCompare(text(a.capturedAt || a.receivedAt));
|
||||||
}).slice(0, MAX_CAPTURES);
|
}).slice(0, MAX_CAPTURES);
|
||||||
}
|
}
|
||||||
|
|
||||||
function globalCaptureKeys(settings) {
|
function globalCaptureKeys(settings) {
|
||||||
var keys = [GLOBAL_KEY];
|
var keys = [LEGACY_KEY, GLOBAL_KEY];
|
||||||
Object.keys(settings || {}).forEach(function (key) {
|
Object.keys(settings || {}).forEach(function (key) {
|
||||||
if (key.indexOf(WORKSPACE_PREFIX) === 0 && keys.indexOf(key) === -1) keys.push(key);
|
if (key.indexOf(WORKSPACE_PREFIX) === 0 && keys.indexOf(key) === -1) keys.push(key);
|
||||||
});
|
});
|
||||||
|
|
@ -411,8 +419,12 @@
|
||||||
statusClass = 'error';
|
statusClass = 'error';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return api.settings.read(scope.key).then(function (stored) {
|
return api.settings.read().then(function (settings) {
|
||||||
captures = normalizeStoredCaptures(stored, scope.key);
|
var scopedCaptures = normalizeStoredCaptures((settings || {})[scope.key], scope.key);
|
||||||
|
var legacyCaptures = normalizeStoredCaptures((settings || {})[LEGACY_KEY], LEGACY_KEY).filter(function (item) {
|
||||||
|
return item.workspaceRootPath === scope.workspaceRoot;
|
||||||
|
});
|
||||||
|
captures = sortCaptures(scopedCaptures.concat(legacyCaptures));
|
||||||
if (!selectedId && captures[0]) selectedId = captures[0].captureId;
|
if (!selectedId && captures[0]) selectedId = captures[0].captureId;
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
statusText = 'Could not load inbox: ' + (err && err.message ? err.message : String(err));
|
statusText = 'Could not load inbox: ' + (err && err.message ? err.message : String(err));
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,34 @@ async function mountWithApi(api, props = { workspaceNode: { name: 'Project' }, w
|
||||||
const persisted = await mountWithApi(persistedApi);
|
const persisted = await mountWithApi(persistedApi);
|
||||||
if (!persisted.container.textContent.includes('Saved note')) throw new Error('persisted activity was not rendered');
|
if (!persisted.container.textContent.includes('Saved note')) throw new Error('persisted activity was not rendered');
|
||||||
|
|
||||||
|
const legacyApi = makeApi({
|
||||||
|
events: [
|
||||||
|
{
|
||||||
|
activityId: 'legacy-global',
|
||||||
|
type: 'browser.capture.page',
|
||||||
|
title: 'Legacy global capture',
|
||||||
|
occurredAt: '2026-06-27T02:00:00Z',
|
||||||
|
sourcePluginId: 'verstak.browser-inbox',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
activityId: 'legacy-project',
|
||||||
|
type: 'note.saved',
|
||||||
|
title: 'Legacy project note',
|
||||||
|
occurredAt: '2026-06-27T02:10:00Z',
|
||||||
|
sourcePluginId: 'verstak.notes',
|
||||||
|
payload: { path: 'Project/Notes/Legacy.md' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const legacyGlobal = await mountWithApi(legacyApi, {});
|
||||||
|
if (!legacyGlobal.container.textContent.includes('Legacy global capture')) throw new Error('legacy global activity was not rendered in global view');
|
||||||
|
if (!legacyGlobal.container.textContent.includes('Legacy project note')) throw new Error('legacy workspace activity was not rendered in global view');
|
||||||
|
component.unmount && component.unmount(legacyGlobal.container);
|
||||||
|
|
||||||
|
const legacyProject = await mountWithApi(legacyApi, { workspaceNode: { name: 'Project' }, workspaceRootPath: 'Project' });
|
||||||
|
if (!legacyProject.container.textContent.includes('Legacy project note')) throw new Error('legacy workspace activity was not rendered in matching workspace');
|
||||||
|
if (legacyProject.container.textContent.includes('Legacy global capture')) throw new Error('legacy global activity leaked into workspace view');
|
||||||
|
|
||||||
console.log('activity plugin smoke passed');
|
console.log('activity plugin smoke passed');
|
||||||
})().catch((err) => {
|
})().catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
||||||
|
|
@ -274,6 +274,44 @@ async function mountWithApi(api, props = { workspaceNode: { name: 'Project' }, w
|
||||||
throw new Error('persisted capture was not rendered on mount');
|
throw new Error('persisted capture was not rendered on mount');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const legacyApi = makeApi({
|
||||||
|
captures: [
|
||||||
|
{
|
||||||
|
captureId: 'legacy-global-capture',
|
||||||
|
capturedAt: '2026-06-27T02:00:00.000Z',
|
||||||
|
kind: 'page',
|
||||||
|
url: 'https://legacy.example.com/',
|
||||||
|
title: 'Legacy Global Capture',
|
||||||
|
domain: 'legacy.example.com',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
captureId: 'legacy-project-capture',
|
||||||
|
capturedAt: '2026-06-27T02:10:00.000Z',
|
||||||
|
kind: 'page',
|
||||||
|
url: 'https://project.example.com/',
|
||||||
|
title: 'Legacy Project Capture',
|
||||||
|
domain: 'project.example.com',
|
||||||
|
workspaceRootPath: 'Project',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const legacyGlobal = await mountWithApi(legacyApi, {});
|
||||||
|
if (!walk(legacyGlobal.container, (node) => node.getAttribute && node.getAttribute('data-browser-capture-id') === 'legacy-global-capture')) {
|
||||||
|
throw new Error('legacy global capture was not rendered in global view');
|
||||||
|
}
|
||||||
|
if (!walk(legacyGlobal.container, (node) => node.getAttribute && node.getAttribute('data-browser-capture-id') === 'legacy-project-capture')) {
|
||||||
|
throw new Error('legacy workspace capture was not rendered in global view');
|
||||||
|
}
|
||||||
|
component.unmount && component.unmount(legacyGlobal.container);
|
||||||
|
|
||||||
|
const legacyProject = await mountWithApi(legacyApi, { workspaceNode: { name: 'Project' }, workspaceRootPath: 'Project' });
|
||||||
|
if (!walk(legacyProject.container, (node) => node.getAttribute && node.getAttribute('data-browser-capture-id') === 'legacy-project-capture')) {
|
||||||
|
throw new Error('legacy workspace capture was not rendered in matching workspace');
|
||||||
|
}
|
||||||
|
if (walk(legacyProject.container, (node) => node.getAttribute && node.getAttribute('data-browser-capture-id') === 'legacy-global-capture')) {
|
||||||
|
throw new Error('legacy global capture leaked into workspace view');
|
||||||
|
}
|
||||||
|
|
||||||
console.log('browser inbox plugin smoke passed');
|
console.log('browser inbox plugin smoke passed');
|
||||||
})().catch((err) => {
|
})().catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue