diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 876c6744..1f9c22b8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,13 +16,12 @@ jobs: python-version: '3.12' - name: "python backend - install requirements" - working-directory: srv/python run: | - pip install -r requirements.txt -r dev-requirements.txt - pip install -e . + pip install -r install/requirements.txt -r install/dev-requirements.txt + pip install -e ./src - name: "python backend - Checking format" - working-directory: srv/python + working-directory: src run: | black . --check diff --git a/.gitignore b/.gitignore index 1a375000..88d42693 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,46 @@ -# Byte-compiled / optimized / DLL files +# Python cache __pycache__/ *.py[cod] *$py.class -# test +# Test / tooling cache .pytest_cache/ .mypy_cache/ +# Build / packaging *.egg-info/ *.egg -srv/python/build +build/ +dist/ - -# IDE stuff -.idea -.vscode +# IDE +.idea/ +.vscode/ *.iml -# venv -**/venv +# Virtual environments +.venv/ +venv/ +env/ + +# Static config +src/static/config.json -# static (python backend) -srv/python/mviewerstudio_backend/static +# Logs +logs/ -# pyenv +# Pyenv .python-version -?venv/ + +# Docs pydocs* -# store +# App data store/ public/ -# npm -node* -package-* +# Node +node_modules/ +package-lock.json +yarn.lock +pnpm-lock.yaml \ No newline at end of file diff --git a/srv/python/.vscode/launch.json b/.vscode/launch.json similarity index 82% rename from srv/python/.vscode/launch.json rename to .vscode/launch.json index 4efb0c14..e838c8ec 100644 --- a/srv/python/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,11 +10,11 @@ "request": "launch", "module": "flask", "env": { - "FLASK_APP": "mviewerstudio_backend/app.py", + "FLASK_APP": "/home/user/git/mviewerstudio/src/app.py", "FLASK_DEBUG": "1", "CONF_PATH_FROM_MVIEWER":"apps/store", - "EXPORT_CONF_FOLDER":"/home/user/git/mviewer/apps/store/", - "MVIEWERSTUDIO_PUBLISH_PATH":"/home/user/git/mviewer/apps/public", + "EXPORT_CONF_FOLDER":"/home/gaetan/projects/mviewer/mviewer/apps/store/", + "MVIEWERSTUDIO_PUBLISH_PATH":"/home/gaetan/projects/mviewer/mviewer/apps/public", "CONF_PUBLISH_PATH_FROM_MVIEWER":"apps/public", "DEFAULT_ORG":"geobretagne", diff --git a/README.md b/README.md index 388ce34e..df808d13 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,55 @@ -# mviewerstudio +# đŸ—ș mviewerstudio -mviewer studio est une application web dont le but est de faciliter la crĂ©ation d'une configuration pour [mviewer](https://github.com/mviewer/mviewer) Ă  l'aide d'une interface graphique ergonomique et simple. +**mviewerstudio** est une application web qui facilite la crĂ©ation de configurations pour [mviewer](https://github.com/mviewer/mviewer) avec une interface graphique ergonomique et simple. -Application Ă©crite en Javascript pour le front. -2 backends disponibles : Ă©crits en Python pour l'un et en PHP pour l'autre. +- **Frontend** : JavaScript +- **Backend** : Python + Flask +- **Plateforme** : Linux -RĂ©fĂ©rez-vous Ă  la documentation pour plus d'information : +--- - * [Documentation utilisateur](https://mviewerstudio.readthedocs.io/fr/stable/doc_user/accueil.html) - * [Documentation d'installation](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html) - * [Documentation administrateur](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html) +## 🚀 Quick Start docker compose + +``` +# code source +git clone https://github.com/mviewer/mviewerstudio.git +cd mviewerstudio +# docker +docker compose up -d +``` +AccĂ©dez Ă  : **http://localhost/mviewerstudio** + +Pour des instructions dĂ©taillĂ©es avec Flask ou Docker, voir le [Guide d'installation](install/README.md) + +--- + +## 📚 Documentation + +### Installation + +- đŸ‡«đŸ‡· [Instructions d'installation en français](install/README.fr.md) +- 🇬🇧 [Installation instructions in English](install/README.en.md) + +### Documentation en ligne + +- 📘 [Documentation utilisateur (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_user/accueil.html) +- 🔧 [Guide d'installation (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html) +- ⚙ [Configuration et administration (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html) +- đŸ’» [Documentation technique (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/dev_corner.html) + +--- + +## ✅ PrĂ©requis + +- SystĂšme Linux avec `bash` +- Python >= 3.9 et `venv` +- `git` +- `apt` (optionnel, pour installation automatique) + +--- + +## 🔗 Ressources + +- [DĂ©pĂŽt GitHub](https://github.com/mviewer/mviewerstudio) +- [Documentation ReadTheDocs](https://mviewerstudio.readthedocs.io/fr/stable/) +- [mviewer](https://github.com/mviewer/mviewer) diff --git a/apps/default.xml b/apps/default.xml new file mode 100644 index 00000000..946c63f9 --- /dev/null +++ b/apps/default.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/store/.gitignore b/apps/store/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/store/register.json b/apps/store/register.json new file mode 100644 index 00000000..5fdb6276 --- /dev/null +++ b/apps/store/register.json @@ -0,0 +1,4 @@ +{ + "total": 0, + "configs": [] +} \ No newline at end of file diff --git a/conf/README.md b/conf/README.md deleted file mode 100644 index e90eab7d..00000000 --- a/conf/README.md +++ /dev/null @@ -1 +0,0 @@ -this location folder is used to store mviewer config files generated by the application \ No newline at end of file diff --git a/config-php-sample.json b/config-php-sample.json deleted file mode 100644 index 14c41c7e..00000000 --- a/config-php-sample.json +++ /dev/null @@ -1,200 +0,0 @@ -{ - "app_conf": { - "studio_title": "GĂ©oBretagne mviewer studio", - "mviewer_version": "4", - "mviewerstudio_version": "4.2.1", - "is_php": "true", - "php": { - "upload_service": "srv/php/store.php", - "delete_service": "srv/php/delete.php", - "list_service": "srv/php/list.php", - "store_style_service": "srv/php/store/style.php" - }, - "api": "api/app", - "store_style_service": "api/style", - "mviewer_instance": "http://172.16.10.30/mviewer/", - "conf_path_from_mviewer": "apps/store/", - "mviewer_short_url": { - "used": true, - "apps_folder": "store" - }, - "external_themes": { - "used": false, - "url": "https://geobretagne.fr/minicatalog/csv" - }, - "user_info": "api/user", - "export_conf_folder": "/var/www/htdocs/mviewer/apps/store/", - "proxy": "../proxy/?url=", - "user_info_visible": false, - "app_form_placeholders": { - "app_title": "Kartenn", - "logo_url": "https://geobretagne.fr/pub/logo/region-bretagne.jpg", - "help_file": "mviewer_help.html" - }, - "map": { - "center": [-307903.74898791354, 6141345.088741366], - "zoom": 7 - }, - "baselayers": { - "positron": { - "id": "positron", - "thumbgallery": "img/basemap/positron.png", - "title": "CartoDb", - "label": "Positron", - "type": "OSM", - "url": "https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", - "attribution": "Map tiles by CartoDb, under CC BY 3.0 " - }, - "ortho_ign": { - "id": "ortho_ign", - "thumbgallery": "img/basemap/ortho.jpg", - "title": "IGN", - "label": "Photographies aĂ©riennes", - "type": "WMTS", - "url": "https://data.geopf.fr/wmts", - "layers": "ORTHOIMAGERY.ORTHOPHOTOS", - "format": "image/jpeg", - "fromcapacity": "false", - "attribution": "", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "plan_ign": { - "id": "plan_ign", - "thumbgallery": "img/basemap/scan-express.jpg", - "title": "IGN", - "label": "Plan IGN v2", - "type": "WMTS", - "url": "https://data.geopf.fr/wmts", - "layers": "GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2", - "format": "image/png", - "fromcapacity": "false", - "attribution": "", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "darkmatter": { - "id": "darkmatter", - "thumbgallery": "img/basemap/darkmatter.png", - "title": "CartoDb", - "label": "Dark Matter", - "type": "OSM", - "url": "https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png", - "maxzoom": "20", - "attribution": "Map tiles by CartoDb, under CC BY 3.0 " - }, - "esriworldimagery": { - "id": "esriworldimagery", - "thumbgallery": "img/basemap/esriworldwide.jpg", - "title": "Esri", - "label": "Esri world imagery", - "type": "OSM", - "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", - "attribution": "Esri world imagery" - }, - "ortho_ir": { - "id": "ortho_ir", - "thumbgallery": "img/basemap/ir.jpg", - "title": "IGN", - "label": "Photographies aĂ©riennes infrarouge", - "type": "WMTS", - "url": "https://data.geopf.fr/wmts", - "layers": "ORTHOIMAGERY.ORTHOPHOTOS.IRC", - "format": "image/jpeg", - "fromcapacity": "false", - "attribution": "", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "ortho_ancienne": { - "id": "ortho_ancienne", - "thumbgallery": "img/basemap/ortho-ancien.jpg", - "title": "IGN", - "label": "Photographies aĂ©riennes anciennes", - "type": "WMTS", - "url": "https://data.geopf.fr/wmts", - "layers": "ORTHOIMAGERY.ORTHOPHOTOS.1950-1965", - "format": "image/png", - "fromcapacity": "false", - "attribution": "", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "osm_google": { - "id": "osm_google", - "thumbgallery": "img/basemap/osm_google.png", - "title": "GĂ©oBretagne", - "label": "OpenStreetMap style Google", - "type": "WMTS", - "url": "https://tile.geobretagne.fr/osm/service", - "layers": "osm:google", - "format": "image/png", - "fromcapacity": "false", - "attribution": "GĂ©oBretagne. DonnĂ©es : les contributeurs d'OpenStreetMap , ODbL ", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "osm_grey": { - "id": "osm_grey", - "thumbgallery": "img/basemap/osm_grey.png", - "title": "GĂ©oBretagne - DataGrandEst", - "label": "OpenStreetMap style noir et blanc", - "type": "WMTS", - "url": "https://tile.geobretagne.fr/osm/service", - "layers": "osm:grey", - "format": "image/png", - "fromcapacity": "false", - "attribution": "GĂ©oBretagne - DataGrandEst. DonnĂ©es : les contributeurs d'OpenStreetMap , ODbL ", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - }, - "osm": { - "id": "osm", - "thumbgallery": "img/basemap/osm.png", - "title": "OSM", - "label": "OpenStreetMap classique", - "type": "OSM", - "url": "https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png", - "attribution": "DonnĂ©es : les contributeurs d'OpenStreetMap ODbL " - }, - "osm_bzh": { - "id": "osm_bzh", - "thumbgallery": "img/basemap/osm.png", - "title": "OSM BZH", - "label": "OpenStreetMap en breton", - "type": "OSM", - "maxzoom": "20", - "url": "https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png", - "attribution": "Kendaolerien OpenStreetMap" - } - }, - "data_providers": { - "csw": [{ - "title": "Catalogue GĂ©oBretagne", - "url": "https://geobretagne.fr/geonetwork/srv/fre/csw", - "baseref": "https://geobretagne.fr/geonetwork/srv/eng/catalog.search?node=srv#/metadata/" - }, - { - "title": "Catalogue DataGrandEst", - "url": "https://datagrandest.fr/geonetwork/srv/fre/csw", - "baseref": "https://datagrandest.fr/geonetwork/srv/eng/catalog.search?node=srv#/metadata/" - } - ], - "wms": [{ - "title": "Serveur WMS de la RĂ©gion", - "url": "https://ows.region-bretagne.fr/geoserver/rb/wms" - }] - }, - "default_params": { - "layer": { - "info_format": "text/html" - } - } - } -} diff --git a/docker-compose.yml b/docker-compose.yml index 97b5d5cb..3857cfc2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,29 +1,10 @@ -version: '3' -volumes: - apps: - services: - # Reverse-proxy using nginx. Groups mviewer and mviewerstudio under respective paths - # Config can be found under ./docker/nginx/default.conf.template - www: - image: nginx - ports: - - 80:80 - environment: - - NGINX_HOST=localhost - - MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio - volumes: - - ./docker/nginx:/etc/nginx/templates - depends_on: - - mviewerstudio - - mviewer - # Python version # Served under /${MVIEWERSTUDIO_URL_PATH_PREFIX}/ see docker/nginx/default.conf.template mviewerstudio: build: context: . - dockerfile: docker/Dockerfile-python-backend + dockerfile: docker/Dockerfile image: mviewer/mviewerstudio:latest # ports: # - "8000:8000" @@ -31,13 +12,12 @@ services: - CONF_PATH_FROM_MVIEWER=apps/store - CONF_PUBLISH_PATH_FROM_MVIEWER=apps/public - DEFAULT_ORG=my_org - - EXPORT_CONF_FOLDER=/home/apprunner/apps/store - - MVIEWERSTUDIO_PUBLISH_PATH=/home/apprunner/apps/public + - EXPORT_CONF_FOLDER=/home/mvuser/apps/store + - MVIEWERSTUDIO_PUBLISH_PATH=/home/mvuser/apps/public - MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio volumes: - - "apps:/home/apprunner/apps" - - "./config-python-sample.json:/home/apprunner/mviewerstudio_backend/static/apps/config.json" - + - "./apps:/home/mvuser/apps" + - "./src/static/config.json:/home/mvuser/src/static/config.json" # Served under /mviewer/ see docker/nginx/default.conf.template mviewer: depends_on: @@ -46,8 +26,22 @@ services: # the mviewer/mviewer github repository # See https://github.com/mviewer/mviewer/pull/236 image: mviewer/mviewer -# ports: -# - "5051:80" + # ports: + # - "5051:80" volumes: - - "apps:/usr/share/nginx/html/apps" -# \ No newline at end of file + - "./apps:/usr/share/nginx/html/apps:ro" + # Reverse-proxy using nginx. Groups mviewer and mviewerstudio under respective paths + # Config can be found under ./docker/nginx/default.conf.template + www: + image: nginx + ports: + - 80:80 + environment: + - NGINX_HOST=localhost + - MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio + volumes: + - ./docker/nginx:/etc/nginx/templates + - "./apps:/usr/share/nginx/html/apps:ro" + depends_on: + - mviewerstudio + - mviewer diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 00000000..e1c3abe2 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,40 @@ +FROM python:3.11-slim + +ARG UID=1000 +ARG GID=1000 + +#install git & studio dependencies +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libxml2-dev \ + libxslt1-dev \ + git \ + && rm -rf /var/lib/apt/lists/* + +RUN groupadd -g ${GID} mvuser && useradd -m -u ${UID} -g ${GID} mvuser + +USER mvuser + +ENV HOME=/home/mvuser +ENV PATH=$HOME/.local/bin:$PATH + +RUN mkdir -p /home/mvuser/apps/store + +WORKDIR /home/mvuser + +COPY --chown=mvuser:mvuser src ./src +COPY --chown=mvuser:mvuser install ./install +# We need to install the app so that the config is properly read (there might be something to fix on +# app-factory.py, calling app.config.from_object requires the package to be installed +RUN pip install --user -r install/requirements.txt && pip install --user ./src + +VOLUME [ "/home/mvuser/apps" ] + +ENV EXPORT_CONF_FOLDER=/home/mvuser/apps/store \ + CONF_PATH_FROM_MVIEWER=apps/store \ + MVIEWERSTUDIO_PUBLISH_PATH=/home/mvuser/apps/public \ + CONF_PUBLISH_PATH_FROM_MVIEWER=apps/public \ + DEFAULT_ORG=public \ + MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio + +CMD ["gunicorn", "-w 1", "-b 0.0.0.0:8000", "src.app:app"] diff --git a/docker/Dockerfile-php-backend b/docker/Dockerfile-php-backend deleted file mode 100644 index c85716c9..00000000 --- a/docker/Dockerfile-php-backend +++ /dev/null @@ -1,27 +0,0 @@ -FROM php:7.4-apache-buster - - -# Inits the apps/ volume -COPY apps/ ./apps -COPY docker/config-docker-php.json ./apps/config.json -RUN chown -R www-data:www-data /var/www/html/apps - -# Reconfigure apache to use the same port as the python backend -RUN sed -i 's/\*:80/*:8000/' /etc/apache2/sites-enabled/000-default.conf -RUN sed -i 's/Listen 80/Listen 8000/' /etc/apache2/ports.conf - -# Note: this is the admin's responsability to -# make sure the following directory will be write-readable -VOLUME [ "/var/www/html/apps" ] - -# Copies the static resources -COPY css/ ./css -COPY img/ ./img -COPY index.html ./index.html -COPY mviewerstudio.i18n.json mviewerstudio.i18n.json -COPY js/ ./js -COPY lib/ ./lib -COPY mviewerstudio.i18n.json ./ - -# Copies the PHP backend -COPY srv/php ./srv diff --git a/docker/Dockerfile-python-backend b/docker/Dockerfile-python-backend deleted file mode 100644 index 7413051a..00000000 --- a/docker/Dockerfile-python-backend +++ /dev/null @@ -1,47 +0,0 @@ -FROM python:3.11-slim - -#install git & studio dependencies -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libxml2-dev \ - libxslt1-dev \ - git \ - && rm -rf /var/lib/apt/lists/* - -RUN useradd -r -m apprunner - -USER apprunner - -ENV HOME=/home/apprunner -ENV PATH=$HOME/.local/bin:$PATH - -RUN mkdir -p /home/apprunner/apps/store -RUN chown -R apprunner:apprunner /home/apprunner/apps - -WORKDIR /home/apprunner - -COPY --chown=apprunner:apprunner srv/python . -# We need to install the app so that the config is properly read (there might be something to fix on -# app-factory.py, calling app.config.from_object requires the package to be installed -RUN pip install --user -r requirements.txt && pip install --user . - -VOLUME [ "/home/apprunner/apps" ] - -COPY css/ mviewerstudio_backend/static/css -COPY img/ mviewerstudio_backend/static/img -COPY index.html mviewerstudio_backend/static/index.html -COPY js/ mviewerstudio_backend/static/js -COPY lib/ mviewerstudio_backend/static/lib -COPY mviewerstudio.i18n.json mviewerstudio_backend/static/mviewerstudio.i18n.json - -ENV EXPORT_CONF_FOLDER=/home/apprunner/apps/store \ - CONF_PATH_FROM_MVIEWER=apps/store \ - MVIEWERSTUDIO_PUBLISH_PATH=/home/apprunner/apps/public \ - CONF_PUBLISH_PATH_FROM_MVIEWER=apps/public \ - DEFAULT_ORG=public \ - MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio/ - -# You will probably have to override this one on runtime with your custom config -COPY config-python-sample.json mviewerstudio_backend/static/apps/config.json - -CMD ["gunicorn", "-w 1", "-b 0.0.0.0:8000", "mviewerstudio_backend.app:app"] diff --git a/docker/config-docker-php.json b/docker/config-docker-php.json deleted file mode 100644 index 7c056e54..00000000 --- a/docker/config-docker-php.json +++ /dev/null @@ -1,190 +0,0 @@ -{ - "app_conf": { - "studio_title": "GĂ©oBretagne mviewer studio", - "upload_service": "srv/store.php", - "delete_service": "srv/delete.php", - "list_service": "srv/list.php", - "store_style_service": "srv/store/style.php", - "mviewer_instance": "/mviewer/", - "conf_path_from_mviewer" :"apps/store", - "mviewer_short_url": { - "used": true, - "apps_folder": "store" - }, - "external_themes": { - "used": false, - "url": "https://geobretagne.fr/minicatalog/csv" - }, - "user_info": "srv/user_info.php", - "export_conf_folder" : "/var/www/html/apps/store/", - "proxy" : "../proxy/?url=", - "user_info_visible": false, - "app_form_placeholders": { - "app_title": "Kartenn", - "logo_url": "https://geobretagne.fr/pub/logo/region-bretagne.jpg", - "help_file": "mviewer_help.html" - }, - "map": { - "center": [-307903.74898791354, 6141345.088741366], - "zoom": 7 - }, - "baselayers": { - "positron": { - "id": "positron", - "thumbgallery": "img/basemap/positron.png", - "title": "CartoDb", - "label": "Positron", - "type": "OSM", - "url": "https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", - "attribution": "Map tiles by CartoDb, under CC BY 3.0 " - }, - "esriworldimagery": { - "id": "esriworldimagery", - "thumbgallery": "img/basemap/esriworldwide.jpg", - "title": "Esri", - "label": "Esri world imagery", - "type": "OSM", - "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", - "attribution": "Esri world imagery" - }, - "stamen1": { - "id": "stamen1", - "thumbgallery": "img/basemap/toner-lite.png", - "title": "Stamen Design", - "label": "Toner-lite", - "type": "OSM", - "url": "http://{a-d}.tile.stamen.com/toner-lite/{z}/{x}/{y}.png", - "maxzoom": "20", - "attribution": "Map tiles by Stamen Design , under CC BY 3.0 " - }, - "stamen2": { - "id": "stamen2", - "thumbgallery": "img/basemap/watercolor.jpg", - "title": "Stamen Design", - "label": "Watercolor", - "type": "OSM", - "url": "http://{a-c}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg", - "maxzoom": "20", - "attribution": "Map tiles by Stamen Design , under CC BY 3.0 " - }, - "darkmatter": { - "id": "darkmatter", - "thumbgallery": "img/basemap/darkmatter.png", - "title": "CartoDb", - "label": "Dark Matter", - "type": "OSM", - "url": "https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png", - "maxzoom": "20", - "attribution": "Map tiles by CartoDb, under CC BY 3.0 " - }, - "ortho1": { - "id": "ortho1", - "thumbgallery": "img/basemap/ortho.jpg", - "title": "GĂ©oBretagne", - "label": "Photo aĂ©rienne actuelle", - "type": "WMTS", - "url": "https://tile.geobretagne.fr/gwc02/service/wmts", - "layers": "satellite", - "format": "image/png", - "style": "_null", - "matrixset": "EPSG:3857", - "fromcapacity": "false", - "attribution": "partenaires GĂ©oBretagne - IGN RGE BD ORTHO - PlanetObserver" - }, - "ortho_ir": { - "id": "ortho_ir", - "thumbgallery": "img/basemap/ir.jpg", - "title": "GĂ©oBretagne", - "label": "Photo aĂ©rienne infra rouge", - "type": "WMTS", - "url": "https://geobretagne.fr/geoserver/gwc/service/wmts", - "layers": "photo:ir-composite", - "format": "image/jpeg", - "style": "_null", - "matrixset": "EPSG:3857", - "fromcapacity": "false", - "attribution": "partenaires GĂ©oBretagne - IGN RGE BD ORTHO - PlanetObserver" - }, - "osm_google": { - "id": "osm_google", - "thumbgallery": "img/basemap/osm_google.png", - "title": "GĂ©oBretagne", - "label": "OpenStreetMap", - "type": "WMS", - "url": "https://osm.geobretagne.fr/gwc01/service/wms", - "layers": "osm:google", - "format": "image/png", - "attribution": "GĂ©oBretagne. DonnĂ©es : les contributeurs d'OpenStreetMap , ODbL " - }, - "osm": { - "id": "osm", - "thumbgallery": "img/basemap/osm.png", - "title": "OSM", - "label": "OpenStreetMap", - "type": "OSM", - "url": "https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png", - "attribution": "DonnĂ©es : les contributeurs d'OpenStreetMap ODbL " - }, - "osm_bzh": { - "id": "osm_bzh", - "thumbgallery": "img/basemap/osm.png", - "title": "OSM BZH", - "label": "OpenStreetMap en breton", - "type": "OSM", - "maxzoom": "20", - "url": "https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png", - "attribution": "Kendaolerien OpenStreetMap" - }, - "scan_ign": { - "id": "scan_ign", - "thumbgallery": "img/basemap/scan.jpg", - "title": "GĂ©oPortail", - "label": "Cartes IGN", - "type": "WMTS", - "url": "https://geobretagne.fr/geoportail/wmts", - "layers": "GEOGRAPHICALGRIDSYSTEMS.MAPS", - "format": "image/jpeg", - "fromcapacity": "false", - "attribution": "", - "style": "normal", - "matrixset": "PM", - "maxzoom": "22" - } - }, - "data_providers" : { - "csw" : [ - { - "title" : "Catalogue GĂ©oBretagne", - "url": "https://geobretagne.fr/geonetwork/srv/fre/csw", - "baseref": "https://geobretagne.fr/geonetwork/srv/eng/catalog.search?node=srv#/metadata/" - }, - { - "title" : "Catalogue RĂ©gion Bretagne", - "url": "https://applications.region-bretagne.fr/geonetwork/srv/fre/csw", - "baseref": "https://applications.region-bretagne.fr/geonetwork/srv/fre/catalog.search#/metadata/" - }, - { - "title" : "Catalogue de la RĂ©gion Grand Est", - "url": "https://geobretagne.fr/geonetwork/srv/fre/csw", - "baseref": "https://www.cigalsace.org/geonetwork/" - }, - { - "title" : "Catalogue de la RĂ©gion Pays de la Loire", - "url": "../proxy/?url=https://www.geopal.org/geonetwork/srv/fre/csw", - "baseref": "https://www.geopal.org/geonetwork/" - } - ], - "wms" : [ - { - "title" : "Serveur WMS de la RĂ©gion", - "url": "https://ows.region-bretagne.fr/geoserver/rb/wms" - } - ] - }, - "default_params" : { - "layer": { - "info_format": "text/html" - } - } - } -} diff --git a/docker/nginx/default.conf.template b/docker/nginx/default.conf.template index c0e216ac..2a7988ec 100644 --- a/docker/nginx/default.conf.template +++ b/docker/nginx/default.conf.template @@ -2,8 +2,16 @@ server { listen 80; server_name ${NGINX_HOST}; + location = /mviewer { + return 302 /mviewer/$is_args$args; + } + location /mviewer/ { - proxy_pass http://mviewer:8080/; + proxy_pass http://mviewer/; + } + + location /apps/ { + alias /usr/share/nginx/html/apps/; } location /${MVIEWERSTUDIO_URL_PATH_PREFIX}/ { @@ -20,7 +28,6 @@ server { location / { server_name_in_redirect off; - return 302 /${MVIEWERSTUDIO_URL_PATH_PREFIX}; + return 302 /${MVIEWERSTUDIO_URL_PATH_PREFIX}/; } } - diff --git a/docker/readme.md b/docker/readme.md index 36c85dd8..2cdd05b5 100644 --- a/docker/readme.md +++ b/docker/readme.md @@ -1,7 +1,7 @@ # mviewerstudio Dockerfile -## Which one ? -The maintained dockerfile is the python one. The php one is there for historical reasons and will probably soon be dropped. +## Image +Only python Dockerfile will be maintained (PHP backend is fully deprecated). ## Environment variables @@ -13,10 +13,17 @@ The maintained dockerfile is the python one. The php one is there for historical ## Default configuration -The default configuration (env vars defined in the dockerfile and json config file copied) assume that: +The default configuration (env vars defined in the dockerfile and json config file present in `src/static/config.json`) assume that: - the mviewer _apps_ folder is mounted at EXPORT_CONF_FOLDER=/home/apprunner/apps - /home/apprunner/apps/store and /home/apprunner/apps/prod are existing folders (you might need to create them manually beforehand) -- it is using config-python-sample.json, which at some point you will probably want to override with your own config. +- it is using `src/static/config.json`, which you will probably want to adapt to your own environment. It is also configured to serve the frontend (static files) with gunicorn, which is usually not recommended. Later versions might use an nginx container to serve the frontend. + +## Build mviewerstudio image + +Use docker compose to build image : + +`docker compose build mviewerstudio` + diff --git a/docs/doc_tech/config_front.rst b/docs/doc_tech/config_front.rst index 581f44af..5ece8269 100644 --- a/docs/doc_tech/config_front.rst +++ b/docs/doc_tech/config_front.rst @@ -9,11 +9,11 @@ Configurer le frontend mviewerstudio Structure du fichier de configuration ---------------------------------------------- -La configuration s'effectue dans le fichier config-python-sample.json localisĂ© Ă  la racine du projet. Ce fichier de configuration sera copiĂ© automatiquement via le script d'installation (ou Ă  copier manuellement) dans le rĂ©pertoire ``srv/python/mviewerstudiobackend/static/apps`` sous le nom ``config.json``. +La configuration du frontend s'effectue dans le fichier ``src/static/config.json`` localisĂ© dans le projet. Ce fichier pilote l'interface web de mviewerstudio et doit ĂȘtre adaptĂ© selon votre environnement. -Voici le fichier d'exemple Ă  utiliser et Ă  adapter selon votre environnement : +Voici le fichier de configuration frontend Ă  utiliser et Ă  adapter selon votre environnement : -https://github.com/mviewer/mviewerstudio/blob/master/config-python-sample.json +https://github.com/mviewer/mviewerstudio/blob/master/src/static/config.json ParamĂštres du fichier de configuration @@ -32,7 +32,7 @@ Ces paramĂštres sont Ă  renseigner dans tous les cas. - ``mviewer_short_url`` : Utilisation du systĂšme d'URL courtes (mviewer/#monappli au lieu de mviewer/?config=apps/monappli.xml). - ``used`` : true | false. - ``apps_folder`` : chemin d'accĂšs depuis le rĂ©pertoire apps (exemple store pour apps/store). - - ``public_folder`` : (pour backend Python seulement) - chemin d'accĂšs depuis le rĂ©pertoire apps pour les Ă©lĂ©ments publiĂ©s (exemple store pour apps/public). + - ``public_folder`` : chemin d'accĂšs depuis le rĂ©pertoire apps pour les Ă©lĂ©ments publiĂ©s (exemple store pour apps/public). - ``external_themes`` : Utilisation du mĂ©canisme d'import de thĂ©matiques externes (prĂ©sentes dans d'autres mviewers). - ``proxy`` : Chemin du proxy par lequel les requĂȘtes envoyĂ©es par mviewerstudio passeront si cette valeur est dĂ©finie. - ``used`` : BoolĂ©en -> Utiliser ``"true"`` pour permettre le chargement et l'utilisation des thĂ©matiques externes. @@ -51,7 +51,7 @@ Ces paramĂštres sont Ă  renseigner dans tous les cas. ParamĂštres obligatoires ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Ces paramĂštres sont obligatoires avec un backend Python. +Ces paramĂštres sont obligatoires. - ``api``: URL vers le service (API) du backend Python. Valeur par dĂ©faut : ``api/app``. - ``user_info``: URL vers le service (API) permettant de rĂ©cupĂ©rer les informations de l'utilisateur connectĂ©. Valeur par dĂ©faut ``api/user``. diff --git a/docs/doc_tech/dev_corner.rst b/docs/doc_tech/dev_corner.rst index c8c01d2b..38722fde 100644 --- a/docs/doc_tech/dev_corner.rst +++ b/docs/doc_tech/dev_corner.rst @@ -24,7 +24,7 @@ PrĂ©requis GĂ©nĂ©ralitĂ©s ----------- -Le debugger VS Code permet d'utiliser le virtualenv (rĂ©pertoire .venv) installĂ© dans le rĂ©pertoire `srv/python`. +Le debugger VS Code permet d'utiliser le virtualenv (rĂ©pertoire `.venv`) installĂ© Ă  la racine du projet. Vous pouvez suivre cette documentation Ă  propos des virtualenv dans VS code : @@ -39,9 +39,9 @@ https://code.visualstudio.com/docs/python/tutorial-flask Synchronisation API / Swagger ----------------------------- -Toute modification des routes backend (fichier ``srv/python/mviewerstudio_backend/route.py``) +Toute modification des routes backend (fichier ``src/route.py``) doit ĂȘtre synchronisĂ©e dans la spĂ©cification Swagger/OpenAPI -(``srv/python/mviewerstudio_backend/swagger.yaml``). +(``src/swagger.yaml``). AccĂšs Ă  Swagger --------------- @@ -61,13 +61,13 @@ les URLs deviennent : Configuration du debugger VS Code --------------------------------- -1. Ouvrir le rĂ©pertoire /srv/python/ dans VS Code. +1. Ouvrir la racine du projet dans VS Code. 2. Ouvrir le fichier .vscode/launch.json (voir la section suivante si non existant) 3. Modifier les variables d'environnement (aidez-vous de la page :ref:`install_python`) selon votre environnement .. code-block:: sh - "FLASK_APP": "mviewerstudio_backend/app.py", + "FLASK_APP": "src/app.py", "FLASK_DEBUG": "1", "CONF_PATH_FROM_MVIEWER":"apps/store", "EXPORT_CONF_FOLDER":"/home/user/git/mviewer/apps/store/", @@ -78,7 +78,7 @@ Configuration du debugger VS Code 4. Dans VS Code assurez-vous de sĂ©lectionner le bon virtualenv (voir les documentations prĂ©cĂ©dentes) -5. Ouvrir le fichier `/srv/python/mviewerstudio_backend/static/apps/config.json` et adapter les bonnes valeurs +5. Ouvrir le fichier ``src/static/config.json`` et adapter les bonnes valeurs Ici, mviewer est accessible en local sur http://localhost:5051 (via NodeJs) et les rĂ©pertoires `apps/store` et `apps/public` ont Ă©tĂ© créés Ă  la main, et accessible en lecture / Ă©criture par l'utilisateur qui exĂ©cute le backend via VS Code. @@ -105,7 +105,7 @@ Si le fichier n'est pas disponible, vous pouvez le crĂ©er via le gĂ©nĂ©rateur VS 1. CrĂ©ation manuelle -Dans `/srv/python`, vous devrez crĂ©er un rĂ©pertoire (si inexistant) `.vscode` et un fichier `launch.json`. +À la racine du projet, vous devrez crĂ©er un rĂ©pertoire (si inexistant) `.vscode` et un fichier `launch.json`. .. warning:: Le type `python` semble dĂ©prĂ©ciĂ© mais fonctionne encore. Le type `debugpy` n'est pas compatible avec cette documentation. @@ -126,7 +126,7 @@ Dans le fichier launch.json, collez ce fichier et reprenez la section `Configura "request": "launch", "module": "flask", "env": { - "FLASK_APP": "mviewerstudio_backend/app.py", + "FLASK_APP": "src/app.py", "FLASK_DEBUG": "1", "CONF_PATH_FROM_MVIEWER":"apps/store", "EXPORT_CONF_FOLDER":"/home/user/git/mviewer/apps/store/", @@ -148,7 +148,7 @@ Dans le fichier launch.json, collez ce fichier et reprenez la section `Configura 2. CrĂ©ation via l'outil VS Code -Ouvrez le rĂ©pertoire srv/python dans VS Code. +Ouvrez la racine du projet dans VS Code. - A gauche, cliquez sur `Run and Debug`. @@ -160,5 +160,5 @@ Ouvrez le rĂ©pertoire srv/python dans VS Code. - Dans la 3Ăš Ă©tape, cliquez sur `Default` -- Dans le nouveau fichier `.vscode/launch.json`, modifier les valeurs et surtout la valeur de "FLASK_APP" pour pointer vers le fichier `srv/python/mviewer_backend/app.py` +- Dans le nouveau fichier `.vscode/launch.json`, modifier les valeurs et surtout la valeur de "FLASK_APP" pour pointer vers le fichier `src/app.py` diff --git a/docs/doc_tech/install_other.rst b/docs/doc_tech/install_docker.rst similarity index 65% rename from docs/doc_tech/install_other.rst rename to docs/doc_tech/install_docker.rst index 37be0391..67a5dffa 100644 --- a/docs/doc_tech/install_other.rst +++ b/docs/doc_tech/install_docker.rst @@ -1,21 +1,12 @@ .. Authors : .. mviewer team -.. _install_other: +.. _install_docker: -Autres types d'installations possibles -====================================== +Installation avec Docker +======================== -Installer avec le Backend PHP -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. warning:: PHP est officiellement annoncĂ© en fin de vie, n'est plus maintenue et sera supprimĂ© dans une prochaine version. - -A partir de la version 4, veuillez suivre la documentation d'installation du backend Python (maintenu) pour disposer des nouvelles fonctionnalitĂ©s. -Pour plus d'informations sur PHP, vous devrez consulter la documentation de la version que vous souhaiter installer. - -Docker -~~~~~~~ +Cette page complĂšte la procĂ©dure d'installation du backend Python avec un dĂ©ploiement conteneurisĂ©. Vous devez avoir installĂ© docker au prĂ©alable. @@ -28,7 +19,7 @@ https://github.com/mviewer/mviewerstudio/edit/master/docker/readme.md 2. Composition docker -Vous pouvez Ă©galement utiliser la composition docker disponible Ă  la racine du projet afin d'obtenir mviewer, mviewerstudio et le backend python : +Vous pouvez Ă©galement utiliser la composition docker disponible Ă  la racine du projet afin d'obtenir mviewer, mviewerstudio et le backend Python : https://github.com/mviewer/mviewerstudio/blob/master/docker-compose.yml diff --git a/docs/doc_tech/install_python.rst b/docs/doc_tech/install_python.rst index 6e3f75c7..d00098cb 100644 --- a/docs/doc_tech/install_python.rst +++ b/docs/doc_tech/install_python.rst @@ -7,7 +7,7 @@ Installer mviewerstudio avec Python ################################### -Mviewerstudio est une application web dĂ©veloppĂ©e en HTML / CSS / PHP / Python. Elle nĂ©cessite simplement d'ĂȘtre dĂ©ployĂ©e sur un serveur WEB qui peut ĂȘtre APACHE, NGINX, TOMCAT
 +Mviewerstudio est une application web dĂ©veloppĂ©e en HTML / CSS / JavaScript avec un backend Python. Elle nĂ©cessite simplement d'ĂȘtre dĂ©ployĂ©e sur un serveur WEB qui peut ĂȘtre APACHE, NGINX, TOMCAT
 Installation ************ @@ -22,24 +22,13 @@ Vous aurez besoin : .. code-block:: sh sudo apt install libxslt1-dev libxml2-dev python3 python3-pip python3-venv - pip install virtualenv -- d'une version Python >= 3.11 +- d'une version Python >= 3.9 - d'une instance mviewer fonctionnelle (/mviewer) ProcĂ©dures d'installation ========================= -.. note:: - Avant de rĂ©aliser l'installation, vous devez avoir connaissance de la diffĂ©rence entre un environnement de - ``production`` et un environnement de ``dĂ©veloppements``. - - ``L’environnement de production`` est la destination finale d’une application web ou d’un site web. - C'est l'environnement final qui sera accessible par vos utilisateurs. - - ``L’environnement de dĂ©veloppement`` reprĂ©sente le contexte dans lequel vous allez rĂ©aliser des dĂ©veloppements, des modifications du code ou des tests - avant de rĂ©aliser le passage de l'application dans l'environnement de production final. - Installation manuelle --------------------- @@ -47,20 +36,12 @@ Installation manuelle #RĂ©cupĂ©ration des sources git clone https://github.com/mviewer/mviewerstudio.git - #Positionnement sur la branche ou la version choisie cd mviewerstudio - git checkout develop - STATIC_DIR=srv/python/mviewerstudio_backend/static - #CrĂ©ation du dossier apps - mkdir -p "${STATIC_DIR}/apps" - #Copie des dossiers ressources dans le dossier static - cp -r css img js lib index.html mviewerstudio.i18n.json "${STATIC_DIR}" #CrĂ©ation de l'environnement virtuel Python et installation des dĂ©pendances - cd srv/python python3 -m venv .venv source .venv/bin/activate - pip install -r requirements.txt -r dev-requirements.txt - pip install -e . + pip install -r install/requirements.txt -r install/dev-requirements.txt + pip install -e src @@ -68,24 +49,23 @@ Installation manuelle Installation scriptĂ©e --------------------- -TĂ©lĂ©chargez le script d'installation - .. code-block:: sh - sudo apt install curl - curl -O https://raw.githubusercontent.com/mviewer/mviewerstudio/master/srv/python/install_backend_python.sh + git clone https://github.com/mviewer/mviewerstudio.git + cd mviewerstudio + bash ./install/install.sh -Le script utilise 3 paramĂštres : +Le script peut utiliser 3 paramĂštres : - ```` : Le chemin dans lequel installer mviewerstudio - ```` : La branche Ă  installer -- ```` : La branche Ă  installer (Option - par dĂ©faut le nom sera ``mviewerstudio``) +- ```` : Le nom du rĂ©pertoire cible (optionnel, par dĂ©faut ``mviewerstudio``) Exemple pour installer mviewerstudio dans le rĂ©pertoire ``/git`` en utilisant la branche ``develop`` : .. code-block:: sh - sh ./install_backend_python.sh /home/monuser/git develop mviewerstudio_develop + bash ./install/install.sh /home/monuser/git develop mviewerstudio_develop Suite Ă  cette commande exemple, le mviewerstudio sera donc accessible sous le chemin suivant et sera directement alignĂ© avec la branche ``develop``: @@ -97,7 +77,7 @@ Configuration Configuration du front ---------------------- -RĂ©cupĂ©rez le fichier ``config-python-sample.json`` (Ă  la racine du projet) et copier son contenu dans le fichier ``/srv/python/mviewerstudio_backend/static/apps/config.json``. +RĂ©cupĂ©rez le fichier ``src/static/config.json`` et adaptez son contenu selon votre environnement. Adaptez ensuite les paramĂštres selon votre environnement (aidez-vous de la page :ref:`config_front`). .. warning:: @@ -113,7 +93,7 @@ Adaptez ensuite les paramĂštres selon votre environnement (aidez-vous de la page Variables d'environnement du backend ------------------------------------ -Ces variables doivent ĂȘtre dĂ©finies dans l'environnement (console batch ou service) +Ces variables doivent ĂȘtre dĂ©finies dans l'environnement soit via la console (commande export ou fichier .bashrc) ou le service : - ``CONF_PATH_FROM_MVIEWER``: rĂ©pertoire d'accĂšs Ă  partir de l'instance mviewer. - ``CONF_PUBLISH_PATH_FROM_MVIEWER``: rĂ©pertoire de publication Ă  partir de l'instance mviewer. @@ -129,46 +109,27 @@ Pour utiliser les services types OGC (catalogue ou serveurs cartographiques), vo Le Proxy interne proposĂ© par mviewer ("/mviewerstudio/proxy/?url=") utilise un paramĂštre ``PROXY_WHITE_LIST`` qui doit ĂȘtre complĂ©tĂ© par tous les domaines (FQDN) des services que vous utiliserez. Ce paramĂštre est accessible dans : -- /srv/python/mviewerstudio_backend/settings.py +- ``src/settings.py`` -Lancement de l'application avec Flask +Lancement de l'application avec Flask (mode developpement) ===================================== .. code-block:: sh - cd mviewerstudio/srv/python + cd mviewerstudio source .venv/bin/activate - export FLASK_APP=python/mviewerstudio_backend.app + export FLASK_APP=src/app.py export CONF_PATH_FROM_MVIEWER=apps/store - export EXPORT_CONF_FOLDER=/home/monuser/mviewer/apps/store/ - export MVIEWERSTUDIO_PUBLISH_PATH=/home/monuser/mviewer/apps/prod + export EXPORT_CONF_FOLDER=/var/www/mviewer/apps/store/ + export MVIEWERSTUDIO_PUBLISH_PATH=/var/www/mviewer/apps/prod export CONF_PUBLISH_PATH_FROM_MVIEWER=apps/prod - export DEFAULT_ORG=megalis + export DEFAULT_ORG=monorg flask run -p 5007 -Documentation Swagger (API) -=========================== - -Le backend Python expose une interface Swagger UI ainsi que le fichier OpenAPI : - -- Swagger UI : ``/swagger`` (ou ``/swagger/``) -- SpĂ©cification OpenAPI : ``/swagger.yaml`` - -Exemples : - -- sans prĂ©fixe d'URL : ``http://localhost:5007/swagger`` -- avec ``MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio`` : ``http://localhost:5007/mviewerstudio/swagger`` - -.. note:: - Ces routes sont servies directement par Flask via ``mviewerstudio_backend/route.py``. - Le fichier de spĂ©cification est ``srv/python/mviewerstudio_backend/swagger.yaml``. - - - Mise en production ****************** @@ -190,10 +151,10 @@ Mode opĂ©ratoire - Servir le backend python et le front de studio avec un service Linux - Proxyfier ce service avec Nginx ou Apache -1) CrĂ©ation des dossiers de stockage dans le dossier mviewer/apps +1) CrĂ©ation des dossiers de stockage des applications mviewer et de log ----------------------------------------------------------------- -CrĂ©ation du rĂ©pertoire de stockage des brouillons (store) et des applications publiĂ©es (prod). +CrĂ©ation du rĂ©pertoire de stockage des brouillons (store) et des applications publiĂ©es (prod) dans mon application mviewer. .. code-block:: sh @@ -203,64 +164,29 @@ CrĂ©ation du rĂ©pertoire de stockage des brouillons (store) et des applications mkdir /var/www/mviewer/apps/prod sudo chown monuser /var/www/mviewer/apps/prod - - -2) CrĂ©ation du service et activation du service ------------------------------------------------ - -CrĂ©er le rĂ©pertoire mviewerstudio dans /var/log +CrĂ©ation du rĂ©pertoire de log mviewerstudio .. code-block:: sh sudo mkdir /var/log/mviewerstudio sudo chown monuser /var/log/mviewerstudio -Vous devez crĂ©er un fichier dans `/etc/systemd/system/mviewerstudio.service`: - .. code-block:: sh +2) CrĂ©ation du service et activation du service +----------------------------------------------- - sudo nano /etc/systemd/system/mviewerstudio.service +Copier maintenant le fichier disponible dans install/mviewerstudio.service dans `/etc/systemd/system/mviewerstudio.service`. +Enfin, adaptez son contenu (notamment le user, le port, les chemins et l'emplacement des logs). -Ajoutez ensuite ce contenu en adaptant les valeurs (chemin, user...) selon votre environnement : + .. code-block:: sh -fichier `mviewerstudio.service` + sudo nano /etc/systemd/system/mviewerstudio.service - .. warning:: - Nous conseillons de laisser la valeur du worker Ă  1 (voir issue #389) - .. code-block:: sh +N'oubliez pas d'adapter le niveau des logs et les droits des rĂ©pertoires (Ă  crĂ©er si nĂ©cessaire) selon l'utilisateur dĂ©fini dans le fichier mviewerstudio.service (dans la configuration par dĂ©faut, l'utilisateur `monuser` devra pouvoir Ă©crire dans `/var/log/mviewerstudio`). - [Unit] - Description=mviewerstudio - After=network.target - - [Service] - User=monuser - Environment="EXPORT_CONF_FOLDER=/var/www/mviewer/apps/store/" - Environment="CONF_PUBLISH_PATH_FROM_MVIEWER=apps/prod" - Environment="CONF_PATH_FROM_MVIEWER=apps/store" - Environment="MVIEWERSTUDIO_PUBLISH_PATH=/var/www/mviewer/apps/prod" - Environment="DEFAULT_ORG=public" - Environment="LOG_LEVEL=INFO" - WorkingDirectory=/home/monuser/mviewerstudio/srv/python - ExecStart=/home/monuser/mviewerstudio/srv/python/.venv/bin/gunicorn \ - -b 127.0.0.1:5007 \ - --workers=1 \ - --access-logfile /var/log/mviewerstudio/gunicorn-access.log \ - --log-level info \ - --error-logfile /var/log/mviewerstudio/gunicorn-error.log \ - mviewerstudio_backend.app:app - - StandardOutput=append:/var/log/mviewerstudio//mviewerstudio.log - StandardError=append:/var/log/mviewerstudio/mviewerstudio.log - - [Install] - WantedBy=multi-user.target - -N'oubliez pas d'adapter le niveau des logs, le rĂ©pertoire des logs (Ă  crĂ©er si nĂ©cessaire) avec les bons droits (`monuser` dans cette confiugration devra pouvoir Ă©crire dans `/var/log/mviewerstudio`). - -Notre service tournera donc sur le port `5007` une fois dĂ©marrĂ©. +Le porte par dĂ©faut est sera le `5007` (Ă  adapter dans mviewerstudio.service). Activation et dĂ©marrage du service : @@ -278,6 +204,7 @@ A partir de maintenant, il est possible de stopper, redĂ©marrer ou afficher le s sudo systemctl restart mviewerstudio sudo systemctl status mviewerstudio.service + 3) Proxyfication du service --------------------------------- @@ -319,30 +246,31 @@ Rechargement de la conf apache Mise Ă  jour de l'application **************************** -Pour mettre Ă  jour le code source (e.g branche ``develop``), vous pouvez utilisez le script ``mviewerstudio/srv/python/sync.sh`` aprĂšs un ``git pull``. - -Il permet de copier / coller les sources vers le rĂ©pertoire ``static`` du backend Python. +Dans cette version (> Ă  4.2.1), la synchronisation entre la racine et le backend n'est plus Ă  rĂ©aliser Ă  la main car, avec un seul backend, tous les fichiers static sont dans /src/static. -Pour la mise Ă  jour, voici donc les commandes Ă  exĂ©cuter Ă  partir du rĂ©pertoire ``/mviewerstudio`` : +Pour la mise Ă  jour du code source, voici donc les commandes Ă  exĂ©cuter Ă  partir du rĂ©pertoire ``/mviewerstudio`` (en partant du principe que vous ĂȘtes bien sur la branche master): .. code-block:: sh - cd /full/path/mviewerstudio git pull - cd srv/python - sh ./sync.sh pull /full/path/mviewerstudio -Si besoin, rĂ©aliser un restart de votre service (e.g gunicorn) : +.. warning:: + + A chaque version, vous devrez comparer le fichier `src/static/config.json` avec la configuration disponible dans le dĂ©pĂŽt github. Ceci afin de vous assurez que vous avez bien toutes les clĂ©s de configuration nĂ©cessaires au bon fonctionnement de votre instance. + +Si vous parter d'une version antĂ©rieure (< 4.3), alors il faudra mettre Ă  jour votre service comme mentionnĂ© ci-dessus, puis recharger la configuration et redĂ©marrer de votre service (e.g gunicorn) : .. code-block:: sh - systemctl restart mviewerstudio + sudo nano /etc/systemd/system/mviewerstudio.service + sudo systemctl daemon-reload + sudo systemctl restart mviewerstudio Pour tout redĂ©marrage de gunicorn, vĂ©rifier que le service a bien dĂ©marrĂ© : .. code-block:: sh - systemctl status mviewerstudio + sudo systemctl status mviewerstudio .. warning:: @@ -351,3 +279,21 @@ Pour tout redĂ©marrage de gunicorn, vĂ©rifier que le service a bien dĂ©marrĂ© : Si vous constater dans le fichier de log d'erreur gunicorn que c'est bien le cas, redĂ©marrer le service avec la commande ``systemctl restart mviewerstudio`` + +Documentation Swagger (API) +**************************** + +Le backend Python expose une interface Swagger UI ainsi que le fichier OpenAPI : + +- Swagger UI : ``/swagger`` (ou ``/swagger/``) +- SpĂ©cification OpenAPI : ``/swagger.yaml`` + +Exemples : + +- sans prĂ©fixe d'URL : ``http://localhost:5007/swagger`` +- avec ``MVIEWERSTUDIO_URL_PATH_PREFIX=mviewerstudio`` : ``http://localhost:5007/mviewerstudio/swagger`` + +.. note:: + Ces routes sont servies directement par Flask via ``src/route.py``. + Le fichier de spĂ©cification est ``src/swagger.yaml``. + diff --git a/docs/doc_tech/migration_notes.rst b/docs/doc_tech/migration_notes.rst index 4e033727..10abc9fc 100644 --- a/docs/doc_tech/migration_notes.rst +++ b/docs/doc_tech/migration_notes.rst @@ -8,6 +8,86 @@ Notes de migration ================================== +Passer de v4.2.x Ă  v4.3.0 +~~~~~~~~~~~~~~~~~~~~~~~~~ + +1. **Suppression du PHP** + +Comme annoncĂ©, le backend PHP a Ă©tĂ© supprimĂ© au profit du backend Python. +Il n'est donc plus nĂ©cessaire d'installer PHP et de configurer le backend PHP pour faire fonctionner mviewerstudio. + +.. warning:: + + Qu'est-ce qu change ? + + - Le backend PHP n'est plus supportĂ©. + - Le frontend appelle uniquement l'API Python. + - Les brouillons, publications et versions reposent sur le backend Python. + - Les anciens XML issus du mode PHP ne sont pas directement exploitables comme des applications Python versionnĂ©es. Il faut les rĂ©importer manuellement dans mviewerstudio avec le backend python. + +Il est donc fortement conseillĂ© de migrer vers le backend Python pour bĂ©nĂ©ficier des derniĂšres fonctionnalitĂ©s et des correctifs de sĂ©curitĂ©. + +2. **Modification de la gestion des fichiers static** + +Suite Ă  la suppression de PHP, tous les fichiers static sont dĂ©sormais gĂ©rĂ©s par le backend Python (gunicorn / Flask). + +- Le backend est localisĂ© dans `/src` +- Les fichiers static sont localisĂ©s dans `/src/static` +- Le fichier de configuration du frontend est localisĂ© dans `/src/static/config.json` + +Autrefois, les fichiers static Ă©taient Ă  la racine du projet et devaient ĂȘtre copiĂ©s vers le rĂ©pertoire static du backend choisi. +Cette modification n'est donc plus Ă  faire. + +Il en est de mĂȘme pour la configuration du frontend qui est Ă  modifier directement dans `/src/static/config.json` + +3. **Impact sur l'installation** + +La procĂ©dure d'installation a Ă©tĂ© simplifiĂ©e puisque le backend PHP n'existe plus et que seules les ressources associĂ©es Ă  Python restent dans le code source. + +4. **Impact sur le service gunicorn** + + +Pour migrer vers cette nouvelle version, il est nĂ©cessaire de modifier le fichier mviewerstudio.service en utilisant les nouveaux chemins d'accĂšs pour : + +- WorkingDirectory - Doit pointer vers le rĂ©pertoire oĂč mviewerstudio est installĂ© +- ExecStart - l'argument WSGI/ASGI (application target) de gunicorn doit ĂȘtre modifiĂ© pour pointer vers l'emplacement du module python et l'objet associĂ© (`src.app:app` par dĂ©faut). + +5. **Processus Ă  partir d'une installation existante** + +.. warning:: + + Vous ne devez avoir aucune modification dans le code source du projet (rĂ©pertoire ISO avec la branche master). + + +.. warning:: + + Faites une copie des fichiers mviewerstudio.service et config.json avant de faire la migration. + + +ExĂ©cuter ces commandes : + +.. code-block:: sh + + cd /path/to/mviewerstudio + git pull + # VĂ©rifiez que vous ĂȘtes bien sur la branche master + + +Modifiez maintenant le contenu du fichier `mviewerstudio.service` en s'aidant de la page :ref:`install_python`). + +Modifiez enfin le fichier de configuration du frontend `src/static/config.json` pour adapter les paramĂštres Ă  votre installation (reprenez votre fichier prĂ©cĂ©dent). + +6. **Impact sur les cartes mviewer créées Ă  partir de mviewerstudio** + +Aucun impact. + +Passer de v4.1 Ă  v4.2 +~~~~~~~~~~~~~~~~~~~~~~ + +Suite aux modifications du backend pour afficher plus de logs, il est nĂ©cessaire de modifier le fichier mviewerstudio.service en ajoutant les options StandardOutput et StandardError comme ici : +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html#creation-du-service-et-activation-du-service + + Passer de v3.9.x Ă  v4.x ~~~~~~~~~~~~~~~~~~~~~~ @@ -25,18 +105,11 @@ La version 4 utilise des propriĂ©tĂ©s et des informations du XML rajoutĂ©es par Ces XML sont notamment versionnĂ©s et non dupliquĂ©s Ă  chaque modification. Les XML rĂ©alisĂ©s avec la version de mviewerstudio < 4 ne sont pas compatibles avec le backend Python de la v4. -2. **Choix du backend** +2. **Migration vers le backend Python** -Le backend PHP reste toutefois utilisable et identique Ă  la version 3.9.x sans nouveautĂ©s. Vos XML seront rĂ©utilisables en l'Ă©tat. -Si vous n'utiliser pas le backend Python, notez alors que vous ne pourrez pas disposer des derniĂšres nouveautĂ©s telles que le versionnement, la publication ou encore le gĂ©nĂ©rateur de template. +Le backend Python est dĂ©sormais l'unique backend maintenu. Les XML issus des versions antĂ©rieures doivent donc ĂȘtre rĂ©importĂ©s puis rĂ©enregistrĂ©s pour bĂ©nĂ©ficier du stockage, du versionnement et de la publication. 3. **Migrer vos XML manuellement** Si vous souhaiter utiliser le backend Python, mais que vous dĂ©sirez conserver vos XML, il sera nĂ©cessaire de les rĂ©importer unitairement en ouvrant le XML ``Depuis un ordinateur``. Vous devrez donc ouvrir le fichier afin de le re sauvegarder avec les informations nĂ©cessaires pour le bon fonctionnement de la v4. - -Passer de v4.1 Ă  v4.2 -~~~~~~~~~~~~~~~~~~~~~~ - -Suite aux modifications du backend pour afficher plus de logs, il est nĂ©cessaire de modifier le fichier mviewerstudio.service en ajoutant les options StandardOutput et StandardError comme ici : -https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html#creation-du-service-et-activation-du-service diff --git a/docs/doc_tech/move_to_python.rst b/docs/doc_tech/move_to_python.rst new file mode 100644 index 00000000..f5688a6e --- /dev/null +++ b/docs/doc_tech/move_to_python.rst @@ -0,0 +1,193 @@ +.. Authors : +.. mviewer team + +.. _move_to_python: + +Migration du backend PHP vers le backend Python +=============================================== + +Ce document dĂ©crit la marche Ă  suivre pour migrer une instance historique de +``mviewerstudio`` utilisant l'ancien backend PHP vers le backend Python +dĂ©sormais maintenu. + +Il complĂšte la documentation existante sans la dupliquer. Pour les dĂ©tails +d'installation et de configuration, reportez-vous aux pages de documentation +dĂ©jĂ  publiĂ©es. + +RĂ©fĂ©rences utiles +----------------- + +- Installation du backend Python : + https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html +- Configuration du frontend : + https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html +- Notes de migration : + https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/migration_notes.html +- Docker : + https://github.com/mviewer/mviewerstudio/blob/master/docker/readme.md +- Exemple de configuration frontend : + https://github.com/mviewer/mviewerstudio/blob/master/src/static/config.json + +Ce qui change +------------- + +- Le backend PHP n'est plus supportĂ©. +- Le frontend appelle uniquement l'API Python. +- Les brouillons, publications et versions reposent sur le backend Python. +- Les anciens XML issus du mode PHP ne sont pas directement exploitables comme + des applications Python versionnĂ©es. + +Voir aussi : +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/migration_notes.html + +PrĂ©parer la migration +--------------------- + +Avant toute bascule : + +1. Sauvegarder l'ancienne configuration front et les rĂ©pertoires contenant les + XML. +2. Identifier les chemins utilisĂ©s par l'instance ``mviewer`` pour lire les + applications. +3. PrĂ©parer les dossiers de travail Python, en gĂ©nĂ©ral : + + - un dossier de brouillons, par exemple ``apps/store`` + - un dossier de publication, par exemple ``apps/prod`` ou ``apps/public`` + +4. VĂ©rifier qu'une version de Python compatible est disponible. + +Pour les prĂ©requis systĂšme et l'installation du backend, voir +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html. + +Installer le backend Python +--------------------------- + +Installez ``mviewerstudio`` avec le backend Python en suivant la documentation +d'installation : + +- installation manuelle +- ou installation scriptĂ©e +- ou dĂ©ploiement Docker + +RĂ©fĂ©rence principale : +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html + +RĂ©fĂ©rence Docker : +https://github.com/mviewer/mviewerstudio/blob/master/docker/readme.md + +Remplacer la configuration frontend +----------------------------------- + +L'ancienne configuration PHP doit ĂȘtre remplacĂ©e par la configuration frontend +du studio, compatible avec le backend Python. + +Base de dĂ©part : + +- partir de ``src/static/config.json`` : + https://github.com/mviewer/mviewerstudio/blob/master/src/static/config.json +- adapter les URLs et chemins Ă  votre environnement + +Les paramĂštres les plus importants Ă  revoir sont : + +- ``api`` +- ``user_info`` +- ``store_style_service`` +- ``mviewer_instance`` +- ``publish_url`` +- ``conf_path_from_mviewer`` +- ``mviewer_short_url`` +- ``proxy`` + +Le dĂ©tail de chaque paramĂštre est documentĂ© dans +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html. + +DĂ©finir les variables d'environnement du backend +------------------------------------------------ + +Le backend Python nĂ©cessite au minimum les variables suivantes : + +- ``CONF_PATH_FROM_MVIEWER`` +- ``CONF_PUBLISH_PATH_FROM_MVIEWER`` +- ``EXPORT_CONF_FOLDER`` +- ``MVIEWERSTUDIO_PUBLISH_PATH`` +- ``DEFAULT_ORG`` + +Selon votre dĂ©ploiement, vous devrez aussi dĂ©finir : + +- ``LOG_LEVEL`` +- ``MVIEWERSTUDIO_URL_PATH_PREFIX`` + +Les valeurs attendues et les exemples de service ``systemd`` sont dĂ©crits dans +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html. + +Migrer les XML existants +------------------------ + +Le point important de la migration est le traitement des anciens XML. + +Les XML provenant du fonctionnement historique avec PHP doivent ĂȘtre rĂ©importĂ©s +puis rĂ©enregistrĂ©s dans le studio pour ĂȘtre pris en charge correctement par le +backend Python. + +ProcĂ©dure recommandĂ©e : + +1. DĂ©marrer l'instance Python. +2. Ouvrir ``mviewerstudio``. +3. Importer chaque ancien XML via l'option ``Depuis un ordinateur``. +4. VĂ©rifier le rendu de l'application. +5. Enregistrer l'application pour que les mĂ©tadonnĂ©es Python soient gĂ©nĂ©rĂ©es. +6. Publier l'application si nĂ©cessaire. + +Cette Ă©tape est rĂ©sumĂ©e dans +https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/migration_notes.html. + +Adapter l'exploitation +---------------------- + +AprĂšs la bascule : + +- supprimer les anciens scripts et fichiers de configuration PHP de votre + dĂ©ploiement +- retirer tout service Docker ou Apache/PHP devenu inutile +- vĂ©rifier les rĂšgles de proxy ou de publication cĂŽtĂ© serveur web +- vĂ©rifier que ``mviewer`` lit bien les applications depuis les rĂ©pertoires + attendus + +Pour une installation Docker, voir +https://github.com/mviewer/mviewerstudio/blob/master/docker/readme.md. + +VĂ©rifications aprĂšs migration +----------------------------- + +ContrĂŽles minimaux Ă  effectuer : + +1. L'accĂšs Ă  l'interface studio fonctionne. +2. La rĂ©cupĂ©ration des informations utilisateur fonctionne. +3. L'enregistrement d'un brouillon fonctionne. +4. La prĂ©visualisation fonctionne. +5. La publication et la dĂ©publication fonctionnent. +6. Les XML publiĂ©s sont accessibles depuis ``mviewer``. +7. L'API Swagger est accessible sur ``/swagger``. + +RĂ©solution de problĂšmes +----------------------- + +- Si le frontend ne charge pas la configuration, vĂ©rifier + ``src/static/config.json``. +- Si les applications ne s'enregistrent pas, vĂ©rifier les droits sur + ``EXPORT_CONF_FOLDER``. +- Si la publication Ă©choue, vĂ©rifier ``MVIEWERSTUDIO_PUBLISH_PATH`` et + ``CONF_PUBLISH_PATH_FROM_MVIEWER``. +- Si les services distants ne rĂ©pondent pas, vĂ©rifier la configuration + ``proxy`` et la liste blanche cĂŽtĂ© backend. + +En rĂ©sumĂ© +--------- + +La migration PHP vers Python consiste Ă  : + +1. installer le backend Python, +2. remplacer l'ancienne configuration PHP par la configuration frontend du studio, +3. configurer les variables d'environnement et les rĂ©pertoires de stockage, +4. rĂ©importer puis rĂ©enregistrer les anciens XML, +5. valider les flux de brouillon, prĂ©visualisation et publication. diff --git a/docs/doc_user/accueil.rst b/docs/doc_user/accueil.rst index cb8a0648..59695fa8 100644 --- a/docs/doc_user/accueil.rst +++ b/docs/doc_user/accueil.rst @@ -115,6 +115,6 @@ Les liens en bas de page renvoient vers : .. _mviewer: https://github.com/mviewer/mviewer -.. _dĂ©lĂ©guĂ©: https://cms.geobretagne.fr/sites/default/files/documents/202410_geobretagne_manuel_administrateur.pdf +.. _dĂ©lĂ©guĂ©: https://cms.geobretagne.fr/formation/kit-de-formation-geobretagne-publier-et-diffuser-une-donnee -.. _GĂ©oBretagne: https://cms.geobretagne.fr/sites/default/files/documents/202410_geobretagne_manuel_administrateur.pdf +.. _GĂ©oBretagne: https://cms.geobretagne.fr/formation/kit-de-formation-geobretagne-publier-et-diffuser-une-donnee diff --git a/docs/index.rst b/docs/index.rst index 3a787ad4..66bf0a9b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,9 +44,10 @@ Cette partie est dĂ©diĂ©e aux personnes qui ont vocation Ă  dĂ©ployer et configu :caption: Documentation technique doc_tech/install_python - doc_tech/install_other + doc_tech/install_docker doc_tech/config_front doc_tech/migration_notes + doc_tech/move_to_python doc_tech/dev_corner @@ -75,4 +76,3 @@ Sauf indication contraire, cette documentation est sous licence **Creative Commo .. _mviewer: https://github.com/mviewer/mviewer .. _GitHub: https://github.com/mviewer/mviewerstudio/ - diff --git a/install/README.en.md b/install/README.en.md new file mode 100644 index 00000000..6f205186 --- /dev/null +++ b/install/README.en.md @@ -0,0 +1,124 @@ +# Installation + +### Requirements + +- A Linux system with `bash` +- Python >= 3.9 and `venv` +- `git` to clone the repository +- `apt` (optional) to automatically install system packages + +The script will attempt to automatically install the following packages: +```sh +libxslt1-dev libxml2-dev python3 python3-pip python3-venv git +``` + +### Online Documentation (more detailed) + +- 📘 [User Documentation (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_user/accueil.html) +- 🔧 [Installation Guide (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html) +- ⚙ [Configuration and Administration (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html) +- đŸ’» [Technical Documentation (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/dev_corner.html) + +--- + +## Quick Installation (with the script) + +This procedure is only for installation for local testing or in a development environment. + +Installation in a production environment is described in the technical documentation and requires configuring a service file (systemctl) via gunicorn. + +### Step 1: Clone the repository + +```sh +git clone https://github.com/mviewer/mviewerstudio.git +cd mviewerstudio +``` + +### Step 2: Run the installation script + +From the project root: + +```sh +bash ./install/install.sh +``` + +The script will: +- ✅ Create the virtual environment in `.venv` +- ✅ Install Python dependencies +- ✅ Configure necessary files + +### Step 3: Configuration + +The script displays the next steps, including: + +- The path to the front configuration file: `src/static/config.json` +- Backend environment variables to export +- The command to start Flask + +### Variant: Installation with clone in a different directory + +```sh +bash ./install/install.sh [branch] [directory_name] +``` + +Example: + +```sh +bash ./install/install.sh /home/user/git develop mviewerstudio_develop +``` + +Parameters: +- `parent_directory`: parent directory where to clone the project +- `branch`: branch to check out after cloning +- `directory_name`: target folder name (default: `mviewerstudio`) + +--- + +## Manual Installation (step by step) + +### Step 1: Clone the repository + +```sh +git clone https://github.com/mviewer/mviewerstudio.git +cd mviewerstudio +``` + +### Step 2: Create the virtual environment + +```sh +python3 -m venv .venv +``` + +### Step 3: Activate the virtual environment + +```sh +source .venv/bin/activate +``` + +### Step 4: Install Python dependencies + +```sh +pip install -r install/requirements.txt +``` + +--- + +## Starting the Application + +### Step 1: Activate the virtual environment + +```sh +source .venv/bin/activate +``` + +### Step 2: Configure environment variables (if necessary) + +Check `src/static/config.json` for front configurations. + +### Step 3: Launch Flask + +```sh +flask --app src/app.py run -p 5007 +``` + +The application will be available at: `http://localhost:5007` diff --git a/install/README.fr.md b/install/README.fr.md new file mode 100644 index 00000000..745d1b89 --- /dev/null +++ b/install/README.fr.md @@ -0,0 +1,124 @@ +# Installation + +### PrĂ©requis + +- Un systĂšme Linux avec `bash` +- Python >= 3.9 et `venv` +- `git` pour cloner le dĂ©pĂŽt +- `apt` (optionnel) pour installer automatiquement les paquets systĂšme + +Le script tentera d'installer automatiquement les paquets suivants : +```sh +libxslt1-dev libxml2-dev python3 python3-pip python3-venv git +``` + +### Documentation en ligne (plus dĂ©taillĂ©e) + +- 📘 [Documentation utilisateur (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_user/accueil.html) +- 🔧 [Guide d'installation (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html) +- ⚙ [Configuration et administration (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/config_front.html) +- đŸ’» [Documentation technique (FR)](https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/dev_corner.html) + +--- + +## Installation rapide (avec le script) + +Cette procĂ©dure concerne uniquement une installation pour un test en local ou dans un environnement de dĂ©veloppement. + +L'installation dans un environnement de production est dĂ©crite dans la documentation technique et nĂ©cessite de configurer un fichier de service (systemctl) via gunicorn. + +### Étape 1 : Cloner le dĂ©pĂŽt + +```sh +git clone https://github.com/mviewer/mviewerstudio.git +cd mviewerstudio +``` + +### Étape 2 : Lancer le script d'installation + +Depuis la racine du projet : + +```sh +bash ./install/install.sh +``` + +Le script va : +- ✅ CrĂ©er l'environnement virtuel dans `.venv` +- ✅ Installer les dĂ©pendances Python +- ✅ Configurer les fichiers nĂ©cessaires + +### Étape 3 : Configuration + +Le script affiche les prochaines Ă©tapes, notamment : + +- Le chemin du fichier de configuration front : `src/static/config.json` +- Les variables d'environnement backend Ă  exporter +- La commande pour dĂ©marrer Flask + +### Variante : Installation avec clonage dans un rĂ©pertoire diffĂ©rent + +```sh +bash ./install/install.sh [branch] [directory_name] +``` + +Exemple : + +```sh +bash ./install/install.sh /home/user/git develop mviewerstudio_develop +``` + +ParamĂštres : +- `parent_directory` : rĂ©pertoire parent dans lequel cloner le projet +- `branch` : branche Ă  checkout aprĂšs le clonage +- `directory_name` : nom du dossier cible (dĂ©faut : `mviewerstudio`) + +--- + +## Installation manuelle (Ă©tape par Ă©tape) + +### Étape 1 : Cloner le dĂ©pĂŽt + +```sh +git clone https://github.com/mviewer/mviewerstudio.git +cd mviewerstudio +``` + +### Étape 2 : CrĂ©er l'environnement virtuel + +```sh +python3 -m venv .venv +``` + +### Étape 3 : Activer l'environnement virtuel + +```sh +source .venv/bin/activate +``` + +### Étape 4 : Installer les dĂ©pendances Python + +```sh +pip install -r install/requirements.txt +``` + +--- + +## DĂ©marrage de l'application + +### Étape 1 : Activer l'environnement virtuel + +```sh +source .venv/bin/activate +``` + +### Étape 2 : Configurer les variables d'environnement (si nĂ©cessaire) + +Consultez `src/static/config.json` pour les configurations front. + +### Étape 3 : Lancer Flask + +```sh +flask --app src/app.py run -p 5007 +``` + +L'application sera disponible Ă  : `http://localhost:5007` diff --git a/install/README.md b/install/README.md new file mode 100644 index 00000000..ba7660fa --- /dev/null +++ b/install/README.md @@ -0,0 +1,9 @@ +# Installation Guide / Guide d'Installation + +## đŸ‡«đŸ‡· Français + +Pour lire les instructions d'installation en français, consultez [README.fr.md](README.fr.md#fr) + +## 🇬🇧 English + +For English installation instructions, see [README.en.md](README.en.md#en) diff --git a/srv/python/dev-requirements.txt b/install/dev-requirements.txt similarity index 100% rename from srv/python/dev-requirements.txt rename to install/dev-requirements.txt diff --git a/install/install.sh b/install/install.sh new file mode 100644 index 00000000..e8c362a7 --- /dev/null +++ b/install/install.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +set -euo pipefail + +# ========================================================================================== +# Script name : install.sh +# Author : PSC mviewer +# Description : Install mviewerstudio from the current checkout or by cloning the repo +# Usage : ./install/install.sh [parent_directory] [branch] [directory_name] +# Documentation : https://mviewerstudio.readthedocs.io/fr/stable/doc_tech/install_python.html +# ========================================================================================== + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +WORKING_PATH="${1:-}" +BRANCH="${2:-}" +TARGET_NAME="${3:-mviewerstudio}" +REPO_URL="https://github.com/mviewer/mviewerstudio.git" + +install_system_packages() { + if ! command -v apt >/dev/null 2>&1; then + echo "Skipping system package installation: 'apt' not found." + return + fi + + local apt_runner="apt" + if [ "${EUID}" -ne 0 ]; then + if command -v sudo >/dev/null 2>&1; then + apt_runner="sudo apt" + else + echo "Cannot install system packages automatically: run as root or install sudo." + return + fi + fi + + echo "Installing required system packages..." + ${apt_runner} install -y libxslt1-dev libxml2-dev python3 python3-pip python3-venv git +} + +resolve_project_dir() { + if [ -z "${WORKING_PATH}" ]; then + printf '%s\n' "${ROOT_DIR}" + return + fi + + mkdir -p "${WORKING_PATH}" + printf '%s\n' "${WORKING_PATH%/}/${TARGET_NAME}" +} + +clone_if_needed() { + local project_dir="$1" + + if [ -z "${WORKING_PATH}" ]; then + return + fi + + if [ ! -d "${project_dir}/.git" ]; then + echo "Cloning repository into ${project_dir}..." + git clone "${REPO_URL}" "${project_dir}" + fi + + if [ -n "${BRANCH}" ]; then + echo "Checking out branch ${BRANCH}..." + git -C "${project_dir}" checkout "${BRANCH}" + fi +} + +setup_front_config() { + local project_dir="$1" + local front_config="${project_dir}/src/static/config.json" + + if [ ! -f "${front_config}" ]; then + echo "Missing front config: ${front_config}" + exit 1 + fi +} + +print_next_steps() { + local project_dir="$1" + + cat < None: def load_config(app: Flask) -> None: - app.config.from_object("mviewerstudio_backend.settings.Config") + app.config.from_object(Config) app.config.from_envvar("CONFIG_FILE", silent=True) diff --git a/srv/python/mviewerstudio_backend/error_handlers.py b/src/error_handlers.py similarity index 100% rename from srv/python/mviewerstudio_backend/error_handlers.py rename to src/error_handlers.py diff --git a/srv/python/mviewerstudio_backend/models/config.py b/src/models/config.py similarity index 100% rename from srv/python/mviewerstudio_backend/models/config.py rename to src/models/config.py diff --git a/srv/python/mviewerstudio_backend/models/register.py b/src/models/register.py similarity index 100% rename from srv/python/mviewerstudio_backend/models/register.py rename to src/models/register.py diff --git a/srv/python/mviewerstudio_backend/models/user.py b/src/models/user.py similarity index 100% rename from srv/python/mviewerstudio_backend/models/user.py rename to src/models/user.py diff --git a/src/mviewerstudio_backend.egg-info/PKG-INFO b/src/mviewerstudio_backend.egg-info/PKG-INFO new file mode 100644 index 00000000..b383dcca --- /dev/null +++ b/src/mviewerstudio_backend.egg-info/PKG-INFO @@ -0,0 +1,26 @@ +Metadata-Version: 2.4 +Name: mviewerstudio_backend +Version: 0.2 +Summary: A simple API for mviewerstudio +Home-page: https://github.com/mviewer/mviewerstudio +Author: mviewer community +Author-email: +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.11 +Classifier: Framework :: Flask +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application +Requires-Python: >=3.11 +Requires-Dist: flask>=2 +Requires-Dist: gunicorn>20 +Requires-Dist: lxml>=4.9.2 +Requires-Dist: GitPython>=3 +Requires-Dist: requests +Requires-Dist: Unidecode +Dynamic: author +Dynamic: classifier +Dynamic: home-page +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary diff --git a/src/mviewerstudio_backend.egg-info/SOURCES.txt b/src/mviewerstudio_backend.egg-info/SOURCES.txt new file mode 100644 index 00000000..2e56a030 --- /dev/null +++ b/src/mviewerstudio_backend.egg-info/SOURCES.txt @@ -0,0 +1,22 @@ +README.md +app.py +app_factory.py +error_handlers.py +register_utils.py +route.py +settings.py +setup.py +test.py +models/config.py +models/register.py +models/user.py +mviewerstudio_backend.egg-info/PKG-INFO +mviewerstudio_backend.egg-info/SOURCES.txt +mviewerstudio_backend.egg-info/dependency_links.txt +mviewerstudio_backend.egg-info/requires.txt +mviewerstudio_backend.egg-info/top_level.txt +utils/commons.py +utils/config_utils.py +utils/git_utils.py +utils/login_utils.py +utils/register_utils.py \ No newline at end of file diff --git a/src/mviewerstudio_backend.egg-info/dependency_links.txt b/src/mviewerstudio_backend.egg-info/dependency_links.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/mviewerstudio_backend.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/mviewerstudio_backend.egg-info/requires.txt b/src/mviewerstudio_backend.egg-info/requires.txt new file mode 100644 index 00000000..f10a22c0 --- /dev/null +++ b/src/mviewerstudio_backend.egg-info/requires.txt @@ -0,0 +1,6 @@ +flask>=2 +gunicorn>20 +lxml>=4.9.2 +GitPython>=3 +requests +Unidecode diff --git a/src/mviewerstudio_backend.egg-info/top_level.txt b/src/mviewerstudio_backend.egg-info/top_level.txt new file mode 100644 index 00000000..2f9a6a9b --- /dev/null +++ b/src/mviewerstudio_backend.egg-info/top_level.txt @@ -0,0 +1,9 @@ +app +app_factory +error_handlers +models +register_utils +route +settings +test +utils diff --git a/srv/python/mviewerstudio_backend/register_utils.py b/src/register_utils.py similarity index 100% rename from srv/python/mviewerstudio_backend/register_utils.py rename to src/register_utils.py diff --git a/srv/python/mviewerstudio_backend/route.py b/src/route.py similarity index 99% rename from srv/python/mviewerstudio_backend/route.py rename to src/route.py index 1f35f0f2..4dffd38c 100644 --- a/srv/python/mviewerstudio_backend/route.py +++ b/src/route.py @@ -7,6 +7,7 @@ redirect, render_template_string, send_from_directory, + url_for, ) from .utils.login_utils import current_user from .utils.config_utils import ( diff --git a/srv/python/mviewerstudio_backend/settings.py b/src/settings.py similarity index 78% rename from srv/python/mviewerstudio_backend/settings.py rename to src/settings.py index cb5d0c53..f7295327 100644 --- a/srv/python/mviewerstudio_backend/settings.py +++ b/src/settings.py @@ -7,7 +7,7 @@ class Config: "CONF_PUBLISH_PATH_FROM_MVIEWER", "apps/public" ) EXPORT_CONF_FOLDER = os.getenv( - "EXPORT_CONF_FOLDER", "/home/user/git/mviewer/apps/store" + "EXPORT_CONF_FOLDER", "/home/gaetan/projects/mviewer/mviewer/apps/store" ) LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") @@ -16,7 +16,8 @@ class Config: "geobretagne.fr,ows.region-bretagne.fr,kartenn.region-bretagne.fr", ).split(",") MVIEWERSTUDIO_PUBLISH_PATH = os.getenv( - "MVIEWERSTUDIO_PUBLISH_PATH", "/home/user/git/mviewer/apps/public" + "MVIEWERSTUDIO_PUBLISH_PATH", + "/home/gaetan/projects/mviewer/mviewer/apps/public", ) DEFAULT_ORG = os.getenv("DEFAULT_ORG", "public") MVIEWERSTUDIO_URL_PATH_PREFIX = os.getenv("MVIEWERSTUDIO_URL_PATH_PREFIX", "") diff --git a/src/setup.py b/src/setup.py new file mode 100644 index 00000000..e9ffa021 --- /dev/null +++ b/src/setup.py @@ -0,0 +1,44 @@ +from pathlib import Path + +from setuptools import find_namespace_packages, setup + +ROOT_DIR = Path(__file__).resolve().parent.parent +REQUIREMENTS_PATH = ROOT_DIR / "install" / "requirements.txt" +REQUIREMENTS = [ + line.strip() + for line in REQUIREMENTS_PATH.read_text().splitlines() + if line.strip() and not line.strip().startswith("#") +] + +setup( + name="mviewerstudio_backend", + version="0.2", + description="A simple API for mviewerstudio", + author="mviewer community", + author_email="", + url="https://github.com/mviewer/mviewerstudio", + packages=find_namespace_packages( + include=["models", "models.*", "utils", "utils.*"] + ), + py_modules=[ + "app", + "app_factory", + "error_handlers", + "register_utils", + "route", + "settings", + "test", + ], + install_requires=REQUIREMENTS, + python_requires=">=3.9", + classifiers=[ + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Framework :: Flask", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + ], +) diff --git a/config-python-sample.json b/src/static/config.json similarity index 98% rename from config-python-sample.json rename to src/static/config.json index 0786e50d..25743858 100644 --- a/config-python-sample.json +++ b/src/static/config.json @@ -1,8 +1,8 @@ { "app_conf": { "studio_title": "Mviewer Studio", - "mviewer_version": "4", - "mviewerstudio_version": "4.2.1", + "mviewer_version": "4.1", + "mviewerstudio_version": "4.3", "api": "api/app", "store_style_service": "api/style", "mviewer_instance": "/mviewer/", @@ -178,7 +178,7 @@ "title": "Catalogue DataGrandEst", "url": "https://datagrandest.fr/geonetwork/srv/fre/csw", "baseref": "https://datagrandest.fr/geonetwork/srv/eng/catalog.search?node=srv#/metadata/" - } + } ], "wms": [{ "title": "Serveur WMS de la RĂ©gion", diff --git a/css/_variables.scss b/src/static/css/_variables.scss similarity index 100% rename from css/_variables.scss rename to src/static/css/_variables.scss diff --git a/css/bootstrap.css b/src/static/css/bootstrap.css similarity index 100% rename from css/bootstrap.css rename to src/static/css/bootstrap.css diff --git a/css/mviewerstudio.css b/src/static/css/mviewerstudio.css similarity index 100% rename from css/mviewerstudio.css rename to src/static/css/mviewerstudio.css diff --git a/css/wizard.css b/src/static/css/wizard.css similarity index 100% rename from css/wizard.css rename to src/static/css/wizard.css diff --git a/img/FRFinanceEU_BLACK Outline.png b/src/static/img/FRFinanceEU_BLACK Outline.png similarity index 100% rename from img/FRFinanceEU_BLACK Outline.png rename to src/static/img/FRFinanceEU_BLACK Outline.png diff --git a/img/Logo_France_Relance_vert.svg b/src/static/img/Logo_France_Relance_vert.svg similarity index 100% rename from img/Logo_France_Relance_vert.svg rename to src/static/img/Logo_France_Relance_vert.svg diff --git a/img/basemap/cassini.jpg b/src/static/img/basemap/cassini.jpg similarity index 100% rename from img/basemap/cassini.jpg rename to src/static/img/basemap/cassini.jpg diff --git a/img/basemap/comic.png b/src/static/img/basemap/comic.png similarity index 100% rename from img/basemap/comic.png rename to src/static/img/basemap/comic.png diff --git a/img/basemap/darkmatter.png b/src/static/img/basemap/darkmatter.png similarity index 100% rename from img/basemap/darkmatter.png rename to src/static/img/basemap/darkmatter.png diff --git a/img/basemap/esriworldwide.jpg b/src/static/img/basemap/esriworldwide.jpg similarity index 100% rename from img/basemap/esriworldwide.jpg rename to src/static/img/basemap/esriworldwide.jpg diff --git a/img/basemap/etatmajor.jpg b/src/static/img/basemap/etatmajor.jpg similarity index 100% rename from img/basemap/etatmajor.jpg rename to src/static/img/basemap/etatmajor.jpg diff --git a/img/basemap/grid.png b/src/static/img/basemap/grid.png similarity index 100% rename from img/basemap/grid.png rename to src/static/img/basemap/grid.png diff --git a/img/basemap/handdrawn.png b/src/static/img/basemap/handdrawn.png similarity index 100% rename from img/basemap/handdrawn.png rename to src/static/img/basemap/handdrawn.png diff --git a/img/basemap/ir.jpg b/src/static/img/basemap/ir.jpg similarity index 100% rename from img/basemap/ir.jpg rename to src/static/img/basemap/ir.jpg diff --git a/img/basemap/location.md b/src/static/img/basemap/location.md similarity index 100% rename from img/basemap/location.md rename to src/static/img/basemap/location.md diff --git a/img/basemap/mapquest.png b/src/static/img/basemap/mapquest.png similarity index 100% rename from img/basemap/mapquest.png rename to src/static/img/basemap/mapquest.png diff --git a/img/basemap/ortho-ancien.jpg b/src/static/img/basemap/ortho-ancien.jpg similarity index 100% rename from img/basemap/ortho-ancien.jpg rename to src/static/img/basemap/ortho-ancien.jpg diff --git a/img/basemap/ortho.jpg b/src/static/img/basemap/ortho.jpg similarity index 100% rename from img/basemap/ortho.jpg rename to src/static/img/basemap/ortho.jpg diff --git a/img/basemap/osm.png b/src/static/img/basemap/osm.png similarity index 100% rename from img/basemap/osm.png rename to src/static/img/basemap/osm.png diff --git a/img/basemap/osm_google.png b/src/static/img/basemap/osm_google.png similarity index 100% rename from img/basemap/osm_google.png rename to src/static/img/basemap/osm_google.png diff --git a/img/basemap/osm_grey.png b/src/static/img/basemap/osm_grey.png similarity index 100% rename from img/basemap/osm_grey.png rename to src/static/img/basemap/osm_grey.png diff --git a/img/basemap/pirate.png b/src/static/img/basemap/pirate.png similarity index 100% rename from img/basemap/pirate.png rename to src/static/img/basemap/pirate.png diff --git a/img/basemap/positron.png b/src/static/img/basemap/positron.png similarity index 100% rename from img/basemap/positron.png rename to src/static/img/basemap/positron.png diff --git a/img/basemap/scan-express.jpg b/src/static/img/basemap/scan-express.jpg similarity index 100% rename from img/basemap/scan-express.jpg rename to src/static/img/basemap/scan-express.jpg diff --git a/img/basemap/scan.jpg b/src/static/img/basemap/scan.jpg similarity index 100% rename from img/basemap/scan.jpg rename to src/static/img/basemap/scan.jpg diff --git a/img/basemap/toner-lite.png b/src/static/img/basemap/toner-lite.png similarity index 100% rename from img/basemap/toner-lite.png rename to src/static/img/basemap/toner-lite.png diff --git a/img/basemap/toner.png b/src/static/img/basemap/toner.png similarity index 100% rename from img/basemap/toner.png rename to src/static/img/basemap/toner.png diff --git a/img/basemap/watercolor.jpg b/src/static/img/basemap/watercolor.jpg similarity index 100% rename from img/basemap/watercolor.jpg rename to src/static/img/basemap/watercolor.jpg diff --git a/img/doc.png b/src/static/img/doc.png similarity index 100% rename from img/doc.png rename to src/static/img/doc.png diff --git a/img/favicon_mstudio.png b/src/static/img/favicon_mstudio.png similarity index 100% rename from img/favicon_mstudio.png rename to src/static/img/favicon_mstudio.png diff --git a/img/homeMstudio.svg b/src/static/img/homeMstudio.svg similarity index 100% rename from img/homeMstudio.svg rename to src/static/img/homeMstudio.svg diff --git a/img/icons/icons-fontawesome.html b/src/static/img/icons/icons-fontawesome.html similarity index 100% rename from img/icons/icons-fontawesome.html rename to src/static/img/icons/icons-fontawesome.html diff --git a/img/logo_mviewerstudio.svg b/src/static/img/logo_mviewerstudio.svg similarity index 100% rename from img/logo_mviewerstudio.svg rename to src/static/img/logo_mviewerstudio.svg diff --git a/index.html b/src/static/index.html similarity index 99% rename from index.html rename to src/static/index.html index 72405554..3a53625d 100755 --- a/index.html +++ b/src/static/index.html @@ -1074,12 +1074,6 @@
-
- -
@@ -1280,11 +1274,6 @@
Style de la donnée
-
  • -
    - Sélectionner les champs à afficher et leurs aspects -
    -
  • diff --git a/js/manageDisplayContainer.js b/src/static/js/manageDisplayContainer.js similarity index 97% rename from js/manageDisplayContainer.js rename to src/static/js/manageDisplayContainer.js index 09706a45..d5804ceb 100644 --- a/js/manageDisplayContainer.js +++ b/src/static/js/manageDisplayContainer.js @@ -3,10 +3,6 @@ function showStudio() { document.getElementById("containerHome").hidden = true; document.getElementById("containerStudio").hidden = false; map.updateSize(); - let onlineCard = document.getElementById("onlineCard"); - if (_conf.is_php && onlineCard) { - onlineCard.remove(); - } } function goHome() { diff --git a/js/mviewerstudio.js b/src/static/js/mviewerstudio.js similarity index 94% rename from js/mviewerstudio.js rename to src/static/js/mviewerstudio.js index 08d7ee4d..7e6432ae 100644 --- a/js/mviewerstudio.js +++ b/src/static/js/mviewerstudio.js @@ -17,7 +17,7 @@ $(document).ready(function () { ) ); } - fetch("apps/config.json", { + fetch("config.json", { method: "GET", header: { contentType: "application/json", @@ -832,28 +832,6 @@ var createBaseLayerDef = function (bsl) { return parameters; }; -var deleteMyApplications = function () { - if (!_conf?.php?.delete_service) { - return alert(mviewer.tr("msg.config_error")); - } - $.ajax({ - type: "GET", - url: _conf.php.delete_service, - success: function (data) { - alert(data.deleted_files + mviewer.tr("msg.deleted_apps")); - mv.getListeApplications(); - }, - error: function (xhr, ajaxOptions, thrownError) { - console.error("map files deletion failed", { - xhr: xhr, - ajaxOptions: ajaxOptions, - thrownError: thrownError, - }); - alert(mviewer.tr("msg.delete_req_error")); - }, - }); -}; - var deleteApplication = (id) => { return fetch(`${_conf.api}/${id}`, { method: "DELETE", @@ -1176,30 +1154,6 @@ var getConfig = () => { return conf; }; -let previewWithPhp = (conf) => { - if (!_conf?.php?.upload_service) { - alertCustom(mviewer.tr("msg.alert_wrong_config"), "error"); - } - // Save the map serverside - $.ajax({ - type: "POST", - url: _conf.php.upload_service, - data: conf.join(""), - dataType: "json", - contentType: "text/xml", - success: function (data) { - // Preview the map - var url = ""; - if (data.success && data.filepath) { - // Build a short and readable URL for the map - let url = mv.produceUrl(data.filepath); - window.open(url, "mvs_vizualize"); - alertCustom(mviewer.tr("msg.download_success"), "success"); - } - }, - }); -}; - let previewAppsWithoutSave = (id, showPublish) => { if (config.relation && _conf.publish_url && showPublish) { const filePath = `${mv.getAuthentUserInfos("groupSlugName")}/${config.relation}`; @@ -1210,9 +1164,6 @@ let previewAppsWithoutSave = (id, showPublish) => { if (!confXml || (confXml && !mv.validateXML(confXml.join("")))) { return alertCustom("XML invalide !", "danger"); } - if (_conf.is_php) { - return previewWithPhp(confXml); - } if (!id || !config.isFile) { return alertCustom(mviewer.tr("msg.preview_no_save"), "danger"); } @@ -1236,9 +1187,6 @@ let previewAppsWithoutSave = (id, showPublish) => { }; const downloadXML = () => { - if (_conf.is_php) { - return downloadXML4PHP(); - } fetch(`api/download/${config.id}`) .then((r) => r.json()) .then((r) => { @@ -1251,37 +1199,6 @@ const downloadXML = () => { delete link; }); }; -const downloadXML4PHP = () => { - const conf = getConfig(); - if (mv.validateXML(conf.join(""))) { - var element = document.createElement("a"); - element.setAttribute( - "href", - "data:text/xml;charset=utf-8," + encodeURIComponent(conf.join("")) - ); - element.setAttribute( - "download", - document.querySelector("#opt-title").value || moment().format("MMDDYYYYhhmmss") - ); - element.style.display = "none"; - document.body.appendChild(element); - element.click(); - document.body.removeChild(element); - } -}; - -var saveAppWithPhp = (conf) => { - $.ajax({ - type: "POST", - url: _conf.php.upload_service, - data: conf.join(""), - dataType: "json", - contentType: "text/xml", - success: function (data) { - alert(mviewer.tr("msg.file_saved_on_server") + " (" + data.filepath + ")."); - }, - }); -}; var saveTemplateToGetUrl = () => new Promise((resolve, reject) => { @@ -1319,13 +1236,9 @@ var saveTemplateToGetUrl = () => }); }); var saveApplicationParameters = (close) => { - if (_conf?.is_php) { + saveTemplateToGetUrl().then(() => { saveApplicationsConfig(close); - } else { - saveTemplateToGetUrl().then(() => { - saveApplicationsConfig(close); - }); - } + }); }; var saveAppWithPython = (exists, conf, url, close) => { @@ -1338,8 +1251,7 @@ var saveAppWithPython = (exists, conf, url, close) => { }) .then((r) => (r.ok ? r.json() : Promise.reject(r))) .then((r) => { - if (!_conf.is_php && !close) { - // don't execute this code with php backend + if (!close) { config.isFile = true; document.querySelector("#toolsbarStudio-delete").classList.remove("d-none"); document.querySelector("#layerOptionBtn").classList.remove("d-none"); @@ -1363,9 +1275,6 @@ var saveApplicationsConfig = (close, message = "") => { if (!conf || !mv.validateXML(conf.join(""))) { return alertCustom(mviewer.tr("msg.xml_doc_invalid"), "danger"); } - if (_conf.is_php) { - return saveAppWithPhp(conf); - } // Save the map serverside const url = message ? `${_conf.api}?message=${message}` : _conf.api; mv.appExists(config.id, (r) => saveAppWithPython(r.exists, conf, url, close)); @@ -1454,33 +1363,28 @@ var loadApplicationParametersFromRemoteFile = function (url) { alertCustom(mviewer.tr("msg.retrieval_req_error"), "danger"); }), ]; - if (!_conf.is_php) { - waitRequests.push( - fetch(_conf.api) - .then((r) => { - return r.ok ? r.json() : Promise.reject(r); - }) - .then((r) => { - return r.filter((app) => app.id == config.id); - }) - .catch(() => alert(mviewer.tr("msg.retrieval_req_error"), "danger")) - ); - } + waitRequests.push( + fetch(_conf.api) + .then((r) => { + return r.ok ? r.json() : Promise.reject(r); + }) + .then((r) => { + return r.filter((app) => app.id == config.id); + }) + .catch(() => alert(mviewer.tr("msg.retrieval_req_error"), "danger")) + ); Promise.all(waitRequests).then((values) => { const data = values[0]; mv.parseApplication(data, true); - if (!_conf.is_php && values[1]) { + if (values[1]) { const appMeta = values[1][0]; if (appMeta?.versions) { config.versions = appMeta.versions; } } showStudio(); - if (!_conf.is_php) { - // don't execute this code with php backend - document.querySelector("#toolsbarStudio-delete").classList.remove("d-none"); - document.querySelector("#layerOptionBtn").classList.remove("d-none"); - } + document.querySelector("#toolsbarStudio-delete").classList.remove("d-none"); + document.querySelector("#layerOptionBtn").classList.remove("d-none"); }); }; @@ -1674,7 +1578,7 @@ $("#mod-importfile").on("shown.bs.modal", function () { var uploadSldFileToBackend = function (e) { var reader = new FileReader(); e.files[0].text().then(function (sldFile) { - const url = _conf.is_php ? _conf.php.store_style_service : _conf.store_style_service; + const url = _conf.store_style_service; $.ajax(url, { data: sldFile, method: "POST", diff --git a/js/wizard.js b/src/static/js/wizard.js similarity index 100% rename from js/wizard.js rename to src/static/js/wizard.js diff --git a/lib/Font-Awesome/all.css b/src/static/lib/Font-Awesome/all.css similarity index 100% rename from lib/Font-Awesome/all.css rename to src/static/lib/Font-Awesome/all.css diff --git a/lib/Font-Awesome/all.js b/src/static/lib/Font-Awesome/all.js similarity index 100% rename from lib/Font-Awesome/all.js rename to src/static/lib/Font-Awesome/all.js diff --git a/lib/Font-Awesome/icons.json b/src/static/lib/Font-Awesome/icons.json similarity index 100% rename from lib/Font-Awesome/icons.json rename to src/static/lib/Font-Awesome/icons.json diff --git a/lib/Sortable.min.js b/src/static/lib/Sortable.min.js similarity index 100% rename from lib/Sortable.min.js rename to src/static/lib/Sortable.min.js diff --git a/lib/bootstrap-table/bootstrap-table-fr-FR.min.js b/src/static/lib/bootstrap-table/bootstrap-table-fr-FR.min.js similarity index 100% rename from lib/bootstrap-table/bootstrap-table-fr-FR.min.js rename to src/static/lib/bootstrap-table/bootstrap-table-fr-FR.min.js diff --git a/lib/bootstrap-table/bootstrap-table.min.css b/src/static/lib/bootstrap-table/bootstrap-table.min.css similarity index 100% rename from lib/bootstrap-table/bootstrap-table.min.css rename to src/static/lib/bootstrap-table/bootstrap-table.min.css diff --git a/lib/bootstrap-table/bootstrap-table.min.js b/src/static/lib/bootstrap-table/bootstrap-table.min.js similarity index 100% rename from lib/bootstrap-table/bootstrap-table.min.js rename to src/static/lib/bootstrap-table/bootstrap-table.min.js diff --git a/lib/bootstrap/5.2/bootstrap.bundle.min.js b/src/static/lib/bootstrap/5.2/bootstrap.bundle.min.js similarity index 100% rename from lib/bootstrap/5.2/bootstrap.bundle.min.js rename to src/static/lib/bootstrap/5.2/bootstrap.bundle.min.js diff --git a/lib/bootstrap/5.2/bootstrap.min.css b/src/static/lib/bootstrap/5.2/bootstrap.min.css similarity index 100% rename from lib/bootstrap/5.2/bootstrap.min.css rename to src/static/lib/bootstrap/5.2/bootstrap.min.css diff --git a/lib/bootstrap5-tags/tags.min.js b/src/static/lib/bootstrap5-tags/tags.min.js similarity index 100% rename from lib/bootstrap5-tags/tags.min.js rename to src/static/lib/bootstrap5-tags/tags.min.js diff --git a/lib/i18njs/i18n.js b/src/static/lib/i18njs/i18n.js similarity index 100% rename from lib/i18njs/i18n.js rename to src/static/lib/i18njs/i18n.js diff --git a/lib/i18njs/i18n.min.js b/src/static/lib/i18njs/i18n.min.js similarity index 100% rename from lib/i18njs/i18n.min.js rename to src/static/lib/i18njs/i18n.min.js diff --git a/lib/icon-picker/icon-picker.css b/src/static/lib/icon-picker/icon-picker.css similarity index 100% rename from lib/icon-picker/icon-picker.css rename to src/static/lib/icon-picker/icon-picker.css diff --git a/lib/icon-picker/icon-picker.js b/src/static/lib/icon-picker/icon-picker.js similarity index 100% rename from lib/icon-picker/icon-picker.js rename to src/static/lib/icon-picker/icon-picker.js diff --git a/lib/icon-picker/iconPickerComponent.js b/src/static/lib/icon-picker/iconPickerComponent.js similarity index 100% rename from lib/icon-picker/iconPickerComponent.js rename to src/static/lib/icon-picker/iconPickerComponent.js diff --git a/lib/moment.js b/src/static/lib/moment.js similarity index 100% rename from lib/moment.js rename to src/static/lib/moment.js diff --git a/lib/mustache-2.3.0/mustache.min.js b/src/static/lib/mustache-2.3.0/mustache.min.js similarity index 100% rename from lib/mustache-2.3.0/mustache.min.js rename to src/static/lib/mustache-2.3.0/mustache.min.js diff --git a/lib/mv.js b/src/static/lib/mv.js similarity index 98% rename from lib/mv.js rename to src/static/lib/mv.js index 04cd4279..a7984440 100755 --- a/lib/mv.js +++ b/src/static/lib/mv.js @@ -321,12 +321,6 @@ var mv = (function () { $("#frm-bl").append(html); $("#frm-bl-visible").append(html2); $(".bl." + classe + " input").bind("change", function (e) { - var checkbox = $(e.currentTarget); - var allChecked = $(".bl." + classe + " input:checked"); - if (!checkbox.prop("checked") && allChecked.length === 0) { - checkbox.prop("checked", true); - return; - } var id = $(this).parent().parent().attr("data-layerid"); var value = $(e.currentTarget).prop("checked"); var select = $("#frm-bl-visible"); @@ -1628,11 +1622,6 @@ var mv = (function () { mv.manageDraftBadge(relation); - let onlineCard = document.getElementById("onlineCard"); - if (_conf.is_php && onlineCard) { - onlineCard.classList.add("d-none"); - } - newConfiguration({ id: app_identifier, isFile: true, @@ -1965,7 +1954,6 @@ var mv = (function () { return map1.title > map2.title ? 1 : -1; }) .forEach((app) => { - // allow to filter according to PHP or Python backend let previewUrl = ""; if (app.relation) { let filePath = `${mv.getAuthentUserInfos("groupSlugName")}/${app.relation}`; @@ -1976,7 +1964,7 @@ var mv = (function () { const navButtons = [ { - show: !_conf.is_php, + show: true, html: `