Skip to content

Commit b434dfe

Browse files
add missing zod schema
1 parent e6d020c commit b434dfe

File tree

6 files changed

+43
-50
lines changed

6 files changed

+43
-50
lines changed

src/locales/en/main.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,7 @@
19851985
"searchAssetsPlaceholder": "Type to search...",
19861986
"uploadModel": "Upload model",
19871987
"uploadModelFromCivitai": "Upload a model from Civitai",
1988+
"uploadModelFailedToRetrieveMetadata": "Failed to retrieve metadata. Please check the link and try again.",
19881989
"uploadModelDescription1": "Paste a Civitai model download link to add it to your library.",
19891990
"uploadModelDescription2": "Only links from https://civitai.com are supported at the moment",
19901991
"uploadModelDescription3": "Max file size: 1 GB",
@@ -2004,7 +2005,8 @@
20042005
"uploadSuccess": "Model uploaded successfully!",
20052006
"uploadFailed": "Upload failed",
20062007
"modelAssociatedWithLink": "The model associated with the link you provided:",
2007-
"whatTypeOfModel": "What type of model is this?",
2008+
"modelTypeSelectorLabel": "What type of model is this?",
2009+
"modelTypeSelectorPlaceholder": "Select model type",
20082010
"selectModelType": "Select model type",
20092011
"notSureLeaveAsIs": "Not sure? Just leave this as is",
20102012
"modelUploaded": "Model uploaded!",

src/platform/assets/components/UploadModelConfirmation.vue

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
<!-- Model Type Selection -->
1414
<div class="flex flex-col gap-2">
1515
<label class="text-sm text-muted">
16-
{{ $t('assetBrowser.whatTypeOfModel') }}
16+
{{ $t('assetBrowser.modelTypeSelectorLabel') }}
1717
</label>
1818
<SingleSelect
1919
v-model="selectedModelType"
20-
:label="$t('assetBrowser.whatTypeOfModel')"
20+
:label="$t('assetBrowser.modelTypeSelectorPlaceholder')"
2121
:options="modelTypes"
2222
/>
2323
<div class="flex items-center gap-2 text-sm text-muted">
@@ -33,30 +33,21 @@ import { computed } from 'vue'
3333
3434
import SingleSelect from '@/components/input/SingleSelect.vue'
3535
import { useModelTypes } from '@/platform/assets/composables/useModelTypes'
36-
37-
interface ModelMetadata {
38-
content_length: number
39-
final_url: string
40-
content_type?: string
41-
filename?: string
42-
name?: string
43-
tags?: string[]
44-
preview_url?: string
45-
}
36+
import type { AssetMetadata } from '@/platform/assets/schemas/assetSchema'
4637
4738
const props = defineProps<{
48-
modelValue: string
49-
metadata: ModelMetadata | null
39+
modelValue: string | undefined
40+
metadata: AssetMetadata | null
5041
}>()
5142
5243
const emit = defineEmits<{
53-
'update:modelValue': [value: string]
44+
'update:modelValue': [value: string | undefined]
5445
}>()
5546
5647
const { modelTypes } = useModelTypes()
5748
5849
const selectedModelType = computed({
59-
get: () => props.modelValue,
60-
set: (value: string) => emit('update:modelValue', value)
50+
get: () => props.modelValue ?? null,
51+
set: (value: string | null) => emit('update:modelValue', value ?? undefined)
6152
})
6253
</script>

src/platform/assets/components/UploadModelDialog.vue

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ import { computed, onMounted, ref, watch } from 'vue'
8181
8282
import IconTextButton from '@/components/button/IconTextButton.vue'
8383
import TextButton from '@/components/button/TextButton.vue'
84+
import { st } from '@/i18n'
8485
import UploadModelConfirmation from '@/platform/assets/components/UploadModelConfirmation.vue'
8586
import UploadModelProgress from '@/platform/assets/components/UploadModelProgress.vue'
8687
import UploadModelUrlInput from '@/platform/assets/components/UploadModelUrlInput.vue'
8788
import { useModelTypes } from '@/platform/assets/composables/useModelTypes'
89+
import type { AssetMetadata } from '@/platform/assets/schemas/assetSchema'
8890
import { assetService } from '@/platform/assets/services/assetService'
8991
import { useDialogStore } from '@/stores/dialogStore'
9092
@@ -102,15 +104,7 @@ const uploadError = ref('')
102104
103105
const wizardData = ref<{
104106
url: string
105-
metadata: {
106-
content_length: number
107-
final_url: string
108-
content_type?: string
109-
filename?: string
110-
name?: string
111-
tags?: string[]
112-
preview_url?: string
113-
} | null
107+
metadata: AssetMetadata | null
114108
name: string
115109
tags: string[]
116110
}>({
@@ -120,7 +114,7 @@ const wizardData = ref<{
120114
tags: []
121115
})
122116
123-
const selectedModelType = ref<string>('loras')
117+
const selectedModelType = ref<string | undefined>(undefined)
124118
125119
const { modelTypes, fetchModelTypes } = useModelTypes()
126120
@@ -186,8 +180,13 @@ async function handleFetchMetadata() {
186180
} catch (error) {
187181
console.error('Failed to retrieve metadata:', error)
188182
uploadError.value =
189-
error instanceof Error ? error.message : 'Failed to retrieve metadata'
190-
// TODO: Show error toast to user
183+
error instanceof Error
184+
? error.message
185+
: st(
186+
'assetBrowser.uploadModelFailedToRetrieveMetadata',
187+
'Failed to retrieve metadata. Please check the link and try again.'
188+
)
189+
currentStep.value = 1
191190
} finally {
192191
isFetchingMetadata.value = false
193192
}
@@ -200,7 +199,9 @@ async function handleUploadModel() {
200199
uploadStatus.value = 'uploading'
201200
202201
try {
203-
const tags = ['models', selectedModelType.value]
202+
const tags = selectedModelType.value
203+
? ['models', selectedModelType.value]
204+
: ['models']
204205
const filename =
205206
wizardData.value.metadata?.filename ||
206207
wizardData.value.metadata?.name ||

src/platform/assets/components/UploadModelProgress.vue

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,12 @@
5959
</template>
6060

6161
<script setup lang="ts">
62-
interface ModelMetadata {
63-
content_length: number
64-
final_url: string
65-
content_type?: string
66-
filename?: string
67-
name?: string
68-
tags?: string[]
69-
preview_url?: string
70-
}
62+
import type { AssetMetadata } from '@/platform/assets/schemas/assetSchema'
7163
7264
defineProps<{
7365
status: 'idle' | 'uploading' | 'success' | 'error'
7466
error?: string
75-
metadata: ModelMetadata | null
76-
modelType: string
67+
metadata: AssetMetadata | null
68+
modelType: string | undefined
7769
}>()
7870
</script>

src/platform/assets/schemas/assetSchema.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ const zModelFile = z.object({
3333
pathIndex: z.number()
3434
})
3535

36+
// Asset metadata from download URL
37+
const zAssetMetadata = z.object({
38+
content_length: z.number(),
39+
final_url: z.string(),
40+
content_type: z.string().optional(),
41+
filename: z.string().optional(),
42+
name: z.string().optional(),
43+
tags: z.array(z.string()).optional(),
44+
preview_url: z.string().optional()
45+
})
46+
3647
// Filename validation schema
3748
export const assetFilenameSchema = z
3849
.string()
@@ -44,10 +55,12 @@ export const assetFilenameSchema = z
4455
// Export schemas following repository patterns
4556
export const assetItemSchema = zAsset
4657
export const assetResponseSchema = zAssetResponse
58+
export const assetMetadataSchema = zAssetMetadata
4759

4860
// Export types derived from Zod schemas
4961
export type AssetItem = z.infer<typeof zAsset>
5062
export type AssetResponse = z.infer<typeof zAssetResponse>
63+
export type AssetMetadata = z.infer<typeof zAssetMetadata>
5164
export type ModelFolder = z.infer<typeof zModelFolder>
5265
export type ModelFile = z.infer<typeof zModelFile>
5366

src/platform/assets/services/assetService.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fromZodError } from 'zod-validation-error'
33
import { assetResponseSchema } from '@/platform/assets/schemas/assetSchema'
44
import type {
55
AssetItem,
6+
AssetMetadata,
67
AssetResponse,
78
ModelFile,
89
ModelFolder
@@ -256,14 +257,7 @@ function createAssetService() {
256257
* @returns Promise with metadata including content_length, final_url, filename, etc.
257258
* @throws Error if metadata retrieval fails
258259
*/
259-
async function getAssetMetadata(url: string): Promise<{
260-
content_length: number
261-
final_url: string
262-
content_type?: string
263-
filename?: string
264-
name?: string
265-
tags?: string[]
266-
}> {
260+
async function getAssetMetadata(url: string): Promise<AssetMetadata> {
267261
const encodedUrl = encodeURIComponent(url)
268262
const res = await api.fetchApi(
269263
`${ASSETS_ENDPOINT}/metadata?url=${encodedUrl}`

0 commit comments

Comments
 (0)