feat(scripts/data-resources): merge tree + add parent_path filter
- Backend: GET /api/v1/data-resources accepts parent_path; LIKE
'{ws_id}/%/{escaped}/%' AND NOT LIKE '{ws_id}/%/{escaped}/%/%' on
StorageObjects.object_key (workspace-wide, escapes _ and %, mirrors
list_scripts parent_path semantics). 13 new tests in
test_resources.py (helper unit / SQL compile / SQLite behavioral).
- Frontend: listResources gains parentPath arg, propagated through
WorkspaceBoundApi + AuthContext binding. WorkspaceTreeGroup title
count and ScriptExplorer header count now include dataResources.
memberScriptGroups backfills data-only owners so users with only
data resources still render a group. loadDataResources accepts an
optional parentPath, default empty preserves prior behavior.
This commit is contained in:
@@ -437,9 +437,14 @@ export type ResourceItem = {
|
||||
|
||||
export async function listResources(
|
||||
workspaceId: string,
|
||||
parentPath: string = "",
|
||||
opts?: { visibility?: string; keyword?: string },
|
||||
): Promise<ResourceItem[]> {
|
||||
// Empty parentPath omits the query string entirely so the backend's
|
||||
// workspace-wide (root-level) filter is applied symmetrically with
|
||||
// non-empty paths, matching listScripts.
|
||||
const parameters = new URLSearchParams();
|
||||
if (parentPath) parameters.set("parent_path", parentPath);
|
||||
if (opts?.visibility) parameters.set("visibility", opts.visibility);
|
||||
if (opts?.keyword) parameters.set("keyword", opts.keyword);
|
||||
const query = parameters.toString();
|
||||
@@ -1484,7 +1489,8 @@ export type WorkspaceBoundApi = {
|
||||
) => Promise<ScriptItem[]>;
|
||||
countScripts: () => Promise<number>;
|
||||
listResources: (
|
||||
opts?: Parameters<typeof listResources>[1],
|
||||
parentPath?: Parameters<typeof listResources>[1],
|
||||
opts?: Parameters<typeof listResources>[2],
|
||||
) => Promise<ResourceItem[]>;
|
||||
createScript: (
|
||||
input: Parameters<typeof createScript>[1],
|
||||
|
||||
Reference in New Issue
Block a user