Skip to content

Commit

Permalink
Merge pull request #58 from kartoza/feat-default-layer-api
Browse files Browse the repository at this point in the history
Feat default layer api
  • Loading branch information
danangmassandy committed Aug 20, 2024
2 parents 7e081c6 + 8c7d0bc commit 665fa3e
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
strategy:
matrix:
python-version:
- 3.10.4
- 3.11.8
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v3
Expand Down
28 changes: 27 additions & 1 deletion django_project/cplus_api/api_views/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
PaginatedInputLayerSerializer,
UploadLayerSerializer,
FinishUploadLayerSerializer,
LAYER_SCHEMA_FIELDS
LAYER_SCHEMA_FIELDS,
InputLayerListSerializer
)
from cplus_api.serializers.common import (
APIErrorSerializer,
Expand Down Expand Up @@ -113,7 +114,32 @@ def get(self, request, *args, **kwargs):
})


class DefaultLayerList(APIView):
"""API to return default layers."""
permission_classes = [IsAuthenticated]

@swagger_auto_schema(
operation_id='layer-default-list',
tags=[LAYER_API_TAG],
responses={
200: InputLayerListSerializer,
400: APIErrorSerializer,
404: APIErrorSerializer
}
)
def get(self, request, *args, **kwargs):
layers = InputLayer.objects.filter(
privacy_type=InputLayer.PrivacyTypes.COMMON
).order_by('name')
return Response(status=200, data=(
InputLayerSerializer(
layers, many=True
).data
))


class BaseLayerUpload(APIView):
"""Base class for layer upload."""

def validate_upload_access(self, privacy_type, user,
is_update=False, existing_layer=None):
Expand Down
18 changes: 18 additions & 0 deletions django_project/cplus_api/migrations/0010_inputlayer_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.7 on 2024-08-19 06:57

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('cplus_api', '0009_scenariotask_stack_trace_errors'),
]

operations = [
migrations.AddField(
model_name='inputlayer',
name='metadata',
field=models.JSONField(blank=True, default=dict, help_text='Layer Metadata.'),
),
]
6 changes: 6 additions & 0 deletions django_project/cplus_api/models/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ class PrivacyTypes(models.TextChoices):
blank=True
)

metadata = models.JSONField(
default=dict,
blank=True,
help_text='Layer Metadata.'
)

def download_to_working_directory(self, base_dir: str):
if not self.is_available():
return None
Expand Down
6 changes: 5 additions & 1 deletion django_project/cplus_api/serializers/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class Meta:
'uuid', 'filename', 'created_on',
'created_by', 'layer_type', 'size',
'url', 'component_type', 'privacy_type',
'client_id'
'client_id', 'metadata'
]


Expand Down Expand Up @@ -215,6 +215,10 @@ class Meta:
}


class InputLayerListSerializer(serializers.ListSerializer):
child = InputLayerSerializer()


class UploadLayerSerializer(serializers.Serializer):
layer_type = serializers.IntegerField()
component_type = serializers.CharField()
Expand Down
28 changes: 5 additions & 23 deletions django_project/cplus_api/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Model factories."""
import factory
import uuid
from typing import Generic, TypeVar
from django.contrib.auth import get_user_model
from django.utils import timezone
from cplus_api.models.scenario import ScenarioTask
Expand All @@ -11,23 +10,10 @@
)


T = TypeVar('T')
User = get_user_model()


class BaseMetaFactory(Generic[T], factory.base.FactoryMetaClass):
def __call__(cls, *args, **kwargs) -> T:
return super().__call__(*args, **kwargs)


class BaseFactory(Generic[T], factory.django.DjangoModelFactory):
@classmethod
def create(cls, **kwargs) -> T:
return super().create(**kwargs)


class UserF(BaseFactory[User],
metaclass=BaseMetaFactory[User]):
class UserF(factory.django.DjangoModelFactory):
class Meta:
model = User

Expand All @@ -38,8 +24,7 @@ class Meta:
last_name = 'Doe'


class ScenarioTaskF(BaseFactory[ScenarioTask],
metaclass=BaseMetaFactory[ScenarioTask]):
class ScenarioTaskF(factory.django.DjangoModelFactory):
class Meta:
model = ScenarioTask

Expand Down Expand Up @@ -266,8 +251,7 @@ class Meta:
}


class InputLayerF(BaseFactory[InputLayer],
metaclass=BaseMetaFactory[InputLayer]):
class InputLayerF(factory.django.DjangoModelFactory):
class Meta:
model = InputLayer

Expand All @@ -281,8 +265,7 @@ class Meta:
privacy_type = InputLayer.PrivacyTypes.PRIVATE


class OutputLayerF(BaseFactory[OutputLayer],
metaclass=BaseMetaFactory[OutputLayer]):
class OutputLayerF(factory.django.DjangoModelFactory):
class Meta:
model = OutputLayer

Expand All @@ -295,8 +278,7 @@ class Meta:
scenario = factory.SubFactory(ScenarioTaskF)


class MultipartUploadF(BaseFactory[MultipartUpload],
metaclass=BaseMetaFactory[MultipartUpload]):
class MultipartUploadF(factory.django.DjangoModelFactory):
class Meta:
model = MultipartUpload

Expand Down
25 changes: 24 additions & 1 deletion django_project/cplus_api/tests/test_layer_api_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
is_internal_user,
validate_layer_access,
LayerUploadAbort,
FetchLayerByClientId
FetchLayerByClientId,
DefaultLayerList
)
from cplus_api.models.profile import UserProfile
from cplus_api.utils.api_helper import convert_size
Expand Down Expand Up @@ -102,6 +103,28 @@ def test_layer_list(self):
self.assertTrue(find_layer)
self.assertTrue(find_layer['url'])

def test_default_layer_list(self):
request = self.factory.get(
reverse('v1:layer-default-list')
)
request.resolver_match = FakeResolverMatchV1
request.user = self.superuser
view = DefaultLayerList.as_view()
response = view(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, [])
input_layer = InputLayerF.create(
privacy_type=InputLayer.PrivacyTypes.COMMON
)
response = view(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 1)
find_layer = self.find_layer_from_response(
response.data, input_layer.uuid)
self.assertTrue(find_layer)
self.assertFalse(find_layer['url'])
self.assertFalse(input_layer.file)

def test_layer_access(self):
input_layer_1 = InputLayerF.create(
privacy_type=InputLayer.PrivacyTypes.COMMON
Expand Down
8 changes: 7 additions & 1 deletion django_project/cplus_api/urls_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
LayerList, LayerDetail, LayerUpload,
LayerUploadStart, LayerUploadFinish,
CheckLayer, LayerUploadAbort,
FetchLayerByClientId
FetchLayerByClientId,
DefaultLayerList
)
from cplus_api.api_views.scenario import (
ScenarioAnalysisSubmit,
Expand Down Expand Up @@ -32,6 +33,11 @@

# LAYER API
layer_urls = [
path(
'layer/default/',
DefaultLayerList.as_view(),
name='layer-default-list'
),
path(
'layer/list/',
LayerList.as_view(),
Expand Down

0 comments on commit 665fa3e

Please sign in to comment.