diff --git a/frontend/src/components/resources/stack/config.tsx b/frontend/src/components/resources/stack/config.tsx index fccc7d2f7..a469e0f9f 100644 --- a/frontend/src/components/resources/stack/config.tsx +++ b/frontend/src/components/resources/stack/config.tsx @@ -47,8 +47,9 @@ export const StackConfig = ({ if (!config) return null; const disabled = global_disabled || perms !== Types.PermissionLevel.Write; - const files_on_host = update.files_on_host ?? config.files_on_host; + const ui_file_contents = + (update.file_contents ?? config.file_contents ?? "").length > 0; return ( { - const https = update.git_https ?? config.git_https; - return ( - set({ git_provider })} - https={https} - onHttpsSwitch={() => set({ git_https: !https })} - /> - ); - }, - git_account: (value, set) => { - const server_id = update.server_id || config.server_id; - return ( - set({ git_account })} - disabled={disabled} - placeholder="None" - /> - ); - }, - repo: { - placeholder: "Enter repo", - description: - "The repo path on the provider. {namespace}/{repo_name}", - }, - branch: { - placeholder: "Enter branch", - description: "Select a custom branch, or default to 'main'.", - }, - commit: { - placeholder: "Enter a specific commit hash. Optional.", - description: - "Switch to a specific hash after cloning the branch.", + "Git Repo": !files_on_host && + !ui_file_contents && [ + { + label: "Git", + description: + "Provide config for repo-based compose files. Not necessary if file contents are configured in UI.", + components: { + git_provider: (provider, set) => { + const https = update.git_https ?? config.git_https; + return ( + set({ git_provider })} + https={https} + onHttpsSwitch={() => set({ git_https: !https })} + /> + ); + }, + git_account: (value, set) => { + const server_id = update.server_id || config.server_id; + return ( + set({ git_account })} + disabled={disabled} + placeholder="None" + /> + ); + }, + repo: { + placeholder: "Enter repo", + description: + "The repo path on the provider. {namespace}/{repo_name}", + }, + branch: { + placeholder: "Enter branch", + description: "Select a custom branch, or default to 'main'.", + }, + commit: { + placeholder: "Enter a specific commit hash. Optional.", + description: + "Switch to a specific hash after cloning the branch.", + }, }, }, - }, - { - label: "Run Path", - labelHidden: true, - components: { - run_directory: { - placeholder: "./", - description: - "Set the cwd when running compose up command. Relative to the repo root.", - boldLabel: true, + { + label: "Run Path", + labelHidden: true, + components: { + run_directory: { + placeholder: "./", + description: + "Set the cwd when running compose up command. Relative to the repo root.", + boldLabel: true, + }, }, }, - }, - { - label: "File Paths", - description: - "Add files to include using 'docker compose -f'. If empty, uses 'compose.yaml'. Relative to 'Run Directory'.", - contentHidden: - (update.file_paths ?? config.file_paths)?.length === 0, - actions: !disabled && ( - - ), - components: { - file_paths: (value, set) => ( - + { + label: "File Paths", + description: + "Add files to include using 'docker compose -f'. If empty, uses 'compose.yaml'. Relative to 'Run Directory'.", + contentHidden: + (update.file_paths ?? config.file_paths)?.length === 0, + actions: !disabled && ( + ), - }, - }, - { - label: "Git Webhooks", - description: - "Configure your repo provider to send webhooks to Monitor", - components: { - ["Guard" as any]: () => { - if (update.branch ?? config.branch) { - return null; - } - return ( - -
Must configure Branch before webhooks will work.
-
- ); - }, - ["Refresh" as any]: () => - (update.branch ?? config.branch) && ( - - - + components: { + file_paths: (value, set) => ( + ), - ["Deploy" as any]: () => - (update.branch ?? config.branch) && ( - - - - ), - webhook_enabled: - !!(update.branch ?? config.branch) && - webhooks !== undefined && - !webhooks.managed, - webhook_secret: { - description: - "Provide a custom webhook secret for this resource, or use the global default.", - placeholder: "Input custom secret", - }, - ["managed" as any]: () => { - const inv = useInvalidate(); - const { toast } = useToast(); - const { mutate: createWebhook, isPending: createPending } = - useWrite("CreateStackWebhook", { - onSuccess: () => { - toast({ title: "Webhook Created" }); - inv(["GetStackWebhooksEnabled", { stack: id }]); - }, - }); - const { mutate: deleteWebhook, isPending: deletePending } = - useWrite("DeleteStackWebhook", { - onSuccess: () => { - toast({ title: "Webhook Deleted" }); - inv(["GetStackWebhooksEnabled", { stack: id }]); - }, - }); - - if ( - !(update.branch ?? config.branch) || - !webhooks || - !webhooks.managed - ) { - return null; - } - - return ( - - {webhooks.deploy_enabled && ( -
-
- Incoming webhook is{" "} -
- ENABLED -
- and will trigger -
- DEPLOY -
-
- } - variant="destructive" - onClick={() => - deleteWebhook({ - stack: id, - action: Types.StackWebhookAction.Deploy, - }) - } - loading={deletePending} - disabled={disabled || deletePending} - /> -
- )} - {!webhooks.deploy_enabled && webhooks.refresh_enabled && ( -
-
- Incoming webhook is{" "} -
- ENABLED -
- and will trigger -
- REFRESH -
-
- } - variant="destructive" - onClick={() => - deleteWebhook({ - stack: id, - action: Types.StackWebhookAction.Refresh, - }) - } - loading={deletePending} - disabled={disabled || deletePending} - /> -
- )} - {!webhooks.deploy_enabled && !webhooks.refresh_enabled && ( -
-
- Incoming webhook is{" "} -
- DISABLED -
-
- } - onClick={() => - createWebhook({ - stack: id, - action: Types.StackWebhookAction.Deploy, - }) - } - loading={createPending} - disabled={disabled || createPending} - /> - } - onClick={() => - createWebhook({ - stack: id, - action: Types.StackWebhookAction.Refresh, - }) - } - loading={createPending} - disabled={disabled || createPending} - /> -
- )} -
- ); }, }, - }, - ], + { + label: "Git Webhooks", + description: + "Configure your repo provider to send webhooks to Monitor", + components: { + ["Guard" as any]: () => { + if (update.branch ?? config.branch) { + return null; + } + return ( + +
+ Must configure Branch before webhooks will work. +
+
+ ); + }, + ["Refresh" as any]: () => + (update.branch ?? config.branch) && ( + + + + ), + ["Deploy" as any]: () => + (update.branch ?? config.branch) && ( + + + + ), + webhook_enabled: + !!(update.branch ?? config.branch) && + webhooks !== undefined && + !webhooks.managed, + webhook_secret: { + description: + "Provide a custom webhook secret for this resource, or use the global default.", + placeholder: "Input custom secret", + }, + ["managed" as any]: () => { + const inv = useInvalidate(); + const { toast } = useToast(); + const { mutate: createWebhook, isPending: createPending } = + useWrite("CreateStackWebhook", { + onSuccess: () => { + toast({ title: "Webhook Created" }); + inv(["GetStackWebhooksEnabled", { stack: id }]); + }, + }); + const { mutate: deleteWebhook, isPending: deletePending } = + useWrite("DeleteStackWebhook", { + onSuccess: () => { + toast({ title: "Webhook Deleted" }); + inv(["GetStackWebhooksEnabled", { stack: id }]); + }, + }); + + if ( + !(update.branch ?? config.branch) || + !webhooks || + !webhooks.managed + ) { + return null; + } + + return ( + + {webhooks.deploy_enabled && ( +
+
+ Incoming webhook is{" "} +
+ ENABLED +
+ and will trigger +
+ DEPLOY +
+
+ } + variant="destructive" + onClick={() => + deleteWebhook({ + stack: id, + action: Types.StackWebhookAction.Deploy, + }) + } + loading={deletePending} + disabled={disabled || deletePending} + /> +
+ )} + {!webhooks.deploy_enabled && webhooks.refresh_enabled && ( +
+
+ Incoming webhook is{" "} +
+ ENABLED +
+ and will trigger +
+ REFRESH +
+
+ } + variant="destructive" + onClick={() => + deleteWebhook({ + stack: id, + action: Types.StackWebhookAction.Refresh, + }) + } + loading={deletePending} + disabled={disabled || deletePending} + /> +
+ )} + {!webhooks.deploy_enabled && + !webhooks.refresh_enabled && ( +
+
+ Incoming webhook is{" "} +
+ DISABLED +
+
+ } + onClick={() => + createWebhook({ + stack: id, + action: Types.StackWebhookAction.Deploy, + }) + } + loading={createPending} + disabled={disabled || createPending} + /> + } + onClick={() => + createWebhook({ + stack: id, + action: Types.StackWebhookAction.Refresh, + }) + } + loading={createPending} + disabled={disabled || createPending} + /> +
+ )} +
+ ); + }, + }, + }, + ], environment: [ { label: "Environment",