Initial commit
This commit is contained in:
32
src/components/dialogs/DeleteConfirmDialog.vue
Normal file
32
src/components/dialogs/DeleteConfirmDialog.vue
Normal file
@@ -0,0 +1,32 @@
|
||||
<script setup lang="ts">
|
||||
defineProps<{
|
||||
modelValue: boolean
|
||||
itemCount: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
'confirm': []
|
||||
}>()
|
||||
|
||||
function handleClose() {
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title>Delete</v-card-title>
|
||||
<v-card-text>
|
||||
Are you sure you want to delete {{ itemCount }} item(s)?
|
||||
This action cannot be undone.
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn variant="text" @click="handleClose">Cancel</v-btn>
|
||||
<v-btn color="error" variant="elevated" @click="emit('confirm')">Delete</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
50
src/components/dialogs/NewFolderDialog.vue
Normal file
50
src/components/dialogs/NewFolderDialog.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
'create': [name: string]
|
||||
}>()
|
||||
|
||||
const folderName = ref('')
|
||||
|
||||
watch(() => props.modelValue, (isOpen) => {
|
||||
if (isOpen) {
|
||||
folderName.value = ''
|
||||
}
|
||||
})
|
||||
|
||||
function handleCreate() {
|
||||
if (!folderName.value.trim()) return
|
||||
emit('create', folderName.value.trim())
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title>New Folder</v-card-title>
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
v-model="folderName"
|
||||
label="Folder name"
|
||||
autofocus
|
||||
@keyup.enter="handleCreate"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn variant="text" @click="handleClose">Cancel</v-btn>
|
||||
<v-btn color="primary" variant="elevated" @click="handleCreate">Create</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
51
src/components/dialogs/RenameDialog.vue
Normal file
51
src/components/dialogs/RenameDialog.vue
Normal file
@@ -0,0 +1,51 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
currentName: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
'rename': [newName: string]
|
||||
}>()
|
||||
|
||||
const newName = ref('')
|
||||
|
||||
watch(() => props.modelValue, (isOpen) => {
|
||||
if (isOpen) {
|
||||
newName.value = props.currentName
|
||||
}
|
||||
})
|
||||
|
||||
function handleRename() {
|
||||
if (!newName.value.trim()) return
|
||||
emit('rename', newName.value.trim())
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" max-width="400">
|
||||
<v-card>
|
||||
<v-card-title>Rename</v-card-title>
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
v-model="newName"
|
||||
label="New name"
|
||||
autofocus
|
||||
@keyup.enter="handleRename"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn variant="text" @click="handleClose">Cancel</v-btn>
|
||||
<v-btn color="primary" variant="elevated" @click="handleRename">Rename</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
143
src/components/dialogs/UploadDialog.vue
Normal file
143
src/components/dialogs/UploadDialog.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<script setup lang="ts">
|
||||
import type { FileUploadProgress } from '@/composables/useFileUpload'
|
||||
import { formatSize, getUploadStatusIcon, getUploadStatusColor } from '@/utils/fileHelpers'
|
||||
|
||||
defineProps<{
|
||||
modelValue: boolean
|
||||
uploads: Map<string, FileUploadProgress>
|
||||
totalProgress: number
|
||||
isUploading: boolean
|
||||
pendingCount: number
|
||||
completedCount: number
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean]
|
||||
'upload-all': []
|
||||
'remove-upload': [id: string]
|
||||
'retry-upload': [id: string]
|
||||
'add-files': []
|
||||
'close': []
|
||||
}>()
|
||||
|
||||
function handleClose() {
|
||||
emit('close')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-dialog :model-value="modelValue" @update:model-value="emit('update:modelValue', $event)" max-width="500" persistent>
|
||||
<v-card>
|
||||
<v-card-title class="d-flex align-center">
|
||||
<v-icon class="mr-2">mdi-upload</v-icon>
|
||||
Upload Files
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<!-- Upload progress -->
|
||||
<div v-if="totalProgress > 0 && isUploading" class="mb-4">
|
||||
<v-progress-linear
|
||||
:model-value="totalProgress"
|
||||
color="primary"
|
||||
height="8"
|
||||
rounded
|
||||
/>
|
||||
<div class="text-caption text-center mt-1">
|
||||
{{ totalProgress }}% complete
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- File list -->
|
||||
<v-list density="compact" class="upload-file-list">
|
||||
<v-list-item
|
||||
v-for="[id, item] in uploads"
|
||||
:key="id"
|
||||
class="px-0"
|
||||
>
|
||||
<template #prepend>
|
||||
<v-icon :color="getUploadStatusColor(item.status)" size="small">
|
||||
{{ getUploadStatusIcon(item.status) }}
|
||||
</v-icon>
|
||||
</template>
|
||||
<v-list-item-title class="text-body-2">
|
||||
{{ item.relativePath || item.file.name }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
{{ formatSize(item.file.size) }}
|
||||
<span v-if="item.error" class="text-error"> — {{ item.error }}</span>
|
||||
</v-list-item-subtitle>
|
||||
<template #append>
|
||||
<v-btn
|
||||
v-if="item.status === 'pending' || item.status === 'error'"
|
||||
icon="mdi-close"
|
||||
size="x-small"
|
||||
variant="text"
|
||||
@click="emit('remove-upload', id)"
|
||||
/>
|
||||
<v-btn
|
||||
v-if="item.status === 'error'"
|
||||
icon="mdi-refresh"
|
||||
size="x-small"
|
||||
variant="text"
|
||||
color="primary"
|
||||
@click="emit('retry-upload', id)"
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<!-- Empty state -->
|
||||
<div v-if="uploads.size === 0" class="text-center py-8 text-grey">
|
||||
<v-icon size="48" color="grey-lighten-1">mdi-file-upload-outline</v-icon>
|
||||
<div class="mt-2">No files selected</div>
|
||||
<v-btn
|
||||
variant="tonal"
|
||||
color="primary"
|
||||
class="mt-4"
|
||||
@click="emit('add-files')"
|
||||
>
|
||||
<v-icon start>mdi-plus</v-icon>
|
||||
Add Files
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<!-- Add more files button -->
|
||||
<div v-else class="text-center mt-4">
|
||||
<v-btn
|
||||
variant="text"
|
||||
size="small"
|
||||
@click="emit('add-files')"
|
||||
>
|
||||
<v-icon start>mdi-plus</v-icon>
|
||||
Add More Files
|
||||
</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
variant="text"
|
||||
@click="handleClose"
|
||||
:disabled="isUploading"
|
||||
>
|
||||
{{ completedCount > 0 ? 'Done' : 'Cancel' }}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="pendingCount > 0"
|
||||
color="primary"
|
||||
variant="elevated"
|
||||
@click="emit('upload-all')"
|
||||
:loading="isUploading"
|
||||
>
|
||||
Upload {{ pendingCount }} File(s)
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.upload-file-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
4
src/components/dialogs/index.ts
Normal file
4
src/components/dialogs/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export { default as NewFolderDialog } from './NewFolderDialog.vue'
|
||||
export { default as RenameDialog } from './RenameDialog.vue'
|
||||
export { default as DeleteConfirmDialog } from './DeleteConfirmDialog.vue'
|
||||
export { default as UploadDialog } from './UploadDialog.vue'
|
||||
Reference in New Issue
Block a user