mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-10 16:05:58 +00:00
listAssetsByUsage and asset nodes on transitive usages
This commit is contained in:
@@ -13005,31 +13005,50 @@ paths:
|
||||
usage_kind:
|
||||
$ref: '#/components/schemas/AssetUsageKind'
|
||||
|
||||
/w/{workspace}/assets/list_for_usage:
|
||||
get:
|
||||
summary: List all assets used by a given usage path
|
||||
operationId: listAssetsForUsage
|
||||
/w/{workspace}/assets/list_by_usages:
|
||||
post:
|
||||
summary: List all assets used by given usages paths
|
||||
operationId: listAssetsByUsage
|
||||
tags:
|
||||
- asset
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/WorkspaceId'
|
||||
- $ref: '#/components/parameters/AssetUsageKind'
|
||||
- $ref: '#/components/parameters/AssetUsagePath'
|
||||
requestBody:
|
||||
description: list assets by usages
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [usages]
|
||||
properties:
|
||||
usages:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [usage_path, usage_kind]
|
||||
properties:
|
||||
usage_path:
|
||||
type: string
|
||||
usage_kind:
|
||||
$ref: '#/components/schemas/AssetUsageKind'
|
||||
responses:
|
||||
'200':
|
||||
description: all assets used by the given usage path
|
||||
description: all assets used by the given usage paths, in the same order
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [path, kind]
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
kind:
|
||||
$ref: '#/components/schemas/AssetKind'
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: [path, kind]
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
kind:
|
||||
$ref: '#/components/schemas/AssetKind'
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
extract::Path,
|
||||
routing::{get, post},
|
||||
Extension, Json, Router,
|
||||
};
|
||||
@@ -17,7 +17,7 @@ pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
.route("/link", post(link_assets))
|
||||
.route("/list", get(list_assets))
|
||||
.route("/list_for_usage", get(list_assets_for_usage))
|
||||
.route("/list_by_usages", post(list_assets_by_usages))
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Copy, Clone, Hash, Eq, sqlx::Type)]
|
||||
@@ -42,6 +42,12 @@ pub struct Asset {
|
||||
pub kind: AssetKind,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Usage {
|
||||
usage_kind: AssetUsageKind,
|
||||
usage_path: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LinkAssetsBody {
|
||||
pub assets: Vec<Asset>,
|
||||
@@ -117,31 +123,37 @@ async fn list_assets(
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ListAssetForUsageQuery {
|
||||
usage_kind: AssetUsageKind,
|
||||
usage_path: String,
|
||||
struct ListAssetsByUsagesBody {
|
||||
usages: Vec<Usage>,
|
||||
}
|
||||
|
||||
async fn list_assets_for_usage(
|
||||
async fn list_assets_by_usages(
|
||||
authed: ApiAuthed,
|
||||
Path(w_id): Path<String>,
|
||||
Query(ListAssetForUsageQuery { usage_kind, usage_path }): Query<ListAssetForUsageQuery>,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
) -> JsonResult<Vec<Value>> {
|
||||
let assets = sqlx::query_scalar!(
|
||||
r#"SELECT
|
||||
jsonb_build_object(
|
||||
'path', path,
|
||||
'kind', kind
|
||||
) as "list!: _"
|
||||
FROM asset
|
||||
WHERE workspace_id = $1 AND usage_path = $2 AND usage_kind = $3"#,
|
||||
w_id,
|
||||
usage_path,
|
||||
usage_kind as AssetUsageKind
|
||||
)
|
||||
.fetch_all(&mut *user_db.begin(&authed).await?)
|
||||
.await?;
|
||||
Json(body): Json<ListAssetsByUsagesBody>,
|
||||
) -> JsonResult<Vec<Vec<Value>>> {
|
||||
let mut assets_vec = vec![];
|
||||
|
||||
Ok(Json(assets))
|
||||
let mut tx = user_db.begin(&authed).await?;
|
||||
|
||||
for usage in body.usages {
|
||||
let assets = sqlx::query_scalar!(
|
||||
r#"SELECT
|
||||
jsonb_build_object(
|
||||
'path', path,
|
||||
'kind', kind
|
||||
) as "list!: _"
|
||||
FROM asset
|
||||
WHERE workspace_id = $1 AND usage_path = $2 AND usage_kind = $3"#,
|
||||
w_id,
|
||||
usage.usage_path,
|
||||
usage.usage_kind as AssetUsageKind
|
||||
)
|
||||
.fetch_all(&mut *tx)
|
||||
.await?;
|
||||
assets_vec.push(assets);
|
||||
}
|
||||
|
||||
Ok(Json(assets_vec))
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export type FlowEditorContext = {
|
||||
|
||||
export type FlowGraphAssetContext = StateStore<{
|
||||
selectedAsset: Asset | undefined
|
||||
assetsMap?: Record<string, { asset: Asset; accessType: 'read' | 'write' }[]> // Maps module ids to their assets
|
||||
assetsMap: Record<string, { asset: Asset; accessType: 'read' | 'write' }[]> // Maps module ids to their assets
|
||||
s3FilePicker: S3FilePicker | undefined
|
||||
dbManagerDrawer: DbManagerDrawer | undefined
|
||||
resourceEditorDrawer: ResourceEditorDrawer | undefined
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { FlowService, ResourceService, type FlowModule } from '../../gen'
|
||||
import {
|
||||
AssetService,
|
||||
FlowService,
|
||||
ResourceService,
|
||||
type AssetUsageKind,
|
||||
type FlowModule
|
||||
} from '../../gen'
|
||||
import { NODE, type GraphModuleState } from '.'
|
||||
import { getContext, onDestroy, setContext, tick, untrack } from 'svelte'
|
||||
|
||||
@@ -191,6 +197,8 @@
|
||||
})
|
||||
setContext<FlowGraphAssetContext>('FlowGraphAssetContext', flowGraphAssetsCtx)
|
||||
const assetsMap = $derived(flowGraphAssetsCtx.val.assetsMap)
|
||||
|
||||
// Fetch resource metadata for the ExploreAssetButton
|
||||
const resMetadataCache = $derived(flowGraphAssetsCtx.val.resourceMetadataCache)
|
||||
$effect(() => {
|
||||
for (const { asset } of Object.values(assetsMap ?? []).flatMap((x) => x)) {
|
||||
@@ -201,6 +209,34 @@
|
||||
}
|
||||
})
|
||||
|
||||
// Fetch transitive assets (path scripts and flows)
|
||||
$effect(() => {
|
||||
if (!$workspaceStore) return
|
||||
let usages: { usage_path: string; usage_kind: AssetUsageKind }[] = []
|
||||
let modIds: string[] = []
|
||||
for (const mod of getAllModules(modules)) {
|
||||
if (mod.id in assetsMap) continue
|
||||
if (mod.value.type === 'flow' || mod.value.type === 'script') {
|
||||
usages.push({ usage_path: mod.value.path, usage_kind: mod.value.type })
|
||||
modIds.push(mod.id)
|
||||
}
|
||||
}
|
||||
if (usages.length) {
|
||||
AssetService.listAssetsByUsage({
|
||||
workspace: $workspaceStore,
|
||||
requestBody: { usages }
|
||||
}).then((result) => {
|
||||
result.map((assets, idx) => {
|
||||
const [usage, modId] = [usages[idx], modIds[idx]]
|
||||
assetsMap[modId] = assets.map((asset) => ({
|
||||
asset,
|
||||
accessType: usage.usage_kind === 'flow' ? 'read' : 'write'
|
||||
}))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
function computeSimplifiableFlow(modules: FlowModule[], simplifiedFlow: boolean) {
|
||||
const isSimplif = isSimplifiable(modules)
|
||||
simplifiableFlow = isSimplif ? { simplifiedFlow } : undefined
|
||||
|
||||
Reference in New Issue
Block a user