[WIP] replace modals and buttons with new ui components

This commit is contained in:
ArneBo 2024-12-12 17:04:41 +01:00 committed by upsiflu
parent e0fb7f0fc4
commit 5399f9be0e
6 changed files with 76 additions and 73 deletions

View File

@ -2,7 +2,7 @@
import Modal from '~/components/ui/Modal.vue' import Modal from '~/components/ui/Modal.vue'
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import Button from '~/components/ui/Button.vue'
const model = defineModel<boolean>() const model = defineModel<boolean>()
@ -141,9 +141,9 @@ const player = computed(() => [
</div> </div>
</section> </section>
<footer class="actions"> <footer class="actions">
<button class="ui basic cancel button"> <Button color="secondary">
{{ t('components.ShortcutsModal.button.close') }} {{ t('components.ShortcutsModal.button.close') }}
</button> </Button>
</footer> </footer>
</Modal> </Modal>
</template> </template>

View File

@ -2,6 +2,8 @@
import type { Form } from '~/types' import type { Form } from '~/types'
import SignupForm from '~/components/auth/SignupForm.vue' import SignupForm from '~/components/auth/SignupForm.vue'
import Button from '~/components/ui/Button.vue'
import { useVModel } from '@vueuse/core' import { useVModel } from '@vueuse/core'
import { computed, ref } from 'vue' import { computed, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
@ -65,18 +67,20 @@ const move = (idx: number, increment: number) => {
<template> <template>
<div> <div>
<div class="ui top attached tabular menu"> <div class="ui top attached tabular menu">
<button <Button
color="primary"
:class="[{active: !isPreviewing}, 'item']" :class="[{active: !isPreviewing}, 'item']"
@click.stop.prevent="isPreviewing = false" @click.stop.prevent="isPreviewing = false"
> >
{{ t('components.admin.SignupFormBuilder.button.edit') }} {{ t('components.admin.SignupFormBuilder.Button.edit') }}
</button> </Button>
<button <Button
color="primary"
:class="[{active: isPreviewing}, 'item']" :class="[{active: isPreviewing}, 'item']"
@click.stop.prevent="isPreviewing = true" @click.stop.prevent="isPreviewing = true"
> >
{{ t('components.admin.SignupFormBuilder.button.preview') }} {{ t('components.admin.SignupFormBuilder.Button.preview') }}
</button> </Button>
</div> </div>
<div <div
v-if="isPreviewing" v-if="isPreviewing"
@ -187,13 +191,13 @@ const move = (idx: number, increment: number) => {
</tbody> </tbody>
</table> </table>
<div class="ui hidden divider" /> <div class="ui hidden divider" />
<button <Button
color = "primary"
v-if="value.fields?.length < maxFields" v-if="value.fields?.length < maxFields"
class="ui basic button"
@click.stop.prevent="addField" @click.stop.prevent="addField"
> >
{{ t('components.admin.SignupFormBuilder.button.add') }} {{ t('components.admin.SignupFormBuilder.button.add') }}
</button> </Button>
</div> </div>
</div> </div>
<div class="ui hidden divider" /> <div class="ui hidden divider" />

View File

@ -3,8 +3,10 @@ import type { OrderingProps } from '~/composables/navigation/useOrdering'
import type { Artist, BackendResponse } from '~/types' import type { Artist, BackendResponse } from '~/types'
import type { RouteRecordName } from 'vue-router' import type { RouteRecordName } from 'vue-router'
import type { OrderingField } from '~/store/ui' import type { OrderingField } from '~/store/ui'
import Popover from "~/components/ui/Popover.vue"
import PopoverItem from "~/components/ui/popover/PopoverItem.vue"
import { computed, ref, watch, onMounted } from 'vue' import { computed, ref, watch } from 'vue'
import { useRouteQuery } from '@vueuse/router' import { useRouteQuery } from '@vueuse/router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { syncRef } from '@vueuse/core' import { syncRef } from '@vueuse/core'
@ -12,11 +14,10 @@ import { sortedUniq } from 'lodash-es'
import { useStore } from '~/store' import { useStore } from '~/store'
import axios from 'axios' import axios from 'axios'
import $ from 'jquery'
import TagsSelector from '~/components/library/TagsSelector.vue' import TagsSelector from '~/components/library/TagsSelector.vue'
import RemoteSearchForm from '~/components/RemoteSearchForm.vue' import RemoteSearchForm from '~/components/RemoteSearchForm.vue'
import SemanticModal from '~/components/semantic/Modal.vue' import Modal from '~/components/ui/Modal.vue'
import ArtistCard from '~/components/artist/Card.vue' import ArtistCard from '~/components/artist/Card.vue'
import Pagination from '~/components/vui/Pagination.vue' import Pagination from '~/components/vui/Pagination.vue'
@ -103,13 +104,13 @@ const search = () => {
q.value = query.value q.value = query.value
} }
const artistOrdering = ref(false)
onOrderingUpdate(() => { onOrderingUpdate(() => {
page.value = 1 page.value = 1
fetchData() fetchData()
}) })
onMounted(() => $('.ui.dropdown').dropdown())
const { t } = useI18n() const { t } = useI18n()
const labels = computed(() => ({ const labels = computed(() => ({
searchPlaceholder: t('components.library.Podcasts.placeholder.search'), searchPlaceholder: t('components.library.Podcasts.placeholder.search'),
@ -157,19 +158,16 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
</div> </div>
<div class="field"> <div class="field">
<label for="artist-ordering">{{ t('components.library.Podcasts.ordering.label') }}</label> <label for="artist-ordering">{{ t('components.library.Podcasts.ordering.label') }}</label>
<select <Popover v-model:open="artistOrdering">
id="artist-ordering" <OptionsButton @click="artistOrdering = !artistOrdering" id="artist-ordering" v-model="ordering"/>
v-model="ordering" <PopoverItem
class="ui dropdown"
>
<option
v-for="(option, key) in orderingOptions" v-for="(option, key) in orderingOptions"
:key="key" :key="key"
:value="option[0]" :value="option[0]"
> >
{{ sharedLabels.filters[option[1]] }} {{ sharedLabels.filters[option[1]] }}
</option> </PopoverItem>
</select> </Popover>
</div> </div>
<div class="field"> <div class="field">
<label for="artist-ordering-direction">{{ t('components.library.Podcasts.ordering.direction.label') }}</label> <label for="artist-ordering-direction">{{ t('components.library.Podcasts.ordering.direction.label') }}</label>
@ -259,14 +257,11 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
/> />
</div> </div>
</section> </section>
<semantic-modal <Modal
v-model:show="showSubscribeModal" v-model:show="showSubscribeModal"
class="tiny" title="t('components.library.Podcasts.modal.subscription.header')"
:fullscreen="false" <!-- class="tiny" TODO: check if necessary -->
> >
<h2 class="header">
{{ t('components.library.Podcasts.modal.subscription.header') }}
</h2>
<div <div
ref="modalContent" ref="modalContent"
class="scrolling content" class="scrolling content"
@ -292,6 +287,6 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
{{ t('components.library.Podcasts.button.subscribe') }} {{ t('components.library.Podcasts.button.subscribe') }}
</button> </button>
</div> </div>
</semantic-modal> </Modal>
</main> </main>
</template> </template>

View File

@ -4,7 +4,7 @@ import type { BackendError, Playlist, APIErrorResponse } from '~/types'
import { filter, sortBy, flow } from 'lodash-es' import { filter, sortBy, flow } from 'lodash-es'
import axios from 'axios' import axios from 'axios'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import SemanticModal from '~/components/semantic/Modal.vue' import Modal from '~/components/ui/Modal.vue'
import PlaylistForm from '~/components/playlists/Form.vue' import PlaylistForm from '~/components/playlists/Form.vue'
import useLogger from '~/composables/useLogger' import useLogger from '~/composables/useLogger'
import { useStore } from '~/store' import { useStore } from '~/store'
@ -78,14 +78,17 @@ const addToPlaylist = async (playlistId: number, allowDuplicates: boolean) => {
} }
store.dispatch('playlists/fetchOwn') store.dispatch('playlists/fetchOwn')
const playlistIsOpen = store.state.playlists.showModal
</script> </script>
<template> <template>
<semantic-modal <Modal
v-model:show="store.state.playlists.showModal" v-model=playlistIsOpen
title="t('components.playlists.PlaylistModal.header.addToPlaylist')"
> >
<h4 class="header"> <h4 class="header">
<template v-if="track"> <template v-if="track">
// TODO: Check subheader
<h2 class="ui header"> <h2 class="ui header">
{{ t('components.playlists.PlaylistModal.header.addToPlaylist') }} {{ t('components.playlists.PlaylistModal.header.addToPlaylist') }}
<div class="ui sub header"> <div class="ui sub header">
@ -241,5 +244,5 @@ store.dispatch('playlists/fetchOwn')
{{ t('components.playlists.PlaylistModal.button.cancel') }} {{ t('components.playlists.PlaylistModal.button.cancel') }}
</button> </button>
</div> </div>
</semantic-modal> </Modal>
</template> </template>

View File

@ -2,8 +2,11 @@
import { computed, ref, reactive } from 'vue' import { computed, ref, reactive } from 'vue'
import { useUploadsStore } from '~/ui/stores/upload' import { useUploadsStore } from '~/ui/stores/upload'
import { bytesToHumanSize } from '~/ui/composables/bytes' import { bytesToHumanSize } from '~/ui/composables/bytes'
import UploadList from '~/ui/components/UploadList.vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import UploadList from '~/ui/components/UploadList.vue'
import Alert from '~/components/ui/Alert.vue'
import Button from '~/components/ui/Button.vue'
import Modal from '~/components/ui/Modal.vue'
const uploads = useUploadsStore() const uploads = useUploadsStore()
@ -54,6 +57,8 @@ const continueInBackground = () => {
return router.push('/upload/running') return router.push('/upload/running')
} }
//TODO (whole file): Translations
// Sorting // Sorting
const sortItems = reactive([ const sortItems = reactive([
{ label: 'Upload time', value: 'upload-time' }, { label: 'Upload time', value: 'upload-time' },
@ -67,25 +72,24 @@ const filterItems = reactive([
{ label: 'All', value: 'all' } { label: 'All', value: 'all' }
]) ])
const currentFilter = ref(filterItems[0]) const currentFilter = ref(filterItems[0])
</script> </script>
<template> <template>
<FwModal <Modal
v-model="libraryOpen" v-model="libraryOpen"
title="Upload music to library" title="Upload music to library"
> >
<template #alert="{ closeAlert }"> <template #alert="closeAlert">
<FwAlert> <Alert>
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.
<template #actions> <template #actions>
<FwButton @click="closeAlert"> <Button @click="closeAlert">
Got it Got it
</FwButton> </Button>
</template> </template>
</FwAlert> </Alert>
</template> </template>
<FwFileInput <FwFileInput
@ -125,24 +129,25 @@ const currentFilter = ref(filterItems[0])
v-model="serverPath" v-model="serverPath"
class="w-full mr-4" class="w-full mr-4"
/> />
<FwButton color="secondary"> <Button color="secondary">
Import Import
</FwButton> </Button>
</div> </div>
</template> </template>
<template #actions> <template #actions>
<FwButton <Button
color="secondary" color="secondary"
@click="cancel" @click="cancel"
> >
Cancel Cancel
</FwButton> </Button>
<FwButton @click="continueInBackground"> <Button @click="continueInBackground">
{{ uploads.queue.length ? 'Continue in background' : 'Save and close' }} {{ uploads.queue.length ? 'Continue in background' : 'Save and close' }}
</FwButton> //TODO: Translations
</Button>
</template> </template>
</FwModal> </Modal>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -10,9 +10,10 @@ import axios from 'axios'
import PlaylistEditor from '~/components/playlists/Editor.vue' import PlaylistEditor from '~/components/playlists/Editor.vue'
import EmbedWizard from '~/components/audio/EmbedWizard.vue' import EmbedWizard from '~/components/audio/EmbedWizard.vue'
import SemanticModal from '~/components/semantic/Modal.vue' import Modal from '~/components/ui/Modal.vue'
import TrackTable from '~/components/audio/track/Table.vue' import TrackTable from '~/components/audio/track/Table.vue'
import PlayButton from '~/components/audio/PlayButton.vue' import PlayButton from '~/components/audio/PlayButton.vue'
import Button from '~/components/ui/Button.vue'
import PlaylistDropdown from '~/components/playlists/PlaylistDropdown.vue' import PlaylistDropdown from '~/components/playlists/PlaylistDropdown.vue'
@ -113,24 +114,23 @@ const deletePlaylist = async () => {
</play-button> </play-button>
</div> </div>
<div class="ui buttons"> <div class="ui buttons">
<button <Button
v-if="store.state.auth.profile && playlist.actor.full_username === store.state.auth.fullUsername" v-if="store.state.auth.profile && playlist.actor.full_username === store.state.auth.fullUsername"
class="ui icon labeled button"
@click="edit = !edit" @click="edit = !edit"
icon="bi-pencil"
> >
<i class="pencil icon" />
<template v-if="edit"> <template v-if="edit">
{{ t('views.playlists.Detail.button.stopEdit') }} {{ t('views.playlists.Detail.button.stopEdit') }}
</template> </template>
<template v-else> <template v-else>
{{ t('views.playlists.Detail.button.edit') }} {{ t('views.playlists.Detail.button.edit') }}
</template> </template>
</button> </Button>
</div> </div>
<div class="ui buttons"> <div class="ui buttons">
<button <Button
v-if="playlist.privacy_level === 'everyone' && playlist.is_playable" v-if="playlist.privacy_level === 'everyone' && playlist.is_playable"
class="ui icon labeled button" icon="bi-code-slash"
@click="showEmbedModal = !showEmbedModal" @click="showEmbedModal = !showEmbedModal"
> >
<i class="code icon" /> <i class="code icon" />
@ -141,7 +141,6 @@ const deletePlaylist = async () => {
class="ui labeled danger icon button" class="ui labeled danger icon button"
:action="deletePlaylist" :action="deletePlaylist"
> >
<i class="trash icon" />
{{ t('views.playlists.Detail.button.delete') }} {{ t('views.playlists.Detail.button.delete') }}
<template #modal-header> <template #modal-header>
<p> <p>
@ -166,13 +165,11 @@ const deletePlaylist = async () => {
/> />
</div> </div>
</div> </div>
<semantic-modal <Modal
v-if="playlist.privacy_level === 'everyone' && playlist.is_playable" v-if="playlist.privacy_level === 'everyone' && playlist.is_playable"
v-model:show="showEmbedModal" v-model="showEmbedModal"
title="t('views.playlists.Detail.modal.embed.header')"
> >
<h4 class="header">
{{ t('views.playlists.Detail.modal.embed.header') }}
</h4>
<div class="scrolling content"> <div class="scrolling content">
<div class="description"> <div class="description">
<embed-wizard <embed-wizard
@ -181,12 +178,12 @@ const deletePlaylist = async () => {
/> />
</div> </div>
</div> </div>
<div class="actions"> <template #actions>
<button class="ui basic deny button"> <Button variant="outline">
{{ t('views.playlists.Detail.button.cancel') }} {{ t('views.playlists.Detail.button.cancel') }}
</button> </Button>
</div> </template>
</semantic-modal> </Modal>
</div> </div>
</section> </section>
<section class="ui vertical stripe segment"> <section class="ui vertical stripe segment">
@ -214,13 +211,12 @@ const deletePlaylist = async () => {
<i class="list icon" /> <i class="list icon" />
{{ t('views.playlists.Detail.empty.noTracks') }} {{ t('views.playlists.Detail.empty.noTracks') }}
</div> </div>
<button <Button
class="ui success icon labeled button" icon="bi-pencil"
@click="edit = !edit" @click="edit = !edit"
> >
<i class="pencil icon" />
{{ t('views.playlists.Detail.button.edit') }} {{ t('views.playlists.Detail.button.edit') }}
</button> </Button>
</div> </div>
</section> </section>
</main> </main>