Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dashboard] form周りの改善(valibotの使用, contextの利用) #938

Merged
merged 53 commits into from
Aug 24, 2024
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
30100e4
use valibot in repository form
eyemono-moe Jul 22, 2024
cb2a8b0
add repository schema tests
eyemono-moe Jul 22, 2024
7139c26
omit destructuring
eyemono-moe Jul 22, 2024
bf0a6f1
rename schema types -> input
eyemono-moe Jul 22, 2024
c6a39fe
add test case
eyemono-moe Jul 22, 2024
f1f71d0
wip application formのvalibot化
eyemono-moe Jul 22, 2024
c690e04
wip: applicationのform作成
eyemono-moe Jul 25, 2024
728bac6
wip: appのビルド設定部分の修正
eyemono-moe Jul 26, 2024
32f9124
refactor: valibotによるtransformでMessageに変換するように
eyemono-moe Jul 26, 2024
cf9a85e
separate create/update handler
eyemono-moe Jul 26, 2024
f479630
update application schema
eyemono-moe Jul 26, 2024
e86c6a3
reafactor type
eyemono-moe Jul 27, 2024
dd540ed
application general config
eyemono-moe Jul 27, 2024
e80cb7f
application config form
eyemono-moe Jul 27, 2024
6de0625
isSPAのデフォルト値を設定
eyemono-moe Jul 27, 2024
376e3fa
fix: ブランチが見つからなかった時のエラー文面を修正
eyemono-moe Jul 27, 2024
aa7269b
wip: website設定
eyemono-moe Aug 3, 2024
8e9a9ab
fmt
eyemono-moe Aug 15, 2024
146b0e7
wip: websites設定
eyemono-moe Aug 15, 2024
e889a9a
chore: Update WebsiteFieldGroup component to disable save button when…
eyemono-moe Aug 15, 2024
3e07d21
fix: singleSelectのhiddenSelectのonChangeが動いていなかった
eyemono-moe Aug 15, 2024
a18da26
chore: refactor URL form
eyemono-moe Aug 15, 2024
af4fdaf
fix: authAvailableがfalseの時自動で認証offを選択するように
eyemono-moe Aug 15, 2024
47fb627
fix type issue
eyemono-moe Aug 15, 2024
5379506
remove debug logs
eyemono-moe Aug 15, 2024
c3ba25f
chore: style URL form and add website warnings
eyemono-moe Aug 16, 2024
5c0da12
chore: remove debug logs
eyemono-moe Aug 16, 2024
0429719
feat: use valibot form in PortForwarding
eyemono-moe Aug 16, 2024
e1180f4
chore: Update useFormContext error message
eyemono-moe Aug 17, 2024
424508a
feat: 環境変数設定formでのvalibotの使用
eyemono-moe Aug 17, 2024
ec5b88d
remove debug logs
eyemono-moe Aug 17, 2024
f507fc9
wip: replace create application form
eyemono-moe Aug 17, 2024
9a6e21c
feat: URL設定でFieldArrayを使用するように
eyemono-moe Aug 23, 2024
1c0a389
fix: useDBの値が正しく表示されていなかった
eyemono-moe Aug 23, 2024
2e89dea
chore: create時のwebsiteとportPublicationsをoptionalに
eyemono-moe Aug 23, 2024
75f996e
chore: appFormのvalidationタイミングを変更
eyemono-moe Aug 23, 2024
e40c986
feat: use new form system in create app form
eyemono-moe Aug 23, 2024
c950f87
remove unused form components
eyemono-moe Aug 23, 2024
22a9d9f
remove DiscardChanges buttons
eyemono-moe Aug 23, 2024
0dbf64d
fix: websiteを空に出来なくなっていた
eyemono-moe Aug 23, 2024
df202a9
remove logs
eyemono-moe Aug 23, 2024
8cd0b6b
fix test
eyemono-moe Aug 23, 2024
c9d5c2f
Merge branch 'main' into fix/use-valibot
eyemono-moe Aug 23, 2024
d947517
chore: pin dependencies versions
eyemono-moe Aug 23, 2024
b08e374
update: yarn.lock
eyemono-moe Aug 23, 2024
3b4bd0e
remove unnecessary comments
eyemono-moe Aug 24, 2024
71dbec3
remove unused import
eyemono-moe Aug 24, 2024
479d1fd
chore: matchで改行が多くなっていたので1行にまとめた
eyemono-moe Aug 24, 2024
652cca2
chore: simplify transform return value
eyemono-moe Aug 24, 2024
c5201db
refactor: replace initialValues func name
eyemono-moe Aug 24, 2024
9364326
refactor: ts-patternのexhaustiveが使える箇所では使うように
eyemono-moe Aug 24, 2024
34ee384
test: add envVars test
eyemono-moe Aug 24, 2024
c328c07
Merge branch 'main' into fix/use-valibot
eyemono-moe Aug 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/dashboard-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,18 @@ jobs:
- run: corepack enable
- run: yarn install --immutable
- run: yarn typecheck
test:
name: Test
runs-on: ubuntu-latest
needs: [packages]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: corepack enable
- run: yarn install --immutable
- run: yarn test
build:
name: Build
runs-on: ubuntu-latest
Expand Down
11 changes: 8 additions & 3 deletions dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"fix": "yarn fmt:apply && yarn lint:apply",
"typecheck": "tsc --noEmit",
"ci": "biome ci src",
"analyze": "vite build --mode analyze"
"analyze": "vite build --mode analyze",
"test": "vitest"
},
"license": "MIT",
"devDependencies": {
Expand All @@ -24,13 +25,15 @@
"@macaron-css/vite": "1.5.1",
"@tanstack/virtual-core": "3.8.4",
"@types/node": "22.1.0",
"jsdom": "^24.1.1",
eyemono-moe marked this conversation as resolved.
Show resolved Hide resolved
"rollup-plugin-visualizer": "5.12.0",
"typescript": "5.5.4",
"unplugin-fonts": "1.1.1",
"vite": "5.3.5",
"vite-plugin-compression": "0.5.1",
"vite-plugin-solid": "2.10.2",
"vite-plugin-solid-svg": "0.8.1"
"vite-plugin-solid-svg": "0.8.1",
"vitest": "^2.0.3"
},
"dependencies": {
"@bufbuild/protobuf": "1.10.0",
Expand All @@ -52,7 +55,9 @@
"solid-js": "1.8.19",
"solid-tippy": "0.2.1",
"solid-toast": "0.5.0",
"tippy.js": "6.3.7"
"tippy.js": "6.3.7",
"ts-pattern": "^5.2.0",
"valibot": "^0.36.0"
},
"packageManager": "[email protected]+sha512.ec40d0639bb307441b945d9467139cbb88d14394baac760b52eca038b330d16542d66fef61574271534ace5a200518dabf3b53a85f1f9e4bfa37141b538a9590"
}
90 changes: 73 additions & 17 deletions dashboard/src/components/templates/RadioGroups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { style } from '@macaron-css/core'
import { styled } from '@macaron-css/solid'
import { For, type JSX, Show, splitProps } from 'solid-js'
import { colorOverlay } from '/@/libs/colorOverlay'
import { colorVars, textVars } from '/@/theme'
import { colorVars, media, textVars } from '/@/theme'
import { RadioIcon } from '../UI/RadioIcon'
import { ToolTip, type TooltipProps } from '../UI/ToolTip'
import { TooltipInfoIcon } from '../UI/TooltipInfoIcon'
Expand All @@ -13,21 +13,41 @@ const OptionsContainer = styled('div', {
base: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
gap: '16px',
},
variants: {
wrap: {
true: {
flexWrap: 'wrap',
},
false: {
flexWrap: 'nowrap',
'@media': {
[media.mobile]: {
flexDirection: 'column',
},
},
},
},
},
defaultVariants: {
wrap: 'true',
},
})
const fullItemStyle = style({
width: '100%',
minWidth: 'min(200px, 100%)',
})
const itemStyle = style({
const fitItemStyle = style({
width: 'fit-content',
minWidth: 'min(200px, 100%)',
})
const labelStyle = style({
width: '100%',
height: '100%',
padding: '16px',
display: 'grid',
gridTemplateColumns: '1fr 20px',
alignItems: 'center',
justifyItems: 'start',
display: 'flex',
flexDirection: 'column',
gap: '8px',

background: colorVars.semantic.ui.primary,
Expand Down Expand Up @@ -57,10 +77,33 @@ const labelStyle = style({
},
},
})
const ItemTitle = styled('div', {
base: {
display: 'grid',
gridTemplateColumns: '1fr 20px',
alignItems: 'center',
justifyItems: 'start',
gap: '8px',
color: colorVars.semantic.text.black,
...textVars.text.regular,
},
})
const Description = styled('div', {
base: {
color: colorVars.semantic.text.black,
...textVars.caption.regular,
},
})
export const errorTextStyle = style({
width: '100%',
color: colorVars.semantic.accent.error,
...textVars.text.regular,
})

export interface RadioOption<T extends string> {
value: T
label: string
description?: string
}

export interface Props<T extends string> {
Expand All @@ -70,6 +113,8 @@ export interface Props<T extends string> {
options: RadioOption<T>[]
value?: T
setValue?: (value: T) => void
wrap?: boolean
full?: boolean
required?: boolean
disabled?: boolean
readOnly?: boolean
Expand All @@ -85,7 +130,7 @@ export const RadioGroup = <T extends string>(props: Props<T>): JSX.Element => {
const [rootProps, _addedProps, inputProps] = splitProps(
props,
['name', 'value', 'options', 'required', 'disabled', 'readOnly'],
['info', 'tooltip', 'setValue'],
['wrap', 'full', 'info', 'tooltip', 'setValue', 'error', 'label'],
)

return (
Expand All @@ -108,25 +153,36 @@ export const RadioGroup = <T extends string>(props: Props<T>): JSX.Element => {
</TitleContainer>
</Show>
<ToolTip {...props.tooltip}>
<OptionsContainer>
<OptionsContainer wrap={props.wrap}>
<For each={props.options}>
{(option) => (
<KRadioGroup.Item value={option.value} class={itemStyle}>
<KRadioGroup.Item
value={option.value}
classList={{
[fullItemStyle]: props.full,
[fitItemStyle]: !props.full,
}}
>
<KRadioGroup.ItemInput {...inputProps} />
<KRadioGroup.ItemLabel class={labelStyle}>
{option.label}
<KRadioGroup.ItemControl>
<KRadioGroup.ItemIndicator forceMount>
<RadioIcon selected={option.value === props.value} />
</KRadioGroup.ItemIndicator>
</KRadioGroup.ItemControl>
<ItemTitle>
{option.label}
<KRadioGroup.ItemControl>
<KRadioGroup.ItemIndicator forceMount>
<RadioIcon selected={option.value === props.value} />
</KRadioGroup.ItemIndicator>
</KRadioGroup.ItemControl>
</ItemTitle>
<Show when={option.description}>
<Description>{option.description}</Description>
</Show>
</KRadioGroup.ItemLabel>
</KRadioGroup.Item>
)}
</For>
</OptionsContainer>
</ToolTip>
<KRadioGroup.ErrorMessage>{props.error}</KRadioGroup.ErrorMessage>
<KRadioGroup.ErrorMessage class={errorTextStyle}>{props.error}</KRadioGroup.ErrorMessage>
</KRadioGroup.Root>
)
}
54 changes: 35 additions & 19 deletions dashboard/src/components/templates/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Combobox as KComboBox, Select as KSelect } from '@kobalte/core'
import { keyframes, style } from '@macaron-css/core'
import { type JSX, Show, createMemo, splitProps } from 'solid-js'
import { type JSX, Show, createEffect, createMemo, createSignal, splitProps, untrack } from 'solid-js'
import { colorVars, textVars } from '/@/theme'
import { CheckBoxIcon } from '../UI/CheckBoxIcon'
import { MaterialSymbols } from '../UI/MaterialSymbols'
Expand Down Expand Up @@ -174,7 +174,19 @@ export const SingleSelect = <T extends string | number>(props: SingleSelectProps
['placeholder', 'ref', 'onInput', 'onChange', 'onBlur'],
)

const selectedOption = () => props.options.find((o) => o.value === props.value)
// const selectedOption = () => props.options.find((o) => o.value === props.value)
const [selectedOption, setSelectedOption] = createSignal<SelectOption<T>>()

createEffect(() => {
const found = props.options.find((o) => o.value === props.value)
// KobalteのSelect/Comboboxではundefinedを使用できないため、空文字列を指定している
setSelectedOption(
found ?? {
label: '',
value: '' as T,
},
)
})

return (
<KSelect.Root<SelectOption<T>>
Expand All @@ -183,7 +195,10 @@ export const SingleSelect = <T extends string | number>(props: SingleSelectProps
multiple={false}
disallowEmptySelection
value={selectedOption()}
onChange={(v) => props.setValue?.(v.value)}
onChange={(v) => {
props.setValue?.(v.value)
setSelectedOption(v)
}}
optionValue="value"
optionTextValue="label"
validationState={props.error ? 'invalid' : 'valid'}
Expand Down Expand Up @@ -346,38 +361,38 @@ const comboBoxInputStyle = style({

export type ComboBoxProps<T extends string | number> = SelectProps<T> & {
value: T | undefined
setValue?: (v: T) => void
setValue?: (v: T | undefined) => void
}

export const ComboBox = <T extends string | number>(props: SingleSelectProps<T>): JSX.Element => {
export const ComboBox = <T extends string | number>(props: ComboBoxProps<T>): JSX.Element => {
const [rootProps, selectProps] = splitProps(
props,
['name', 'placeholder', 'options', 'required', 'disabled', 'readOnly'],
['placeholder', 'ref', 'onInput', 'onChange', 'onBlur'],
)

const selectedOption = createMemo<SelectOption<T>>(
(prev) => {
const find = props.options.find((o) => o.value === props.value)
if (find) {
props.setValue?.(find.value)
return find
}
props.setValue?.(prev.value)
return prev
},
{ label: props.value?.toString() ?? '', value: props.value ?? ('' as T) },
)
const [selectedOption, setSelectedOption] = createSignal<SelectOption<T>>()

createEffect(() => {
const found = props.options.find((o) => o.value === props.value)
// KobalteのSelect/Comboboxではundefinedを使用できないため、空文字列を指定している
setSelectedOption(
found ?? {
label: '',
value: '' as T,
},
)
})

return (
<KComboBox.Root<SelectOption<T>>
class={containerStyle}
{...rootProps}
multiple={false}
disallowEmptySelection
allowDuplicateSelectionEvents
value={selectedOption()}
onChange={(v) => {
props.setValue?.(v.value)
setSelectedOption(v)
}}
optionValue="value"
optionTextValue="label"
Expand All @@ -389,6 +404,7 @@ export const ComboBox = <T extends string | number>(props: SingleSelectProps<T>)
<KComboBox.ItemLabel>{props.item.textValue}</KComboBox.ItemLabel>
</KComboBox.Item>
)}
{...rootProps}
>
<Show when={props.label}>
<TitleContainer>
Expand Down
Loading
Loading