Skip to content

Commit b1464af

Browse files
author
mdatelle
committed
refactor: cleanup Select stories and component and replace in ApiKeyCreate
1 parent b6bf65f commit b1464af

File tree

4 files changed

+176
-28
lines changed

4 files changed

+176
-28
lines changed

unraid-ui/src/components/common/dropdown-menu/DropdownMenu.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ function handleItemClick(item: DropdownMenuItemData) {
5959

6060
<!-- Props-based items rendering -->
6161
<template v-if="props.items && props.items.length > 0">
62-
<template v-for="(item, index) in props.items" :key="item.label || `item-${index}`">
62+
<template v-for="item in props.items" :key="item.label || item.type">
6363
<DropdownMenuSeparator v-if="item.type === 'separator'" />
6464

6565
<DropdownMenuLabel v-else-if="item.type === 'label'">

unraid-ui/src/components/form/select/Select.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { computed } from 'vue';
1313
1414
type SelectValueType = string | number;
1515
16+
type AcceptableValue = SelectValueType | SelectValueType[] | Record<string, unknown> | null;
17+
1618
interface SelectItemInterface {
1719
label: string;
1820
value: SelectValueType;
@@ -38,7 +40,7 @@ export type SelectItemType =
3840
| SelectValueType;
3941
4042
export interface SelectProps {
41-
modelValue?: SelectValueType | SelectValueType[];
43+
modelValue?: AcceptableValue;
4244
items?: SelectItemType[] | SelectItemType[][];
4345
placeholder?: string;
4446
multiple?: boolean;
@@ -58,7 +60,7 @@ const props = withDefaults(defineProps<SelectProps>(), {
5860
});
5961
6062
const emit = defineEmits<{
61-
'update:modelValue': [value: SelectValueType | SelectValueType[]];
63+
'update:modelValue': [value: AcceptableValue];
6264
}>();
6365
6466
function isStructuredItem(item: SelectItemType): item is SelectItemInterface {
@@ -146,6 +148,10 @@ const multipleValueDisplay = computed(() => {
146148
return `${displayLabels[0]}, ${displayLabels[1]} +${displayLabels.length - 2} more`;
147149
}
148150
});
151+
152+
function handleUpdateModelValue(value: AcceptableValue) {
153+
emit('update:modelValue', value);
154+
}
149155
</script>
150156

151157
<template>
@@ -155,7 +161,7 @@ const multipleValueDisplay = computed(() => {
155161
:disabled="props.disabled"
156162
:required="props.required"
157163
:name="props.name"
158-
@update:model-value="(value: any) => emit('update:modelValue', value)"
164+
@update:model-value="handleUpdateModelValue"
159165
>
160166
<SelectTrigger :class="props.class">
161167
<slot>

unraid-ui/stories/components/form/Select.stories.ts

Lines changed: 159 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,18 @@ export const SimpleArray: Story = {
4646
components: { Select },
4747
setup() {
4848
const value = ref(null);
49+
4950
return { args, value };
5051
},
5152
template: `
5253
<div class="space-y-4">
53-
<Select v-model="value" v-bind="args" />
54+
<Select
55+
v-model="value"
56+
:items="args.items"
57+
:placeholder="args.placeholder"
58+
:valueKey="args.valueKey"
59+
:labelKey="args.labelKey"
60+
/>
5461
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
5562
<p class="text-sm">Items: {{ args.items }}</p>
5663
</div>
@@ -63,6 +70,26 @@ export const SimpleArray: Story = {
6370
};
6471

6572
export const ObjectArray: Story = {
73+
render: (args) => ({
74+
components: { Select },
75+
setup() {
76+
const value = ref(null);
77+
78+
return { args, value };
79+
},
80+
template: `
81+
<div class="space-y-4">
82+
<Select
83+
v-model="value"
84+
:items="args.items"
85+
:placeholder="args.placeholder"
86+
:valueKey="args.valueKey"
87+
:labelKey="args.labelKey"
88+
/>
89+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
90+
</div>
91+
`,
92+
}),
6693
args: {
6794
placeholder: 'Select a color',
6895
items: [
@@ -76,6 +103,26 @@ export const ObjectArray: Story = {
76103
};
77104

78105
export const GroupedItems: Story = {
106+
render: (args) => ({
107+
components: { Select },
108+
setup() {
109+
const value = ref(null);
110+
111+
return { args, value };
112+
},
113+
template: `
114+
<div class="space-y-4">
115+
<Select
116+
v-model="value"
117+
:items="args.items"
118+
:placeholder="args.placeholder"
119+
:valueKey="args.valueKey"
120+
:labelKey="args.labelKey"
121+
/>
122+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
123+
</div>
124+
`,
125+
}),
79126
args: {
80127
placeholder: 'Select food',
81128
items: [
@@ -96,6 +143,26 @@ export const GroupedItems: Story = {
96143
};
97144

98145
export const WithDisabledItems: Story = {
146+
render: (args) => ({
147+
components: { Select },
148+
setup() {
149+
const value = ref(null);
150+
151+
return { args, value };
152+
},
153+
template: `
154+
<div class="space-y-4">
155+
<Select
156+
v-model="value"
157+
:items="args.items"
158+
:placeholder="args.placeholder"
159+
:valueKey="args.valueKey"
160+
:labelKey="args.labelKey"
161+
/>
162+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
163+
</div>
164+
`,
165+
}),
99166
args: {
100167
placeholder: 'Select an option',
101168
items: [
@@ -108,6 +175,26 @@ export const WithDisabledItems: Story = {
108175
};
109176

110177
export const WithSeparators: Story = {
178+
render: (args) => ({
179+
components: { Select },
180+
setup() {
181+
const value = ref(null);
182+
183+
return { args, value };
184+
},
185+
template: `
186+
<div class="space-y-4">
187+
<Select
188+
v-model="value"
189+
:items="args.items"
190+
:placeholder="args.placeholder"
191+
:valueKey="args.valueKey"
192+
:labelKey="args.labelKey"
193+
/>
194+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
195+
</div>
196+
`,
197+
}),
111198
args: {
112199
placeholder: 'Select action',
113200
items: [
@@ -127,11 +214,18 @@ export const ControlledValue: Story = {
127214
components: { Select },
128215
setup() {
129216
const value = ref('banana');
217+
130218
return { args, value };
131219
},
132220
template: `
133221
<div class="space-y-4">
134-
<Select v-model="value" v-bind="args" />
222+
<Select
223+
v-model="value"
224+
:items="args.items"
225+
:placeholder="args.placeholder"
226+
:valueKey="args.valueKey"
227+
:labelKey="args.labelKey"
228+
/>
135229
<p class="text-sm text-muted-foreground">Selected value: {{ value }}</p>
136230
</div>
137231
`,
@@ -151,17 +245,26 @@ export const MultipleSelection: Story = {
151245
components: { Select },
152246
setup() {
153247
const value = ref(['apple', 'orange']);
248+
154249
return { args, value };
155250
},
156251
template: `
157252
<div class="space-y-4">
158-
<Select v-model="value" multiple v-bind="args" />
253+
<Select
254+
v-model="value"
255+
:items="args.items"
256+
:placeholder="args.placeholder"
257+
:multiple="args.multiple"
258+
:valueKey="args.valueKey"
259+
:labelKey="args.labelKey"
260+
/>
159261
<p class="text-sm text-muted-foreground">Selected values: {{ Array.isArray(value) ? value.join(', ') : value }}</p>
160262
</div>
161263
`,
162264
}),
163265
args: {
164266
placeholder: 'Select fruits',
267+
multiple: true,
165268
items: [
166269
{ value: 'apple', label: 'Apple' },
167270
{ value: 'banana', label: 'Banana' },
@@ -176,17 +279,28 @@ export const CustomSlots: Story = {
176279
render: (args) => ({
177280
components: { Select },
178281
setup() {
179-
return { args };
282+
const value = ref(null);
283+
284+
return { args, value };
180285
},
181286
template: `
182-
<Select v-bind="args">
183-
<template #item="{ item }">
184-
<div class="flex items-center gap-2">
185-
<span class="w-3 h-3 rounded-full" :style="{ backgroundColor: item.color }"></span>
186-
{{ item.label }}
187-
</div>
188-
</template>
189-
</Select>
287+
<div class="space-y-4">
288+
<Select
289+
v-model="value"
290+
:items="args.items"
291+
:placeholder="args.placeholder"
292+
:valueKey="args.valueKey"
293+
:labelKey="args.labelKey"
294+
>
295+
<template #item="{ item }">
296+
<div class="flex items-center gap-2">
297+
<span class="w-3 h-3 rounded-full" :style="{ backgroundColor: item.color }"></span>
298+
{{ item.label }}
299+
</div>
300+
</template>
301+
</Select>
302+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
303+
</div>
190304
`,
191305
}),
192306
args: {
@@ -200,3 +314,36 @@ export const CustomSlots: Story = {
200314
],
201315
},
202316
};
317+
318+
export const DisabledSelect: Story = {
319+
render: (args) => ({
320+
components: { Select },
321+
setup() {
322+
const value = ref(null);
323+
return { args, value };
324+
},
325+
template: `
326+
<div class="space-y-4">
327+
<Select
328+
v-model="value"
329+
:items="args.items"
330+
:placeholder="args.placeholder"
331+
:disabled="args.disabled"
332+
:valueKey="args.valueKey"
333+
:labelKey="args.labelKey"
334+
/>
335+
<p class="text-sm text-muted-foreground">Selected: {{ value }}</p>
336+
<p class="text-xs text-muted-foreground">The entire select is disabled</p>
337+
</div>
338+
`,
339+
}),
340+
args: {
341+
placeholder: 'This select is disabled',
342+
disabled: true,
343+
items: [
344+
{ value: 'option1', label: 'Option 1' },
345+
{ value: 'option2', label: 'Option 2' },
346+
{ value: 'option3', label: 'Option 3' },
347+
],
348+
},
349+
};

web/components/ApiKey/ApiKeyCreate.vue

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,6 @@ import {
1313
Input,
1414
Label,
1515
Select,
16-
SelectContent,
17-
SelectItem,
18-
SelectTrigger,
19-
SelectValue,
2016
} from '@unraid/ui';
2117
import { extractGraphQLErrorMessage } from '~/helpers/functions';
2218
@@ -224,14 +220,13 @@ async function upsertKey() {
224220
</div>
225221
<div class="mb-2">
226222
<Label for="api-key-roles">Roles</Label>
227-
<Select v-model="newKeyRoles" multiple class="mt-1 w-full">
228-
<SelectTrigger>
229-
<SelectValue placeholder="Select Roles" />
230-
</SelectTrigger>
231-
<SelectContent>
232-
<SelectItem v-for="role in possibleRoles" :key="role" :value="role">{{ role }}</SelectItem>
233-
</SelectContent>
234-
</Select>
223+
<Select
224+
v-model="newKeyRoles"
225+
:items="possibleRoles"
226+
:multiple="true"
227+
:placeholder="'Select Roles'"
228+
class="mt-1 w-full"
229+
/>
235230
</div>
236231
<div class="mb-2">
237232
<Accordion id="api-key-permissions" type="single" collapsible class="w-full mt-2">

0 commit comments

Comments
 (0)