diff --git a/www/index.html b/www/index.html index 2f61aada146f0f95a7e721ef59a1bb99e7253daf..3ba552d6ae6bc873ac73138cf68a2a82ab4d238d 100644 --- a/www/index.html +++ b/www/index.html @@ -197,6 +197,7 @@ <script src="dist/dist_js/plugins/map/js/services/utils-services.js"></script> <script src="dist/dist_js/plugins/map/js/controllers/wot-controllers.js"></script> <script src="dist/dist_js/plugins/map/js/controllers/network-controllers.js"></script> + <script src="dist/dist_js/plugins/map/js/controllers/user-controllers.js"></script> <!-- RML9 plugin --> <!--<script src="dist/dist_js/plugins/rml9/plugin-01-add_button.js"></script>--> diff --git a/www/js/app.js b/www/js/app.js index bcc256716449be2c3b46209c2d65d5d0b9c4ce43..c4ee9698cd4956458592d4dfb1aa9b58d4b4c567 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -281,6 +281,16 @@ if (typeof String.prototype.startsWith !== 'function') { }; } +// Workaround to add "".startsWith() if not present +if (typeof String.prototype.trim !== 'function') { + console.debug("Adding String.prototype.trim() -> was missing on this platform"); + // Make sure we trim BOM and NBSP + var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + String.prototype.trim = function() { + return this.replace(rtrim, ''); + }; +} + // Workaround to add Math.trunc() if not present - fix #144 if (Math && typeof Math.trunc !== 'function') { console.debug("Adding Math.trunc() -> was missing on this platform"); diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index bd0daf4174c3c312a5ae1d636345a274a8f4745f..8c07f40b02fb2c0b6b45c6083328db74cc5ce685 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -224,6 +224,7 @@ function NetworkLookupController($scope, $state, $ionicHistory, $ionicPopover, }; $scope.selectPeer = function(peer) { + if (!peer.online) return; // nothing to do var stateParams = {server: peer.getServer()}; if (peer.isSsl()) { stateParams.ssl = true; diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js index 4bf6deea3c9c178057176601bc016826da5cf457..2a49997c44072e208bae78a042fea73cc709144c 100644 --- a/www/js/services/network-services.js +++ b/www/js/services/network-services.js @@ -239,7 +239,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi .then(function (refreshedPeer) { if (existingPeer) { // remove existing peers, when reject or offline - if (!refreshedPeer || (refreshedPeer.online !== data.filter.online)) { + if (!refreshedPeer || (refreshedPeer.online !== data.filter.online && data.filter.online !== 'all')) { console.debug('[network] Peer [{0}] removed (cause: {1})'.format(peer.server, !refreshedPeer ? 'filtered' : (refreshedPeer.online ? 'UP': 'DOWN'))); data.peers.splice(data.peers.indexOf(existingPeer), 1); hasUpdates = true; @@ -249,15 +249,15 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi hasUpdates = true; } else if (existingOnline !== refreshedPeer.online){ - console.debug('[network] Peer [{0}] is now UP'.format(refreshedPeer.server)); + console.debug('[network] Peer [{0}] is now {1}'.format(refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN')); hasUpdates = true; } else { console.debug("[network] Peer [{0}] unchanged".format(refreshedPeer.server)); } } - else if (refreshedPeer && (refreshedPeer.online === data.filter.online)) { - console.debug("[network] Peer [{0}] is UP".format(refreshedPeer.server)); + else if (refreshedPeer && (refreshedPeer.online === data.filter.online || data.filter.online === 'all')) { + console.debug("[network] Peer [{0}] is {1}".format(refreshedPeer.server, refreshedPeer.online ? 'UP' : 'DOWN')); list.push(refreshedPeer); hasUpdates = true; } @@ -308,14 +308,14 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi // Apply filter if (!applyPeerFilter(peer)) return $q.when(); - if (!data.filter.online) { + if (!data.filter.online || (data.filter.online === 'all' && peer.status === 'DOWN')) { peer.online = false; return $q.when(peer); } // Cesium running in SSL: Do not try to access not SSL node, if (isHttpsMode && !peer.bma.useSsl) { - peer.online = (peer.status == 'UP'); + peer.online = (peer.status === 'UP'); peer.buid = constants.UNKNOWN_BUID; delete peer.version; @@ -473,7 +473,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.bma.services', 'cesi }); _.forEach(data.peers, function(peer){ peer.hasMainConsensusBlock = peer.buid == mainBlock.buid; - peer.hasConsensusBlock = !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; + peer.hasConsensusBlock = peer.buid && !peer.hasMainConsensusBlock && buids[peer.buid].count > 1; if (peer.hasConsensusBlock) { peer.consensusBlockDelta = buids[peer.buid].medianTime - mainBlock.medianTime; } diff --git a/www/plugins/es/i18n/locale-en-GB.json b/www/plugins/es/i18n/locale-en-GB.json index cf4c37c31311669ca0a4c83dc090c4ecaf6afdfd..a8fcc0de4aa904f23dba696fe7e58458434bd086 100644 --- a/www/plugins/es/i18n/locale-en-GB.json +++ b/www/plugins/es/i18n/locale-en-GB.json @@ -320,7 +320,9 @@ "LOOKUP_RECORDS_FAILED": "Error while loading records.", "REMOVE_RECORD_FAILED": "Deleting failed", "SAVE_RECORD_FAILED": "Saving failed", - "RECORD_NOT_EXISTS": "Record not found" + "RECORD_NOT_EXISTS": "Record not found", + "FAILED_SAVE_COMMENT": "Saving comment failed", + "FAILED_REMOVE_COMMENT": "Deleting comment failed" }, "INFO": { "RECORD_REMOVED" : "Reference successfully deleted" @@ -331,6 +333,9 @@ "NO_PROFILE_DEFINED": "No Cesium+ profile", "BTN_ADD": "Create my profile", "BTN_EDIT": "Edit my profile", + "BTN_GEOLOC_ADDRESS": "Update position from address", + "BTN_GEOLOC_ME": "Localize me", + "BTN_REMOVE_GEOLOC": "Remove position", "UID": "Pseudonym", "TITLE": "Lastname, FirstName", "TITLE_HELP": "Name", @@ -344,6 +349,10 @@ "GENERAL_DIVIDER": "General data", "LOCATION_DIVIDER": "Localisation", "SOCIAL_NETWORKS_DIVIDER": "Social networks and web site", + "LATITUDE": "Latitude", + "LATITUDE_HELP": "Latitude", + "LONGITUDE": "Longitude", + "LONGITUDE_HELP": "Longitude", "TECHNICAL_DIVIDER": "Technical data", "MODAL_AVATAR": { "TITLE": "Avatar", @@ -356,7 +365,8 @@ "LOAD_PROFILE_FAILED": "Could not load user profile.", "SAVE_PROFILE_FAILED": "Saving profile failed", "INVALID_SOCIAL_NETWORK_FORMAT": "Invalid format: please fill a valid Internet address.<br/><br/>Examples :<ul><li>- A Facebook page (https://www.facebook.com/user)</li><li>- A web page (http://www.domain.com)</li><li>- An email address (joe@dalton.com)</li></ul>", - "IMAGE_RESIZE_FAILED": "Error while resizing picture" + "IMAGE_RESIZE_FAILED": "Error while resizing picture", + "GEO_LOCATION_FAILED": "Unable to retrieve your current position" }, "INFO": { "PROFILE_SAVED": "Profile saved" @@ -437,6 +447,8 @@ "NODE_BMA_UP": "Node <b>{{params[0]}}:{{params[1]}}</b> is reachable again.", "MEMBER_JOIN": "You are now a <b>member</b> of currency <b>{{params[0]}}</b>!", "MEMBER_LEAVE": "You are <b>not a member anymore</b> of currency <b>{{params[0]}}</b>!", + "MEMBER_EXCLUDE": "You are <b>not more member</b> of the currency <b>{{params[0]}}</b>, for lack of renewal or lack of certifications.", + "MEMBER_REVOKE": "Your account has been revoked. It will no longer be a member of the currency <b>{{params[0]}}</b>.", "MEMBER_ACTIVE": "Your membership to <b>{{params[0]}}</b> has been <b>renewed successfully</b>.", "TX_SENT": "Your payment to <span ng-class=\"{'gray': !notification.uid, 'positive':notification.uid}\" ><i class=\"icon\" ng-class=\"{'ion-person': notification.uid, 'ion-key': !notification.uid}\"></i> {{name||uid||params[1]}}</span> was executed.", "TX_SENT_MULTI": "Your payment to <b>{{params[1]}}</b> was executed.", diff --git a/www/plugins/es/i18n/locale-en.json b/www/plugins/es/i18n/locale-en.json index 587093f0fb851119ba11d8efa3cd588740025776..a8fcc0de4aa904f23dba696fe7e58458434bd086 100644 --- a/www/plugins/es/i18n/locale-en.json +++ b/www/plugins/es/i18n/locale-en.json @@ -333,6 +333,9 @@ "NO_PROFILE_DEFINED": "No Cesium+ profile", "BTN_ADD": "Create my profile", "BTN_EDIT": "Edit my profile", + "BTN_GEOLOC_ADDRESS": "Update position from address", + "BTN_GEOLOC_ME": "Localize me", + "BTN_REMOVE_GEOLOC": "Remove position", "UID": "Pseudonym", "TITLE": "Lastname, FirstName", "TITLE_HELP": "Name", @@ -346,6 +349,10 @@ "GENERAL_DIVIDER": "General data", "LOCATION_DIVIDER": "Localisation", "SOCIAL_NETWORKS_DIVIDER": "Social networks and web site", + "LATITUDE": "Latitude", + "LATITUDE_HELP": "Latitude", + "LONGITUDE": "Longitude", + "LONGITUDE_HELP": "Longitude", "TECHNICAL_DIVIDER": "Technical data", "MODAL_AVATAR": { "TITLE": "Avatar", @@ -358,7 +365,8 @@ "LOAD_PROFILE_FAILED": "Could not load user profile.", "SAVE_PROFILE_FAILED": "Saving profile failed", "INVALID_SOCIAL_NETWORK_FORMAT": "Invalid format: please fill a valid Internet address.<br/><br/>Examples :<ul><li>- A Facebook page (https://www.facebook.com/user)</li><li>- A web page (http://www.domain.com)</li><li>- An email address (joe@dalton.com)</li></ul>", - "IMAGE_RESIZE_FAILED": "Error while resizing picture" + "IMAGE_RESIZE_FAILED": "Error while resizing picture", + "GEO_LOCATION_FAILED": "Unable to retrieve your current position" }, "INFO": { "PROFILE_SAVED": "Profile saved" diff --git a/www/plugins/es/i18n/locale-fr-FR.json b/www/plugins/es/i18n/locale-fr-FR.json index 08e041fb15fa5a5d665c308a18ee26724171c9f7..c4d28a409385d340d557e18d636847f3cc0092fd 100644 --- a/www/plugins/es/i18n/locale-fr-FR.json +++ b/www/plugins/es/i18n/locale-fr-FR.json @@ -374,8 +374,9 @@ "NO_PROFILE_DEFINED": "Aucun profil Cesium+", "BTN_ADD": "Saisir mon profil", "BTN_EDIT": "Editer mon profil", - "BTN_GEOLOC_CITY": "Localiser la ville", + "BTN_GEOLOC_ADDRESS": "Mettre à jour à partir de l'adresse", "BTN_GEOLOC_ME": "Me localiser", + "BTN_REMOVE_GEOLOC": "Supprimer la position", "UID": "Pseudonyme", "TITLE": "Nom, Prénom", "TITLE_HELP": "Nom, Prénom", @@ -389,7 +390,6 @@ "GENERAL_DIVIDER": "Informations générales", "LOCATION_DIVIDER": "Adresse", "SOCIAL_NETWORKS_DIVIDER": "Réseaux sociaux, sites web", - "GEO_POINT_DIVIDER": "Position GPS", "LATITUDE": "Latitude", "LATITUDE_HELP": "Latitude", "LONGITUDE": "Longitude", @@ -407,7 +407,7 @@ "SAVE_PROFILE_FAILED": "Erreur lors de la sauvegarde", "INVALID_SOCIAL_NETWORK_FORMAT": "Format non pris en compte : veuillez indiquer une adresse valide.<br/><br/>Exemples :<ul><li>- Une page Facebook (https://www.facebook.com/user)</li><li>- Une page web (http://www.monsite.fr)</li><li>- Une adresse email (joe@dalton.com)</li></ul>", "IMAGE_RESIZE_FAILED": "Erreur lors du redimensionnement de l'image", - "GEO_LOCATION_FAILED": "Echec de la récupération de votre position" + "GEO_LOCATION_FAILED": "Impossible de récupérer votre position actuelle" }, "INFO": { "PROFILE_SAVED": "Profil sauvegardé" diff --git a/www/plugins/es/js/controllers/profile-controllers.js b/www/plugins/es/js/controllers/profile-controllers.js index 5322dd8a50a762f711beaf197b366fc996754319..67a9d396836a0ef960f133acb880ebb13497f42c 100644 --- a/www/plugins/es/js/controllers/profile-controllers.js +++ b/www/plugins/es/js/controllers/profile-controllers.js @@ -24,7 +24,7 @@ angular.module('cesium.es.profile.controllers', ['cesium.es.services']) ; -function ESViewEditProfileController($scope, $rootScope, $timeout, $state, $focus, $translate, $ionicHistory, +function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $focus, $translate, $ionicHistory, UIUtils, esHttp, esProfile, esGeo, ModalUtils, Device) { 'ngInject'; @@ -137,13 +137,20 @@ function ESViewEditProfileController($scope, $rootScope, $timeout, $state, $focu }; $scope.$watch('formData', $scope.onFormDataChanged, true); - $scope.save = function(silent) { + $scope.save = function(silent, hasWaitDebounce) { if(!$scope.form.$valid || !$rootScope.walletData || $scope.saving) { - return; + return $q.reject(); + } + + if (!hasWaitDebounce) { + console.debug('[ES] [profile] Waiting debounce end, before saving...'); + return $timeout(function() { + return $scope.save(silent, true); + }, 650); } - console.debug('[ES] [profile] Saving user profile...'); $scope.saving = true; + console.debug('[ES] [profile] Saving user profile...'); // removeIf(no-device) if (!silent) { @@ -193,6 +200,19 @@ function ESViewEditProfileController($scope, $rootScope, $timeout, $state, $focu return social.url; }); } + + // Workaround for old data + if (formData.position) { + delete formData.position; + } + if ($scope.formData.geoPoint && $scope.formData.geoPoint.lat && $scope.formData.geoPoint.lon) { + $scope.formData.geoPoint.lat = parseFloat($scope.formData.geoPoint.lat); + $scope.formData.geoPoint.lon = parseFloat($scope.formData.geoPoint.lon); + } + else{ + $scope.formData.geoPoint = null; + } + if (!$scope.existing) { return esProfile.add(formData) .then(function() { @@ -291,29 +311,97 @@ function ESViewEditProfileController($scope, $rootScope, $timeout, $state, $focu }); }; - $scope.localizeByCity = function() { - if (!$scope.formData.city) { - return; - } + $scope.localizeByAddress = function() { - var address = angular.copy($scope.formData.city); - - return esGeo.point.searchByAddress(address) + return $scope.searchPositions() .then(function(res) { - if (address != $scope.formData.city) return; // user changed value again - - if (res && res.length >= 1) { - var position = res[0]; - if (position.lat && position.lon) { - $scope.formData.geoPoint = $scope.formData.geoPoint || {}; - $scope.formData.geoPoint.lat = parseFloat(position.lat); - $scope.formData.geoPoint.lon = parseFloat(position.lon); - $scope.dirty = true; - } + if (!res) return; // no result, or city value just changed + if (res.length == 1) { + return res[0]; + } + + return ModalUtils.show('plugins/es/templates/common/modal_category.html', 'ESCategoryModalCtrl as ctrl', + {categories : res}, + {focusFirstInput: true} + ); + }) + .then(function(position) { + if (position && position.lat && position.lon) { + $scope.formData.geoPoint = $scope.formData.geoPoint || {}; + $scope.formData.geoPoint.lat = parseFloat(position.lat); + $scope.formData.geoPoint.lon = parseFloat(position.lon); + + //$scope.dirty = true; // not need ?? } }); }; + $scope.searchPositions = function(query) { + + // Build the query + if (!query) { + if (!$scope.formData.city) { + return $q.when(); // nothing to search + } + + var cityPart = $scope.formData.city.split(','); + var city = cityPart[0]; + var country = cityPart.length > 1 ? cityPart[1].trim() : undefined; + var street = $scope.formData.address ? angular.copy($scope.formData.address.trim()) : undefined; + if (street) { + // Search with AND without street + return $q.all([ + $scope.searchPositions({ + street: street, + city: city, + country: country + }), + $scope.searchPositions({ + city: city, + country: country + }) + ]) + .then(function(res){ + return res[0].concat(res[1]); + }); + } + else { + return $scope.searchPositions({ + city: city, + country: country + }); + } + } + + // Execute the given query + return esGeo.point.searchByAddress(query) + .then(function(res) { + if (!res) return $q.when(); // no result + + // Ask user to choose + var index = 0; + var parent = {name: 'Résultat pour <b>' + + (query.street ? query.street + ', ' : '') + + query.city + + (query.country ? ', ' + query.country : '') + + '</b>', id: 0}; + var hits = res.reduce(function(res, hit){ + index++; + if (hit.class == 'waterway') return res; + return res.concat({ + id: index, + name: hit.display_name, + parent: parent, + lat: hit.lat, + lon: hit.lon + }); + }, [parent]); + + if (hits.length == 1) return $q.when(); // no result (after filtering) + + return hits; + }); + }; $scope.localizeMe = function() { return esGeo.point.current() @@ -326,13 +414,20 @@ function ESViewEditProfileController($scope, $rootScope, $timeout, $state, $focu .catch(UIUtils.onError('PROFILE.ERROR.GEO_LOCATION_FAILED')); }; + $scope.removeLocalisation = function() { + if ($scope.formData.geoPoint) { + $scope.formData.geoPoint.lat = null; + $scope.formData.geoPoint.lon = null; + } + }; + $scope.onCityChanged = function() { + if ($scope.loading) return; var hasGeoPoint = $scope.formData.geoPoint && $scope.formData.geoPoint.lat && $scope.formData.geoPoint.lon; if (!hasGeoPoint) { - return $scope.localizeByCity(); + return $scope.localizeByAddress(); } }; - $scope.$watch('formData.city', $scope.onCityChanged, true); } diff --git a/www/plugins/es/js/services/geo-services.js b/www/plugins/es/js/services/geo-services.js index 86e67f8f0622080d3b6bc4ab6dd0482e8a4433b8..e05efc3570a8c9388d5ac65adaefd2168886d62a 100644 --- a/www/plugins/es/js/services/geo-services.js +++ b/www/plugins/es/js/services/geo-services.js @@ -17,22 +17,37 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser that = this; that.raw = { - searchByAddress: csHttp.get('nominatim.openstreetmap.org', 80, '/search.php?format=json&q=:query'), + searchByString: csHttp.get('nominatim.openstreetmap.org', 80, '/search.php?format=json&q=:query'), + searchByQuery: csHttp.get('nominatim.openstreetmap.org', 80, '/search.php?format=json'), searchByIP: csHttp.get('freegeoip.net', 80, '/json/:ip') }; - function searchPositionByAddress(queryString) { + function searchPositionByString(queryString) { var now = new Date(); - console.debug('[ES] [geo] Searching address position [{0}]...'.format(queryString)); + console.debug('[ES] [geo] Searching position by string query [{0}]...'.format(queryString)); - return that.raw.searchByAddress({query: queryString}) + return that.raw.searchByString({query: queryString}) .then(function(res) { console.debug('[ES] [geo] Found {0} address position(s) in {0}ms'.format(res && res.length || 0, new Date().getTime() - now.getTime())); return res; }); } + function searchhPositionByQuery(query) { + + if (typeof query == 'string') return searchPositionByString(query); + + var now = new Date(); + console.debug('[ES] [geo] Searching position by query...', query); + + return that.raw.searchByQuery(query) + .then(function(res) { + console.debug('[ES] [geo] Found {0} address position(s) in {0}ms'.format(res && res.length || 0, new Date().getTime() - now.getTime()), res); + return res; + }); + } + function getCurrentPosition() { var defer = $q.defer(); if (navigator.geolocation) { @@ -69,7 +84,7 @@ angular.module('cesium.es.geo.services', ['cesium.services', 'cesium.es.http.ser return { point: { current: getCurrentPosition, - searchByAddress: searchPositionByAddress, + searchByAddress: searchhPositionByQuery, searchByIP: searchPositionByIP } }; diff --git a/www/plugins/es/templates/user/edit_profile.html b/www/plugins/es/templates/user/edit_profile.html index a6a1923108b9a3bb9644eedf0296e72a272dbbbc..0dc08b5e514741c84ef84541a82d213ea83cfe5a 100644 --- a/www/plugins/es/templates/user/edit_profile.html +++ b/www/plugins/es/templates/user/edit_profile.html @@ -109,15 +109,10 @@ <span class="input-label" translate>PROFILE.CITY</span> <input type="text" placeholder="{{'PROFILE.CITY_HELP'|translate}}" ng-model="formData.city" - ng-model-options="{ debounce: 350 }"> + ng-model-options="{ updateOn: 'blur' }" + ng-change="onCityChanged()"> </div> - <!--<div class="item"> - <span class="input-label"> - {{'PROFILE.GEO_POINT_DIVIDER' | translate}} - </span> - </div>--> - <!-- Position (lat/lon) --> <div class="row responsive-md responsive-sm no-padding"> @@ -128,8 +123,7 @@ <input class="no-padding-right" type="number" placeholder="{{'PROFILE.LATITUDE_HELP'|translate}}" ng-model="formData.geoPoint.lat" ng-model-options="{ debounce: 350 }" - ng-change="onGeoPointChanged()" - required> + ng-change="onGeoPointChanged()"> </label> </div> @@ -144,8 +138,7 @@ <input class="no-padding-right" type="number" placeholder="{{'PROFILE.LONGITUDE_HELP'|translate}}" ng-model="formData.geoPoint.lon" ng-model-options="{ debounce: 350 }" - ng-change="onGeoPointChanged()" - required> + ng-change="onGeoPointChanged()"> </label> </div> @@ -154,18 +147,27 @@ <span class="input-label"></span> <a class="button button-stable button-small-padding icon ion-refresh" - title="{{'PROFILE.BTN_GEOLOC_CITY'|translate}}" - ng-click="localizeByCity()"> + title="{{'PROFILE.BTN_GEOLOC_ADDRESS'|translate}}" + ng-disabled="!formData.city" + ng-click="localizeByAddress()"> </a> <a class="button button-stable button-small-padding icon ion-android-locate" title="{{'PROFILE.BTN_GEOLOC_ME'|translate}}" ng-click="localizeMe()"> </a> + + <a class="button button-stable button-small-padding icon ion-close" + title="{{'PROFILE.BTN_REMOVE_GEOLOC'|translate}}" + ng-disabled="!formData.geoPoint || (!formData.geoPoint.lat && !formData.geoPoint.lon)" + ng-click="removeLocalisation()"> + </a> </div> </div> </div> + <cs-extension-point name="after-position"></cs-extension-point> + <!-- social networks --> <ng-include src="'plugins/es/templates/common/edit_socials.html'"></ng-include> diff --git a/www/plugins/map/i18n/locale-en-GB.json b/www/plugins/map/i18n/locale-en-GB.json new file mode 100644 index 0000000000000000000000000000000000000000..4d23c5c79d9b9f615c470459e2bdf36963304c18 --- /dev/null +++ b/www/plugins/map/i18n/locale-en-GB.json @@ -0,0 +1,40 @@ +{ + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Search..." + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Peers map", + "BTN_MAP_HELP": "Open peers map" + }, + "VIEW": { + "TITLE": "Peers map", + "LAYER": { + "MEMBER": "Member peers", + "MIRROR": "Mirror peers", + "OFFLINE": "Offline peers" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Members map", + "BTN_MAP_HELP": "Open members map" + }, + "VIEW": { + "TITLE": "Members map", + "LAYER": { + "MEMBER": "Members", + "WALLET": "Simple wallets" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Drag and drop</b> this marker to <b>update<br/>your position</b>, or use the buttons<br/>on top of the map." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Unable to retrieve your current position" + } + } +} diff --git a/www/plugins/map/i18n/locale-en.json b/www/plugins/map/i18n/locale-en.json new file mode 100644 index 0000000000000000000000000000000000000000..4d23c5c79d9b9f615c470459e2bdf36963304c18 --- /dev/null +++ b/www/plugins/map/i18n/locale-en.json @@ -0,0 +1,40 @@ +{ + "MAP": { + "COMMON": { + "SEARCH_DOTS": "Search..." + }, + "NETWORK": { + "LOOKUP": { + "BTN_MAP": "Peers map", + "BTN_MAP_HELP": "Open peers map" + }, + "VIEW": { + "TITLE": "Peers map", + "LAYER": { + "MEMBER": "Member peers", + "MIRROR": "Mirror peers", + "OFFLINE": "Offline peers" + } + } + }, + "WOT": { + "LOOKUP": { + "BTN_MAP": "Members map", + "BTN_MAP_HELP": "Open members map" + }, + "VIEW": { + "TITLE": "Members map", + "LAYER": { + "MEMBER": "Members", + "WALLET": "Simple wallets" + } + } + }, + "PROFILE": { + "MARKER_HELP": "<b>Drag and drop</b> this marker to <b>update<br/>your position</b>, or use the buttons<br/>on top of the map." + }, + "ERROR": { + "LOCALIZE_ME_FAILED": "Unable to retrieve your current position" + } + } +} diff --git a/www/plugins/map/i18n/locale-fr-FR.json b/www/plugins/map/i18n/locale-fr-FR.json index 97bbbd0a815b757a833b401fbade4560b5670565..4083d3d55a1b7e8b927536b7d1ca142f734a052f 100644 --- a/www/plugins/map/i18n/locale-fr-FR.json +++ b/www/plugins/map/i18n/locale-fr-FR.json @@ -31,8 +31,11 @@ } } }, + "PROFILE": { + "MARKER_HELP": "<b>Glissez-déposez</b> ce marqueur pour <b>mettre<br/>à jour votre position</b>, ou utilisez les boutons<br/>au dessus de la carte." + }, "ERROR": { - "LOCALIZE_ME_FAILED": "Echec de la récupération de votre position" + "LOCALIZE_ME_FAILED": "Impossible de récupérer votre position actuelle" } } } diff --git a/www/plugins/map/js/controllers/network-controllers.js b/www/plugins/map/js/controllers/network-controllers.js index eaaeba27d356bade8f19a3ff1f034d480885636f..f511a09b4f1547710694af497e49a43381af82ab 100644 --- a/www/plugins/map/js/controllers/network-controllers.js +++ b/www/plugins/map/js/controllers/network-controllers.js @@ -9,7 +9,6 @@ angular.module('cesium.map.network.controllers', ['cesium.services', 'cesium.map PluginServiceProvider - // Extension de la vue d'une identité: ajout d'un bouton .extendState('app.network', { points: { 'filter-buttons': { @@ -18,7 +17,6 @@ angular.module('cesium.map.network.controllers', ['cesium.services', 'cesium.map } }); - // [NEW] Ajout d'une nouvelle page #/app/wot/map $stateProvider .state('app.view_network_map', { url: "/network/map?c", @@ -133,6 +131,13 @@ angular.module('cesium.map.network.controllers', ['cesium.services', 'cesium.map }; $scope.$on('$ionicView.enter', $scope.enter); + var inheritedComputeOptions = $scope.computeOptions; + $scope.computeOptions = function() { + var options = inheritedComputeOptions(); + options.filter.online = 'all'; + return options; + }; + $scope.loadMap = function() { return leafletData.getMap($scope.mapId).then(function(map) { if (!$scope.map.loading) return map; // already loaded diff --git a/www/plugins/map/js/controllers/user-controllers.js b/www/plugins/map/js/controllers/user-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..457941574c44ee86d39e45036a8ceadfcfb24c8d --- /dev/null +++ b/www/plugins/map/js/controllers/user-controllers.js @@ -0,0 +1,121 @@ + +angular.module('cesium.map.user.controllers', ['cesium.services', 'cesium.map.services']) + + .config(function(PluginServiceProvider, csConfig) { + 'ngInject'; + + var enable = csConfig.plugins && csConfig.plugins.es; + if (enable) { + + PluginServiceProvider + + .extendState('app.user_edit_profile', { + points: { + 'after-position': { + templateUrl: 'plugins/map/templates/user/edit_profile_extend.html', + controller: 'MapEditProfileViewCtrl' + } + } + }); + } + }) + + // [NEW] Manage events from the page #/app/wot/map + .controller('MapEditProfileViewCtrl', function($scope, $timeout, $q, MapUtils, $translate) { + 'ngInject'; + + var listeners = []; + $scope.mapId = 'map-user-profile-' + $scope.$id; + $scope.map = MapUtils.map({ + markers: {}, + center: { + zoom: 13 + }, + defaults: { + tileLayerOptions: { + attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>' + } + } + }); + $scope.loading = true; + + $scope.enter = function(e, state) { + + // Wait parent controller load the profile + if (!$scope.formData || !$scope.formData.title) { + return $timeout($scope.enter, 500); + } + + $scope.loading = true; + return $scope.load(); + }; + $scope.$on('$csExtension.enter', $scope.enter); + $scope.$on('$ionicParentView.enter', $scope.enter); + + $scope.load = function() { + + // no position define: remove existing listener + if (!$scope.formData.geoPoint || !$scope.formData.geoPoint.lat || !$scope.formData.geoPoint.lon) { + _.forEach(listeners, function(listener){ + listener(); // unlisten + }); + listeners = []; + delete $scope.map.markers.geoPoint; + $scope.loading = false; + return $q.when(); + } + + // If no marker exists on map: create it + if (!$scope.map.markers.geoPoint) { + + return $translate('MAP.PROFILE.MARKER_HELP') + .then(function(helpText) { + + + $scope.map.markers.geoPoint = { + message: helpText, + lat: parseFloat($scope.formData.geoPoint.lat), + lng: parseFloat($scope.formData.geoPoint.lon), + draggable: true, + focus: true + }; + angular.extend($scope.map.center, { + lat: $scope.map.markers.geoPoint.lat, + lng: $scope.map.markers.geoPoint.lng + }); + + // Listening changes + var listener = $scope.$watch('map.markers.geoPoint', function() { + if ($scope.loading) return; + if ($scope.map.markers.geoPoint && $scope.map.markers.geoPoint.lat && $scope.map.markers.geoPoint.lng) { + $scope.formData.geoPoint = $scope.formData.geoPoint || {}; + $scope.formData.geoPoint.lat = $scope.map.markers.geoPoint.lat; + $scope.formData.geoPoint.lon = $scope.map.markers.geoPoint.lng; + } + }, true); + listeners.push(listener); + + + // Make sure map appear, if shown later + if (!$scope.ionItemClass) { + $scope.ionItemClass = 'done in'; + } + + $scope.loading = false; + }); + } + + // Marker exists: update lat/lon + else { + $scope.map.markers.geoPoint.lat = $scope.formData.geoPoint.lat; + $scope.map.markers.geoPoint.lng = $scope.formData.geoPoint.lon; + } + }; + + + $scope.$watch('formData.geoPoint', function() { + if ($scope.loading) return; + $scope.load(); + }, true); + + }); diff --git a/www/plugins/map/js/controllers/wot-controllers.js b/www/plugins/map/js/controllers/wot-controllers.js index d7dbe85130a0e8f63f025b2ed2db7d4a20becace..a5dc55dd1b69aeb8c7f396e16087f20d29651b83 100644 --- a/www/plugins/map/js/controllers/wot-controllers.js +++ b/www/plugins/map/js/controllers/wot-controllers.js @@ -9,7 +9,6 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser PluginServiceProvider - // Extension de la vue d'une identité: ajout d'un bouton .extendState('app.wot_lookup', { points: { 'filter-buttons': { @@ -18,7 +17,6 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser } }); - // Wot map (default position) $stateProvider .state('app.view_wot_map', { url: "/wot/map?c¢er", @@ -43,7 +41,6 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser var // Create a hidden layer, to hold search markers markersSearchLayer = L.layerGroup({visible: false}), - loadingControl, searchControl, localizeMe, icons= { member: { type: 'awesomeMarker', @@ -119,19 +116,19 @@ angular.module('cesium.map.wot.controllers', ['cesium.services', 'cesium.map.ser if (!$scope.map.loading) return map; // already loaded // Add loading control - loadingControl = L.Control.loading({ + var loadingControl = L.Control.loading({ position: 'topright', separate: true }); loadingControl.addTo(map); // Add localize me control - localizeMe = MapUtils.control.localizeMe(); + var localizeMe = MapUtils.control.localizeMe(); localizeMe.addTo(map); // Add search control var searchTip = $interpolate($templateCache.get('plugins/map/templates/wot/item_search_tooltip.html')); - searchControl = MapUtils.control.search({ + var searchControl = MapUtils.control.search({ layer: markersSearchLayer, propertyName: 'title', buildTip: function (text, val) { diff --git a/www/plugins/map/js/plugin.js b/www/plugins/map/js/plugin.js index f3f2437335276cd885aed6b5554f675ce5991873..d5bef3326e9f246c3a391523c13e537fa277e5be 100644 --- a/www/plugins/map/js/plugin.js +++ b/www/plugins/map/js/plugin.js @@ -5,7 +5,8 @@ angular.module('cesium.map.plugin', [ 'cesium.map.services', // Controllers 'cesium.map.wot.controllers', - 'cesium.map.network.controllers' + 'cesium.map.network.controllers', + 'cesium.map.user.controllers' ]) // Configure plugin diff --git a/www/plugins/map/js/services/utils-services.js b/www/plugins/map/js/services/utils-services.js index 37ce44f95b6c96372a4f5f8b5254564e130d03fd..1e19a0c8b2756888faf2ef9f670e081317cf0e46 100644 --- a/www/plugins/map/js/services/utils-services.js +++ b/www/plugins/map/js/services/utils-services.js @@ -108,14 +108,14 @@ angular.module('cesium.map.utils.services', ['cesium.services', 'ui-leaflet']) options.zoom = angular.isDefined(options.zoom) ? options.zoom : constants.LOCALIZE_ZOOM; options.markerLocation = angular.isDefined(options.markerLocation) ? options.markerLocation : true; - var translatePromise = $translate(['MAP.WOT.VIEW.SEARCH_DOTS', 'COMMON.SEARCH_NO_RESULT']); + var translatePromise = $translate(['MAP.COMMON.SEARCH_DOTS', 'COMMON.SEARCH_NO_RESULT']); return { // Simulate an addTo function, but wait for end of translations job addTo: function (map) { translatePromise.then(function (translations) { L.control.search(angular.merge(options, { - textPlaceholder: translations['MAP.WOT.VIEW.SEARCH_DOTS'], + textPlaceholder: translations['MAP.COMMON.SEARCH_DOTS'], textErr: translations['COMMON.SEARCH_NO_RESULT'] })).addTo(map); }); diff --git a/www/plugins/map/templates/user/edit_profile_extend.html b/www/plugins/map/templates/user/edit_profile_extend.html new file mode 100644 index 0000000000000000000000000000000000000000..94757d48b558941d886263b51128d8d4586037da --- /dev/null +++ b/www/plugins/map/templates/user/edit_profile_extend.html @@ -0,0 +1,7 @@ +<div class="item no-padding {{ionItemClass}}" ng-if="formData.geoPoint && formData.geoPoint.lat && formData.geoPoint.lon"> + <leaflet height="250px" + center="map.center" + markers="map.markers" + defaults="map.defaults"> + </leaflet> +</div>