parent
3c24963884
commit
3685155a1d
@ -1,3 +1,27 @@
|
||||
# front
|
||||
# Memory Map
|
||||
|
||||
Front du projet MemoryMap
|
||||
|
||||
## Project setup
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
"baseUrl": "./",
|
||||
"moduleResolution": "node",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "memory_map",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^3.8.3",
|
||||
"flowbite": "^2.5.1",
|
||||
"leaflet": "^1.9.4",
|
||||
"vue": "^3.2.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.16",
|
||||
"@babel/eslint-parser": "^7.12.16",
|
||||
"@vue/cli-plugin-babel": "~5.0.0",
|
||||
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||
"@vue/cli-service": "~5.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"postcss": "^8.4.47",
|
||||
"tailwindcss": "^3.4.12"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"parser": "@babel/eslint-parser"
|
||||
},
|
||||
"rules": {}
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not dead",
|
||||
"not ie 11"
|
||||
]
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
After Width: | Height: | Size: 89 KiB |
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
|
||||
<title>Memory Map</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong
|
||||
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
|
||||
properly without JavaScript enabled. Please enable it to
|
||||
continue.</strong
|
||||
>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div class="container mx-auto h-screen">
|
||||
<NavBar />
|
||||
<LeafletMap />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LeafletMap from "./components/LeafletMap.vue";
|
||||
import NavBar from "./components/NavBar.vue";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
components: {
|
||||
NavBar,
|
||||
LeafletMap,
|
||||
},
|
||||
};
|
||||
</script>
|
After Width: | Height: | Size: 244 KiB |
@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="map-container h-[calc(100vh_-_72px)]">
|
||||
<div id="map" class="h-full w-full"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import L from "leaflet";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { createApp, h, onMounted } from "vue";
|
||||
import { monuments } from "../data/stub";
|
||||
import MonumentMarker from "./MonumentMarker.vue";
|
||||
|
||||
export default {
|
||||
name: "LeafletMap",
|
||||
setup() {
|
||||
onMounted(() => {
|
||||
// Initialiser la carte
|
||||
const map = L.map("map").setView([46.603354, 1.888334], 6); // TODO: A modifier pour centrer par rapport aux points de la carte
|
||||
// Supprimer les attributions de la carte Leaflet
|
||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
attribution: "",
|
||||
}).addTo(map);
|
||||
map.attributionControl.setPrefix("");
|
||||
|
||||
// Définir une fonction pour créer des icônes avec Heroicons
|
||||
const createDivIcon = (htmlContent) => {
|
||||
return L.divIcon({
|
||||
html: htmlContent,
|
||||
className: "text-2xl text-blue-500", // Utilise les classes CSS de Flowbite ou Tailwind pour styliser les icônes
|
||||
iconSize: [24, 24], // Taille approximative du conteneur de l'icône
|
||||
iconAnchor: [12, 24], // Point d'ancrage de l'icône (centre-bas)
|
||||
popupAnchor: [0, -24], // Point d'ancrage du popup (juste au-dessus du marqueur)
|
||||
});
|
||||
};
|
||||
|
||||
// Définir les icônes Heroicons
|
||||
const visitedIcon = createDivIcon(`
|
||||
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" d="M11.906 1.994a8.002 8.002 0 0 1 8.09 8.421 7.996 7.996 0 0 1-1.297 3.957.996.996 0 0 1-.133.204l-.108.129c-.178.243-.37.477-.573.699l-5.112 6.224a1 1 0 0 1-1.545 0L5.982 15.26l-.002-.002a18.146 18.146 0 0 1-.309-.38l-.133-.163a.999.999 0 0 1-.13-.202 7.995 7.995 0 0 1 6.498-12.518ZM15 9.997a3 3 0 1 1-5.999 0 3 3 0 0 1 5.999 0Z" clip-rule="evenodd"/>
|
||||
</svg>
|
||||
`);
|
||||
|
||||
const notVisitedIcon = createDivIcon(`
|
||||
<svg class="w-[24px] h-[24px] text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" stroke-width="3" d="M11.083 5.104c.35-.8 1.485-.8 1.834 0l1.752 4.022a1 1 0 0 0 .84.597l4.463.342c.9.069 1.255 1.2.556 1.771l-3.33 2.723a1 1 0 0 0-.337 1.016l1.03 4.119c.214.858-.71 1.552-1.474 1.106l-3.913-2.281a1 1 0 0 0-1.008 0L7.583 20.8c-.764.446-1.688-.248-1.474-1.106l1.03-4.119A1 1 0 0 0 6.8 14.56l-3.33-2.723c-.698-.571-.342-1.702.557-1.771l4.462-.342a1 1 0 0 0 .84-.597l1.753-4.022Z"/>
|
||||
</svg>
|
||||
`);
|
||||
|
||||
// Ajouter les marqueurs pour chaque monument
|
||||
monuments.forEach((monument) => {
|
||||
// Choisir l'icône en fonction de la propriété `visited`
|
||||
const icon = monument.visited ? visitedIcon : notVisitedIcon;
|
||||
|
||||
// Ajouter un marqueur avec l'icône appropriée
|
||||
const marker = L.marker(monument.coords, { icon }).addTo(map);
|
||||
|
||||
// Créer un conteneur DOM pour monter le composant Vue
|
||||
const popupContainer = document.createElement("div");
|
||||
|
||||
// Monter le composant Vue MonumentMarker sur le conteneur
|
||||
const app = createApp({
|
||||
render() {
|
||||
return h(MonumentMarker, { monument });
|
||||
},
|
||||
});
|
||||
app.mount(popupContainer);
|
||||
|
||||
// Attacher le popup au marqueur avec le contenu monté
|
||||
marker.bindPopup(popupContainer);
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<strong>{{ monument.name }}</strong>
|
||||
<div
|
||||
class="relative carousel overflow-hidden"
|
||||
v-if="monument.images.length > 0"
|
||||
>
|
||||
<!-- Carousel wrapper -->
|
||||
<div
|
||||
class="relative h-40 mt-2 overflow-hidden rounded-lg flex items-center justify-center"
|
||||
>
|
||||
<div
|
||||
v-for="(image, index) in monument.images"
|
||||
:key="index"
|
||||
:class="[
|
||||
'absolute inset-0 transition-opacity duration-700 ease-in-out',
|
||||
{
|
||||
'opacity-100': index === currentIndex,
|
||||
'opacity-0': index !== currentIndex,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<img
|
||||
:src="image"
|
||||
:alt="monument.name"
|
||||
class="object-contain max-h-full max-w-full h-full w-auto mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slider controls -->
|
||||
<div v-if="monument.images.length > 1">
|
||||
<button
|
||||
type="button"
|
||||
class="absolute top-0 left-0 z-30 flex items-center justify-center h-full cursor-pointer group focus:outline-none"
|
||||
@click="prevSlide"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-black/30 dark:bg-black-800/30 group-hover:bg-black/50 dark:group-hover:bg-black-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 text-white dark:text-gray-800 rtl:rotate-180"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 6 10"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 1 1 5l4 4"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Previous</span>
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="absolute top-0 right-0 z-30 flex items-center justify-center h-full cursor-pointer group focus:outline-none"
|
||||
@click="nextSlide"
|
||||
>
|
||||
<span
|
||||
class="inline-flex items-center justify-center w-8 h-8 rounded-full bg-black/30 dark:bg-black-800/30 group-hover:bg-black/50 dark:group-hover:bg-black-800/60"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 text-white dark:text-gray-800 rtl:rotate-180"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 6 10"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M1 9l4-4-4-4"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Next</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p v-html="formattedDescription"></p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "MonumentMarker",
|
||||
props: {
|
||||
monument: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
formattedDescription() {
|
||||
return this.formatDescription(this.monument.description);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// Remplace les mentions d'utilisateurs par des liens cliquables
|
||||
formatDescription(description) {
|
||||
const regex = /@(\w+(-\w+)*(\.\w+(-\w+)*)*)/g;
|
||||
return description.replace(
|
||||
regex,
|
||||
'<a href="/profile/$1" class="text-blue-500 hover:underline">@$1</a>'
|
||||
);
|
||||
},
|
||||
prevSlide() {
|
||||
this.currentIndex =
|
||||
(this.currentIndex - 1 + this.monument.images.length) %
|
||||
this.monument.images.length;
|
||||
},
|
||||
nextSlide() {
|
||||
this.currentIndex = (this.currentIndex + 1) % this.monument.images.length;
|
||||
},
|
||||
},
|
||||
// mounted() {
|
||||
// setInterval(this.nextSlide, 3000);
|
||||
// }
|
||||
};
|
||||
</script>
|
@ -0,0 +1,152 @@
|
||||
<template>
|
||||
<nav class="bg-white border-gray-200 dark:bg-gray-900">
|
||||
<div
|
||||
class="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"
|
||||
>
|
||||
<a class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||
<img src="../assets/logo.png" class="h-10" alt="Memory Map Logo" />
|
||||
<span
|
||||
class="self-center text-2xl font-semibold whitespace-nowrap dark:text-white"
|
||||
>Memory Map</span
|
||||
>
|
||||
</a>
|
||||
<div class="flex lg:order-2">
|
||||
<button
|
||||
type="button"
|
||||
data-collapse-toggle="navbar-search"
|
||||
aria-controls="navbar-search"
|
||||
aria-expanded="false"
|
||||
class="lg:hidden text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5 me-1"
|
||||
>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Search</span>
|
||||
</button>
|
||||
<div class="relative hidden lg:block">
|
||||
<div
|
||||
class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 text-gray-500 dark:text-gray-400"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">Search icon</span>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
id="search-navbar"
|
||||
class="block w-full p-2 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
data-collapse-toggle="navbar-search"
|
||||
type="button"
|
||||
class="inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg lg:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600"
|
||||
aria-controls="navbar-search"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<svg
|
||||
class="w-5 h-5"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 17 14"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M1 1h15M1 7h15M1 13h15"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="items-center justify-between hidden w-full lg:flex lg:w-auto lg:order-1"
|
||||
id="navbar-search"
|
||||
>
|
||||
<div class="relative mt-3 lg:hidden">
|
||||
<div
|
||||
class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none"
|
||||
>
|
||||
<svg
|
||||
class="w-4 h-4 text-gray-500 dark:text-gray-400"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
id="search-navbar"
|
||||
class="block w-full p-2 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
class="flex flex-col p-4 lg:p-0 mt-4 font-medium border border-gray-100 rounded-lg bg-gray-50 lg:space-x-8 rtl:space-x-reverse lg:flex-row lg:mt-0 lg:border-0 lg:bg-white dark:bg-gray-800 lg:dark:bg-gray-900 dark:border-gray-700"
|
||||
>
|
||||
<li class="flex items-center space-x-2">
|
||||
<a
|
||||
href="#"
|
||||
class="block py-2 px-3 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white md:dark:text-blue-500"
|
||||
aria-current="page"
|
||||
>Home</a
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center space-x-2">
|
||||
<a href="#" class="block py-2 text-gray-900 dark:text-white"
|
||||
>Quests</a
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center space-x-2">
|
||||
<a href="#" class="block py-2 text-gray-900 dark:text-white"
|
||||
>Add a pin</a
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-center space-x-2">
|
||||
<a href="#" class="block py-2 text-gray-900 dark:text-white"
|
||||
>Friends</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
@ -0,0 +1,30 @@
|
||||
export const monuments = [
|
||||
{
|
||||
coords: [48.85837, 2.294481],
|
||||
name: "Tour Eiffel",
|
||||
images: [
|
||||
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQGGib245tSFiK1Qcx0cB0dZsoVyJElwsY3kA&s",
|
||||
"https://encrypted-tbn2.gstatic.com/licensed-image?q=tbn:ANd9GcTLB9B0j50rJbcSbdja9_hySHS6_KATbhTK_iCeWeNKtA92hTmTX5nTW3udjjovZrnU1JxqAjMS_VqHnMwHGhTs35-sU-7B29_X_T3uLV8",
|
||||
],
|
||||
description: "Visité en 2020 avec la famille, un moment inoubliable.",
|
||||
visited: true,
|
||||
},
|
||||
{
|
||||
coords: [43.296482, 5.36978],
|
||||
name: "Vieux Port de Marseille",
|
||||
images: [
|
||||
"https://upload.wikimedia.org/wikipedia/commons/thumb/7/74/Marseille_Old_Port.jpg/390px-Marseille_Old_Port.jpg",
|
||||
],
|
||||
description:
|
||||
"Découvert lors d'un week-end ensoleillé en 2019 avec @John-Doe.",
|
||||
visited: true,
|
||||
},
|
||||
{
|
||||
coords: [48.636063, -1.511457],
|
||||
name: "Mont Saint-Michel",
|
||||
images: [],
|
||||
description: "",
|
||||
visited: false,
|
||||
},
|
||||
// ...
|
||||
];
|
@ -0,0 +1,6 @@
|
||||
import "flowbite";
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import "./assets/main.css";
|
||||
|
||||
createApp(App).mount("#app");
|
@ -0,0 +1,12 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{vue,js,ts,jsx,tsx}",
|
||||
"./node_modules/flowbite/**/*.js",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [require("flowbite/plugin")],
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require("@vue/cli-service");
|
||||
|
||||
module.exports = defineConfig({
|
||||
transpileDependencies: true,
|
||||
});
|
Loading…
Reference in new issue