diff --git a/src/components/playlist/APlaylistEditor.vue b/src/components/playlist/APlaylistEditor.vue index 65dba322eab5daaf14aaf97e775c506df0cab7b5..99d5b3fd670ec01d9ceaae3c032317edb3d43964 100644 --- a/src/components/playlist/APlaylistEditor.vue +++ b/src/components/playlist/APlaylistEditor.vue @@ -87,50 +87,73 @@ <fieldset v-if="allowAddEntries" ref="dropzoneEl" - class="tw-rounded tw-bg-gray-50 tw-border-2 tw-border-dashed tw-flex tw-mb-3 tw-p-6" - :class="{ 'tw-border-teal-600': isOverDropZone, 'tw-border-gray-200': !isOverDropZone }" + class="tw-rounded tw-bg-gray-50 tw-border-2 tw-flex tw-mb-3 tw-p-6" + :class="{ + 'tw-border-teal-600': isOverDropZone && isAllowedToAddFiles, + 'tw-border-gray-200': !isOverDropZone, + 'tw-border-dashed': isAllowedToAddFiles, + }" > <div class="tw-place-self-center tw-mx-auto tw-flex tw-flex-col tw-gap-2 tw-items-center"> - <icon-system-uicons-file-upload class="tw-text-xl" /> - <p class="tw-mb-0">{{ t('playlist.editor.control.dropFiles') }}</p> - <p class="tw-text-gray-400 tw-text-sm tw-mb-1.5 tw-leading-none"> - {{ t('playlist.editor.control._or') }} - </p> + <template v-if="isAllowedToAddFiles"> + <icon-system-uicons-file-upload class="tw-text-xl" /> + <p class="tw-mb-0">{{ t('playlist.editor.control.dropFiles') }}</p> + <p class="tw-text-gray-400 tw-text-sm tw-mb-1.5 tw-leading-none"> + {{ t('playlist.editor.control._or') }} + </p> + </template> <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3"> - <button type="button" class="btn btn-default" @click="openFileDialog()"> + <button + v-if="isAllowedToAddFiles" + type="button" + class="btn btn-default" + @click="openFileDialog()" + > <icon-iconamoon-file-audio-thin class="tw-flex-none" /> {{ t('playlist.editor.control.selectFiles') }} </button> - <button type="button" class="btn btn-default" @click="importFileFromURL()"> - <icon-formkit-url class="tw-flex-none" /> - {{ t('playlist.editor.control.importFile') }} - </button> + <APermissionGuard show-permissions="program.add__import"> + <button type="button" class="btn btn-default" @click="importFileFromURL()"> + <icon-formkit-url class="tw-flex-none" /> + {{ t('playlist.editor.control.importFile') }} + </button> + </APermissionGuard> </div> <div class="tw-flex tw-flex-wrap tw-justify-center tw-items-center tw-gap-3 tw-mt-1"> - <button type="button" class="btn btn-default" @click="addStreamToPlaylist()"> - <icon-solar-play-stream-bold class="tw-flex-none" /> - {{ t('playlist.editor.control.addStream') }} - </button> - <button type="button" class="btn btn-default" @click="addInputToPlaylist"> - <icon-game-icons-jack-plug class="tw-flex-none" /> - {{ t('playlist.editor.control.addInput') }} - </button> + <APermissionGuard show-permissions="program.add__stream"> + <button type="button" class="btn btn-default" @click="addStreamToPlaylist()"> + <icon-solar-play-stream-bold class="tw-flex-none" /> + {{ t('playlist.editor.control.addStream') }} + </button> + </APermissionGuard> + <APermissionGuard show-permissions="program.add__line"> + <button type="button" class="btn btn-default" @click="addInputToPlaylist"> + <icon-game-icons-jack-plug class="tw-flex-none" /> + {{ t('playlist.editor.control.addInput') }} + </button> + </APermissionGuard> </div> </div> </fieldset> </div> - <GetStreamUrl v-slot="{ resolve, reject }"> - <AStreamURLDialog @save="resolve($event)" @close="reject(undefined)" /> - </GetStreamUrl> + <APermissionGuard show-permissions="program.add__stream"> + <GetStreamUrl v-slot="{ resolve, reject }"> + <AStreamURLDialog @save="resolve($event)" @close="reject(undefined)" /> + </GetStreamUrl> + </APermissionGuard> - <GetFileImportUrl v-slot="{ resolve, reject }"> - <AFileUrlDialog @save="resolve($event)" @close="reject(undefined)" /> - </GetFileImportUrl> + <APermissionGuard show-permissions="program.add__import"> + <GetFileImportUrl v-slot="{ resolve, reject }"> + <AFileUrlDialog @save="resolve($event)" @close="reject(undefined)" /> + </GetFileImportUrl> + </APermissionGuard> - <GetInputUrl v-slot="{ resolve, reject }"> - <AInputUrlDialog @save="resolve($event)" @close="reject(undefined)" /> - </GetInputUrl> + <APermissionGuard show-permissions="program.add__line"> + <GetInputUrl v-slot="{ resolve, reject }"> + <AInputUrlDialog @save="resolve($event)" @close="reject(undefined)" /> + </GetInputUrl> + </APermissionGuard> </template> <script lang="ts" setup> @@ -152,6 +175,8 @@ import AUploadProgress from '@/components/playlist/AUploadProgress.vue' import SaveIndicator from '@/components/generic/SaveIndicator.vue' import APlaylistDurationCheck from '@/components/playlist/APlaylistDurationCheck.vue' import APlaylistEntries from '@/components/playlist/APlaylistEntries.vue' +import APermissionGuard from '@/components/generic/APermissionGuard.vue' +import { useHasUserPermission } from '@/stores/auth' const props = withDefaults( defineProps<{ @@ -189,6 +214,8 @@ const entryAddError = ref<Error>() const nonAddedEntries = ref<Partial<PlaylistEntry>[]>([]) const isRetrying = ref(false) +const isAllowedToAddFiles = useHasUserPermission(['program.add__file']) + const uploadedFiles = ref( new Map< TankFile['id'], @@ -199,7 +226,11 @@ const dropzoneEl = ref<HTMLDivElement>() const { open: openFileDialog, files } = useFileDialog({ accept: 'audio/*', multiple: true }) watch(files, (newFiles) => uploadFiles(Array.from(newFiles ?? []))) const { isOverDropZone } = useDropZone(dropzoneEl, { - onDrop: (files) => uploadFiles(files ?? []), + onDrop: (files) => { + if (isAllowedToAddFiles.value) { + uploadFiles(files ?? []) + } + }, }) async function retryUpload(tankFile: TankFile, file: File) {