refactor(upload): [WIP] rebuild upload modal functionality
This commit is contained in:
parent
5a39323e11
commit
a23996bbdd
|
@ -40,6 +40,7 @@ const fetchData = async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log("I found another album with artist", props.channel?.artist.name, ":", response.data.results)
|
||||||
albums.push(...response.data.results)
|
albums.push(...response.data.results)
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
@ -57,6 +58,7 @@ watch(() => props.channel, fetchData, { immediate: true })
|
||||||
{{ t('components.channels.AlbumSelect.label.album') }}
|
{{ t('components.channels.AlbumSelect.label.album') }}
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
{{ albums }}
|
||||||
<select
|
<select
|
||||||
id="album-dropdown"
|
id="album-dropdown"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
|
|
|
@ -89,7 +89,7 @@ const fetchChannels = async () => {
|
||||||
availableChannels.loading = false
|
availableChannels.loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedChannel = computed(() => availableChannels.channels.find((channel) => channel.uuid === values.channel) ?? null)
|
const selectedChannel = computed(() => availableChannels.channels[0])
|
||||||
|
|
||||||
//
|
//
|
||||||
// Quota and space
|
// Quota and space
|
||||||
|
@ -302,49 +302,6 @@ const retry = async (file: VueUploadItem) => {
|
||||||
fetchChannels()
|
fetchChannels()
|
||||||
fetchQuota()
|
fetchQuota()
|
||||||
|
|
||||||
//
|
|
||||||
// Dropdown
|
|
||||||
//
|
|
||||||
const el = useCurrentElement()
|
|
||||||
watch(() => availableChannels.channels, () => {
|
|
||||||
$(el.value).find('#channel-dropdown').dropdown({
|
|
||||||
onChange (value) {
|
|
||||||
values.channel = value
|
|
||||||
},
|
|
||||||
values: availableChannels.channels.map((channel) => {
|
|
||||||
const value = {
|
|
||||||
name: channel.artist?.name ?? '',
|
|
||||||
value: channel.uuid,
|
|
||||||
selected: props.channel?.uuid === channel.uuid
|
|
||||||
} as {
|
|
||||||
name: string
|
|
||||||
value: string
|
|
||||||
selected: boolean
|
|
||||||
image?: string
|
|
||||||
imageClass?: string
|
|
||||||
icon?: string
|
|
||||||
iconClass?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel.artist?.cover?.urls.medium_square_crop) {
|
|
||||||
value.image = store.getters['instance/absoluteUrl'](channel.artist.cover.urls.medium_square_crop)
|
|
||||||
value.imageClass = channel.artist.content_category !== 'podcast'
|
|
||||||
? 'ui image avatar'
|
|
||||||
: 'ui image'
|
|
||||||
} else {
|
|
||||||
value.icon = 'user'
|
|
||||||
value.iconClass = channel.artist?.content_category !== 'podcast'
|
|
||||||
? 'circular icon'
|
|
||||||
: 'bordered icon'
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
$(el.value).find('#channel-dropdown').dropdown('hide')
|
|
||||||
})
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Step
|
// Step
|
||||||
//
|
//
|
||||||
|
@ -454,15 +411,8 @@ defineExpose({
|
||||||
</div>
|
</div>
|
||||||
<div :class="['ui', 'required', {hidden: step > 1}, 'field']">
|
<div :class="['ui', 'required', {hidden: step > 1}, 'field']">
|
||||||
<label for="channel-dropdown">
|
<label for="channel-dropdown">
|
||||||
{{ t('components.channels.UploadForm.label.channel') }}
|
{{ t('components.channels.UploadForm.label.channel') }}: {{ selectedChannel?.artist.name }}
|
||||||
</label>
|
</label>
|
||||||
<div
|
|
||||||
id="channel-dropdown"
|
|
||||||
class="ui search normal selection dropdown"
|
|
||||||
>
|
|
||||||
<div class="text" />
|
|
||||||
<i class="dropdown icon" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<album-select
|
<album-select
|
||||||
v-model.number="values.album"
|
v-model.number="values.album"
|
||||||
|
|
|
@ -18,6 +18,7 @@ import FileUploadWidget from '~/components/library/FileUploadWidget.vue';
|
||||||
import type { VueUploadItem } from 'vue-upload-component';
|
import type { VueUploadItem } from 'vue-upload-component';
|
||||||
import ChannelUpload from '~/components/channels/UploadForm.vue';
|
import ChannelUpload from '~/components/channels/UploadForm.vue';
|
||||||
import LibraryUpload from '~/components/library/FileUpload.vue';
|
import LibraryUpload from '~/components/library/FileUpload.vue';
|
||||||
|
import LibraryWidget from '~/components/federation/LibraryWidget.vue'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
@ -29,40 +30,23 @@ const isOpen = computed({
|
||||||
return store.state.ui.modalsOpen.has(modalName);
|
return store.state.ui.modalsOpen.has(modalName);
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
store.commit('ui/setModal', [modalName, value]);
|
if (value===false) {
|
||||||
|
state.value = init()
|
||||||
|
}
|
||||||
|
store.commit('ui/setModal', [modalName, value])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
onKeyboardShortcut('u', () => store.commit('ui/toggleModal', modalName))
|
onKeyboardShortcut('u', () => store.commit('ui/toggleModal', modalName))
|
||||||
|
|
||||||
const dummyActor = (number:number) : Actor => ({
|
|
||||||
id: number,
|
|
||||||
summary: "actor summary",
|
|
||||||
preferred_username: `actor ${number}`,
|
|
||||||
full_username: "actor full username",
|
|
||||||
is_local: false,
|
|
||||||
domain: "domain"
|
|
||||||
})
|
|
||||||
|
|
||||||
const dummyChannel=(number:number) : Channel=>
|
|
||||||
({
|
|
||||||
id : number,
|
|
||||||
uuid : 'uuid',
|
|
||||||
actor: dummyActor(number),
|
|
||||||
attributed_to: dummyActor(number),
|
|
||||||
rss_url: "rss url string",
|
|
||||||
subscriptions_count: 10,
|
|
||||||
downloads_count: 10,
|
|
||||||
content_category: 'music'
|
|
||||||
})
|
|
||||||
|
|
||||||
type UploadDestination = 'channel' | 'library' | 'podcast'
|
type UploadDestination = 'channel' | 'library' | 'podcast'
|
||||||
|
|
||||||
type State =
|
type State =
|
||||||
{ uploadDestination? : UploadDestination, page: typeof pages[number], files?: string[] }
|
{ uploadDestination? : UploadDestination, page: typeof pages[number], files?: string[] }
|
||||||
|
|
||||||
// initial state
|
// initial state
|
||||||
const state = ref<State>({page : 'selectDestination'});
|
const init = () => ({ page : 'selectDestination' } as const)
|
||||||
|
const state = ref<State>(init())
|
||||||
|
|
||||||
const pages = ['selectDestination', 'uploadFiles', 'uploadsInProgress'] as const
|
const pages = ['selectDestination', 'uploadFiles', 'uploadsInProgress'] as const
|
||||||
|
|
||||||
|
@ -70,6 +54,20 @@ const pages = ['selectDestination', 'uploadFiles', 'uploadsInProgress'] as const
|
||||||
const destinationSelected = (destination: UploadDestination) =>
|
const destinationSelected = (destination: UploadDestination) =>
|
||||||
state.value = {...state.value, uploadDestination:destination, page:'uploadFiles' }
|
state.value = {...state.value, uploadDestination:destination, page:'uploadFiles' }
|
||||||
|
|
||||||
|
// Wait for pablo: If no channel exists, auto-create an empty channel
|
||||||
|
|
||||||
|
// Step 1.1
|
||||||
|
|
||||||
|
/*
|
||||||
|
- Load the library for the chosen privacy level
|
||||||
|
-
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Lade User
|
||||||
|
const url="`federation/actors/${object.full_username}/libraries/`"
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
const filesSelected = (e: InputEvent)=>{
|
const filesSelected = (e: InputEvent)=>{
|
||||||
state.value = {...state.value, files: [] }
|
state.value = {...state.value, files: [] }
|
||||||
|
@ -79,18 +77,6 @@ const modalTitle = computed(()=>
|
||||||
({ 'selectDestination' : 'Upload', 'uploadFiles' : 'Select files for upload', 'uploadsInProgress': 'Uploading...'}
|
({ 'selectDestination' : 'Upload', 'uploadFiles' : 'Select files for upload', 'uploadsInProgress': 'Uploading...'}
|
||||||
[state.value.page])
|
[state.value.page])
|
||||||
)
|
)
|
||||||
|
|
||||||
// Upload input metadata
|
|
||||||
|
|
||||||
const values = reactive({
|
|
||||||
channel: null,
|
|
||||||
license: null,
|
|
||||||
album: null
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const channels = [0,1,2,3,4].map(dummyChannel)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -98,83 +84,92 @@ const channels = [0,1,2,3,4].map(dummyChannel)
|
||||||
:title="modalTitle"
|
:title="modalTitle"
|
||||||
v-model="isOpen"
|
v-model="isOpen"
|
||||||
>
|
>
|
||||||
|
|
||||||
|
<!-- Alert -->
|
||||||
|
|
||||||
<template #alert v-if="state.page === 'selectDestination'">
|
<template #alert v-if="state.page === 'selectDestination'">
|
||||||
<Alert yellow>
|
<Alert blue>
|
||||||
Before uploading, please ensure your files are tagged properly.
|
Before uploading, please ensure your files are tagged properly.
|
||||||
We recommend using Picard for that purpose.
|
We recommend using Picard for that purpose.
|
||||||
</Alert>
|
</Alert>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<Layout flex style="place-content:center" v-if="state.page === 'selectDestination'">
|
<!-- Page content -->
|
||||||
<Card small solid secondary title="Music"
|
<!-- Page 1 -->
|
||||||
@click="destinationSelected('channel')"
|
|
||||||
icon="bi-upload primary solid"
|
|
||||||
>
|
|
||||||
<template #image>
|
|
||||||
<i class="bi bi-music-note-beamed solid primary" :class="$style.icon"></i>
|
|
||||||
</template>
|
|
||||||
Publish music you make
|
|
||||||
</Card>
|
|
||||||
<Card small solid secondary title="Podcast"
|
|
||||||
@click="destinationSelected('podcast')"
|
|
||||||
icon="bi-upload primary solid"
|
|
||||||
>
|
|
||||||
<template #image>
|
|
||||||
<i class="bi bi-mic-fill solid primary" :class="$style.icon"></i>
|
|
||||||
</template>
|
|
||||||
Publish podcasts you make
|
|
||||||
</Card>
|
|
||||||
<Card small solid secondary title="Mix & Share"
|
|
||||||
@click="destinationSelected('library')"
|
|
||||||
icon="bi-upload"
|
|
||||||
>
|
|
||||||
<template #image>
|
|
||||||
<i class="bi bi-headphones solid secondary raised" :class="$style.icon"></i>
|
|
||||||
</template>
|
|
||||||
Host music you listen to
|
|
||||||
</Card>
|
|
||||||
</Layout>
|
|
||||||
|
|
||||||
<Layout stack v-if="state.page === 'uploadFiles'">
|
<Layout flex style="place-content:center" v-if="state.page === 'selectDestination'">
|
||||||
UPLOAD FILES
|
<Card small title="Music"
|
||||||
<!-- <Input
|
icon="bi-upload primary solid"
|
||||||
type="file"
|
@click="destinationSelected('channel')"
|
||||||
:accept="['.flac', '.ogg', '.opus', '.mp3', '.aac', '.aif', '.aiff', '.m4a'].join(', ')"
|
>
|
||||||
multiple
|
<template #image>
|
||||||
auto-reset
|
<i class="bi bi-music-note-beamed solid primary" :class="$style.icon"></i>
|
||||||
@input="filesSelected"
|
</template>
|
||||||
/> -->
|
{{ "Publish music you make" /* TODO: Translate */ }}
|
||||||
|
</Card>
|
||||||
|
<Card small title="Podcast"
|
||||||
|
icon="bi-upload primary solid"
|
||||||
|
@click="destinationSelected('podcast')"
|
||||||
|
>
|
||||||
|
<template #image>
|
||||||
|
<i class="bi bi-mic-fill solid primary" :class="$style.icon"></i>
|
||||||
|
</template>
|
||||||
|
{{ "Publish podcasts you make" /* TODO: Translate */ }}
|
||||||
|
</Card>
|
||||||
|
<Card small title="Mix & Share"
|
||||||
|
icon="bi-upload"
|
||||||
|
@click="destinationSelected('library')"
|
||||||
|
>
|
||||||
|
<template #image>
|
||||||
|
<i class="bi bi-headphones solid secondary raised" :class="$style.icon"></i>
|
||||||
|
</template>
|
||||||
|
{{ "Host music you listen to" /* TODO: Translate */ }}
|
||||||
|
</Card>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
<!-- <UploadForm></UploadForm> -->
|
<!-- Page 2 -->
|
||||||
<LibraryUpload v-if="state.uploadDestination==='library'"
|
|
||||||
:library="{uuid: 'string'}">
|
|
||||||
</LibraryUpload>
|
|
||||||
{{ state.files }}
|
|
||||||
|
|
||||||
<ChannelUpload v-if="state.uploadDestination==='channel'" />
|
<Layout stack v-if="state.page === 'uploadFiles'">
|
||||||
</Layout>
|
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<ChannelUpload v-if="state.uploadDestination === 'channel'" />
|
||||||
|
|
||||||
|
<!-- -->
|
||||||
|
|
||||||
|
<!-- Privacy Slider -->
|
||||||
|
<LibraryUpload v-if="state.uploadDestination === 'library'"
|
||||||
|
:library="{uuid: 'string'} /* Get corresponding library from user */">
|
||||||
|
</LibraryUpload>
|
||||||
|
{{ state.files }}
|
||||||
|
</Layout>
|
||||||
|
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<Button secondary>
|
<Button secondary
|
||||||
Cancel
|
v-if="state.page !== pages[0]"
|
||||||
|
:onClick="() => { state.page = pages[(pages.indexOf(state.page) || 1) - 1] }">
|
||||||
|
{{ t('components.channels.UploadModal.button.previous') }}
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled v-if="state.page === 'selectDestination'">
|
<Spacer h grow />
|
||||||
Continue in background' : 'Save and close'
|
<Button secondary :onClick="() => { isOpen = false }">
|
||||||
|
{{ t('components.channels.UploadModal.button.cancel') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Spacer size-16 />
|
||||||
<Button primary v-if="state.page === 'uploadFiles'">
|
<Button primary v-if="state.page === 'uploadFiles'">
|
||||||
Continue in background' : 'Save and close'
|
{{ t('components.channels.UploadModal.button.finishLater') }} /
|
||||||
|
{{ t('components.channels.UploadModal.button.publish') }} /
|
||||||
|
{{ t('components.channels.UploadModal.button.update') }}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
</Modal>
|
</Modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style module>
|
<style module>
|
||||||
.icon {
|
.icon {
|
||||||
font-size:100px;
|
font-size:100px;
|
||||||
padding:28px;
|
padding:28px;
|
||||||
inset:0;
|
inset:0;
|
||||||
display:block;
|
display:block;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue