diff --git a/frontend/components.d.ts b/frontend/components.d.ts
index 6117b75..000432b 100644
--- a/frontend/components.d.ts
+++ b/frontend/components.d.ts
@@ -22,11 +22,13 @@ declare module 'vue' {
IconEcosystem: typeof import('./src/components/icons/IconEcosystem.vue')['default']
IconSupport: typeof import('./src/components/icons/IconSupport.vue')['default']
IconTooling: typeof import('./src/components/icons/IconTooling.vue')['default']
+ InputText: typeof import('primevue/inputtext')['default']
Menubar: typeof import('primevue/menubar')['default']
Panel: typeof import('primevue/panel')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
TaskDetail: typeof import('./src/components/TaskDetail.vue')['default']
TasksTable: typeof import('./src/components/TasksTable.vue')['default']
+ ToggleButton: typeof import('primevue/togglebutton')['default']
}
}
diff --git a/frontend/src/components/TaskDetail.vue b/frontend/src/components/TaskDetail.vue
index 2633bd5..26ba64b 100644
--- a/frontend/src/components/TaskDetail.vue
+++ b/frontend/src/components/TaskDetail.vue
@@ -1,14 +1,42 @@
-
+
+
+ Trace Details
+
+
+
+
+
{{ slotProps.index }}
@@ -16,7 +44,8 @@ defineProps<{
- {{ slotProps.data }}
+
+ {{ slotProps.data }}
diff --git a/frontend/src/stores/tasks.ts b/frontend/src/stores/tasks.ts
index 2cd37f8..63ee1cf 100644
--- a/frontend/src/stores/tasks.ts
+++ b/frontend/src/stores/tasks.ts
@@ -3,9 +3,9 @@ import {defineStore} from 'pinia'
export const useTasksStore = defineStore('tasks', () => {
- const tasks = ref([])
+ const tasks = ref([])
- const taskSelected = ref(null)
+ const taskSelected = ref(null)
const load = async (id:string)=>{
const data = await fetch(`${import.meta.env.VITE_API_URL}/tasks/${id}`)
@@ -16,5 +16,19 @@ export const useTasksStore = defineStore('tasks', () => {
taskSelected.value = task
}
- return { tasks, load, taskSelected, setSelected }
+ const updateTask = async (session: string, taskId: number, updates: any) => {
+ const response = await fetch(`${import.meta.env.VITE_API_URL}/tasks/${session}/${taskId}`, {
+ method: 'PUT',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(updates)
+ })
+ tasks.value = await response.json()
+ if (taskSelected.value && taskSelected.value.id === taskId) {
+ taskSelected.value = tasks.value.find((t: any) => t.id === taskId) || taskSelected.value
+ }
+ }
+
+ return { tasks, load, taskSelected, setSelected, updateTask }
})
diff --git a/frontend/src/views/TaskView.vue b/frontend/src/views/TaskView.vue
index a87040a..39d88a4 100644
--- a/frontend/src/views/TaskView.vue
+++ b/frontend/src/views/TaskView.vue
@@ -43,6 +43,7 @@ const goBack = ()=>{
diff --git a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/StorageService.groovy b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/StorageService.groovy
index 93d2a48..857d00d 100644
--- a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/StorageService.groovy
+++ b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/StorageService.groovy
@@ -10,4 +10,6 @@ interface StorageService {
List tasks(String session)
void renameWorkDir(String oldPath, String newPath, String task)
+
+ void updateTask(String session, Long taskId, Map traceUpdates)
}
\ No newline at end of file
diff --git a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/controller/ApiController.groovy b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/controller/ApiController.groovy
index 7c80c44..ae51389 100644
--- a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/controller/ApiController.groovy
+++ b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/controller/ApiController.groovy
@@ -32,4 +32,10 @@ class ApiController {
storageService.renameWorkDir(renameRequest.oldPath(), renameRequest.newPath(), renameRequest.task())
executions()
}
+
+ @Put("/tasks/{session}/{taskId}")
+ List updateTask(String session, Long taskId, @Body Map updates){
+ storageService.updateTask(session, taskId, updates)
+ tasks(session)
+ }
}
diff --git a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/AbstractStorage.groovy b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/AbstractStorage.groovy
index b45497b..2863a1f 100644
--- a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/AbstractStorage.groovy
+++ b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/AbstractStorage.groovy
@@ -30,6 +30,17 @@ abstract class AbstractStorage implements StorageService{
renameWorkDir0(oldPath, newPath, task)
}
+ final void updateTask(String session, Long taskId, Map traceUpdates) {
+ def details = tasks(session)
+ def task = details.find { it.id == taskId }
+ if (task) {
+ traceUpdates.each { k, v ->
+ task.trace[k] = v
+ }
+ saveTasks(session, details)
+ }
+ }
+
private void renameWorkDir0(String oldPath, String newPath, String task){
newPath = newPath.endsWith("/") ? newPath : "$newPath/"
def executions = executions()
diff --git a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/DuckdbStorage.groovy b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/DuckdbStorage.groovy
index 8a5f2ee..90f3740 100644
--- a/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/DuckdbStorage.groovy
+++ b/src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/DuckdbStorage.groovy
@@ -101,6 +101,15 @@ class DuckdbStorage extends AbstractStorage{
@Override
protected void saveTasks(String session, List tasks) {
-
+ validateConnection()
+ tasks.each { task ->
+ def payload = [
+ KryoHelper.serialize(task.trace),
+ task.context ? KryoHelper.serialize(task.context) : new byte[0],
+ Integer.valueOf(task.refCount)
+ ]
+ byte[] bytes = KryoHelper.serialize(payload)
+ sql.execute("update CACHE_ENTRIES set entry=? where id=? and session_id=?", [bytes, task.id, session])
+ }
}
}