diff --git a/src/c3nav/editor/static/editor/js/editor.js b/src/c3nav/editor/static/editor/js/editor.js index 1baabac6..ce3fea59 100644 --- a/src/c3nav/editor/static/editor/js/editor.js +++ b/src/c3nav/editor/static/editor/js/editor.js @@ -93,16 +93,17 @@ editor = { // load sources editor._sources_control = L.control.layers([], [], { autoZIndex: false }); - $.getJSON('/api/sources/', function (sources) { - var source; - for (var i = 0; i < sources.length; i++) { - source = sources[i]; - editor.sources[source.id] = source; - source.layer = L.imageOverlay('/api/sources/'+source.id+'/image/', L.GeoJSON.coordsToLatLngs(source.bounds), {opacity: 0.3}); - editor._sources_control.addOverlay(source.layer, source.name); - } - if (sources.length) editor._sources_control.addTo(editor.map); - }); + c3nav_api.get('mapdata/sources') + .then(sources => { + var source; + for (var i = 0; i < sources.length; i++) { + source = sources[i]; + editor.sources[source.id] = source; + source.layer = L.imageOverlay('/api/sources/'+source.id+'/image/', L.GeoJSON.coordsToLatLngs(source.bounds), {opacity: 0.3}); + editor._sources_control.addOverlay(source.layer, source.name); + } + if (sources.length) editor._sources_control.addTo(editor.map); + }) }, // sidebar @@ -148,7 +149,7 @@ editor = { if (window.mobileclient && mobileclient.wificollectorStop && $('#sidebar').find('.wificollector.running').length) { mobileclient.wificollectorStop(); } - + $('#sidebar').addClass('loading').find('.content').html(''); editor._cancel_editing(); }, @@ -664,16 +665,19 @@ editor = { editor.map.on('zoomend', editor._adjust_line_zoom); - $.getJSON('/api/editor/geometrystyles/', function(geometrystyles) { - editor.geometrystyles = geometrystyles; - $.getJSON('/api/editor/bounds/', function(bounds) { - bounds = L.GeoJSON.coordsToLatLngs(bounds.bounds); - editor._max_bounds = bounds; - editor._set_max_bounds(); - editor.map.fitBounds(bounds, {padding: [30, 50]}); - editor.init_sidebar(); - }); - }); + c3nav_api.get('editor/geometrystyles') + .then(geometrystyles => { + editor.geometrystyles = geometrystyles; + c3nav_api.get('editor/bounds') + .then(bounds => { + bounds = L.GeoJSON.coordsToLatLngs(bounds.bounds); + editor._max_bounds = bounds; + editor._set_max_bounds(); + editor.map.fitBounds(bounds, {padding: [30, 50]}); + editor.init_sidebar(); + }) + }) + editor.get_sources(); }, _set_max_bounds: function(bounds) { @@ -703,102 +707,103 @@ editor = { editor._set_max_bounds(); if (same_url && editor._last_geometry_update_cache_key) { - geometry_url += '&update_cache_key='+editor._last_geometry_update_cache_key; + geometry_url += '?update_cache_key='+editor._last_geometry_update_cache_key; } - $.getJSON(geometry_url, function(result) { - var geometries = [], feature, new_cache = {}, feature_type, feature_id; - // geometries cache logic - for (var i=0;i { + var geometries = [], feature, new_cache = {}, feature_type, feature_id; + // geometries cache logic + for (var i=0;i'); - defs = editor.map.options.renderer._container.querySelector('defs'); - } else { - defs.innerHTML = ''; + editor._geometries_layer.addTo(editor.map); + editor._highlight_layer.addTo(editor.map); + editor._loading_geometry = false; + if (editor._bounds_layer === null && editor._geometries_layer.getLayers().length) editor._bounds_layer = editor._geometries_layer; + if (editor._next_zoom && editor._bounds_layer !== null) { + editor.map.flyToBounds((editor._bounds_layer.getBounds !== undefined) ? editor._bounds_layer.getBounds() : [editor._bounds_layer.getLatLng(), editor._bounds_layer.getLatLng()], { + maxZoom: Math.max(4, editor.map.getZoom()), + duration: 0.5, + padding: [20, 20] + }); } - for(i=0;i'); - } - } + editor._next_zoom = null; + editor.map.doubleClickZoom.enable(); - editor._check_start_editing(); - }); + editor._adjust_line_zoom(); + + if (editor.map.options.renderer._container !== undefined) { + var defs = editor.map.options.renderer._container.querySelector('defs'); + if (defs === null) { + editor.map.options.renderer._container.insertAdjacentHTML('afterbegin', ''); + defs = editor.map.options.renderer._container.querySelector('defs'); + } else { + defs.innerHTML = ''; + } + for(i=0;i'); + } + } + + editor._check_start_editing(); + }) }, reload_geometries: function () { if ($('body').is('.map-enabled') && editor._last_geometry_url !== null) { @@ -870,13 +875,13 @@ editor = { style.weight = 3; style.color = '#00ff00'; } - if (feature.properties.color !== undefined) { + if (feature.properties.color !== null) { style.fillColor = feature.properties.color; } if (feature.geometry.type === 'LineString') { style = editor._line_draw_geometry_style(style); } - if (feature.properties.opacity !== undefined) { + if (feature.properties.opacity !== null) { style.fillOpacity = feature.properties.opacity; } return style @@ -1402,5 +1407,5 @@ LevelControl = L.Control.extend({ if ($('#sidebar').length) { - editor.init(); + c3nav_api.authenticated().then(() => editor.init()); } diff --git a/src/c3nav/editor/templates/editor/base.html b/src/c3nav/editor/templates/editor/base.html index a5a250ea..74fffe23 100644 --- a/src/c3nav/editor/templates/editor/base.html +++ b/src/c3nav/editor/templates/editor/base.html @@ -79,6 +79,7 @@ + {% endcompress %} diff --git a/src/c3nav/editor/utils.py b/src/c3nav/editor/utils.py index cfc4915b..b661088e 100644 --- a/src/c3nav/editor/utils.py +++ b/src/c3nav/editor/utils.py @@ -34,7 +34,7 @@ class LevelChildEditUtils(DefaultEditUtils): @property def _geometry_url(self): - return '/api/editor/geometries/?level=' + str(self.level.primary_level_pk) + return '/api/v2/editor/geometries/level/' + str(self.level.primary_level_pk) class SpaceChildEditUtils(DefaultEditUtils): @@ -54,4 +54,4 @@ class SpaceChildEditUtils(DefaultEditUtils): @property def _geometry_url(self): - return '/api/editor/geometries/?space='+str(self.space.pk) + return '/api/v2/editor/geometries/space/'+str(self.space.pk) diff --git a/src/c3nav/editor/views/edit.py b/src/c3nav/editor/views/edit.py index b0394601..f0acad21 100644 --- a/src/c3nav/editor/views/edit.py +++ b/src/c3nav/editor/views/edit.py @@ -85,7 +85,7 @@ def level_detail(request, pk): 'child_models': [child_model(request, model_name, kwargs={'level': pk}, parent=level) for model_name in submodels], 'levels_on_top': level.levels_on_top.filter(Level.q_for_request(request)).all(), - 'geometry_url': ('/api/editor/geometries/?level='+str(level.primary_level_pk) + 'geometry_url': ('/api/v2/editor/geometries/level/'+str(level.primary_level_pk) if request.user_permissions.can_access_base_mapdata else None), }, fields=('level', 'can_edit_graph', 'can_create_level', 'child_models', 'levels_on_top')) @@ -596,7 +596,7 @@ def graph_edit(request, level=None, space=None): 'back_url': reverse('editor.levels.detail', kwargs={'pk': level.pk}), 'back_title': _('back to level'), 'level': level, - 'geometry_url': '/api/editor/geometries/?level='+str(level.primary_level_pk), + 'geometry_url': '/api/v2/editor/geometries/level/'+str(level.primary_level_pk), }) elif space is not None: queryset = Space.objects.filter(Space.q_for_request(request)).select_related('level').defer('geometry') @@ -609,7 +609,7 @@ def graph_edit(request, level=None, space=None): 'back_title': _('back to space'), 'parent_url': reverse('editor.levels.graph', kwargs={'level': level.pk}), 'parent_title': _('to level graph'), - 'geometry_url': '/api/editor/geometries/?space='+str(space.pk), + 'geometry_url': '/api/v2/editor/geometries/space/'+str(space.pk), }) create_nodes = True diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index 7fbae9ef..107f2820 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -137,16 +137,13 @@ c3nav = { _searchable_locations_timer: null, load_searchable_locations: function(firstTime) { c3nav._searchable_locations_timer = null; - $.ajax({ - dataType: "json", - url: '/api/locations/?searchable', - success: c3nav._searchable_locations_loaded, - ifModified: true, - }).fail(function() { - if(c3nav._searchable_locations_timer === null) { - c3nav._searchable_locations_timer = window.setTimeout(c3nav.load_searchable_locations, c3nav.init_completed ? 300000 : 15000); - } - }); + c3nav_api.get('map/locations?searchable=true') + .then(c3nav._searchable_locations_loaded) + .catch(() => { + if (c3nav._searchable_locations_timer === null) { + c3nav._searchable_locations_timer = window.setTimeout(c3nav.load_searchable_locations, c3nav.init_completed ? 300000 : 15000); + } + }); }, _sort_labels: function(a, b) { var result = (a[0].label_settings.min_zoom || -10) - (b[0].label_settings.min_zoom || -10); @@ -424,14 +421,15 @@ c3nav = { if ($location_details.attr('data-id') !== String(location.id)) { $location_details.addClass('loading').attr('data-id', location.id); c3nav._clear_route_layers(); - $.getJSON('/api/locations/'+location.id+'/details', c3nav._location_details_loaded).fail(function (data) { - var $location_details = $('#location-details'); - $location_details.find('.details-body').text('Error '+String(data.status)); - $location_details.find('.details-body').html('').append(elem); - $location_details.find('.editor').hide(); - $location_details.find('.report').hide(); - $location_details.removeClass('loading'); - }); + c3nav_api.get(`map/locations/${location.id}/display`).then(c3nav._location_details_loaded) + .catch(data => { + var $location_details = $('#location-details'); + $location_details.find('.details-body').text('Error ' + String(data.status)); + $location_details.find('.details-body').html('').append(elem); + $location_details.find('.editor').hide(); + $location_details.find('.report').hide(); + $location_details.removeClass('loading'); + }) } }, _location_details_loaded: function(data) { @@ -505,17 +503,13 @@ c3nav = { $route.addClass('loading').attr('data-origin', origin.id).attr('data-destination', destination.id); $details_wrapper.addClass('loading'); $options_wrapper.addClass('loading'); - $.post('/api/routing/route/', $.extend({ - 'origin': origin.id, - 'destination': destination.id, - 'csrfmiddlewaretoken': c3nav.get_csrf_token() - }, c3nav.next_route_options || {}), function(data) { - c3nav._route_loaded(data, nofly) - }, 'json').fail(function(data) { - c3nav._route_loaded({ - 'error': 'Error '+String(data.status) - }) - }); + c3nav_api.post('routing/route', { + origin: origin.id, + destination: destination.id, + ...(c3nav.next_route_options || {}), + }) + .then(data => c3nav._route_loaded(data, nofly)) + .catch(data => c3nav._route_loaded({error: `Error ${data.status}`})); } c3nav.next_route_options = null; }, @@ -824,7 +818,7 @@ c3nav = { options[$(this).attr('name')] = $(this).val(); }); if ($(this).is('.save')) { - $.post('/api/routing/options/', options); + c3nav_api.post('routing/options', options); } c3nav.next_route_options = options; c3nav.update_state(null, null, null, false); @@ -1443,30 +1437,32 @@ c3nav = { name = c3nav._latlng_to_name(latlng); c3nav._click_anywhere_popup = popup; popup.on('remove', function() { c3nav._click_anywhere_popup = null }).openOn(c3nav.map); - $.getJSON('/api/locations/'+name+'/', function(data) { - if (c3nav._click_anywhere_popup !== popup || !popup.isOpen()) return; - popup.remove(); - if (nearby) { - var $destination = $('#destination-input'); - c3nav._locationinput_set($destination, data); - c3nav.update_state(false, false, false, false, true); - } else { - newpopup = L.popup(c3nav._add_map_padding({ - className: 'location-popup', - maxWidth: 500 - }, 'autoPanPaddingTopLeft', 'autoPanPaddingBottomRight')); - var buttons = $('#location-popup-buttons').clone(); - buttons.find('.report-issue').remove(); - buttons.find('.report').attr('href', '/report/l/' + String(data.id) + '/'); - newpopup.setLatLng(latlng).setContent(c3nav._build_location_html(data) + buttons.html()); - c3nav._click_anywhere_popup = newpopup; - newpopup.on('remove', function () { - c3nav._click_anywhere_popup = null - }).openOn(c3nav.map); - } - }).fail(function() { - popup.remove(); - }); + c3nav_api.get(`map/locations/${name}/`) + .then(data => { + if (c3nav._click_anywhere_popup !== popup || !popup.isOpen()) return; + popup.remove(); + if (nearby) { + var $destination = $('#destination-input'); + c3nav._locationinput_set($destination, data); + c3nav.update_state(false, false, false, false, true); + } else { + newpopup = L.popup(c3nav._add_map_padding({ + className: 'location-popup', + maxWidth: 500 + }, 'autoPanPaddingTopLeft', 'autoPanPaddingBottomRight')); + var buttons = $('#location-popup-buttons').clone(); + buttons.find('.report-issue').remove(); + buttons.find('.report').attr('href', '/report/l/' + String(data.id) + '/'); + newpopup.setLatLng(latlng).setContent(c3nav._build_location_html(data) + buttons.html()); + c3nav._click_anywhere_popup = newpopup; + newpopup.on('remove', function () { + c3nav._click_anywhere_popup = null + }).openOn(c3nav.map); + } + }) + .catch(function() { + popup.remove(); + }); }, _map_moved: function () { c3nav.update_map_state(); @@ -1588,7 +1584,8 @@ c3nav = { } if (location.dynamic) { if (!('available' in location)) { - $.getJSON('/api/locations/dynamic/' + location.id + '/', c3nav._dynamic_location_loaded); + c3nav_api.get(`map/locations/dynamic/${location.id}/`) + .then(c3nav._dynamic_location_loaded); return; } else if (!location.available) { return; @@ -1605,7 +1602,7 @@ c3nav = { if (!no_geometry && c3nav._visible_map_locations.indexOf(location.id) === -1) { c3nav._visible_map_locations.push(location.id); - $.getJSON('/api/locations/' + location.id + '/geometry/', c3nav._location_geometry_loaded); + c3nav_api.get(`map/locations/${location.id}/geometry/`).then(c3nav._location_geometry_loaded); } if (!location.point) return; @@ -1675,12 +1672,14 @@ c3nav = { _fetch_updates_failure_count: 0, fetch_updates: function () { c3nav._fetch_updates_timer = null; - $.get('/api/updates/fetch/', c3nav._fetch_updates_callback).fail(function() { - c3nav._fetch_updates_failure_count++; - waittime = Math.min(5 + c3nav._fetch_updates_failure_count * 5, 120); - // console.log('fetch updates failed, retying in ' + waittime + 'sec'); - c3nav.schedule_fetch_updates(waittime*1000); - }); + c3nav_api.get('updates/fetch') + .then(c3nav._fetch_updates_callback) + .catch(() => { + c3nav._fetch_updates_failure_count++; + waittime = Math.min(5 + c3nav._fetch_updates_failure_count * 5, 120); + // console.log('fetch updates failed, retying in ' + waittime + 'sec'); + c3nav.schedule_fetch_updates(waittime*1000); + }); }, _fetch_updates_callback: function (data) { c3nav._fetch_updates_failure_count = 0; @@ -1782,21 +1781,12 @@ c3nav = { } c3nav._no_wifi_count = 0; - $.post({ - url: '/api/routing/locate/', - data: JSON.stringify(data), - dataType: 'json', - contentType: 'application/json', - beforeSend: function(xhrObj){ - xhrObj.setRequestHeader('X-CSRFToken', c3nav.get_csrf_token()); - }, - success: function(data) { - c3nav._set_user_location(data.location); - } - }).fail(function() { - c3nav._set_user_location(null); - c3nav._last_wifi_scan = Date.now() + 20000 - }); + c3nav_api.post('routing/locate', data) + .then(data => c3nav._set_user_location(data.location)) + .catch(() => { + c3nav._set_user_location(null); + c3nav._last_wifi_scan = Date.now() + 20000 + }); }, _current_user_location: null, _set_user_location: function(location) { diff --git a/src/c3nav/site/templates/site/map.html b/src/c3nav/site/templates/site/map.html index 4ff56833..a77270be 100644 --- a/src/c3nav/site/templates/site/map.html +++ b/src/c3nav/site/templates/site/map.html @@ -238,6 +238,7 @@ + {% endcompress %} {% endblock %} diff --git a/src/c3nav/static/c3nav/js/api.js b/src/c3nav/static/c3nav/js/api.js new file mode 100644 index 00000000..6fd2ab9f --- /dev/null +++ b/src/c3nav/static/c3nav/js/api.js @@ -0,0 +1,62 @@ +(function () { + + class C3NavApi { + token = 'anonymous'; + + constructor(base ) { + this.base = base; + this.auth_promise = fetch(this.base+'auth/session/', { + credentials: 'same-origin', + method: 'GET', + }) + .then(res => res.json()) + .then(data => { + this.token = data.token + }) + .catch(err => { + throw err; + }) + .then(_ => null); + } + + authenticated() { + return this.auth_promise; + } + + make_url(path) { + const url = new URL(path, this.base); + if (!url.pathname.endsWith('/')) { + url.pathname += '/'; + } + return url; + } + + get(path) { + return fetch(this.make_url(path), { + credentials: 'omit', + method: 'GET', + headers: { + 'Authorization': `Bearer ${this.token}`, + 'Accept': 'application/json' + } + }) + .then(res => res.json()) + } + + async post(path, data) { + return fetch(this.make_url(path), { + credentials: 'omit', + method: 'POST', + headers: { + 'Authorization': `Bearer ${this.token}`, + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + }) + .then(res => res.json()) + } + } + + window.c3nav_api = new C3NavApi(`${window.location.origin}/api/v2/`); +})(); \ No newline at end of file