chore(front): replace semantic-modal with Modal component (+ some modernization)
This commit is contained in:
parent
eb4258d66e
commit
a463cc305a
|
@ -1,11 +1,13 @@
|
|||
<script setup lang="ts">
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import axios from 'axios'
|
||||
import { uniq } from 'lodash-es'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { ref, computed, watch, nextTick } from 'vue'
|
||||
import { useStore } from '~/store'
|
||||
// import { useGettext } from 'vue3-gettext'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
interface Props {
|
||||
show: boolean
|
||||
|
@ -63,13 +65,13 @@ const checkAndSwitch = async (url: string) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal
|
||||
v-model:show="show"
|
||||
@update:show="isError = false"
|
||||
<Modal :title="t('views.ChooseInstance.header.chooseInstance')"
|
||||
v-model="show"
|
||||
@update="isError = false"
|
||||
>
|
||||
<h3 class="header">
|
||||
<!-- TODO: translate -->
|
||||
Choose your instance
|
||||
|
||||
<!-- <translate translate-context="Popup/Instance/Title">
|
||||
</translate> -->
|
||||
</h3>
|
||||
|
@ -177,5 +179,5 @@ const checkAndSwitch = async (url: string) => {
|
|||
</translate> -->
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { Track, Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||
import type { Track, SimpleArtist as Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||
import type { PlayOptionsProps } from '~/composables/audio/usePlayOptions'
|
||||
// import type { Track } from '~/types'
|
||||
|
||||
import { useStore } from '~/store'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||
import useReport from '~/composables/moderation/useReport'
|
||||
|
@ -93,13 +92,14 @@ const labels = computed(() => ({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal
|
||||
<Modal
|
||||
:title="track.title"
|
||||
ref="modal"
|
||||
v-model:show="show"
|
||||
v-model="show"
|
||||
:scrolling="true"
|
||||
:additional-classes="['scrolling-track-options']"
|
||||
class="scrolling-track-options"
|
||||
>
|
||||
<div class="header">
|
||||
<template #topright>
|
||||
<div class="ui large centered rounded image">
|
||||
<img
|
||||
v-if="track.album && track.album.cover && track.album.cover.urls.original"
|
||||
|
@ -122,7 +122,7 @@ const labels = computed(() => ({
|
|||
class="ui centered image"
|
||||
>
|
||||
<img
|
||||
v-else-if="!!track.artist_credit?.length && track.artist_credit[0].artist.cover"
|
||||
v-else-if="!!track.artist_credit?.length && track.artist_credit[0].artist.attachment_cover"
|
||||
v-lazy="
|
||||
getArtistCoverUrl(track.artist_credit)
|
||||
"
|
||||
|
@ -136,13 +136,10 @@ const labels = computed(() => ({
|
|||
src="../../../assets/audio/default-cover.png"
|
||||
>
|
||||
</div>
|
||||
<h3 class="track-modal-title">
|
||||
{{ track.title }}
|
||||
</h3>
|
||||
<h4 class="track-modal-subtitle">
|
||||
{{ generateTrackCreditString(track) }}
|
||||
</h4>
|
||||
</div>
|
||||
</template>
|
||||
<div class="ui hidden divider" />
|
||||
<div class="content">
|
||||
<div class="ui one column unstackable grid">
|
||||
|
@ -178,7 +175,7 @@ const labels = computed(() => ({
|
|||
:aria-label="labels.addToQueue"
|
||||
@click.stop.prevent="
|
||||
enqueue();
|
||||
modal.closeModal();
|
||||
show=false
|
||||
"
|
||||
>
|
||||
<i class="plus icon track-modal list-icon" />
|
||||
|
@ -192,7 +189,7 @@ const labels = computed(() => ({
|
|||
:aria-label="labels.playNext"
|
||||
@click.stop.prevent="
|
||||
enqueueNext(true);
|
||||
modal.closeModal();
|
||||
show=false
|
||||
"
|
||||
>
|
||||
<i class="step forward icon track-modal list-icon" />
|
||||
|
@ -209,7 +206,7 @@ const labels = computed(() => ({
|
|||
type: 'similar',
|
||||
objectId: track.id,
|
||||
});
|
||||
modal.closeModal();
|
||||
show=false
|
||||
"
|
||||
>
|
||||
<i class="rss icon track-modal list-icon" />
|
||||
|
@ -301,5 +298,5 @@ const labels = computed(() => ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import type { Track, Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||
import type { Track, SimpleArtist as Artist, Album, Playlist, Library, Channel, Actor } from '~/types'
|
||||
import type { PlayOptionsProps } from '~/composables/audio/usePlayOptions'
|
||||
// import type { Track } from '~/types'
|
||||
import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||
import useReport from '~/composables/moderation/useReport'
|
||||
|
||||
import { useStore } from '~/store'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import usePlayOptions from '~/composables/audio/usePlayOptions'
|
||||
import useReport from '~/composables/moderation/useReport'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { generateTrackCreditString, getArtistCoverUrl } from '~/utils/utils'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
|
||||
interface Events {
|
||||
(e: 'update:show', value: boolean): void
|
||||
}
|
||||
|
@ -92,11 +93,11 @@ const labels = computed(() => ({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal
|
||||
<Modal :title="track.title"
|
||||
ref="modal"
|
||||
v-model:show="show"
|
||||
v-model="show"
|
||||
:scrolling="true"
|
||||
:additional-classes="['scrolling-track-options']"
|
||||
class="scrolling-track-options"
|
||||
>
|
||||
<div class="header">
|
||||
<div class="ui large centered rounded image">
|
||||
|
@ -125,9 +126,6 @@ const labels = computed(() => ({
|
|||
src="../../../assets/audio/default-cover.png"
|
||||
>
|
||||
</div>
|
||||
<h3 class="track-modal-title">
|
||||
{{ track.title }}
|
||||
</h3>
|
||||
<h4 class="track-modal-subtitle">
|
||||
{{ generateTrackCreditString(track) }}
|
||||
</h4>
|
||||
|
@ -155,7 +153,7 @@ const labels = computed(() => ({
|
|||
class="column"
|
||||
role="button"
|
||||
:aria-label="labels.addToQueue"
|
||||
@click.stop.prevent="enqueue(); modal.closeModal()"
|
||||
@click.stop.prevent="enqueue(); show = false"
|
||||
>
|
||||
<i class="plus icon track-modal list-icon" />
|
||||
<span class="track-modal list-item">{{ labels.addToQueue }}</span>
|
||||
|
@ -166,7 +164,7 @@ const labels = computed(() => ({
|
|||
class="column"
|
||||
role="button"
|
||||
:aria-label="labels.playNext"
|
||||
@click.stop.prevent="enqueueNext(true);modal.closeModal()"
|
||||
@click.stop.prevent="enqueueNext(true);show = false"
|
||||
>
|
||||
<i class="step forward icon track-modal list-icon" />
|
||||
<span class="track-modal list-item">{{ labels.playNext }}</span>
|
||||
|
@ -177,7 +175,7 @@ const labels = computed(() => ({
|
|||
class="column"
|
||||
role="button"
|
||||
:aria-label="labels.startRadio"
|
||||
@click.stop.prevent="() => { store.dispatch('radios/start', { type: 'similar', objectId: track.id }); modal.closeModal() }"
|
||||
@click.stop.prevent="() => { store.dispatch('radios/start', { type: 'similar', objectId: track.id }); show = false }"
|
||||
>
|
||||
<i class="rss icon track-modal list-icon" />
|
||||
<span class="track-modal list-item">{{ labels.startRadio }}</span>
|
||||
|
@ -253,5 +251,5 @@ const labels = computed(() => ({
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
import type { Channel } from '~/types'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import ChannelAlbumForm from '~/components/channels/AlbumForm.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
import { watch, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Spacer from '~/components/ui/Spacer.vue'
|
||||
|
||||
interface Events {
|
||||
(e: 'created'): void
|
||||
}
|
||||
|
@ -36,18 +38,11 @@ defineExpose({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal
|
||||
v-model:show="show"
|
||||
<Modal :title="t(channel.artist.content_category === 'podcast' ? 'components.channels.AlbumModal.header.newSeries' : 'components.channels.AlbumModal.header.newAlbum')"
|
||||
v-model="show"
|
||||
class="small"
|
||||
:cancel="t('components.channels.AlbumModal.button.cancel')"
|
||||
>
|
||||
<h4 class="header">
|
||||
<span v-if="channel.content_category === 'podcast'">
|
||||
{{ t('components.channels.AlbumModal.header.newSeries') }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ t('components.channels.AlbumModal.header.newAlbum') }}
|
||||
</span>
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<channel-album-form
|
||||
ref="albumForm"
|
||||
|
@ -57,10 +52,8 @@ defineExpose({
|
|||
@created="emit('created')"
|
||||
/>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<Button secondary>
|
||||
{{ t('components.channels.AlbumModal.button.cancel') }}
|
||||
</Button>
|
||||
<template #actions>
|
||||
<Spacer h grow />
|
||||
<Button
|
||||
:is-loading="isLoading"
|
||||
:disabled="!submittable"
|
||||
|
@ -68,6 +61,6 @@ defineExpose({
|
|||
>
|
||||
{{ t('components.channels.AlbumModal.button.create') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import ChannelUploadForm from '~/components/channels/UploadForm.vue'
|
||||
import Popover from '~/components/ui/Popover.vue'
|
||||
import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
|
||||
|
@ -53,24 +53,11 @@ const open = ref(false)
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal
|
||||
v-model:show="store.state.channels.showUploadModal"
|
||||
<Modal
|
||||
:title="t(`components.channels.UploadModal.header.${['', 'publish', 'uploadFiles', 'uploadDetails', 'processing'][step]}`)"
|
||||
v-model="store.state.channels.showUploadModal"
|
||||
class="small"
|
||||
>
|
||||
<h4 class="header">
|
||||
<span v-if="step === 1">
|
||||
{{ t('components.channels.UploadModal.header.publish') }}
|
||||
</span>
|
||||
<span v-else-if="step === 2">
|
||||
{{ t('components.channels.UploadModal.header.uploadFiles') }}
|
||||
</span>
|
||||
<span v-else-if="step === 3">
|
||||
{{ t('components.channels.UploadModal.header.uploadDetails') }}
|
||||
</span>
|
||||
<span v-else-if="step === 4">
|
||||
{{ t('components.channels.UploadModal.header.processing') }}
|
||||
</span>
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<channel-upload-form
|
||||
ref="uploadForm"
|
||||
|
@ -156,5 +143,5 @@ const open = ref(false)
|
|||
{{ t('components.channels.UploadModal.button.close') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -2,11 +2,14 @@
|
|||
import type { RouteLocationRaw } from 'vue-router'
|
||||
import type { Cover } from '~/types'
|
||||
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useStore } from '~/store'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Link from '~/components/ui/Link.vue'
|
||||
import Spacer from '~/components/ui/Spacer.vue'
|
||||
|
||||
interface Props {
|
||||
nextRoute: RouteLocationRaw
|
||||
message: string
|
||||
|
@ -29,10 +32,7 @@ const labels = computed(() => ({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal v-model:show="show">
|
||||
<h4 class="header">
|
||||
{{ labels.header }}
|
||||
</h4>
|
||||
<Modal v-model="show" :title="labels.header">
|
||||
<div
|
||||
v-if="cover"
|
||||
class="image content"
|
||||
|
@ -60,22 +60,21 @@ const labels = computed(() => ({
|
|||
{{ message }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<router-link
|
||||
<template #actions>
|
||||
<Spacer grow />
|
||||
<Link
|
||||
:to="{path: '/login', query: { next: nextRoute as string }}"
|
||||
class="ui labeled icon button"
|
||||
icon="bi-key-fill"
|
||||
>
|
||||
<i class="key icon" />
|
||||
{{ labels.login }}
|
||||
</router-link>
|
||||
<router-link
|
||||
</Link>
|
||||
<Link
|
||||
v-if="store.state.instance.settings.users.registration_enabled.value"
|
||||
:to="{path: '/signup'}"
|
||||
class="ui labeled icon button"
|
||||
icon="bi-person-fill"
|
||||
>
|
||||
<i class="user icon" />
|
||||
{{ labels.signup }}
|
||||
</router-link>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Link>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import type { BackendError } from '~/types'
|
||||
|
||||
import axios from 'axios'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import { useTimeoutFn } from '@vueuse/core'
|
||||
import { ref } from 'vue'
|
||||
|
@ -80,13 +80,11 @@ const { start: startPolling } = useTimeoutFn(poll, 1000, { immediate: false })
|
|||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
<semantic-modal
|
||||
v-model:show="showModal"
|
||||
<Modal :title="t('components.federation.FetchButton.header.refresh')"
|
||||
v-model="showModal"
|
||||
class="small"
|
||||
:cancel="t('components.federation.FetchButton.button.close')"
|
||||
>
|
||||
<h3 class="header">
|
||||
{{ t('components.federation.FetchButton.header.refresh') }}
|
||||
</h3>
|
||||
<div class="scrolling content">
|
||||
<template v-if="data && data.status != 'pending'">
|
||||
<div
|
||||
|
@ -213,9 +211,6 @@ const { start: startPolling } = useTimeoutFn(poll, 1000, { immediate: false })
|
|||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<Button color="secondary">
|
||||
{{ t('components.federation.FetchButton.button.close') }}
|
||||
</Button>
|
||||
<Button
|
||||
v-if="data && data.status === 'finished'"
|
||||
@click.prevent="showModal = false; emit('refresh')"
|
||||
|
@ -223,6 +218,6 @@ const { start: startPolling } = useTimeoutFn(poll, 1000, { immediate: false })
|
|||
{{ t('components.federation.FetchButton.button.reload') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -10,7 +10,8 @@ import { getDomain } from '~/utils'
|
|||
import useReport from '~/composables/moderation/useReport'
|
||||
|
||||
import EmbedWizard from '~/components/audio/EmbedWizard.vue'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Popover from '~/components/ui/Popover.vue'
|
||||
import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
|
||||
|
@ -45,7 +46,10 @@ const labels = computed(() => ({
|
|||
more: t('components.library.AlbumDropdown.button.more')
|
||||
}))
|
||||
|
||||
const isEmbedable = computed(() => (props.isChannel && props.artistCredit[0].artist?.channel?.actor) || props.publicLibraries.length)
|
||||
// TODO: What is the condition for an album to be embeddable?
|
||||
// (a) props.publicLibraries.length
|
||||
// (b) I am the channel's artist: props.isChannel && props.artistCredit[0].artist?.channel?.actor)
|
||||
const isEmbedable = computed(() => (props.publicLibraries.length))
|
||||
const musicbrainzUrl = computed(() => props.object?.mbid ? `https://musicbrainz.org/release/${props.object.mbid}` : null)
|
||||
const discogsUrl = computed(() => `https://discogs.com/search/?type=release&title=${encodeURI(props.object?.title)}&artist=${encodeURI(props.object?.artist_credit[0].artist.name)}`)
|
||||
|
||||
|
@ -56,32 +60,20 @@ const open = ref(false)
|
|||
|
||||
<template>
|
||||
<span>
|
||||
<semantic-modal
|
||||
<Modal :title="t('components.library.AlbumDropdown.modal.embed.header')"
|
||||
v-if="isEmbedable"
|
||||
v-model:show="showEmbedModal"
|
||||
v-model="showEmbedModal"
|
||||
:cancel="t('components.library.AlbumDropdown.button.cancel')"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('components.library.AlbumDropdown.modal.embed.header') }}
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<div class="description">
|
||||
<embed-wizard
|
||||
:id="object.id"
|
||||
type="album"
|
||||
/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<Button
|
||||
color="secondary"
|
||||
variant="outline"
|
||||
@click="showEmbedModal = false"
|
||||
>
|
||||
{{ t('components.library.AlbumDropdown.button.cancel') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
<Popover v-model:open="open">
|
||||
<template #default="{ toggleOpen }">
|
||||
<OptionsButton
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { Upload } from '~/types'
|
|||
import { useVModel } from '@vueuse/core'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
interface ErrorEntry {
|
||||
|
@ -76,10 +76,10 @@ const getErrorData = (upload: Upload) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal v-model:show="show">
|
||||
<h4 class="header">
|
||||
{{ t('components.library.ImportStatusModal.header.importDetail') }}
|
||||
</h4>
|
||||
<Modal :title="t('components.library.ImportStatusModal.header.importDetail')"
|
||||
v-model="show"
|
||||
:cancel="t('components.library.ImportStatusModal.button.close')"
|
||||
>
|
||||
<div
|
||||
v-if="Object.keys(upload).length > 0"
|
||||
class="content"
|
||||
|
@ -183,10 +183,5 @@ const getErrorData = (upload: Upload) => {
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<Button color="secondary">
|
||||
{{ t('components.library.ImportStatusModal.button.close') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ref, onMounted, watch, computed } from 'vue'
|
|||
import { useStore } from '~/store'
|
||||
import { clone } from 'lodash-es'
|
||||
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import TrackTable from '~/components/audio/track/Table.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
|
@ -49,6 +49,10 @@ const exclude = computed({
|
|||
})
|
||||
|
||||
const el = useCurrentElement()
|
||||
|
||||
// This component appears on "create new radio" and offers filters. "New filter" => Dropdown search field
|
||||
// TODO: Re-implement with <Input>, <select>
|
||||
|
||||
onMounted(() => {
|
||||
for (const field of data.value.filter.fields) {
|
||||
const settings: SemanticUI.DropdownSettings = {
|
||||
|
@ -182,13 +186,10 @@ fetchCandidates()
|
|||
>
|
||||
{{ t('components.library.radios.Filter.matchingTracks', checkResult.candidates.count) }}
|
||||
</a>
|
||||
<semantic-modal
|
||||
<Modal :title="t('components.library.radios.Filter.matchingTracksModalHeader')"
|
||||
v-if="checkResult"
|
||||
v-model:show="showCandidadesModal"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('components.library.radios.Filter.matchingTracksModalHeader') }}
|
||||
</h4>
|
||||
<div class="content">
|
||||
<div class="description">
|
||||
<track-table
|
||||
|
@ -202,7 +203,7 @@ fetchCandidates()
|
|||
{{ t('components.library.radios.Filter.cancelButton') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</td>
|
||||
<td>
|
||||
<Button
|
||||
|
|
|
@ -3,12 +3,12 @@ import type { BackendError } from '~/types'
|
|||
|
||||
import axios from 'axios'
|
||||
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import InstancePolicyForm from '~/components/manage/moderation/InstancePolicyForm.vue'
|
||||
import InstancePolicyCard from '~/components/manage/moderation/InstancePolicyCard.vue'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
interface Props {
|
||||
|
@ -29,6 +29,11 @@ const result = ref()
|
|||
const obj = computed(() => result.value?.results[0] ?? null)
|
||||
|
||||
const isLoading = ref(false)
|
||||
|
||||
watch (show, (newValue) => {
|
||||
if (newValue) fetchData()
|
||||
})
|
||||
|
||||
const fetchData = async () => {
|
||||
const [username, domain] = props.target.split('@')
|
||||
|
||||
|
@ -67,13 +72,10 @@ const fetchData = async () => {
|
|||
<slot>
|
||||
{{ t('components.manage.moderation.InstancePolicyModal.button.show') }}
|
||||
</slot>
|
||||
<semantic-modal
|
||||
v-model:show="show"
|
||||
@show="fetchData"
|
||||
<Modal :title="t('components.manage.moderation.InstancePolicyModal.modal.manage.header', {obj: target})"
|
||||
v-model="show"
|
||||
:cancel="t('components.manage.moderation.InstancePolicyModal.button.close')"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('components.manage.moderation.InstancePolicyModal.modal.manage.header', {obj: target}) }}
|
||||
</h4>
|
||||
<div class="content">
|
||||
<div class="description">
|
||||
<div
|
||||
|
@ -104,11 +106,6 @@ const fetchData = async () => {
|
|||
<div class="ui hidden divider" />
|
||||
<div class="ui hidden divider" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<Button color="secondary">
|
||||
{{ t('components.manage.moderation.InstancePolicyModal.button.close') }}
|
||||
</Button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</Button>
|
||||
</template>
|
||||
|
|
|
@ -7,9 +7,11 @@ import { computed, ref } from 'vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
import { useStore } from '~/store'
|
||||
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import useLogger from '~/composables/useLogger'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Alert from '~/components/ui/Alert.vue'
|
||||
|
||||
const logger = useLogger()
|
||||
const { t } = useI18n()
|
||||
|
||||
|
@ -58,23 +60,15 @@ const hide = async () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal v-model:show="show">
|
||||
<h4
|
||||
v-if="type === 'artist'"
|
||||
class="header"
|
||||
>
|
||||
{{ t('components.moderation.FilterModal.header.modal', {name: target?.name}) }}
|
||||
</h4>
|
||||
<Modal v-model="show"
|
||||
:title="type==='artist' ? t('components.moderation.FilterModal.header.modal', {name: target?.name}) : errors.length > 0 ? t('components.moderation.FilterModal.header.failure') : ''"
|
||||
:cancel="t('components.moderation.FilterModal.button.cancel')"
|
||||
>
|
||||
<div class="scrolling content">
|
||||
<div class="description">
|
||||
<div
|
||||
<Alert red
|
||||
v-if="errors.length > 0"
|
||||
role="alert"
|
||||
class="ui negative message"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('components.moderation.FilterModal.header.failure') }}
|
||||
</h4>
|
||||
<ul class="list">
|
||||
<li
|
||||
v-for="(error, key) in errors"
|
||||
|
@ -83,7 +77,7 @@ const hide = async () => {
|
|||
{{ error }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Alert>
|
||||
<template v-if="type === 'artist'">
|
||||
<p>
|
||||
{{ t('components.moderation.FilterModal.warning.createFilter.listIntro') }}
|
||||
|
@ -109,9 +103,6 @@ const hide = async () => {
|
|||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui basic cancel button">
|
||||
{{ t('components.moderation.FilterModal.button.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
:class="['ui', 'success', {loading: isLoading}, 'button']"
|
||||
@click="hide"
|
||||
|
@ -119,5 +110,5 @@ const hide = async () => {
|
|||
{{ t('components.moderation.FilterModal.button.hide') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -3,11 +3,13 @@ import type { BackendError } from '~/types'
|
|||
|
||||
import axios from 'axios'
|
||||
import ReportCategoryDropdown from '~/components/moderation/ReportCategoryDropdown.vue'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import { computed, ref, watchEffect } from 'vue'
|
||||
import { useStore } from '~/store'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
interface ReportType {
|
||||
anonymous: boolean
|
||||
type: string
|
||||
|
@ -120,12 +122,14 @@ watchEffect(async () => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<semantic-modal v-model:show="show">
|
||||
<Modal :title="target ? t('components.moderation.ReportModal.header.modal') : errors.length > 0 ? t('components.moderation.ReportModal.header.submissionFailure') : ''"
|
||||
v-model="show"
|
||||
:cancel="t('components.moderation.ReportModal.button.cancel')"
|
||||
>
|
||||
<h2
|
||||
v-if="target"
|
||||
class="ui header"
|
||||
>
|
||||
{{ t('components.moderation.ReportModal.header.modal') }}
|
||||
<div class="ui sub header">
|
||||
{{ target.typeLabel }}
|
||||
<span class="middle hyphen symbol" />
|
||||
|
@ -134,14 +138,9 @@ watchEffect(async () => {
|
|||
</h2>
|
||||
<div class="scrolling content">
|
||||
<div class="description">
|
||||
<div
|
||||
<Alert red
|
||||
v-if="errors.length > 0"
|
||||
role="alert"
|
||||
class="ui negative message"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('components.moderation.ReportModal.header.submissionFailure') }}
|
||||
</h4>
|
||||
<ul class="list">
|
||||
<li
|
||||
v-for="(error, key) in errors"
|
||||
|
@ -150,7 +149,7 @@ watchEffect(async () => {
|
|||
{{ error }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</Alert>
|
||||
</div>
|
||||
<p>
|
||||
{{ t('components.moderation.ReportModal.description.modal') }}
|
||||
|
@ -238,18 +237,15 @@ watchEffect(async () => {
|
|||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui basic cancel button">
|
||||
{{ t('components.moderation.ReportModal.button.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
<template #actions>
|
||||
<Button
|
||||
v-if="canSubmit"
|
||||
:class="['ui', 'success', {loading: isLoading}, 'button']"
|
||||
type="submit"
|
||||
form="report-form"
|
||||
>
|
||||
{{ t('components.moderation.ReportModal.button.submit') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from '~/store'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
|
||||
interface Props {
|
||||
fullscreen?: boolean
|
||||
scrolling?: boolean
|
||||
additionalClasses?: string[]
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
fullscreen: true,
|
||||
scrolling: false,
|
||||
additionalClasses: () => []
|
||||
})
|
||||
const store = useStore()
|
||||
const classes = computed(() => [
|
||||
...props.additionalClasses,
|
||||
{
|
||||
scrolling: props.scrolling,
|
||||
'overlay fullscreen': props.fullscreen && ['phone', 'tablet'].includes(store.getters['ui/windowSize'])
|
||||
}
|
||||
])
|
||||
|
||||
const isOpen = ref(false)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
(Semantic Modal)
|
||||
</template>
|
|
@ -1,7 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import type { Actor } from '~/types'
|
||||
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import LibraryWidget from '~/components/federation/LibraryWidget.vue'
|
||||
import ChannelsWidget from '~/components/audio/ChannelsWidget.vue'
|
||||
import ChannelForm from '~/components/audio/ChannelForm.vue'
|
||||
|
@ -10,6 +9,9 @@ import { useI18n } from 'vue-i18n'
|
|||
import { useStore } from '~/store'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
|
||||
interface Events {
|
||||
(e: 'updated', value: Actor): void
|
||||
}
|
||||
|
@ -83,24 +85,16 @@ const createForm = ref()
|
|||
</library-widget>
|
||||
</div>
|
||||
|
||||
<semantic-modal v-model:show="showCreateModal">
|
||||
<h4 class="header">
|
||||
<span
|
||||
v-if="step === 1"
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.modal.createChannel.header') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="category === 'podcast'"
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.modal.createChannel.podcast.header') }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.modal.createChannel.artist.header') }}
|
||||
</span>
|
||||
</h4>
|
||||
<Modal v-model="showCreateModal"
|
||||
:title="t(`views.auth.ProfileOverview.modal.createChannel.${
|
||||
step === 1 ?
|
||||
'header' :
|
||||
category === 'podcast' ?
|
||||
'podcast.header'
|
||||
:
|
||||
'artist.header'
|
||||
}`)"
|
||||
>
|
||||
<div
|
||||
ref="modalContent"
|
||||
class="scrolling content"
|
||||
|
@ -117,37 +111,35 @@ const createForm = ref()
|
|||
/>
|
||||
<div class="ui hidden divider" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button
|
||||
<template #actions>
|
||||
<Button destructive
|
||||
v-if="step === 1"
|
||||
class="ui basic deny button"
|
||||
autofocus
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.button.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
<Button secondary
|
||||
v-if="step > 1"
|
||||
class="ui basic button"
|
||||
@click.stop.prevent="step -= 1"
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.button.previous') }}
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
<Button primary
|
||||
v-if="step === 1"
|
||||
class="ui primary button"
|
||||
@click.stop.prevent="step += 1"
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.button.next') }}
|
||||
</button>
|
||||
<button
|
||||
</Button>
|
||||
<Button primary
|
||||
v-if="step === 2"
|
||||
:class="['ui', 'primary button', { loading }]"
|
||||
type="submit"
|
||||
:disabled="!submittable && !loading"
|
||||
:isLoading="loading"
|
||||
@click.prevent.stop="createForm.submit"
|
||||
>
|
||||
{{ t('views.auth.ProfileOverview.button.createChannel') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
@ -8,14 +8,17 @@ import { useStore } from '~/store'
|
|||
|
||||
import axios from 'axios'
|
||||
|
||||
import useErrorHandler from '~/composables/useErrorHandler'
|
||||
import useReport from '~/composables/moderation/useReport'
|
||||
|
||||
import SubscribeButton from '~/components/channels/SubscribeButton.vue'
|
||||
import ChannelForm from '~/components/audio/ChannelForm.vue'
|
||||
import EmbedWizard from '~/components/audio/EmbedWizard.vue'
|
||||
import HumanDuration from '~/components/common/HumanDuration.vue'
|
||||
import PlayButton from '~/components/audio/PlayButton.vue'
|
||||
import TagsList from '~/components/tags/List.vue'
|
||||
import SemanticModal from '~/components/semantic/Modal.vue'
|
||||
import RadioButton from '~/components/radios/Button.vue'
|
||||
|
||||
import Loader from '~/components/ui/Loader.vue'
|
||||
import Button from '~/components/ui/Button.vue'
|
||||
import Tabs from '~/components/ui/Tabs.vue'
|
||||
|
@ -24,11 +27,8 @@ import OptionsButton from '~/components/ui/button/Options.vue'
|
|||
import Popover from '~/components/ui/Popover.vue'
|
||||
import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
|
||||
import Layout from '~/components/ui/Layout.vue'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
import Spacer from '~/components/ui/Spacer.vue'
|
||||
|
||||
import useErrorHandler from '~/composables/useErrorHandler'
|
||||
import useReport from '~/composables/moderation/useReport'
|
||||
import Modal from '~/components/ui/Modal.vue'
|
||||
|
||||
interface Events {
|
||||
(e: 'deleted'): void
|
||||
|
@ -347,13 +347,12 @@ const updateSubscriptionCount = (delta: number) => {
|
|||
@unsubscribed="updateSubscriptionCount(-1)"
|
||||
/>
|
||||
|
||||
<semantic-modal
|
||||
<Modal
|
||||
:title="t('views.channels.DetailBase.modal.embed.header')"
|
||||
v-if="totalTracks > 0"
|
||||
v-model:show="showEmbedModal"
|
||||
v-model="showEmbedModal"
|
||||
:cancel="t('views.channels.DetailBase.button.cancel')"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('views.channels.DetailBase.modal.embed.header') }}
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<div class="description">
|
||||
<embed-wizard
|
||||
|
@ -362,28 +361,19 @@ const updateSubscriptionCount = (delta: number) => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<template #actions>
|
||||
<button class="ui basic deny button">
|
||||
{{ t('views.channels.DetailBase.button.cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
<semantic-modal
|
||||
</template>
|
||||
</Modal>
|
||||
<Modal
|
||||
:title="t(`views.channels.DetailBase.header.${
|
||||
object.artist?.content_category === 'podcast' ? 'podcastChannel' : 'artistChannel'
|
||||
}`)"
|
||||
v-if="isOwner"
|
||||
v-model:show="showEditModal"
|
||||
v-model="showEditModal"
|
||||
>
|
||||
<h4 class="header">
|
||||
<span
|
||||
v-if="object.artist?.content_category === 'podcast'"
|
||||
>
|
||||
{{ t('views.channels.DetailBase.header.podcastChannel') }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
>
|
||||
{{ t('views.channels.DetailBase.header.artistChannel') }}
|
||||
</span>
|
||||
</h4>
|
||||
<div class="scrolling content">
|
||||
<channel-form
|
||||
ref="editForm"
|
||||
|
@ -394,31 +384,29 @@ const updateSubscriptionCount = (delta: number) => {
|
|||
/>
|
||||
<div class="ui hidden divider" />
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui left floated basic deny button">
|
||||
{{ t('views.channels.DetailBase.button.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
:class="['ui', 'primary', 'confirm', {loading: edit.loading}, 'button']"
|
||||
<template #actions>
|
||||
<Button
|
||||
primary
|
||||
autofocus
|
||||
:isLoading="edit.loading"
|
||||
:disabled="!edit.submittable"
|
||||
@click.stop="editForm?.submit"
|
||||
>
|
||||
{{ t('views.channels.DetailBase.button.updateChannel') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
<Button
|
||||
secondary
|
||||
icon="bi-rss"
|
||||
@click.stop.prevent="showSubscribeModal = true"
|
||||
/>
|
||||
<semantic-modal
|
||||
<Modal
|
||||
:title="t('views.channels.DetailBase.modal.subscribe.header')"
|
||||
v-model:show="showSubscribeModal"
|
||||
class="tiny"
|
||||
:cancel="t('views.channels.DetailBase.button.cancel')"
|
||||
>
|
||||
<h4 class="header">
|
||||
{{ t('views.channels.DetailBase.modal.subscribe.header') }}
|
||||
</h4>
|
||||
<div class="scrollable content">
|
||||
<div class="description">
|
||||
<template v-if="store.state.auth.authenticated">
|
||||
|
@ -457,12 +445,7 @@ const updateSubscriptionCount = (delta: number) => {
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="ui basic deny button">
|
||||
{{ t('views.channels.DetailBase.button.cancel') }}
|
||||
</button>
|
||||
</div>
|
||||
</semantic-modal>
|
||||
</Modal>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
|
Loading…
Reference in New Issue