Skip to content

Commit

Permalink
Merge pull request #4348 from camptocamp/port_offline_feature
Browse files Browse the repository at this point in the history
Port offline feature
  • Loading branch information
llienher committed May 21, 2019
2 parents 32f7a92 + c19561f commit 4c27b6c
Show file tree
Hide file tree
Showing 25 changed files with 2,602 additions and 13 deletions.
1 change: 1 addition & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ globals:
google: false
Bloodhound: false
DateFormatter: false
localforage: false
13 changes: 7 additions & 6 deletions contribs/gmf/src/less/base.less
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,21 @@ i, cite, em, var, address, dfn {
line-height: 1;
}

.ui-draggable {
.ui-draggable-handle {
cursor: grab;
cursor: -webkit-grab;
cursor:-moz-grab;
}

&.ui-draggable-dragging {
.ui-draggable-dragging {
.ui-draggable-handle {
cursor: move;
}

iframe {
display: none;
}
iframe {
display: none;
}
}

.ui-resizable {
&.ui-resizable-resizing {
iframe {
Expand Down
21 changes: 21 additions & 0 deletions examples/offline.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html ng-app='app'>
<head>
<title>Offline example</title>
<meta charset="utf-8">
<meta name="viewport"
content="initial-scale=1.0, user-scalable=no, width=device-width">
<meta name="mobile-web-app-capable" content="yes">
<script src="https://cdnjs.cloudflare.com/ajax/libs/localforage/1.7.3/localforage.min.js"></script>
</head>
<body ng-controller="MainController as ctrl" ng-class="{offline: ctrl.ngeoNetworkStatus.isDisconnected()}">
<div class="offline-msg alert-danger" translate>You are currently offline.</div>
<div id="map" ngeo-map="ctrl.map">
<ngeo-offline
ngeo-offline-map="ctrl.map"
ngeo-offline-extentsize="ctrl.offlineExtentSize">
</ngeo-offline>
</div>
<p id="desc">This example shows how to use the <code><a href="../apidoc/ngeo.offline.component.html" title="Read our documentation">ngeo-offline</a></code> component.</p>
</body>
</html>
87 changes: 87 additions & 0 deletions examples/offline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* @module app.offline
*/
const exports = {};

import './offline.less';
import './common_dependencies.js';
import olMap from 'ol/Map.js';

import olView from 'ol/View.js';
import olLayerTile from 'ol/layer/Tile.js';
import olSourceOSM from 'ol/source/OSM.js';
import ngeoMapModule from 'ngeo/map/module.js';
import ngeoOfflineModule from 'ngeo/offline/module.js';
import ngeoOfflineConfiguration from 'ngeo/offline/Configuration.js';
import NgeoOfflineServiceManager from 'ngeo/offline/ServiceManager.js';


// Useful to work on example - remove me later
import 'bootstrap/js/modal.js';
import 'jquery-ui/ui/widgets/resizable.js';
import 'jquery-ui/ui/widgets/draggable.js';

/** @type {!angular.Module} **/
exports.module = angular.module('app', [
'gettext',
ngeoMapModule.name,
ngeoOfflineModule.name,
NgeoOfflineServiceManager.module.name,
]);

exports.module.value('ngeoOfflineTestUrl', '../../src/offline/component.html');

// Define the offline download configuration service
ngeoOfflineModule.service('ngeoOfflineConfiguration', ngeoOfflineConfiguration);

class MainController {

/**
* @param {ngeoFeatureOverlayMgr} ngeoFeatureOverlayMgr ngeo feature overlay manager service.
* @param {ngeoNetworkStatus} ngeoNetworkStatus ngeo network status service.
* @param {NgeoOfflineServiceManager} ngeoOfflineServiceManager ngeo offline service.
* @ngInject
*/
constructor(ngeoFeatureOverlayMgr, ngeoNetworkStatus, ngeoOfflineServiceManager) {

/**
* Save a square of 10 km sideways (Map's unit is the meter).
* @type {number}
* @export
*/
this.offlineExtentSize = 10000;

/**
* @type {ngeoNetworkStatus}
* @export
*/
this.ngeoNetworkStatus = ngeoNetworkStatus;

/**
* @type {ol.Map}
* @export
*/
this.map = new olMap({
layers: [
new olLayerTile({
source: new olSourceOSM()
})
],
view: new olView({
center: [352379, 5172733],
zoom: 4
})
});

ngeoFeatureOverlayMgr.init(this.map);

ngeoOfflineServiceManager.setSaveService('offlineDownloader');
ngeoOfflineServiceManager.setRestoreService('ngeoOfflineRestorer');
}
}


exports.module.controller('MainController', MainController);


export default exports;
74 changes: 74 additions & 0 deletions examples/offline.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
@import "~bootstrap/dist/css/bootstrap.css";
@import "~font-awesome/less/font-awesome.less";

#map {
width: 600px;
height: 400px;
position: relative;
}

ngeo-offline {
div {
z-index: 1;
}
.main-button {
position: absolute;
right: 1rem;
bottom: 5rem;
cursor: pointer;
.no-data {
color: black;
}
.with-data {
color: red;
}
.no-data, .with-data {
background-color: white;
text-align: center;
font-size: 2.5rem;
line-height: 2rem;
border-radius: 2rem;
font-family: FontAwesome;
&::after {
content: @fa-var-arrow-circle-o-down;
}
}
}

.validate-extent {
position: absolute;
bottom: 0.5rem;
width: 10rem;
left: calc(~"50% - 5rem");
}

.in-progress {
position: absolute;
left: calc(~"50% - 3.3rem");
top: calc(~"50% - 3rem");
color: white;
font-weight: bold;
background-color: #337ab7;
padding: 2rem 2rem;
border-radius: 1rem;
}

.modal-content {
width: 30rem;
}

.modal-body {
button {
display: block;
margin: 0.5rem auto;
width: 25rem;
}
}
}

.offline-msg {
display: none;
}
.offline .offline-msg {
display: block;
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,7 @@
"webpack-dev-server": "3.1.4",
"webpack-merge": "4.1.2"
},
"dependencies": {}
"dependencies": {
"localforage": "^1.7.3"
}
}
10 changes: 6 additions & 4 deletions src/message/modalComponent.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* @module ngeo.message.modalComponent
*/
import 'jquery';
import 'jquery-ui';
import 'jquery-ui/ui/widgets/draggable.js';
import 'bootstrap/js/modal.js';
import googAsserts from 'goog/asserts.js';
Expand Down Expand Up @@ -110,9 +112,7 @@ exports.Controller_ = class {
this.ngModel;
}

$onInit() {
this.closable = this.closable !== false;

$postLink() {
this.modal_ = this.$element_.children();

if (!this.closable) {
Expand All @@ -123,7 +123,9 @@ exports.Controller_ = class {
this.resizable = !!this.resizable;

const dialog = this.modal_.find('.modal-dialog');
dialog.draggable();
dialog.draggable({
'handle': '.modal-header'
});
if (this.resizable) {
dialog.resizable();
}
Expand Down
108 changes: 108 additions & 0 deletions src/offline/AbstractLocalforageWrapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @module ngeo.offline.AbstractLocalforageWrapper
*/
/**
* @typedef {{
* id: number,
* plugin: string,
* command: string,
* args: !Array<*>,
* context: (*|undefined)
* }}
*/
// eslint-disable-next-line no-unused-vars
let Action;

/**
* @abstract
*/
const exports = class AbstractLocalforageWrapper {
constructor() {
this.waitingPromises_ = new window.Map();
this.currentId_ = 0;
}

setItem(...args) {
return this.createAction('setItem', ...args);
}

getItem(...args) {
return this.createAction('getItem', ...args);
}

clear() {
return this.createAction('clear');
}

config(...args) {
return this.createAction('config', ...args);
}

/**
* @export
* @param {string} command .
* @param {...*} args .
* @return {Promise} .
*/
createAction(command, ...args) {
const id = ++this.currentId_;
/**
* @type {Action}
*/
const action = {
'plugin': 'localforage',
'command': command,
'args': args,
'id': id
};
const waitingPromise = {};
const promise = new Promise((resolve, reject) => {
waitingPromise['resolve'] = resolve;
waitingPromise['reject'] = reject;
});
this.waitingPromises_.set(id, waitingPromise);
this.postToBackend(action);
return promise;
}

/**
* @export
* @param {*} event .
*/
receiveMessage(event) {
/**
* @type {Action}
*/
const action = event['data'];
const id = action['id'];
const command = action['command'];
const args = action['args'] || [];
const context = action['context'];
const msg = action['msg'];

const waitingPromise = this.waitingPromises_.get(id);
if (command === 'error') {
console.error(msg, args, context);
if (waitingPromise) {
waitingPromise.reject(args, context);
this.waitingPromises_.delete(id);
}
} else if (command === 'response') {
waitingPromise.resolve(...args);
this.waitingPromises_.delete(id);
} else {
console.error('Unhandled command', JSON.stringify(action, null, '\t'));
}
}

/**
* @abstract
* @protected
* @param {Action} action .
*/
postToBackend(action) {
}
};


export default exports;

0 comments on commit 4c27b6c

Please sign in to comment.