forked from Ivasoft/geovisio-website
365 lines
8.9 KiB
Vue
365 lines
8.9 KiB
Vue
<template>
|
|
<main class="entry-page">
|
|
<h1 class="sequences-title">{{ $t('pages.sequences.title') }}</h1>
|
|
<ul v-if="!isLoading" class="sequence-list">
|
|
<li class="sequence-item">
|
|
<div class="sequence-header-item"></div>
|
|
<div class="sequence-header-item">
|
|
<Button
|
|
:text="$t('pages.sequences.sequence_name')"
|
|
look="link--grey"
|
|
icon="bi bi-arrow-down-up"
|
|
data-test="button-sort-title"
|
|
@trigger="sortAlpha('title')"
|
|
/>
|
|
</div>
|
|
<div class="sequence-header-item">
|
|
<Button
|
|
:text="$t('pages.sequences.sequence_photos')"
|
|
look="link--grey"
|
|
icon="bi bi-arrow-down-up"
|
|
data-test="button-sort-number"
|
|
@trigger="sortNum('num')"
|
|
/>
|
|
</div>
|
|
<div class="sequence-header-item">
|
|
<Button
|
|
:text="$t('pages.sequences.sequence_date')"
|
|
look="link--grey"
|
|
icon="bi bi-arrow-down-up"
|
|
data-test="button-sort-date"
|
|
@trigger="sortNum('date')"
|
|
/>
|
|
</div>
|
|
<div class="sequence-header-item">
|
|
<Button
|
|
:text="$t('pages.sequences.sequence_status')"
|
|
look="link--grey"
|
|
icon="bi bi-arrow-down-up"
|
|
data-test="button-sort-date"
|
|
@trigger="sortAlpha('geovisio:status')"
|
|
/>
|
|
</div>
|
|
</li>
|
|
<li
|
|
v-if="userSequences.length"
|
|
v-for="item in userSequences"
|
|
class="sequence-item"
|
|
>
|
|
<router-link
|
|
class="button-item"
|
|
:to="{
|
|
name: 'sequence',
|
|
params: { id: item.id }
|
|
}"
|
|
>
|
|
<div class="wrapper-thumb">
|
|
<img
|
|
v-if="item['stats:items'].count > 0"
|
|
:src="`${item.href}/thumb.jpg`"
|
|
lazy="loading"
|
|
alt=""
|
|
class="thumb"
|
|
/>
|
|
<div class="wrapper-thumb-hover">
|
|
<img
|
|
v-if="item['stats:items'].count > 0"
|
|
:src="`${item.href}/thumb.jpg`"
|
|
lazy="loading"
|
|
alt=""
|
|
class="thumb-hover"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<span>
|
|
{{ item.title }}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<i class="bi bi-images"></i>
|
|
<span>
|
|
{{ item['stats:items'].count }}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<span>
|
|
{{
|
|
formatDate(
|
|
item.extent.temporal.interval[0][0],
|
|
'Do MMMM YYYY HH:mm:ss'
|
|
)
|
|
}}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<span>{{ sequenceStatus(item['geovisio:status']) }}</span>
|
|
</div>
|
|
</router-link>
|
|
</li>
|
|
<div v-else class="no-sequence">
|
|
<p class="no-sequence-text">
|
|
{{ $t('pages.sequences.no_sequences_text') }}
|
|
</p>
|
|
<Link
|
|
:text="$t('general.header.upload_text')"
|
|
look="button"
|
|
:route="{ name: 'share-pictures' }"
|
|
/>
|
|
</div>
|
|
</ul>
|
|
<div v-else class="loader">
|
|
<Loader look="sm" :is-loaded="false" />
|
|
</div>
|
|
<Toast :text="toastText" :look="toastLook" @trigger="toastText = ''" />
|
|
</main>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onMounted, ref } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useSequenceStore } from '@/store/sequence'
|
|
import { storeToRefs } from 'pinia'
|
|
import axios from 'axios'
|
|
import Button from '@/components/Button.vue'
|
|
import Link from '@/components/Link.vue'
|
|
import Toast from '@/components/Toast.vue'
|
|
import Loader from '@/components/Loader.vue'
|
|
import type {
|
|
LinkInterface,
|
|
ExtentLinkInterface
|
|
} from './interfaces/MySequencesView'
|
|
import { formatDate } from '@/utils/dates'
|
|
const { t } = useI18n()
|
|
const sequenceStore = useSequenceStore()
|
|
const { toastText, toastLook } = storeToRefs(sequenceStore)
|
|
|
|
let userSequences = ref<LinkInterface[]>([])
|
|
let isSorted = ref<boolean>(false)
|
|
let isLoading = ref<boolean>(false)
|
|
|
|
function sequenceStatus(status: string): string {
|
|
if (status === 'ready') return t('pages.sequences.sequence_published')
|
|
if (status === 'waiting-for-process')
|
|
return t('pages.sequences.sequence_waiting')
|
|
return t('pages.sequences.sequence_hidden')
|
|
}
|
|
function sortAlpha<TKey extends keyof LinkInterface>(key: TKey): void {
|
|
const sorted = userSequences.value.sort(
|
|
(
|
|
a: { [K in TKey]: LinkInterface[TKey] },
|
|
b: { [K in TKey]: LinkInterface[TKey] }
|
|
) => {
|
|
if (a[key] < b[key]) return !isSorted.value ? -1 : 1
|
|
if (a[key] > b[key]) return !isSorted.value ? 1 : -1
|
|
return 0
|
|
}
|
|
)
|
|
isSorted.value = !isSorted.value
|
|
userSequences.value = sorted
|
|
}
|
|
function sortNum(type: string): void {
|
|
let aa, bb: number
|
|
const sorted = userSequences.value.sort(
|
|
(a: ExtentLinkInterface, b: ExtentLinkInterface) => {
|
|
aa = new Date(a.extent.temporal.interval[0][0]).getTime()
|
|
bb = new Date(b.extent.temporal.interval[0][0]).getTime()
|
|
if (type === 'num') {
|
|
aa = Number(a['stats:items'].count)
|
|
bb = Number(b['stats:items'].count)
|
|
}
|
|
if (aa < bb) return !isSorted.value ? -1 : 1
|
|
if (aa > bb) return !isSorted.value ? 1 : -1
|
|
return 0
|
|
}
|
|
)
|
|
isSorted.value = !isSorted.value
|
|
userSequences.value = sorted
|
|
}
|
|
onMounted(async () => {
|
|
isLoading.value = true
|
|
try {
|
|
const { data } = await axios.get('api/users/me/catalog')
|
|
const relChild = data.links.filter(
|
|
(el: LinkInterface) => el.rel === 'child'
|
|
)
|
|
userSequences.value = relChild
|
|
isLoading.value = false
|
|
} catch (err) {
|
|
isLoading.value = false
|
|
console.log(err)
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.entry-page {
|
|
padding-right: toRem(8);
|
|
padding-left: toRem(8);
|
|
padding-top: toRem(11);
|
|
min-height: calc(100vh - #{toRem(8)});
|
|
}
|
|
|
|
.sequences-title {
|
|
@include text(h1);
|
|
margin-bottom: toRem(4);
|
|
}
|
|
.sequence-list {
|
|
box-shadow: 0px 2px 30px 0px #0000000f;
|
|
border-radius: toRem(2);
|
|
padding: 0;
|
|
}
|
|
.sequence-item {
|
|
@include text(s-regular);
|
|
border: none;
|
|
display: flex;
|
|
justify-content: center;
|
|
margin: auto;
|
|
background-color: var(--blue-pale);
|
|
&:last-child {
|
|
border-bottom-right-radius: toRem(2);
|
|
border-bottom-left-radius: toRem(2);
|
|
.button-item {
|
|
border-bottom-right-radius: toRem(2);
|
|
border-bottom-left-radius: toRem(2);
|
|
}
|
|
}
|
|
&:first-child {
|
|
margin-bottom: toRem(1);
|
|
padding: toRem(1) toRem(3);
|
|
border-bottom: toRem(0.1) solid var(--grey);
|
|
border-radius: toRem(2) toRem(2) 0rem 0rem;
|
|
background-color: var(--white);
|
|
}
|
|
&:nth-child(2n) {
|
|
background-color: var(--white);
|
|
}
|
|
}
|
|
.wrapper-title {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
.wrapper-thumb {
|
|
position: relative;
|
|
}
|
|
.wrapper-thumb-hover {
|
|
display: none;
|
|
border-radius: toRem(0.3);
|
|
border: toRem(1) solid var(--grey);
|
|
position: absolute;
|
|
bottom: 0;
|
|
height: toRem(15);
|
|
z-index: 1;
|
|
}
|
|
.thumb-hover {
|
|
height: 100%;
|
|
}
|
|
.wrapper-thumb:hover {
|
|
.wrapper-thumb-hover {
|
|
display: block;
|
|
}
|
|
}
|
|
.thumb {
|
|
height: 100%;
|
|
width: 100%;
|
|
object-fit: cover;
|
|
border-radius: toRem(0.5);
|
|
position: relative;
|
|
}
|
|
.button-item {
|
|
display: flex;
|
|
align-items: center;
|
|
width: 100%;
|
|
padding: toRem(2) toRem(3);
|
|
background-color: transparent;
|
|
border: none;
|
|
text-decoration: none;
|
|
& > * {
|
|
padding: toRem(1);
|
|
text-align: initial;
|
|
width: 31%;
|
|
color: var(--black);
|
|
}
|
|
> :first-child {
|
|
color: var(--blue);
|
|
width: toRem(6);
|
|
}
|
|
& > :first-child {
|
|
padding: 0;
|
|
margin-right: toRem(2);
|
|
}
|
|
& > :nth-child(2) {
|
|
color: var(--blue);
|
|
}
|
|
&:hover {
|
|
background-color: var(--blue);
|
|
& > * {
|
|
color: var(--white);
|
|
}
|
|
}
|
|
}
|
|
.bi-images {
|
|
margin-right: toRem(0.5);
|
|
}
|
|
.sequence-header-item {
|
|
width: 31%;
|
|
&:first-child {
|
|
margin-right: toRem(2);
|
|
}
|
|
&:first-child {
|
|
width: toRem(6);
|
|
}
|
|
}
|
|
.no-sequence {
|
|
padding-top: toRem(2);
|
|
padding-bottom: toRem(4);
|
|
margin: auto;
|
|
width: fit-content;
|
|
text-align: center;
|
|
@include text(m-regular);
|
|
}
|
|
.no-sequence-text {
|
|
margin-bottom: toRem(4);
|
|
}
|
|
.loader {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 100%;
|
|
margin-top: toRem(20);
|
|
}
|
|
@media (max-width: toRem(76.8)) {
|
|
.entry-page {
|
|
padding-right: toRem(2);
|
|
padding-left: toRem(2);
|
|
padding-top: toRem(14);
|
|
min-height: calc(100vh - #{toRem(11)});
|
|
}
|
|
.button-item,
|
|
.sequence-item:first-child {
|
|
padding-right: toRem(1);
|
|
padding-left: toRem(1);
|
|
}
|
|
}
|
|
@media (max-width: toRem(50)) {
|
|
.button-item {
|
|
flex-direction: column;
|
|
align-items: center;
|
|
& > * {
|
|
text-align: center;
|
|
width: 100%;
|
|
}
|
|
.wrapper-thumb {
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
.sequence-item:first-child {
|
|
display: none;
|
|
}
|
|
.sequence-item {
|
|
border-top-right-radius: toRem(1);
|
|
border-top-left-radius: toRem(1);
|
|
}
|
|
}
|
|
</style>
|