|
5 | 5 | <template> |
6 | 6 | <NcEmptyContent class="file-drop-empty-content" |
7 | 7 | data-cy-files-sharing-file-drop |
8 | | - :name="t('files_sharing', 'File drop')"> |
| 8 | + :name="name"> |
9 | 9 | <template #icon> |
10 | 10 | <NcIconSvgWrapper :svg="svgCloudUpload" /> |
11 | 11 | </template> |
12 | 12 | <template #description> |
13 | | - {{ t('files_sharing', 'Upload files to {foldername}.', { foldername }) }} |
14 | | - {{ disclaimer === '' ? '' : t('files_sharing', 'By uploading files, you agree to the terms of service.') }} |
| 13 | + <p> |
| 14 | + {{ shareNote || t('files_sharing', 'Upload files to {foldername}.', { foldername }) }} |
| 15 | + </p> |
| 16 | + <p v-if="disclaimer"> |
| 17 | + {{ t('files_sharing', 'By uploading files, you agree to the terms of service.') }} |
| 18 | + </p> |
| 19 | + <NcNoteCard v-if="getSortedUploads().length" |
| 20 | + class="file-drop-empty-content__note-card" |
| 21 | + type="success"> |
| 22 | + <h2 id="file-drop-empty-content__heading"> |
| 23 | + {{ t('files_sharing', 'Successfully uploaded files') }} |
| 24 | + </h2> |
| 25 | + <ul aria-labelledby="file-drop-empty-content__heading" class="file-drop-empty-content__list"> |
| 26 | + <li v-for="file in getSortedUploads()" :key="file"> |
| 27 | + {{ file }} |
| 28 | + </li> |
| 29 | + </ul> |
| 30 | + </NcNoteCard> |
15 | 31 | </template> |
16 | 32 | <template #action> |
17 | 33 | <template v-if="disclaimer"> |
|
34 | 50 | </NcEmptyContent> |
35 | 51 | </template> |
36 | 52 |
|
| 53 | +<script lang="ts"> |
| 54 | +/* eslint-disable import/first */ |
| 55 | +
|
| 56 | +// We need this on module level rather than on the instance as view will be refreshed by the files app after uploading |
| 57 | +const uploads = new Set<string>() |
| 58 | +</script> |
| 59 | + |
37 | 60 | <script setup lang="ts"> |
38 | 61 | import { loadState } from '@nextcloud/initial-state' |
39 | 62 | import { translate as t } from '@nextcloud/l10n' |
40 | | -import { getUploader, UploadPicker } from '@nextcloud/upload' |
| 63 | +import { getUploader, UploadPicker, UploadStatus } from '@nextcloud/upload' |
41 | 64 | import { ref } from 'vue' |
42 | 65 |
|
43 | 66 | import NcButton from '@nextcloud/vue/components/NcButton' |
44 | 67 | import NcDialog from '@nextcloud/vue/components/NcDialog' |
45 | 68 | import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent' |
46 | 69 | import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper' |
| 70 | +import NcNoteCard from '@nextcloud/vue/components/NcNoteCard' |
47 | 71 | import svgCloudUpload from '@mdi/svg/svg/cloud-upload.svg?raw' |
48 | 72 |
|
49 | 73 | defineProps<{ |
50 | 74 | foldername: string |
51 | 75 | }>() |
52 | 76 |
|
53 | 77 | const disclaimer = loadState<string>('files_sharing', 'disclaimer', '') |
| 78 | +const shareLabel = loadState<string>('files_sharing', 'label', '') |
| 79 | +const shareNote = loadState<string>('files_sharing', 'note', '') |
| 80 | +
|
| 81 | +const name = shareLabel || t('files_sharing', 'File drop') |
| 82 | +
|
54 | 83 | const showDialog = ref(false) |
55 | 84 | const uploadDestination = getUploader().destination |
56 | | -</script> |
57 | 85 |
|
58 | | -<style scoped> |
59 | | -:deep(.terms-of-service-dialog) { |
60 | | - min-height: min(100px, 20vh); |
| 86 | +getUploader() |
| 87 | + .addNotifier((upload) => { |
| 88 | + if (upload.status === UploadStatus.FINISHED && upload.file.name) { |
| 89 | + // if a upload is finished and is not a meta upload (name is set) |
| 90 | + // then we add the upload to the list of finished uploads to be shown to the user |
| 91 | + uploads.add(upload.file.name) |
| 92 | + } |
| 93 | + }) |
| 94 | +
|
| 95 | +/** |
| 96 | + * Get the previous uploads as sorted list |
| 97 | + */ |
| 98 | +function getSortedUploads() { |
| 99 | + return [...uploads].sort((a, b) => a.localeCompare(b)) |
61 | 100 | } |
62 | | -/* TODO fix in library */ |
63 | | -.file-drop-empty-content :deep(.empty-content__action) { |
64 | | - display: flex; |
65 | | - gap: var(--default-grid-baseline); |
| 101 | +</script> |
| 102 | + |
| 103 | +<style scoped lang="scss"> |
| 104 | +.file-drop-empty-content { |
| 105 | + margin: auto; |
| 106 | + max-width: max(50vw, 300px); |
| 107 | +
|
| 108 | + .file-drop-empty-content__note-card { |
| 109 | + width: fit-content; |
| 110 | + margin-inline: auto; |
| 111 | + } |
| 112 | +
|
| 113 | + #file-drop-empty-content__heading { |
| 114 | + margin-block: 0 10px; |
| 115 | + font-weight: bold; |
| 116 | + font-size: 20px; |
| 117 | + } |
| 118 | +
|
| 119 | + .file-drop-empty-content__list { |
| 120 | + list-style: inside; |
| 121 | + max-height: min(350px, 33vh); |
| 122 | + overflow-y: scroll; |
| 123 | + padding-inline-end: calc(2 * var(--default-grid-baseline)); |
| 124 | + } |
| 125 | +
|
| 126 | + :deep(.terms-of-service-dialog) { |
| 127 | + min-height: min(100px, 20vh); |
| 128 | + } |
| 129 | +
|
| 130 | + /* TODO fix in library */ |
| 131 | + :deep(.empty-content__action) { |
| 132 | + display: flex; |
| 133 | + gap: var(--default-grid-baseline); |
| 134 | + } |
66 | 135 | } |
67 | 136 | </style> |
0 commit comments