forked from Ivasoft/geovisio-website
Compare commits
16 Commits
2.3.1
...
fix/conf-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dfb184da1 | ||
|
|
03ba508d7b | ||
|
|
518f06c846 | ||
|
|
50f1f7b472 | ||
|
|
2f4000291f | ||
|
|
6ad1d85604 | ||
|
|
707420c69e | ||
|
|
1bd41002af | ||
|
|
c30eeb020d | ||
|
|
c37296066f | ||
|
|
19f5f5a320 | ||
|
|
589f7c64c0 | ||
|
|
459efcfd57 | ||
|
|
966be42f19 | ||
|
|
c4066930ba | ||
|
|
6322a75f42 |
34
CHANGELOG.md
34
CHANGELOG.md
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
Before _0.1.0_, website development was on rolling release, meaning there are no version tags.
|
Before _0.1.0_, website development was on rolling release, meaning there are no version tags.
|
||||||
|
|
||||||
|
## [2.5.0] - 2024-03-11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- GeoVisio web viewer updated to [2.5.0](https://gitlab.com/geovisio/web-viewer/-/compare/2.4.0...2.5.0) to reduce tiles size.
|
||||||
|
|
||||||
|
## [2.4.1] - 2024-02-01
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix geovisio version yarn.lock
|
||||||
|
|
||||||
|
## [2.4.0] - 2024-01-31
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Possibility to edit a sequence title in the sequence page
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- GeoVisio web viewer updated to [2.4.0](https://gitlab.com/geovisio/web-viewer/-/compare/2.3.1...2.4.0) to manage sequence by user
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix filter reset button to include bbox filter
|
||||||
|
- Fix fullscreen button added by the widget viewer
|
||||||
|
- Some UI and UX fixes before user tests
|
||||||
|
|
||||||
## [2.3.1] - 2024-01-29
|
## [2.3.1] - 2024-01-29
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -164,7 +192,10 @@ Before _0.1.0_, website development was on rolling release, meaning there are no
|
|||||||
- Header have now a new entry `Mes photos` when the user is logged to access to the sequence list
|
- Header have now a new entry `Mes photos` when the user is logged to access to the sequence list
|
||||||
- The router guard for logged pages has been changed to not call the api to check the token
|
- The router guard for logged pages has been changed to not call the api to check the token
|
||||||
|
|
||||||
[unreleased]: https://gitlab.com/geovisio/website/-/compare/2.3.1...develop
|
[unreleased]: https://gitlab.com/geovisio/website/-/compare/2.5.0...develop
|
||||||
|
[2.5.0]: https://gitlab.com/geovisio/website/-/compare/2.4.1...2.5.0
|
||||||
|
[2.4.1]: https://gitlab.com/geovisio/website/-/compare/2.4.0...2.4.1
|
||||||
|
[2.4.0]: https://gitlab.com/geovisio/website/-/compare/2.3.1...2.4.0
|
||||||
[2.3.1]: https://gitlab.com/geovisio/website/-/compare/2.3.0...2.3.1
|
[2.3.1]: https://gitlab.com/geovisio/website/-/compare/2.3.0...2.3.1
|
||||||
[2.3.0]: https://gitlab.com/geovisio/website/-/compare/2.2.3...2.3.0
|
[2.3.0]: https://gitlab.com/geovisio/website/-/compare/2.2.3...2.3.0
|
||||||
[2.2.3]: https://gitlab.com/geovisio/website/-/compare/2.2.2...2.2.3
|
[2.2.3]: https://gitlab.com/geovisio/website/-/compare/2.2.2...2.2.3
|
||||||
@@ -176,4 +207,3 @@ Before _0.1.0_, website development was on rolling release, meaning there are no
|
|||||||
[2.1.1]: https://gitlab.com/geovisio/website/-/compare/2.1.0...2.1.1
|
[2.1.1]: https://gitlab.com/geovisio/website/-/compare/2.1.0...2.1.1
|
||||||
[2.1.0]: https://gitlab.com/geovisio/website/-/compare/0.1.0...2.1.0
|
[2.1.0]: https://gitlab.com/geovisio/website/-/compare/0.1.0...2.1.0
|
||||||
[0.1.0]: https://gitlab.com/geovisio/website/-/commits/0.1.0
|
[0.1.0]: https://gitlab.com/geovisio/website/-/commits/0.1.0
|
||||||
|
|
||||||
25
index.html
25
index.html
@@ -4,6 +4,31 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" href="/static/favicon.ico" />
|
<link rel="icon" href="/static/favicon.ico" />
|
||||||
|
<title>
|
||||||
|
Panoramax <%- instanceName %> : photo-cartographier les territoires
|
||||||
|
</title>
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="L'instance Panoramax <%- instanceName %> permet la publication de photo de terrain pour cartographier le territoire. Panoramax favorise la réutilisation des photos pour de nombreux cas d'usages."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="twitter:title"
|
||||||
|
content="Panoramax <%- instanceName %> : photo-cartographier les territoires"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="og:title"
|
||||||
|
content="Panoramax <%- instanceName %> : photo-cartographier les territoires"
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="L'instance Panoramax <%- instanceName %> permet la publication de photo de terrain pour cartographier le territoire. Panoramax favorise la réutilisation des photos pour de nombreux cas d'usages."
|
||||||
|
/>
|
||||||
|
<meta
|
||||||
|
name="og:description"
|
||||||
|
content="L'instance Panoramax <%- instanceName %> permet la publication de photo de terrain pour cartographier le territoire. Panoramax favorise la réutilisation des photos pour de nombreux cas d'usages."
|
||||||
|
/>
|
||||||
|
<meta name="og:image" content="<%- frontUrl %>/static/meta-img.jpg" />
|
||||||
|
<meta name="twitter:image" content="<%- frontUrl %>/static/meta-img.jpg" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "geovisio-website",
|
"name": "geovisio-website",
|
||||||
"version": "2.3.1",
|
"version": "2.5.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18.16.1"
|
"node": "18.16.1"
|
||||||
},
|
},
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"axios": "^1.2.3",
|
"axios": "^1.2.3",
|
||||||
"bootstrap": "^5.2.3",
|
"bootstrap": "^5.2.3",
|
||||||
"bootstrap-icons": "^1.10.3",
|
"bootstrap-icons": "^1.10.3",
|
||||||
"geovisio": "2.3.1",
|
"geovisio": "2.5.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"pinia": "^2.1.4",
|
"pinia": "^2.1.4",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"vue-draggable-resizable-vue3": "^2.3.1-beta.13",
|
"vue-draggable-resizable-vue3": "^2.3.1-beta.13",
|
||||||
"vue-eslint-parser": "^9.1.0",
|
"vue-eslint-parser": "^9.1.0",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "9.2.2",
|
||||||
"vue-meta": "^3.0.0-alpha.10",
|
"vue-matomo": "^4.2.0",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
"vue3-cookies": "^1.0.6",
|
"vue3-cookies": "^1.0.6",
|
||||||
"vue3-smooth-scroll": "^0.8.1"
|
"vue3-smooth-scroll": "^0.8.1"
|
||||||
@@ -70,6 +70,7 @@
|
|||||||
"typescript": "~4.7.4",
|
"typescript": "~4.7.4",
|
||||||
"vite": "^3.2.4",
|
"vite": "^3.2.4",
|
||||||
"vite-plugin-eslint": "^1.8.1",
|
"vite-plugin-eslint": "^1.8.1",
|
||||||
|
"vite-plugin-html": "^3.2.2",
|
||||||
"vitest": "^0.25.3",
|
"vitest": "^0.25.3",
|
||||||
"vue-tsc": "^1.0.9"
|
"vue-tsc": "^1.0.9"
|
||||||
},
|
},
|
||||||
|
|||||||
14
src/App.vue
14
src/App.vue
@@ -3,28 +3,14 @@ import { ref, computed } from 'vue'
|
|||||||
import Header from '@/components/Header.vue'
|
import Header from '@/components/Header.vue'
|
||||||
import Footer from '@/components/Footer.vue'
|
import Footer from '@/components/Footer.vue'
|
||||||
import { RouterView } from 'vue-router'
|
import { RouterView } from 'vue-router'
|
||||||
import { useMeta } from 'vue-meta'
|
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { hasASessionCookieDecoded } from '@/utils/auth'
|
import { hasASessionCookieDecoded } from '@/utils/auth'
|
||||||
import { title } from '@/utils/index'
|
|
||||||
import authConfig from './composables/auth'
|
import authConfig from './composables/auth'
|
||||||
const { authConf } = authConfig()
|
const { authConf } = authConfig()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
let focusMap = ref<string>('focus-map')
|
let focusMap = ref<string>('focus-map')
|
||||||
|
|
||||||
useMeta({
|
|
||||||
title: title(t('general.title')),
|
|
||||||
og: {
|
|
||||||
title: title(t('general.meta.title')),
|
|
||||||
description: title(t('general.meta.description'))
|
|
||||||
},
|
|
||||||
twitter: {
|
|
||||||
title: title(t('general.meta.title')),
|
|
||||||
description: title(t('general.meta.description'))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
function setFocusMap(value: string) {
|
function setFocusMap(value: string) {
|
||||||
focusMap.value = value
|
focusMap.value = value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,45 @@
|
|||||||
export function createLink(href: string, text: string): string {
|
export function createLink(href: string, text: string): string {
|
||||||
return `<a href='mailto:signalement.ign@panoramax.fr${href}' target='_blank' title='${text}' class='gvs-btn gvs-widget-bg gvs-btn-large' style='font-size: 1.6em;display: block'><i class="bi bi-exclamation-triangle"></i></a>`
|
return `<a href='mailto:signalement.ign@panoramax.fr${href}' target='_blank' title='${text}' class='gvs-btn gvs-widget-bg gvs-btn-large' style='font-size: 1.6em;display: block; margin-top: 0.5em;'><i class="bi bi-exclamation-triangle"></i></a>`
|
||||||
}
|
}
|
||||||
export function createSequenceLink(href: string, title: string): string {
|
export function createSequenceLink(href: string, title: string): string {
|
||||||
return `<a href='${href}' title='${title}' class='gvs-btn gvs-widget-bg gvs-btn-large' style='font-size: 1.6em;display: block; position: relative'>
|
return `<a href='${href}' title='${title}' class='gvs-btn gvs-widget-bg gvs-btn-large' style='font-size: 1.6em;display: block; position: relative; margin-top: 0.5em;'>
|
||||||
<i class="bi bi-images"></i>
|
<i class="bi bi-images"></i>
|
||||||
</a>`
|
</a>`
|
||||||
}
|
}
|
||||||
|
export function createFullScreenButton(): string {
|
||||||
|
return `<button type='button' onClick="
|
||||||
|
const header = document.getElementById('navHeader')
|
||||||
|
const footer = document.getElementById('navFooter')
|
||||||
|
const icon = document.getElementById('iconScreen')
|
||||||
|
const home = document.getElementById('homePage')
|
||||||
|
if (header) {
|
||||||
|
const isHiddenHeader = header.classList.contains('hidden')
|
||||||
|
if (isHiddenHeader) header.classList.remove('hidden')
|
||||||
|
else header.classList.add('hidden')
|
||||||
|
}
|
||||||
|
if (footer) {
|
||||||
|
const isHiddenHeader = footer.classList.contains('hidden')
|
||||||
|
if (isHiddenHeader) footer.classList.remove('hidden')
|
||||||
|
else footer.classList.add('hidden')
|
||||||
|
}
|
||||||
|
if (icon) {
|
||||||
|
const isIconNotFull = icon.classList.contains('bi-fullscreen')
|
||||||
|
if(isIconNotFull) {
|
||||||
|
icon.classList.remove('bi-fullscreen')
|
||||||
|
icon.classList.add('bi-fullscreen-exit')
|
||||||
|
} else {
|
||||||
|
icon.classList.remove('bi-fullscreen-exit')
|
||||||
|
icon.classList.add('bi-fullscreen')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (home) {
|
||||||
|
const isHomeFull = home.classList.contains('full-viewer')
|
||||||
|
if(isHomeFull) home.classList.remove('full-viewer')
|
||||||
|
else home.classList.add('full-viewer')
|
||||||
|
}
|
||||||
|
"
|
||||||
|
class='gvs-btn gvs-widget-bg gvs-btn-large'
|
||||||
|
>
|
||||||
|
<i id='iconScreen' class="bi bi-fullscreen"></i>
|
||||||
|
</button>`
|
||||||
|
}
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ defineProps({
|
|||||||
}
|
}
|
||||||
.button--white {
|
.button--white {
|
||||||
color: var(--blue);
|
color: var(--blue);
|
||||||
|
background-color: var(--white);
|
||||||
border: toRem(0.1) solid var(--blue);
|
border: toRem(0.1) solid var(--blue);
|
||||||
.icon {
|
.icon {
|
||||||
font-size: toRem(1.4);
|
font-size: toRem(1.4);
|
||||||
@@ -143,7 +144,7 @@ defineProps({
|
|||||||
.no-text-blue-dark .icon {
|
.no-text-blue-dark .icon {
|
||||||
color: var(--blue-dark);
|
color: var(--blue-dark);
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
font-size: toRem(1.6);
|
font-size: toRem(1.4);
|
||||||
}
|
}
|
||||||
.no-text-green .icon {
|
.no-text-green .icon {
|
||||||
color: var(--blue);
|
color: var(--blue);
|
||||||
@@ -216,6 +217,7 @@ defineProps({
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
width: toRem(20);
|
width: toRem(20);
|
||||||
right: 0;
|
right: 0;
|
||||||
|
z-index: 9;
|
||||||
@include text(xss-regular);
|
@include text(xss-regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="entry-edit">
|
<div :class="['entry-edit', { 'edit-mode': isEditTitle }]">
|
||||||
<form
|
<span v-if="isEditTitle && formTitle" class="form-title">{{
|
||||||
v-if="isEditTitle && !isDisabled"
|
formTitle
|
||||||
@submit.prevent="isEditTitle = false"
|
}}</span>
|
||||||
class="edit-form"
|
<div class="entry-form">
|
||||||
>
|
<form
|
||||||
<div class="wrapper-input">
|
v-if="isEditTitle && !isDisabled"
|
||||||
<Input
|
@submit.prevent="isEditTitle = false"
|
||||||
id="upload-title"
|
class="edit-form"
|
||||||
:text="text || ''"
|
>
|
||||||
:placeholder="$t('pages.upload.edit_placeholder_input')"
|
<div class="wrapper-input">
|
||||||
@input="changeTextValue"
|
<Input
|
||||||
|
id="upload-title"
|
||||||
|
:text="text || ''"
|
||||||
|
:placeholder="$t('pages.upload.edit_placeholder_input')"
|
||||||
|
@input="changeTextValue"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
id="valid-button"
|
||||||
|
:text="$t('pages.upload.ok_button')"
|
||||||
|
type="submit"
|
||||||
|
look="button--white"
|
||||||
|
@trigger="validNewName"
|
||||||
/>
|
/>
|
||||||
<div class="close-button">
|
<div class="close-button">
|
||||||
<Button
|
<Button
|
||||||
@@ -20,24 +32,17 @@
|
|||||||
@trigger="closeEdition"
|
@trigger="closeEdition"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</form>
|
||||||
|
<span v-else class="title">{{ text }}</span>
|
||||||
|
<div v-if="!isEditTitle" class="edit-button">
|
||||||
|
<Button
|
||||||
|
look="no-text-blue-dark"
|
||||||
|
icon="bi bi-pen"
|
||||||
|
:tooltip="$t('pages.upload.edit_title_tooltip')"
|
||||||
|
:disabled="isDisabled"
|
||||||
|
@trigger="goToEditMode"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
id="valid-button"
|
|
||||||
:text="$t('pages.upload.ok_button')"
|
|
||||||
type="submit"
|
|
||||||
look="button button--blue"
|
|
||||||
@trigger="validNewName"
|
|
||||||
/>
|
|
||||||
</form>
|
|
||||||
<span v-else class="title">{{ text }}</span>
|
|
||||||
<div v-if="!isEditTitle" class="edit-button">
|
|
||||||
<Button
|
|
||||||
look="no-text-blue-dark"
|
|
||||||
icon="bi bi-pen"
|
|
||||||
:tooltip="$t('pages.upload.edit_title_tooltip')"
|
|
||||||
:disabled="isDisabled"
|
|
||||||
@trigger="goToEditMode"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -53,7 +58,8 @@ const emit = defineEmits<{
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
defaultText: { type: String, default: null },
|
defaultText: { type: String, default: null },
|
||||||
isLoading: { type: Boolean, default: false },
|
isLoading: { type: Boolean, default: false },
|
||||||
isLoaded: { type: Boolean, default: false }
|
isLoaded: { type: Boolean, default: false },
|
||||||
|
formTitle: { type: String, default: null }
|
||||||
})
|
})
|
||||||
let titleToEdit = ref<string | null>(null)
|
let titleToEdit = ref<string | null>(null)
|
||||||
let isEditTitle = ref<boolean>(false)
|
let isEditTitle = ref<boolean>(false)
|
||||||
@@ -86,13 +92,27 @@ const isDisabled = computed<boolean>(() => props.isLoading && !props.isLoaded)
|
|||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.title {
|
.title {
|
||||||
color: var(--blue-dark);
|
color: var(--blue-dark);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.form-title {
|
||||||
|
text-align: left;
|
||||||
|
width: 100%;
|
||||||
|
@include text(xs-r-regular);
|
||||||
|
margin-bottom: toRem(0.3);
|
||||||
}
|
}
|
||||||
.entry-edit {
|
.entry-edit {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.entry-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: toRem(2);
|
}
|
||||||
width: 100%;
|
.edit-mode {
|
||||||
height: toRem(4.7);
|
background-color: var(--blue-pale);
|
||||||
|
padding: toRem(1);
|
||||||
|
border-radius: toRem(0.4);
|
||||||
}
|
}
|
||||||
.wrapper-edit {
|
.wrapper-edit {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -103,13 +123,14 @@ const isDisabled = computed<boolean>(() => props.isLoading && !props.isLoaded)
|
|||||||
.edit-button {
|
.edit-button {
|
||||||
background-color: var(--grey);
|
background-color: var(--grey);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
height: toRem(3.5);
|
height: toRem(2.5);
|
||||||
width: toRem(3.5);
|
width: toRem(2.5);
|
||||||
padding: toRem(1);
|
padding: toRem(1);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: toRem(1.5);
|
margin-left: toRem(1.5);
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.wrapper-input {
|
.wrapper-input {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@@ -24,10 +24,11 @@ function emitValue(event: Event): void {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.input {
|
.input {
|
||||||
padding: toRem(1);
|
padding: toRem(0.5) toRem(1);
|
||||||
border-radius: toRem(0.5);
|
border-radius: toRem(0.5);
|
||||||
border: toRem(0.1) solid var(--blue-dark);
|
border: toRem(0.1) solid var(--blue-dark);
|
||||||
color: var(--blue-dark);
|
color: var(--blue-dark);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@include text(s-r-regular);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="viewer" class="entry-viewer">
|
<div id="viewer" class="entry-viewer"></div>
|
||||||
<slot name="fullscreen"></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@@ -11,7 +9,11 @@ import { useSequenceStore } from '@/store/sequence'
|
|||||||
import { Viewer, StandaloneMap } from 'geovisio'
|
import { Viewer, StandaloneMap } from 'geovisio'
|
||||||
import { getIgnTiles } from '@/utils/mapAndViewer'
|
import { getIgnTiles } from '@/utils/mapAndViewer'
|
||||||
import { createUrlLink } from '@/utils'
|
import { createUrlLink } from '@/utils'
|
||||||
import { createLink, createSequenceLink } from '@/components-viewer/reportLink'
|
import {
|
||||||
|
createLink,
|
||||||
|
createSequenceLink,
|
||||||
|
createFullScreenButton
|
||||||
|
} from '@/components-viewer/reportLink'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { hasASessionCookieDecoded } from '@/utils/auth'
|
import { hasASessionCookieDecoded } from '@/utils/auth'
|
||||||
import type { ViewerInterface, MapInterface } from '@/views/interfaces/common'
|
import type { ViewerInterface, MapInterface } from '@/views/interfaces/common'
|
||||||
@@ -49,6 +51,7 @@ async function getSequenceId(imgId: string): Promise<{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function createViewerButton(link: HTMLDivElement): void {
|
function createViewerButton(link: HTMLDivElement): void {
|
||||||
|
link.innerHTML = `<div>${createFullScreenButton()}</div>`
|
||||||
viewer.value.addEventListener(
|
viewer.value.addEventListener(
|
||||||
'picture-loaded',
|
'picture-loaded',
|
||||||
async (e: { detail: { picId: string } }): Promise<void> => {
|
async (e: { detail: { picId: string } }): Promise<void> => {
|
||||||
@@ -56,17 +59,26 @@ function createViewerButton(link: HTMLDivElement): void {
|
|||||||
let href: string
|
let href: string
|
||||||
if (isLogged.value && sequenceInformation.username === userName.value) {
|
if (isLogged.value && sequenceInformation.username === userName.value) {
|
||||||
href = `${window.location.origin}/sequence/${sequenceInformation.sequenceId}?currentPic=${e.detail.picId}`
|
href = `${window.location.origin}/sequence/${sequenceInformation.sequenceId}?currentPic=${e.detail.picId}`
|
||||||
link.innerHTML = createSequenceLink(
|
link.innerHTML = `<div>
|
||||||
href,
|
${createFullScreenButton()}
|
||||||
t('pages.home.sequence_title')
|
${createSequenceLink(
|
||||||
)
|
href,
|
||||||
|
t('pages.home.sequence_title')
|
||||||
|
)}
|
||||||
|
</div>`
|
||||||
sequenceStore.addSequence(e.detail.picId)
|
sequenceStore.addSequence(e.detail.picId)
|
||||||
} else {
|
} else {
|
||||||
href = t('pages.home.report_mail', {
|
href = t('pages.home.report_mail', {
|
||||||
picId: e.detail.picId,
|
picId: e.detail.picId,
|
||||||
link: createUrlLink(e.detail.picId)
|
link: createUrlLink(e.detail.picId)
|
||||||
})
|
})
|
||||||
link.innerHTML = createLink(href, t('pages.home.report_button_text'))
|
link.innerHTML = `<div>
|
||||||
|
${createFullScreenButton()}
|
||||||
|
${createLink(
|
||||||
|
href,
|
||||||
|
t('pages.home.report_button_text')
|
||||||
|
)}
|
||||||
|
</div>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -142,8 +154,7 @@ async function setupViewerMap(tiles: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
async function setupMap(tiles: string): Promise<void> {
|
async function setupMap(tiles: string): Promise<void> {
|
||||||
let paramsMap: MapInterface
|
let paramsMap: MapInterface
|
||||||
paramsMap = { minZoom: 7 }
|
paramsMap = { users: [props.userId], minZoom: 7 }
|
||||||
//virer
|
|
||||||
if (tiles && tiles.length) {
|
if (tiles && tiles.length) {
|
||||||
const style = tiles.includes('wxs.ign.fr') ? await getIgnTiles() : tiles
|
const style = tiles.includes('wxs.ign.fr') ? await getIgnTiles() : tiles
|
||||||
paramsMap = {
|
paramsMap = {
|
||||||
@@ -162,7 +173,6 @@ async function setupMap(tiles: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
viewer.value.addEventListener('ready', () => {
|
viewer.value.addEventListener('ready', () => {
|
||||||
viewer.value.setFilters({ user: props.userId }, true)
|
|
||||||
viewer.value.fitBounds(bbox, {
|
viewer.value.fitBounds(bbox, {
|
||||||
padding: { top: 70, bottom: 70, left: 70, right: 70 },
|
padding: { top: 70, bottom: 70, left: 70, right: 70 },
|
||||||
maxZoom: 14,
|
maxZoom: 14,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
"sequence_published": "Published",
|
"sequence_published": "Published",
|
||||||
"sequence_waiting": "Still processing",
|
"sequence_waiting": "Still processing",
|
||||||
"sequence_hidden": "Hidden",
|
"sequence_hidden": "Hidden",
|
||||||
|
"sequence_form_title": "Edit the title",
|
||||||
"hide_sequence_tooltip": "Hide this sequences",
|
"hide_sequence_tooltip": "Hide this sequences",
|
||||||
"back_button": "Back to my sequence list",
|
"back_button": "Back to my sequence list",
|
||||||
"delete_sequence_tooltip": "Permanently delete this sequence",
|
"delete_sequence_tooltip": "Permanently delete this sequence",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"general": {
|
"general": {
|
||||||
"title": "Instance Panoramax",
|
"title": "DESC Panoramax {instanceName}: photo-cartographier les territoires",
|
||||||
|
"description": "DESC L'instance Panoramax {instanceName} permet la publication de photo de terrain pour cartographier le territoire. Panoramax favorise la réutilisation des photos pour de nombreux cas d'usages.",
|
||||||
"meta": {
|
"meta": {
|
||||||
"title": "Instance Panoramax",
|
"title": "Instance Panoramax",
|
||||||
"description": "Panoramax, l’alternative libre pour photo-cartographier les territoires"
|
"description": "Panoramax, l’alternative libre pour photo-cartographier les territoires"
|
||||||
@@ -50,6 +51,7 @@
|
|||||||
"sequence_published": "Publiée",
|
"sequence_published": "Publiée",
|
||||||
"sequence_waiting": "En cours de publication",
|
"sequence_waiting": "En cours de publication",
|
||||||
"sequence_hidden": "Masquée",
|
"sequence_hidden": "Masquée",
|
||||||
|
"sequence_form_title": "Modifier le titre",
|
||||||
"hide_sequence_tooltip": "Masque la séquence sur la carte",
|
"hide_sequence_tooltip": "Masque la séquence sur la carte",
|
||||||
"back_button": "Retourner à la liste de mes séquences",
|
"back_button": "Retourner à la liste de mes séquences",
|
||||||
"delete_sequence_tooltip": "Supprime définitivement la séquence",
|
"delete_sequence_tooltip": "Supprime définitivement la séquence",
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
"sequence_published": "Közzétéve",
|
"sequence_published": "Közzétéve",
|
||||||
"sequence_waiting": "Feldolgozás alatt",
|
"sequence_waiting": "Feldolgozás alatt",
|
||||||
"sequence_hidden": "Rejtett",
|
"sequence_hidden": "Rejtett",
|
||||||
|
"sequence_form_title": "Szerkessze a címet",
|
||||||
"hide_sequence_tooltip": "A sorozat elrejtése",
|
"hide_sequence_tooltip": "A sorozat elrejtése",
|
||||||
"back_button": "Vissza a sorozatlistámhoz",
|
"back_button": "Vissza a sorozatlistámhoz",
|
||||||
"delete_sequence_tooltip": "A sorozat végleges törlése",
|
"delete_sequence_tooltip": "A sorozat végleges törlése",
|
||||||
|
|||||||
22
src/main.ts
22
src/main.ts
@@ -1,10 +1,10 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
import VueMatomo from 'vue-matomo'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import VueAxios from 'vue-axios'
|
import VueAxios from 'vue-axios'
|
||||||
import { createMetaManager } from 'vue-meta'
|
|
||||||
import { VueDraggableResizable } from 'vue-draggable-resizable-vue3'
|
import { VueDraggableResizable } from 'vue-draggable-resizable-vue3'
|
||||||
import VCalendar from 'v-calendar'
|
import VCalendar from 'v-calendar'
|
||||||
import 'v-calendar/style.css'
|
import 'v-calendar/style.css'
|
||||||
@@ -17,8 +17,17 @@ import 'bootstrap/dist/css/bootstrap.css'
|
|||||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||||
import 'geovisio/build/index.css'
|
import 'geovisio/build/index.css'
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
_paq: any[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
axios.defaults.baseURL = import.meta.env.VITE_API_URL
|
axios.defaults.baseURL = import.meta.env.VITE_API_URL
|
||||||
axios.defaults.withCredentials = true
|
axios.defaults.withCredentials = true
|
||||||
|
const matomoHost = import.meta.env.VITE_MATOMO_HOST
|
||||||
|
const matomoSiteId = import.meta.env.VITE_MATOMO_SITE_ID
|
||||||
|
const matomoExist = matomoHost && matomoSiteId
|
||||||
|
|
||||||
const i18n = createI18n({
|
const i18n = createI18n({
|
||||||
locale: navigator.language.split('-')[0],
|
locale: navigator.language.split('-')[0],
|
||||||
@@ -34,13 +43,20 @@ const i18n = createI18n({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
app.use(i18n)
|
app.use(i18n)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.use(VueAxios, axios)
|
app.use(VueAxios, axios)
|
||||||
app.provide('axios', app.config.globalProperties.axios)
|
app.provide('axios', app.config.globalProperties.axios)
|
||||||
app.use(createMetaManager())
|
|
||||||
app.use(VueDraggableResizable)
|
app.use(VueDraggableResizable)
|
||||||
app.use(VCalendar)
|
app.use(VCalendar)
|
||||||
|
if (matomoExist) {
|
||||||
|
app.use(VueMatomo, {
|
||||||
|
host: matomoHost,
|
||||||
|
siteId: matomoExist
|
||||||
|
})
|
||||||
|
}
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
if (matomoExist) {
|
||||||
|
window._paq.push(['trackPageView']) // Pour suivre les visites sur vos pages
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
hasASessionCookieDecoded
|
hasASessionCookieDecoded
|
||||||
} from '../../utils/auth'
|
} from '../../utils/auth'
|
||||||
import { img } from '../../utils/image'
|
import { img } from '../../utils/image'
|
||||||
import { title } from '../../utils/index'
|
|
||||||
import { useCookies } from 'vue3-cookies'
|
import { useCookies } from 'vue3-cookies'
|
||||||
vi.mock('vue3-cookies', () => {
|
vi.mock('vue3-cookies', () => {
|
||||||
const mockCookies = {
|
const mockCookies = {
|
||||||
@@ -185,19 +184,6 @@ describe('img', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('title', () => {
|
|
||||||
it('should return the formated title with instance name', () => {
|
|
||||||
import.meta.env.VITE_INSTANCE_NAME = 'my instance'
|
|
||||||
const myTitle = 'my title'
|
|
||||||
expect(title(myTitle)).toEqual('my title my instance')
|
|
||||||
})
|
|
||||||
it('should return the formated title without instance name', () => {
|
|
||||||
import.meta.env.VITE_INSTANCE_NAME = ''
|
|
||||||
const myTitle = 'my title'
|
|
||||||
expect(title(myTitle)).toEqual('my title')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sortByName', () => {
|
describe('sortByName', () => {
|
||||||
it('should return the the list sorted by name', () => {
|
it('should return the the list sorted by name', () => {
|
||||||
const list1 = [
|
const list1 = [
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
export function title(title: string): string {
|
|
||||||
const instanceName = import.meta.env.VITE_INSTANCE_NAME
|
|
||||||
if (instanceName) return `${title} ${instanceName}`
|
|
||||||
return title
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createUrlLink(picId: string): string {
|
export function createUrlLink(picId: string): string {
|
||||||
return encodeURIComponent(`${window.location.origin}/#focus=pic&pic=${picId}`)
|
return encodeURIComponent(`${window.location.origin}/#focus=pic&pic=${picId}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,29 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
async function getIgnTiles(): Promise<object> {
|
async function getIgnTiles(): Promise<object | string> {
|
||||||
const { data } = await axios.get(
|
try {
|
||||||
'https://wxs.ign.fr/essentiels/static/vectorTiles/styles/PLAN.IGN/attenue.json'
|
const { data } = await axios.get(
|
||||||
)
|
'https://wxs.ign.fr/essentiels/static/vectorTiles/styles/PLAN.IGN/attenue.json'
|
||||||
data.sources.plan_ign.scheme = 'xyz'
|
)
|
||||||
data.sources.plan_ign.attribution = 'Données cartographiques : © IGN'
|
data.sources.plan_ign.scheme = 'xyz'
|
||||||
const objIndex = data.layers.findIndex(
|
data.sources.plan_ign.attribution = 'Données cartographiques : © IGN'
|
||||||
(el: { id: string }) => el.id === 'toponyme - parcellaire - adresse'
|
const objIndex = data.layers.findIndex(
|
||||||
)
|
(el: { id: string }) => el.id === 'toponyme - parcellaire - adresse'
|
||||||
data.layers[objIndex].layout = {
|
)
|
||||||
...data.layers[objIndex].layout,
|
data.layers[objIndex].layout = {
|
||||||
'text-field': ['concat', ['get', 'numero'], ['get', 'indice_de_repetition']]
|
...data.layers[objIndex].layout,
|
||||||
|
'text-field': [
|
||||||
|
'concat',
|
||||||
|
['get', 'numero'],
|
||||||
|
['get', 'indice_de_repetition']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
// Patch tms scheme to xyz to make it compatible for Maplibre GL JS / Mapbox GL JS
|
||||||
|
// Patch num_repetition
|
||||||
|
return data
|
||||||
|
} catch (error) {
|
||||||
|
return 'https://tile-vect.openstreetmap.fr/styles/basic/style.json'
|
||||||
}
|
}
|
||||||
// Patch tms scheme to xyz to make it compatible for Maplibre GL JS / Mapbox GL JS
|
|
||||||
// Patch num_repetition
|
|
||||||
return data
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getIgnTiles }
|
export { getIgnTiles }
|
||||||
|
|||||||
@@ -1,68 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<main :class="['entry-page', { 'full-viewer': isFull }]">
|
<main id="homePage" class="entry-page">
|
||||||
<section ref="sectionRef" class="entry-section">
|
<section class="entry-section">
|
||||||
<Viewer ref="viewerRef">
|
<Viewer ref="viewerRef"> </Viewer>
|
||||||
<template v-slot:fullscreen>
|
|
||||||
<div class="fullscreen-button">
|
|
||||||
<Button
|
|
||||||
class="desktop"
|
|
||||||
:text="buttonText"
|
|
||||||
look="button-border--black"
|
|
||||||
:icon="isFull ? 'bi bi-fullscreen-exit' : 'bi bi-fullscreen'"
|
|
||||||
@trigger="fullBrowser"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
class="mobile"
|
|
||||||
look="button--rounded no-text"
|
|
||||||
:icon="isFull ? 'bi bi-fullscreen-exit' : 'bi bi-fullscreen'"
|
|
||||||
@trigger="fullscreen"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</Viewer>
|
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
|
||||||
import Viewer from '@/components/Viewer.vue'
|
import Viewer from '@/components/Viewer.vue'
|
||||||
import Button from '@/components/Button.vue'
|
|
||||||
import type ViewerType from '@/components/Viewer.vue'
|
import type ViewerType from '@/components/Viewer.vue'
|
||||||
import type { ExtendedHtmlEl } from '@/views/interfaces/HomeView'
|
|
||||||
import { toggleFullscreen } from '@/views/utils/home'
|
|
||||||
const { t } = useI18n()
|
|
||||||
const viewerRef = ref<InstanceType<typeof ViewerType>>()
|
const viewerRef = ref<InstanceType<typeof ViewerType>>()
|
||||||
const sectionRef = ref<HTMLDivElement>()
|
|
||||||
const isFull = ref<boolean>(false)
|
|
||||||
|
|
||||||
const buttonText = computed<string>(() => {
|
|
||||||
if (isFull.value) return t('pages.home.close_fullscreen')
|
|
||||||
return t('pages.home.open_fullscreen')
|
|
||||||
})
|
|
||||||
function fullscreen() {
|
|
||||||
if (sectionRef.value) {
|
|
||||||
const elem = sectionRef.value as ExtendedHtmlEl
|
|
||||||
toggleFullscreen(elem)
|
|
||||||
isFull.value = !isFull.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function fullBrowser() {
|
|
||||||
const header = document.getElementById('navHeader')
|
|
||||||
const footer = document.getElementById('navFooter')
|
|
||||||
if (header) {
|
|
||||||
const isHiddenHeader = header.classList.contains('hidden')
|
|
||||||
if (isHiddenHeader) header.classList.remove('hidden')
|
|
||||||
else header.classList.add('hidden')
|
|
||||||
}
|
|
||||||
if (footer) {
|
|
||||||
const isHiddenHeader = footer.classList.contains('hidden')
|
|
||||||
if (isHiddenHeader) footer.classList.remove('hidden')
|
|
||||||
else footer.classList.add('hidden')
|
|
||||||
}
|
|
||||||
isFull.value = !isFull.value
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.entry-page {
|
.entry-page {
|
||||||
@@ -75,13 +23,6 @@ function fullBrowser() {
|
|||||||
.mobile {
|
.mobile {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.fullscreen-button {
|
|
||||||
position: absolute;
|
|
||||||
bottom: toRem(1);
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.focus-pic,
|
.focus-pic,
|
||||||
.logged .entry-section {
|
.logged .entry-section {
|
||||||
height: calc(100vh - #{toRem(8)});
|
height: calc(100vh - #{toRem(8)});
|
||||||
@@ -108,12 +49,6 @@ function fullBrowser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (max-width: toRem(50)) {
|
@media (max-width: toRem(50)) {
|
||||||
.fullscreen-button {
|
|
||||||
left: initial;
|
|
||||||
transform: initial;
|
|
||||||
right: toRem(1.3);
|
|
||||||
top: toRem(16);
|
|
||||||
}
|
|
||||||
.mobile {
|
.mobile {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,25 +25,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="menu-top">
|
<div class="menu-top">
|
||||||
<div class="header-menu">
|
<div class="header-menu">
|
||||||
|
<div class="wrapper-title">
|
||||||
|
<span :class="[sequence.status, 'sequence-status']">{{
|
||||||
|
sequenceStatus
|
||||||
|
}}</span>
|
||||||
|
<div @click.stop class="entry-edit-text">
|
||||||
|
<EditText
|
||||||
|
:default-text="sequence.title"
|
||||||
|
:is-loading="isLoadingTitle"
|
||||||
|
:form-title="$t('pages.sequence.sequence_form_title')"
|
||||||
|
@triggerNewText="setNewSequenceTitle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
data-bs-target="#collapseTarget"
|
data-bs-target="#collapseTarget"
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
class="button-collapse"
|
class="button-collapse"
|
||||||
@click="toggleMenu"
|
@click="toggleMenu"
|
||||||
>
|
>
|
||||||
<div class="wrapper-title">
|
|
||||||
<span :class="[sequence.status, 'sequence-status']">{{
|
|
||||||
sequenceStatus
|
|
||||||
}}</span>
|
|
||||||
<h1 class="title desktop">
|
|
||||||
{{ sequence.title }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<i :class="headerPanelIsOpen ? 'bi bi-dash' : 'bi bi-plus'"></i>
|
<i :class="headerPanelIsOpen ? 'bi bi-dash' : 'bi bi-plus'"></i>
|
||||||
</button>
|
</button>
|
||||||
<h1 class="title responsive">
|
|
||||||
{{ sequence.title }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="isSequenceOwner" class="wrapper-button">
|
<div v-if="isSequenceOwner" class="wrapper-button">
|
||||||
<Button
|
<Button
|
||||||
@@ -211,6 +213,7 @@ import Pagination from '@/components/Pagination.vue'
|
|||||||
import InputCheckbox from '@/components/InputCheckbox.vue'
|
import InputCheckbox from '@/components/InputCheckbox.vue'
|
||||||
import Loader from '@/components/Loader.vue'
|
import Loader from '@/components/Loader.vue'
|
||||||
import ImageItem from '@/components/ImageItem.vue'
|
import ImageItem from '@/components/ImageItem.vue'
|
||||||
|
import EditText from '@/components/EditText.vue'
|
||||||
import Viewer from '@/components/Viewer.vue'
|
import Viewer from '@/components/Viewer.vue'
|
||||||
import type ViewerType from '@/components/Viewer.vue'
|
import type ViewerType from '@/components/Viewer.vue'
|
||||||
import { durationCalc, formatDate } from '@/utils/dates'
|
import { durationCalc, formatDate } from '@/utils/dates'
|
||||||
@@ -254,6 +257,7 @@ let headerPanelIsOpen = ref<boolean>(true)
|
|||||||
let isShiftPressed = ref<boolean>(false)
|
let isShiftPressed = ref<boolean>(false)
|
||||||
let itemSelected = ref<string>('')
|
let itemSelected = ref<string>('')
|
||||||
let isLoading = ref<boolean>(false)
|
let isLoading = ref<boolean>(false)
|
||||||
|
let isLoadingTitle = ref<boolean>(false)
|
||||||
const collapseMenu = ref<HTMLDivElement>()
|
const collapseMenu = ref<HTMLDivElement>()
|
||||||
const deleteAll = ref<HTMLDivElement>()
|
const deleteAll = ref<HTMLDivElement>()
|
||||||
const menuHeight = ref<string>()
|
const menuHeight = ref<string>()
|
||||||
@@ -321,7 +325,15 @@ watchEffect(async () => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
async function setNewSequenceTitle(value: string | null): Promise<void> {
|
||||||
|
isLoadingTitle.value = true
|
||||||
|
if (value && value.length > 0) {
|
||||||
|
await patchACollection(route.params.id, { title: value })
|
||||||
|
const fetchCollectionInfo = await fetchCollection(route.params.id)
|
||||||
|
formatSequenceFetched(fetchCollectionInfo.data)
|
||||||
|
isLoadingTitle.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
function getCurrentPicId(id: string): string {
|
function getCurrentPicId(id: string): string {
|
||||||
const parseParams = new URLSearchParams(window.location.search)
|
const parseParams = new URLSearchParams(window.location.search)
|
||||||
const pict = parseParams.get('currentPic')
|
const pict = parseParams.get('currentPic')
|
||||||
@@ -442,7 +454,7 @@ async function patchCollection(): Promise<void> {
|
|||||||
let visible
|
let visible
|
||||||
if (sequence.value?.status === 'ready') visible = 'false'
|
if (sequence.value?.status === 'ready') visible = 'false'
|
||||||
else visible = 'true'
|
else visible = 'true'
|
||||||
await patchACollection(route.params.id, visible)
|
await patchACollection(route.params.id, { visible: visible })
|
||||||
const fetchCollectionInfo = await fetchCollection(route.params.id)
|
const fetchCollectionInfo = await fetchCollection(route.params.id)
|
||||||
formatSequenceFetched(fetchCollectionInfo.data)
|
formatSequenceFetched(fetchCollectionInfo.data)
|
||||||
if (visible === 'false') hiddeAllPictures()
|
if (visible === 'false') hiddeAllPictures()
|
||||||
@@ -641,8 +653,7 @@ async function patchOrDeleteCollectionItems(
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.wrapper-title {
|
.wrapper-title {
|
||||||
display: flex;
|
min-width: 60%;
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
.wrapper-button {
|
.wrapper-button {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -682,6 +693,7 @@ async function patchOrDeleteCollectionItems(
|
|||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
@include text(h4);
|
@include text(h4);
|
||||||
|
text-align: left;
|
||||||
color: var(--grey-dark);
|
color: var(--grey-dark);
|
||||||
margin-right: toRem(1);
|
margin-right: toRem(1);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@@ -690,8 +702,9 @@ async function patchOrDeleteCollectionItems(
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.menu-top {
|
.menu-top {
|
||||||
|
position: relative;
|
||||||
margin: toRem(2) toRem(2) 0;
|
margin: toRem(2) toRem(2) 0;
|
||||||
padding: toRem(1) toRem(2);
|
padding: toRem(2.5) toRem(2) toRem(1);
|
||||||
border: toRem(0.1) solid var(--grey);
|
border: toRem(0.1) solid var(--grey);
|
||||||
border-radius: toRem(0.5);
|
border-radius: toRem(0.5);
|
||||||
background-color: var(--blue-semi);
|
background-color: var(--blue-semi);
|
||||||
@@ -699,12 +712,16 @@ async function patchOrDeleteCollectionItems(
|
|||||||
.header-menu {
|
.header-menu {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin-bottom: toRem(1);
|
||||||
}
|
}
|
||||||
.sequence-status {
|
.sequence-status {
|
||||||
@include text(xs-r-regular);
|
position: absolute;
|
||||||
border-radius: toRem(1);
|
top: 0;
|
||||||
padding: toRem(0.5) toRem(1);
|
left: 0;
|
||||||
margin-right: toRem(1);
|
z-index: 1;
|
||||||
|
@include text(xss-regular);
|
||||||
|
border-radius: toRem(0.4);
|
||||||
|
padding: toRem(0.3) toRem(0.8);
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
&.ready {
|
&.ready {
|
||||||
background-color: var(--green);
|
background-color: var(--green);
|
||||||
@@ -723,11 +740,9 @@ async function patchOrDeleteCollectionItems(
|
|||||||
border: none;
|
border: none;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
position: absolute;
|
||||||
align-items: center;
|
top: 0;
|
||||||
justify-content: space-between;
|
right: toRem(2);
|
||||||
width: 100%;
|
|
||||||
margin-bottom: toRem(1);
|
|
||||||
}
|
}
|
||||||
.bi-plus,
|
.bi-plus,
|
||||||
.bi-dash {
|
.bi-dash {
|
||||||
@@ -795,9 +810,8 @@ async function patchOrDeleteCollectionItems(
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
@media (max-width: toRem(102.4)) {
|
@media (max-width: toRem(102.4)) {
|
||||||
.header-menu {
|
.wrapper-title {
|
||||||
flex-direction: column;
|
width: 90%;
|
||||||
align-items: flex-start;
|
|
||||||
}
|
}
|
||||||
.block-collapse {
|
.block-collapse {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -846,9 +860,10 @@ async function patchOrDeleteCollectionItems(
|
|||||||
margin-bottom: toRem(1);
|
margin-bottom: toRem(1);
|
||||||
}
|
}
|
||||||
.button-collapse {
|
.button-collapse {
|
||||||
width: 100%;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
top: toRem(-1);
|
||||||
|
right: 0;
|
||||||
}
|
}
|
||||||
.photo-item {
|
.photo-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -905,6 +920,7 @@ async function patchOrDeleteCollectionItems(
|
|||||||
}
|
}
|
||||||
.menu-top {
|
.menu-top {
|
||||||
width: 0vw;
|
width: 0vw;
|
||||||
|
padding: toRem(2.5) toRem(1);
|
||||||
}
|
}
|
||||||
.button-close {
|
.button-close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -920,9 +936,6 @@ async function patchOrDeleteCollectionItems(
|
|||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
border: toRem(0.1) solid var(--black);
|
border: toRem(0.1) solid var(--black);
|
||||||
}
|
}
|
||||||
.menu-top {
|
|
||||||
padding: toRem(1);
|
|
||||||
}
|
|
||||||
.menu-is-open {
|
.menu-is-open {
|
||||||
.menu-right {
|
.menu-right {
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
|
|||||||
@@ -59,7 +59,9 @@
|
|||||||
{{ $t('pages.sequences.title') }}
|
{{ $t('pages.sequences.title') }}
|
||||||
</h1>
|
</h1>
|
||||||
<Button
|
<Button
|
||||||
v-if="filterDate.start || filterDate.end || sortDate.sortBy"
|
v-if="
|
||||||
|
filterDate.start || filterDate.end || sortDate.sortBy || filterBbox
|
||||||
|
"
|
||||||
look="button-border--black"
|
look="button-border--black"
|
||||||
:text="$t('pages.sequences.reset_filter_button')"
|
:text="$t('pages.sequences.reset_filter_button')"
|
||||||
@trigger="resetAllFilter"
|
@trigger="resetAllFilter"
|
||||||
@@ -121,7 +123,7 @@
|
|||||||
<li
|
<li
|
||||||
v-if="userSequences.length"
|
v-if="userSequences.length"
|
||||||
v-for="item in userSequences"
|
v-for="item in userSequences"
|
||||||
class="sequence-item"
|
:class="['sequence-item', { 'sequence-selected': item.id === seqId }]"
|
||||||
@mouseover="goToSequence(item)"
|
@mouseover="goToSequence(item)"
|
||||||
>
|
>
|
||||||
<router-link
|
<router-link
|
||||||
@@ -130,7 +132,6 @@
|
|||||||
name: 'sequence',
|
name: 'sequence',
|
||||||
params: { id: item.id }
|
params: { id: item.id }
|
||||||
}"
|
}"
|
||||||
@mouseover.stop
|
|
||||||
>
|
>
|
||||||
<div class="wrapper-thumb">
|
<div class="wrapper-thumb">
|
||||||
<img
|
<img
|
||||||
@@ -334,6 +335,7 @@ const headerLisPos = ref<PositionInterface | null>(null)
|
|||||||
async function resetAllFilter(): Promise<void> {
|
async function resetAllFilter(): Promise<void> {
|
||||||
filterDate.value = { start: null, end: null, type: '' }
|
filterDate.value = { start: null, end: null, type: '' }
|
||||||
sortDate.value = { sortBy: null }
|
sortDate.value = { sortBy: null }
|
||||||
|
filterBbox.value = null
|
||||||
formatUri()
|
formatUri()
|
||||||
await updateSequence(uri.value)
|
await updateSequence(uri.value)
|
||||||
}
|
}
|
||||||
@@ -388,7 +390,7 @@ async function patchCollection(sequence: SequenceLinkInterface): Promise<void> {
|
|||||||
let visible
|
let visible
|
||||||
if (sequence['geovisio:status'] === 'ready') visible = 'false'
|
if (sequence['geovisio:status'] === 'ready') visible = 'false'
|
||||||
else visible = 'true'
|
else visible = 'true'
|
||||||
await patchACollection(sequence.id, visible)
|
await patchACollection(sequence.id, { visible: visible })
|
||||||
await fetchAndFormatSequence()
|
await fetchAndFormatSequence()
|
||||||
if (viewerRef.value) viewerRef.value.viewer.reloadVectorTiles()
|
if (viewerRef.value) viewerRef.value.viewer.reloadVectorTiles()
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@@ -484,8 +486,6 @@ function goToSequence(sequence: SequenceLinkInterface): void {
|
|||||||
sequence.extent.spatial.bbox[0][0],
|
sequence.extent.spatial.bbox[0][0],
|
||||||
sequence.extent.spatial.bbox[0][1]
|
sequence.extent.spatial.bbox[0][1]
|
||||||
],
|
],
|
||||||
zoom: 10,
|
|
||||||
//peut être à virer
|
|
||||||
duration: 0
|
duration: 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -575,7 +575,7 @@ async function updateFilters(value: {
|
|||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
if (viewerRef.value && viewerRef.value.viewer) {
|
if (viewerRef.value && viewerRef.value.viewer) {
|
||||||
viewerRef.value.viewer.addEventListener(
|
viewerRef.value.viewer.addEventListener(
|
||||||
'hover',
|
'select',
|
||||||
(e: { detail: { seqId: string } }) => {
|
(e: { detail: { seqId: string } }) => {
|
||||||
if (seqId.value === e.detail.seqId) return
|
if (seqId.value === e.detail.seqId) return
|
||||||
seqId.value = e.detail.seqId
|
seqId.value = e.detail.seqId
|
||||||
@@ -681,9 +681,9 @@ watchEffect(() => {
|
|||||||
&:nth-child(2n) {
|
&:nth-child(2n) {
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover,
|
||||||
|
&.sequence-selected {
|
||||||
background-color: var(--blue-semi);
|
background-color: var(--blue-semi);
|
||||||
color: var(--white);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.wrapper-button {
|
.wrapper-button {
|
||||||
|
|||||||
@@ -39,12 +39,14 @@
|
|||||||
<p class="import-text">
|
<p class="import-text">
|
||||||
{{ $t('pages.upload.description_title_sequence') }}
|
{{ $t('pages.upload.description_title_sequence') }}
|
||||||
</p>
|
</p>
|
||||||
<EditText
|
<div class="wrapper-edit-text">
|
||||||
:default-text="newSequenceTitle || sequenceTitle"
|
<EditText
|
||||||
:is-loading="isLoading"
|
:default-text="newSequenceTitle || sequenceTitle"
|
||||||
:is-loaded="isLoaded"
|
:is-loading="isLoading"
|
||||||
@triggerNewText="setNewSequenceTitle"
|
:is-loaded="isLoaded"
|
||||||
/>
|
@triggerNewText="setNewSequenceTitle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<form>
|
<form>
|
||||||
<div class="wrapper-form">
|
<div class="wrapper-form">
|
||||||
<InputUpload
|
<InputUpload
|
||||||
@@ -346,6 +348,9 @@ h3 {
|
|||||||
.import-text {
|
.import-text {
|
||||||
@include text(m-r-regular);
|
@include text(m-r-regular);
|
||||||
}
|
}
|
||||||
|
.wrapper-edit-text {
|
||||||
|
margin-bottom: toRem(2);
|
||||||
|
}
|
||||||
.entry-license {
|
.entry-license {
|
||||||
margin-bottom: toRem(1);
|
margin-bottom: toRem(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
export interface MapInterface {
|
export interface MapInterface {
|
||||||
startWide?: boolean
|
startWide?: boolean
|
||||||
|
users?: string[]
|
||||||
maxZoom?: number
|
maxZoom?: number
|
||||||
minZoom?: number
|
minZoom?: number
|
||||||
style?: object | string
|
style?: object | string
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ function deleteACollection(collectionId: string | string[]): Promise<unknown> {
|
|||||||
|
|
||||||
function patchACollection(
|
function patchACollection(
|
||||||
collectionId: string | string[],
|
collectionId: string | string[],
|
||||||
visible: string
|
fieldObject: object
|
||||||
): Promise<unknown> {
|
): Promise<unknown> {
|
||||||
return axios.patch(`api/collections/${collectionId}`, { visible: visible })
|
return axios.patch(`api/collections/${collectionId}`, fieldObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteACollectionItem(
|
function deleteACollectionItem(
|
||||||
|
|||||||
BIN
static/meta-img.jpg
Normal file
BIN
static/meta-img.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
@@ -1,33 +1,51 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig, loadEnv } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import eslintPlugin from 'vite-plugin-eslint'
|
import eslintPlugin from 'vite-plugin-eslint'
|
||||||
|
import { createHtmlPlugin } from 'vite-plugin-html'
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default ({ mode }) => {
|
||||||
server: {
|
process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }
|
||||||
host: true,
|
return defineConfig({
|
||||||
port: 5173,
|
server: {
|
||||||
strictPort: true,
|
host: true,
|
||||||
hmr: {
|
port: 5173,
|
||||||
clientPort: 5173,
|
strictPort: true,
|
||||||
overlay: false
|
hmr: {
|
||||||
}
|
clientPort: 5173,
|
||||||
},
|
overlay: false
|
||||||
base: '/',
|
}
|
||||||
plugins: [vue(), eslintPlugin()],
|
},
|
||||||
css: {
|
base: '/',
|
||||||
preprocessorOptions: {
|
plugins: [
|
||||||
scss: {
|
vue(),
|
||||||
additionalData:
|
eslintPlugin(),
|
||||||
'@import "@/assets/font-size.scss"; @import "@/assets/rem-calc.scss";'
|
createHtmlPlugin({
|
||||||
|
minify: true,
|
||||||
|
/**
|
||||||
|
* Data that needs to be injected into the index.html ejs template
|
||||||
|
*/
|
||||||
|
inject: {
|
||||||
|
data: {
|
||||||
|
instanceName: process.env.VITE_INSTANCE_NAME,
|
||||||
|
frontUrl: process.env.VITE_FRONT_URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
css: {
|
||||||
|
preprocessorOptions: {
|
||||||
|
scss: {
|
||||||
|
additionalData:
|
||||||
|
'@import "@/assets/font-size.scss"; @import "@/assets/rem-calc.scss";'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||||
|
'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
resolve: {
|
}
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
||||||
'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
1
vue-matomo.d.ts
vendored
Normal file
1
vue-matomo.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
declare module 'vue-matomo'
|
||||||
Reference in New Issue
Block a user