mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
fix: address second round of review findings
- Remove bidirectional $effect sync in RawAppSidebar; bind FileExplorer
directly to files prop with {} default
- Avoid creating new files object on every keystroke in FilesetEditor;
merge editContent → args in a single effect without intermediate spread
- Simplify no-op `?? undefined` in addResourceType
- Add backend validation: reject create_resource_type when both
is_fileset and format_extension are set
- Fix fileset alert title showing undefined format extension
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
1b4489acac
commit
753c05a030
@@ -1345,6 +1345,12 @@ async fn create_resource_type(
|
||||
|
||||
let is_fileset = resource_type.is_fileset.unwrap_or(false);
|
||||
|
||||
if is_fileset && resource_type.format_extension.is_some() {
|
||||
return Err(Error::BadRequest(
|
||||
"A fileset resource type cannot have a format_extension".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO resource_type
|
||||
(workspace_id, name, schema, description, created_by, format_extension, is_fileset, edited_at)
|
||||
|
||||
@@ -32,28 +32,30 @@
|
||||
selectedFileKey?.replace(/^\//, '')
|
||||
)
|
||||
|
||||
function flushEditContent() {
|
||||
if (selectedFileKey != null && selectedFileKey in files && files[selectedFileKey] !== editContent) {
|
||||
files = { ...files, [selectedFileKey]: editContent }
|
||||
}
|
||||
}
|
||||
|
||||
function handleSelectPath(path: string) {
|
||||
flushEditContent()
|
||||
selectedPath = path
|
||||
if (!path.endsWith('/') && path !== '') {
|
||||
editContent = files[path] ?? ''
|
||||
}
|
||||
}
|
||||
|
||||
// Sync editContent → files → args reactively
|
||||
$effect(() => {
|
||||
const key = selectedFileKey
|
||||
const content = editContent
|
||||
if (key != null && key in files && files[key] !== content) {
|
||||
files = { ...files, [key]: content }
|
||||
}
|
||||
})
|
||||
|
||||
// Sync files → args (strip / prefix, skip folder entries)
|
||||
// Sync files → args, overlaying current editContent for the active file.
|
||||
// This avoids spreading a new files object on every keystroke.
|
||||
$effect(() => {
|
||||
const currentKey = selectedFileKey
|
||||
const currentContent = editContent
|
||||
const newArgs: Record<string, any> = {}
|
||||
for (const [key, value] of Object.entries(files)) {
|
||||
if (!key.endsWith('/')) {
|
||||
newArgs[key.replace(/^\//, '')] = value
|
||||
const argKey = key.replace(/^\//, '')
|
||||
newArgs[argKey] = key === currentKey ? currentContent : value
|
||||
}
|
||||
}
|
||||
args = newArgs
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
interface Props {
|
||||
runnables: Record<string, Runnable>
|
||||
selectedRunnable: string | undefined
|
||||
files: Record<string, string> | undefined
|
||||
files: Record<string, string>
|
||||
modules?: Modules
|
||||
onSelectFile?: (path: string) => void
|
||||
selectedDocument: string | undefined
|
||||
@@ -37,7 +37,7 @@
|
||||
let {
|
||||
runnables,
|
||||
selectedRunnable = $bindable(),
|
||||
files = $bindable(),
|
||||
files = $bindable({}),
|
||||
modules,
|
||||
onSelectFile,
|
||||
selectedDocument = $bindable(),
|
||||
@@ -74,21 +74,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure files is always an object for FileExplorer binding
|
||||
let explorerFiles: Record<string, string> = $state(files ?? {})
|
||||
|
||||
// Sync explorerFiles → files (parent binding)
|
||||
$effect(() => {
|
||||
files = explorerFiles
|
||||
})
|
||||
|
||||
// Sync files → explorerFiles when files changes externally
|
||||
$effect(() => {
|
||||
if (files && files !== explorerFiles) {
|
||||
explorerFiles = files
|
||||
}
|
||||
})
|
||||
|
||||
let fileExplorer: FileExplorer | undefined = $state()
|
||||
|
||||
function handleSelectPath(path: string) {
|
||||
@@ -126,7 +111,7 @@
|
||||
{/snippet}
|
||||
<FileExplorer
|
||||
bind:this={fileExplorer}
|
||||
bind:files={explorerFiles}
|
||||
bind:files
|
||||
selectedPath={selectedDocument}
|
||||
onSelectPath={handleSelectPath}
|
||||
extraNodes={[{ name: 'wmill.ts', path: '/wmill.ts', isFolder: false }]}
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
schema: newResourceType.schema,
|
||||
description: newResourceType.description,
|
||||
format_extension: newResourceType.formatExtension,
|
||||
is_fileset: newResourceType.isFileset ?? undefined
|
||||
is_fileset: newResourceType.isFileset
|
||||
}
|
||||
})
|
||||
resourceTypeDrawer?.closeDrawer?.()
|
||||
@@ -658,7 +658,7 @@
|
||||
>
|
||||
<div>
|
||||
{#if editResourceType.isFileset}
|
||||
<Alert type="info" title="Fileset resource (.{editResourceType.formatExtension})">
|
||||
<Alert type="info" title="Fileset resource type">
|
||||
This resource type represents a collection of files. The schema cannot be edited.
|
||||
</Alert>
|
||||
{:else if editResourceType.formatExtension}
|
||||
|
||||
Reference in New Issue
Block a user