Replace index page by a map where you can optionally start a pad

pull/54/merge
Candid Dauth 2016-10-11 18:09:01 +03:00
rodzic 7b97b59e00
commit 54657ef048
15 zmienionych plików z 252 dodań i 147 usunięć

Wyświetl plik

@ -1,3 +1,6 @@
RewriteEngine on RewriteEngine on
RewriteRule ^$ build/index.html
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.+$ build/index.html RewriteRule ^.+$ build/index.html

Wyświetl plik

@ -29,7 +29,6 @@ var FacilPad = {
}); });
fp.app.run([ "$rootScope", "fpUtils", function($rootScope, fpUtils) { fp.app.run([ "$rootScope", "fpUtils", function($rootScope, fpUtils) {
$rootScope.padId = location.pathname.match(/[^\/]*$/)[0];
$rootScope.urlPrefix = location.protocol + "//" + location.host + location.pathname.replace(/[^\/]*$/, ""); $rootScope.urlPrefix = location.protocol + "//" + location.host + location.pathname.replace(/[^\/]*$/, "");
$rootScope.round = fpUtils.round; $rootScope.round = fpUtils.round;
@ -79,14 +78,19 @@ var FacilPad = {
}; };
fp.app.controller("PadCtrl", function($scope, fpMap, $timeout) { fp.app.controller("PadCtrl", function($scope, fpMap, $timeout) {
$scope.padId = location.pathname.match(/[^\/]*$/)[0];
$timeout(function() { $timeout(function() {
var map = fpMap.getMap("map"); var map = fpMap.getMap("map");
if(map.socket.padData)
$scope.padName = map.socket.padData.name;
map.socket.$watch("padData.name", function(newVal) { map.socket.$watch("padData.name", function(newVal) {
$scope.padName = newVal; $scope.padName = newVal;
}); });
map.socket.$watch("padId", function(padId) {
if(padId)
history.replaceState(null, "", $scope.urlPrefix + padId);
});
}, 0); }, 0);
}); });

Wyświetl plik

@ -4,7 +4,7 @@
<img src="spinner.gif" alt="Loading…"> <img src="spinner.gif" alt="Loading…">
</div> </div>
</div> </div>
<div class="fp-map-disabled-cover" ng-show="!loaded || disconnected"></div> <div class="fp-map-disabled-cover" ng-show="disconnected || serverError"></div>
<div class="fp-map-loading" ng-hide="loaded"> <div class="fp-map-loading" ng-hide="loaded || serverError">
Loading... Loading...
</div> </div>

Wyświetl plik

@ -19,20 +19,18 @@
}; };
ret.initMap = function(el, id, padId) { ret.initMap = function(el, id, padId) {
return maps[id] = new Map(el, id, padId); return maps[id] = new Map(el, padId);
}; };
return ret; return ret;
function Map(el, id, padId) { function Map(el, padId) {
var map = this; var map = this;
map.el = el; map.el = el;
map.mapEvents = $rootScope.$new(true); /* Event types: click, layerchange */ map.mapEvents = $rootScope.$new(true); /* Event types: click, layerchange */
map.socket = fpSocket(padId); map.socket = fpSocket(padId);
//map.socket.id = id; // To be in scope for template
map.layers = { }; map.layers = { };
[ [
L.tileLayer("http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", { L.tileLayer("http://korona.geog.uni-heidelberg.de/tiles/roads/x={x}&y={y}&z={z}", {
@ -91,9 +89,12 @@
direction: "right" direction: "right"
}; };
var scope = map.socket.$new();
scope.loaded = false;
var tpl = $($templateCache.get("map/map/map.html")); var tpl = $($templateCache.get("map/map/map.html"));
el.append(tpl); el.append(tpl);
$compile(tpl)(map.socket); $compile(tpl)(scope);
map.map = L.map(el.find(".fp-map")[0]); map.map = L.map(el.find(".fp-map")[0]);
@ -268,18 +269,22 @@
fpMapLegend(map); fpMapLegend(map);
var loadedWatcher = map.socket.$watch("loaded", function(loaded) { if(padId) {
if(loaded) { var loadedWatcher = map.socket.$watch("padData", function(padData) {
setTimeout(function() { if(padData != null) {
map.displayView(map.socket.padData.defaultView); loadedWatcher();
}, 0); map.displayView(padData.defaultView);
loadedWatcher(); scope.loaded = true;
} }
}); });
} else {
map.displayView();
scope.loaded = true;
}
var errorMessage = null; var errorMessage = null;
map.socket.$watch("disconnected", function(disconnected) { map.socket.$watch("disconnected", function(disconnected) {
if(disconnected && !errorMessage) if(disconnected && !errorMessage && !map.socket.serverError)
errorMessage = map.messages.showMessage("danger", "The connection to the server was lost."); errorMessage = map.messages.showMessage("danger", "The connection to the server was lost.");
else if(!disconnected && errorMessage) { else if(!disconnected && errorMessage) {
errorMessage.close(); errorMessage.close();
@ -287,8 +292,16 @@
} }
}); });
map.socket.$watch("serverError", function(serverError) {
if(serverError) {
errorMessage && errorMessage.close();
map.messages.showMessage("danger", serverError);
}
});
map.map.on("moveend", function() { map.map.on("moveend", function() {
map.socket.updateBbox(fpUtils.leafletToFpBbox(map.map.getBounds(), map.map.getZoom())); if(map.socket.padId)
map.socket.updateBbox(fpUtils.leafletToFpBbox(map.map.getBounds(), map.map.getZoom()));
}); });
} }
}); });

Wyświetl plik

@ -1,28 +1,38 @@
<div class="modal-header"> <div class="modal-header">
<button class="close" ng-click="$dismiss()"><span aria-hidden="true">&times;</span></button> <button class="close" ng-click="$dismiss()"><span aria-hidden="true">&times;</span></button>
<h3 class="modal-title">Pad settings</h3> <h3 class="modal-title">{{create ? 'Start collaborative map' : 'Pad settings'}}</h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal"> <form class="form-horizontal">
<div uib-alert class="alert-danger" ng-show="error">{{error}}</div> <div uib-alert class="alert-danger" ng-show="error">{{error}}</div>
<div class="form-group"> <div class="form-group">
<label for="pad-link-input" class="col-sm-3 control-label">Link</label> <label for="pad-link-input" class="col-sm-3 control-label">Edit-only Link</label>
<div class="col-sm-9"><input id="pad-link-input" value="{{urlPrefix}}{{padId}}" class="form-control" readonly /></div> <div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon">{{urlPrefix}}</span>
<input id="pad-link-input" ng-model="writeId" class="form-control" />
</div>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="pad-rolink-input" class="col-sm-3 control-label">Read-only link</label> <label for="pad-rolink-input" class="col-sm-3 control-label">Read-only link</label>
<div class="col-sm-9"><input id="pad-rolink-input" value="{{urlPrefix}}{{padData.id}}" class="form-control" readonly /></div> <div class="col-sm-9">
<div class="input-group">
<span class="input-group-addon">{{urlPrefix}}</span>
<input id="pad-rolink-input" ng-model="readId" class="form-control" />
</div>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="pad-name-input" class="col-sm-3 control-label">Pad name</label> <label for="pad-name-input" class="col-sm-3 control-label">Pad name</label>
<div class="col-sm-9"><input id="pad-name-input" ng-model="padData.name" class="form-control" /></div> <div class="col-sm-9"><input id="pad-name-input" ng-model="padName" class="form-control" /></div>
</div> </div>
</form> </form>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="$dismiss()">Cancel</button> <button type="button" class="btn btn-default" ng-click="$dismiss()">Cancel</button>
<button type="button" class="btn btn-primary" ng-click="save()">Save</button> <button type="button" class="btn btn-primary" ng-click="save()">{{create ? 'Create' : 'Save'}}</button>
</div> </div>

Wyświetl plik

@ -3,22 +3,29 @@
fp.app.factory("fpMapPad", function($uibModal, fpUtils) { fp.app.factory("fpMapPad", function($uibModal, fpUtils) {
return function(map) { return function(map) {
var ret = { var ret = {
editPadSettings : function() { createPad : function() {
ret.editPadSettings(true);
},
editPadSettings : function(create) {
var dialog = $uibModal.open({ var dialog = $uibModal.open({
templateUrl: "map/pad/pad-settings.html", templateUrl: "map/pad/pad-settings.html",
scope: map.socket, scope: map.socket,
controller: "fpMapPadSettingsCtrl", controller: "fpMapPadSettingsCtrl",
size: "lg", size: "lg",
resolve: { resolve: {
map: function() { return map; } map: function() { return map; },
create: function() { return create; }
} }
}); });
var preserve = fpUtils.preserveObject(map.socket, "padData", "padData", function() { if(!create) {
dialog.dismiss(); // TODO: use child scope!
}); var preserve = fpUtils.preserveObject(map.socket, "padData", "padData", function() {
dialog.dismiss();
});
dialog.result.then(preserve.leave.bind(preserve), preserve.revert.bind(preserve)); dialog.result.then(preserve.leave.bind(preserve), preserve.revert.bind(preserve));
}
} }
}; };
@ -43,16 +50,43 @@
}; };
}); });
fp.app.controller("fpMapPadSettingsCtrl", function($scope, map) { fp.app.controller("fpMapPadSettingsCtrl", function($scope, map, create, fpUtils) {
$scope.save = function() { $scope.create = create;
var padData = $.extend({ }, map.socket.padData);
delete padData.defaultView;
map.socket.emit("editPad", padData, function(err) {
if(err)
return $scope.error = err;
$scope.$close(); if(create) {
}); $scope.writeId = fpUtils.generateRandomPadId(14);
$scope.readId = fpUtils.generateRandomPadId(12);
$scope.padName = "New FacilPad";
} else {
$scope.writeId = map.socket.padData.writeId;
$scope.readId = map.socket.padData.id;
$scope.padName = map.socket.padData.name;
}
$scope.save = function() {
var newData = {
name: $scope.padName,
id: $scope.readId,
writeId: $scope.writeId
};
if(create) {
map.socket.emit("createPad", newData, function(err) {
if(err)
return $scope.error = err;
map.socket.updateBbox(fpUtils.leafletToFpBbox(map.map.getBounds(), map.map.getZoom()));
$scope.$close();
});
} else {
map.socket.emit("editPad", newData, function(err) {
if(err)
return $scope.error = err;
$scope.$close();
});
}
}; };
}); });

Wyświetl plik

@ -3,7 +3,10 @@
<nav class="navbar navbar-default" ng-class="{'hidden-xs': !showXs}"> <nav class="navbar navbar-default" ng-class="{'hidden-xs': !showXs}">
<div class="container-fluid" id="fp-toolbox-content"> <div class="container-fluid" id="fp-toolbox-content">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li role="presentation" uib-dropdown ng-if="!readonly"> <li role="presentation" ng-if="!padId">
<a href="javascript:" ng-click="startPad()">Start collaborative map</a>
</li>
<li role="presentation" uib-dropdown ng-if="!readonly && padId">
<a href="javascript:" id="toolbox-add-dropdown" uib-dropdown-toggle role="button">Add <span class="caret"></span></a> <a href="javascript:" id="toolbox-add-dropdown" uib-dropdown-toggle role="button">Add <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelledby="toolbox-add-dropdown"> <ul uib-dropdown-menu aria-labelledby="toolbox-add-dropdown">
<li ng-repeat="type in types"><a href="javascript:" ng-click="addObject(type)">{{type.name}}</a></li> <li ng-repeat="type in types"><a href="javascript:" ng-click="addObject(type)">{{type.name}}</a></li>
@ -11,7 +14,7 @@
<li><a href="javascript:" ng-click="editObjectTypes()">Manage types</a></li> <li><a href="javascript:" ng-click="editObjectTypes()">Manage types</a></li>
</ul> </ul>
</li> </li>
<li role="presentation" uib-dropdown> <li role="presentation" uib-dropdown ng-if="padId">
<a href="javascript:" id="toolbox-views-dropdown" uib-dropdown-toggle role="button">Saved views <span class="caret"></span></a> <a href="javascript:" id="toolbox-views-dropdown" uib-dropdown-toggle role="button">Saved views <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelledby="toolbox-views-dropdown"> <ul uib-dropdown-menu aria-labelledby="toolbox-views-dropdown">
<li ng-repeat="(id, view) in views"><a href="javascript:" ng-click="displayView(view)">{{view.name}}</a></li> <li ng-repeat="(id, view) in views"><a href="javascript:" ng-click="displayView(view)">{{view.name}}</a></li>
@ -36,9 +39,9 @@
<ul uib-dropdown-menu aria-labelledby="toolbox-layers-dropdown" class="dropdown-menu-right"> <ul uib-dropdown-menu aria-labelledby="toolbox-layers-dropdown" class="dropdown-menu-right">
<!--<li ng-if="!readonly"><a href="javascript:" ng-click="openDialog('copy-pad-dialog')">Copy pad</a></li>--> <!--<li ng-if="!readonly"><a href="javascript:" ng-click="openDialog('copy-pad-dialog')">Copy pad</a></li>-->
<!--<li><a href="javascript:" ng-click="importFile()">Import File</a></li>--> <!--<li><a href="javascript:" ng-click="importFile()">Import File</a></li>-->
<li><a href="javascript:" ng-click="exportGpx()">Export GPX</a></li> <li ng-if="padId"><a href="javascript:" ng-click="exportGpx()">Export GPX</a></li>
<li><a href="javascript:" ng-click="showTable()">View as table</a></li> <li ng-if="padId"><a href="javascript:" ng-click="showTable()">View as table</a></li>
<li ng-if="!readonly"><a href="javascript:" ng-click="editPadSettings()">Settings</a></li> <li ng-if="!readonly && padId"><a href="javascript:" ng-click="editPadSettings()">Settings</a></li>
<li><a href="javascript:" ng-click="showAbout()">About FacilPad</a></li> <li><a href="javascript:" ng-click="showAbout()">About FacilPad</a></li>
</ul> </ul>
</li> </li>

Wyświetl plik

@ -43,6 +43,10 @@
map.aboutUi.showAbout(); map.aboutUi.showAbout();
}; };
scope.startPad = function() {
map.padUi.createPad();
};
var ret = { var ret = {
div: $($templateCache.get("map/toolbox/toolbox.html")) div: $($templateCache.get("map/toolbox/toolbox.html"))
}; };

Wyświetl plik

@ -5,7 +5,6 @@
return function(padId) { return function(padId) {
var scope = $rootScope.$new(); var scope = $rootScope.$new();
scope.padId = padId;
scope.padData = null; scope.padData = null;
scope.readonly = null; scope.readonly = null;
scope.markers = { }; scope.markers = { };
@ -41,16 +40,21 @@
return socket.emit.apply(socket, arguments); return socket.emit.apply(socket, arguments);
}; };
scope.on("serverError", function(data) {
scope.serverError = data;
});
scope.on("padData", function(data) { scope.on("padData", function(data) {
scope.padData = data; scope.padData = data;
if(data.writable != null) if(data.writable != null)
scope.readonly = !data.writable; scope.readonly = !data.writable;
scope.disconnected = false; var id = scope.readonly ? data.id : data.writeId;
if(id != null)
scope.padId = id;
if(!scope.loaded) scope.disconnected = false;
scope.loaded = true;
}); });
scope.on("marker", function(data) { scope.on("marker", function(data) {
@ -128,17 +132,31 @@
}); });
scope.on("reconnect", function() { scope.on("reconnect", function() {
scope.emit("setPadId", scope.padId); if(scope.padId)
scope.emit("updateBbox", scope.bbox); scope.emit("setPadId", scope.padId);
else
scope.disconnected = false; // Otherwise it gets set when padData arrives
if(scope.bbox)
scope.emit("updateBbox", scope.bbox);
}); });
scope.setPadId = function(padId) {
if(scope.padId != null)
return;
scope.padId = padId;
scope.emit("setPadId", padId);
};
scope.updateBbox = function(bbox) { scope.updateBbox = function(bbox) {
scope.emit("updateBbox", bbox); scope.emit("updateBbox", bbox);
scope.bbox = bbox; scope.bbox = bbox;
}; };
scope.emit("setPadId", scope.padId); if(padId)
scope.setPadId(padId);
scope.$on("$destroy", function() { scope.$on("$destroy", function() {
socket.removeAllListeners(); socket.removeAllListeners();

Wyświetl plik

@ -7,9 +7,12 @@
var LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; var LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var LENGTH = 12; var LENGTH = 12;
fpUtils.generateRandomPadId = function() { fpUtils.generateRandomPadId = function(length) {
if(length == null)
length = LENGTH;
var randomPadId = ""; var randomPadId = "";
for(var i=0; i<LENGTH; i++) { for(var i=0; i<length; i++) {
randomPadId += LETTERS[Math.floor(Math.random() * LETTERS.length)]; randomPadId += LETTERS[Math.floor(Math.random() * LETTERS.length)];
} }
return randomPadId; return randomPadId;

Wyświetl plik

@ -2,7 +2,7 @@
<html ng-controller="PadCtrl"> <html ng-controller="PadCtrl">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title fp-title="padName + ' – FacilPad'">FacilPad</title> <title fp-title="padName ? padName + ' – FacilPad' : 'FacilPad'">FacilPad</title>
<meta name="robots" content="index,nofollow" /> <meta name="robots" content="index,nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="shortcut icon" href="assets/img/favicon.png"> <link rel="shortcut icon" href="assets/img/favicon.png">
@ -20,61 +20,17 @@
</style> </style>
</head> </head>
<body> <body>
<div id="introContainer"> <noscript><p><strong>FacilPad requires JavaScript to work.</strong></p></noscript>
<h1>FacilPad</h1> <div id="loading" ng-if="false">Loading...</div>
<p>Welcome to FacilPad.</p> <div id="map" fp-map fp-pad-id="{{padId}}"></div>
<noscript><p><strong>FacilPad requires JavaScript to work.</strong></p></noscript>
<p><a id="create-pad-link" rel="nofollow">Create a new pad</a></p>
</div>
<div id="loading" style="display:none">Loading...</div>
<div id="mapContainer" style="display:none">
<div id="map" fp-map fp-pad-id="{{padId}}"></div>
</div>
<script> <script>
(function() { var interval = setInterval(function() {
var loaded = 0; if(window.angular != null && window.io != null) {
clearInterval(interval);
var l = document.getElementById("create-pad-link"); angular.bootstrap(document, [ "facilpad" ]);
var LETTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var LENGTH = 12;
var randomPadId = "";
for(var i=0; i<LENGTH; i++) {
randomPadId += LETTERS[Math.floor(Math.random() * LETTERS.length)];
} }
}, 100);
l.href = randomPadId;
l.onclick = function() {
if(window.history && history.pushState) {
history.pushState(null, null, randomPadId);
check();
return false;
}
};
var interval = setInterval(check, 100);
function check() {
if(loaded == 0 && !location.pathname.match(/\/$/)) {
document.getElementById("introContainer").style.display = "none";
document.getElementById("loading").style.display = "";
loaded = 1;
}
if(loaded == 1 && window.FacilPad != null && window.io != null && $("#map").css("height") == "100%") {
$("#introContainer,#loading").remove();
$("#map").unwrap();
angular.bootstrap(document, [ "facilpad" ]);
loaded = 2;
clearInterval(interval);
}
}
check();
})();
</script> </script>
<!-- inject:js --> <!-- inject:js -->

Wyświetl plik

@ -16,22 +16,29 @@ function getPadData(padId, callback) {
if(err) if(err)
return callback(err); return callback(err);
else if(data != null) else if(data != null)
return callback(null, utils.extend(JSON.parse(JSON.stringify(data)), { writable: true, writeId: null })); return callback(null, utils.extend(JSON.parse(JSON.stringify(data)), { writable: true }));
backend.getPadData(padId, function(err, data) { backend.getPadData(padId, function(err, data) {
if(err || data != null) if(err)
return callback(err, utils.extend(JSON.parse(JSON.stringify(data)), { writable: false, writeId: null })); return callback(err);
backend.createPad(utils.generateRandomId(10), padId, function(err, data) { if(data == null)
if(err) return callback("This pad does not exist.");
return callback(err);
async.each(DEFAULT_TYPES, function(it, next) { return callback(null, utils.extend(JSON.parse(JSON.stringify(data)), { writable: false, writeId: null }));
backend.createType(data.id, it, next); });
}, function(err) { });
callback(err, utils.extend(JSON.parse(JSON.stringify(data)), { writable: true, writeId: null })); }
});
}); function createPad(data, callback) {
backend.createPad(data, function(err, data) {
if(err)
return callback(err);
async.each(DEFAULT_TYPES, function(it, next) {
backend.createType(data.id, it, next);
}, function(err) {
callback(err, utils.extend(JSON.parse(JSON.stringify(data)), { writable: true }));
}); });
}); });
} }
@ -41,7 +48,17 @@ function updatePadData(padId, data, callback) {
if(err) if(err)
return callback(err); return callback(err);
listeners.notifyPadListeners(padId, "padData", data); listeners.notifyPadListeners(padId, "padData", function(listener) {
var dataClone = JSON.parse(JSON.stringify(data));
if(!listener.writable)
dataClone.writeId = null;
return dataClone;
});
if(data.id && data.id != padId)
listeners.changePadId(padId, data.id);
callback(null, data); callback(null, data);
}); });
} }
@ -350,8 +367,8 @@ function _setLinePoints(padId, lineId, trackPoints, callback) {
if(err) if(err)
return callback(err); return callback(err);
listeners.notifyPadListeners(padId, "linePoints", function(bboxWithZoom) { listeners.notifyPadListeners(padId, "linePoints", function(listener) {
return { reset: true, id: lineId, trackPoints : (bboxWithZoom ? routing.prepareForBoundingBox(trackPoints, bboxWithZoom) : [ ]) }; return { reset: true, id: lineId, trackPoints : (listener && listener.bbox ? routing.prepareForBoundingBox(trackPoints, listener.bbox) : [ ]) };
}); });
callback(null); callback(null);
@ -478,8 +495,8 @@ function _calculateRouting(line, callback) {
} }
function _getMarkerDataFunc(marker) { function _getMarkerDataFunc(marker) {
return function(bbox) { return function(listener) {
if(!bbox || !utils.isInBbox(marker, bbox)) if(!listener || !listener.bbox || !utils.isInBbox(marker, listener.bbox))
return null; return null;
return marker; return marker;
@ -513,6 +530,7 @@ function _getLinePoints(lineId, bboxWithZoom, callback) {
module.exports = { module.exports = {
connect : backend.connect, connect : backend.connect,
getPadData : getPadData, getPadData : getPadData,
createPad : createPad,
updatePadData : updatePadData, updatePadData : updatePadData,
getViews : getViews, getViews : getViews,
createView : createView, createView : createView,

Wyświetl plik

@ -62,9 +62,9 @@ function _makeNotNullForeignKey(type, field, error) {
/* Pads */ /* Pads */
var Pad = conn.define("Pad", { var Pad = conn.define("Pad", {
id : { type: Sequelize.STRING, allowNull: false, unique: "padId", primaryKey: true }, id : { type: Sequelize.STRING, allowNull: false, unique: "padId", primaryKey: true, validate: { is: /^.+$/ } },
name: { type: Sequelize.TEXT, allowNull: true, get: function() { return this.getDataValue("name") || "New FacilPad"; } }, name: { type: Sequelize.TEXT, allowNull: true, get: function() { return this.getDataValue("name") || "New FacilPad"; } },
writeId: { type: Sequelize.STRING, allowNull: false, unique: "padId" } writeId: { type: Sequelize.STRING, allowNull: false, unique: "padId", validate: { is: /^.+$/ } }
}); });
@ -262,8 +262,8 @@ function getPadDataByWriteId(writeId, callback) {
_promiseComplete(Pad.findOne({ where: { writeId: writeId }, include: [ { model: View, as: "defaultView" } ] }), callback); _promiseComplete(Pad.findOne({ where: { writeId: writeId }, include: [ { model: View, as: "defaultView" } ] }), callback);
} }
function createPad(padId, writeId, callback) { function createPad(data, callback) {
_promiseComplete(Pad.create({ id: padId, writeId: writeId }), callback); _promiseComplete(Pad.create(data), callback);
} }
function updatePadData(padId, data, callback) { function updatePadData(padId, data, callback) {
@ -272,7 +272,7 @@ function updatePadData(padId, data, callback) {
_promiseComplete(Pad.update(data, { where: { id: padId } }), next); _promiseComplete(Pad.update(data, { where: { id: padId } }), next);
}, },
function(affectedNumber, next) { function(affectedNumber, next) {
getPadData(padId, next); getPadData(data.id || padId, next);
} }
], callback); ], callback);
} }

Wyświetl plik

@ -7,7 +7,7 @@ function notifyPadListeners(padId, eventType, getData) {
var isFunc = (typeof getData == "function"); var isFunc = (typeof getData == "function");
( listeners[padId] || [ ]).forEach(function(listener) { ( listeners[padId] || [ ]).forEach(function(listener) {
var data = isFunc ? getData(listener.bbox) : getData; var data = isFunc ? getData(listener) : getData;
if(data == null) if(data == null)
return; return;
@ -34,8 +34,21 @@ function removePadListener(listener) {
listeners[listener.padId] = l.slice(0, idx).concat(l.slice(idx+1)); listeners[listener.padId] = l.slice(0, idx).concat(l.slice(idx+1));
} }
function changePadId(oldPadId, newPadId) {
if(oldPadId == newPadId)
return;
listeners[newPadId] = listeners[oldPadId];
delete listeners[oldPadId];
listeners[newPadId].forEach(function(listener) {
listener.padId = newPadId;
});
}
module.exports = { module.exports = {
notifyPadListeners : notifyPadListeners, notifyPadListeners : notifyPadListeners,
addPadListener : addPadListener, addPadListener : addPadListener,
removePadListener: removePadListener removePadListener: removePadListener,
changePadId: changePadId
}; };

Wyświetl plik

@ -66,19 +66,7 @@ database.connect(function(err) {
if(err) if(err)
return _sendData(socket, "padData", err); return _sendData(socket, "padData", err);
socket.padId = data.id; _setPadId(socket, data);
socket.writable = data.writable;
listeners.addPadListener(socket);
_sendData(socket, "padData", null, data);
_sendStreamData(socket, "view", database.getViews(socket.padId));
_sendStreamData(socket, "type", database.getTypes(socket.padId));
_sendStreamData(socket, "line", database.getPadLines(socket.padId));
if(socket.bbox) { // In case bbox is set while fetching pad data
_sendStreamData(socket, "marker", database.getPadMarkers(socket.padId, socket.bbox));
_sendStreamData(socket, "linePoints", database.getLinePoints(socket.padId, socket.bbox));
}
}); });
}, },
@ -103,8 +91,25 @@ database.connect(function(err) {
listeners.removePadListener(socket); listeners.removePadListener(socket);
}, },
createPad : function(data, callback) {
if(!utils.stripObject(data, { name: "string", defaultViewId: "number", id: "string", writeId: "string" }))
return callback("Invalid parameters.");
if(socket.padId)
return callback("Pad already loaded.");
database.createPad(data, function(err, padData) {
if(err)
return callback(err);
_setPadId(socket, padData);
callback(null, padData);
});
},
editPad : function(data, callback) { editPad : function(data, callback) {
if(!utils.stripObject(data, { name: "string", defaultViewId: "number" })) if(!utils.stripObject(data, { name: "string", defaultViewId: "number", id: "string", writeId: "string" }))
return callback("Invalid parameters."); return callback("Invalid parameters.");
if(!socket.writable) if(!socket.writable)
@ -241,6 +246,9 @@ database.connect(function(err) {
}, },
exportGpx : function(data, callback) { exportGpx : function(data, callback) {
if(socket.padId == null)
return callback("No pad ID set.");
gpx.exportGpx(socket.padId, data.useTracks, callback); gpx.exportGpx(socket.padId, data.useTracks, callback);
}, },
@ -278,7 +286,9 @@ database.connect(function(err) {
function _sendData(socket, eventName, err, data) { function _sendData(socket, eventName, err, data) {
if(err) { if(err) {
console.warn("_sendData", err, err.stack); console.warn("_sendData", err, err.stack);
return socket.emit("error", err); socket.emit("serverError", err);
socket.disconnect();
return;
} }
socket.emit(eventName, data); socket.emit(eventName, data);
@ -292,4 +302,20 @@ function _sendStreamData(socket, eventName, stream) {
console.warn("_sendStreamData", err, err.stack); console.warn("_sendStreamData", err, err.stack);
socket.emit("error", err); socket.emit("error", err);
}) })
}
function _setPadId(socket, data) {
socket.padId = data.id;
socket.writable = data.writable;
listeners.addPadListener(socket);
_sendData(socket, "padData", null, data);
_sendStreamData(socket, "view", database.getViews(socket.padId));
_sendStreamData(socket, "type", database.getTypes(socket.padId));
_sendStreamData(socket, "line", database.getPadLines(socket.padId));
if(socket.bbox) { // In case bbox is set while fetching pad data
_sendStreamData(socket, "marker", database.getPadMarkers(socket.padId, socket.bbox));
_sendStreamData(socket, "linePoints", database.getLinePoints(socket.padId, socket.bbox));
}
} }