diff --git a/resources/js/components/Combobox.vue b/resources/js/components/Combobox.vue deleted file mode 100644 index 79f8c3ca71c..00000000000 --- a/resources/js/components/Combobox.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - - - diff --git a/resources/js/components/form/CraftCombobox.vue b/resources/js/components/form/CraftCombobox.vue index 4d68cc445fe..f24ac9b1130 100644 --- a/resources/js/components/form/CraftCombobox.vue +++ b/resources/js/components/form/CraftCombobox.vue @@ -2,13 +2,10 @@ import {t} from '@craftcms/cp'; import InputCombobox from '@/components/form/InputCombobox.vue'; import type {SelectItem} from '@/types'; - import {computed} from 'vue'; + import {computed, useSlots} from 'vue'; - const emit = defineEmits<{ - (e: 'update:modelValue', value: string): void; - }>(); + const modelValue = defineModel(); const props = defineProps<{ - modelValue: string; label: string; id?: string; name?: string; @@ -16,15 +13,13 @@ options?: Array; callouts?: Array; error?: string; + requireOptionMatch?: boolean; }>(); - const valueProxy = computed({ - get() { - return props.modelValue; - }, - set(newValue) { - emit('update:modelValue', newValue); - }, + const slots = useSlots(); + const forwardedSlots = computed(() => { + const {default: _, ...rest} = slots; + return rest; }); @@ -35,14 +30,20 @@ :name="name" :disabled="disabled" :has-feedback-for="error ? 'error' : ''" + :require-options-match="requireOptionMatch" v-bind="$attrs" > + > + + +
diff --git a/resources/js/components/form/InputCombobox.vue b/resources/js/components/form/InputCombobox.vue index 8f86358c022..27ec1a049dc 100644 --- a/resources/js/components/form/InputCombobox.vue +++ b/resources/js/components/form/InputCombobox.vue @@ -18,13 +18,13 @@ import InputComboboxOption from '@/components/form/InputComboboxOption.vue'; const emit = defineEmits<{ - (e: 'update:modelValue', value: string): void; + (e: 'update:modelValue', value: string | number): void; }>(); const props = withDefaults( defineProps<{ label?: string; options?: Array; - modelValue?: string; + modelValue?: string | number | boolean; requireOptionMatch?: boolean; transformModelValue?: (newValue: SelectOption | null) => string; class?: HTMLAttributes['class']; @@ -60,7 +60,7 @@ if (!selectedItem && !props.requireOptionMatch) { selectedItem = { - label: props.modelValue, + label: String(props.modelValue), value: props.modelValue, }; } @@ -76,7 +76,7 @@ }); const reference = useTemplateRef('reference'); - const query = ref(props.modelValue ?? ''); + const query = ref(String(props.modelValue ?? '')); const referenceCoordinates = computed(() => { const coordinates = reference.value?.getBoundingClientRect(); @@ -88,12 +88,12 @@ }); function matchesQuery(query: MaybeRef, item: MaybeRef) { - const lowerQuery = unref(query).toLowerCase(); + const lowerQuery = String(unref(query)).toLowerCase(); const option = unref(item); return ( option.label.toLowerCase().includes(lowerQuery) || - option.value.toLowerCase().includes(lowerQuery) || + option.value.toString().toLowerCase().includes(lowerQuery) || (option.data?.keywords?.toLowerCase().includes(lowerQuery) ?? false) ); } diff --git a/resources/js/components/form/InputComboboxOption.vue b/resources/js/components/form/InputComboboxOption.vue index 1518f08b1fd..50965173dd3 100644 --- a/resources/js/components/form/InputComboboxOption.vue +++ b/resources/js/components/form/InputComboboxOption.vue @@ -15,16 +15,21 @@ :checked="selected" :hint="option.data?.hint" > - +
diff --git a/resources/js/pages/SettingsGeneralPage.vue b/resources/js/pages/SettingsGeneralPage.vue index 9f81c979609..115047e44ee 100644 --- a/resources/js/pages/SettingsGeneralPage.vue +++ b/resources/js/pages/SettingsGeneralPage.vue @@ -2,44 +2,38 @@ import {t} from '@craftcms/cp'; import AppLayout from '@/layout/AppLayout.vue'; import {store} from '@/actions/CraftCms/Cms/Http/Controllers/Settings/GeneralSettingsController'; - import {type SystemData, type TimezoneOption} from '@/types/settings'; + import {type SystemData} from '@/types/settings'; import {useForm} from '@inertiajs/vue3'; import useCraftData from '@/composables/useCraftData'; import TransitionFade from '@/components/TransitionFade.vue'; import {computed} from 'vue'; import {useEventListener} from '@vueuse/core'; - import type {SelectOption, SuggestionGroup} from '@/types'; + import type {SelectItem} from '@/types'; import CalloutReadOnly from '@/components/CalloutReadOnly.vue'; + import CraftCombobox from '@/components/form/CraftCombobox.vue'; + import CraftInput from '@craftcms/cp/vue/CraftInput.vue'; + import {transformBooleanOptions} from '@/utils/transformBooleanOptions'; const props = defineProps<{ - readOnly?: boolean; system: SystemData; - nameSuggestions?: Array; - timezoneOptions?: Array; - systemStatusOptions?: Array; - saveUrl: string; + nameSuggestions?: Array; + timezoneOptions?: Array; + systemStatusOptions?: Array; flash?: Record; errors: Record; }>(); const flash = computed(() => props.flash); const errors = computed(() => props.errors); + const {readOnly} = useCraftData(); const form = useForm({ - name: props.system.name, + name: props.system.name ?? '', live: props.system.live, retryDuration: props.system.retryDuration, timeZone: props.system.timeZone, }); - function handleUpdate(event: CustomEvent) { - const target = event.target as HTMLSelectElement & {modelValue: string}; - if (target) { - // @ts-ignore we're just going to trust that `name` is a key of `form` for now - form[target.name] = target.modelValue; - } - } - // Handle cmd + s events useEventListener('keydown', (event) => { if ((event.metaKey || event.ctrlKey) && event.key === 's') { @@ -48,6 +42,29 @@ } }); + const statusOptions = computed(() => { + return [ + { + label: t('Online'), + value: true, + data: { + indicator: {variant: 'success'}, + }, + }, + { + label: t('Offline'), + value: false, + data: { + indicator: {variant: 'empty'}, + }, + }, + ...transformBooleanOptions(props.systemStatusOptions ?? [], { + trueLabel: t('Online'), + falseLabel: t('Offline'), + }), + ]; + }); + function save() { form.clearErrors().submit(store()); } @@ -123,26 +140,19 @@ - - -
+ + - - -
- - {{ t('Online') }} -
-
- -
- - {{ t('Offline') }} -
-
- -