From 65c49c0dea35e63152aed096b2f776e361719af4 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Fri, 13 Sep 2024 15:55:16 +0500 Subject: [PATCH 1/8] condition removed to make tasks public when they are validated --- src/apps/tasks/models.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/apps/tasks/models.py b/src/apps/tasks/models.py index 3b38efe9b..c93d2b60a 100644 --- a/src/apps/tasks/models.py +++ b/src/apps/tasks/models.py @@ -66,10 +66,6 @@ def get_chahub_data(self, include_solutions=True): data['solutions'] = [solution.get_chahub_data(include_tasks=False) for solution in self.solutions.all()] return self.clean_private_data(data) - def save(self, *args, **kwargs): - self.is_public = self.is_public and self._validated - return super().save(*args, **kwargs) - class Solution(ChaHubSaveMixin, models.Model): name = models.CharField(max_length=256) From 87712f4950d528150ffec4518d691d49de8ed0d9 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Fri, 13 Sep 2024 17:27:11 +0500 Subject: [PATCH 2/8] Removed key from front-end. Removed validated condition to show making task public/private buttion. Updated task update method to enable updating is_public status. Once a task is_public was updated, the response was not serialized, now fixed. Removed key from the task detail serializer. Modified validated and shared with methods to return correct responses. Added is_public to TaskListSerializer to show checkmark in the tasks list table. --- src/apps/api/serializers/tasks.py | 14 ++++------ src/apps/api/views/tasks.py | 41 +++++++++++++++++++--------- src/static/riot/tasks/management.tag | 5 +--- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index acd07a8c4..034a5bb6f 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -79,12 +79,6 @@ class Meta: 'created_by', ) - def validate_is_public(self, is_public): - validated = Task.objects.get(id=self.instance.id)._validated - if is_public and not validated: - raise ValidationError('Task must be validated before it can be published') - return is_public - def get_validated(self, instance): return hasattr(instance, 'validated') and instance.validated is not None @@ -106,7 +100,6 @@ class Meta: 'id', 'name', 'description', - 'key', 'created_by', 'owner_display_name', 'created_when', @@ -123,10 +116,12 @@ class Meta: ) def get_validated(self, task): - return task.validated is not None + return task._validated def get_shared_with(self, instance): - return self.context['shared_with'][instance.pk] + # Fetch the users with whom the task is shared + shared_users = instance.shared_with.all() + return [user.username for user in shared_users] def get_owner_display_name(self, instance): # Get the user's display name if not None, otherwise return username @@ -156,6 +151,7 @@ class Meta: 'value', 'competitions', 'shared_with', + 'is_public' ) def get_competitions(self, instance): diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index 71bfb59bd..be05e86f3 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -92,19 +92,34 @@ def update(self, request, *args, **kwargs): if request.user != task.created_by and not request.user.is_superuser: raise PermissionDenied("Cannot update a task that is not yours") - # If the key is not in the request data, set the corresponding field to None - # No condition for scoring program because a task must have a scoring program - if "ingestion_program" not in request.data: - task.ingestion_program = None - if "input_data" not in request.data: - task.input_data = None - if "reference_data" not in request.data: - task.reference_data = None - - # Save the task to apply the changes - task.save() - - return super().update(request, *args, **kwargs) + # Check if 'is_public' is sent in the data + # This means that from the front end the update is_public api is calle + # with `is_public` in the data + if 'is_public' in request.data: + # Perform the update using the parent class's update method + super().update(request, *args, **kwargs) + else: + # If the key is not in the request data, set the corresponding field to None + # No condition for scoring program because a task must have a scoring program + if "ingestion_program" not in request.data: + task.ingestion_program = None + if "input_data" not in request.data: + task.input_data = None + if "reference_data" not in request.data: + task.reference_data = None + + # Save the task to apply the changes + task.save() + super().update(request, *args, **kwargs) + + # Fetch the updated task from the database to ensure it reflects all changes + task.refresh_from_db() + + # Serialize the updated task using TaskDetailSerializer + task_detail_serializer = serializers.TaskDetailSerializer(task) + + # Return the serialized data as a response + return Response(task_detail_serializer.data) def destroy(self, request, *args, **kwargs): instance = self.get_object() diff --git a/src/static/riot/tasks/management.tag b/src/static/riot/tasks/management.tag index 37510275e..f6529ef6c 100644 --- a/src/static/riot/tasks/management.tag +++ b/src/static/riot/tasks/management.tag @@ -36,8 +36,6 @@ {comp.title} - - { task.shared_with.join(', ') } { timeSince(Date.parse(task.created_when)) } ago @@ -101,13 +99,12 @@

{selected_task.description}

Created By: {selected_task.owner_display_name}
-
Key: {selected_task.key}
Has Been Validated : {selected_task.validated ? "Yes" : "No"}
Is Public: {selected_task.is_public ? "Yes" : "No"}
-
{selected_task.is_public ? 'Make Private' : 'Make Public'} From 71f2b686a8998bfcd6c4709a1fd715d3d3cf8591 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Fri, 13 Sep 2024 17:40:01 +0500 Subject: [PATCH 3/8] Taskview set updated to add a condition for showing public task details from other users --- src/apps/api/views/tasks.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index be05e86f3..b78bee8c7 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -42,7 +42,11 @@ def get_queryset(self): ) task_filter = Q(created_by=self.request.user) | Q(shared_with=self.request.user) - if self.request.query_params.get('public'): + # when there is `public` in the query params, it means user has checked on the front end + # the Show public tasks checkbox. + # When a user clicks that public task that may not belong to the user, we want to show + # the public task to the user and hence we check the `retrieve` action + if self.request.query_params.get('public') or self.action == 'retrieve': task_filter |= Q(is_public=True) qs = qs.filter(task_filter) From 988a1a0085fe26500322ce592e6bfc84edd1faa8 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Sat, 14 Sep 2024 18:39:27 +0500 Subject: [PATCH 4/8] In edit competition, now users can select a public task in their phases --- src/apps/api/views/tasks.py | 2 +- src/static/riot/competitions/editor/_phases.tag | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index b78bee8c7..68d63714e 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -42,7 +42,7 @@ def get_queryset(self): ) task_filter = Q(created_by=self.request.user) | Q(shared_with=self.request.user) - # when there is `public` in the query params, it means user has checked on the front end + # when there is `public` in the query params, it means user has checked on the front-end # the Show public tasks checkbox. # When a user clicks that public task that may not belong to the user, we want to show # the public task to the user and hence we check the `retrieve` action diff --git a/src/static/riot/competitions/editor/_phases.tag b/src/static/riot/competitions/editor/_phases.tag index 371d7a3e6..e7d5a98fe 100644 --- a/src/static/riot/competitions/editor/_phases.tag +++ b/src/static/riot/competitions/editor/_phases.tag @@ -216,7 +216,7 @@ // semantic multiselect $(self.refs.multiselect).dropdown({ apiSettings: { - url: `${URLS.API}tasks/?search={query}`, + url: `${URLS.API}tasks/?public=true&search={query}`, cache: false, onResponse: (data) => { return {success: true, results: _.values(data.results)} From 3ae64e6ab84a80b2ab895aa12fff06455de6b583 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Thu, 19 Sep 2024 18:38:32 +0500 Subject: [PATCH 5/8] condition added to show make task public/private to owners of the tasks only --- src/static/riot/tasks/management.tag | 1 + 1 file changed, 1 insertion(+) diff --git a/src/static/riot/tasks/management.tag b/src/static/riot/tasks/management.tag index f6529ef6c..55991846a 100644 --- a/src/static/riot/tasks/management.tag +++ b/src/static/riot/tasks/management.tag @@ -105,6 +105,7 @@ : {selected_task.validated ? "Yes" : "No"}
Is Public: {selected_task.is_public ? "Yes" : "No"}
{selected_task.is_public ? 'Make Private' : 'Make Public'} From 741fd8f54159af42209131b2390be6ef83c4a271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20Pav=C3=A3o?= Date: Tue, 1 Oct 2024 22:08:52 +0200 Subject: [PATCH 6/8] Remove unused import from tasks.py --- src/apps/api/serializers/tasks.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index 034a5bb6f..bd470f9f3 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -1,7 +1,5 @@ from drf_writable_nested import WritableNestedModelSerializer from rest_framework import serializers -from rest_framework.exceptions import ValidationError - from api.mixins import DefaultUserCreateMixin from api.serializers.datasets import DataDetailSerializer, DataSimpleSerializer from competitions.models import PhaseTaskInstance, Phase From 313808af004ba4628839e8176b935f18800d3ad4 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Thu, 10 Oct 2024 19:49:20 +0500 Subject: [PATCH 7/8] reversed the change of task validation --- src/apps/api/serializers/tasks.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index bd470f9f3..03f9ab43c 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -114,7 +114,7 @@ class Meta: ) def get_validated(self, task): - return task._validated + return task.validated is not None def get_shared_with(self, instance): # Fetch the users with whom the task is shared From 85c1ec9b86aa2fa5c200e0b345e4b4d60bb072b6 Mon Sep 17 00:00:00 2001 From: Ihsan Ullah Date: Fri, 25 Oct 2024 12:21:01 +0500 Subject: [PATCH 8/8] task update failure fixed by using TaskSerializer, get_validated function updated to not raise error in the future --- src/apps/api/serializers/tasks.py | 4 ++-- src/apps/api/views/tasks.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/apps/api/serializers/tasks.py b/src/apps/api/serializers/tasks.py index 03f9ab43c..01875e128 100644 --- a/src/apps/api/serializers/tasks.py +++ b/src/apps/api/serializers/tasks.py @@ -113,8 +113,8 @@ class Meta: 'shared_with', ) - def get_validated(self, task): - return task.validated is not None + def get_validated(self, instance): + return hasattr(instance, 'validated') and instance.validated is not None def get_shared_with(self, instance): # Fetch the users with whom the task is shared diff --git a/src/apps/api/views/tasks.py b/src/apps/api/views/tasks.py index 68d63714e..385c4a8a5 100644 --- a/src/apps/api/views/tasks.py +++ b/src/apps/api/views/tasks.py @@ -120,7 +120,7 @@ def update(self, request, *args, **kwargs): task.refresh_from_db() # Serialize the updated task using TaskDetailSerializer - task_detail_serializer = serializers.TaskDetailSerializer(task) + task_detail_serializer = serializers.TaskSerializer(task) # Return the serialized data as a response return Response(task_detail_serializer.data)