forked from Ivasoft/geovisio-website
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
542eefac03 | ||
|
|
edd5d207a1 | ||
|
|
f99d19a13a | ||
|
|
448cd1af41 | ||
|
|
81cbe90d01 |
21
CHANGELOG.md
21
CHANGELOG.md
@@ -7,6 +7,24 @@ 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.
|
||||
|
||||
## [2.2.3] - 2023-11-03
|
||||
|
||||
### Added
|
||||
|
||||
- Add translation based on the browser language (only trad for FR and EN for now)
|
||||
|
||||
### Changed
|
||||
|
||||
- Page My Sequences, add the possibility to select a sequence in the list with the map :
|
||||
- the user can only see his sequences on the list
|
||||
- display the selected sequence in blue in the map
|
||||
- display a thumbnail the hovered sequence
|
||||
- hover the sequence selected in the map on the list
|
||||
|
||||
- add some test e2e
|
||||
- maj viewer Geovisio version to 2.2.1
|
||||
- fix some CSS
|
||||
|
||||
## [2.2.2] - 2023-10-16
|
||||
|
||||
### Changed
|
||||
@@ -107,7 +125,8 @@ 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
|
||||
- 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.2.2...develop
|
||||
[unreleased]: https://gitlab.com/geovisio/website/-/compare/2.2.3...develop
|
||||
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.2...2.2.3
|
||||
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.1...2.2.2
|
||||
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.0...2.2.1
|
||||
[2.2.0]: https://gitlab.com/geovisio/website/-/compare/2.1.3...2.2.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "geovisio-website",
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.3",
|
||||
"engines": {
|
||||
"node": "18.16.0"
|
||||
},
|
||||
@@ -25,7 +25,7 @@
|
||||
"axios": "^1.2.3",
|
||||
"bootstrap": "^5.2.3",
|
||||
"bootstrap-icons": "^1.10.3",
|
||||
"geovisio": "2.2.0",
|
||||
"geovisio": "2.2.1",
|
||||
"moment": "^2.29.4",
|
||||
"pinia": "^2.1.4",
|
||||
"vue": "^3.2.45",
|
||||
|
||||
@@ -5,14 +5,12 @@ import Footer from '@/components/Footer.vue'
|
||||
import { RouterView } from 'vue-router'
|
||||
import { useMeta } from 'vue-meta'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useCookies } from 'vue3-cookies'
|
||||
import { title } from '@/utils/index'
|
||||
import authConfig from './composables/auth'
|
||||
const { authConf } = authConfig()
|
||||
const { t } = useI18n()
|
||||
const { cookies } = useCookies()
|
||||
const route = useRoute()
|
||||
|
||||
let focusMap = ref<string>('focus-map')
|
||||
|
||||
|
||||
@@ -36,9 +36,9 @@ h5 {
|
||||
--grey-dark: #3e3e3e;
|
||||
--blue: #2954e9;
|
||||
--blue-dark: #0a1f69;
|
||||
--blue-geovisio: #34495e;
|
||||
--blue-semi: #d7dffc;
|
||||
--blue-pale: #f2f5ff;
|
||||
--blue-geovisio: #34495e;
|
||||
--beige: #f5f3ec;
|
||||
--yellow: #fec868;
|
||||
--orange: #ff6f00;
|
||||
|
||||
@@ -89,12 +89,31 @@ ul {
|
||||
margin-right: toRem(2);
|
||||
height: toRem(2);
|
||||
}
|
||||
@media (max-width: toRem(76.8)) {
|
||||
.footer {
|
||||
padding: toRem(1);
|
||||
height: toRem(6.5);
|
||||
}
|
||||
.link-list {
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.logo {
|
||||
margin-right: toRem(0.5);
|
||||
height: toRem(1.5);
|
||||
}
|
||||
.link-item {
|
||||
margin-right: toRem(1);
|
||||
margin-bottom: toRem(1);
|
||||
}
|
||||
.link {
|
||||
height: toRem(1.5);
|
||||
}
|
||||
}
|
||||
@media (max-width: toRem(50)) {
|
||||
.title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.footer {
|
||||
padding: toRem(2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -80,16 +80,6 @@ function triggerButton() {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
color: var(--black);
|
||||
font-size: toRem(2.4);
|
||||
margin-right: toRem(1);
|
||||
}
|
||||
.logo {
|
||||
height: inherit;
|
||||
border-radius: toRem(0.5);
|
||||
margin-right: toRem(1);
|
||||
}
|
||||
.button {
|
||||
height: toRem(4);
|
||||
border-radius: toRem(1);
|
||||
@@ -105,6 +95,16 @@ function triggerButton() {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
color: var(--black);
|
||||
font-size: toRem(2.4);
|
||||
margin-right: toRem(1);
|
||||
}
|
||||
.logo {
|
||||
height: inherit;
|
||||
border-radius: toRem(0.5);
|
||||
margin-right: toRem(1);
|
||||
}
|
||||
.text {
|
||||
width: 100%;
|
||||
white-space: break-spaces;
|
||||
@@ -200,10 +200,6 @@ function triggerButton() {
|
||||
}
|
||||
}
|
||||
@media (max-width: toRem(50)) {
|
||||
.default {
|
||||
min-height: toRem(4);
|
||||
min-width: toRem(4);
|
||||
}
|
||||
.icon {
|
||||
margin-right: toRem(0.5);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import type { ViewerInterface } from '@/views/interfaces/common'
|
||||
import type { ViewerInterface, MapInterface } from '@/views/interfaces/common'
|
||||
import { getIgnTiles } from '@/utils/mapAndViewer'
|
||||
import { Viewer, StandaloneMap } from 'geovisio'
|
||||
import { createUrlLink } from '@/utils'
|
||||
@@ -17,7 +17,8 @@ let viewer = ref()
|
||||
const props = defineProps({
|
||||
fetchOptions: { type: Object, default: {} },
|
||||
geovisioViewer: { type: Boolean, default: true },
|
||||
bbox: { type: Array, default: null }
|
||||
bbox: { type: Array, default: null },
|
||||
userId: { type: String, default: '' }
|
||||
})
|
||||
defineExpose({
|
||||
viewer
|
||||
@@ -28,6 +29,7 @@ onMounted(async () => {
|
||||
const zoom = import.meta.env.VITE_ZOOM
|
||||
const center = import.meta.env.VITE_CENTER
|
||||
let paramsViewer: ViewerInterface
|
||||
let paramsMap: MapInterface
|
||||
|
||||
try {
|
||||
if (props.geovisioViewer) {
|
||||
@@ -98,7 +100,7 @@ onMounted(async () => {
|
||||
)
|
||||
}
|
||||
} else {
|
||||
let paramsMap = {}
|
||||
paramsMap = { minZoom: 7 }
|
||||
if (tiles) {
|
||||
const style = tiles.includes('wxs.ign.fr') ? await getIgnTiles() : tiles
|
||||
paramsMap = {
|
||||
@@ -110,9 +112,14 @@ onMounted(async () => {
|
||||
'viewer', // Div ID
|
||||
`${import.meta.env.VITE_API_URL}/api/search`,
|
||||
{
|
||||
...paramsMap
|
||||
...paramsMap,
|
||||
bounds: [props.bbox[0], props.bbox[1], props.bbox[2], props.bbox[3]],
|
||||
zoom: 9
|
||||
}
|
||||
)
|
||||
viewer.value.addEventListener('ready', () => {
|
||||
viewer.value.setFilters({ user: props.userId }, true)
|
||||
})
|
||||
}
|
||||
mapIsLoaded.value = true
|
||||
} catch (err) {
|
||||
|
||||
179
src/locales/en.json
Normal file
179
src/locales/en.json
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"general": {
|
||||
"title": "Panoramax instance",
|
||||
"meta": {
|
||||
"title": "Panoramax instance",
|
||||
"description": "Panoramax, the free alternative to photo-mapping territories"
|
||||
},
|
||||
"header": {
|
||||
"login_text": "Connect",
|
||||
"register_text": "Register",
|
||||
"contribute_text": "Why contribute ?",
|
||||
"my_account": "My account",
|
||||
"upload_text": "+ Share pictures",
|
||||
"sequences_text": "My pictures",
|
||||
"alt_logo": "Instance logo",
|
||||
"alt_photos": "Pictures icon",
|
||||
"alt_information": "User icon",
|
||||
"alt_settings": "Parameters icon",
|
||||
"alt_logout": "Logout icon",
|
||||
"title": "Panoramax",
|
||||
"beta_text": "Beta version",
|
||||
"logout_text": "Logout",
|
||||
"my_information_text": "My details",
|
||||
"my_settings_text": "My parameters",
|
||||
"burger_menu_aria_label_open": "Show menu",
|
||||
"burger_menu_aria_label_closed": "Hide menu"
|
||||
},
|
||||
"footer": {
|
||||
"panoramax_site": "Discover Panoramax",
|
||||
"information_gitlab": "Show source code",
|
||||
"gitlab_logo": "Gitlab logo",
|
||||
"ay11_text": "Accessibility: not compliant"
|
||||
},
|
||||
"error_text": "An error occured",
|
||||
"success_text": "Update done"
|
||||
},
|
||||
"pages": {
|
||||
"home": {
|
||||
"report_mail": "?subject=⚠️ Report on picture {picId}&body=HEllo, %0D%0A%0D%0A Problem on image (keep type of problem reported) : %0D%0A%0D%0A %0D%0A%0D%0A inappropriate content / lack of blurring on an element to be anonymized or blurred for security reasons / overblurring (too much blurring) %0D%0A%0D%0A Link to affected photo : {link} %0D%0A%0D%0A Details of affected elements (especially for blurring problems - what should be blurred or unblurred?) :",
|
||||
"report_button_text": "Report this picture"
|
||||
},
|
||||
"settings": {
|
||||
"title": "My tokens",
|
||||
"setting_tooltip": "Show or hide token"
|
||||
},
|
||||
"sequence": {
|
||||
"sequence_published": "Published",
|
||||
"sequence_waiting": "Still processing",
|
||||
"sequence_hidden": "Hidden",
|
||||
"hide_sequence_tooltip": "Hide this sequences",
|
||||
"delete_sequence_tooltip": "Permanently delete this sequence",
|
||||
"hide_photo_tooltip": "Hide selected pictures",
|
||||
"delete_photo_tooltip": "Permanently delete selected pictures",
|
||||
"confirm_pictures_dialog": "⚠️ Selected photos will be permanently deleted",
|
||||
"confirm_sequence_dialog": "⚠️ This sequence will be permanently deleted",
|
||||
"created": "Uploaded :",
|
||||
"taken": "Shot on :",
|
||||
"duration": "Duration :",
|
||||
"duration_begin": "Start :",
|
||||
"duration_end": "End :",
|
||||
"camera": "Camera :",
|
||||
"button_delete": "Delete",
|
||||
"button_disable": "Hide",
|
||||
"button_enable": "Show",
|
||||
"picture_selected": "{count} picture selected| {count} pictures selected",
|
||||
"hours": "{count} hour| {count} hours",
|
||||
"minutes": "{count} minute| {count} minutes",
|
||||
"seconds": "{count} second| {count} seconds",
|
||||
"select_text": "Select all",
|
||||
"unselect_text": "Deselect all",
|
||||
"select_shift_text": "Select multiple photos with shift",
|
||||
"waiting_process": "Photo in process",
|
||||
"broken": "Photo error processing",
|
||||
"no_image": "No picture in this sequence"
|
||||
},
|
||||
"sequences": {
|
||||
"title": "My sequences",
|
||||
"sequence_name": "Name",
|
||||
"sequence_photos": "Photos",
|
||||
"sequence_date": "Shot on",
|
||||
"sequence_creation": "Upload",
|
||||
"sequence_status": "Status",
|
||||
"sequence_published": "Published",
|
||||
"sequence_waiting": "Still processing",
|
||||
"sequence_hidden": "Hidden",
|
||||
"no_sequences_text": "You have no photos published yet \uD83D\uDE22",
|
||||
"button_upload": "Upload pictures",
|
||||
"sequence_deleted": "The sequence has been deleted"
|
||||
},
|
||||
"share_pictures": {
|
||||
"title": "Why contribute to Panoramax?",
|
||||
"description": "Contributing to Panoramax means participating in the development of a geo-common, a sovereign, free and reusable digital resource. Each geolocalized photo published on Panoramax can be used by anyone for a variety of purposes, for example by a local authority needing to observe the status of its roads, or by a telecoms operator to prepare an intervention.\n\nEach contributor can send his or her image sequences, modify them and consult them, as well as all the views - 360° or not - contributed by the community. The compulsory blurring of faces and license plates is automated on the platform.",
|
||||
"alt_img_map": "Illustration of a woman looking at a map with her geolocated smartphone",
|
||||
"card_photo1": "Places visible from the public highway",
|
||||
"card_photo2": "Photos published in 360° format or not",
|
||||
"card_photo3": "Easily reusable photos",
|
||||
"card_photo4": "A quick and easy image contribution",
|
||||
"card_alt_photo1": "Image of a building",
|
||||
"card_alt_photo2": "Image showing 360-degree ",
|
||||
"card_alt_photo3": "Image showing a map with a pointer",
|
||||
"card_alt_photo4": "Image representing a pointer",
|
||||
"card_description1": "All photos taken from the public highway are accepted, as long as they are geolocated and viewed from the ground.",
|
||||
"card_description2": "360° pictures are not mandatory: photos taken with a smartphone are all that's needed. Dates, locations and jpg format are the only prerequisites.",
|
||||
"card_description3": "All photos easily accessible and reusable without an account: via the website or a standard API (STAC standard).",
|
||||
"card_description4": "Several tools are available to facilitate contributions, including a command line and a web interface.",
|
||||
"upload_subtitle": "Simply upload your images online",
|
||||
"upload_illustration_alt": "Illustration showing online photo uploading",
|
||||
"upload_description": "Panoramax's web application lets you upload all your field photos in JPEG format at the click of a button. No programming skills are required. For larger numbers, however, we recommend using the command-line tool",
|
||||
"upload_button": "+ Upload pictures",
|
||||
"command_line_subtitle": "Command line tool",
|
||||
"comment_install": "Install the geovisio command-line tool",
|
||||
"comment_upload": "LanceStart the image upload command on the chosen folder",
|
||||
"description_terminal": "<a href='https://gitlab.com/geovisio/cli' target='_blank' style='color:black'>The CLI</a> lets you share large volumes of photos. The procedure is simple and requires <a target='_blank' href='https://www.python.org/downloads/' style='color:black'>python (version 3.8 or above)</a>.\n\nThe tool will ask for your login details before importing. Once the pictures have been uploaded, a processing time is required before publication.",
|
||||
"terminal_install": "pip install geovisio_cli",
|
||||
"terminal_text": "geovisio upload --api-url {url} <DOSSIER_PHOTOS>",
|
||||
"button_copy": "Copy",
|
||||
"information_subtitle": "Here, your photos are accessible to all : ",
|
||||
"information_text1": "Automatically blurred in compliance with legislation.",
|
||||
"information_text2": "The uploaded pictures will be published under {word}",
|
||||
"information_text3": "In its original format and resolution for various reuse.",
|
||||
"information_about_title": "Need to access pictures ?",
|
||||
"information_about_description": "An API is available to retrieve all metadata and pictures. <a href='{docLink}' target='_blank' style='color:#0a1f69'>\nFind out more here</a>\nData is also displayed in the form <a href='{docTiles}' target='_blank' style='color:#0a1f69'>of vector tiles</a>",
|
||||
"doc_subtitle": "Need help contributing to Panoramax?",
|
||||
"doc_description": "Panoramax documentation is available from us, and you can access tutorials on the geo-commons forum.",
|
||||
"doc_button": "See the documentation",
|
||||
"doc_illustration_alt": "Illustration of a character with a sheet of documents"
|
||||
},
|
||||
"upload": {
|
||||
"title": "Contribute to the Panoramax project",
|
||||
"description": "For large volumes of pictures, the command line tool is more suitable.",
|
||||
"know_more_button": "Read more",
|
||||
"input_label": "Drag your pictures here or click on ",
|
||||
"import_word": "upload",
|
||||
"import_type": "JPEG format only",
|
||||
"subtitle_import": "Picture upload",
|
||||
"text_import": "Upload your jpg files here. Each picture or series of pictures constitutes a \"sequence\". You can then find them in the \"my pictures\" section and choose to hide, show or delete them.",
|
||||
"subtitle_process": "Upload processing",
|
||||
"uploading_process": "Upload in progress...",
|
||||
"sequence_title": "Sequence ",
|
||||
"import": "Uploads",
|
||||
"upload_pending": "Upload in progress...",
|
||||
"images_count_text": "Pictures uploaded",
|
||||
"no_img_text": "no picture upload so far",
|
||||
"upload_done": "Sequence upload done",
|
||||
"sequence_link": "Show this sequence",
|
||||
"pictures_error": "{count} picture could not be uploaded| {count} pictures could not be uploaded",
|
||||
"sequence_loading_information": "Once uploaded, the sequence will be processed then published on Panoramax (usually within a couple of minutes).",
|
||||
"sequence_loaded_information": "The sequences has been uploaded and is under processing. It should be publicly available on Panoramax within a couple of minutes.",
|
||||
"leave_message": "⚠️ WARNING, the download will be interrupted if you leave the page before the end.",
|
||||
"error_button": "Show errors",
|
||||
"modal_error_title": "Pictures in error"
|
||||
},
|
||||
"ay11": {
|
||||
"title": "Déclaration d’accessibilité",
|
||||
"date": "Établie le 18 septembre 2023.",
|
||||
"introduction": "IGN s’engage à rendre son service accessible, conformément à l’article 47 de la loi n° 2005-102 du 11 février 2005.\n Cette déclaration d’accessibilité s’applique à Panoramax Instance IGN : https://panoramax.ign.fr",
|
||||
"subtitle_conformity": "État de conformité",
|
||||
"conformity_text": "Panoramax Instance IGN est non conforme avec le ",
|
||||
"conformity_text2": "Le site n’a encore pas été audité.",
|
||||
"subtitle_conformity2": "Contenus non accessibles",
|
||||
"subtitle_increase": "Amélioration et contact",
|
||||
"increase_text": "Si vous n’arrivez pas à accéder à un contenu ou à un service, vous pouvez\n contacter le responsable de Panoramax Instance IGN pour être orienté vers une alternative accessible ou obtenir le contenu sous une autre forme.",
|
||||
"phone": "Téléphone : +33 14 398 84 61",
|
||||
"email_text": "E-mail :",
|
||||
"email": "signalement.ign@panoramax.fr",
|
||||
"address": "Adresse : IGN, Saint-Mandé",
|
||||
"increase_info": "Nous essayons de répondre dans les 5 jours ouvrés.",
|
||||
"subtitle_to_do": "Voie de recours",
|
||||
"to_do_text": "Cette procédure est à utiliser dans le cas suivant : vous avez signalé au responsable du site internet un défaut d’accessibilité qui vous\n empêche d’accéder à un contenu ou à un des services du portail et vous n’avez pas obtenu de réponse satisfaisante. \n vous pouvez :",
|
||||
"write_message": "Écrire un message au",
|
||||
"defenseur_droits": "Défenseur des droits",
|
||||
"contact": "Contacter",
|
||||
"contact_text": "le délégué du Défenseur des droits dans votre région",
|
||||
"send_letter": "Envoyer un courrier par la poste (gratuit, ne pas mettre de\n timbre):\n Défenseur des droits\n Libre réponse 71120 75342 Paris CEDEX 07",
|
||||
"end": "Cette déclaration d’accessibilité a été créé le\n 18 septembre 2023 grâce au",
|
||||
"generator_betagouv": "Générateur de Déclaration d’Accessibilité de BetaGouv"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { globalCookiesConfig } from 'vue3-cookies'
|
||||
import { createMetaManager } from 'vue-meta'
|
||||
import { pinia } from './store'
|
||||
import fr from './locales/fr.json'
|
||||
import en from './locales/en.json'
|
||||
import './assets/main.scss'
|
||||
import 'bootstrap/dist/css/bootstrap.css'
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||
@@ -17,13 +18,14 @@ axios.defaults.baseURL = import.meta.env.VITE_API_URL
|
||||
axios.defaults.withCredentials = true
|
||||
|
||||
const i18n = createI18n({
|
||||
locale: 'fr',
|
||||
locale: navigator.language.split('-')[0],
|
||||
fallbackLocale: 'fr',
|
||||
warnHtmlMessage: false,
|
||||
globalInjection: true,
|
||||
legacy: false,
|
||||
messages: {
|
||||
fr
|
||||
fr,
|
||||
en
|
||||
}
|
||||
})
|
||||
globalCookiesConfig({
|
||||
|
||||
39
src/tests/unit/components/Footer.spec.js
Normal file
39
src/tests/unit/components/Footer.spec.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { test, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import Footer from '../../../components/Footer.vue'
|
||||
import Link from '../../../components/Link.vue'
|
||||
import i18n from '../config'
|
||||
describe('Template', () => {
|
||||
test('should have the links without the ay11 link', () => {
|
||||
const wrapper = shallowMount(Footer, {
|
||||
global: {
|
||||
stubs: { Link },
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
expect(wrapper.html()).contains('href="https://panoramax.fr/"')
|
||||
expect(wrapper.html()).contains('logo.jpeg')
|
||||
expect(wrapper.html()).contains('Découvrir Panoramax')
|
||||
|
||||
expect(wrapper.html()).contains('href="https://gitlab.com/geovisio"')
|
||||
expect(wrapper.html()).contains('gitlab-logo.svg')
|
||||
expect(wrapper.html()).contains('Voir le code')
|
||||
})
|
||||
test('should have the ay11 link', () => {
|
||||
Object.create(window)
|
||||
const url = 'http://test.ign.fr'
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
href: url
|
||||
},
|
||||
writable: true // possibility to override
|
||||
})
|
||||
const wrapper = shallowMount(Footer, {
|
||||
global: {
|
||||
stubs: { Link },
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
expect(wrapper.html()).contains('Accessibilité : non conforme')
|
||||
})
|
||||
})
|
||||
33
src/tests/unit/components/InformationCard.spec.js
Normal file
33
src/tests/unit/components/InformationCard.spec.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { test, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import InformationCard from '../../../components/InformationCard.vue'
|
||||
import i18n from '../config'
|
||||
describe('Template', () => {
|
||||
describe('Props', () => {
|
||||
test('should have default props', () => {
|
||||
const wrapper = shallowMount(InformationCard, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.text).toBe(null)
|
||||
expect(wrapper.vm.title).toBe(null)
|
||||
expect(wrapper.vm.look).toBe('')
|
||||
})
|
||||
test('should have all the props filled', () => {
|
||||
const wrapper = shallowMount(InformationCard, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
},
|
||||
props: {
|
||||
text: 'my text',
|
||||
title: 'my title',
|
||||
look: 'my-look'
|
||||
}
|
||||
})
|
||||
expect(wrapper.html()).contains('my title</h3>')
|
||||
expect(wrapper.html()).contains('my text</p>')
|
||||
expect(wrapper.html()).contains('class="information-block my-look"')
|
||||
})
|
||||
})
|
||||
})
|
||||
80
src/tests/unit/components/InputUpload.spec.js
Normal file
80
src/tests/unit/components/InputUpload.spec.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import { test, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import InputUpload from '../../../components/InputUpload.vue'
|
||||
import i18n from '../config'
|
||||
describe('Template', () => {
|
||||
describe('Props', () => {
|
||||
test('should have default props', () => {
|
||||
const wrapper = shallowMount(InputUpload, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.text).toBe(null)
|
||||
expect(wrapper.vm.textPictureType).toBe(null)
|
||||
expect(wrapper.vm.textSecondPart).toBe(null)
|
||||
expect(wrapper.vm.accept).toBe('')
|
||||
})
|
||||
test('should have all the props filled', () => {
|
||||
const wrapper = shallowMount(InputUpload, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
},
|
||||
props: {
|
||||
text: 'my text',
|
||||
textPictureType: 'my textPictureType',
|
||||
textSecondPart: 'my textSecondPart',
|
||||
accept: 'accept'
|
||||
}
|
||||
})
|
||||
expect(wrapper.html()).contains('accept="accept"')
|
||||
expect(wrapper.html()).contains('my text')
|
||||
expect(wrapper.html()).contains('my textSecondPart')
|
||||
expect(wrapper.html()).contains('my textPictureType')
|
||||
})
|
||||
})
|
||||
describe('When the input is dragover', () => {
|
||||
test('should set the component dragging state', async () => {
|
||||
const wrapper = shallowMount(InputUpload, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
await wrapper.find('label').trigger('dragover')
|
||||
expect(wrapper.vm.isDragging).toBe(true)
|
||||
expect(wrapper.html()).contains('class="file-upload dragging"')
|
||||
})
|
||||
})
|
||||
describe('When the input is dragleave', () => {
|
||||
test('should set the component dragging state', async () => {
|
||||
const wrapper = shallowMount(InputUpload, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
await wrapper.find('label').trigger('dragover')
|
||||
await wrapper.find('label').trigger('dragleave')
|
||||
|
||||
expect(wrapper.vm.isDragging).toBe(false)
|
||||
expect(wrapper.html()).contains('class="file-upload"')
|
||||
})
|
||||
})
|
||||
describe('When the input is dropped', () => {
|
||||
test('should emit with value', async () => {
|
||||
const wrapper = shallowMount(InputUpload, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
const dataTransfer = {
|
||||
files: [{ type: 'image/jpeg' }]
|
||||
}
|
||||
const label = await wrapper.find('label')
|
||||
await label.trigger('drop', { dataTransfer })
|
||||
|
||||
expect(wrapper.emitted()).toHaveProperty('trigger')
|
||||
expect(wrapper.emitted().trigger[0][0]).toEqual(dataTransfer.files)
|
||||
})
|
||||
})
|
||||
// TODO TEST -> When the input is changed should emit with value
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import { it, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import BetaText from '../../../components/InstanceName.vue'
|
||||
import InstanceName from '../../../components/InstanceName.vue'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import fr from '../../../locales/fr.json'
|
||||
|
||||
@@ -16,7 +16,7 @@ const i18n = createI18n({
|
||||
|
||||
describe('Template', () => {
|
||||
it('should render the component with good wording keys', async () => {
|
||||
const wrapper = shallowMount(BetaText, {
|
||||
const wrapper = shallowMount(InstanceName, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
mocks: {
|
||||
51
src/tests/unit/components/Modal.spec.js
Normal file
51
src/tests/unit/components/Modal.spec.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { it, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import Modal from '../../../components/Modal.vue'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import fr from '../../../locales/fr.json'
|
||||
|
||||
const i18n = createI18n({
|
||||
locale: 'fr',
|
||||
fallbackLocale: 'fr',
|
||||
globalInjection: true,
|
||||
legacy: false,
|
||||
messages: {
|
||||
fr
|
||||
}
|
||||
})
|
||||
|
||||
describe('Template', () => {
|
||||
describe('Props', () => {
|
||||
it('should render the default props', async () => {
|
||||
document.body.innerHTML = '<div id="bs-modal"></div>'
|
||||
const wrapper = shallowMount(Modal, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
mocks: {
|
||||
$t: (msg) => msg
|
||||
}
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.uploadErrors).toEqual([])
|
||||
})
|
||||
it('should render the props filled', async () => {
|
||||
document.body.innerHTML = '<div id="bs-modal"></div>'
|
||||
const uploadErrors = [{ message: 'my message', name: 'my name' }]
|
||||
const wrapper = shallowMount(Modal, {
|
||||
global: {
|
||||
plugins: [i18n],
|
||||
mocks: {
|
||||
$t: (msg) => msg
|
||||
}
|
||||
},
|
||||
props: {
|
||||
uploadErrors
|
||||
}
|
||||
})
|
||||
|
||||
expect(wrapper.vm.uploadErrors).toEqual(uploadErrors)
|
||||
expect(wrapper.html()).contains('my name - ')
|
||||
expect(wrapper.html()).contains('my message')
|
||||
})
|
||||
})
|
||||
})
|
||||
36
src/tests/unit/components/share-pictures/Card.spec.js
Normal file
36
src/tests/unit/components/share-pictures/Card.spec.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { test, describe, expect } from 'vitest'
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import Card from '../../../../components/share-pictures/Card.vue'
|
||||
import i18n from '../../config'
|
||||
describe('Template', () => {
|
||||
describe('Props', () => {
|
||||
test('should have default props', () => {
|
||||
const wrapper = shallowMount(Card, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.title).toBe(null)
|
||||
expect(wrapper.vm.description).toBe(null)
|
||||
expect(wrapper.vm.imgSrc).toBe(null)
|
||||
expect(wrapper.vm.imgAlt).toBe(null)
|
||||
})
|
||||
test('should have all the props filled', () => {
|
||||
const wrapper = shallowMount(Card, {
|
||||
global: {
|
||||
plugins: [i18n]
|
||||
},
|
||||
props: {
|
||||
title: 'my title',
|
||||
description: 'my description',
|
||||
imgSrc: 'my-imgSrc.jpg',
|
||||
imgAlt: 'my imgAlt'
|
||||
}
|
||||
})
|
||||
expect(wrapper.html()).contains('my title</h2>')
|
||||
expect(wrapper.html()).contains('my description</p>')
|
||||
expect(wrapper.html()).contains('/my-imgSrc.jpg')
|
||||
expect(wrapper.html()).contains('alt="my imgAlt"')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -10,7 +10,7 @@
|
||||
import { ref } from 'vue'
|
||||
import Viewer from '@/components/Viewer.vue'
|
||||
const emit = defineEmits<{ (e: 'trigger', value: string): void }>()
|
||||
const viewerRef = ref<any>(null)
|
||||
const viewerRef = ref<unknown>(null)
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.entry-page {
|
||||
@@ -29,11 +29,11 @@ const viewerRef = ref<any>(null)
|
||||
}
|
||||
@media (max-width: toRem(76.8)) {
|
||||
.entry-page {
|
||||
padding-top: toRem(11);
|
||||
padding-top: toRem(11.5);
|
||||
overflow: hidden;
|
||||
}
|
||||
.entry-section {
|
||||
height: calc(100vh - #{toRem(11)});
|
||||
height: calc(100dvh - #{toRem(18)});
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,20 +2,22 @@
|
||||
<main class="entry-page">
|
||||
<section class="section-viewer">
|
||||
<Viewer
|
||||
v-if="collectionBbox.length"
|
||||
:fetch-options="{
|
||||
fetchOptions: {
|
||||
credentials: 'include'
|
||||
}
|
||||
}"
|
||||
:sequence-id="seqId"
|
||||
:geovisio-viewer="false"
|
||||
:user-id="getUserId"
|
||||
:bbox="collectionBbox"
|
||||
ref="viewerRef"
|
||||
/>
|
||||
</section>
|
||||
<section class="section-sequence">
|
||||
<h1 class="sequences-title">{{ $t('pages.sequences.title') }}</h1>
|
||||
<ul v-if="!isLoading" class="sequence-list">
|
||||
<li class="sequence-item">
|
||||
<li class="sequence-item sequence-item-head">
|
||||
<div class="sequence-header-item"></div>
|
||||
<div class="sequence-header-item">
|
||||
<Button
|
||||
@@ -67,18 +69,19 @@
|
||||
v-if="userSequences.length"
|
||||
v-for="(item, i) in userSequences"
|
||||
:id="`el-list${i}`"
|
||||
class="sequence-item"
|
||||
:class="[
|
||||
'sequence-item',
|
||||
item.id === seqId ? 'button-item-hover' : ''
|
||||
]"
|
||||
@mouseover="goToSequence(item)"
|
||||
>
|
||||
<router-link
|
||||
:class="[
|
||||
'button-item',
|
||||
item.id === seqId ? 'button-item-hover' : ''
|
||||
]"
|
||||
class="button-item"
|
||||
:to="{
|
||||
name: 'sequence',
|
||||
params: { id: item.id }
|
||||
}"
|
||||
@mouseover.stop
|
||||
>
|
||||
<div class="wrapper-thumb">
|
||||
<img
|
||||
@@ -156,6 +159,7 @@ import { useI18n } from 'vue-i18n'
|
||||
import { useSequenceStore } from '@/store/sequence'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { scrollIntoSelected } from '@/views/utils/sequence/index'
|
||||
import { useCookies } from 'vue3-cookies'
|
||||
import axios from 'axios'
|
||||
import Viewer from '@/components/Viewer.vue'
|
||||
import Button from '@/components/Button.vue'
|
||||
@@ -168,6 +172,7 @@ import type {
|
||||
} from './interfaces/MySequencesView'
|
||||
import { formatDate } from '@/utils/dates'
|
||||
const { t } = useI18n()
|
||||
const { cookies } = useCookies()
|
||||
const sequenceStore = useSequenceStore()
|
||||
const { toastText, toastLook } = storeToRefs(sequenceStore)
|
||||
|
||||
@@ -226,14 +231,13 @@ function goToSequence(sequence: SequenceLinkInterface) {
|
||||
function getRelChild(sequences: SequenceLinkInterface[]) {
|
||||
return sequences.filter((el: SequenceLinkInterface) => el.rel === 'child')
|
||||
}
|
||||
|
||||
const getUserId = computed<string>(() => cookies.get('user_id'))
|
||||
onMounted(async () => {
|
||||
isLoading.value = true
|
||||
try {
|
||||
const { data } = await axios.get('api/users/me/catalog')
|
||||
const collectionData = await axios.get('api/users/me/collection')
|
||||
collectionBbox.value = collectionData.data.extent.spatial.bbox[0]
|
||||
viewerRef.value.viewer.fitBounds(collectionBbox.value)
|
||||
const sequences = getRelChild(data.links)
|
||||
const sequencesCollection = getRelChild(collectionData.data.links)
|
||||
sequencesCollection.map((el: SequenceLinkInterface) => {
|
||||
@@ -256,6 +260,7 @@ watchEffect(() => {
|
||||
(e: { detail: { seqId: string } }) => {
|
||||
seqId.value = e.detail.seqId
|
||||
scrollIntoSelected(e.detail.seqId, userSequences.value)
|
||||
viewerRef.value.viewer.select(e.detail.seqId)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -295,6 +300,7 @@ watchEffect(() => {
|
||||
justify-content: center;
|
||||
margin: auto;
|
||||
background-color: var(--blue-pale);
|
||||
padding: toRem(2);
|
||||
&:first-child {
|
||||
margin-bottom: toRem(1);
|
||||
padding: toRem(1) toRem(2);
|
||||
@@ -306,6 +312,22 @@ watchEffect(() => {
|
||||
background-color: var(--white);
|
||||
}
|
||||
}
|
||||
.button-item-hover {
|
||||
background-color: var(--blue);
|
||||
&:nth-child(2n) {
|
||||
background-color: var(--blue);
|
||||
}
|
||||
.button-item {
|
||||
& > *,
|
||||
& > :nth-child(2) {
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
}
|
||||
.sequence-item-head:hover {
|
||||
background-color: initial;
|
||||
color: initial;
|
||||
}
|
||||
.wrapper-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -350,7 +372,6 @@ watchEffect(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: toRem(2);
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
@@ -374,19 +395,6 @@ watchEffect(() => {
|
||||
& > :nth-child(2) {
|
||||
color: var(--blue-dark);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--blue);
|
||||
& > * {
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-item-hover {
|
||||
background-color: var(--blue);
|
||||
& > *,
|
||||
& > :nth-child(2) {
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
.bi-images {
|
||||
margin-right: toRem(0.5);
|
||||
|
||||
@@ -247,6 +247,9 @@ h3 {
|
||||
padding: toRem(2) toRem(5) toRem(5);
|
||||
color: var(--grey-dark);
|
||||
}
|
||||
.logged {
|
||||
height: calc(100vh - #{toRem(8)});
|
||||
}
|
||||
.section {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
export interface OptionalViewerInterface {
|
||||
export interface MapInterface {
|
||||
startWide?: boolean
|
||||
maxZoom?: number
|
||||
minZoom?: number
|
||||
style?: object | string
|
||||
zoom?: number
|
||||
center?: number[]
|
||||
bounds?: number[]
|
||||
}
|
||||
|
||||
export interface ViewerInterface {
|
||||
fetchOptions?: {
|
||||
credentials: string
|
||||
}
|
||||
hash?: boolean
|
||||
picId?: string
|
||||
widgets?: {
|
||||
customWidget: HTMLAnchorElement
|
||||
}
|
||||
}
|
||||
|
||||
export interface ViewerInterface extends OptionalViewerInterface {
|
||||
map: {
|
||||
startWide: boolean
|
||||
style?: object | string
|
||||
maxZoom?: number
|
||||
zoom?: number
|
||||
center?: number[]
|
||||
}
|
||||
bounds?: number[]
|
||||
map: MapInterface
|
||||
}
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
import axios from 'axios'
|
||||
|
||||
function createASequence(title: string): Promise<any> {
|
||||
interface SequenceCreatedInterface {
|
||||
data: {
|
||||
created: string
|
||||
description: string
|
||||
extent: { spatial: object; temporal: object }
|
||||
['geovisio:status']: string
|
||||
id: string
|
||||
keywords: string[]
|
||||
license: string
|
||||
links: object[]
|
||||
providers: object[]
|
||||
stac_extensions: string[]
|
||||
stac_version: string
|
||||
['stats:items']: { count: number }
|
||||
title: string
|
||||
type: string
|
||||
}
|
||||
}
|
||||
|
||||
function createASequence(title: string): Promise<SequenceCreatedInterface> {
|
||||
return axios.post('api/collections', { title: title })
|
||||
}
|
||||
|
||||
|
||||
@@ -3164,10 +3164,10 @@ 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.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/geovisio/-/geovisio-2.2.0.tgz#8d67bf4e3fe04699d16d76bfcc0c5ee3e10e88f1"
|
||||
integrity sha512-EGUvDNW4gyYdBSszU8fqgpQHWxeSS04pdSUK0oWvBLV24Fl0PYtDOI6uoUAa/69B1kQbGs5qp4wNCyzll7hIrg==
|
||||
geovisio@2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/geovisio/-/geovisio-2.2.1.tgz#75ded2d10ca0c69464b5c734c0c2b3eeff8db8eb"
|
||||
integrity sha512-E2s6dCXmMSRbtmZ7c4bMCDhgqT5xaKpGZxmbXMfB7+VgLQugiaIyRPKTB5Xtvw3f08FS7mC42WNqZqN5sFitKg==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-svg-core" "^6.4.0"
|
||||
"@fortawesome/free-solid-svg-icons" "^6.4.0"
|
||||
|
||||
Reference in New Issue
Block a user