diff --git a/dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts b/dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts index 6c0f9782..f14c678c 100644 --- a/dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts +++ b/dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts @@ -660,6 +660,75 @@ export class SimpleCommit extends Message { } } +/** + * @generated from message neoshowcase.protobuf.AutoShutdownConfig + */ +export class AutoShutdownConfig extends Message { + /** + * @generated from field: bool enabled = 1; + */ + enabled = false; + + /** + * @generated from field: neoshowcase.protobuf.AutoShutdownConfig.StartupBehavior startup = 2; + */ + startup = AutoShutdownConfig_StartupBehavior.UNDEFINED; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "neoshowcase.protobuf.AutoShutdownConfig"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "enabled", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 2, name: "startup", kind: "enum", T: proto3.getEnumType(AutoShutdownConfig_StartupBehavior) }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): AutoShutdownConfig { + return new AutoShutdownConfig().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): AutoShutdownConfig { + return new AutoShutdownConfig().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): AutoShutdownConfig { + return new AutoShutdownConfig().fromJsonString(jsonString, options); + } + + static equals(a: AutoShutdownConfig | PlainMessage | undefined, b: AutoShutdownConfig | PlainMessage | undefined): boolean { + return proto3.util.equals(AutoShutdownConfig, a, b); + } +} + +/** + * @generated from enum neoshowcase.protobuf.AutoShutdownConfig.StartupBehavior + */ +export enum AutoShutdownConfig_StartupBehavior { + /** + * @generated from enum value: UNDEFINED = 0; + */ + UNDEFINED = 0, + + /** + * @generated from enum value: LOADING_PAGE = 1; + */ + LOADING_PAGE = 1, + + /** + * @generated from enum value: BLOCKING = 2; + */ + BLOCKING = 2, +} +// Retrieve enum metadata with: proto3.getEnumType(AutoShutdownConfig_StartupBehavior) +proto3.util.setEnumType(AutoShutdownConfig_StartupBehavior, "neoshowcase.protobuf.AutoShutdownConfig.StartupBehavior", [ + { no: 0, name: "UNDEFINED" }, + { no: 1, name: "LOADING_PAGE" }, + { no: 2, name: "BLOCKING" }, +]); + /** * @generated from message neoshowcase.protobuf.RuntimeConfig */ @@ -685,9 +754,9 @@ export class RuntimeConfig extends Message { command = ""; /** - * @generated from field: bool auto_shutdown = 5; + * @generated from field: neoshowcase.protobuf.AutoShutdownConfig auto_shutdown = 5; */ - autoShutdown = false; + autoShutdown?: AutoShutdownConfig; constructor(data?: PartialMessage) { super(); @@ -701,7 +770,7 @@ export class RuntimeConfig extends Message { { no: 2, name: "use_mongodb", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, { no: 3, name: "entrypoint", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 4, name: "command", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 5, name: "auto_shutdown", kind: "scalar", T: 8 /* ScalarType.BOOL */ }, + { no: 5, name: "auto_shutdown", kind: "message", T: AutoShutdownConfig }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): RuntimeConfig { diff --git a/dashboard/src/components/templates/CheckBox.tsx b/dashboard/src/components/templates/CheckBox.tsx index cba39de1..c9457ab3 100644 --- a/dashboard/src/components/templates/CheckBox.tsx +++ b/dashboard/src/components/templates/CheckBox.tsx @@ -27,6 +27,7 @@ const labelStyle = style({ alignItems: 'center', justifyItems: 'start', gap: '8px', + whiteSpace: 'nowrap', background: colorVars.semantic.ui.primary, borderRadius: '8px', diff --git a/dashboard/src/features/application/components/form/config/deploy/RuntimeConfigField.tsx b/dashboard/src/features/application/components/form/config/deploy/RuntimeConfigField.tsx index f096f3e2..651cf516 100644 --- a/dashboard/src/features/application/components/form/config/deploy/RuntimeConfigField.tsx +++ b/dashboard/src/features/application/components/form/config/deploy/RuntimeConfigField.tsx @@ -1,5 +1,6 @@ import { Field, getValues, setValues } from '@modular-forms/solid' import { type Component, Show, createEffect, createResource } from 'solid-js' +import { AutoShutdownConfig_StartupBehavior } from '/@/api/neoshowcase/protobuf/gateway_pb' import { TextField } from '/@/components/UI/TextField' import { ToolTip } from '/@/components/UI/ToolTip' import { CheckBox } from '/@/components/templates/CheckBox' @@ -49,30 +50,27 @@ const RuntimeConfigField: Component = (props) => { } }) - const AutoShutdownField = () => ( - - {(field, fieldProps) => ( - アプリへのアクセスが一定期間ない場合、自動でアプリをシャットダウンします }, - }} - > - - - )} - - ) + // @ts-expect-error: autoShutdown は deployConfig.type === "static" の時存在しないためtsの型の仕様上エラーが出る + const autoShutdown = () => getValues(formStore).form?.config?.deployConfig?.value?.runtime?.autoShutdown?.enabled + + const setStartupBehavior = (value: string | undefined) => { + setValues(formStore, { + form: { + config: { + deployConfig: { + value: { + // @ts-expect-error: deployConfig は form.type === "static" の時存在しないためtsの型の仕様上エラーが出る + runtime: { + autoShutdown: { + startup: value, + }, + }, + }, + }, + }, + }, + }) + } const EntryPointField = () => ( @@ -188,7 +186,6 @@ const RuntimeConfigField: Component = (props) => { - @@ -198,6 +195,73 @@ const RuntimeConfigField: Component = (props) => { + + + + {(field, fieldProps) => ( + + )} + + + + + + + {(field, fieldProps) => ( + + )} + + + ) } diff --git a/dashboard/src/features/application/schema/applicationConfigSchema.ts b/dashboard/src/features/application/schema/applicationConfigSchema.ts index ce7bf2d1..ecdcf09d 100644 --- a/dashboard/src/features/application/schema/applicationConfigSchema.ts +++ b/dashboard/src/features/application/schema/applicationConfigSchema.ts @@ -1,7 +1,7 @@ import type { PartialMessage } from '@bufbuild/protobuf' import { P, match } from 'ts-pattern' import * as v from 'valibot' -import type { ApplicationConfig } from '/@/api/neoshowcase/protobuf/gateway_pb' +import { type ApplicationConfig, AutoShutdownConfig_StartupBehavior } from '/@/api/neoshowcase/protobuf/gateway_pb' import { stringBooleanSchema } from '/@/libs/schemaUtil' const optionalBooleanSchema = (defaultValue = false) => @@ -10,12 +10,37 @@ const optionalBooleanSchema = (defaultValue = false) => v.transform((i) => i ?? defaultValue), ) +const autoShutdownSchema = v.optional( + v.object({ + enabled: v.boolean(), + startup: v.pipe( + v.optional( + v.union([ + v.literal(`${AutoShutdownConfig_StartupBehavior.LOADING_PAGE}`), + v.literal(`${AutoShutdownConfig_StartupBehavior.BLOCKING}`), + ]), + ), + v.transform((input) => { + return match(input) + .returnType() + .with(undefined, () => AutoShutdownConfig_StartupBehavior.UNDEFINED) + .with( + `${AutoShutdownConfig_StartupBehavior.LOADING_PAGE}`, + () => AutoShutdownConfig_StartupBehavior.LOADING_PAGE, + ) + .with(`${AutoShutdownConfig_StartupBehavior.BLOCKING}`, () => AutoShutdownConfig_StartupBehavior.BLOCKING) + .exhaustive() + }), + ), + }), +) + const runtimeConfigSchema = v.object({ useMariadb: optionalBooleanSchema(), useMongodb: optionalBooleanSchema(), entrypoint: v.string(), command: v.string(), - autoShutdown: v.boolean(), + autoShutdown: autoShutdownSchema, }) const staticConfigSchema = v.object({ artifactPath: v.pipe(v.string(), v.nonEmpty('Enter Artifact Path')), @@ -184,12 +209,16 @@ export const configMessageToSchema = (config: ApplicationConfig): ApplicationCon (buildConfig) => ({ type: 'runtime', value: { - runtime: buildConfig.value.runtimeConfig ?? { - command: '', - entrypoint: '', - useMariadb: false, - useMongodb: false, - autoShutdown: false, + runtime: { + ...buildConfig.value.runtimeConfig, + entrypoint: buildConfig.value.runtimeConfig?.entrypoint ?? '', + command: buildConfig.value.runtimeConfig?.command ?? '', + autoShutdown: { + enabled: buildConfig.value.runtimeConfig?.autoShutdown?.enabled ?? false, + startup: buildConfig.value.runtimeConfig?.autoShutdown?.startup + ? `${buildConfig.value.runtimeConfig.autoShutdown.startup}` + : undefined, + }, }, }, }), diff --git a/dashboard/src/features/application/schema/applicationSchema.test.ts b/dashboard/src/features/application/schema/applicationSchema.test.ts index d3425a60..5b4532e0 100644 --- a/dashboard/src/features/application/schema/applicationSchema.test.ts +++ b/dashboard/src/features/application/schema/applicationSchema.test.ts @@ -1,6 +1,10 @@ import { safeParse } from 'valibot' import { describe, expect, test } from 'vitest' -import { AuthenticationType, PortPublicationProtocol } from '/@/api/neoshowcase/protobuf/gateway_pb' +import { + AuthenticationType, + AutoShutdownConfig_StartupBehavior, + PortPublicationProtocol, +} from '/@/api/neoshowcase/protobuf/gateway_pb' import { createOrUpdateApplicationSchema } from './applicationSchema' const validator = (input: unknown) => safeParse(createOrUpdateApplicationSchema, input) @@ -15,7 +19,9 @@ describe('Create Application Schema', () => { useMongodb: false, entrypoint: '.', command: "echo 'test'", - autoShutdown: false, + autoShutdown: { + enabled: false, + }, }, }, }, @@ -109,7 +115,9 @@ describe('Create Application Schema', () => { useMongodb: false, entrypoint: '.', command: "echo 'test'", - autoShutdown: false, + autoShutdown: { + enabled: false, + }, }, }, }, @@ -142,7 +150,9 @@ describe('Create Application Schema', () => { useMongodb: false, entrypoint: '.', command: "echo 'test'", - autoShutdown: false, + autoShutdown: { + enabled: false, + }, }, }, }, @@ -176,7 +186,9 @@ describe('Create Application Schema', () => { useMongodb: false, entrypoint: '.', command: "echo 'test'", - autoShutdown: false, + autoShutdown: { + enabled: false, + }, }, }, }, diff --git a/dashboard/src/libs/application.tsx b/dashboard/src/libs/application.tsx index 1b56ab2a..c1423b4d 100644 --- a/dashboard/src/libs/application.tsx +++ b/dashboard/src/libs/application.tsx @@ -36,7 +36,7 @@ const autoShutdownEnabled = (app: Application): boolean => { case 'runtimeBuildpack': case 'runtimeCmd': case 'runtimeDockerfile': - return app.config.buildConfig.value.runtimeConfig?.autoShutdown ?? false + return app.config.buildConfig.value.runtimeConfig?.autoShutdown?.enabled ?? false } return false }