+
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/offlineWebComponent.ts b/geoportal/geoportailv3_geoportal/static-ngeo/js/offlineWebComponent.ts
deleted file mode 100644
index 530367963..000000000
--- a/geoportal/geoportailv3_geoportal/static-ngeo/js/offlineWebComponent.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-import i18next from 'i18next';
-import {LuxBaseElement} from './LuxBaseElement';
-import {html} from 'lit';
-import {customElement, state, property} from 'lit/decorators.js';
-
-@customElement('lux-offline')
-export class LuxOffline extends LuxBaseElement {
-
- @property({type: Boolean})
- disabled: boolean = false;
-
- @state()
- private server;
-
- @state()
- private menuDisplayed;
-
- @state()
- private tilePackages = {
- ALL: [],
- IN_PROGRESS: [],
- UPDATE_AVAILABLE: [],
- UP_TO_DATE: []
- };
-
- @state()
- private status;
-
- private checkTimeout;
-
- constructor() {
- super();
- const searchParams = new URLSearchParams(document.location.search);
- const server = searchParams.get('embeddedserver');
- const proto = searchParams.get('embeddedserverprotocol') || 'http';
- this.baseURL = (server ? `${proto}://${server}` : "http://localhost:8766/map/");
- if (server) {
- this.checkTiles();
- }
- this.server = server;
- }
-
- renderMenu() {
- return html`
-
-
- ${i18next.t('Update offline data')}
- ${this.status==="IN_PROGRESS"
- ? html ``
- : ''
- }
-
-
-
- ${i18next.t('Delete offline data')}
-
-
-
- `;
- }
-
- render() {
- return html`
-
-
-
-
-
- ${this.menuDisplayed?this.renderMenu():""}
- `;
- }
-
- toggleMenu() {
- this.menuDisplayed = !this.menuDisplayed;
- }
-
- checkTiles() {
- fetch(this.baseURL + "/check")
- .then((response) => response.json())
- .then((statusJson) => this.getStatus(statusJson))
- .catch((error) => {
- console.error('Error:', error);
- });
- }
-
- getStatus(tiles) {
- this.tilePackages = {
- ALL: [],
- IN_PROGRESS: [],
- UPDATE_AVAILABLE: [],
- UP_TO_DATE: []
- }
- for(const tileKey in tiles) {
- // skip package hillshade (too large for transfers)
- if (tileKey == "hillshade-lu") {
- continue;
- }
- this.tilePackages.ALL.push(tileKey);
- if (tiles[tileKey].status === "IN_PROGRESS") {
- this.tilePackages.IN_PROGRESS.push(tileKey);
- } else if ((tiles[tileKey].current < tiles[tileKey].available)
- || (!tiles[tileKey].current && tiles[tileKey].available)
- ) {
- this.tilePackages.UPDATE_AVAILABLE.push(tileKey);
- } else {
- this.tilePackages.UP_TO_DATE.push(tileKey);
- }
- }
- if (this.tilePackages.IN_PROGRESS.length > 0) {
- this.status = 'IN_PROGRESS';
- } else if (this.tilePackages.UPDATE_AVAILABLE.length > 0) {
- this.status = 'UPDATE_AVAILABLE';
- } else {
- this.status = 'UP_TO_DATE';
- }
- if (this.status == 'IN_PROGRESS') {
- this.reCheckTilesTimeout(2500);
- }
- }
-
- updateTiles() {
- this.tilePackages.UPDATE_AVAILABLE.forEach(tilePackage => {
- this.sendRequest(tilePackage, 'PUT');
- })
- }
-
- deleteTiles() {
- // keep resources, so that vector maps remain operational
- this.tilePackages.ALL.filter(tp => tp != 'resources').forEach(tilePackage => {
- this.sendRequest(tilePackage, 'DELETE');
- })
- }
-
- sendRequest(tiles: string, method: string) {
- fetch(this.baseURL + "/map/" + tiles, {method})
- .then((data) => {
- console.log('Success:', data);
- })
- .catch((error) => {
- console.error('Error:', error);
- })
- .finally(() => {this.reCheckTilesTimeout(250)});
- }
-
- reCheckTilesTimeout(timeout) {
- // prevent multiple timers
- if (this.checkTimeout !== undefined) {
- clearTimeout(this.checkTimeout);
- }
- this.checkTimeout = setTimeout(()=> {
- this.checkTiles();
- }, timeout)
- }
-
- createRenderRoot() {
- // no shadow dom
- return this;
- }
-}
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/less/icons.less b/geoportal/geoportailv3_geoportal/static-ngeo/less/icons.less
index d2c8ec72e..6f6096745 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/less/icons.less
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/less/icons.less
@@ -18,6 +18,16 @@
font-weight: normal;
font-style: normal;
}
+/* Font that inlcudes all lux icons from the other font files defined in this CSS
+** which will be used by the web components. To view or edit file use a tool like fontforge.
+** Icon codes are between "e000" and "e064".
+*/
+@font-face {
+ font-family: "geoportail-icons-wc";
+ src: url("../webfonts/geoportail-icons-wc.woff") format("woff");
+ font-weight: normal;
+ font-style: normal;
+}
@font-face {
font-family: 'apart-geoportail';
src: url('../webfonts/apart-geoportail.eot');
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/less/offline.less b/geoportal/geoportailv3_geoportal/static-ngeo/less/offline.less
index b3b59d410..6e2d238b2 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/less/offline.less
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/less/offline.less
@@ -1,3 +1,16 @@
+lux-offline-alert {
+ .offline-modal {
+ width: 300px;
+ }
+}
+
+lux-offline-reload {
+ .offline-modal {
+ width: 300px;
+ top: 100px;
+ }
+}
+
ngeo-offline, lux-offline {
div {
z-index: 1;
@@ -5,7 +18,7 @@ ngeo-offline, lux-offline {
.main-button, .db-button {
position: absolute;
right: 96px;
- bottom: 152px;
+ bottom: 151px;
cursor: pointer;
.no-data {
color: black;
@@ -14,27 +27,17 @@ ngeo-offline, lux-offline {
background-color: white;
text-align: center;
font-size: 2.7rem;
- font-family: FontAwesome;
- line-height: 1.5em;
color: #2980b9;
width: 41px;
height: 41px;
border: 1px solid #8394a0;
- &::after {
- content: @fa-var-arrow-circle-o-down;
- }
- }
- .offline-wc {
- &::after {
- content: @fa-var-database;
- }
}
.no-data[disabled], .with-data[disabled], .offline-wc[disabled] {
opacity: 0.65;
cursor: not-allowed;
}
.with-data {
- color: red;
+ color: red !important;
}
}
.db-button {right: 52px}
@@ -42,7 +45,7 @@ ngeo-offline, lux-offline {
&.offline-mode {
.main-button {
.no-data, .with-data{
- color: green;
+ color: green !important;
}
}
}
@@ -57,7 +60,6 @@ ngeo-offline, lux-offline {
}
.offline-btn {
- // width: 20rem;
margin: 5px;
i {
margin-left: 6px;
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.de.json b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.de.json
index 48f94ee55..242b3ff38 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.de.json
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.de.json
@@ -1,20 +1,23 @@
{
"(Deactivates zoom and pan on the profile!)": "",
"Altitude: ": "",
+ "An error occured during download": "",
+ "App reload needed: Offline data updated successfully": "",
+ "Check for offline data updates": "",
"Classes": "",
"Classification: ": "",
"Copy": "",
"custom": "",
+ "Delete offline data": "Offline Daten löschen",
"Distance: ": "",
"Draw a lidar profile": "",
"Draw a line on the map to dislay the corresponding LIDAR profile. Double clic to confirm.": "",
- "Delete offline data": "Offline Daten herunterladen",
"Embed map": "",
"Export CSV": "",
"Export PNG": "",
+ "Full offline (only available on mobile)": "",
"Intensity: ": "",
"It might be offline": "",
- "Full offline (only available on mobile)": "Full offline (nur mobile App)",
"large": "",
"Lidar profile service error": "",
"loaded": "",
@@ -22,10 +25,13 @@
"LOD: ": "",
"Measure distances on the profile below.": "",
"medium": "",
+ "New offline data available": "Neue Offlinedaten verfügbar",
"Or did you attempt to draw a profile outside data extent?": "",
"Or did you attempt to draw such a small profile that no point was returned?": "",
"Profile width: ": "",
+ "Restart app": "",
+ "Retry": "",
"small": "",
"Take measure": "",
- "Update offline data": "Offline Daten löschen"
+ "Update offline data": "Offline Daten herunterladen"
}
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.en.json b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.en.json
index e4def2cf1..09bab717c 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.en.json
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.en.json
@@ -1,20 +1,23 @@
{
"(Deactivates zoom and pan on the profile!)": "",
"Altitude: ": "",
+ "An error occured during download": "",
+ "App reload needed: Offline data updated successfully": "",
+ "Check for offline data updates": "",
"Classes": "",
"Classification: ": "",
"Copy": "",
"custom": "",
+ "Delete offline data": "",
"Distance: ": "",
"Draw a lidar profile": "",
"Draw a line on the map to dislay the corresponding LIDAR profile. Double clic to confirm.": "",
- "Delete offline data": "",
"Embed map": "",
"Export CSV": "",
"Export PNG": "",
+ "Full offline (only available on mobile)": "",
"Intensity: ": "",
"It might be offline": "",
- "Full offline (only available on mobile)": "",
"large": "",
"Lidar profile service error": "",
"loaded": "",
@@ -22,9 +25,12 @@
"LOD: ": "",
"Measure distances on the profile below.": "",
"medium": "",
+ "New offline data available": "",
"Or did you attempt to draw a profile outside data extent?": "",
"Or did you attempt to draw such a small profile that no point was returned?": "",
"Profile width: ": "",
+ "Restart app": "",
+ "Retry": "",
"small": "",
"Take measure": "",
"Update offline data": ""
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.fr.json b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.fr.json
index cdc3fc292..b2fdd2d5b 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.fr.json
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.fr.json
@@ -1,20 +1,23 @@
{
"(Deactivates zoom and pan on the profile!)": "(Désactive le zoom et le pan sur le profil !)",
"Altitude: ": "",
+ "An error occured during download": "Une erreur s'est produite lors du téléchargement",
+ "App reload needed: Offline data updated successfully": "Rechargement de l'application nécessaire : données hors connexion mises à jour avec succès",
+ "Check for offline data updates": "Vérifier les mises à jour des données hors ligne",
"Classes": "Classes",
"Classification: ": "",
"Copy": "Copier",
"custom": "Taille personnalisée",
+ "Delete offline data": "Supprimer données hors connexion",
"Distance: ": "",
"Draw a lidar profile": "Dessiner un profil lidar",
"Draw a line on the map to dislay the corresponding LIDAR profile. Double clic to confirm.": "Dessiner une ligne sur la carte pour afficher le profil LIDAR correspondant. Utilisez un double-clic pour terminer le profil.",
- "Delete offline data": "Supprimer données hors connexion",
"Embed map": "Intégrer la carte",
"Export CSV": "",
"Export PNG": "",
+ "Full offline (only available on mobile)": "",
"Intensity: ": "",
"It might be offline": "",
- "Full offline (only available on mobile)": "Full offline (seulement mobile)",
"large": "Grande",
"Lidar profile service error": "",
"loaded": "",
@@ -22,10 +25,13 @@
"LOD: ": "",
"Measure distances on the profile below.": "Mesurer des distances sur le profil ci-dessous",
"medium": "Moyenne",
+ "New offline data available": "Mise à jour des données hors connexion disponible",
"Or did you attempt to draw a profile outside data extent?": "",
"Or did you attempt to draw such a small profile that no point was returned?": "",
"Profile width: ": "",
- "Take measure": "Mesurer",
+ "Restart app": "Redémarrer l'application",
+ "Retry": "Recommencez",
"small": "Petite",
+ "Take measure": "Mesurer",
"Update offline data": "Mettre à jour données hors connexion"
}
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.lb.json b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.lb.json
index e4def2cf1..09bab717c 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.lb.json
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/locales/app.lb.json
@@ -1,20 +1,23 @@
{
"(Deactivates zoom and pan on the profile!)": "",
"Altitude: ": "",
+ "An error occured during download": "",
+ "App reload needed: Offline data updated successfully": "",
+ "Check for offline data updates": "",
"Classes": "",
"Classification: ": "",
"Copy": "",
"custom": "",
+ "Delete offline data": "",
"Distance: ": "",
"Draw a lidar profile": "",
"Draw a line on the map to dislay the corresponding LIDAR profile. Double clic to confirm.": "",
- "Delete offline data": "",
"Embed map": "",
"Export CSV": "",
"Export PNG": "",
+ "Full offline (only available on mobile)": "",
"Intensity: ": "",
"It might be offline": "",
- "Full offline (only available on mobile)": "",
"large": "",
"Lidar profile service error": "",
"loaded": "",
@@ -22,9 +25,12 @@
"LOD: ": "",
"Measure distances on the profile below.": "",
"medium": "",
+ "New offline data available": "",
"Or did you attempt to draw a profile outside data extent?": "",
"Or did you attempt to draw such a small profile that no point was returned?": "",
"Profile width: ": "",
+ "Restart app": "",
+ "Retry": "",
"small": "",
"Take measure": "",
"Update offline data": ""
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/src/offline/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/src/offline/component.js
index 5057f6b7d..fb13e6491 100644
--- a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/src/offline/component.js
+++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/src/offline/component.js
@@ -102,7 +102,7 @@ exports.Controller = class {
* @ngdoc controller
* @ngname ngeoOfflineController
*/
- constructor($timeout, ngeoFeatureOverlayMgr, ngeoOfflineServiceManager, ngeoOfflineConfiguration, ngeoOfflineMode, ngeoNetworkStatus) {
+ constructor($timeout, ngeoFeatureOverlayMgr, ngeoOfflineServiceManager, ngeoOfflineConfiguration, ngeoOfflineMode, ngeoNetworkStatus, appOfflineBar) {
/**
* @type {angular.$timeout}
@@ -133,6 +133,8 @@ exports.Controller = class {
*/
this.offlineMode = ngeoOfflineMode;
+ this.offlineBar = appOfflineBar;
+
/**
* @type {ngeo.offline.NetworkStatus}
* @export
@@ -329,6 +331,7 @@ exports.Controller = class {
toggleViewExtentSelection(finished) {
this.menuDisplayed = false;
this.selectingExtent = !this.selectingExtent;
+ this.offlineBar.toggleNgeoOffline();
this.map.removeLayer(this.maskLayer_);
this.removeZoomConstraints_();
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/webfonts/geoportail-icons-wc.woff b/geoportal/geoportailv3_geoportal/static-ngeo/webfonts/geoportail-icons-wc.woff
new file mode 100644
index 000000000..e1e397f3d
Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/webfonts/geoportail-icons-wc.woff differ
diff --git a/geoportal/package.json b/geoportal/package.json
index 7b3b4624e..ddf0bdaf4 100644
--- a/geoportal/package.json
+++ b/geoportal/package.json
@@ -108,6 +108,7 @@
"proj4": "2.4.4",
"raven-js": "3.24.2",
"save-csv": "^4.1.0",
+ "rxjs": "7.5.6",
"source-map-loader": "0.2.4",
"svg2ttf": "4.1.0",
"ttf2eot": "2.0.0",
diff --git a/tile_server/README.md b/tile_server/README.md
new file mode 100644
index 000000000..43acf9685
--- /dev/null
+++ b/tile_server/README.md
@@ -0,0 +1,13 @@
+This basic server can be used to test the offline functionality of the mobile app.
+
+To run the mobile app on a desktop launch the test server with:
+
+```
+python3 server.py
+```
+
+This opens the server on localhost port 8000
+
+Then go to the mobile app dev home page:
+
+http://localhost:8080/dev/main.html/theme/main?embeddedserver=localhost%3A8000&embeddedserverprotocol=http
diff --git a/tile_server/server.py b/tile_server/server.py
new file mode 100644
index 000000000..15b13a6e1
--- /dev/null
+++ b/tile_server/server.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3
+
+from http.server import HTTPServer, BaseHTTPRequestHandler
+import json
+
+
+RES_NAMES = ["contours-lu", "hillshade-lu", "omt-geoportail-lu",
+ "omt-topo-geoportail-lu", "resources", "fonts", "sprites"]
+MAX_STATUS = 5
+OLD_VER = "0.1.0"
+NEW_VER = "0.5.2"
+
+
+class UpdateHandler(BaseHTTPRequestHandler):
+ dl_status = {res: 0 for res in RES_NAMES}
+ res_ver = {res: OLD_VER
+ for res in RES_NAMES}
+
+ @staticmethod
+ def get_status_string(dl_status):
+ if dl_status == 0:
+ return "UNKNOWN"
+ elif dl_status < MAX_STATUS:
+ return "IN_PROGRESS"
+ else:
+ return "DONE"
+
+ def do_GET(self):
+ if self.path == "/check":
+ self.send_response(200, "OK")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ resp = {
+ res: {
+ "status": self.get_status_string(self.dl_status[res]),
+ "filesize": 5000 * self.dl_status[res],
+ "current": self.res_ver[res],
+ "available": NEW_VER
+ } for res in RES_NAMES
+ }
+ # self.wfile.write("bla")
+ self.wfile.write(json.dumps(resp).encode())
+ else:
+ # import pdb;pdb.set_trace()
+ self.send_response(400, "bla")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ self.wfile.write(b"Test\n")
+
+ for res in RES_NAMES:
+ if 0 < self.dl_status[res] < MAX_STATUS:
+ self.dl_status[res] += 1
+ if self.dl_status[res] >= MAX_STATUS:
+ self.res_ver[res] = NEW_VER
+
+ def do_PUT(self):
+ res = self.path.replace("/map/", "")
+ if res in RES_NAMES:
+ self.dl_status[res] = 1
+
+ self.send_response(202, "ACCEPTED")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ self.wfile.write(f"Update started for {res}\n".encode())
+
+ else:
+ self.send_response(404, "NOT FOUND")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ self.wfile.write(f"Resource {res} not found.\n".encode())
+
+ def do_DELETE(self):
+ res = self.path.replace("/map/", "")
+ if res in RES_NAMES:
+ self.dl_status[res] = 0
+ self.res_ver[res] = OLD_VER
+
+ self.send_response(202, "ACCEPTED")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ self.wfile.write(f"Deleted {res}\n".encode())
+
+ else:
+ self.send_response(404, "NOT FOUND")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.end_headers()
+ self.wfile.write(f"Resource {res} not found.\n".encode())
+
+ def do_OPTIONS(self):
+ self.send_response(200, "OK")
+ self.send_header("Access-Control-Allow-Origin", "*")
+ self.send_header("Access-Control-Allow-Methods", "PUT, DELETE")
+ self.end_headers()
+
+
+server_address = ('', 8000)
+httpd = HTTPServer(server_address, UpdateHandler)
+httpd.serve_forever()