forked from Ivasoft/geovisio-website
Feat/filters sequence list
This commit is contained in:
@@ -19,6 +19,7 @@ COPY *.json *.js *.ts *.html ./
|
||||
|
||||
# Replace env variables by placeholder for dynamic change on container start
|
||||
ENV VITE_INSTANCE_NAME=DOCKER_VITE_INSTANCE_NAME
|
||||
ENV VITE_RASTER_TILE=DOCKER_VITE_RASTER_TILE
|
||||
ENV VITE_API_URL=DOCKER_VITE_API_URL
|
||||
ENV VITE_TILES=DOCKER_VITE_TILES
|
||||
ENV VITE_MAX_ZOOM=DOCKER_VITE_MAX_ZOOM
|
||||
@@ -50,6 +51,7 @@ ENV VITE_INSTANCE_NAME="GeoVisio/Docker"
|
||||
ENV VITE_API_URL="https://panoramax.openstreetmap.fr"
|
||||
ENV VITE_TILES="https://tile-vect.openstreetmap.fr/styles/basic/style.json"
|
||||
ENV VITE_MAX_ZOOM=""
|
||||
ENV VITE_RASTER_TILE=""
|
||||
ENV VITE_ZOOM=""
|
||||
ENV VITE_CENTER=""
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ Available parameters are:
|
||||
- `VITE_MAX_ZOOM`: the max zoom to use on the map (defaults to 24).
|
||||
- `VITE_ZOOM`: the zoom to use at the initialization of the map (defaults to 0).
|
||||
- `VITE_CENTER`: the center position to use at the initialization of the map (defaults to 0).
|
||||
- `VITE_RASTER_TILE`: the raster tile. Example : `https://maplibre.org/maplibre-style-spec/sources/#raster`.
|
||||
- Settings for the work environment:
|
||||
- `NPM_CONFIG_PRODUCTION`: is it production environment (`true`, `false`)
|
||||
- `YARN_PRODUCTION`: same as below, but if you use Yarn instead of NPM
|
||||
|
||||
@@ -25,10 +25,11 @@
|
||||
"axios": "^1.2.3",
|
||||
"bootstrap": "^5.2.3",
|
||||
"bootstrap-icons": "^1.10.3",
|
||||
"geovisio": "2.3.0",
|
||||
"geovisio": "2.3.1",
|
||||
"moment": "^2.29.4",
|
||||
"pako": "^2.1.0",
|
||||
"pinia": "^2.1.4",
|
||||
"v-calendar": "^3.1.2",
|
||||
"vue": "^3.2.45",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-draggable-resizable-vue3": "^2.3.1-beta.13",
|
||||
|
||||
BIN
src/assets/images/how-to-share-map.png
Normal file
BIN
src/assets/images/how-to-share-map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
@@ -59,6 +59,10 @@ defineProps({
|
||||
color: var(--white);
|
||||
background-color: var(--black);
|
||||
}
|
||||
.button-border--black {
|
||||
background-color: var(--white);
|
||||
border: toRem(0.1) solid var(--black);
|
||||
}
|
||||
.button--blue {
|
||||
color: var(--white);
|
||||
background-color: var(--blue);
|
||||
@@ -93,10 +97,7 @@ defineProps({
|
||||
.icon {
|
||||
font-size: toRem(1.4);
|
||||
color: var(--blue);
|
||||
margin-right: 0;
|
||||
}
|
||||
.text {
|
||||
margin-left: toRem(1);
|
||||
margin-right: toRem(1);
|
||||
}
|
||||
}
|
||||
.no-text {
|
||||
@@ -104,7 +105,6 @@ defineProps({
|
||||
width: toRem(3);
|
||||
padding: 0;
|
||||
.icon {
|
||||
color: var(--black);
|
||||
font-size: toRem(1.8);
|
||||
margin-right: 0;
|
||||
}
|
||||
@@ -113,6 +113,16 @@ defineProps({
|
||||
color: var(--white);
|
||||
margin-right: 0;
|
||||
}
|
||||
.no-text-blue-dark .icon {
|
||||
color: var(--blue-dark);
|
||||
margin-right: 0;
|
||||
font-size: toRem(1.6);
|
||||
}
|
||||
.no-text-green .icon {
|
||||
color: var(--blue);
|
||||
margin-right: 0;
|
||||
font-size: toRem(1.6);
|
||||
}
|
||||
.background-white {
|
||||
background-color: var(--white);
|
||||
}
|
||||
@@ -123,6 +133,13 @@ defineProps({
|
||||
color: var(--grey-semi-dark);
|
||||
}
|
||||
}
|
||||
.link--black {
|
||||
color: var(--black);
|
||||
.icon {
|
||||
font-size: toRem(1.4);
|
||||
color: var(--black);
|
||||
}
|
||||
}
|
||||
.link--red {
|
||||
color: var(--red);
|
||||
background-color: var(--white);
|
||||
|
||||
@@ -101,7 +101,7 @@ const isDisabled = computed<boolean>(() => props.isLoading && !props.isLoaded)
|
||||
width: 100%;
|
||||
}
|
||||
.edit-button {
|
||||
background-color: var(--grey);
|
||||
background-color: var(--blue-dark);
|
||||
border-radius: 50%;
|
||||
height: toRem(3.5);
|
||||
width: toRem(3.5);
|
||||
|
||||
@@ -13,15 +13,10 @@
|
||||
<i class="bi bi-x-circle-fill"></i>
|
||||
</button>
|
||||
<div class="modal-header">
|
||||
<h5>{{ $t('pages.upload.modal_error_title') }}</h5>
|
||||
<h5>{{ title }}</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul>
|
||||
<li v-for="item in uploadErrors" class="error-item">
|
||||
<span>{{ item.name }} - </span>
|
||||
<span>{{ item.details.error }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<slot name="body"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,15 +25,13 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { Modal } from 'bootstrap'
|
||||
let bsModal = ref()
|
||||
import type { uploadErrorInterface } from '@/views/interfaces/UploadPicturesView'
|
||||
|
||||
defineProps({
|
||||
uploadErrors: {
|
||||
type: Array as PropType<uploadErrorInterface[]>,
|
||||
default: []
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
@@ -62,12 +55,6 @@ ul {
|
||||
.modal {
|
||||
background: rgba(10, 31, 105, 0.6);
|
||||
}
|
||||
.error-item {
|
||||
padding: toRem(1);
|
||||
&:nth-child(odd) {
|
||||
background-color: var(--grey);
|
||||
}
|
||||
}
|
||||
.modal-content {
|
||||
border-radius: toRem(1.5);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,16 @@ async function setupViewerMap(tiles: string): Promise<void> {
|
||||
const maxZoom = import.meta.env.VITE_MAX_ZOOM
|
||||
const zoom = import.meta.env.VITE_ZOOM
|
||||
const center = import.meta.env.VITE_CENTER
|
||||
const raster = import.meta.env.VITE_RASTER_TILE
|
||||
let paramsViewer: ViewerInterface = { map: { startWide: true } }
|
||||
if (raster && raster !== '') {
|
||||
paramsViewer = {
|
||||
map: {
|
||||
...paramsViewer.map,
|
||||
raster: JSON.parse(raster)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (center && center !== '') {
|
||||
const centerMap = center.split(',').map((el: string) => parseInt(el))
|
||||
paramsViewer = {
|
||||
|
||||
166
src/components/filters/CalendarFilter.vue
Normal file
166
src/components/filters/CalendarFilter.vue
Normal file
@@ -0,0 +1,166 @@
|
||||
<template>
|
||||
<div class="wrapper-calendar">
|
||||
<div class="inputs-wrapper">
|
||||
<div class="input-wrapper">
|
||||
<i class="bi bi-calendar-plus"></i>
|
||||
<input
|
||||
:value="
|
||||
range && range.start
|
||||
? formatDate(new Date(range.start), 'YYYY-MM-DD')
|
||||
: null
|
||||
"
|
||||
:placeholder="$t('pages.sequences.radio_date_placeholder')"
|
||||
@input="setStartValue"
|
||||
class="input"
|
||||
/>
|
||||
</div>
|
||||
<i class="bi bi-arrow-right"></i>
|
||||
<div class="input-wrapper">
|
||||
<i class="bi bi-calendar-plus"></i>
|
||||
<input
|
||||
:value="
|
||||
range && range.end
|
||||
? formatDate(new Date(range.end), 'YYYY-MM-DD')
|
||||
: null
|
||||
"
|
||||
:placeholder="$t('pages.sequences.radio_date_placeholder')"
|
||||
@input="setEndValue"
|
||||
class="input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<v-date-picker
|
||||
ref="datePicker"
|
||||
v-model="range"
|
||||
mode="date"
|
||||
:masks="{
|
||||
input: 'YYYY-MM-DD'
|
||||
}"
|
||||
is-range
|
||||
expanded
|
||||
:max-date="new Date()"
|
||||
/>
|
||||
<div class="footer-modal">
|
||||
<Button
|
||||
:text="$t('pages.sequences.filter_date_close_button')"
|
||||
look="button--transparent"
|
||||
@trigger="$emit('triggerCloseModal')"
|
||||
/>
|
||||
<Button
|
||||
v-if="range && (range.start || range.end)"
|
||||
:text="$t('pages.sequences.filter_date_reset_button')"
|
||||
icon="bi bi-trash"
|
||||
look="button--red"
|
||||
@trigger="resetCalendar"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import moment from 'moment'
|
||||
import { ref, watch } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { formatDate } from '@/utils/dates'
|
||||
import Button from '@/components/Button.vue'
|
||||
interface CalendarDateInterface {
|
||||
start: Date | string | null
|
||||
end: Date | string | null
|
||||
type: string
|
||||
}
|
||||
const emit = defineEmits(['triggerDate', 'triggerCloseModal'])
|
||||
const props = defineProps({
|
||||
type: { type: String, default: '' },
|
||||
rangeSelected: {
|
||||
type: Object as PropType<CalendarDateInterface>,
|
||||
default: { start: null, end: null, type: '' }
|
||||
}
|
||||
})
|
||||
let range = ref<CalendarDateInterface>({
|
||||
start: props.rangeSelected.start,
|
||||
end: props.rangeSelected.end,
|
||||
type: props.rangeSelected.type
|
||||
})
|
||||
const datePicker = ref()
|
||||
function checkValidityDate(dateToValid: string): boolean {
|
||||
const date = moment(dateToValid, 'YYYY-MM-DD', true)
|
||||
return date.isValid() && date.format('YYYY-MM-DD') === dateToValid
|
||||
}
|
||||
function setStartValue(event: Event): void {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
if (checkValidityDate(value)) {
|
||||
range.value.start = new Date(value)
|
||||
const startDate = `${formatDate(new Date(value), 'YYYY-MM-DD')} 12:00 AM`
|
||||
if (range && range.value.end && range.value.start) {
|
||||
range.value = {
|
||||
start: new Date(startDate),
|
||||
end: range.value.end,
|
||||
type: props.type
|
||||
}
|
||||
datePicker.value.updateValue(range.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
function setEndValue(event: Event): void {
|
||||
const value = (event.target as HTMLInputElement).value
|
||||
if (checkValidityDate(value)) {
|
||||
range.value.end = new Date(value)
|
||||
const endDate = `${formatDate(new Date(value), 'YYYY-MM-DD')} 11:59 PM`
|
||||
if (range && range.value.end && range.value.start) {
|
||||
range.value = {
|
||||
end: new Date(endDate),
|
||||
start: range.value.start,
|
||||
type: props.type
|
||||
}
|
||||
datePicker.value.updateValue(range.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
function resetCalendar(): void {
|
||||
range.value = { start: null, end: null, type: '' }
|
||||
emit('triggerDate', { start: null, end: null, type: props.type })
|
||||
}
|
||||
watch(range, (range) => {
|
||||
if (range && range.start && range.end) {
|
||||
const startDate = `${formatDate(range.start, 'YYYY-MM-DD')} 12:00 AM`
|
||||
const endDate = `${formatDate(range.end, 'YYYY-MM-DD')} 11:59 PM`
|
||||
range.type = props.type
|
||||
emit('triggerDate', { start: startDate, end: endDate, type: props.type })
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.wrapper-calendar {
|
||||
margin-bottom: toRem(2);
|
||||
}
|
||||
.inputs-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include text(xs-r-regular);
|
||||
}
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.footer-modal {
|
||||
margin-top: toRem(2);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.bi-arrow-right {
|
||||
margin-right: toRem(1);
|
||||
margin-left: toRem(1);
|
||||
}
|
||||
.bi-calendar-plus {
|
||||
position: absolute;
|
||||
left: 5%;
|
||||
top: 20%;
|
||||
}
|
||||
.input {
|
||||
padding: toRem(0.5) toRem(0.5) toRem(0.5) toRem(2.5);
|
||||
border-radius: toRem(0.3);
|
||||
border: toRem(0.1) solid var(--grey-pale);
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -76,10 +76,20 @@
|
||||
},
|
||||
"sequences": {
|
||||
"title": "My sequences",
|
||||
"filter_date_upload_title": "Filter by upload date",
|
||||
"filter_date_title": "Filter by shooting date :",
|
||||
"radio_date_placeholder": "03/01/2024",
|
||||
"radio_datetime_placeholder": "03/01/2024 12:00 AM",
|
||||
"radio_date": "date",
|
||||
"filter_date_reset_button": "Reset",
|
||||
"filter_date_close_button": "Close",
|
||||
"no_sequence_found": "No sequence found",
|
||||
"sequence_name": "Name",
|
||||
"sequence_photos": "Photos",
|
||||
"sequence_date": "Shot on",
|
||||
"sequence_creation": "Upload",
|
||||
"sequence_creation_tooltip": "Filter by uploaded date",
|
||||
"sequence_date_tooltip": "Filter by shooting date",
|
||||
"sequence_status": "Status",
|
||||
"sequence_published": "Published",
|
||||
"sequence_waiting": "Still processing",
|
||||
|
||||
@@ -76,10 +76,20 @@
|
||||
},
|
||||
"sequences": {
|
||||
"title": "Mes séquences de photos",
|
||||
"filter_date_upload_title": "Filtrer par date de versement :",
|
||||
"filter_date_title": "Filtrer par date de prise de vue :",
|
||||
"radio_date_placeholder": "2024-01-03",
|
||||
"radio_date": "date",
|
||||
"filter_date_reset_button": "Réinitialiser",
|
||||
"filter_date_close_button": "Fermer",
|
||||
"no_sequence_found": "Aucune séquence trouvée",
|
||||
"sequence_name": "Nom",
|
||||
"sequence_photos": "Photos",
|
||||
"sequence_date": "Prise de vue",
|
||||
"sequence_creation": "Versement",
|
||||
"sequence_creation_tooltip": "Filtre par date de versement",
|
||||
"sequence_date_tooltip": "Filtre par date de prise de vue",
|
||||
"reset_filter_button": "Réinitialiser tous les filtres",
|
||||
"sequence_status": "Statut",
|
||||
"sequence_published": "Publiée",
|
||||
"sequence_waiting": "En cours de publication",
|
||||
|
||||
@@ -76,10 +76,20 @@
|
||||
},
|
||||
"sequences": {
|
||||
"title": "Saját fényképsorozatok",
|
||||
"filter_date_upload_title": "Szűrés feltöltés dátuma szerint :",
|
||||
"filter_date_title": "Szűrés forgatás dátuma szerint :",
|
||||
"radio_date_placeholder": "03/01/2024",
|
||||
"radio_datetime_placeholder": "03/01/2024 12:00 AM",
|
||||
"radio_date": "dátum",
|
||||
"filter_date_reset_button": "Visszaállítás",
|
||||
"filter_date_close_button": "Bezárás",
|
||||
"no_sequence_found": "Nem található felvétel",
|
||||
"sequence_name": "Név",
|
||||
"sequence_photos": "Fényképek",
|
||||
"sequence_date": "Elkészítés ideje",
|
||||
"sequence_creation": "Feltöltés ideje",
|
||||
"sequence_creation_tooltip": "Szűrés feltöltés dátuma szerint",
|
||||
"sequence_date_tooltip": "Szűrés forgatás dátuma szerint",
|
||||
"sequence_status": "Állapot",
|
||||
"sequence_published": "Közzétéve",
|
||||
"sequence_waiting": "Feldolgozás alatt",
|
||||
|
||||
@@ -6,6 +6,8 @@ import axios from 'axios'
|
||||
import VueAxios from 'vue-axios'
|
||||
import { createMetaManager } from 'vue-meta'
|
||||
import { VueDraggableResizable } from 'vue-draggable-resizable-vue3'
|
||||
import VCalendar from 'v-calendar'
|
||||
import 'v-calendar/style.css'
|
||||
import { pinia } from './store'
|
||||
import fr from './locales/fr.json'
|
||||
import en from './locales/en.json'
|
||||
@@ -40,4 +42,5 @@ app.use(VueAxios, axios)
|
||||
app.provide('axios', app.config.globalProperties.axios)
|
||||
app.use(createMetaManager())
|
||||
app.use(VueDraggableResizable)
|
||||
app.use(VCalendar)
|
||||
app.mount('#app')
|
||||
|
||||
@@ -26,17 +26,10 @@ describe('Template', () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.uploadErrors).toEqual([])
|
||||
expect(wrapper.vm.title).toEqual('')
|
||||
})
|
||||
it('should render the props filled', async () => {
|
||||
document.body.innerHTML = '<div id="bs-modal"></div>'
|
||||
const uploadErrors = [
|
||||
{
|
||||
details: { error: 'my error' },
|
||||
message: 'my message',
|
||||
name: 'my name'
|
||||
}
|
||||
]
|
||||
const wrapper = shallowMount(Modal, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
@@ -45,13 +38,12 @@ describe('Template', () => {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
uploadErrors
|
||||
title: 'My title'
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.vm.uploadErrors).toEqual(uploadErrors)
|
||||
expect(wrapper.html()).contains('my name - ')
|
||||
expect(wrapper.html()).contains('my error')
|
||||
expect(wrapper.vm.title).toEqual('My title')
|
||||
expect(wrapper.html()).contains('My title')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('Template', () => {
|
||||
spyPicture.mockReturnValue({ data: {} })
|
||||
const sequenceTitle = `Séquence du ${formatDate(
|
||||
new Date(),
|
||||
'Do MMMM YYYY, hh:mm:ss'
|
||||
'Do MMMM YYYY, HH:mm:ss'
|
||||
)}`
|
||||
const body = new FormData()
|
||||
body.append('position', '1')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import moment from 'moment'
|
||||
import 'moment/dist/locale/fr'
|
||||
|
||||
function formatDate(date: Date, formatType: string): string {
|
||||
function formatDate(date: Date | null | string, formatType: string): string {
|
||||
const formatDate = moment(date)
|
||||
return formatDate.locale(window.navigator.language).format(formatType)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue'
|
||||
import Viewer from '@/components/Viewer.vue'
|
||||
import type ViewerType from '@/components/Viewer.vue'
|
||||
|
||||
const viewerRef = ref<unknown>(null)
|
||||
const viewerRef = ref<InstanceType<typeof ViewerType>>()
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.entry-page {
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<Button
|
||||
look="button--white background-white"
|
||||
look="button--white background-white no-text"
|
||||
:icon="
|
||||
picturesToDeleteStatus === 'hidden' ||
|
||||
imagesSelectedHaveDifferentStatus
|
||||
@@ -140,7 +140,7 @@
|
||||
/>
|
||||
<div class="button-hidde">
|
||||
<Button
|
||||
look="button--red background-white"
|
||||
look="button--red background-white no-text"
|
||||
icon="bi bi-trash"
|
||||
:tooltip="$t('pages.sequence.delete_photo_tooltip')"
|
||||
:disabled="!picturesToDelete.length"
|
||||
@@ -201,6 +201,7 @@ import InputCheckbox from '@/components/InputCheckbox.vue'
|
||||
import Loader from '@/components/Loader.vue'
|
||||
import ImageItem from '@/components/ImageItem.vue'
|
||||
import Viewer from '@/components/Viewer.vue'
|
||||
import type ViewerType from '@/components/Viewer.vue'
|
||||
import { durationCalc, formatDate } from '@/utils/dates'
|
||||
import {
|
||||
deleteACollectionItem,
|
||||
@@ -245,7 +246,7 @@ let isLoading = ref<boolean>(false)
|
||||
const collapseMenu = ref<HTMLDivElement>()
|
||||
const deleteAll = ref<HTMLDivElement>()
|
||||
const menuHeight = ref<string>()
|
||||
const viewerRef = ref<InstanceType<typeof Viewer>>()
|
||||
const viewerRef = ref<InstanceType<typeof ViewerType>>()
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@@ -616,7 +617,7 @@ async function patchOrDeleteCollectionItems(
|
||||
.menu-right {
|
||||
width: 50vw;
|
||||
height: calc(100vh - #{toRem(8)});
|
||||
overflow: hidden;
|
||||
overflow: auto;
|
||||
}
|
||||
.wrapper-loader {
|
||||
display: flex;
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
:bbox="collectionBbox"
|
||||
ref="viewerRef"
|
||||
/>
|
||||
<div v-else class="no-map">
|
||||
<img
|
||||
src="@/assets/images/how-to-share-map.png"
|
||||
:alt="$t('pages.share_pictures.alt_img_map')"
|
||||
class="no-map-img"
|
||||
/>
|
||||
</div>
|
||||
</vue-draggable-resizable>
|
||||
</section>
|
||||
<section
|
||||
@@ -31,9 +38,17 @@
|
||||
class="section-sequence"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<div class="header-title">
|
||||
<h1 id="sequenceTitle" class="sequences-title">
|
||||
{{ $t('pages.sequences.title') }}
|
||||
</h1>
|
||||
<Button
|
||||
v-if="filterDate.start || filterDate.end || sortDate.sortBy"
|
||||
look="button-border--black"
|
||||
:text="$t('pages.sequences.reset_filter_button')"
|
||||
@trigger="resetAllFilter"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
ref="headerList"
|
||||
:class="['sequence-item sequence-item-head', headerListClass]"
|
||||
@@ -48,21 +63,39 @@
|
||||
</div>
|
||||
<div class="sequence-header-item">
|
||||
<Button
|
||||
:text="$t('pages.sequences.sequence_date')"
|
||||
look="link--grey"
|
||||
icon="bi bi-arrow-down-up"
|
||||
look="link--black no-text"
|
||||
:icon="iconButtonSort('datetime')"
|
||||
data-test="button-sort-date"
|
||||
@trigger="sortList('datetime')"
|
||||
/>
|
||||
<span class="title">{{ $t('pages.sequences.sequence_date') }}</span>
|
||||
<div class="button-filter">
|
||||
<Button
|
||||
:look="filterClass"
|
||||
:icon="iconButtonFilter('datetime')"
|
||||
:tooltip="$t('pages.sequences.sequence_date_tooltip')"
|
||||
@trigger="displayModal('datetime')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sequence-header-item">
|
||||
<Button
|
||||
:text="$t('pages.sequences.sequence_creation')"
|
||||
look="link--grey"
|
||||
icon="bi bi-arrow-down-up"
|
||||
look="link--black no-text"
|
||||
:icon="iconButtonSort('created')"
|
||||
data-test="button-sort-date"
|
||||
@trigger="sortList('created')"
|
||||
/>
|
||||
<span class="title">{{
|
||||
$t('pages.sequences.sequence_creation')
|
||||
}}</span>
|
||||
<div class="button-filter">
|
||||
<Button
|
||||
:look="filterClass"
|
||||
:icon="iconButtonFilter('created')"
|
||||
:tooltip="$t('pages.sequences.sequence_creation_tooltip')"
|
||||
@trigger="displayModal('created')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sequence-header-item">
|
||||
<span>{{ $t('pages.sequences.sequence_status') }}</span>
|
||||
@@ -136,7 +169,7 @@
|
||||
<div class="wrapper-button">
|
||||
<Button
|
||||
:tooltip="$t('pages.sequence.hide_sequence_tooltip')"
|
||||
look="button--white background-white"
|
||||
look="button--white background-white no-text"
|
||||
:icon="
|
||||
item['geovisio:status'] === 'ready'
|
||||
? 'bi bi-eye-slash'
|
||||
@@ -147,12 +180,17 @@
|
||||
/>
|
||||
<Button
|
||||
:tooltip="$t('pages.sequence.delete_sequence_tooltip')"
|
||||
look="button--red background-white"
|
||||
look="button--red background-white no-text"
|
||||
icon="bi bi-trash"
|
||||
@trigger="deleteCollection(item)"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
<div v-else-if="!userSequences.length && noSequencesFound">
|
||||
<p class="no-sequence-found">
|
||||
{{ $t('pages.sequences.no_sequence_found') }}
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="no-sequence">
|
||||
<p class="no-sequence-text">
|
||||
{{ $t('pages.sequences.no_sequences_text') }}
|
||||
@@ -178,6 +216,28 @@
|
||||
</div>
|
||||
<Toast :text="toastText" :look="toastLook" @trigger="toastText = ''" />
|
||||
</section>
|
||||
<Modal ref="modal" :title="modalTitle">
|
||||
<template v-slot:body>
|
||||
<CalendarFilter
|
||||
v-if="calendarType === filterDate.type"
|
||||
:type="calendarType"
|
||||
:range-selected="{
|
||||
start: filterDate.start,
|
||||
end: filterDate.end,
|
||||
type: filterDate.type
|
||||
}"
|
||||
@triggerCloseModal="closeModal"
|
||||
@triggerDate="updateFilters"
|
||||
/>
|
||||
<CalendarFilter
|
||||
v-else
|
||||
:type="calendarType"
|
||||
:range-selected="{ start: null, end: null, type: '' }"
|
||||
@triggerCloseModal="closeModal"
|
||||
@triggerDate="updateFilters"
|
||||
/>
|
||||
</template>
|
||||
</Modal>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -193,10 +253,13 @@ import {
|
||||
import { useCookies } from 'vue3-cookies'
|
||||
import axios from 'axios'
|
||||
import Viewer from '@/components/Viewer.vue'
|
||||
import type ViewerType from '@/components/Viewer.vue'
|
||||
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 Modal from '@/components/Modal.vue'
|
||||
import CalendarFilter from '@/components/filters/CalendarFilter.vue'
|
||||
import Pagination from '@/components/Pagination.vue'
|
||||
import type { SequenceLinkInterface } from './interfaces/MySequencesView'
|
||||
import type { ResponseUserPhotoLinksInterface } from './interfaces/MySequenceView'
|
||||
@@ -223,23 +286,65 @@ let paginationLinks = ref<ResponseUserPhotoLinksInterface[] | []>([])
|
||||
let selfLink = ref<ResponseUserPhotoLinksInterface[] | []>([])
|
||||
let collectionBbox = ref<number[]>([])
|
||||
let isLoading = ref<boolean>(false)
|
||||
let sortedBy = ref<string>('')
|
||||
let isSorted = ref<boolean>(false)
|
||||
let noSequencesFound = ref<boolean>(false)
|
||||
let seqId = ref<string>('')
|
||||
let calendarType = ref<string>('')
|
||||
let width = ref<number>(0)
|
||||
let mapWidth = ref<number>(window.innerWidth / 3)
|
||||
let listWidth = ref<number>(window.innerWidth / 1.5)
|
||||
let filterDate = ref<{
|
||||
end: string | null
|
||||
start: string | null
|
||||
type: string
|
||||
}>({
|
||||
start: null,
|
||||
end: null,
|
||||
type: ''
|
||||
})
|
||||
let sortDate = ref<{ sortBy: string | null }>({ sortBy: null })
|
||||
let uri = ref<string>('api/users/me/collection?limit=50')
|
||||
let modal = ref()
|
||||
const windowWidth = ref<number>(window.innerWidth)
|
||||
const windowHeight = ref<number>(window.innerHeight - 80)
|
||||
const viewerRef = ref<InstanceType<typeof Viewer>>()
|
||||
const viewerRef = ref<InstanceType<typeof ViewerType>>()
|
||||
const headerList = ref<HTMLDivElement | null>(null)
|
||||
const list = ref<HTMLDListElement | null>(null)
|
||||
const listPos = ref<PositionInterface | null>(null)
|
||||
const headerLisPos = ref<PositionInterface | null>(null)
|
||||
|
||||
async function resetAllFilter(): Promise<void> {
|
||||
filterDate.value = { start: null, end: null, type: '' }
|
||||
sortDate.value = { sortBy: null }
|
||||
formatUri()
|
||||
await updateSequence(uri.value)
|
||||
}
|
||||
function displayModal(type: string): void {
|
||||
calendarType.value = type
|
||||
if (modal.value) modal.value.show()
|
||||
}
|
||||
function closeModal(): void {
|
||||
if (modal.value) modal.value.close()
|
||||
}
|
||||
function iconButtonSort(type: string): string {
|
||||
if (isSorted.value && sortedBy.value === type) return 'bi bi-sort-numeric-up'
|
||||
return 'bi bi-sort-numeric-down'
|
||||
}
|
||||
function iconButtonFilter(type: string): string {
|
||||
if (
|
||||
filterDate.value.start &&
|
||||
filterDate.value.end &&
|
||||
filterDate.value.type === type
|
||||
) {
|
||||
return 'bi bi-funnel-fill'
|
||||
}
|
||||
return 'bi bi-funnel'
|
||||
}
|
||||
async function fetchAndFormatSequence(): Promise<void> {
|
||||
const { data } = await axios.get('api/users/me/collection')
|
||||
const { data } = await axios.get('api/users/me/collection?limit=50')
|
||||
collectionBbox.value = data.extent.spatial.bbox[0]
|
||||
userSequences.value = getRelChild(data.links)
|
||||
userSequences.value = getLinkByRel(data.links, 'child')
|
||||
}
|
||||
|
||||
async function patchCollection(sequence: SequenceLinkInterface): Promise<void> {
|
||||
@@ -269,7 +374,7 @@ function sequenceStatus(status: string): string {
|
||||
return t('pages.sequences.sequence_waiting')
|
||||
}
|
||||
function onResizeMap(width: any): void {
|
||||
if (width) {
|
||||
if (width && collectionBbox.value.length) {
|
||||
width.value = width
|
||||
mapWidth.value = width.value.width
|
||||
listWidth.value = window.innerWidth - width.value.width
|
||||
@@ -284,21 +389,29 @@ const handleScroll = async () => {
|
||||
listPos.value = list.value.getBoundingClientRect()
|
||||
}
|
||||
}
|
||||
async function sortList(dateToSort: string): Promise<void> {
|
||||
isLoading.value = true
|
||||
let sortBy = `+${dateToSort}`
|
||||
if (isSorted.value) sortBy = `-${dateToSort}`
|
||||
const { data } = await axios.get(
|
||||
`api/users/me/collection?limit=50&sortby=${encodeURIComponent(sortBy)}`
|
||||
)
|
||||
selfLink.value = data.links.filter(
|
||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
||||
)
|
||||
async function updateSequence(uri: string) {
|
||||
try {
|
||||
const { data } = await axios.get(uri)
|
||||
selfLink.value = getLinkByRel(data.links, 'self')
|
||||
paginationLinks.value = formatPaginationItems(data.links)
|
||||
userSequences.value = getRelChild(data.links)
|
||||
isSorted.value = !isSorted.value
|
||||
userSequences.value = getLinkByRel(data.links, 'child')
|
||||
scrollToElement()
|
||||
isLoading.value = false
|
||||
} catch (e) {
|
||||
userSequences.value = []
|
||||
noSequencesFound.value = true
|
||||
isLoading.value = false
|
||||
}
|
||||
}
|
||||
async function sortList(dateToSort: string): Promise<void> {
|
||||
isLoading.value = true
|
||||
sortedBy.value = dateToSort
|
||||
let sortBy = `+${dateToSort}`
|
||||
if (isSorted.value) sortBy = `-${dateToSort}`
|
||||
sortDate.value.sortBy = encodeURIComponent(sortBy)
|
||||
formatUri()
|
||||
await updateSequence(uri.value)
|
||||
isSorted.value = !isSorted.value
|
||||
}
|
||||
|
||||
function bboxIsInsideOther(mainBbox: number[], bboxInside: number[]): boolean {
|
||||
@@ -334,10 +447,11 @@ function goToSequence(sequence: SequenceLinkInterface): void {
|
||||
duration: 0
|
||||
})
|
||||
}
|
||||
function getRelChild(
|
||||
sequences: SequenceLinkInterface[]
|
||||
function getLinkByRel(
|
||||
sequences: SequenceLinkInterface[],
|
||||
rel: string
|
||||
): SequenceLinkInterface[] {
|
||||
return sequences.filter((el: SequenceLinkInterface) => el.rel === 'child')
|
||||
return sequences.filter((el: SequenceLinkInterface) => el.rel === rel)
|
||||
}
|
||||
function scrollToElement(): void {
|
||||
const elementTarget = document.querySelector('#sequenceTitle')
|
||||
@@ -345,21 +459,22 @@ function scrollToElement(): void {
|
||||
}
|
||||
async function goToNextPage(value: string): Promise<void> {
|
||||
isLoading.value = true
|
||||
const { data } = await axios.get(value)
|
||||
selfLink.value = data.links.filter(
|
||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
||||
)
|
||||
paginationLinks.value = formatPaginationItems(data.links)
|
||||
userSequences.value = getRelChild(data.links)
|
||||
scrollToElement()
|
||||
isLoading.value = false
|
||||
await updateSequence(value)
|
||||
}
|
||||
const filterClass = computed<string>((): string => {
|
||||
return 'no-text-green'
|
||||
})
|
||||
const modalTitle = computed<string>((): string => {
|
||||
if (calendarType.value === 'datetime') {
|
||||
return t('pages.sequences.filter_date_title')
|
||||
}
|
||||
return t('pages.sequences.filter_date_upload_title')
|
||||
})
|
||||
const getUserId = computed<string>((): string => cookies.get('user_id'))
|
||||
const headerListClass = computed<string>((): string => {
|
||||
if (headerLisPos.value && listPos.value) {
|
||||
return headerLisPos.value.y != 0 && listPos.value.top < 180
|
||||
? 'item-head-fixed'
|
||||
: ''
|
||||
const classCondition = headerLisPos.value.y != 0 && listPos.value.top < 174
|
||||
return classCondition ? 'item-head-fixed' : ''
|
||||
}
|
||||
return ''
|
||||
})
|
||||
@@ -367,23 +482,55 @@ onMounted(async () => {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const { data } = await axios.get('api/users/me/collection?limit=50')
|
||||
selfLink.value = data.links.filter(
|
||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
||||
)
|
||||
selfLink.value = getLinkByRel(data.links, 'self')
|
||||
paginationLinks.value = formatPaginationItems(data.links)
|
||||
userSequences.value = getRelChild(data.links)
|
||||
userSequences.value = getLinkByRel(data.links, 'child')
|
||||
if (userSequences.value[0]) {
|
||||
collectionBbox.value = [
|
||||
userSequences.value[0].extent.spatial.bbox[0][0],
|
||||
userSequences.value[0].extent.spatial.bbox[0][1],
|
||||
userSequences.value[0].extent.spatial.bbox[0][2],
|
||||
userSequences.value[0].extent.spatial.bbox[0][3]
|
||||
]
|
||||
}
|
||||
isLoading.value = false
|
||||
} catch (err) {
|
||||
isLoading.value = false
|
||||
console.log(err)
|
||||
}
|
||||
})
|
||||
function formatUri(): void {
|
||||
let params: string[] = []
|
||||
if (filterDate.value.start && filterDate.value.end) {
|
||||
const rangeFilter = encodeURIComponent(
|
||||
`${filterDate.value.type} BETWEEN '${filterDate.value.start}' AND '${filterDate.value.end}'`
|
||||
)
|
||||
params = [...params, `&filter=${rangeFilter}`]
|
||||
}
|
||||
if (sortDate.value.sortBy) {
|
||||
params = [...params, `&sortby=${sortDate.value.sortBy}`]
|
||||
}
|
||||
if (params.length) {
|
||||
const constructParams = params.join('')
|
||||
uri.value = `api/users/me/collection?limit=50${constructParams}`
|
||||
} else uri.value = 'api/users/me/collection?limit=50'
|
||||
}
|
||||
async function updateFilters(value: {
|
||||
start: null
|
||||
end: null
|
||||
type: ''
|
||||
}): Promise<void> {
|
||||
isLoading.value = true
|
||||
noSequencesFound.value = false
|
||||
if (value.start && value.end) {
|
||||
filterDate.value = { start: value.start, end: value.end, type: value.type }
|
||||
formatUri()
|
||||
} else {
|
||||
uri.value = 'api/users/me/collection?limit=50'
|
||||
filterDate.value = { end: null, start: null, type: '' }
|
||||
}
|
||||
await updateSequence(uri.value)
|
||||
}
|
||||
watchEffect(() => {
|
||||
if (viewerRef.value && viewerRef.value.viewer) {
|
||||
viewerRef.value.viewer.addEventListener(
|
||||
@@ -431,18 +578,38 @@ watchEffect(() => {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.no-map {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--blue-pale);
|
||||
}
|
||||
.section-sequence {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
.header-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
margin: toRem(3);
|
||||
}
|
||||
.sequences-title {
|
||||
@include text(h1);
|
||||
color: var(--blue-dark);
|
||||
margin-bottom: toRem(5);
|
||||
margin-top: toRem(3);
|
||||
margin-left: toRem(3);
|
||||
}
|
||||
.date-filter-title {
|
||||
@include text(s-r-regular);
|
||||
}
|
||||
.wrapper-date-filter-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.sequence-list {
|
||||
box-shadow: 0px 2px 30px 0px #0000000f;
|
||||
@@ -574,7 +741,10 @@ watchEffect(() => {
|
||||
margin-right: toRem(0.5);
|
||||
}
|
||||
.sequence-header-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: calc(31% - #{toRem(4.75)});
|
||||
color: var(--grey-semi-dark);
|
||||
&:first-child {
|
||||
margin-right: toRem(2);
|
||||
}
|
||||
@@ -584,6 +754,15 @@ watchEffect(() => {
|
||||
&:nth-child(3) {
|
||||
width: toRem(13);
|
||||
}
|
||||
.title {
|
||||
color: var(--black);
|
||||
}
|
||||
}
|
||||
.button-filter {
|
||||
margin-left: toRem(-1);
|
||||
.icon {
|
||||
font-size: toRem(1);
|
||||
}
|
||||
}
|
||||
.no-sequence {
|
||||
padding-top: toRem(2);
|
||||
@@ -599,6 +778,10 @@ watchEffect(() => {
|
||||
.no-sequence-text {
|
||||
margin-bottom: toRem(4);
|
||||
}
|
||||
.no-sequence-found {
|
||||
text-align: center;
|
||||
padding: toRem(2);
|
||||
}
|
||||
.loader {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -639,8 +822,21 @@ watchEffect(() => {
|
||||
width: 100% !important;
|
||||
}
|
||||
.sequence-item-head {
|
||||
width: 100% !important;
|
||||
flex-direction: row !important;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.sequence-header-item {
|
||||
width: 50%;
|
||||
justify-content: center;
|
||||
&:first-child,
|
||||
&:last-child,
|
||||
&:nth-child(2),
|
||||
&:nth-child(3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.button-item {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
@@ -90,7 +90,20 @@
|
||||
v-if="uploadedSequence && uploadedSequence.picturesOnError"
|
||||
ref="modal"
|
||||
:upload-errors="uploadedSequence.picturesOnError"
|
||||
/>
|
||||
:title="$t('pages.upload.modal_error_title')"
|
||||
>
|
||||
<template v-slot:body>
|
||||
<ul>
|
||||
<li
|
||||
v-for="item in uploadedSequence.picturesOnError"
|
||||
class="error-item"
|
||||
>
|
||||
<span>{{ item.name }} - </span>
|
||||
<span>{{ item.details.error }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</Modal>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -169,7 +182,7 @@ function setNewSequenceTitle(value: string | null): void {
|
||||
function formatSequenceTitle(): string {
|
||||
return `${t('pages.upload.sequence_title')}${formatDate(
|
||||
new Date(),
|
||||
'Do MMMM YYYY, hh:mm:ss'
|
||||
'Do MMMM YYYY, HH:mm:ss'
|
||||
)}`
|
||||
}
|
||||
function picturesToUploadSizeText(): void {
|
||||
@@ -300,6 +313,12 @@ h3 {
|
||||
margin-right: toRem(2);
|
||||
}
|
||||
}
|
||||
.error-item {
|
||||
padding: toRem(1);
|
||||
&:nth-child(odd) {
|
||||
background-color: var(--grey);
|
||||
}
|
||||
}
|
||||
.subtitle {
|
||||
@include text(h3);
|
||||
color: var(--blue-dark);
|
||||
@@ -340,6 +359,9 @@ h3 {
|
||||
align-items: center;
|
||||
}
|
||||
@media (max-width: toRem(76.8)) {
|
||||
.section {
|
||||
display: none;
|
||||
}
|
||||
.entry-page {
|
||||
padding-top: toRem(15);
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@ export interface ResponseUserSequenceInterface extends UserSequenceInterface {
|
||||
|
||||
export interface CheckboxInterface {
|
||||
isChecked: boolean
|
||||
isIndeterminate: boolean
|
||||
isIndeterminate?: boolean
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@ export interface MapInterface {
|
||||
zoom?: number
|
||||
center?: number[]
|
||||
bounds?: number[]
|
||||
raster?: {
|
||||
type: string
|
||||
tiles: string[]
|
||||
attribution: string
|
||||
tileSize: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface ViewerInterface {
|
||||
|
||||
1
v-calendar.d.ts
vendored
Normal file
1
v-calendar.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
declare module 'v-calendar'
|
||||
113
yarn.lock
113
yarn.lock
@@ -272,6 +272,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.22.5"
|
||||
|
||||
"@babel/runtime@^7.21.0":
|
||||
version "7.23.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.7.tgz#dd7c88deeb218a0f8bd34d5db1aa242e0f203193"
|
||||
integrity sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.22.15", "@babel/template@^7.3.3":
|
||||
version "7.22.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
|
||||
@@ -888,16 +895,6 @@
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
|
||||
integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
|
||||
|
||||
"@maplibre/maplibre-gl-geocoder@^1.5.0":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-geocoder/-/maplibre-gl-geocoder-1.5.0.tgz#6b413525b361b4759df0fd17429e12b78f03b3a4"
|
||||
integrity sha512-PsAbV7WFIOu5QYZne95FiXoV7AV1/6ULMjQxgInhZ5DdB0hDLjciQPegnyDgkzI8JfeqoUMZVS/MglZnSZYhyQ==
|
||||
dependencies:
|
||||
lodash.debounce "^4.0.6"
|
||||
subtag "^0.5.0"
|
||||
suggestions-list "^0.0.2"
|
||||
xtend "^4.0.1"
|
||||
|
||||
"@maplibre/maplibre-gl-style-spec@^19.3.3":
|
||||
version "19.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-19.3.3.tgz#a106248bd2e25e77c963a362aeaf630e00f924e9"
|
||||
@@ -1184,6 +1181,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@types/lodash@^4.14.165":
|
||||
version "4.14.202"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8"
|
||||
integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==
|
||||
|
||||
"@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz#0ef017b75eedce02ff6243b4189210e2e6d5e56d"
|
||||
@@ -1244,6 +1246,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/pbf/-/pbf-3.0.5.tgz#a9495a58d8c75be4ffe9a0bd749a307715c07404"
|
||||
integrity sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==
|
||||
|
||||
"@types/resize-observer-browser@^0.1.7":
|
||||
version "0.1.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.11.tgz#d3c98d788489d8376b7beac23863b1eebdd3c13c"
|
||||
integrity sha512-cNw5iH8JkMkb3QkCoe7DaZiawbDQEUX8t7iuQaRTyLOyQCR2h+ibBD4GJt7p5yhUHrlOeL7ZtbxNHeipqNsBzQ==
|
||||
|
||||
"@types/semver@^7.3.12":
|
||||
version "7.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339"
|
||||
@@ -2679,6 +2686,18 @@ data-urls@^3.0.2:
|
||||
whatwg-mimetype "^3.0.0"
|
||||
whatwg-url "^11.0.0"
|
||||
|
||||
date-fns-tz@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns-tz/-/date-fns-tz-2.0.0.tgz#1b14c386cb8bc16fc56fe333d4fc34ae1d1099d5"
|
||||
integrity sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==
|
||||
|
||||
date-fns@^2.16.1:
|
||||
version "2.30.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
|
||||
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.21.0"
|
||||
|
||||
dayjs@^1.10.4:
|
||||
version "1.11.10"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
|
||||
@@ -3604,6 +3623,11 @@ fd-slicer@~1.1.0:
|
||||
dependencies:
|
||||
pend "~1.2.0"
|
||||
|
||||
fflate@^0.8.0:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.1.tgz#1ed92270674d2ad3c73f077cd0acf26486dae6c9"
|
||||
integrity sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==
|
||||
|
||||
figures@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
|
||||
@@ -3779,11 +3803,6 @@ functions-have-names@^1.2.3:
|
||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||
|
||||
fuzzy@^0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fuzzy/-/fuzzy-0.1.3.tgz#4c76ec2ff0ac1a36a9dccf9a00df8623078d4ed8"
|
||||
integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==
|
||||
|
||||
gensync@^1.0.0-beta.2:
|
||||
version "1.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
@@ -3794,14 +3813,13 @@ geojson-vt@^3.2.1:
|
||||
resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
|
||||
integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
|
||||
|
||||
geovisio@2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/geovisio/-/geovisio-2.3.0.tgz#45108c32557ac9ebcd0a595cf1b13488cc03cf84"
|
||||
integrity sha512-M43onTVE6ulek23M0FyTLKN5JEdRfSfKgTxo2b3wIplb5u20TAuliP3wQpeHGYeT/bii0r/L81uX4K4EJldF3g==
|
||||
geovisio@2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/geovisio/-/geovisio-2.3.1.tgz#4c4151ebfb597edf558dcd7a069f6c87a947bf0b"
|
||||
integrity sha512-k9JA6Pw1Ro+ONdCWiRSmVMzxAiIB4+K7bwg0astdhBoc0SQsU9Jtu+Nc/scjHrenm+kJZvm42kMre5buNa3lLg==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-svg-core" "^6.4.0"
|
||||
"@fortawesome/free-solid-svg-icons" "^6.4.0"
|
||||
"@maplibre/maplibre-gl-geocoder" "^1.5.0"
|
||||
"@photo-sphere-viewer/core" "^5.5.0"
|
||||
"@photo-sphere-viewer/equirectangular-tiles-adapter" "^5.5.0"
|
||||
"@photo-sphere-viewer/gallery-plugin" "^5.5.0"
|
||||
@@ -3809,6 +3827,7 @@ geovisio@2.3.0:
|
||||
"@photo-sphere-viewer/virtual-tour-plugin" "^5.5.0"
|
||||
documentation "^14.0.1"
|
||||
maplibre-gl "^3.3.0"
|
||||
pmtiles "^2.11.0"
|
||||
|
||||
get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
@@ -5367,11 +5386,6 @@ locate-path@^7.1.0:
|
||||
dependencies:
|
||||
p-locate "^6.0.0"
|
||||
|
||||
lodash.debounce@^4.0.6:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
@@ -5382,7 +5396,7 @@ lodash.once@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
|
||||
|
||||
lodash@^4.17.21:
|
||||
lodash@^4.17.20, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
@@ -6574,6 +6588,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
||||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
pmtiles@^2.11.0:
|
||||
version "2.11.0"
|
||||
resolved "https://registry.yarnpkg.com/pmtiles/-/pmtiles-2.11.0.tgz#53aac29408e001a73b15b1c8cad0b17c944ab7bd"
|
||||
integrity sha512-dU9SzzaqmCGpdEuTnIba6bDHT6j09ZJFIXxwGpvkiEnce3ZnBB1VKt6+EOmJGueriweaZLAMTUmKVElU2CBe0g==
|
||||
dependencies:
|
||||
fflate "^0.8.0"
|
||||
|
||||
postcss-selector-parser@^6.0.13:
|
||||
version "6.0.13"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b"
|
||||
@@ -6786,6 +6807,11 @@ readdirp@~3.6.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
regenerator-runtime@^0.14.0:
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
|
||||
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
|
||||
|
||||
regexp.prototype.flags@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e"
|
||||
@@ -7439,19 +7465,6 @@ strip-literal@^1.0.0:
|
||||
dependencies:
|
||||
acorn "^8.10.0"
|
||||
|
||||
subtag@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/subtag/-/subtag-0.5.0.tgz#1728a8df5257fb98ded4fb981b2ac7af10cf58ba"
|
||||
integrity sha512-CaIBcTSb/nyk4xiiSOtZYz1B+F12ZxW8NEp54CdT+84vmh/h4sUnHGC6+KQXUfED8u22PQjCYWfZny8d2ELXwg==
|
||||
|
||||
suggestions-list@^0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/suggestions-list/-/suggestions-list-0.0.2.tgz#3c5f501833e697a726a1bf58fbc454d57ffa0e98"
|
||||
integrity sha512-Yw0fdq14c6RQWQIfE1/8WEi9Dp8rjyCD6FhYA/Tit2/ADbE9Y4ADG4ezlvivsa8Civ5nz++pyVVBMjOMlgIUJw==
|
||||
dependencies:
|
||||
fuzzy "^0.1.1"
|
||||
xtend "^4.0.0"
|
||||
|
||||
supercluster@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5"
|
||||
@@ -7931,6 +7944,18 @@ uvu@^0.5.0:
|
||||
kleur "^4.0.3"
|
||||
sade "^1.7.3"
|
||||
|
||||
v-calendar@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/v-calendar/-/v-calendar-3.1.2.tgz#fb47320a5469973454f030d850134eebcd2307eb"
|
||||
integrity sha512-QDWrnp4PWCpzUblctgo4T558PrHgHzDtQnTeUNzKxfNf29FkCeFpwGd9bKjAqktaa2aJLcyRl45T5ln1ku34kg==
|
||||
dependencies:
|
||||
"@types/lodash" "^4.14.165"
|
||||
"@types/resize-observer-browser" "^0.1.7"
|
||||
date-fns "^2.16.1"
|
||||
date-fns-tz "^2.0.0"
|
||||
lodash "^4.17.20"
|
||||
vue-screen-utils "^1.0.0-beta.13"
|
||||
|
||||
v8-to-istanbul@^9.0.1:
|
||||
version "9.2.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad"
|
||||
@@ -8137,6 +8162,11 @@ vue-router@^4.1.6:
|
||||
dependencies:
|
||||
"@vue/devtools-api" "^6.5.0"
|
||||
|
||||
vue-screen-utils@^1.0.0-beta.13:
|
||||
version "1.0.0-beta.13"
|
||||
resolved "https://registry.yarnpkg.com/vue-screen-utils/-/vue-screen-utils-1.0.0-beta.13.tgz#0c739e19f6ffbffab63184aba7b6d710b6a63681"
|
||||
integrity sha512-EJ/8TANKhFj+LefDuOvZykwMr3rrLFPLNb++lNBqPOpVigT2ActRg6icH9RFQVm4nHwlHIHSGm5OY/Clar9yIg==
|
||||
|
||||
vue-template-compiler@^2.7.14, vue-template-compiler@^2.7.8:
|
||||
version "2.7.15"
|
||||
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz#ec88ba8ceafe0f17a528b89c57e01e02da92b0de"
|
||||
@@ -8375,11 +8405,6 @@ xmlchars@^2.2.0:
|
||||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
|
||||
Reference in New Issue
Block a user