diff --git a/src/c3nav/editor/api.py b/src/c3nav/editor/api.py index b31de59d..fe1266bb 100644 --- a/src/c3nav/editor/api.py +++ b/src/c3nav/editor/api.py @@ -196,6 +196,7 @@ class EditorViewSet(ViewSet): space.lineobstacles.all(), space.columns.all(), space.altitudemarkers.all(), + space.wifi_measurements.all(), space.pois.filter(POI.q_for_request(request)).prefetch_related('groups'), other_spaces_upper, graphedges, @@ -224,6 +225,7 @@ class EditorViewSet(ViewSet): 'graphnode': '#009900', 'graphedge': '#00CC00', 'altitudemarker': '#0000FF', + 'wifimeasurement': '#DDDD00', }) @list_route(methods=['get']) diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index c9762ce1..af9b1f09 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -25,6 +25,10 @@ class EditorFormBase(I18nModelFormMixin, ModelForm): super().__init__(*args, **kwargs) creating = not self.instance.pk + if hasattr(self.instance, 'author_id'): + if self.instance.author_id is None: + self.instance.author = request.user + if 'level' in self.fields: # hide level widget self.fields['level'].widget = HiddenInput() @@ -186,7 +190,7 @@ def create_editor_form(editor_model): 'ordering', 'category', 'width', 'groups', 'color', 'priority', 'icon_name', 'base_altitude', 'waytype', 'access_restriction', 'height', 'default_height', 'door_height', 'outside', 'can_search', 'can_describe', 'geometry', 'single', 'altitude', 'short_label', - 'origin_space', 'target_space', + 'origin_space', 'target_space', 'data', 'comment', 'extra_seconds', 'speed', 'description', 'speed_up', 'description_up', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'left', 'top', 'right', 'bottom'] field_names = [field.name for field in editor_model._meta.get_fields() if not field.one_to_many] diff --git a/src/c3nav/editor/static/editor/css/editor.css b/src/c3nav/editor/static/editor/css/editor.css index f4a38409..fb9f2468 100644 --- a/src/c3nav/editor/static/editor/css/editor.css +++ b/src/c3nav/editor/static/editor/css/editor.css @@ -74,7 +74,8 @@ nav.navbar .navbar-nav > li > a { } /* sidebar contents */ -#sidebar form.creation-lock .btn.btn-primary { +#sidebar form.creation-lock [type=submit].btn.btn-primary, +#sidebar form.scan-lock [type=submit].btn.btn-primary{ display:none; } #sidebar h3 { @@ -317,3 +318,42 @@ h4 { .btn + .btn { margin-left: 5px; } + +textarea.form-control { + resize: none; + height: 75px; +} + +.wificollector { + padding: 10px; + height: auto; +} +body > .wificollector { + display: none; +} +.wificollector:not(.empty) .btn.start, +.wificollector:not(.running) .btn.stop, +.wificollector:not(.done) .btn.reset, +.wificollector.empty .count-line { + display: none; +} +.wificollector .btn { + margin: 0 5px 0 0; +} +.wificollector p { + height: 26px; + margin: 0; +} +.wificollector table { + width: 100%; +} +.wificollector table td { + padding: 5px 5px 0 0; +} +.wificollector table td:last-child { + padding-right: 0; + text-align: right; +} +.wificollector table tr td { + color: #666666; +} diff --git a/src/c3nav/editor/static/editor/js/editor.js b/src/c3nav/editor/static/editor/js/editor.js index 048c2196..8489fd8e 100644 --- a/src/c3nav/editor/static/editor/js/editor.js +++ b/src/c3nav/editor/static/editor/js/editor.js @@ -53,6 +53,7 @@ editor = { editor._sublevel_control_container = $(editor._sublevel_control._container); editor.init_geometries(); + editor.init_wificollector(); }, _onbeforeunload: function(e) { if ($('#sidebar').find('[data-onbeforeunload]').length) { @@ -229,6 +230,13 @@ editor = { editor._level_control.hide(); editor._sublevel_control.hide(); } + + var data_field = $('form [name=data]'); + if (data_field.length) { + data_field.hide(); + data_field.after($('body .wificollector')[0].outerHTML); + data_field.closest('form').addClass('scan-lock'); + } }, _sidebar_error: function(data) { $('#sidebar').removeClass('loading').find('.content').html('

Error '+data.status+'

'+data.statusText); @@ -256,7 +264,7 @@ editor = { _sidebar_submit: function(e) { // listener for form submits in the sidebar. e.preventDefault(); - if (editor._loading_geometry || $(this).is('.creation-lock')) return; + if (editor._loading_geometry || $(this).is('.creation-lock') || $(this).is('.scan-lock')) return; var data = $(this).serialize(); var btn = $(this).data('btn'); if (btn !== undefined && btn !== null) { @@ -829,9 +837,78 @@ editor = { if (editor._editing_layer !== null) { $('#id_geometry').val(JSON.stringify(editor._editing_layer.toGeoJSON().geometry)); } + }, + + init_wificollector: function () { + // init geometries and edit listeners + editor._highlight_layer = L.layerGroup().addTo(editor.map); + + $('#sidebar').on('click', '.wificollector .start', editor._wificollector_start) + .on('click', '.wificollector .stop', editor._wificollector_stop) + .on('click', '.wificollector .reset', editor._wificollector_reset); + editor._wificollector_scan_perhaps(); + }, + _wificollector_data: [], + _wificollector_start: function () { + var $collector = $('#sidebar').find('.wificollector'); + $collector.removeClass('empty').addClass('running'); + editor._wificollector_data = []; + $collector.find('.count').text(0); + }, + _wificollector_stop: function () { + var $collector = $('#sidebar').find('.wificollector'); + $collector.removeClass('running').delay(1000).queue(function(n) { + $(this).addClass('done'); + n(); + }); + $collector.closest('form').removeClass('scan-lock'); + }, + _wificollector_reset: function () { + var $collector = $('#sidebar').find('.wificollector'); + $collector.removeClass('done').addClass('empty').find('table').html(''); + $collector.siblings('[name=data]').val(''); + $collector.closest('form').addClass('scan-lock'); + }, + _wificollector_result: function(data) { + var $collector = $('#sidebar').find('.wificollector.running'), + $table = $collector.find('table'), + item, i, line, apid, color; + editor._wificollector_scan_perhaps(); + $table.find('tr').addClass('old'); + for (i=0; i < data.length; i++) { + item = data[i]; + apid = 'ap-'+item.bssid.replace(/:/g, '-'); + line = $table.find('tr.'+apid); + console.log(line); + color = Math.max(0, Math.min(50, item.level+80)) + color = 'rgb('+String(250-color*5)+', '+String(color*4)+', 0)'; + if (line.length) { + line.removeClass('old').find(':last-child').text(item.level).css('color', color); + } else { + line = $('').addClass(apid); + line.append($('').text(item.bssid)); + line.append($('').text(item.ssid)); + line.append($('').text(item.level).css('color', color)); + $table.append(line); + } + } + editor._wificollector_data.push(data); + $collector.find('.count').text(editor._wificollector_data.length); + $collector.siblings('[name=data]').val(JSON.stringify(editor._wificollector_data)); + }, + _wificollector_scan_perhaps: function() { + if ($('#sidebar').find('.wificollector.running').length) { + mobileclient.scanNow(); + } else { + window.setTimeout(editor._wificollector_scan_perhaps, 1000); + } } }; +function nearby_stations_available() { + editor._wificollector_result(JSON.parse(mobileclient.getNearbyStations())); +} + LevelControl = L.Control.extend({ options: { diff --git a/src/c3nav/editor/templates/editor/base.html b/src/c3nav/editor/templates/editor/base.html index 2f8705f1..531f3994 100644 --- a/src/c3nav/editor/templates/editor/base.html +++ b/src/c3nav/editor/templates/editor/base.html @@ -44,6 +44,16 @@ {% endblock %} +
+

+ {% trans 'Start scanning' %} + {% trans 'Stop scanning' %} + {% trans 'Reset scan results' %} + 0 scans +

+
+
+ {% include 'site/fragment_fakemobileclient.html' %} {% compress js %} diff --git a/src/c3nav/editor/urls.py b/src/c3nav/editor/urls.py index 9a0c1820..9c3a592f 100644 --- a/src/c3nav/editor/urls.py +++ b/src/c3nav/editor/urls.py @@ -68,3 +68,4 @@ urlpatterns.extend(add_editor_urls('POI', 'Space')) urlpatterns.extend(add_editor_urls('AltitudeMarker', 'Space')) urlpatterns.extend(add_editor_urls('LeaveDescription', 'Space')) urlpatterns.extend(add_editor_urls('CrossDescription', 'Space')) +urlpatterns.extend(add_editor_urls('WifiMeasurement', 'Space')) diff --git a/src/c3nav/editor/views/edit.py b/src/c3nav/editor/views/edit.py index 52cde339..911b4b26 100644 --- a/src/c3nav/editor/views/edit.py +++ b/src/c3nav/editor/views/edit.py @@ -89,7 +89,8 @@ def space_detail(request, level, pk): 'child_models': [child_model(request, model_name, kwargs={'space': pk}, parent=space) for model_name in ('POI', 'Area', 'Obstacle', 'LineObstacle', 'Stair', 'Ramp', 'Column', - 'Hole', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription')], + 'Hole', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription', + 'WifiMeasurement')], 'geometry_url': '/api/editor/geometries/?space='+pk, }) diff --git a/src/c3nav/editor/wrappers.py b/src/c3nav/editor/wrappers.py index d9da05f1..ee26363f 100644 --- a/src/c3nav/editor/wrappers.py +++ b/src/c3nav/editor/wrappers.py @@ -51,7 +51,7 @@ class BaseWrapper: return instance instance = instance._obj assert isinstance(instance, models.Model) - return self._wrap_model(type(instance)).create_wrapped_model_class()(self._changeset, instance) + return self._wrap_model(instance.__class__).create_wrapped_model_class()(self._changeset, instance) def _wrap_manager(self, manager): """