refactor(front): library upload pages
This commit is contained in:
		
							parent
							
								
									cb9ba7d153
								
							
						
					
					
						commit
						f754b397a9
					
				| 
						 | 
				
			
			@ -1,11 +1,23 @@
 | 
			
		|||
<script setup lang="ts">
 | 
			
		||||
import { useI18n } from 'vue-i18n'
 | 
			
		||||
import { computed } from 'vue'
 | 
			
		||||
import { computed, ref } from 'vue'
 | 
			
		||||
import { useRoute } from 'vue-router'
 | 
			
		||||
 | 
			
		||||
import Nav from '~/components/ui/Nav.vue'
 | 
			
		||||
import Spacer from '~/components/ui/Spacer.vue'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n()
 | 
			
		||||
const route = useRoute()
 | 
			
		||||
 | 
			
		||||
const tabs = ref([{
 | 
			
		||||
  title: t('views.content.Base.link.libraries'),
 | 
			
		||||
  to: { name: 'content.libraries.index'}
 | 
			
		||||
},
 | 
			
		||||
{
 | 
			
		||||
  title: t('views.content.Base.link.tracks'),
 | 
			
		||||
  to: { name: 'content.libraries.files' },
 | 
			
		||||
}])
 | 
			
		||||
 | 
			
		||||
const labels = computed(() => ({
 | 
			
		||||
  secondaryMenu: t('views.content.Base.menu.secondary'),
 | 
			
		||||
  title: t('views.content.Base.title')
 | 
			
		||||
| 
						 | 
				
			
			@ -17,24 +29,11 @@ const labels = computed(() => ({
 | 
			
		|||
    v-title="labels.title"
 | 
			
		||||
    class="main"
 | 
			
		||||
  >
 | 
			
		||||
    <nav
 | 
			
		||||
      class="ui secondary pointing menu"
 | 
			
		||||
      role="navigation"
 | 
			
		||||
    <Nav
 | 
			
		||||
      v-model="tabs"
 | 
			
		||||
      :aria-label="labels.secondaryMenu"
 | 
			
		||||
    >
 | 
			
		||||
      <router-link
 | 
			
		||||
        class="ui item"
 | 
			
		||||
        :to="{name: 'content.libraries.index'}"
 | 
			
		||||
      >
 | 
			
		||||
        {{ t('views.content.Base.link.libraries') }}
 | 
			
		||||
      </router-link>
 | 
			
		||||
      <router-link
 | 
			
		||||
        class="ui item"
 | 
			
		||||
        :to="{name: 'content.libraries.files'}"
 | 
			
		||||
      >
 | 
			
		||||
        {{ t('views.content.Base.link.tracks') }}
 | 
			
		||||
      </router-link>
 | 
			
		||||
    </nav>
 | 
			
		||||
    />
 | 
			
		||||
    <Spacer />
 | 
			
		||||
    <router-view :key="route.fullPath" />
 | 
			
		||||
  </main>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,7 +9,5 @@ defineProps<Props>()
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <section class="ui vertical aligned stripe segment">
 | 
			
		||||
    <library-files-table :default-query="query" />
 | 
			
		||||
  </section>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -227,6 +227,7 @@ const getImportStatusChoice = (importStatus: ImportStatus) => {
 | 
			
		|||
      </Layout>
 | 
			
		||||
    </Layout>
 | 
			
		||||
  </Layout>
 | 
			
		||||
  <Spacer />
 | 
			
		||||
  <import-status-modal
 | 
			
		||||
    v-if="detailedUpload"
 | 
			
		||||
    v-model:show="showUploadDetailModal"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,20 +2,29 @@
 | 
			
		|||
import type { Library } from '~/types'
 | 
			
		||||
import { useRouter } from 'vue-router'
 | 
			
		||||
import { ref } from 'vue'
 | 
			
		||||
import { useStore } from '~/store'
 | 
			
		||||
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
 | 
			
		||||
import LibraryForm from './Form.vue'
 | 
			
		||||
import LibraryCard from './Card.vue'
 | 
			
		||||
import LibraryCard from '~/views/content/remote/Card.vue'
 | 
			
		||||
import Quota from './Quota.vue'
 | 
			
		||||
 | 
			
		||||
import useErrorHandler from '~/composables/useErrorHandler'
 | 
			
		||||
 | 
			
		||||
import Loader from '~/components/ui/Loader.vue'
 | 
			
		||||
import Section from '~/components/ui/Section.vue'
 | 
			
		||||
import Alert from '~/components/ui/Alert.vue'
 | 
			
		||||
import Button from '~/components/ui/Button.vue'
 | 
			
		||||
import Spacer from '~/components/ui/Spacer.vue'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import { useI18n } from 'vue-i18n'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n()
 | 
			
		||||
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
const store = useStore()
 | 
			
		||||
 | 
			
		||||
const libraries = ref([] as Library[])
 | 
			
		||||
const isLoading = ref(false)
 | 
			
		||||
| 
						 | 
				
			
			@ -44,61 +53,42 @@ const libraryCreated = (library: Library) => {
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <section class="ui vertical aligned stripe segment">
 | 
			
		||||
    <!-- TODO: Modernise to new Ui -->
 | 
			
		||||
    <div
 | 
			
		||||
      v-if="isLoading"
 | 
			
		||||
      :class="['ui', {'active': isLoading}, 'inverted', 'dimmer']"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="ui text loader">
 | 
			
		||||
        {{ t('views.content.libraries.Home.loading.libraries') }}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div
 | 
			
		||||
    <Loader v-if="isLoading" />
 | 
			
		||||
    <Section
 | 
			
		||||
      v-else
 | 
			
		||||
      class="ui text container"
 | 
			
		||||
      :h1="t('views.content.libraries.Home.header.libraries')"
 | 
			
		||||
      page-header
 | 
			
		||||
    >
 | 
			
		||||
      <Alert
 | 
			
		||||
        v-if="libraries.length == 0"
 | 
			
		||||
        yellow
 | 
			
		||||
      >
 | 
			
		||||
      <h1 class="ui header">
 | 
			
		||||
        {{ t('views.content.libraries.Home.header.libraries') }}
 | 
			
		||||
      </h1>
 | 
			
		||||
 | 
			
		||||
      <p v-if="libraries.length == 0">
 | 
			
		||||
        {{ t('views.content.libraries.Home.empty.noLibrary') }}
 | 
			
		||||
      </p>
 | 
			
		||||
      <a
 | 
			
		||||
        <Button
 | 
			
		||||
          :aria-expanded="!hiddenForm"
 | 
			
		||||
        href=""
 | 
			
		||||
          :icon="hiddenForm ? 'bi-plus' : 'bi-minus'"
 | 
			
		||||
          @click.prevent="hiddenForm = !hiddenForm"
 | 
			
		||||
        >
 | 
			
		||||
        <i
 | 
			
		||||
          v-if="hiddenForm"
 | 
			
		||||
          class="plus icon"
 | 
			
		||||
        />
 | 
			
		||||
        <i
 | 
			
		||||
          v-else
 | 
			
		||||
          class="minus icon"
 | 
			
		||||
        />
 | 
			
		||||
          {{ t('views.content.libraries.Home.link.createLibrary') }}
 | 
			
		||||
      </a>
 | 
			
		||||
        </Button>
 | 
			
		||||
      </Alert>
 | 
			
		||||
      <library-form
 | 
			
		||||
        v-if="!hiddenForm"
 | 
			
		||||
        @created="libraryCreated"
 | 
			
		||||
      />
 | 
			
		||||
      <div class="ui hidden divider" />
 | 
			
		||||
    </Section>
 | 
			
		||||
    <quota />
 | 
			
		||||
      <div class="ui hidden divider" />
 | 
			
		||||
      <div
 | 
			
		||||
    <Spacer />
 | 
			
		||||
    <Section
 | 
			
		||||
      v-if="libraries.length > 0"
 | 
			
		||||
        class="ui two column grid"
 | 
			
		||||
    >
 | 
			
		||||
        <div
 | 
			
		||||
      <library-card
 | 
			
		||||
        v-for="library in libraries"
 | 
			
		||||
        :key="library.uuid"
 | 
			
		||||
          class="column"
 | 
			
		||||
        >
 | 
			
		||||
          <library-card :library="library" />
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </section>
 | 
			
		||||
        :display-scan="false"
 | 
			
		||||
        :display-follow="store.state.auth.authenticated && library.actor.full_username != store.state.auth.fullUsername"
 | 
			
		||||
        :initial-library="library"
 | 
			
		||||
        :display-copy-fid="true"
 | 
			
		||||
      />
 | 
			
		||||
    </Section>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,12 @@ import { useI18n } from 'vue-i18n'
 | 
			
		|||
 | 
			
		||||
import DangerousButton from '~/components/common/DangerousButton.vue'
 | 
			
		||||
 | 
			
		||||
import Alert from '~/components/ui/Alert.vue'
 | 
			
		||||
import Section from '~/components/ui/Section.vue'
 | 
			
		||||
import Layout from '~/components/ui/Layout.vue'
 | 
			
		||||
import Link from '~/components/ui/Link.vue'
 | 
			
		||||
import Spacer from '~/components/ui/Spacer.vue'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n()
 | 
			
		||||
 | 
			
		||||
const quotaStatus = ref()
 | 
			
		||||
| 
						 | 
				
			
			@ -56,10 +62,9 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="ui segment">
 | 
			
		||||
    <h3 class="ui header">
 | 
			
		||||
      {{ t('views.content.libraries.Quota.header.currentUsage') }}
 | 
			
		||||
    </h3>
 | 
			
		||||
  <Section
 | 
			
		||||
    :h3="t('views.content.libraries.Quota.header.currentUsage')"
 | 
			
		||||
  >
 | 
			
		||||
    <div
 | 
			
		||||
      v-if="isLoading"
 | 
			
		||||
      :class="['ui', {'active': isLoading}, 'inverted', 'dimmer']"
 | 
			
		||||
| 
						 | 
				
			
			@ -68,9 +73,11 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
        {{ t('views.content.libraries.Quota.loading.currentUsage') }}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div
 | 
			
		||||
      :class="['ui', {'success': progress < 60}, {'warning': progress >= 60 && progress < 96}, {'error': progress >= 95}, 'progress']"
 | 
			
		||||
    <Alert
 | 
			
		||||
      data-percent="progress"
 | 
			
		||||
      :green="progress < 60"
 | 
			
		||||
      :yellow="progress >= 60 && progress < 96"
 | 
			
		||||
      :red="progress >= 95"
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
        class="bar"
 | 
			
		||||
| 
						 | 
				
			
			@ -86,17 +93,16 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
      >
 | 
			
		||||
        {{ t('views.content.libraries.Quota.label.currentUsage', {max: humanSize(quotaStatus.max * 1000 * 1000), currentAmount: humanSize(quotaStatus.current * 1000 * 1000)}) }}
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="ui hidden divider" />
 | 
			
		||||
    <div
 | 
			
		||||
    </Alert>
 | 
			
		||||
    <Layout
 | 
			
		||||
      v-if="quotaStatus"
 | 
			
		||||
      class="ui stackable three column grid"
 | 
			
		||||
      flex
 | 
			
		||||
    >
 | 
			
		||||
      <div
 | 
			
		||||
      <Alert
 | 
			
		||||
        v-if="quotaStatus.pending > 0"
 | 
			
		||||
        class="column"
 | 
			
		||||
        yellow
 | 
			
		||||
      >
 | 
			
		||||
        <div class="ui tiny warning statistic">
 | 
			
		||||
        <div class="statistic">
 | 
			
		||||
          <div class="value">
 | 
			
		||||
            {{ humanSize(quotaStatus.pending * 1000 * 1000) }}
 | 
			
		||||
          </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -104,13 +110,16 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
            {{ t('views.content.libraries.Quota.label.pending') }}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <router-link
 | 
			
		||||
            class="ui basic primary tiny button"
 | 
			
		||||
        <Spacer />
 | 
			
		||||
        <Layout flex>
 | 
			
		||||
          <Link
 | 
			
		||||
            primary
 | 
			
		||||
            solid
 | 
			
		||||
            low-height
 | 
			
		||||
            :to="{name: 'content.libraries.files', query: {q: compileTokens([{field: 'status', value: 'pending'}])}}"
 | 
			
		||||
          >
 | 
			
		||||
            {{ t('views.content.libraries.Quota.link.viewFiles') }}
 | 
			
		||||
          </router-link>
 | 
			
		||||
          </Link>
 | 
			
		||||
 | 
			
		||||
          <dangerous-button
 | 
			
		||||
            low-height
 | 
			
		||||
| 
						 | 
				
			
			@ -125,11 +134,11 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
              {{ t('views.content.libraries.Quota.button.purge') }}
 | 
			
		||||
            </template>
 | 
			
		||||
          </dangerous-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        </Layout>
 | 
			
		||||
      </Alert>
 | 
			
		||||
      <Alert
 | 
			
		||||
        v-if="quotaStatus.skipped > 0"
 | 
			
		||||
        class="column"
 | 
			
		||||
        yellow
 | 
			
		||||
      >
 | 
			
		||||
        <div class="ui tiny statistic">
 | 
			
		||||
          <div class="value">
 | 
			
		||||
| 
						 | 
				
			
			@ -139,13 +148,16 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
            {{ t('views.content.libraries.Quota.label.skipped') }}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <router-link
 | 
			
		||||
            class="ui basic primary tiny button"
 | 
			
		||||
        <Spacer />
 | 
			
		||||
        <Layout flex>
 | 
			
		||||
          <Link
 | 
			
		||||
            primary
 | 
			
		||||
            solid
 | 
			
		||||
            low-height
 | 
			
		||||
            :to="{name: 'content.libraries.files', query: {q: compileTokens([{field: 'status', value: 'skipped'}])}}"
 | 
			
		||||
          >
 | 
			
		||||
            {{ t('views.content.libraries.Quota.link.viewFiles') }}
 | 
			
		||||
          </router-link>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <dangerous-button
 | 
			
		||||
            low-height
 | 
			
		||||
            :action="purgeSkippedFiles"
 | 
			
		||||
| 
						 | 
				
			
			@ -159,11 +171,11 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
              {{ t('views.content.libraries.Quota.button.purge') }}
 | 
			
		||||
            </template>
 | 
			
		||||
          </dangerous-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        </Layout>
 | 
			
		||||
      </Alert>
 | 
			
		||||
      <Alert
 | 
			
		||||
        v-if="quotaStatus.errored > 0"
 | 
			
		||||
        class="column"
 | 
			
		||||
        red
 | 
			
		||||
      >
 | 
			
		||||
        <div class="ui tiny danger statistic">
 | 
			
		||||
          <div class="value">
 | 
			
		||||
| 
						 | 
				
			
			@ -173,13 +185,16 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
            {{ t('views.content.libraries.Quota.label.errored') }}
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div>
 | 
			
		||||
          <router-link
 | 
			
		||||
            class="ui basic primary tiny button"
 | 
			
		||||
        <Spacer />
 | 
			
		||||
        <Layout flex>
 | 
			
		||||
          <Link
 | 
			
		||||
            primary
 | 
			
		||||
            solid
 | 
			
		||||
            low-height
 | 
			
		||||
            :to="{name: 'content.libraries.files', query: {q: compileTokens([{field: 'status', value: 'errored'}])}}"
 | 
			
		||||
          >
 | 
			
		||||
            {{ t('views.content.libraries.Quota.link.viewFiles') }}
 | 
			
		||||
          </router-link>
 | 
			
		||||
          </Link>
 | 
			
		||||
          <dangerous-button
 | 
			
		||||
            low-height
 | 
			
		||||
            :action="purgeErroredFiles"
 | 
			
		||||
| 
						 | 
				
			
			@ -193,8 +208,8 @@ const purgeErroredFiles = () => purge('errored')
 | 
			
		|||
              {{ t('views.content.libraries.Quota.button.purge') }}
 | 
			
		||||
            </template>
 | 
			
		||||
          </dangerous-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
        </Layout>
 | 
			
		||||
      </Alert>
 | 
			
		||||
    </Layout>
 | 
			
		||||
  </Section>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue