diff --git a/layers/admin.py b/layers/admin.py index 2d7febf..3d0864e 100644 --- a/layers/admin.py +++ b/layers/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin from .models import * from django import forms +import nested_admin # Register your models here. @@ -45,162 +46,141 @@ def label_from_instance(self, obj): -# class LayerForm(forms.ModelForm): +class LayerForm(forms.ModelForm): -# order = forms.IntegerField(required=False) -# themes = ThemeChoiceField(queryset=Theme.all_objects.all().filter(layer_type=''), required=False, widget = admin.widgets.FilteredSelectMultiple('themes', False)) -# is_sublayer = forms.BooleanField(required=False) -# has_companion = forms.BooleanField(required=False) -# sublayers = SublayerChoiceField(queryset=Layer.all_objects.all(), required=False, widget = admin.widgets.FilteredSelectMultiple('sublayers', False)) -# companion_layers = CompanionLayerChoiceField(queryset=Layer.all_objects.all(), required=False, widget = admin.widgets.FilteredSelectMultiple('companion layers', False)) -# class Meta: -# exclude = ('slug_name',) -# model = Layer -# fields = '__all__' -# widgets = { + order = forms.IntegerField(required=False) + themes = ThemeChoiceField(queryset=Theme.all_objects.all().filter(layer_type=''), required=False, widget = admin.widgets.FilteredSelectMultiple('themes', False)) + is_sublayer = forms.BooleanField(required=False) + has_companion = forms.BooleanField(required=False) + sublayers = SublayerChoiceField(queryset=Layer.all_objects.all(), required=False, widget = admin.widgets.FilteredSelectMultiple('sublayers', False)) + companion_layers = CompanionLayerChoiceField(queryset=Layer.all_objects.all(), required=False, widget = admin.widgets.FilteredSelectMultiple('companion layers', False)) + class Meta: + exclude = ('slug_name',) + model = Layer + fields = '__all__' + widgets = { -# 'attribute_fields': admin.widgets.FilteredSelectMultiple('Attribute fields', False), -# 'lookup_table': admin.widgets.FilteredSelectMultiple('Lookup table', False), -# } + 'attribute_fields': admin.widgets.FilteredSelectMultiple('Attribute fields', False), + 'lookup_table': admin.widgets.FilteredSelectMultiple('Lookup table', False), + } +class ArcRESTInline(nested_admin.NestedTabularInline): + model = LayerArcREST -# def save(self, commit=True): -# # Save the Layer instance first -# layer = super().save(commit=commit) - -# # Now save or update the related ChildOrder instance or other related data -# # This is simplified; you'd likely need more logic here -# ChildOrder.objects.update_or_create( -# content_object=layer, -# defaults={'order': self.cleaned_data['order']} -# ) -# # Handle other fields similarly - -# return layer -# class LayerArcRESTForm(LayerForm): -# class Meta: -# model = LayerArcREST -# fields = ['arcgis_layers', 'password_protected', 'query_by_point', 'disable_arcgis_attributes'] -# class LayerAdmin(admin.ModelAdmin): -# def get_parent_theme(self, obj): -# # Fetch the ContentType for the Layer model -# content_type = ContentType.objects.get_for_model(obj) +class WMSInline(admin.StackedInline): + model = LayerWMS + +class XYZInline(admin.StackedInline): + model = LayerXYZ + +class VectorInline(admin.StackedInline): + model = LayerVector + +class LayerAdmin(admin.ModelAdmin): + def get_parent_theme(self, obj): + # Fetch the ContentType for the Layer model + content_type = ContentType.objects.get_for_model(obj) -# # Try to fetch the corresponding ChildOrder for this Layer -# child_order = ChildOrder.objects.filter(content_type=content_type, object_id=obj.pk).first() + # Try to fetch the corresponding ChildOrder for this Layer + child_order = ChildOrder.objects.filter(content_type=content_type, object_id=obj.pk).first() -# # Return the name of the parent theme if exists -# return child_order.parent_theme.name if child_order and child_order.parent_theme else 'None' -# get_parent_theme.short_description = 'Theme' # Sets column name + # Return the name of the parent theme if exists + return child_order.parent_theme.name if child_order and child_order.parent_theme else 'None' + get_parent_theme.short_description = 'Theme' # Sets column name -# def get_order(self, obj): -# # Fetch the ContentType for the Layer model -# content_type = ContentType.objects.get_for_model(obj) + def get_order(self, obj): + # Fetch the ContentType for the Layer model + content_type = ContentType.objects.get_for_model(obj) -# # Try to fetch the corresponding ChildOrder for this Layer -# child_order = ChildOrder.objects.filter(content_type=content_type, object_id=obj.pk).first() + # Try to fetch the corresponding ChildOrder for this Layer + child_order = ChildOrder.objects.filter(content_type=content_type, object_id=obj.pk).first() -# # Return the order if exists -# return child_order.order if child_order else 'None' -# get_order.short_description = 'Order' # Sets column name - -# def get_form(self, request, obj=None, **kwargs): -# # Dynamically set the form class based on the layer_type -# if obj and obj.layer_type == 'ArcRest': -# kwargs['form'] = LayerArcRESTForm -# else: -# kwargs['form'] = LayerForm -# return super().get_form(request, obj, **kwargs) - -# def get_fieldsets(self, request, obj=None): -# # Dynamically return fieldsets based on the layer_type -# if obj and obj.layer_type == 'ArcRest': -# # No need to modify self.fieldsets; directly return the combined fieldsets -# return self.base_fieldsets + self.arcrest_fieldsets -# return self.base_fieldsets -# list_display = ('name', 'layer_type', 'date_modified', "get_parent_theme", "get_order", 'data_publish_date', 'data_source') -# search_fields = ['name', 'layer_type', 'date_modified', 'url', 'data_source'] -# ordering = ('name', ) -# exclude = ('slug_name',) -# class Media: -# js = ['layer_admin.js',] - -# if settings.CATALOG_TECHNOLOGY not in ['default', None]: -# # catalog_fields = ('catalog_name', 'catalog_id',) -# # catalog_fields = 'catalog_name' -# basic_fields = ( -# 'catalog_name', -# ('name','layer_type',), -# ('url', 'proxy_url'), -# 'site' -# ) -# else: -# basic_fields = ( -# ('name','layer_type',), -# ('url', 'proxy_url'), -# 'site' -# ) -# base_fieldsets = ( -# ('BASIC INFO', { -# 'fields': basic_fields -# }), -# ('LAYER ORGANIZATION', { -# # 'classes': ('collapse', 'open',), -# 'fields': ( -# ('order','themes'), -# ('is_sublayer','sublayers'), -# ('has_companion','companion_layers'), -# # RDH 2019-10-25: We don't use this, and it doesn't seem helpful -# # ('is_disabled','disabled_message') -# ) -# }), -# ('METADATA', { -# 'classes': ('collapse',), -# 'fields': ( -# 'description', 'overview','data_source','data_notes', 'data_publish_date' -# ) -# }), -# ('LEGEND', { -# 'classes': ('collapse',), -# 'fields': ( -# 'show_legend', -# 'legend', -# ('legend_title','legend_subtitle') -# ) -# }), -# ('LINKS', { -# 'classes': ('collapse',), -# 'fields': ( -# ('metadata','source'), -# ('bookmark', 'kml'), -# ('data_download','learn_more'), -# ('map_tiles'), -# ) -# }), -# ('SHARING', { -# 'classes': ('collapse',), -# 'fields': ( -# 'shareable_url', -# ) -# }),) -# arcrest_fieldsets = ( -# ('ArcGIS DETAILS', { -# 'classes': ('collapse',), -# 'fields': ( -# ('arcgis_layers', 'password_protected', 'query_by_point', 'disable_arcgis_attributes'), -# ) -# }), -# ) + # Return the order if exists + return child_order.order if child_order else 'None' + get_order.short_description = 'Order' # Sets column name + + def get_fieldsets(self, request, obj=None): + # Dynamically return fieldsets based on the layer_type + if obj and obj.layer_type == 'ArcRest': + # No need to modify self.fieldsets; directly return the combined fieldsets + return self.base_fieldsets + self.arcrest_fieldsets + return self.base_fieldsets + list_display = ('name', 'layer_type', 'date_modified', "get_parent_theme", "get_order", 'data_publish_date', 'data_source') + search_fields = ['name', 'layer_type', 'date_modified', 'url', 'data_source'] + ordering = ('name', ) + exclude = ('slug_name',) + class Media: + js = ['layer_admin.js',] + + if settings.CATALOG_TECHNOLOGY not in ['default', None]: + # catalog_fields = ('catalog_name', 'catalog_id',) + # catalog_fields = 'catalog_name' + basic_fields = ( + 'catalog_name', + ('name','layer_type',), + ('url', 'proxy_url'), + 'site' + ) + else: + basic_fields = ( + ('name','layer_type',), + ('url', 'proxy_url'), + 'site' + ) + base_fieldsets = ( + ('BASIC INFO', { + 'fields': basic_fields + }), + ('LAYER ORGANIZATION', { + # 'classes': ('collapse', 'open',), + 'fields': ( + ('order','themes'), + ('is_sublayer','sublayers'), + ('has_companion','companion_layers'), + # RDH 2019-10-25: We don't use this, and it doesn't seem helpful + # ('is_disabled','disabled_message') + ) + }), + ('METADATA', { + 'classes': ('collapse',), + 'fields': ( + 'description', 'overview','data_source','data_notes', 'data_publish_date' + ) + }), + ('LEGEND', { + 'classes': ('collapse',), + 'fields': ( + 'show_legend', + 'legend', + ('legend_title','legend_subtitle') + ) + }), + ('LINKS', { + 'classes': ('collapse',), + 'fields': ( + ('metadata','source'), + ('bookmark', 'kml'), + ('data_download','learn_more'), + ('map_tiles'), + ) + }), + ('SHARING', { + 'classes': ('collapse',), + 'fields': ( + 'shareable_url', + ) + }),) + inlines = [ArcRESTInline, WMSInline, XYZInline, VectorInline] -# def get_queryset(self, request): -# # use our manager, rather than the default one -# qs = self.model.all_objects.get_queryset() - -# # we need this from the superclass method -# ordering = self.ordering or () # otherwise we might try to *None, which is bad ;) -# if ordering: -# qs = qs.order_by(*ordering) -# return qs + def get_queryset(self, request): + # use our manager, rather than the default one + qs = self.model.all_objects.get_queryset() + + # we need this from the superclass method + ordering = self.ordering or () # otherwise we might try to *None, which is bad ;) + if ordering: + qs = qs.order_by(*ordering) + return qs # if hasattr(settings, 'DATA_MANAGER_ADMIN'): # admin.site.register(Theme, ThemeAdmin) diff --git a/layers/migrations/0002_auto_20240207_1925.py b/layers/migrations/0002_auto_20240214_1825.py similarity index 91% rename from layers/migrations/0002_auto_20240207_1925.py rename to layers/migrations/0002_auto_20240214_1825.py index 31530c1..dbfe6c9 100644 --- a/layers/migrations/0002_auto_20240207_1925.py +++ b/layers/migrations/0002_auto_20240214_1825.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.23 on 2024-02-07 19:25 +# Generated by Django 3.2.23 on 2024-02-14 18:25 import colorfield.fields import django.contrib.sites.managers @@ -30,116 +30,6 @@ class Migration(migrations.Migration): ('preserve_format', models.BooleanField(default=False, help_text='Prevent portal from making any changes to the data to make it human-readable')), ], ), - migrations.CreateModel( - name='LayerArcFeatureService', - fields=[ - ('layer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='layers.layer')), - ('custom_style', models.CharField(blank=True, choices=[(None, '------'), ('color', 'color'), ('random', 'random')], default=None, help_text="Apply a custom styling rule: i.e. 'color' for Native-Land.ca layers, or 'random' to assign arbitary colors", max_length=255, null=True)), - ('outline_width', models.IntegerField(blank=True, default=None, null=True, verbose_name='Vector Stroke Width')), - ('outline_color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Stroke Color')), - ('outline_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Stroke Opacity')), - ('fill_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Fill Opacity')), - ('color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Fill Color')), - ('point_radius', models.IntegerField(blank=True, default=None, help_text='Used only for for Point layers (default is 2)', null=True)), - ('graphic', models.CharField(blank=True, default=None, help_text='address of image to use for point data', max_length=255, null=True, verbose_name='Vector Graphic')), - ('graphic_scale', models.FloatField(blank=True, default=1.0, help_text='Scale for the vector graphic from original size.', null=True, verbose_name='Vector Graphic Scale')), - ('opacity', models.FloatField(blank=True, default=0.5, null=True, verbose_name='Initial Opacity')), - ('arcgis_layers', models.CharField(blank=True, help_text='comma separated list of arcgis layer IDs', max_length=255, null=True)), - ('password_protected', models.BooleanField(default=False, help_text='check this if the server requires a password to show layers')), - ('disable_arcgis_attributes', models.BooleanField(default=False, help_text='Click to disable clickable ArcRest layers')), - ], - options={ - 'abstract': False, - }, - bases=('layers.layer',), - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager('site')), - ('all_objects', layers.models.AllObjectsManager()), - ], - ), - migrations.CreateModel( - name='LayerArcREST', - fields=[ - ('layer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='layers.layer')), - ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), - ('arcgis_layers', models.CharField(blank=True, help_text='comma separated list of arcgis layer IDs', max_length=255, null=True)), - ('password_protected', models.BooleanField(default=False, help_text='check this if the server requires a password to show layers')), - ('disable_arcgis_attributes', models.BooleanField(default=False, help_text='Click to disable clickable ArcRest layers')), - ], - options={ - 'abstract': False, - }, - bases=('layers.layer',), - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager('site')), - ('all_objects', layers.models.AllObjectsManager()), - ], - ), - migrations.CreateModel( - name='LayerVector', - fields=[ - ('layer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='layers.layer')), - ('custom_style', models.CharField(blank=True, choices=[(None, '------'), ('color', 'color'), ('random', 'random')], default=None, help_text="Apply a custom styling rule: i.e. 'color' for Native-Land.ca layers, or 'random' to assign arbitary colors", max_length=255, null=True)), - ('outline_width', models.IntegerField(blank=True, default=None, null=True, verbose_name='Vector Stroke Width')), - ('outline_color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Stroke Color')), - ('outline_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Stroke Opacity')), - ('fill_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Fill Opacity')), - ('color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Fill Color')), - ('point_radius', models.IntegerField(blank=True, default=None, help_text='Used only for for Point layers (default is 2)', null=True)), - ('graphic', models.CharField(blank=True, default=None, help_text='address of image to use for point data', max_length=255, null=True, verbose_name='Vector Graphic')), - ('graphic_scale', models.FloatField(blank=True, default=1.0, help_text='Scale for the vector graphic from original size.', null=True, verbose_name='Vector Graphic Scale')), - ('opacity', models.FloatField(blank=True, default=0.5, null=True, verbose_name='Initial Opacity')), - ], - options={ - 'abstract': False, - }, - bases=('layers.layer',), - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager('site')), - ('all_objects', layers.models.AllObjectsManager()), - ], - ), - migrations.CreateModel( - name='LayerWMS', - fields=[ - ('layer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='layers.layer')), - ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), - ('wms_help', models.BooleanField(default=False, help_text='Enable simple selection for WMS fields. Only supports WMS 1.1.1')), - ('wms_slug', models.CharField(blank=True, max_length=255, null=True, verbose_name='WMS Layer Name')), - ('wms_version', models.CharField(blank=True, choices=[(None, ''), ('1.0.0', '1.0.0'), ('1.1.0', '1.1.0'), ('1.1.1', '1.1.1'), ('1.3.0', '1.3.0')], default=None, help_text='WMS Versioning - usually either 1.1.1 or 1.3.0', max_length=10, null=True)), - ('wms_format', models.CharField(blank=True, default=None, help_text='most common: image/png. Only image types supported.', max_length=100, null=True, verbose_name='WMS Format')), - ('wms_srs', models.CharField(blank=True, default=None, help_text='If not EPSG:3857 WMS requests will be proxied', max_length=100, null=True, verbose_name='WMS SRS')), - ('wms_timing', models.CharField(blank=True, default=None, help_text='http://docs.geoserver.org/stable/en/user/services/wms/time.html#specifying-a-time', max_length=255, null=True, verbose_name='WMS Time')), - ('wms_time_item', models.CharField(blank=True, default=None, help_text='Time Attribute Field, if different from "TIME". Proxy only.', max_length=255, null=True, verbose_name='WMS Time Field')), - ('wms_styles', models.CharField(blank=True, default=None, help_text='pre-determined styles, if exist', max_length=255, null=True, verbose_name='WMS Styles')), - ('wms_additional', models.TextField(blank=True, default='', help_text='additional WMS key-value pairs: &key=value...', null=True, verbose_name='WMS Additional Fields')), - ('wms_info', models.BooleanField(default=False, help_text='enable Feature Info requests on click')), - ('wms_info_format', models.CharField(blank=True, default=None, help_text='Available supported feature info formats', max_length=255, null=True)), - ], - options={ - 'abstract': False, - }, - bases=('layers.layer',), - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager('site')), - ('all_objects', layers.models.AllObjectsManager()), - ], - ), - migrations.CreateModel( - name='LayerXYZ', - fields=[ - ('layer_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='layers.layer')), - ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), - ], - options={ - 'abstract': False, - }, - bases=('layers.layer',), - managers=[ - ('objects', django.contrib.sites.managers.CurrentSiteManager('site')), - ('all_objects', layers.models.AllObjectsManager()), - ], - ), migrations.CreateModel( name='Library', fields=[ @@ -421,16 +311,6 @@ class Migration(migrations.Migration): name='uuid', field=models.UUIDField(default=uuid.uuid4, unique=True), ), - migrations.AddField( - model_name='theme', - name='data_notes', - field=models.TextField(blank=True, default=''), - ), - migrations.AddField( - model_name='theme', - name='data_source', - field=models.CharField(blank=True, max_length=255, null=True), - ), migrations.AddField( model_name='theme', name='date_created', @@ -453,6 +333,41 @@ class Migration(migrations.Migration): field=models.CharField(default='test', max_length=100), preserve_default=False, ), + migrations.AddField( + model_name='theme', + name='factsheet_link', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='theme', + name='factsheet_thumb', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='theme', + name='feature_excerpt', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='theme', + name='feature_image', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='theme', + name='feature_link', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='theme', + name='header_attrib', + field=models.CharField(blank=True, max_length=255, null=True), + ), + migrations.AddField( + model_name='theme', + name='header_image', + field=models.CharField(blank=True, max_length=255, null=True), + ), migrations.AddField( model_name='theme', name='is_visible', @@ -461,8 +376,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='theme', name='layer_type', - field=models.CharField(choices=[('radio', 'radio'), ('checkbox', 'checkbox')], default='arcgis', help_text='use placeholder to temporarily remove layer from TOC', max_length=50), - preserve_default=False, + field=models.CharField(blank=True, choices=[('radio', 'radio'), ('checkbox', 'checkbox')], help_text='use placeholder to temporarily remove layer from TOC', max_length=50), ), migrations.AddField( model_name='theme', @@ -486,8 +400,8 @@ class Migration(migrations.Migration): ), migrations.AddField( model_name='theme', - name='source', - field=models.CharField(blank=True, help_text='link back to the data source', max_length=255, null=True), + name='thumbnail', + field=models.URLField(blank=True, max_length=255, null=True), ), migrations.AddField( model_name='theme', @@ -524,6 +438,96 @@ class Migration(migrations.Migration): name='parentLayer', field=models.ForeignKey(db_column='parentlayer', on_delete=django.db.models.deletion.CASCADE, related_name='parent_layer', to='layers.layer'), ), + migrations.CreateModel( + name='LayerXYZ', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), + ('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layers.layer')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LayerWMS', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), + ('wms_help', models.BooleanField(default=False, help_text='Enable simple selection for WMS fields. Only supports WMS 1.1.1')), + ('wms_slug', models.CharField(blank=True, max_length=255, null=True, verbose_name='WMS Layer Name')), + ('wms_version', models.CharField(blank=True, choices=[(None, ''), ('1.0.0', '1.0.0'), ('1.1.0', '1.1.0'), ('1.1.1', '1.1.1'), ('1.3.0', '1.3.0')], default=None, help_text='WMS Versioning - usually either 1.1.1 or 1.3.0', max_length=10, null=True)), + ('wms_format', models.CharField(blank=True, default=None, help_text='most common: image/png. Only image types supported.', max_length=100, null=True, verbose_name='WMS Format')), + ('wms_srs', models.CharField(blank=True, default=None, help_text='If not EPSG:3857 WMS requests will be proxied', max_length=100, null=True, verbose_name='WMS SRS')), + ('wms_timing', models.CharField(blank=True, default=None, help_text='http://docs.geoserver.org/stable/en/user/services/wms/time.html#specifying-a-time', max_length=255, null=True, verbose_name='WMS Time')), + ('wms_time_item', models.CharField(blank=True, default=None, help_text='Time Attribute Field, if different from "TIME". Proxy only.', max_length=255, null=True, verbose_name='WMS Time Field')), + ('wms_styles', models.CharField(blank=True, default=None, help_text='pre-determined styles, if exist', max_length=255, null=True, verbose_name='WMS Styles')), + ('wms_additional', models.TextField(blank=True, default='', help_text='additional WMS key-value pairs: &key=value...', null=True, verbose_name='WMS Additional Fields')), + ('wms_info', models.BooleanField(default=False, help_text='enable Feature Info requests on click')), + ('wms_info_format', models.CharField(blank=True, default=None, help_text='Available supported feature info formats', max_length=255, null=True)), + ('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layers.layer')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LayerVector', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('custom_style', models.CharField(blank=True, choices=[(None, '------'), ('color', 'color'), ('random', 'random')], default=None, help_text="Apply a custom styling rule: i.e. 'color' for Native-Land.ca layers, or 'random' to assign arbitary colors", max_length=255, null=True)), + ('outline_width', models.IntegerField(blank=True, default=None, null=True, verbose_name='Vector Stroke Width')), + ('outline_color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Stroke Color')), + ('outline_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Stroke Opacity')), + ('fill_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Fill Opacity')), + ('color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Fill Color')), + ('point_radius', models.IntegerField(blank=True, default=None, help_text='Used only for for Point layers (default is 2)', null=True)), + ('graphic', models.CharField(blank=True, default=None, help_text='address of image to use for point data', max_length=255, null=True, verbose_name='Vector Graphic')), + ('graphic_scale', models.FloatField(blank=True, default=1.0, help_text='Scale for the vector graphic from original size.', null=True, verbose_name='Vector Graphic Scale')), + ('opacity', models.FloatField(blank=True, default=0.5, null=True, verbose_name='Initial Opacity')), + ('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layers.layer')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LayerArcREST', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('query_by_point', models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)')), + ('arcgis_layers', models.CharField(blank=True, help_text='comma separated list of arcgis layer IDs', max_length=255, null=True)), + ('password_protected', models.BooleanField(default=False, help_text='check this if the server requires a password to show layers')), + ('disable_arcgis_attributes', models.BooleanField(default=False, help_text='Click to disable clickable ArcRest layers')), + ('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layers.layer')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LayerArcFeatureService', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('custom_style', models.CharField(blank=True, choices=[(None, '------'), ('color', 'color'), ('random', 'random')], default=None, help_text="Apply a custom styling rule: i.e. 'color' for Native-Land.ca layers, or 'random' to assign arbitary colors", max_length=255, null=True)), + ('outline_width', models.IntegerField(blank=True, default=None, null=True, verbose_name='Vector Stroke Width')), + ('outline_color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Stroke Color')), + ('outline_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Stroke Opacity')), + ('fill_opacity', models.FloatField(blank=True, default=None, null=True, verbose_name='Vector Fill Opacity')), + ('color', colorfield.fields.ColorField(blank=True, default=None, image_field=None, max_length=25, null=True, samples=[('#FFFFFF', 'white'), ('#888888', 'gray'), ('#000000', 'black'), ('#FF0000', 'red'), ('#FFFF00', 'yellow'), ('#00FF00', 'green'), ('#00FFFF', 'cyan'), ('#0000FF', 'blue'), ('#FF00FF', 'magenta')], verbose_name='Vector Fill Color')), + ('point_radius', models.IntegerField(blank=True, default=None, help_text='Used only for for Point layers (default is 2)', null=True)), + ('graphic', models.CharField(blank=True, default=None, help_text='address of image to use for point data', max_length=255, null=True, verbose_name='Vector Graphic')), + ('graphic_scale', models.FloatField(blank=True, default=1.0, help_text='Scale for the vector graphic from original size.', null=True, verbose_name='Vector Graphic Scale')), + ('opacity', models.FloatField(blank=True, default=0.5, null=True, verbose_name='Initial Opacity')), + ('arcgis_layers', models.CharField(blank=True, help_text='comma separated list of arcgis layer IDs', max_length=255, null=True)), + ('password_protected', models.BooleanField(default=False, help_text='check this if the server requires a password to show layers')), + ('disable_arcgis_attributes', models.BooleanField(default=False, help_text='Click to disable clickable ArcRest layers')), + ('layer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='layers.layer')), + ], + options={ + 'abstract': False, + }, + ), migrations.CreateModel( name='Companionship', fields=[ diff --git a/layers/migrations/0003_auto_20240207_2012.py b/layers/migrations/0003_auto_20240207_2012.py deleted file mode 100644 index da6f765..0000000 --- a/layers/migrations/0003_auto_20240207_2012.py +++ /dev/null @@ -1,65 +0,0 @@ -# Generated by Django 3.2.23 on 2024-02-07 20:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('layers', '0002_auto_20240207_1925'), - ] - - operations = [ - migrations.RemoveField( - model_name='theme', - name='data_notes', - ), - migrations.RemoveField( - model_name='theme', - name='data_source', - ), - migrations.RemoveField( - model_name='theme', - name='source', - ), - migrations.AddField( - model_name='theme', - name='factsheet_link', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='factsheet_thumb', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='feature_excerpt', - field=models.TextField(blank=True, null=True), - ), - migrations.AddField( - model_name='theme', - name='feature_image', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='feature_link', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='header_attrib', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='header_image', - field=models.CharField(blank=True, max_length=255, null=True), - ), - migrations.AddField( - model_name='theme', - name='thumbnail', - field=models.URLField(blank=True, max_length=255, null=True), - ), - ] diff --git a/layers/migrations/0004_alter_theme_layer_type.py b/layers/migrations/0004_alter_theme_layer_type.py deleted file mode 100644 index f4afc04..0000000 --- a/layers/migrations/0004_alter_theme_layer_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.23 on 2024-02-07 20:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('layers', '0003_auto_20240207_2012'), - ] - - operations = [ - migrations.AlterField( - model_name='theme', - name='layer_type', - field=models.CharField(blank=True, choices=[('radio', 'radio'), ('checkbox', 'checkbox')], help_text='use placeholder to temporarily remove layer from TOC', max_length=50), - ), - ] diff --git a/layers/models.py b/layers/models.py index cb58adc..03cc03d 100644 --- a/layers/models.py +++ b/layers/models.py @@ -348,7 +348,13 @@ class Companionship(models.Model): # (Each companionship can relate to multiple Layers and vice versa) companions = models.ManyToManyField(Layer, related_name='companion_to') -class VectorType(Layer): +class LayerType(models.Model): + layer = models.ForeignKey(Layer, on_delete=models.CASCADE) + + class Meta: + abstract = True + +class VectorType(LayerType): CUSTOM_STYLE_CHOICES = ( (None, '------'), ('color', 'color'), @@ -406,13 +412,13 @@ class VectorType(Layer): class Meta: abstract = True -class RasterType(Layer): +class RasterType(LayerType): query_by_point = models.BooleanField(default=False, help_text='Do not buffer selection clicks (not recommended for point or line data)') class Meta: abstract = True -class ArcServer(Layer): +class ArcServer(LayerType): arcgis_layers = models.CharField(max_length=255, blank=True, null=True, help_text='comma separated list of arcgis layer IDs') password_protected = models.BooleanField(default=False, help_text='check this if the server requires a password to show layers') disable_arcgis_attributes = models.BooleanField(default=False, help_text='Click to disable clickable ArcRest layers') @@ -420,6 +426,7 @@ class ArcServer(Layer): class Meta: abstract = True + class LayerArcREST(ArcServer, RasterType): def save(self, *args, **kwargs): if not self.id: # Check if this is a new instance diff --git a/layers/static/layer_admin.js b/layers/static/layer_admin.js index 8faf7df..6b8e95f 100644 --- a/layers/static/layer_admin.js +++ b/layers/static/layer_admin.js @@ -1,18 +1,20 @@ document.addEventListener("DOMContentLoaded", function() { - function updateFormDisplay() { - const layerType = document.querySelector("#id_layer_type").value; - console.log("Layer Type:", layerType); // Debugging output - const isArcGIS = layerType === "ArcRest"; // Make sure this matches exactly - console.log("Is ArcGIS:", isArcGIS); // Debugging output + function updateInlines() { + const layerType = document.querySelector("#id_layer_type").value; // Adjust the selector as needed + const inlines = document.querySelectorAll(".inline-group"); - document.querySelectorAll(".form-row.field-arcgis_layers, .form-row.field-password_protected, .form-row.field-query_by_point, .form-row.field-disable_arcgis_attributes").forEach(function(row) { - console.log("Row to update:", row); // Debugging output - row.style.display = isArcGIS ? "block" : "none"; + inlines.forEach(function(inline) { + if (inline.id.includes(layerType.toLowerCase())) { // Assuming inline IDs contain the lowercase `layer_type` + inline.style.display = ''; + } else { + inline.style.display = 'none'; + } }); } + const layerTypeField = document.querySelector("#id_layer_type"); if (layerTypeField) { - layerTypeField.addEventListener("change", updateFormDisplay); - updateFormDisplay(); // Initial update on page load + layerTypeField.addEventListener("change", updateInlines); + updateInlines(); } }); \ No newline at end of file