Skip to content

Commit

Permalink
Merge 727bc2c into 6f98715
Browse files Browse the repository at this point in the history
  • Loading branch information
morrme committed Jul 4, 2020
2 parents 6f98715 + 727bc2c commit e888ab6
Show file tree
Hide file tree
Showing 31 changed files with 939 additions and 585 deletions.
11 changes: 2 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,13 @@ before_install:
- pip install -U $DJANGO
- pip install --no-cache-dir -U -r requirements-test.txt
- npm install -g jslint
- jslint django_loci/static/django-loci/js/*.js

install:
- pip install -e .

script:
- |
openwisp-utils-qa-checks \
--migration-path \
"./django_loci/migrations \
./django_loci/tests/testdeviceapp/migrations" \
--migration-module django_loci
- ./run-qa-checks
- pytest --cov=django_loci
- coverage run -a --source=django_loci runtests.py

after_success:
coveralls
after_success: coveralls
2 changes: 1 addition & 1 deletion conftest.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest


@pytest.fixture(scope='session')
@pytest.fixture(scope="session")
def django_db_modify_db_settings():
""" used to speed up pytest with django """
pass
12 changes: 9 additions & 3 deletions django_loci/admin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from django.contrib import admin

from .base.admin import (AbstractFloorPlanAdmin, AbstractFloorPlanForm, AbstractFloorPlanInline,
AbstractLocationAdmin, AbstractLocationForm, AbstractObjectLocationForm,
AbstractObjectLocationInline)
from .base.admin import (
AbstractFloorPlanAdmin,
AbstractFloorPlanForm,
AbstractFloorPlanInline,
AbstractLocationAdmin,
AbstractLocationForm,
AbstractObjectLocationForm,
AbstractObjectLocationInline,
)
from .models import FloorPlan, Location, ObjectLocation


Expand Down
2 changes: 2 additions & 0 deletions django_loci/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ def __setmodels__(self):
this method can be overridden in 3rd party apps
"""
from .models import Location

self.location_model = Location

def ready(self):
import leaflet

leaflet.app_settings['NO_GLOBALS'] = False
self.__setmodels__()
self._load_receivers()
Expand Down
195 changes: 123 additions & 72 deletions django_loci/base/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ class Meta:
exclude = tuple()

class Media:
js = ('admin/js/jquery.init.js',
'django-loci/js/loci.js',
'django-loci/js/floorplan-inlines.js',)
js = (
'admin/js/jquery.init.js',
'django-loci/js/loci.js',
'django-loci/js/floorplan-inlines.js',
)
css = {'all': ('django-loci/css/loci.css',)}


Expand All @@ -63,36 +65,46 @@ def get_urls(self):
# without having to change templates
app_label = 'django_loci'
return [
url(r'^(?P<pk>[^/]+)/json/$',
url(
r'^(?P<pk>[^/]+)/json/$',
self.admin_site.admin_view(self.json_view),
name='{0}_location_json'.format(app_label)),
url(r'^(?P<pk>[^/]+)/floorplans/json/$',
name='{0}_location_json'.format(app_label),
),
url(
r'^(?P<pk>[^/]+)/floorplans/json/$',
self.admin_site.admin_view(self.floorplans_json_view),
name='{0}_location_floorplans_json'.format(app_label))
name='{0}_location_floorplans_json'.format(app_label),
),
] + super().get_urls()

def json_view(self, request, pk):
instance = get_object_or_404(self.model, pk=pk)
return JsonResponse({
'name': instance.name,
'type': instance.type,
'is_mobile': instance.is_mobile,
'address': instance.address,
'geometry': json.loads(instance.geometry.json) if instance.geometry else None
})
return JsonResponse(
{
'name': instance.name,
'type': instance.type,
'is_mobile': instance.is_mobile,
'address': instance.address,
'geometry': json.loads(instance.geometry.json)
if instance.geometry
else None,
}
)

def floorplans_json_view(self, request, pk):
instance = get_object_or_404(self.model, pk=pk)
choices = []
for floorplan in instance.floorplan_set.all():
choices.append({
'id': floorplan.pk,
'str': str(floorplan),
'floor': floorplan.floor,
'image': floorplan.image.url,
'image_width': floorplan.image.width,
'image_height': floorplan.image.height,
})
choices.append(
{
'id': floorplan.pk,
'str': str(floorplan),
'floor': floorplan.floor,
'image': floorplan.image.url,
'image_width': floorplan.image.width,
'image_height': floorplan.image.height,
}
)
return JsonResponse({'choices': choices})


Expand All @@ -112,42 +124,55 @@ class AbstractObjectLocationForm(forms.ModelForm):
FORM_CHOICES = (
('', _('--- Please select an option ---')),
('new', _('New')),
('existing', _('Existing'))
('existing', _('Existing')),
)
LOCATION_TYPES = (
FORM_CHOICES[0],
AbstractLocation.LOCATION_TYPES[0],
AbstractLocation.LOCATION_TYPES[1]
AbstractLocation.LOCATION_TYPES[1],
)
location_selection = forms.ChoiceField(choices=FORM_CHOICES, required=False)
name = forms.CharField(label=_('Location name'),
max_length=75, required=False,
help_text=_get_field('name').help_text)
name = forms.CharField(
label=_('Location name'),
max_length=75,
required=False,
help_text=_get_field('name').help_text,
)
address = forms.CharField(max_length=128, required=False)
type = forms.ChoiceField(choices=LOCATION_TYPES, required=True,
help_text=_get_field('type').help_text)
is_mobile = forms.BooleanField(label=_get_field('is_mobile').verbose_name,
help_text=_get_field('is_mobile').help_text,
required=False)
type = forms.ChoiceField(
choices=LOCATION_TYPES, required=True, help_text=_get_field('type').help_text
)
is_mobile = forms.BooleanField(
label=_get_field('is_mobile').verbose_name,
help_text=_get_field('is_mobile').help_text,
required=False,
)
geometry = GeometryField(required=False)
floorplan_selection = forms.ChoiceField(required=False,
choices=FORM_CHOICES)
floorplan = UnvalidatedChoiceField(choices=((None, FORM_CHOICES[0][1]),),
required=False)
floorplan_selection = forms.ChoiceField(required=False, choices=FORM_CHOICES)
floorplan = UnvalidatedChoiceField(
choices=((None, FORM_CHOICES[0][1]),), required=False
)
floor = forms.IntegerField(required=False)
image = forms.ImageField(required=False,
widget=ImageWidget(thumbnail=False),
help_text=_('floor plan image'))
indoor = forms.CharField(max_length=64, required=False,
label=_('indoor position'),
widget=FloorPlanWidget)
image = forms.ImageField(
required=False,
widget=ImageWidget(thumbnail=False),
help_text=_('floor plan image'),
)
indoor = forms.CharField(
max_length=64,
required=False,
label=_('indoor position'),
widget=FloorPlanWidget,
)

class Meta:
exclude = tuple()

class Media:
js = ('admin/js/jquery.init.js',
'django-loci/js/loci.js',)
js = (
'admin/js/jquery.init.js',
'django-loci/js/loci.js',
)
css = {'all': ('django-loci/css/loci.css',)}

def __init__(self, *args, **kwargs):
Expand All @@ -158,23 +183,29 @@ def __init__(self, *args, **kwargs):
location = obj.location
floorplan = obj.floorplan
if location:
initial.update({
'location_selection': 'existing',
'type': location.type,
'is_mobile': location.is_mobile,
'name': location.name,
'address': location.address,
'geometry': location.geometry,
})
initial.update(
{
'location_selection': 'existing',
'type': location.type,
'is_mobile': location.is_mobile,
'name': location.name,
'address': location.address,
'geometry': location.geometry,
}
)
if floorplan:
initial.update({
'floorplan_selection': 'existing',
'floorplan': floorplan.pk,
'floor': floorplan.floor,
'image': floorplan.image
})
initial.update(
{
'floorplan_selection': 'existing',
'floorplan': floorplan.pk,
'floor': floorplan.floor,
'image': floorplan.image,
}
)
floorplan_choices = self.fields['floorplan'].choices
self.fields['floorplan'].choices = floorplan_choices + [(floorplan.pk, floorplan)]
self.fields['floorplan'].choices = floorplan_choices + [
(floorplan.pk, floorplan)
]
self.initial.update(initial)

@cached_property
Expand All @@ -189,8 +220,7 @@ def clean_floorplan(self):
floorplan_model = self.floorplan_model
type_ = self.cleaned_data.get('type')
floorplan_selection = self.cleaned_data.get('floorplan_selection')
if type_ != 'indoor' or floorplan_selection == 'new' or \
not floorplan_selection:
if type_ != 'indoor' or floorplan_selection == 'new' or not floorplan_selection:
return None
pk = self.cleaned_data['floorplan']
if not pk:
Expand All @@ -200,7 +230,9 @@ def clean_floorplan(self):
except floorplan_model.DoesNotExist:
raise ValidationError(_('Selected floorplan does not exist'))
if fl.location != self.cleaned_data['location']:
raise ValidationError(_('This floorplan is associated to a different location'))
raise ValidationError(
_('This floorplan is associated to a different location')
)
return fl

def clean(self):
Expand Down Expand Up @@ -274,6 +306,7 @@ class ObjectLocationMixin(TimeReadonlyAdminMixin):
mixed in with different inline classes (stacked, tabular).
If you need the generic inline look below.
"""

verbose_name = _('geographic information')
verbose_name_plural = verbose_name
raw_id_fields = ('location',)
Expand All @@ -282,21 +315,39 @@ class ObjectLocationMixin(TimeReadonlyAdminMixin):
template = 'admin/django_loci/location_inline.html'
fieldsets = (
(None, {'fields': ('location_selection',)}),
('Geographic coordinates', {
'classes': ('loci', 'coords'),
'fields': ('location', 'type', 'is_mobile',
'name', 'address', 'geometry'),
}),
('Indoor coordinates', {
'classes': ('indoor', 'coords'),
'fields': ('floorplan_selection', 'floorplan',
'floor', 'image', 'indoor',),
})
(
'Geographic coordinates',
{
'classes': ('loci', 'coords'),
'fields': (
'location',
'type',
'is_mobile',
'name',
'address',
'geometry',
),
},
),
(
'Indoor coordinates',
{
'classes': ('indoor', 'coords'),
'fields': (
'floorplan_selection',
'floorplan',
'floor',
'image',
'indoor',
),
},
),
)


class AbstractObjectLocationInline(ObjectLocationMixin, GenericStackedInline):
"""
Generic Inline + ObjectLocationMixin
"""

pass

0 comments on commit e888ab6

Please sign in to comment.