Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync to latest plugin #674

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
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
14 changes: 14 additions & 0 deletions src/dioptra/restapi/v1/entrypoints/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from marshmallow import Schema, fields, validate

from dioptra.restapi.v1.queues.schema import QueueRefSchema
from dioptra.restapi.v1.plugins.schema import PluginTaskSchema
from dioptra.restapi.v1.schemas import (
BasePageSchema,
GroupIdQueryParametersSchema,
Expand Down Expand Up @@ -49,6 +50,12 @@ class EntrypointPluginFileSchema(Schema):
metadata=dict(description="URL for accessing the full PluginFile snapshot."),
relative=True,
)
tasks = fields.Nested(
PluginTaskSchema,
attribute="tasks",
metadata=dict(description="Tasks associated with the PluginFile resource."),
many=True,
)


class EntrypointPluginSchema(Schema):
Expand All @@ -66,6 +73,13 @@ class EntrypointPluginSchema(Schema):
attribute="snapshot_id",
metadata=dict(description="Snapshot ID for the Plugin resource."),
)
latestSnapshot = fields.Boolean(
attribute="latest_snapshot",
metadata=dict(
description=f"Whether or not the {name} resource is the latest version."
),
dump_only=True,
)
url = fields.Url(
attribute="url",
metadata=dict(description="URL for accessing the full Plugin snapshot."),
Expand Down
40 changes: 23 additions & 17 deletions src/dioptra/restapi/v1/plugins/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,6 @@ class PluginSnapshotRefSchema(PluginSnapshotRefBaseSchema): # type: ignore
)


PluginFileRefBaseSchema = generate_base_resource_ref_schema("PluginFile")


class PluginFileRefSchema(PluginFileRefBaseSchema): # type: ignore
"""The reference schema for the data stored in a PluginFile."""

pluginId = fields.Int(
attribute="plugin_id",
data_key="plugin",
metadata=dict(description="ID for the Plugin resource this file belongs to."),
)
filename = fields.String(
attribute="filename",
metadata=dict(description="Filename of the PluginFile resource."),
)


class PluginTaskParameterSchema(Schema):
"""The schema for the data stored in a PluginTaskParameter"""

Expand Down Expand Up @@ -168,6 +151,29 @@ class PluginTaskSchema(Schema):
)


PluginFileRefBaseSchema = generate_base_resource_ref_schema("PluginFile")


class PluginFileRefSchema(PluginFileRefBaseSchema): # type: ignore
"""The reference schema for the data stored in a PluginFile."""

pluginId = fields.Int(
attribute="plugin_id",
data_key="plugin",
metadata=dict(description="ID for the Plugin resource this file belongs to."),
)
filename = fields.String(
attribute="filename",
metadata=dict(description="Filename of the PluginFile resource."),
)
tasks = fields.Nested(
PluginTaskSchema,
attribute="tasks",
metadata=dict(description="Tasks associated with the PluginFile resource."),
many=True,
)


PluginBaseSchema = generate_base_resource_schema("Plugin", snapshot=True)


Expand Down
3 changes: 3 additions & 0 deletions src/dioptra/restapi/v1/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ def build_entrypoint_plugin(plugin_with_files: PluginWithFilesDict) -> dict[str,
return {
"id": plugin.resource_id,
"snapshot_id": plugin.resource_snapshot_id,
"latest_snapshot": plugin.resource.latest_snapshot_id == plugin.resource_snapshot_id,
"name": plugin.name,
"url": build_url(
f"{PLUGINS}/{plugin.resource_id}/snapshots/{plugin.resource_snapshot_id}"
Expand All @@ -268,6 +269,7 @@ def build_entrypoint_plugin(plugin_with_files: PluginWithFilesDict) -> dict[str,
f"{PLUGINS}/{plugin.resource_id}/{PLUGIN_FILES}/{plugin_file.resource_id}/"
f"snapshots/{plugin_file.resource_snapshot_id}"
),
"tasks": [build_plugin_task(task) for task in plugin_file.tasks]
}
for plugin_file in plugin_files
],
Expand Down Expand Up @@ -311,6 +313,7 @@ def build_plugin_file_ref(plugin_file: models.PluginFile) -> dict[str, Any]:
"url": build_url(
f"{PLUGINS}/{plugin_id}/{PLUGIN_FILES}/{plugin_file.resource_id}"
),
"tasks": [build_plugin_task(task) for task in plugin_file.tasks]
}


Expand Down
98 changes: 58 additions & 40 deletions src/frontend/src/dialogs/AssignPluginsDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,42 @@
<div class="field-label">Plugins:</div>
</template>
<template v-slot:selected>
<q-chip
v-for="(plugin, i) in selectedPlugins"
:key="plugin.id"
removable
color="secondary"
text-color="white"
class="q-my-none q-ml-xs q-mr-none"
@remove="selectedPlugins.splice(i, 1)"
>
{{ plugin.name }}
</q-chip>
<div >
<div
v-for="(plugin, i) in selectedPlugins"
:key="plugin.id"
:class="i > 0 ? 'q-mt-xs' : ''"
>
<q-chip
removable
color="secondary"
text-color="white"
class="q-ml-xs "
@remove="selectedPlugins.splice(i, 1)"
>
{{ plugin.name }}
<q-badge
v-if="!plugin.latestSnapshot"
color="red"
label="Outdated"
rounded
class="q-ml-xs"
/>
</q-chip>
<q-btn
v-if="!plugin.latestSnapshot"
round
color="red"
icon="sync"
size="sm"
@click="syncPlugin(plugin.id, i)"
>
<q-tooltip>
Sync to latest version of plugin
</q-tooltip>
</q-btn>
</div>
</div>
</template>
</q-select>
</DialogComponent>
Expand Down Expand Up @@ -70,7 +95,7 @@
})

async function submitPlugins() {
let pluginsToAdd = []
let pluginsToAdd = [...pluginsToUpdate.value]
let pluginsToRemove = []

selectedPluginIds.value.forEach((plugin) => {
Expand All @@ -84,41 +109,21 @@
pluginsToRemove.push(plugin)
}
})

try {
// Wait for all add and remove operations to finish
const addPromise = (pluginsToAdd.length > 0) ? addPlugins(pluginsToAdd) : Promise.resolve()
const removePromises = pluginsToRemove.map(plugin => removePlugin(plugin))
await Promise.all([addPromise, ...removePromises]);

// Log after both operations are complete
emit('refreshTable')
if(pluginsToAdd.length > 0) {
await api.addPluginsToEntrypoint(props.editObj.id, pluginsToAdd)
}
for(const plugin of pluginsToRemove) {
await api.removePluginFromEntrypoint(props.editObj.id, plugin)
}
notify.success(`Successfully updated plugins for '${props.editObj.name}'`)
showDialog.value = false
emit('refreshTable')
} catch (err) {
notify.error("Error in processing plugins: " + err.message);
}
}


async function addPlugins(pluginsToAdd) {
try {
await api.addPluginsToEntrypoint(props.editObj.id, pluginsToAdd)
} catch(err) {
console.log('err = ', err)
notify.error(err.response.data.message);
}
}

async function removePlugin(plugin) {
try {
await api.removePluginFromEntrypoint(props.editObj.id, plugin)
} catch(err) {
notify.error(err.response.data.message);
}
}


async function getPlugins(val = '', update) {
update(async () => {
try {
Expand All @@ -127,11 +132,24 @@
rowsPerPage: 0, // get all
index: 0
})
pluginOptions.value = res.data.data
console.log('res = ', res)
pluginOptions.value = res.data.data.filter((plugin) => !selectedPluginIds.value.includes(plugin.id))
} catch(err) {
notify.error(err.response.data.message)
}
})
}

const pluginsToUpdate = ref([])

async function syncPlugin(pluginID, index) {
try {
const res = await api.getItem('plugins', pluginID)
selectedPlugins.value.splice(index, 1, res.data)
pluginsToUpdate.value.push(pluginID)
} catch(err) {
console.warn(err)
}
}

</script>
89 changes: 70 additions & 19 deletions src/frontend/src/views/CreateEntryPoint.vue
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,16 @@
<template v-slot:before>
<div class="field-label">Queues:</div>
</template>
<template v-slot:selected-item="scope">
<q-chip
:label="scope.opt.name"
removable
@remove="scope.removeAtIndex(scope.index)"
:tabindex="scope.tabindex"
color="primary"
text-color="white"
/>
</template>
</q-select>

<q-select
Expand All @@ -189,6 +199,44 @@
<div class="field-label">Plugins:</div>
</template>
</q-select>
<div class="row" v-if="route.params.id !== 'new' && entryPoint.plugins.length > 0">
<label class="field-label q-pt-xs">Plugins:</label>
<div
class="col"
style="border: 1px solid lightgray; border-radius: 4px; padding: 5px 8px; margin-left: 6px;"
>
<div
v-for="(plugin, i) in entryPoint.plugins"
:key="i"
>
<q-chip
:label="plugin.name"
color="secondary"
text-color="white"
>
<q-badge
v-if="!plugin.latestSnapshot"
color="red"
label="Outdated"
rounded
class="q-ml-xs"
/>
</q-chip>
<q-btn
v-if="!plugin.latestSnapshot"
round
color="red"
icon="sync"
size="sm"
@click="syncPlugin(plugin.id, i)"
>
<q-tooltip>
Sync to latest version of plugin
</q-tooltip>
</q-btn>
</div>
</div>
</div>
</div>

<TableComponent
Expand Down Expand Up @@ -335,26 +383,16 @@

watch(() => entryPoint.value.plugins, () => {
tasks.value = []
entryPoint.value.plugins.forEach(async(plugin) => {
let pluginID = typeof plugin === 'object' ? plugin.id : plugin
try {
const res = await api.getFiles(pluginID, {
search: '',
rowsPerPage: 0, // get all
index: 0
entryPoint.value.plugins.forEach((plugin) => {
if (typeof plugin === 'number') return
const pluginName = plugin.name
plugin.files.forEach((file) => {
file.tasks.forEach((task) => {
tasks.value.push({ ...task, pluginName: pluginName })
})
console.log('res = ', res)
res.data.data.forEach((file) => {
file.tasks.forEach((task) => {
task.pluginName = file.plugin.name
tasks.value.push(task)
})
})
} catch(err) {
console.warn(err)
}
})
})
})
}, { deep: true })

const parameter = reactive({
name: '',
Expand Down Expand Up @@ -505,6 +543,7 @@
parameters: entryPoint.value.parameters,
queues: entryPoint.value.queues,
})
await api.addPluginsToEntrypoint(route.params.id, pluginsToUpdate.value)
notify.success(`Successfully updated '${entryPoint.value.name}'`)
}
} catch(err) {
Expand Down Expand Up @@ -571,7 +610,6 @@
}

function addToTaskGraph(task) {
console.log('task = ', task)
let string = `<step-name>:\n ${task.name}:`
task.inputParams.forEach((param) => {
string += `\n ${param.name}: <input-value>`
Expand Down Expand Up @@ -629,4 +667,17 @@
confirmLeave.value = true
router.push(toPath.value)
}

const pluginsToUpdate = ref([])

async function syncPlugin(pluginID, index) {
try {
const res = await api.getItem('plugins', pluginID)
entryPoint.value.plugins.splice(index, 1, res.data)
pluginsToUpdate.value.push(pluginID)
} catch(err) {
console.warn(err)
}
}

</script>
Loading
Loading