forked from Ivasoft/geovisio-website
Compare commits
3 Commits
tech-add-t
...
fix/cookie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02e145456e | ||
|
|
7341883c14 | ||
|
|
230f978ffa |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -90,7 +90,6 @@ sw.*
|
|||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
# Cypress generated screen and videos files
|
# Cypress generated screen and videos files
|
||||||
cypress/downloads/*
|
|
||||||
cypress/screenshot/
|
cypress/screenshot/
|
||||||
cypress/videos/
|
cypress/videos/
|
||||||
*.cy.ts.mp4
|
*.cy.ts.mp4
|
||||||
@@ -8,10 +8,9 @@ variables:
|
|||||||
DOCKER_BUILDKIT: 1 # use buildkit for better performance
|
DOCKER_BUILDKIT: 1 # use buildkit for better performance
|
||||||
DOCKER_DRIVER: overlay2 # better docker driver to avoid copying too many files on each run
|
DOCKER_DRIVER: overlay2 # better docker driver to avoid copying too many files on each run
|
||||||
GITLAB_REGISTRY: registry.gitlab.com # We use docker.io for official images and gitlab's registry to store temporary images
|
GITLAB_REGISTRY: registry.gitlab.com # We use docker.io for official images and gitlab's registry to store temporary images
|
||||||
IMAGE_NAME: geovisio/website
|
IMAGE_NAME: geovisio/api
|
||||||
CI_IMAGE_CACHE: $GITLAB_REGISTRY/$IMAGE_NAME:build_cache
|
CI_IMAGE_CACHE: $GITLAB_REGISTRY/$IMAGE_NAME:build_cache
|
||||||
DOCKER_TLS_CERTDIR: ''
|
DOCKER_TLS_CERTDIR: ""
|
||||||
DOCKER_HOST: tcp://docker:2375
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
## chmod is unfortunately currently mandatory : https://github.com/nodejs/docker-node/issues/661
|
## chmod is unfortunately currently mandatory : https://github.com/nodejs/docker-node/issues/661
|
||||||
@@ -23,29 +22,28 @@ cache:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
stage: Install
|
stage: Install
|
||||||
image: node:18.16.1
|
image: node:18.16.0
|
||||||
script:
|
script:
|
||||||
- yarn install
|
- yarn install
|
||||||
- ls node_modules/.bin/cypress
|
- ls node_modules/.bin/cypress
|
||||||
|
|
||||||
test:unit:
|
test:unit:
|
||||||
stage: Test
|
stage: Test
|
||||||
image: node:18.16.1
|
image: node:18.16.0
|
||||||
script:
|
script:
|
||||||
- yarn test:unit
|
- yarn test:unit
|
||||||
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
||||||
|
|
||||||
test:e2e:
|
test:e2e:
|
||||||
stage: Test
|
stage: Test
|
||||||
image: node:18.16.1-alpine
|
image: cypress/browsers:node-18.16.0-chrome-113.0.5672.92-1-ff-113.0-edge-113.0.1774.35-1
|
||||||
services:
|
|
||||||
- docker:dind
|
|
||||||
script:
|
script:
|
||||||
- apk add --update --no-cache docker-cli docker-cli-compose git
|
- yarn install
|
||||||
- PROJECT_DIR=$PWD docker compose -f cypress/docker-compose-geovisio.yml -f cypress/docker-compose-gitlab-override.yml run --rm e2e
|
- ./node_modules/.bin/cypress install
|
||||||
after_script:
|
- echo "VITE_API_URL=https://geovisio-proxy-dev.osc-fr1.scalingo.io/" > .env
|
||||||
- PROJECT_DIR=$PWD docker compose -f cypress/docker-compose-geovisio.yml -f cypress/docker-compose-gitlab-override.yml logs web || true
|
- echo "VITE_ENV=dev" >> .env
|
||||||
- PROJECT_DIR=$PWD docker compose -f cypress/docker-compose-geovisio.yml -f cypress/docker-compose-gitlab-override.yml down || true
|
- PORT=5173 yarn start &
|
||||||
|
- yarn test:e2e
|
||||||
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
@@ -56,7 +54,7 @@ test:e2e:
|
|||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
stage: Deploy
|
stage: Deploy
|
||||||
image: node:18.16.1
|
image: node:18.16.0
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- node_modules
|
- node_modules
|
||||||
@@ -76,7 +74,7 @@ deploy:develop:
|
|||||||
stage: Deploy
|
stage: Deploy
|
||||||
image: docker:latest
|
image: docker:latest
|
||||||
services:
|
services:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
before_script:
|
before_script:
|
||||||
# login to the gitlab docker registry to use the cache and to publish
|
# login to the gitlab docker registry to use the cache and to publish
|
||||||
- echo $CI_DEPLOY_PASSWORD | docker login -u $CI_DEPLOY_USER --password-stdin $GITLAB_REGISTRY
|
- echo $CI_DEPLOY_PASSWORD | docker login -u $CI_DEPLOY_USER --password-stdin $GITLAB_REGISTRY
|
||||||
@@ -108,7 +106,7 @@ deploy:latest:
|
|||||||
stage: Deploy
|
stage: Deploy
|
||||||
image: docker:latest
|
image: docker:latest
|
||||||
services:
|
services:
|
||||||
- docker:dind
|
- docker:dind
|
||||||
before_script:
|
before_script:
|
||||||
# login to the gitlab docker registry to use the cache and to publish
|
# login to the gitlab docker registry to use the cache and to publish
|
||||||
- echo $CI_DEPLOY_PASSWORD | docker login -u $CI_DEPLOY_USER --password-stdin $GITLAB_REGISTRY
|
- echo $CI_DEPLOY_PASSWORD | docker login -u $CI_DEPLOY_USER --password-stdin $GITLAB_REGISTRY
|
||||||
|
|||||||
25
CHANGELOG.md
25
CHANGELOG.md
@@ -7,27 +7,6 @@ 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.3.0] - 2023-12-06
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Add the possibility to an user to select a sequence in the list using the map : https://gitlab.com/geovisio/website/-/merge_requests/100
|
|
||||||
- For a selected sequence in the list, if the sequence is not displayed in the map, fly to the sequence on the map : https://gitlab.com/geovisio/website/-/merge_requests/108
|
|
||||||
- Add the pagination to the sequence with sort with API routes : https://gitlab.com/geovisio/website/-/merge_requests/107
|
|
||||||
- Add Hungarian translation : https://gitlab.com/geovisio/website/-/merge_requests/105
|
|
||||||
- Add the possibility to hide/delete a sequence in the sequence list : https://gitlab.com/geovisio/website/-/merge_requests/101
|
|
||||||
- Add the possibility for the user to change the title of the sequence before upload the pictures : https://gitlab.com/geovisio/website/-/merge_requests/101
|
|
||||||
- Add the possibility to resize the sequence page by dragging the blocs : https://gitlab.com/geovisio/website/-/merge_requests/101
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- GeoVisio web viewer updated to [2.3.0](https://gitlab.com/geovisio/web-viewer/-/compare/2.2.1...2.3.0)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Nginx server in Docker container was not recognizing routes other than `/` on first loading.
|
|
||||||
- Fix the cookie bug by decoding flask cookie : https://gitlab.com/geovisio/website/-/merge_requests/102
|
|
||||||
|
|
||||||
## [2.2.3] - 2023-11-03
|
## [2.2.3] - 2023-11-03
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -37,7 +16,6 @@ Before _0.1.0_, website development was on rolling release, meaning there are no
|
|||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Page My Sequences, add the possibility to select a sequence in the list with the map :
|
- 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
|
- the user can only see his sequences on the list
|
||||||
- display the selected sequence in blue in the map
|
- display the selected sequence in blue in the map
|
||||||
- display a thumbnail the hovered sequence
|
- display a thumbnail the hovered sequence
|
||||||
@@ -147,8 +125,7 @@ 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.0...develop
|
[unreleased]: https://gitlab.com/geovisio/website/-/compare/2.2.3...develop
|
||||||
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.3...2.3.0
|
|
||||||
[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.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.1...2.2.2
|
||||||
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.0...2.2.1
|
[2.2.1]: https://gitlab.com/geovisio/website/-/compare/2.2.0...2.2.1
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#- Build image
|
#- Build image
|
||||||
#-
|
#-
|
||||||
|
|
||||||
FROM node:18.16.1-alpine AS build
|
FROM node:18.16.0-alpine AS build
|
||||||
|
|
||||||
WORKDIR /opt/geovisio
|
WORKDIR /opt/geovisio
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ export default defineConfig({
|
|||||||
setupNodeEvents(on, config) {
|
setupNodeEvents(on, config) {
|
||||||
// implement node event listeners here
|
// implement node event listeners here
|
||||||
},
|
},
|
||||||
baseUrl: 'http://localhost:5173/'
|
baseUrl: 'http://localhost:5173'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"api_url": "http://localhost:5000/"
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
services:
|
|
||||||
api:
|
|
||||||
image: geovisio/api:develop
|
|
||||||
command: api
|
|
||||||
restart: always
|
|
||||||
ports:
|
|
||||||
- 5000:5000
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
auth:
|
|
||||||
condition: service_healthy
|
|
||||||
environment:
|
|
||||||
DB_URL: postgres://gvs:gvspwd@db/geovisio
|
|
||||||
PICTURE_PROCESS_THREADS_LIMIT: 2
|
|
||||||
PICTURE_PROCESS_DERIVATES_STRATEGY: ON_DEMAND
|
|
||||||
API_FORCE_AUTH_ON_UPLOAD: 'true'
|
|
||||||
OAUTH_CLIENT_ID: geovisio
|
|
||||||
OAUTH_CLIENT_SECRET: what_a_secret
|
|
||||||
OAUTH_OIDC_URL: http://localhost:8183/realms/geovisio
|
|
||||||
OAUTH_PROVIDER: oidc
|
|
||||||
FLASK_SECRET_KEY: a_very_secret_key_never_to_be_used_in_production
|
|
||||||
healthcheck:
|
|
||||||
test: python -c "import requests; requests.get('http://localhost:5000/api').raise_for_status()"
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
extra_hosts:
|
|
||||||
- 'localhost:host-gateway'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
db: {}
|
|
||||||
geovisio:
|
|
||||||
aliases:
|
|
||||||
- api.localtest.me
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: postgis/postgis:13-3.2
|
|
||||||
environment:
|
|
||||||
- POSTGRES_USER=gvs
|
|
||||||
- POSTGRES_PASSWORD=gvspwd
|
|
||||||
- POSTGRES_DB=geovisio
|
|
||||||
healthcheck:
|
|
||||||
test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
networks:
|
|
||||||
db: {}
|
|
||||||
|
|
||||||
auth:
|
|
||||||
command: start-dev --import-realm
|
|
||||||
environment:
|
|
||||||
GEOVISIO_BASE_URL: http://localhost:5000
|
|
||||||
GEOVISIO_CLIENT_SECRET: what_a_secret
|
|
||||||
KEYCLOAK_ADMIN: admin
|
|
||||||
KEYCLOAK_ADMIN_PASSWORD: password
|
|
||||||
KEYCLOAK_FRONTEND_URL: http://localhost:5000/api/auth/login
|
|
||||||
KC_HTTP_PORT: 8183
|
|
||||||
ports:
|
|
||||||
- '8183:8183'
|
|
||||||
healthcheck:
|
|
||||||
test: curl --fail http://localhost:8183/realms/geovisio
|
|
||||||
timeout: 5s
|
|
||||||
interval: 2s
|
|
||||||
retries: 20
|
|
||||||
start_period: 15s
|
|
||||||
image: quay.io/keycloak/keycloak:20.0.1
|
|
||||||
volumes:
|
|
||||||
- ./keycloak-realm.json:/opt/keycloak/data/import/geovisio_realm.json
|
|
||||||
|
|
||||||
networks:
|
|
||||||
geovisio:
|
|
||||||
aliases:
|
|
||||||
- keycloak.localtest.me
|
|
||||||
|
|
||||||
networks:
|
|
||||||
db: {}
|
|
||||||
geovisio: {}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# Docker-compose used in gitlab-ci to run a container having access to all the other containers
|
|
||||||
services:
|
|
||||||
web:
|
|
||||||
image: node:18.16.1-alpine
|
|
||||||
volumes:
|
|
||||||
- $PROJECT_DIR:/src
|
|
||||||
working_dir: /src
|
|
||||||
command: >
|
|
||||||
sh -c "apk add --update --no-cache curl && yarn install && yarn start"
|
|
||||||
environment:
|
|
||||||
PORT: 5173
|
|
||||||
VITE_API_URL: http://api.localtest.me:5000
|
|
||||||
VITE_ENV: dev
|
|
||||||
depends_on:
|
|
||||||
api:
|
|
||||||
condition: service_healthy
|
|
||||||
auth:
|
|
||||||
condition: service_healthy
|
|
||||||
ports:
|
|
||||||
- 5173:5173
|
|
||||||
healthcheck:
|
|
||||||
test: curl --fail http://0.0.0.0:5173
|
|
||||||
timeout: 10s
|
|
||||||
interval: 3s
|
|
||||||
retries: 20
|
|
||||||
start_period: 15s
|
|
||||||
networks:
|
|
||||||
geovisio:
|
|
||||||
aliases:
|
|
||||||
- front.localtest.me
|
|
||||||
e2e:
|
|
||||||
image: cypress/included:cypress-12.17.3-node-18.16.1-chrome-114.0.5735.133-1-ff-114.0.2-edge-114.0.1823.51-1
|
|
||||||
volumes:
|
|
||||||
- $PROJECT_DIR:/src
|
|
||||||
working_dir: /src
|
|
||||||
environment:
|
|
||||||
- CYPRESS_baseUrl=http://front.localtest.me:5173/
|
|
||||||
- CYPRESS_api_url=http://api.localtest.me:5000/
|
|
||||||
- LANG=fr
|
|
||||||
command: sleep 2 && yarn add --dev cypress && ./node_modules/.bin/cypress install && yarn test:e2e
|
|
||||||
depends_on:
|
|
||||||
web:
|
|
||||||
condition: service_healthy
|
|
||||||
networks:
|
|
||||||
geovisio: {}
|
|
||||||
|
|
||||||
api:
|
|
||||||
environment:
|
|
||||||
OAUTH_OIDC_URL: http://keycloak.localtest.me:8183/realms/geovisio
|
|
||||||
FLASK_SESSION_COOKIE_DOMAIN: localtest.me
|
|
||||||
|
|
||||||
auth:
|
|
||||||
environment:
|
|
||||||
GEOVISIO_BASE_URL: http://api.localtest.me:5000
|
|
||||||
KEYCLOAK_FRONTEND_URL: http://api.localtest.me:5000/api/auth/login
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
describe('In the contribute page', () => {
|
|
||||||
it('go to the login page', () => {
|
|
||||||
cy.visit('/pourquoi-contribuer')
|
|
||||||
cy.get('.upload-text').scrollIntoView()
|
|
||||||
cy.fixture('contribute').then((contributeData: contributeInterface) => {
|
|
||||||
cy.contains(contributeData.textButtonContribute).click()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('go to the doc pages', () => {
|
|
||||||
cy.visit('pourquoi-contribuer')
|
|
||||||
cy.fixture('contribute').then((contributeData: contributeInterface) => {
|
|
||||||
cy.get('.upload-text').scrollIntoView()
|
|
||||||
cy.contains(contributeData.textButtonDocPython).click()
|
|
||||||
cy.contains(contributeData.textButtonCli).click()
|
|
||||||
cy.contains(contributeData.textButtonDocCli).click()
|
|
||||||
cy.contains(contributeData.textButtonTiles).click()
|
|
||||||
cy.contains(contributeData.textButtonDoc).click()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
interface contributeInterface {
|
|
||||||
textButtonContribute: string
|
|
||||||
textButtonCli: string
|
|
||||||
}
|
|
||||||
export {}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
describe('In the home page', () => {
|
|
||||||
it('click on the link in the footer to go to Panoramax.fr', () => {
|
|
||||||
cy.visit('/')
|
|
||||||
cy.fixture('home').then((homeData) => {
|
|
||||||
cy.contains(homeData.textLinkPanoramax).click()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
it('click on the link in the footer to go to Gitlab', () => {
|
|
||||||
cy.visit('/')
|
|
||||||
cy.fixture('home').then((homeData) => {
|
|
||||||
cy.contains(homeData.textLinkGitlab).click()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
export {}
|
|
||||||
@@ -1,25 +1,7 @@
|
|||||||
describe('In the login page', () => {
|
describe('In the login page', () => {
|
||||||
it('type in the form to login', () => {
|
it('type in the form to login', () => {
|
||||||
cy.visit(`${Cypress.env('api_url')}api/auth/login`)
|
|
||||||
cy.get('#username').type('Elysee')
|
|
||||||
cy.get('#password').type('my password')
|
|
||||||
cy.contains('Sign In').click()
|
|
||||||
cy.visit('/')
|
cy.visit('/')
|
||||||
})
|
})
|
||||||
it('go to the register form and create an account', () => {
|
|
||||||
cy.visit(`${Cypress.env('api_url')}api/auth/login`)
|
|
||||||
cy.fixture('login').then((loginData) => {
|
|
||||||
cy.contains(loginData.textLinkRegister).click()
|
|
||||||
cy.get('#firstName').type('Tom')
|
|
||||||
cy.get('#lastName').type('Tom')
|
|
||||||
cy.get('#email').type('test@test123.com')
|
|
||||||
cy.get('#username').type('Elysee12445')
|
|
||||||
cy.get('#password').type('my password1')
|
|
||||||
cy.get('#password-confirm').type('my password1')
|
|
||||||
cy.get('form').submit()
|
|
||||||
cy.visit('/')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"types": ["reflect-metadata", "jest", "cypress"],
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "es5",
|
|
||||||
"sourceMap": true
|
|
||||||
},
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"textButtonContribute": "Partager des images",
|
|
||||||
"textButtonDocCli": "Voir la documentation",
|
|
||||||
"textButtonDoc": "Retrouvez sa documentation ici",
|
|
||||||
"textButtonDocPython": "de python (au moins la version 3.8)",
|
|
||||||
"textButtonCli": "L'outil en ligne de commande",
|
|
||||||
"textButtonTiles": "de tuiles vectorielles"
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"textLinkContribute": "Pourquoi contribuer ?",
|
|
||||||
"textLinkPanoramax": "Découvrir Panoramax",
|
|
||||||
"textLinkGitlab": "Voir le code"
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 65 KiB |
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"textLinkRegister": "Register",
|
|
||||||
"textLinkLogin": "Sign In"
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -18,10 +18,5 @@ http {
|
|||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
gzip_static on;
|
gzip_static on;
|
||||||
|
|
||||||
location / {
|
|
||||||
root /usr/share/nginx/html;
|
|
||||||
try_files $uri /index.html;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "geovisio-website",
|
"name": "geovisio-website",
|
||||||
"version": "2.3.0",
|
"version": "2.2.3",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18.16.1"
|
"node": "18.16.0"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -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.0",
|
"geovisio": "2.2.1-develop-acb9989e",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"pako": "^2.1.0",
|
"pako": "^2.1.0",
|
||||||
"pinia": "^2.1.4",
|
"pinia": "^2.1.4",
|
||||||
@@ -42,7 +42,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@pinia/testing": "^0.1.2",
|
"@pinia/testing": "^0.1.2",
|
||||||
"@rushstack/eslint-patch": "^1.1.4",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@types/jest": "^29.5.4",
|
|
||||||
"@types/jsdom": "^20.0.1",
|
"@types/jsdom": "^20.0.1",
|
||||||
"@types/node": "^18.11.18",
|
"@types/node": "^18.11.18",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
||||||
@@ -53,13 +52,12 @@
|
|||||||
"@vue/eslint-config-typescript": "^11.0.0",
|
"@vue/eslint-config-typescript": "^11.0.0",
|
||||||
"@vue/test-utils": "^2.2.4",
|
"@vue/test-utils": "^2.2.4",
|
||||||
"@vue/tsconfig": "^0.1.3",
|
"@vue/tsconfig": "^0.1.3",
|
||||||
"cypress": "^13.1.0",
|
"cypress": "^12.12.0",
|
||||||
"eslint": "^8.29.0",
|
"eslint": "^8.29.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-import-resolver-typescript": "^3.5.5",
|
"eslint-import-resolver-typescript": "^3.5.5",
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"eslint-plugin-vue": "^9.8.0",
|
"eslint-plugin-vue": "^9.8.0",
|
||||||
"jest": "^29.6.4",
|
|
||||||
"jsdom": "^20.0.3",
|
"jsdom": "^20.0.3",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"less-loader": "^11.1.3",
|
"less-loader": "^11.1.3",
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import { RouterView } from 'vue-router'
|
|||||||
import { useMeta } from 'vue-meta'
|
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 { useCookies } from 'vue3-cookies'
|
||||||
import { title } from '@/utils/index'
|
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()
|
||||||
|
const { cookies } = useCookies()
|
||||||
|
|
||||||
let focusMap = ref<string>('focus-map')
|
let focusMap = ref<string>('focus-map')
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ defineProps({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.default {
|
.default {
|
||||||
height: toRem(3);
|
height: toRem(3.5);
|
||||||
min-width: toRem(3.5);
|
min-width: toRem(3.5);
|
||||||
@include text(s-regular);
|
@include text(s-regular);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="entry-edit">
|
<div class="entry-edit">
|
||||||
<form
|
<form
|
||||||
v-if="isEditTitle && !isDisabled"
|
v-if="isEditTitle"
|
||||||
@submit.prevent="isEditTitle = false"
|
@submit.prevent="isEditTitle = false"
|
||||||
class="edit-form"
|
class="edit-form"
|
||||||
>
|
>
|
||||||
@@ -34,7 +34,6 @@
|
|||||||
look="no-text"
|
look="no-text"
|
||||||
icon="bi bi-pen"
|
icon="bi bi-pen"
|
||||||
:tooltip="$t('pages.upload.edit_title_tooltip')"
|
:tooltip="$t('pages.upload.edit_title_tooltip')"
|
||||||
:disabled="isDisabled"
|
|
||||||
@trigger="goToEditMode"
|
@trigger="goToEditMode"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,9 +49,7 @@ const emit = defineEmits<{
|
|||||||
(e: 'triggerNewText', value: string | null): void
|
(e: 'triggerNewText', value: string | null): void
|
||||||
}>()
|
}>()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
defaultText: { type: String, default: null },
|
defaultText: { type: String, default: null }
|
||||||
isLoading: { type: Boolean, default: false },
|
|
||||||
isLoaded: { type: Boolean, default: false }
|
|
||||||
})
|
})
|
||||||
let titleToEdit = ref<string | null>(null)
|
let titleToEdit = ref<string | null>(null)
|
||||||
let isEditTitle = ref<boolean>(false)
|
let isEditTitle = ref<boolean>(false)
|
||||||
@@ -78,8 +75,6 @@ const text = computed<string | null>(() => {
|
|||||||
if (props.defaultText) return props.defaultText
|
if (props.defaultText) return props.defaultText
|
||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
const isDisabled = computed<boolean>(() => props.isLoading && !props.isLoaded)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const emit = defineEmits<{ (e: 'input', value: string): void }>()
|
const emit = defineEmits<{ (e: 'input', value: string): void }>()
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
text: { type: String, default: null },
|
text: { type: String, default: null },
|
||||||
placeholder: { type: String, default: '' }
|
placeholder: { type: String, default: '' }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const titleImg = computed<string>(() =>
|
const titleImg = computed<string>(() =>
|
||||||
props.disabled ? t('general.header.about_text') : ''
|
props.disabled ? t('general.header.contribute_text') : ''
|
||||||
)
|
)
|
||||||
function triggerButton() {
|
function triggerButton() {
|
||||||
if (props.disabled) return
|
if (props.disabled) return
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li v-for="item in uploadErrors" class="error-item">
|
<li v-for="item in uploadErrors" class="error-item">
|
||||||
<span>{{ item.name }} - </span>
|
<span>{{ item.name }} - </span>
|
||||||
<span>{{ item.details.error }}</span>
|
<span>{{ item.message }}</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -108,23 +108,17 @@ onMounted(async () => {
|
|||||||
style
|
style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const bbox = [props.bbox[0], props.bbox[1], props.bbox[2], props.bbox[3]]
|
|
||||||
viewer.value = new StandaloneMap(
|
viewer.value = new StandaloneMap(
|
||||||
'viewer', // Div ID
|
'viewer', // Div ID
|
||||||
`${import.meta.env.VITE_API_URL}/api/search`,
|
`${import.meta.env.VITE_API_URL}/api/search`,
|
||||||
{
|
{
|
||||||
...paramsMap,
|
...paramsMap,
|
||||||
bounds: bbox,
|
bounds: [props.bbox[0], props.bbox[1], props.bbox[2], props.bbox[3]],
|
||||||
zoom: 14
|
zoom: 9
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
viewer.value.addEventListener('ready', () => {
|
viewer.value.addEventListener('ready', () => {
|
||||||
viewer.value.setFilters({ user: props.userId }, true)
|
viewer.value.setFilters({ user: props.userId }, true)
|
||||||
viewer.value.fitBounds(bbox, {
|
|
||||||
padding: { top: 70, bottom: 70, left: 70, right: 70 },
|
|
||||||
maxZoom: 14,
|
|
||||||
speed: 10
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mapIsLoaded.value = true
|
mapIsLoaded.value = true
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ ul {
|
|||||||
width: toRem(25);
|
width: toRem(25);
|
||||||
top: toRem(8);
|
top: toRem(8);
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 3;
|
z-index: 2;
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
box-shadow: 0 toRem(0.2) toRem(0.4) rgb(0 0 0 / 10%);
|
box-shadow: 0 toRem(0.2) toRem(0.4) rgb(0 0 0 / 10%);
|
||||||
border-radius: toRem(1);
|
border-radius: toRem(1);
|
||||||
|
|||||||
@@ -137,7 +137,7 @@
|
|||||||
"description_title_sequence": "Le titre d'une séquence est par défaut la date du jour. Vous pouvez, si vous le souhaitez le modifier ci-dessous.",
|
"description_title_sequence": "Le titre d'une séquence est par défaut la date du jour. Vous pouvez, si vous le souhaitez le modifier ci-dessous.",
|
||||||
"text_import": "Déposez ici vos fichiers jpg. Chaque image ou série d’images constitue une « séquence ». Vous pourrez ensuite les retrouver dans la section « mes images » et choisir de les masquer, les afficher ou les supprimer.",
|
"text_import": "Déposez ici vos fichiers jpg. Chaque image ou série d’images constitue une « séquence ». Vous pourrez ensuite les retrouver dans la section « mes images » et choisir de les masquer, les afficher ou les supprimer.",
|
||||||
"subtitle_process": "Traitements de l'import",
|
"subtitle_process": "Traitements de l'import",
|
||||||
"uploading_process": "Envoi en cours...",
|
"uploading_process": "Téléchargement en cours...",
|
||||||
"sequence_title": "Séquence du ",
|
"sequence_title": "Séquence du ",
|
||||||
"import": "Imports",
|
"import": "Imports",
|
||||||
"upload_pending": "Transfert en cours...",
|
"upload_pending": "Transfert en cours...",
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
"edit_title_tooltip": "Modifier le titre de la séquence",
|
"edit_title_tooltip": "Modifier le titre de la séquence",
|
||||||
"edit_placeholder_input": "Modifier le titre de la séquence",
|
"edit_placeholder_input": "Modifier le titre de la séquence",
|
||||||
"ok_button": "Valider",
|
"ok_button": "Valider",
|
||||||
"pictures_error": "{count} image n'a pas pu être chargée| {count} images n'ont pas pu être chargées",
|
"pictures_error": "{count} image n'a pas pu être chargée| {count} image n'ont pas pu être chargées",
|
||||||
"sequence_loading_information": "Une fois chargée, la séquence sera en traitement et accessible sur Panoramax dans les prochaines minutes.",
|
"sequence_loading_information": "Une fois chargée, la séquence sera en traitement et accessible sur Panoramax dans les prochaines minutes.",
|
||||||
"sequence_loaded_information": "La séquence est chargée et est en cours de traitement. Elle sera accessible sur Panoramax dans quelques minutes.",
|
"sequence_loaded_information": "La séquence est chargée et est en cours de traitement. Elle sera accessible sur Panoramax dans quelques minutes.",
|
||||||
"leave_message": "⚠️ Attention, le téléchargement sera interrompu si vous quittez la page avant la fin.",
|
"leave_message": "⚠️ Attention, le téléchargement sera interrompu si vous quittez la page avant la fin.",
|
||||||
|
|||||||
@@ -1,184 +0,0 @@
|
|||||||
{
|
|
||||||
"general": {
|
|
||||||
"title": "Panoramax-példány",
|
|
||||||
"meta": {
|
|
||||||
"title": "Panoramax-példány",
|
|
||||||
"description": "Panoramax, szabad alternatíva a világ fotós feltérképezéséhez"
|
|
||||||
},
|
|
||||||
"header": {
|
|
||||||
"login_text": "Kapcsolódás",
|
|
||||||
"register_text": "Regisztráció",
|
|
||||||
"contribute_text": "Miért működjön közre?",
|
|
||||||
"my_account": "Saját fiók",
|
|
||||||
"upload_text": "+ Fényképek megosztása",
|
|
||||||
"sequences_text": "Saját fényképek",
|
|
||||||
"alt_logo": "A példány logója",
|
|
||||||
"alt_photos": "Képek ikon",
|
|
||||||
"alt_information": "Felhasználó ikon",
|
|
||||||
"alt_settings": "Paraméterek ikon",
|
|
||||||
"alt_logout": "Kijelentkezés ikon",
|
|
||||||
"title": "Panoramax",
|
|
||||||
"beta_text": "Béta verzió",
|
|
||||||
"logout_text": "Kijelentkezés",
|
|
||||||
"my_information_text": "Saját adatok",
|
|
||||||
"my_settings_text": "Saját beállítások",
|
|
||||||
"burger_menu_aria_label_open": "A menü megjelenítése",
|
|
||||||
"burger_menu_aria_label_closed": "A menü bezárása"
|
|
||||||
},
|
|
||||||
"footer": {
|
|
||||||
"panoramax_site": "A Panoramax felfedezése",
|
|
||||||
"information_gitlab": "Forráskód megjelenítése",
|
|
||||||
"gitlab_logo": "Gitlab logó",
|
|
||||||
"ay11_text": "Akadálymentesítés: nem felel meg"
|
|
||||||
},
|
|
||||||
"error_text": "Hiba történt",
|
|
||||||
"success_text": "Sikeres frissítés"
|
|
||||||
},
|
|
||||||
"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": "Fénykép jelentése"
|
|
||||||
},
|
|
||||||
"settings": {
|
|
||||||
"title": "Saját tokenek",
|
|
||||||
"setting_tooltip": "A token megjelenítése vagy elrejtése"
|
|
||||||
},
|
|
||||||
"sequence": {
|
|
||||||
"sequence_published": "Közzétéve",
|
|
||||||
"sequence_waiting": "Feldolgozás alatt",
|
|
||||||
"sequence_hidden": "Rejtett",
|
|
||||||
"hide_sequence_tooltip": "A sorozat elrejtése",
|
|
||||||
"delete_sequence_tooltip": "A sorozat végleges törlése",
|
|
||||||
"hide_photo_tooltip": "A kiválasztott fényképek elrejtése",
|
|
||||||
"delete_photo_tooltip": "A kiválasztottt fényképek végleges törlése",
|
|
||||||
"confirm_pictures_dialog": "⚠️ A kiválasztott fényképek véglegesen elvesznek",
|
|
||||||
"confirm_sequence_dialog": "⚠️ A kiválasztott sorozat véglegesen elvész",
|
|
||||||
"created": "Feltöltés ideje:",
|
|
||||||
"taken": "Elkészítés ideje:",
|
|
||||||
"duration": "Hossz:",
|
|
||||||
"duration_begin": "Kezdet:",
|
|
||||||
"duration_end": "Vég:",
|
|
||||||
"camera": "Kamera:",
|
|
||||||
"button_delete": "Törlés",
|
|
||||||
"button_disable": "Elrejtés",
|
|
||||||
"button_enable": "Megjelenítés",
|
|
||||||
"picture_selected": "{count} fénykép kiválasztva| {count} fénykép kiválasztva",
|
|
||||||
"hours": "{count} óra| {count} óra",
|
|
||||||
"minutes": "{count} perc| {count} perc",
|
|
||||||
"seconds": "{count} másodperc| {count} másodperc",
|
|
||||||
"select_text": "Kiválasztás",
|
|
||||||
"unselect_text": "Kiválasztás törlése",
|
|
||||||
"select_shift_text": "Több elemet a Shift segítségével választhat ki",
|
|
||||||
"waiting_process": "A fénykép feldolgozás alatt áll",
|
|
||||||
"broken": "Fénykép-feldolgozási hiba",
|
|
||||||
"no_image": "Nincsenek fényképek ebben a sorozatban"
|
|
||||||
},
|
|
||||||
"sequences": {
|
|
||||||
"title": "Saját fényképsorozatok",
|
|
||||||
"sequence_name": "Név",
|
|
||||||
"sequence_photos": "Fényképek",
|
|
||||||
"sequence_date": "Elkészítés ideje",
|
|
||||||
"sequence_creation": "Feltöltés ideje",
|
|
||||||
"sequence_status": "Állapot",
|
|
||||||
"sequence_published": "Közzétéve",
|
|
||||||
"sequence_waiting": "Feldolgozás alatt",
|
|
||||||
"sequence_hidden": "Rejtett",
|
|
||||||
"no_sequences_text": "Még nincsenek közzétett fényképei \uD83D\uDE22",
|
|
||||||
"button_upload": "Fényképek feltöltése",
|
|
||||||
"sequence_deleted": "A sorozat törlésre került"
|
|
||||||
},
|
|
||||||
"share_pictures": {
|
|
||||||
"title": "Miért működjön közre a Panoramaxban?",
|
|
||||||
"description": "A Panoramaxban való közreműködés azt jelenti, hogy részt vesz egy közös, független, szabad és újrafelhasználható digitális erőforrás fejlesztésében. A Panoramaxon található minden georeferált fénykép bárki által használható, számos célra, például egy önkormányzat megtekintheti az utai állapotát, vagy egy távközlési vállalat felkészülhet a beavatkozásaira.\n\nMinden közreműködő beküldheti a saját képsorozatait, módosíthatja és megnézheti azokat, ahogyan ezt teheti a közösség más tagjai által feltöltött képekkel is. Az arcok és rendszámtáblák kötelező kitakarását maga a platform automatizálja.",
|
|
||||||
"alt_img_map": "Illusztráció egy nőről, aki egy térképet néz a földrajzi helymeghatározással rendelkező okostelefonján",
|
|
||||||
"card_photo1": "Közútról látható helyek",
|
|
||||||
"card_photo2": "Közzétett fényképek 360°-os vagy más formátumban",
|
|
||||||
"card_photo3": "Könnyen újrafelhasználható fényképek",
|
|
||||||
"card_photo4": "Képek gyors és egyszerű megosztása",
|
|
||||||
"card_alt_photo1": "Egy épületet tartalmazó kép",
|
|
||||||
"card_alt_photo2": "Egy 360°-ot megjelenítő kép",
|
|
||||||
"card_alt_photo3": "Egy kép egy térképről mutatóval",
|
|
||||||
"card_alt_photo4": "Egy mutatót ábrázoló kép",
|
|
||||||
"card_description1": "Minden közútról készült kép elfogadható, ha az georeferált és a földről készült.",
|
|
||||||
"card_description2": "A 360°-os képek nem kötelezők: az okostelefonnal készült képek is megfelelők. Az előfeltételek a dátum, a helyszín és a jpg formátum használata.",
|
|
||||||
"card_description3": "Minden fénykép fiók nélkül is könnyedén elérhető és felhasználható: a weboldalon vagy egy szabványos API-n keresztül (STAC szabvány).",
|
|
||||||
"card_description4": "Számos eszköz elérhető a közreműködések lehetővé tételéhez, köztük egy parancssoros és egy webes felület is.",
|
|
||||||
"upload_subtitle": "Töltse fel egyszerűen a fényképeit",
|
|
||||||
"upload_illustration_alt": "Online képfeltöltést ábrázoló illusztráció",
|
|
||||||
"upload_description": "A Panoramax webalkalmazása lehetővé teszi, hogy egy gombnyomással feltöltse az összes fényképét JPG formátumban. Programozói készségek nem szükségesek. Sok kép esetén viszont a parancssoros eszköz használatát javasoljuk.",
|
|
||||||
"upload_button": "+ Képek feltöltése",
|
|
||||||
"command_line_subtitle": "Parancssoros eszköz",
|
|
||||||
"comment_install": "A geovisio parancssoros eszköz telepítése",
|
|
||||||
"comment_upload": "A képfeltöltési parancs indítása a kiválasztott mappán",
|
|
||||||
"description_terminal": "<a href='https://gitlab.com/geovisio/cli' target='_blank' style='color:black'>A parancssor</a> lehetővé teszi, hogy nagy számú képet osszon meg. A folyamat egyszerű, és <a target='_blank' href='https://www.python.org/downloads/' style='color:black'>Pythont (3.8-as vagy újabb verzió)</a> igényli.\n\nAz importálás előtt az eszköz bekéri a bejelentkezési adatait. Amint a képek felöltésre kerültek, azok közzététele előtt feldolgozási idő szükséges.",
|
|
||||||
"terminal_install": "pip install geovisio_cli",
|
|
||||||
"terminal_text": "geovisio upload --api-url {webcím} <FÉNYKÉPMAPPA>",
|
|
||||||
"button_copy": "Másolás",
|
|
||||||
"information_subtitle": "Itt a fényképek mindenki számára elérhetők: ",
|
|
||||||
"information_text1": "Automatikusan kitakarva, a törvényi előírásoknak megfelelően.",
|
|
||||||
"information_text2": "A feltöltött képek a következő alatt lesznek közzétéve: {word}",
|
|
||||||
"information_text3": "Az eredeti formátumban és felbontásban, számos újrafeldolgozáshoz.",
|
|
||||||
"information_about_title": "Hozzá kell férnie a fényképeihez?",
|
|
||||||
"information_about_description": "Az API elérhető az összes metaadat és kép letöltéséhez. <a href='{docLink}' target='_blank' style='color:#0a1f69'>\nTudjon meg többet itt.</a>\nAz adatok <a href='{docTiles}' target='_blank' style='color:#0a1f69'>vektorcsempék</a> formájában is megjelennek.",
|
|
||||||
"doc_subtitle": "Segítségre van szüksége a Panoramaxban történő közreműködéshez?",
|
|
||||||
"doc_description": "A Panoramax dokumentációja elérhető tőlünk, oktatóanyagokat pedig a geo-commons fórumán találhat.",
|
|
||||||
"doc_button": "A dokumentáció megtekintése",
|
|
||||||
"doc_illustration_alt": "Illusztráció egy karakterről dokumentumokkal"
|
|
||||||
},
|
|
||||||
"upload": {
|
|
||||||
"title": "Közreműködés a Panoramax projektben",
|
|
||||||
"description": "Nagy számú fényképhez a parancssoros eszköz jobban megfelelő.",
|
|
||||||
"know_more_button": "További tudnivalók",
|
|
||||||
"input_label": "Húzza ide a képeket, vagy kattintson a",
|
|
||||||
"import_word": "feltöltésre",
|
|
||||||
"import_type": "Csak JPEG formátum",
|
|
||||||
"subtitle_import": "Képfeltöltés",
|
|
||||||
"title_sequence": "Sorozat címe",
|
|
||||||
"description_title_sequence": "Alapértelmezés szerint a sorozat cím a nap dátuma lesz. Ha akarja, itt szerkesztheti a címet.",
|
|
||||||
"text_import": "Ide töltse fel a JPG-fájljait. Minden kép vagy képsorozat egy „sorozatot” alkot. Megtalálhatja azokat a „saját fényképek” szakaszban, és elrejtheti, megjelenítheti vagy törölheti azokat.",
|
|
||||||
"subtitle_process": "Feltöltés feldolgozása",
|
|
||||||
"uploading_process": "Feltöltés folyamatban…",
|
|
||||||
"sequence_title": "Sorozat ",
|
|
||||||
"import": "Feltöltések",
|
|
||||||
"upload_pending": "Feltöltés folyamatban…",
|
|
||||||
"images_count_text": "Feltöltött képek",
|
|
||||||
"no_img_text": "még nem volt képfeltöltés",
|
|
||||||
"upload_done": "A sorozat feltöltése elkészült",
|
|
||||||
"sequence_link": "A sorozat megjelenítése",
|
|
||||||
"edit_title_tooltip": "A sorozat címének szerkesztése",
|
|
||||||
"edit_placeholder_input": "A sorozat címének szerkesztése",
|
|
||||||
"ok_button": "OK",
|
|
||||||
"pictures_error": "{count} kép feltöltése nem sikerült| {count} kép feltöltése nem sikerült",
|
|
||||||
"sequence_loading_information": "Amint feltöltötte, a sorozat feldolgozásra, majd közzétételre került a Panoramaxon (általában néhány perc múlva).",
|
|
||||||
"sequence_loaded_information": "A sorozatok fel lettek töltve, és feldolgozás alatt vannak. Néhány perc múlva nyilvánosan elérhetőnek kellene lenniük a Panoramaxon.",
|
|
||||||
"leave_message": "⚠️ FIGYELMEZTETÉS, a feltöltés meg fog szakadni, ha a végezte előtt hagyja el a lapot.",
|
|
||||||
"error_button": "Hibák megjelenítése",
|
|
||||||
"modal_error_title": "A hibában érintett képek"
|
|
||||||
},
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,12 +4,12 @@ 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 { globalCookiesConfig } from 'vue3-cookies'
|
||||||
import { createMetaManager } from 'vue-meta'
|
import { createMetaManager } from 'vue-meta'
|
||||||
import { VueDraggableResizable } from 'vue-draggable-resizable-vue3'
|
import { VueDraggableResizable } from 'vue-draggable-resizable-vue3'
|
||||||
import { pinia } from './store'
|
import { pinia } from './store'
|
||||||
import fr from './locales/fr.json'
|
import fr from './locales/fr.json'
|
||||||
import en from './locales/en.json'
|
import en from './locales/en.json'
|
||||||
import hu from './locales/hu.json'
|
|
||||||
import './assets/main.scss'
|
import './assets/main.scss'
|
||||||
import 'bootstrap/dist/css/bootstrap.css'
|
import 'bootstrap/dist/css/bootstrap.css'
|
||||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||||
@@ -26,10 +26,12 @@ const i18n = createI18n({
|
|||||||
legacy: false,
|
legacy: false,
|
||||||
messages: {
|
messages: {
|
||||||
fr,
|
fr,
|
||||||
en,
|
en
|
||||||
hu
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
globalCookiesConfig({
|
||||||
|
expireTimes: '7d'
|
||||||
|
})
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import { useCookies } from 'vue3-cookies'
|
||||||
import type {
|
import type {
|
||||||
RouteRecordRaw,
|
RouteRecordRaw,
|
||||||
NavigationGuardNext,
|
NavigationGuardNext,
|
||||||
@@ -14,6 +15,7 @@ import MySequenceView from '../views/MySequenceView.vue'
|
|||||||
import SharePicturesView from '../views/SharePicturesView.vue'
|
import SharePicturesView from '../views/SharePicturesView.vue'
|
||||||
import UploadPicturesView from '../views/UploadPicturesView.vue'
|
import UploadPicturesView from '../views/UploadPicturesView.vue'
|
||||||
import Ay11View from '../views/Ay11View.vue'
|
import Ay11View from '../views/Ay11View.vue'
|
||||||
|
const { cookies } = useCookies()
|
||||||
let routes: Array<RouteRecordRaw> = [
|
let routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|||||||
@@ -30,13 +30,7 @@ describe('Template', () => {
|
|||||||
})
|
})
|
||||||
it('should render the props filled', async () => {
|
it('should render the props filled', async () => {
|
||||||
document.body.innerHTML = '<div id="bs-modal"></div>'
|
document.body.innerHTML = '<div id="bs-modal"></div>'
|
||||||
const uploadErrors = [
|
const uploadErrors = [{ message: 'my message', name: 'my name' }]
|
||||||
{
|
|
||||||
details: { error: 'my error' },
|
|
||||||
message: 'my message',
|
|
||||||
name: 'my name'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
const wrapper = shallowMount(Modal, {
|
const wrapper = shallowMount(Modal, {
|
||||||
global: {
|
global: {
|
||||||
plugins: [i18n],
|
plugins: [i18n],
|
||||||
@@ -51,7 +45,7 @@ describe('Template', () => {
|
|||||||
|
|
||||||
expect(wrapper.vm.uploadErrors).toEqual(uploadErrors)
|
expect(wrapper.vm.uploadErrors).toEqual(uploadErrors)
|
||||||
expect(wrapper.html()).contains('my name - ')
|
expect(wrapper.html()).contains('my name - ')
|
||||||
expect(wrapper.html()).contains('my error')
|
expect(wrapper.html()).contains('my message')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ function fullImagesToDelete(): ResponseUserPhotoInterface[] {
|
|||||||
return pictures.value.filter((el) => picturesToDelete.value.includes(el.id))
|
return pictures.value.filter((el) => picturesToDelete.value.includes(el.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function goToNextPage(value: string): Promise<void> {
|
async function goToNextPage(value: string) {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
const { data } = await fetchCollectionItemsWithFullUrl(value)
|
const { data } = await fetchCollectionItemsWithFullUrl(value)
|
||||||
selfLink.value = data.links.filter((el) => el.rel === 'self')
|
selfLink.value = data.links.filter((el) => el.rel === 'self')
|
||||||
|
|||||||
@@ -26,52 +26,61 @@
|
|||||||
/>
|
/>
|
||||||
</vue-draggable-resizable>
|
</vue-draggable-resizable>
|
||||||
</section>
|
</section>
|
||||||
<section
|
<section :style="{ width: `${listWidth}px` }" class="section-sequence">
|
||||||
:style="{ width: `${listWidth}px` }"
|
<h1 class="sequences-title">{{ $t('pages.sequences.title') }}</h1>
|
||||||
class="section-sequence"
|
<ul v-if="!isLoading" class="sequence-list">
|
||||||
@scroll="handleScroll"
|
<li class="sequence-item sequence-item-head">
|
||||||
>
|
<div class="sequence-header-item"></div>
|
||||||
<h1 id="sequenceTitle" class="sequences-title">
|
<div class="sequence-header-item">
|
||||||
{{ $t('pages.sequences.title') }}
|
<Button
|
||||||
</h1>
|
:text="$t('pages.sequences.sequence_name')"
|
||||||
<div
|
look="link--grey"
|
||||||
ref="headerList"
|
icon="bi bi-arrow-down-up"
|
||||||
:class="['sequence-item sequence-item-head', headerListClass]"
|
data-test="button-sort-title"
|
||||||
:style="{ width: `${listWidth}px`, borderRadius: '0px' }"
|
@trigger="sortAlpha('title')"
|
||||||
>
|
/>
|
||||||
<div class="sequence-header-item"></div>
|
</div>
|
||||||
<div class="sequence-header-item">
|
<div class="sequence-header-item">
|
||||||
<span>{{ $t('pages.sequences.sequence_name') }}</span>
|
<Button
|
||||||
</div>
|
:text="$t('pages.sequences.sequence_photos')"
|
||||||
<div class="sequence-header-item">
|
look="link--grey"
|
||||||
<span>{{ $t('pages.sequences.sequence_photos') }}</span>
|
icon="bi bi-arrow-down-up"
|
||||||
</div>
|
data-test="button-sort-number"
|
||||||
<div class="sequence-header-item">
|
@trigger="sortNum('num')"
|
||||||
<Button
|
/>
|
||||||
:text="$t('pages.sequences.sequence_date')"
|
</div>
|
||||||
look="link--grey"
|
<div class="sequence-header-item">
|
||||||
icon="bi bi-arrow-down-up"
|
<Button
|
||||||
data-test="button-sort-date"
|
:text="$t('pages.sequences.sequence_date')"
|
||||||
@trigger="sortList('datetime')"
|
look="link--grey"
|
||||||
/>
|
icon="bi bi-arrow-down-up"
|
||||||
</div>
|
data-test="button-sort-date"
|
||||||
<div class="sequence-header-item">
|
@trigger="sortNum('date')"
|
||||||
<Button
|
/>
|
||||||
:text="$t('pages.sequences.sequence_creation')"
|
</div>
|
||||||
look="link--grey"
|
<div class="sequence-header-item">
|
||||||
icon="bi bi-arrow-down-up"
|
<Button
|
||||||
data-test="button-sort-date"
|
:text="$t('pages.sequences.sequence_creation')"
|
||||||
@trigger="sortList('created')"
|
look="link--grey"
|
||||||
/>
|
icon="bi bi-arrow-down-up"
|
||||||
</div>
|
data-test="button-sort-date"
|
||||||
<div class="sequence-header-item">
|
@trigger="sortNum('date', 'created')"
|
||||||
<span>{{ $t('pages.sequences.sequence_status') }}</span>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="sequence-header-item">
|
||||||
<ul v-if="!isLoading" ref="list" class="sequence-list">
|
<Button
|
||||||
|
:text="$t('pages.sequences.sequence_status')"
|
||||||
|
look="link--grey"
|
||||||
|
icon="bi bi-arrow-down-up"
|
||||||
|
data-test="button-sort-date"
|
||||||
|
@trigger="sortAlpha('geovisio:status')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
v-if="userSequences.length"
|
v-if="userSequences.length"
|
||||||
v-for="item in userSequences"
|
v-for="(item, i) in userSequences"
|
||||||
|
:id="`el-list${i}`"
|
||||||
:class="[
|
:class="[
|
||||||
'sequence-item',
|
'sequence-item',
|
||||||
item.id === seqId ? 'button-item-hover' : ''
|
item.id === seqId ? 'button-item-hover' : ''
|
||||||
@@ -170,29 +179,17 @@
|
|||||||
<div v-else class="loader">
|
<div v-else class="loader">
|
||||||
<Loader look="sm" :is-loaded="false" />
|
<Loader look="sm" :is-loaded="false" />
|
||||||
</div>
|
</div>
|
||||||
<div class="entry-pagination">
|
|
||||||
<Pagination
|
|
||||||
v-for="item in paginationLinks"
|
|
||||||
:type="item.rel"
|
|
||||||
:href="item.href"
|
|
||||||
:self-link="selfLink[0]"
|
|
||||||
@trigger="goToNextPage"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Toast :text="toastText" :look="toastLook" @trigger="toastText = ''" />
|
<Toast :text="toastText" :look="toastLook" @trigger="toastText = ''" />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, watchEffect, computed, nextTick } from 'vue'
|
import { onMounted, ref, watchEffect, computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useSequenceStore } from '@/store/sequence'
|
import { useSequenceStore } from '@/store/sequence'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import {
|
import { scrollIntoSelected } from '@/views/utils/sequence/index'
|
||||||
scrollIntoSelected,
|
|
||||||
formatPaginationItems
|
|
||||||
} from '@/views/utils/sequence/index'
|
|
||||||
import { useCookies } from 'vue3-cookies'
|
import { useCookies } from 'vue3-cookies'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import Viewer from '@/components/Viewer.vue'
|
import Viewer from '@/components/Viewer.vue'
|
||||||
@@ -200,33 +197,23 @@ import Button from '@/components/Button.vue'
|
|||||||
import Link from '@/components/Link.vue'
|
import Link from '@/components/Link.vue'
|
||||||
import Toast from '@/components/Toast.vue'
|
import Toast from '@/components/Toast.vue'
|
||||||
import Loader from '@/components/Loader.vue'
|
import Loader from '@/components/Loader.vue'
|
||||||
import Pagination from '@/components/Pagination.vue'
|
import type {
|
||||||
import type { SequenceLinkInterface } from './interfaces/MySequencesView'
|
SequenceLinkInterface,
|
||||||
import type { ResponseUserPhotoLinksInterface } from './interfaces/MySequenceView'
|
ExtentSequenceLinkInterface
|
||||||
|
} from './interfaces/MySequencesView'
|
||||||
import { formatDate } from '@/utils/dates'
|
import { formatDate } from '@/utils/dates'
|
||||||
import {
|
import {
|
||||||
deleteACollection,
|
deleteACollection,
|
||||||
patchACollection
|
patchACollection
|
||||||
} from '@/views/utils/sequence/request'
|
} from '@/views/utils/sequence/request'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { cookies } = useCookies()
|
const { cookies } = useCookies()
|
||||||
const sequenceStore = useSequenceStore()
|
const sequenceStore = useSequenceStore()
|
||||||
const { toastText, toastLook } = storeToRefs(sequenceStore)
|
const { toastText, toastLook } = storeToRefs(sequenceStore)
|
||||||
interface PositionInterface {
|
|
||||||
bottom: number
|
|
||||||
top: number
|
|
||||||
right: number
|
|
||||||
left: number
|
|
||||||
y: number
|
|
||||||
x: number
|
|
||||||
}
|
|
||||||
let userSequences = ref<SequenceLinkInterface[]>([])
|
let userSequences = ref<SequenceLinkInterface[]>([])
|
||||||
let paginationLinks = ref<ResponseUserPhotoLinksInterface[] | []>([])
|
|
||||||
let selfLink = ref<ResponseUserPhotoLinksInterface[] | []>([])
|
|
||||||
let collectionBbox = ref<number[]>([])
|
let collectionBbox = ref<number[]>([])
|
||||||
let isLoading = ref<boolean>(false)
|
|
||||||
let isSorted = ref<boolean>(false)
|
let isSorted = ref<boolean>(false)
|
||||||
|
let isLoading = ref<boolean>(false)
|
||||||
let seqId = ref<string>('')
|
let seqId = ref<string>('')
|
||||||
let width = ref<number>(0)
|
let width = ref<number>(0)
|
||||||
let mapWidth = ref<number>(window.innerWidth / 3)
|
let mapWidth = ref<number>(window.innerWidth / 3)
|
||||||
@@ -234,10 +221,6 @@ let listWidth = ref<number>(window.innerWidth / 1.5)
|
|||||||
const windowWidth = ref<number>(window.innerWidth)
|
const windowWidth = ref<number>(window.innerWidth)
|
||||||
const windowHeight = ref<number>(window.innerHeight - 80)
|
const windowHeight = ref<number>(window.innerHeight - 80)
|
||||||
const viewerRef = ref<any>(null)
|
const viewerRef = ref<any>(null)
|
||||||
const headerList = ref<any>(null)
|
|
||||||
const list = ref<any>(null)
|
|
||||||
const listPos = ref<PositionInterface | null>(null)
|
|
||||||
const headerLisPos = ref<PositionInterface | null>(null)
|
|
||||||
|
|
||||||
async function fetchAndFormatSequence(): Promise<void> {
|
async function fetchAndFormatSequence(): Promise<void> {
|
||||||
const { data } = await axios.get('api/users/me/collection')
|
const { data } = await axios.get('api/users/me/collection')
|
||||||
@@ -271,110 +254,63 @@ function sequenceStatus(status: string): string {
|
|||||||
if (status === 'hidden') return t('pages.sequences.sequence_hidden')
|
if (status === 'hidden') return t('pages.sequences.sequence_hidden')
|
||||||
return t('pages.sequences.sequence_waiting')
|
return t('pages.sequences.sequence_waiting')
|
||||||
}
|
}
|
||||||
function onResizeMap(width: any): void {
|
function sortAlpha<TKey extends keyof SequenceLinkInterface>(key: TKey): void {
|
||||||
|
const sorted = userSequences.value.sort(
|
||||||
|
(
|
||||||
|
a: { [K in TKey]: SequenceLinkInterface[TKey] },
|
||||||
|
b: { [K in TKey]: SequenceLinkInterface[TKey] }
|
||||||
|
) => {
|
||||||
|
if (a[key] < b[key]) return !isSorted.value ? -1 : 1
|
||||||
|
if (a[key] > b[key]) return !isSorted.value ? 1 : -1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
isSorted.value = !isSorted.value
|
||||||
|
userSequences.value = sorted
|
||||||
|
}
|
||||||
|
function onResizeMap(width: any) {
|
||||||
if (width) {
|
if (width) {
|
||||||
width.value = width
|
width.value = width
|
||||||
mapWidth.value = width.value.width
|
mapWidth.value = width.value.width
|
||||||
listWidth.value = window.innerWidth - width.value.width
|
listWidth.value = window.innerWidth - width.value.width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const handleScroll = async () => {
|
function sortNum(type: string, dateToSort?: string): void {
|
||||||
await nextTick()
|
let aa, bb: number
|
||||||
if (headerList.value && headerList.value.getBoundingClientRect()) {
|
const sorted = userSequences.value.sort(
|
||||||
headerLisPos.value = headerList.value.getBoundingClientRect()
|
(a: ExtentSequenceLinkInterface, b: ExtentSequenceLinkInterface) => {
|
||||||
}
|
aa = new Date(a.extent.temporal.interval[0][0]).getTime()
|
||||||
if (list.value && list.value.getBoundingClientRect()) {
|
bb = new Date(b.extent.temporal.interval[0][0]).getTime()
|
||||||
listPos.value = list.value.getBoundingClientRect()
|
if (dateToSort === 'created') {
|
||||||
}
|
aa = new Date(a.created).getTime()
|
||||||
}
|
bb = new Date(b.created).getTime()
|
||||||
async function sortList(dateToSort: string): Promise<void> {
|
}
|
||||||
isLoading.value = true
|
if (type === 'num') {
|
||||||
let sortBy = `+${dateToSort}`
|
aa = Number(a['stats:items'].count)
|
||||||
if (isSorted.value) sortBy = `-${dateToSort}`
|
bb = Number(b['stats:items'].count)
|
||||||
const { data } = await axios.get(
|
}
|
||||||
`api/users/me/collection?limit=50&sortby=${encodeURIComponent(sortBy)}`
|
if (aa < bb) return !isSorted.value ? -1 : 1
|
||||||
|
if (aa > bb) return !isSorted.value ? 1 : -1
|
||||||
|
return 0
|
||||||
|
}
|
||||||
)
|
)
|
||||||
selfLink.value = data.links.filter(
|
|
||||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
|
||||||
)
|
|
||||||
paginationLinks.value = formatPaginationItems(data.links)
|
|
||||||
userSequences.value = getRelChild(data.links)
|
|
||||||
isSorted.value = !isSorted.value
|
isSorted.value = !isSorted.value
|
||||||
scrollToElement()
|
userSequences.value = sorted
|
||||||
isLoading.value = false
|
|
||||||
}
|
}
|
||||||
|
function goToSequence(sequence: SequenceLinkInterface) {
|
||||||
function bboxIsInsideOther(mainBbox: number[], bboxInside: number[]): boolean {
|
|
||||||
return (
|
|
||||||
bboxInside[0] <= mainBbox[0] &&
|
|
||||||
bboxInside[1] <= mainBbox[1] &&
|
|
||||||
bboxInside[2] >= mainBbox[2] &&
|
|
||||||
bboxInside[3] >= mainBbox[3]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
function goToSequence(sequence: SequenceLinkInterface): void {
|
|
||||||
seqId.value = sequence.id
|
seqId.value = sequence.id
|
||||||
viewerRef.value.viewer.select(seqId.value)
|
viewerRef.value.viewer.select(seqId.value)
|
||||||
const currentBbox = [
|
|
||||||
viewerRef.value.viewer._map.getBounds()._ne.lng,
|
|
||||||
viewerRef.value.viewer._map.getBounds()._ne.lat,
|
|
||||||
viewerRef.value.viewer._map.getBounds()._sw.lng,
|
|
||||||
viewerRef.value.viewer._map.getBounds()._sw.lat
|
|
||||||
]
|
|
||||||
if (bboxIsInsideOther(currentBbox, sequence.extent.spatial.bbox[0])) return
|
|
||||||
viewerRef.value.viewer._map.flyTo({
|
|
||||||
center: [
|
|
||||||
sequence.extent.spatial.bbox[0][0],
|
|
||||||
sequence.extent.spatial.bbox[0][1]
|
|
||||||
],
|
|
||||||
zoom: 10,
|
|
||||||
duration: 0
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
function getRelChild(
|
function getRelChild(sequences: SequenceLinkInterface[]) {
|
||||||
sequences: SequenceLinkInterface[]
|
|
||||||
): SequenceLinkInterface[] {
|
|
||||||
return sequences.filter((el: SequenceLinkInterface) => el.rel === 'child')
|
return sequences.filter((el: SequenceLinkInterface) => el.rel === 'child')
|
||||||
}
|
}
|
||||||
function scrollToElement(): void {
|
const getUserId = computed<string>(() => cookies.get('user_id'))
|
||||||
const elementTarget = document.querySelector('#sequenceTitle')
|
|
||||||
if (elementTarget) elementTarget.scrollIntoView({ behavior: 'smooth' })
|
|
||||||
}
|
|
||||||
async function goToNextPage(value: string): Promise<void> {
|
|
||||||
isLoading.value = true
|
|
||||||
const { data } = await axios.get(value)
|
|
||||||
selfLink.value = data.links.filter(
|
|
||||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
|
||||||
)
|
|
||||||
paginationLinks.value = formatPaginationItems(data.links)
|
|
||||||
userSequences.value = getRelChild(data.links)
|
|
||||||
scrollToElement()
|
|
||||||
isLoading.value = false
|
|
||||||
}
|
|
||||||
const getUserId = computed<string>((): string => cookies.get('user_id'))
|
|
||||||
const headerListClass = computed<string>((): string => {
|
|
||||||
if (headerLisPos.value && listPos.value) {
|
|
||||||
return headerLisPos.value.y != 0 && listPos.value.top < 180
|
|
||||||
? 'item-head-fixed'
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
return ''
|
|
||||||
})
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.get('api/users/me/collection?limit=50')
|
const { data } = await axios.get('api/users/me/collection')
|
||||||
selfLink.value = data.links.filter(
|
collectionBbox.value = data.extent.spatial.bbox[0]
|
||||||
(el: SequenceLinkInterface) => el.rel === 'self'
|
|
||||||
)
|
|
||||||
paginationLinks.value = formatPaginationItems(data.links)
|
|
||||||
userSequences.value = getRelChild(data.links)
|
userSequences.value = getRelChild(data.links)
|
||||||
collectionBbox.value = [
|
|
||||||
userSequences.value[0].extent.spatial.bbox[0][0],
|
|
||||||
userSequences.value[0].extent.spatial.bbox[0][1],
|
|
||||||
userSequences.value[0].extent.spatial.bbox[0][2],
|
|
||||||
userSequences.value[0].extent.spatial.bbox[0][3]
|
|
||||||
]
|
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
@@ -451,21 +387,25 @@ watchEffect(() => {
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
background-color: var(--blue-pale);
|
background-color: var(--blue-pale);
|
||||||
padding: toRem(2);
|
padding: toRem(2);
|
||||||
|
&:first-child {
|
||||||
|
margin-bottom: toRem(1);
|
||||||
|
padding: toRem(1) toRem(2);
|
||||||
|
border-bottom: toRem(0.1) solid var(--grey);
|
||||||
|
border-radius: toRem(2) toRem(2) 0rem 0rem;
|
||||||
|
background-color: var(--white);
|
||||||
|
}
|
||||||
&:nth-child(2n) {
|
&:nth-child(2n) {
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.wrapper-button {
|
.wrapper-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: toRem(1);
|
right: toRem(2);
|
||||||
bottom: 0;
|
bottom: toRem(2);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100%;
|
|
||||||
.button--white:first-child {
|
.button--white:first-child {
|
||||||
margin-bottom: toRem(1);
|
margin-right: toRem(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button-item-hover {
|
.button-item-hover {
|
||||||
@@ -480,21 +420,8 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.item-head-fixed {
|
|
||||||
position: fixed;
|
|
||||||
top: toRem(8);
|
|
||||||
width: 100%;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
.sequence-item-head {
|
|
||||||
margin-bottom: toRem(1);
|
|
||||||
padding: toRem(1) toRem(2);
|
|
||||||
border-bottom: toRem(0.1) solid var(--grey);
|
|
||||||
border-radius: toRem(2) toRem(2) 0rem 0rem;
|
|
||||||
background-color: var(--white);
|
|
||||||
}
|
|
||||||
.sequence-item-head:hover {
|
.sequence-item-head:hover {
|
||||||
background-color: var(--white);
|
background-color: initial;
|
||||||
color: initial;
|
color: initial;
|
||||||
}
|
}
|
||||||
.wrapper-title {
|
.wrapper-title {
|
||||||
@@ -570,6 +497,7 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
.sequence-header-item {
|
.sequence-header-item {
|
||||||
width: calc(31% - #{toRem(4.75)});
|
width: calc(31% - #{toRem(4.75)});
|
||||||
|
margin-left: toRem(-1);
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-right: toRem(2);
|
margin-right: toRem(2);
|
||||||
}
|
}
|
||||||
@@ -605,13 +533,6 @@ watchEffect(() => {
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
.entry-pagination {
|
|
||||||
margin-top: toRem(4);
|
|
||||||
margin-bottom: toRem(4);
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
@media (max-width: toRem(102.4)) {
|
@media (max-width: toRem(102.4)) {
|
||||||
.section-viewer {
|
.section-viewer {
|
||||||
width: 30%;
|
width: 30%;
|
||||||
@@ -633,7 +554,7 @@ watchEffect(() => {
|
|||||||
.section-sequence {
|
.section-sequence {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
.sequence-item-head {
|
.sequence-item:first-child {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.button-item {
|
.button-item {
|
||||||
@@ -655,17 +576,11 @@ watchEffect(() => {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.wrapper-button {
|
.wrapper-button {
|
||||||
flex-direction: row;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: toRem(1);
|
margin-top: toRem(1);
|
||||||
margin-bottom: 0;
|
|
||||||
.button--white:first-child {
|
|
||||||
margin-right: toRem(1);
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -41,8 +41,6 @@
|
|||||||
</p>
|
</p>
|
||||||
<EditText
|
<EditText
|
||||||
:default-text="newSequenceTitle || sequenceTitle"
|
:default-text="newSequenceTitle || sequenceTitle"
|
||||||
:is-loading="isLoading"
|
|
||||||
:is-loaded="isLoaded"
|
|
||||||
@triggerNewText="setNewSequenceTitle"
|
@triggerNewText="setNewSequenceTitle"
|
||||||
/>
|
/>
|
||||||
<form>
|
<form>
|
||||||
@@ -150,7 +148,7 @@ onUnmounted(() => {
|
|||||||
window.onbeforeunload = null
|
window.onbeforeunload = null
|
||||||
})
|
})
|
||||||
onBeforeRouteLeave((to, from, next) => {
|
onBeforeRouteLeave((to, from, next) => {
|
||||||
if (!isLoaded.value && isLoading.value) {
|
if (isLoading.value) {
|
||||||
const answer = window.confirm(t('pages.upload.leave_message'))
|
const answer = window.confirm(t('pages.upload.leave_message'))
|
||||||
if (answer) return next()
|
if (answer) return next()
|
||||||
return next(false)
|
return next(false)
|
||||||
@@ -240,7 +238,6 @@ async function uploadPicture(): Promise<void> {
|
|||||||
picturesUploadingSize.value = picturesUploadingSize.value + el.size
|
picturesUploadingSize.value = picturesUploadingSize.value + el.size
|
||||||
const picturesOnError = {
|
const picturesOnError = {
|
||||||
message: err.response.data.message,
|
message: err.response.data.message,
|
||||||
details: { error: err.response.data.details.error },
|
|
||||||
name: el.name
|
name: el.name
|
||||||
}
|
}
|
||||||
uploadedSequence.value.picturesOnError = [
|
uploadedSequence.value.picturesOnError = [
|
||||||
|
|||||||
@@ -5,7 +5,14 @@ export interface SequenceLinkInterface {
|
|||||||
title: string
|
title: string
|
||||||
type: string
|
type: string
|
||||||
created: Date
|
created: Date
|
||||||
extent: { temporal: { interval: [Date[]] }; spatial: { bbox: [number[]] } }
|
extent: { temporal: { interval: [Date[]] } }
|
||||||
['stats:items']: { count: number }
|
['stats:items']: { count: number }
|
||||||
['geovisio:status']: string
|
['geovisio:status']: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExtentSequenceLinkInterface {
|
||||||
|
extent: { temporal: { interval: [Date[]] } }
|
||||||
|
['stats:items']: { count: number }
|
||||||
|
title: string
|
||||||
|
created: Date
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ export interface SequenceInterface {
|
|||||||
}
|
}
|
||||||
export interface uploadErrorInterface {
|
export interface uploadErrorInterface {
|
||||||
message: string
|
message: string
|
||||||
details: { error: string }
|
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user