chore(front): refactor admin manage library pages

This commit is contained in:
ArneBo 2025-03-18 13:22:54 +01:00
parent 551af184c0
commit f9f53c32db
10 changed files with 980 additions and 1011 deletions

View File

@ -10,7 +10,6 @@ import { useI18n } from 'vue-i18n'
import axios from 'axios' import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
@ -18,6 +17,12 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -88,22 +93,24 @@ const labels = computed(() => ({
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="channel-search">{{ t('components.manage.ChannelsTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="channel-search" id="channel-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.ChannelsTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="channel-category">{{ t('components.manage.ChannelsTable.label.category') }}</label> <label for="channel-category">{{ t('components.manage.ChannelsTable.label.category') }}</label>
<select <select
@ -157,15 +164,10 @@ const labels = computed(() => ({
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -246,19 +248,15 @@ const labels = computed(() => ({
</td> </td>
</template> </template>
</action-table> </action-table>
</div>
<div> <div>
<pagination <Pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.ChannelsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.ChannelsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div> </div>
</div>
</template> </template>

View File

@ -10,7 +10,6 @@ import { useI18n } from 'vue-i18n'
import axios from 'axios' import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
@ -18,6 +17,12 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -100,22 +105,24 @@ const labels = computed(() => ({
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="albums-search">{{ t('components.manage.library.AlbumsTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="albums-search" id="albums-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.AlbumsTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="albums-ordering">{{ t('components.manage.library.AlbumsTable.ordering.label') }}</label> <label for="albums-ordering">{{ t('components.manage.library.AlbumsTable.ordering.label') }}</label>
<select <select
@ -146,15 +153,10 @@ const labels = computed(() => ({
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -242,19 +244,13 @@ const labels = computed(() => ({
</td> </td>
</template> </template>
</action-table> </action-table>
</div> <Pagination
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.AlbumsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.AlbumsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -10,7 +10,6 @@ import { useI18n } from 'vue-i18n'
import axios from 'axios' import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
@ -18,6 +17,12 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -104,22 +109,24 @@ const getUrl = (artist: { channel?: number; id: number }) => {
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="artists-serarch">{{ t('components.manage.library.ArtistsTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="artists-search" id="artists-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.ArtistsTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="artists-category">{{ t('components.manage.library.ArtistsTable.label.category') }}</label> <label for="artists-category">{{ t('components.manage.library.ArtistsTable.label.category') }}</label>
<select <select
@ -173,15 +180,10 @@ const getUrl = (artist: { channel?: number; id: number }) => {
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -248,19 +250,13 @@ const getUrl = (artist: { channel?: number; id: number }) => {
</td> </td>
</template> </template>
</action-table> </action-table>
</div> <Pagination
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.ArtistsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.ArtistsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -12,7 +12,6 @@ import { uniq } from 'lodash-es'
import axios from 'axios' import axios from 'axios'
import Pagination from '~/components/vui/Pagination.vue'
import EditCard from '~/components/library/EditCard.vue' import EditCard from '~/components/library/EditCard.vue'
import useEditConfigs from '~/composables/moderation/useEditConfigs' import useEditConfigs from '~/composables/moderation/useEditConfigs'
@ -22,6 +21,13 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Section from '~/components/ui/Section.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -159,28 +165,36 @@ const getCurrentState = (target?: StateTarget): ReviewState => {
</script> </script>
<template> <template>
<div class="ui text container">
<slot /> <slot />
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui field"> <div class="ui field">
<label for="search-edits">{{ t('components.manage.library.EditsCardList.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
search
id="search-edits" id="search-edits"
ref="search" ref="search"
name="search" name="search"
type="text" v-model="query"
:value="query" :label="t('components.manage.library.EditsCardList.label.search')"
autofocus
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<div class="field"> <Spacer :size="16" />
<label for="edit-status">{{ t('components.manage.library.EditsCardList.label.status') }}</label> <Layout flex>
<Spacer grow />
<Layout
stack
no-gap
label
for="edit-status"
>
<span class="label">{{ t('components.manage.library.EditsCardList.label.status') }}</span>
<select <select
id="edit-status" id="edit-status"
class="ui dropdown" class="dropdown"
:value="getTokenValue('is_approved', '')" :value="getTokenValue('is_approved', '')"
@change="addSearchToken('is_approved', ($event.target as HTMLSelectElement).value)" @change="addSearchToken('is_approved', ($event.target as HTMLSelectElement).value)"
> >
@ -197,7 +211,7 @@ const getCurrentState = (target?: StateTarget): ReviewState => {
{{ t('components.manage.library.EditsCardList.option.rejected') }} {{ t('components.manage.library.EditsCardList.option.rejected') }}
</option> </option>
</select> </select>
</div> </Layout>
<div class="field"> <div class="field">
<label for="edit-ordering">{{ t('components.manage.library.EditsCardList.ordering.label') }}</label> <label for="edit-ordering">{{ t('components.manage.library.EditsCardList.ordering.label') }}</label>
<select <select
@ -229,16 +243,14 @@ const getCurrentState = (target?: StateTarget): ReviewState => {
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div <Section
v-if="isLoading" v-else-if="(result?.count ?? 0) > 0"
class="ui active inverted dimmer" small-items
> >
<div class="ui loader" />
</div>
<div v-else-if="(result?.count ?? 0) > 0">
<edit-card <edit-card
v-for="obj in result?.results ?? []" v-for="obj in result?.results ?? []"
:key="obj.uuid" :key="obj.uuid"
@ -247,26 +259,19 @@ const getCurrentState = (target?: StateTarget): ReviewState => {
@deleted="handle('delete', obj.uuid, false)" @deleted="handle('delete', obj.uuid, false)"
@approved="handle('approved', obj.uuid, $event)" @approved="handle('approved', obj.uuid, $event)"
/> />
</div> </Section>
<empty-state <empty-state
v-else v-else
:refresh="true" :refresh="true"
@refresh="fetchData()" @refresh="fetchData()"
/> />
</div> <Pagination
<div class="ui hidden divider" />
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.EditsCardList.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.EditsCardList.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -10,7 +10,6 @@ import { useI18n } from 'vue-i18n'
import axios from 'axios' import axios from 'axios'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
@ -18,6 +17,12 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -103,22 +108,24 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="libraries-search">{{ t('components.manage.library.LibrariesTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="libraries-search" id="libraries-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.LibrariesTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="libraries-visibility">{{ t('components.manage.library.LibrariesTable.label.visibility') }}</label> <label for="libraries-visibility">{{ t('components.manage.library.LibrariesTable.label.visibility') }}</label>
<select <select
@ -172,15 +179,10 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -272,19 +274,13 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</td> </td>
</template> </template>
</action-table> </action-table>
</div> <Pagination
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.LibrariesTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.LibrariesTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -12,7 +12,6 @@ import axios from 'axios'
import ImportStatusModal from '~/components/library/ImportStatusModal.vue' import ImportStatusModal from '~/components/library/ImportStatusModal.vue'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
@ -20,6 +19,12 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -105,22 +110,24 @@ const showUploadDetailModal = ref(false)
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="tags-search">{{ t('components.manage.library.TagsTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="tags-search" id="tags-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.TagsTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="tags-ordering">{{ t('components.manage.library.TagsTable.ordering.label') }}</label> <label for="tags-ordering">{{ t('components.manage.library.TagsTable.ordering.label') }}</label>
<select <select
@ -152,6 +159,7 @@ const showUploadDetailModal = ref(false)
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<import-status-modal <import-status-modal
@ -159,13 +167,7 @@ const showUploadDetailModal = ref(false)
v-model:show="showUploadDetailModal" v-model:show="showUploadDetailModal"
:upload="detailedUpload" :upload="detailedUpload"
/> />
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -214,19 +216,13 @@ const showUploadDetailModal = ref(false)
</td> </td>
</template> </template>
</action-table> </action-table>
</div> <Pagination
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.TagsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.TagsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -11,13 +11,18 @@ import axios from 'axios'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useOrdering from '~/composables/navigation/useOrdering' import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -97,22 +102,24 @@ const labels = computed(() => ({
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="tracks-search">{{ t('components.manage.library.TracksTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="tracks-search" id="tracks-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.TracksTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="tracks-ordering">{{ t('components.manage.library.TracksTable.ordering.label') }}</label> <label for="tracks-ordering">{{ t('components.manage.library.TracksTable.ordering.label') }}</label>
<select <select
@ -144,15 +151,10 @@ const labels = computed(() => ({
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -252,19 +254,15 @@ const labels = computed(() => ({
</td> </td>
</template> </template>
</action-table> </action-table>
</div>
<div> <div>
<pagination <Pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.TracksTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.TracksTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div> </div>
</div>
</template> </template>

View File

@ -13,8 +13,6 @@ import axios from 'axios'
import ImportStatusModal from '~/components/library/ImportStatusModal.vue' import ImportStatusModal from '~/components/library/ImportStatusModal.vue'
import ActionTable from '~/components/common/ActionTable.vue' import ActionTable from '~/components/common/ActionTable.vue'
import Pagination from '~/components/vui/Pagination.vue'
import Button from '~/components/ui/Button.vue'
import useSmartSearch from '~/composables/navigation/useSmartSearch' import useSmartSearch from '~/composables/navigation/useSmartSearch'
import useSharedLabels from '~/composables/locale/useSharedLabels' import useSharedLabels from '~/composables/locale/useSharedLabels'
@ -22,6 +20,13 @@ import useOrdering from '~/composables/navigation/useOrdering'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import usePage from '~/composables/navigation/usePage' import usePage from '~/composables/navigation/usePage'
import Layout from '~/components/ui/Layout.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Button from '~/components/ui/Button.vue'
import Input from '~/components/ui/Input.vue'
import Loader from '~/components/ui/Loader.vue'
import Pagination from '~/components/ui/Pagination.vue'
interface Props extends SmartSearchProps, OrderingProps { interface Props extends SmartSearchProps, OrderingProps {
filters?: object filters?: object
@ -120,22 +125,24 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</script> </script>
<template> <template>
<div>
<div class="ui inline form"> <div class="ui inline form">
<div class="fields"> <div class="fields">
<div class="ui six wide field"> <div class="ui six wide field">
<label for="uploads-search">{{ t('components.manage.library.UploadsTable.label.search') }}</label>
<form @submit.prevent="query = search.value"> <form @submit.prevent="query = search.value">
<input <Input
id="uploads-search" id="uploads-search"
ref="search" ref="search"
name="search" name="search"
type="text" search
:value="query" :label="t('components.manage.library.UploadsTable.label.search')"
v-model="query"
:placeholder="labels.searchPlaceholder" :placeholder="labels.searchPlaceholder"
> />
</form> </form>
</div> </div>
<Spacer :size="16" />
<Layout flex>
<Spacer grow />
<div class="field"> <div class="field">
<label for="uploads-visibility">{{ t('components.manage.library.UploadsTable.label.visibility') }}</label> <label for="uploads-visibility">{{ t('components.manage.library.UploadsTable.label.visibility') }}</label>
<select <select
@ -214,6 +221,7 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</option> </option>
</select> </select>
</div> </div>
</Layout>
</div> </div>
</div> </div>
<!-- TODO (wvffle): Check if :upload shouldn't be v-model:upload --> <!-- TODO (wvffle): Check if :upload shouldn't be v-model:upload -->
@ -222,13 +230,7 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
v-model:show="showUploadDetailModal" v-model:show="showUploadDetailModal"
:upload="detailedUpload" :upload="detailedUpload"
/> />
<div class="dimmable"> <Loader v-if="isLoading" />
<div
v-if="isLoading"
class="ui active inverted dimmer"
>
<div class="ui loader" />
</div>
<action-table <action-table
v-if="result" v-if="result"
:objects-data="result" :objects-data="result"
@ -362,19 +364,13 @@ const getPrivacyLevelChoice = (privacyLevel: PrivacyLevel) => {
</td> </td>
</template> </template>
</action-table> </action-table>
</div> <Pagination
<div>
<pagination
v-if="result && result.count > paginateBy" v-if="result && result.count > paginateBy"
v-model:current="page" v-model:page="page"
:compact="true" :pages="Math.ceil(result.count / paginateBy)"
:paginate-by="paginateBy"
:total="result.count"
/> />
<span v-if="result && result.results.length > 0"> <span v-if="result && result.results.length > 0">
{{ t('components.manage.library.UploadsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }} {{ t('components.manage.library.UploadsTable.pagination.results', {start: ((page-1) * paginateBy) + 1, end: ((page-1) * paginateBy) + result.results.length, total: result.count}) }}
</span> </span>
</div>
</div>
</template> </template>

View File

@ -1,73 +1,62 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'
import Layout from '~/components/ui/Layout.vue'
import Tabs from '~/components/ui/Tabs.vue'
import Tab from '~/components/ui/Tab.vue'
const { t } = useI18n() const { t } = useI18n()
const labels = computed(() => ({ const labels = computed(() => ({
title: t('views.admin.library.Base.title'), title: t('views.admin.library.Base.title'),
secondaryMenu: t('views.admin.library.Base.menu.secondary') secondaryMenu: t('views.admin.library.Base.menu.secondary')
})) }))
const route = useRoute()
</script> </script>
<template> <template>
<div <Layout
v-title="labels.title" v-title="labels.title"
class="main page-admin-library" main
stack
class="page-admin-library"
> >
<nav <Tabs>
class="ui secondary pointing menu" <Tab
role="navigation" :title="t('views.admin.library.Base.link.edits')"
:aria-label="labels.secondaryMenu"
>
<router-link
class="ui item"
:to="{name: 'manage.library.edits'}" :to="{name: 'manage.library.edits'}"
> />
{{ t('views.admin.library.Base.link.edits') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.channels')"
<router-link
class="ui item"
:to="{name: 'manage.channels'}" :to="{name: 'manage.channels'}"
> />
{{ t('views.admin.library.Base.link.channels') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.artists')"
<router-link
class="ui item"
:to="{name: 'manage.library.artists'}" :to="{name: 'manage.library.artists'}"
> />
{{ t('views.admin.library.Base.link.artists') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.albums')"
<router-link
class="ui item"
:to="{name: 'manage.library.albums'}" :to="{name: 'manage.library.albums'}"
> />
{{ t('views.admin.library.Base.link.albums') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.tracks')"
<router-link
class="ui item"
:to="{name: 'manage.library.tracks'}" :to="{name: 'manage.library.tracks'}"
> />
{{ t('views.admin.library.Base.link.tracks') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.libraries')"
<router-link
class="ui item"
:to="{name: 'manage.library.libraries'}" :to="{name: 'manage.library.libraries'}"
> />
{{ t('views.admin.library.Base.link.libraries') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.uploads')"
<router-link
class="ui item"
:to="{name: 'manage.library.uploads'}" :to="{name: 'manage.library.uploads'}"
> />
{{ t('views.admin.library.Base.link.uploads') }} <Tab
</router-link> :title="t('views.admin.library.Base.link.tags')"
<router-link
class="ui item"
:to="{name: 'manage.library.tags'}" :to="{name: 'manage.library.tags'}"
> />
{{ t('views.admin.library.Base.link.tags') }} </Tabs>
</router-link> <router-view :key="route.fullPath" />
</nav> </Layout>
<router-view :key="$route.fullPath" />
</div>
</template> </template>

View File

@ -4,6 +4,8 @@ import { computed } from 'vue'
import EditsCardList from '~/components/manage/library/EditsCardList.vue' import EditsCardList from '~/components/manage/library/EditsCardList.vue'
import Header from '~/components/ui/Header.vue'
interface Props { interface Props {
defaultQuery?: string defaultQuery?: string
} }
@ -19,16 +21,13 @@ const labels = computed(() => ({
</script> </script>
<template> <template>
<main v-title="labels.title"> <Header
<section class="ui vertical stripe segment"> align-left
no-items
:h1="t('views.admin.library.EditsList.header.edits')"
/>
<edits-card-list <edits-card-list
:update-url="true" :update-url="true"
:default-query="defaultQuery" :default-query="defaultQuery"
> />
<h2 class="ui header">
{{ t('views.admin.library.EditsList.header.edits') }}
</h2>
</edits-card-list>
</section>
</main>
</template> </template>