From b04f0b2a2e1b513ce8655fd5fd8b473fc91b10b4 Mon Sep 17 00:00:00 2001 From: elf Pavlik Date: Mon, 25 Mar 2024 09:00:18 -0600 Subject: [PATCH] wip use @ldo/solid --- examples/vuejectron/package.json | 3 +- examples/vuejectron/src/store/app.ts | 143 ++++++++++++---------- examples/vuejectron/src/views/Agent.vue | 2 +- examples/vuejectron/src/views/Project.vue | 21 ++-- pnpm-lock.yaml | 15 +++ 5 files changed, 107 insertions(+), 77 deletions(-) diff --git a/examples/vuejectron/package.json b/examples/vuejectron/package.json index a7b3afcc..3239e9e1 100644 --- a/examples/vuejectron/package.json +++ b/examples/vuejectron/package.json @@ -12,9 +12,10 @@ "dependencies": { "@inrupt/solid-client-authn-browser": "^2.0.0", "@janeirodigital/interop-application": "^1.0.0-rc.24", - "@janeirodigital/interop-utils": "^1.0.0-rc.24", "@janeirodigital/interop-data-model": "^1.0.0-rc.24", + "@janeirodigital/interop-utils": "^1.0.0-rc.24", "@ldo/ldo": "0.0.1-alpha.23", + "@ldo/solid": "0.0.1-alpha.23", "@mdi/font": "7.3.67", "@vueuse/core": "^10.5.0", "core-js": "^3.33.0", diff --git a/examples/vuejectron/src/store/app.ts b/examples/vuejectron/src/store/app.ts index 6ce12d85..3baf2145 100644 --- a/examples/vuejectron/src/store/app.ts +++ b/examples/vuejectron/src/store/app.ts @@ -3,8 +3,9 @@ import { defineStore } from 'pinia'; import { ref } from 'vue'; import { Agent, FileInstance, ImageInstance, Registration } from '@/models'; import { useCoreStore } from './core'; -import { toSparqlUpdate, LdoBase, startTransaction, commitTransaction, write, createLdoDataset } from '@ldo/ldo'; +import { LdoBase } from '@ldo/ldo'; import { DataInstance } from '@janeirodigital/interop-data-model'; +import { changeData as ldoChangeData, commitData, createSolidLdoDataset, type SolidLdoDataset } from "@ldo/solid" import { getDefaultSession } from '@inrupt/solid-client-authn-browser'; import { Application, SaiEvent } from '@janeirodigital/interop-application'; @@ -13,7 +14,6 @@ import { ProjectShapeType } from '../../ldo/Project$.shapeTypes'; import { TaskShapeType } from '../../ldo/Task$.shapeTypes'; import { Task } from '../../ldo/Task$.typings'; import { Project } from '../../ldo/Project$.typings'; -import { i } from 'vite/dist/node/types.d-jgA8ss1A'; const ownerIndex: { [key: string]: string } = {}; @@ -50,7 +50,6 @@ export const useAppStore = defineStore('app', () => { const fileInstances: Record = {} const coreStore = useCoreStore(); const agents = ref([]); - const projects = ref>({}); const registrations = ref>({}); const tasks = ref>({}); const files = ref([]); @@ -58,6 +57,10 @@ export const useAppStore = defineStore('app', () => { const currentAgent = ref(); const currentProject = ref(); const saiError = ref(); + + let solidLdoDataset: SolidLdoDataset + const ldoProjects = ref>({}); + const ldoTasks = ref>({}); async function loadAgents(force = false): Promise { if (force || !agents.value.length) { @@ -89,7 +92,7 @@ export const useAppStore = defineStore('app', () => { if (!user) { throw new Error(`data registration not found for ${ownerId}`); } - const ownerProjects: Record = {}; + const ldoOwnerProjects: Record = {}; const ownerRegistration: Record = {}; ownerRegistration[ownerId] = []; for (const registration of user.selectRegistrations(shapeTrees.project)) { @@ -99,7 +102,7 @@ export const useAppStore = defineStore('app', () => { owner: ownerId, canCreate: registration.grant.accessMode.includes(ACL.Create.value) }); - ownerProjects[registration.iri] = []; + ldoOwnerProjects[registration.iri] = []; // eslint-disable-next-line no-await-in-loop for await (const dataInstance of registration.dataInstances) { projectInstances[dataInstance.iri] = { @@ -108,13 +111,20 @@ export const useAppStore = defineStore('app', () => { registration: registration.iri } ownerIndex[dataInstance.iri] = ownerId; - const ldoDataset = createLdoDataset([...dataInstance.dataset]); - const ldoProject = ldoDataset.usingType(ProjectShapeType).fromSubject(dataInstance.iri); - ownerProjects[registration.iri].push(ldoProject); + + // @ldo-solid + const ldoResource = solidLdoDataset.getResource(dataInstance.iri) + const readResult = await ldoResource.read() + if (readResult.isError) throw readResult + + const ldoSolidProject = solidLdoDataset + .usingType(ProjectShapeType) + .fromSubject(dataInstance.iri) + ldoOwnerProjects[registration.iri].push(ldoSolidProject); } } - projects.value = { ...projects.value, ...ownerProjects }; + ldoProjects.value = { ...ldoProjects.value, ...ldoOwnerProjects }; registrations.value = { ...registrations.value, ...ownerRegistration }; } @@ -124,20 +134,42 @@ export const useAppStore = defineStore('app', () => { if (!project) { throw new Error(`Project not found for: ${projectId}`); } - const projectTasks = []; + const ldoProjectTasks = []; for await (const dataInstance of project.instance.getChildInstancesIterator(shapeTrees.task)) { taskInstances[dataInstance.iri] = { instance: dataInstance, agent: project.agent, project: projectId } - const ldoDataset = createLdoDataset([...dataInstance.dataset]); - ldoDataset.on([dataInstance.node, null, null, null], console.log) - const ldoTask = ldoDataset.usingType(TaskShapeType).fromSubject(dataInstance.iri); - projectTasks.push(ldoTask); + + // @ldo-solid + const ldoResource = solidLdoDataset.getResource(dataInstance.iri) + const readResult = await ldoResource.read() + if (readResult.isError) throw readResult + + const ldoSolidTask = solidLdoDataset + .usingType(TaskShapeType) + .fromSubject(dataInstance.iri) + ldoProjectTasks.push(ldoSolidTask); } - tasks.value[projectId] = projectTasks + ldoTasks.value[projectId] = ldoProjectTasks + } + + async function draftTask(projectId: string): Promise { + const projectInfo = projectInstances[projectId] + const newTaskInstance = await projectInfo.instance.newChildDataInstance(shapeTrees.task) + taskInstances[newTaskInstance.iri] = { + instance: newTaskInstance, + agent: projectInfo.agent, + project: projectInfo.instance.iri + } + const ldoSolidTask = solidLdoDataset + .usingType(TaskShapeType) + .fromSubject(newTaskInstance.iri) + ldoTasks.value[projectId].push(ldoSolidTask); + return ldoSolidTask + // return solidLdoDataset.createData(TaskShapeType, newTaskInstance.iri, ldoResource) } async function updateTask(task: Task) { @@ -148,40 +180,32 @@ export const useAppStore = defineStore('app', () => { if (!project) { throw new Error(`project not found ${info.project}`); } - let instance: DataInstance; - if (task['@id'] !== 'DRAFT') { - const cached = taskInstances[task['@id']]; - if (!cached) { - throw new Error(`Data Instance not found for: ${task['@id']}`); - } - instance = cached.instance; - } else { - instance = await project.instance.newChildDataInstance(shapeTrees.task); - taskInstances[instance.iri] = { - instance: instance, - agent: project.agent, - project: project.instance.iri - } - } - - try { - await updateLdo(task); - commitTransaction(task) - } catch (error) { - console.error('error updating task', error); + const instance = taskInstances[task['@id']]; + if (!instance) { + throw new Error(`Data Instance not found for: ${task['@id']}`); } - if (task['@id'] === 'DRAFT') { - tasks.value[info.project].push(task); - } else { - const indexToUpdate = tasks.value[info.project].findIndex((t) => t['@id'] === task['@id']); - if (indexToUpdate === -1) { - throw new Error(`task not found: ${task['@id']}`); - } - const same = tasks.value[info.project][indexToUpdate]; - tasks.value[info.project][indexToUpdate] = null as unknown as Task - tasks.value[info.project][indexToUpdate] = same + const ldoProject = ldoProjects.value[project.registration] + .find(p => p['@id'] === project.instance.iri) + if (!ldoProject) throw new Error(`ldo project not found: ${project.instance.iri}`) + const isDraft = !ldoProject.hasTask?.find(t => t['@id'] === task['@id']) + if (isDraft) { + // add reference to new task + const cProject = changeData(ldoProject) + if (!cProject.hasTask) cProject.hasTask = [] + cProject.hasTask.push({ '@id': task['@id'] }) + const result = await commitData(cProject) + if (result.isError) throw result } + const result = await commitData(task) + if (result.isError) throw result + + const indexToUpdate = ldoTasks.value[info.project].findIndex((t) => t['@id'] === task['@id']); + if (indexToUpdate === -1) throw new Error(`task not found: ${task['@id']}`) + // trigger effects + const same = ldoTasks.value[info.project][indexToUpdate]; + delete ldoTasks.value[info.project][indexToUpdate] + ldoTasks.value[info.project][indexToUpdate] = same } async function deleteTask(task: Task) { @@ -256,7 +280,7 @@ export const useAppStore = defineStore('app', () => { } function setCurrentProject(registrationId: string, projectId: string) { - currentProject.value = projects.value[registrationId]?.find((p) => p['@id'] === projectId); + currentProject.value = ldoProjects.value[registrationId]?.find((p) => p['@id'] === projectId); } async function shareProject(projectId: string) { @@ -265,11 +289,9 @@ export const useAppStore = defineStore('app', () => { function changeData(input: Type): Type { - const [transactionLdo] = write(input['@id']).usingCopy( - input, - ); - startTransaction(transactionLdo); - return transactionLdo; + const resource = solidLdoDataset.getResource(input['@id']); + return ldoChangeData(input, resource); + } function getProjectChildInfo(id: string): ProjectChildInfo { @@ -348,6 +370,7 @@ export const useAppStore = defineStore('app', () => { } throw err } + solidLdoDataset = createSolidLdoDataset({ fetch: authnFetch}) return saiSession; } @@ -387,18 +410,6 @@ export const useAppStore = defineStore('app', () => { })); } - async function updateLdo(ldo: LdoBase) { - const { fetch: authFetch } = getDefaultSession(); - const sparql = await toSparqlUpdate(ldo) - authFetch(ldo['@id'], { - method: 'PATCH', - body: sparql, - headers: { - 'Content-Type': 'application/sparql-update' - } - }); - } - async function getFiles(projectId: string): Promise<{ projectId: string; files: FileInstance[] }> { await ensureSaiSession(); const project = projectInstances[projectId]; @@ -450,7 +461,6 @@ export const useAppStore = defineStore('app', () => { currentAgent, currentProject, registrations, - projects, tasks, files, images, @@ -479,5 +489,8 @@ export const useAppStore = defineStore('app', () => { canAddTasks, canAddImages, canAddFiles, + ldoProjects, + ldoTasks, + draftTask }; }); diff --git a/examples/vuejectron/src/views/Agent.vue b/examples/vuejectron/src/views/Agent.vue index 3d14cd47..65422186 100644 --- a/examples/vuejectron/src/views/Agent.vue +++ b/examples/vuejectron/src/views/Agent.vue @@ -7,7 +7,7 @@ >

{{ registration.label }}

- + diff --git a/examples/vuejectron/src/views/Project.vue b/examples/vuejectron/src/views/Project.vue index bc56ef8f..fc7878ac 100644 --- a/examples/vuejectron/src/views/Project.vue +++ b/examples/vuejectron/src/views/Project.vue @@ -13,7 +13,7 @@ > - + {{ task.label }} @@ -118,16 +118,17 @@ async function downloadFile(file: FileInstance) { } } -function updateTask(label: string) { +async function updateTask(label: string) { + let cTask: Task if (selectedTask.value) { - const cTask = appStore.changeData(selectedTask.value); - cTask.label = label; - appStore.updateTask(cTask); - selectedTask.value = null; - } else if (label && appStore.currentProject) { - // const task = { id: 'DRAFT', label, project: appStore.currentProject.id, owner: appStore.currentProject.owner }; - // appStore.updateTask(task); - } + cTask = appStore.changeData(selectedTask.value); + } else { + const newTask = await appStore.draftTask(appStore.currentProject!['@id']!) + cTask = appStore.changeData(newTask); + } + cTask.label = label; + appStore.updateTask(cTask); + selectedTask.value = null; dialog.value = false; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c7bdab1..c562ed2c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -183,6 +183,9 @@ importers: '@ldo/ldo': specifier: 0.0.1-alpha.23 version: 0.0.1-alpha.23 + '@ldo/solid': + specifier: 0.0.1-alpha.23 + version: 0.0.1-alpha.23 '@mdi/font': specifier: 7.3.67 version: 7.3.67 @@ -4843,6 +4846,18 @@ packages: transitivePeerDependencies: - encoding + /@ldo/solid@0.0.1-alpha.23: + resolution: {integrity: sha512-Ts/geXO8Ulnh9SiZ5X3CP7vkOnFi3z2uuo9MVzVQf2rjB5ZSrqFUn8FFfyTMj5sgi/t/tNKRzOoXWebNgi4AMQ==} + dependencies: + '@ldo/dataset': 0.0.1-alpha.24 + '@ldo/ldo': 0.0.1-alpha.24 + '@ldo/rdf-utils': 0.0.1-alpha.24 + cross-fetch: 3.1.8 + http-link-header: 1.1.1 + transitivePeerDependencies: + - encoding + dev: false + /@ldo/solid@0.0.1-alpha.24: resolution: {integrity: sha512-dMELYBGPrBHlKeKJB8icji78Tr+c5H1yFgnVyhCPqajIvnHKCWYOtkHNd4ctx1CJeTcJaYezsqOOOfU6LoZRBg==} dependencies: