From e945aa9b71f029837599bf1ae96d9e5c659ffa26 Mon Sep 17 00:00:00 2001 From: "onFire(Abhi)" <40654066+AbhiShake1@users.noreply.github.com> Date: Mon, 20 Nov 2023 09:06:46 +0000 Subject: [PATCH 1/3] fix: newly added cycle doesnt appear unlelss the page is manually reloaded (#2673) * fix: newly added cycle doesnt appear unlelss the page is manually reloaded * Delete \ * Delete web/layouts/profile-layout/profile-sidebar.tsx * Update cycles.store.ts * fix: remove duplicate type declaration --------- Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> --- .../[workspaceSlug]/projects/[projectId]/cycles/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index c1314b414..9df2357b8 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -28,7 +28,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => { const [createModal, setCreateModal] = useState(false); // store const { project: projectStore, cycle: cycleStore } = useMobxStore(); - const { currentProjectDetails } = projectStore; + const { projectCycles } = cycleStore // router const router = useRouter(); const { workspaceSlug, projectId, peekCycle } = router.query; @@ -73,6 +73,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => { const cycleView = cycleStore?.cycleView; const cycleLayout = cycleStore?.cycleLayout; + const totalCycles = projectCycles?.length ?? 0 if (!workspaceSlug || !projectId) return null; @@ -84,7 +85,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => { isOpen={createModal} handleClose={() => setCreateModal(false)} /> - {currentProjectDetails?.total_cycles === 0 ? ( + {totalCycles === 0 ? (
Date: Mon, 20 Nov 2023 14:53:06 +0530 Subject: [PATCH 2/3] fix: file asset delete (#2804) --- apiserver/plane/app/views/asset.py | 40 +++++++++---------- apiserver/plane/bgtasks/file_asset_task.py | 29 ++++++++++++++ apiserver/plane/celery.py | 4 ++ .../migrations/0051_fileasset_is_deleted.py | 18 +++++++++ apiserver/plane/db/models/asset.py | 1 + apiserver/plane/settings/common.py | 1 + 6 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 apiserver/plane/bgtasks/file_asset_task.py create mode 100644 apiserver/plane/db/migrations/0051_fileasset_is_deleted.py diff --git a/apiserver/plane/app/views/asset.py b/apiserver/plane/app/views/asset.py index eddbb4505..31e002e15 100644 --- a/apiserver/plane/app/views/asset.py +++ b/apiserver/plane/app/views/asset.py @@ -39,10 +39,8 @@ class FileAssetEndpoint(BaseAPIView): def delete(self, request, workspace_id, asset_key): asset_key = str(workspace_id) + "/" + asset_key file_asset = FileAsset.objects.get(asset=asset_key) - # Delete the file from storage - file_asset.asset.delete(save=False) - # Delete the file object - file_asset.delete() + file_asset.is_deleted = True + file_asset.save() return Response(status=status.HTTP_204_NO_CONTENT) @@ -50,25 +48,25 @@ class UserAssetsEndpoint(BaseAPIView): parser_classes = (MultiPartParser, FormParser) def get(self, request, asset_key): - files = FileAsset.objects.filter(asset=asset_key, created_by=request.user) - if files.exists(): - serializer = FileAssetSerializer(files, context={"request": request}) - return Response({"data": serializer.data, "status": True}, status=status.HTTP_200_OK) - else: - return Response({"error": "Asset key does not exist", "status": False}, status=status.HTTP_200_OK) + files = FileAsset.objects.filter(asset=asset_key, created_by=request.user) + if files.exists(): + serializer = FileAssetSerializer(files, context={"request": request}) + return Response({"data": serializer.data, "status": True}, status=status.HTTP_200_OK) + else: + return Response({"error": "Asset key does not exist", "status": False}, status=status.HTTP_200_OK) def post(self, request): - serializer = FileAssetSerializer(data=request.data) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + serializer = FileAssetSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, asset_key): - file_asset = FileAsset.objects.get(asset=asset_key, created_by=request.user) - # Delete the file from storage - file_asset.asset.delete(save=False) - # Delete the file object - file_asset.delete() - return Response(status=status.HTTP_204_NO_CONTENT) + file_asset = FileAsset.objects.get(asset=asset_key, created_by=request.user) + # Delete the file from storage + file_asset.asset.delete(save=False) + # Delete the file object + file_asset.delete() + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/apiserver/plane/bgtasks/file_asset_task.py b/apiserver/plane/bgtasks/file_asset_task.py new file mode 100644 index 000000000..339d24583 --- /dev/null +++ b/apiserver/plane/bgtasks/file_asset_task.py @@ -0,0 +1,29 @@ +# Python imports +from datetime import timedelta + +# Django imports +from django.utils import timezone +from django.db.models import Q + +# Third party imports +from celery import shared_task + +# Module imports +from plane.db.models import FileAsset + + +@shared_task +def delete_file_asset(): + + # file assets to delete + file_assets_to_delete = FileAsset.objects.filter( + Q(is_deleted=True) & Q(updated_at__lte=timezone.now() - timedelta(days=7)) + ) + + # Delete the file from storage and the file object from the database + for file_asset in file_assets_to_delete: + # Delete the file from storage + file_asset.asset.delete(save=False) + # Delete the file object + file_asset.delete() + diff --git a/apiserver/plane/celery.py b/apiserver/plane/celery.py index dfb094339..4d4e3475b 100644 --- a/apiserver/plane/celery.py +++ b/apiserver/plane/celery.py @@ -24,6 +24,10 @@ app.conf.beat_schedule = { "task": "plane.bgtasks.exporter_expired_task.delete_old_s3_link", "schedule": crontab(hour=0, minute=0), }, + "check-every-day-to-delete-file-asset": { + "task": "plane.bgtasks.file_asset_task.delete_file_asset", + "schedule": crontab(hour=0, minute=0), + }, } # Load task modules from all registered Django app configs. diff --git a/apiserver/plane/db/migrations/0051_fileasset_is_deleted.py b/apiserver/plane/db/migrations/0051_fileasset_is_deleted.py new file mode 100644 index 000000000..914852bfd --- /dev/null +++ b/apiserver/plane/db/migrations/0051_fileasset_is_deleted.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.7 on 2023-11-20 08:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('db', '0050_user_use_case_alter_workspace_organization_size'), + ] + + operations = [ + migrations.AddField( + model_name='fileasset', + name='is_deleted', + field=models.BooleanField(default=False), + ), + ] diff --git a/apiserver/plane/db/models/asset.py b/apiserver/plane/db/models/asset.py index 01ef1d9d8..ab3c38d9c 100644 --- a/apiserver/plane/db/models/asset.py +++ b/apiserver/plane/db/models/asset.py @@ -36,6 +36,7 @@ class FileAsset(BaseModel): workspace = models.ForeignKey( "db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets" ) + is_deleted = models.BooleanField(default=False) class Meta: verbose_name = "File Asset" diff --git a/apiserver/plane/settings/common.py b/apiserver/plane/settings/common.py index 2cf94a68c..8b81102fe 100644 --- a/apiserver/plane/settings/common.py +++ b/apiserver/plane/settings/common.py @@ -285,6 +285,7 @@ else: CELERY_IMPORTS = ( "plane.bgtasks.issue_automation_task", "plane.bgtasks.exporter_expired_task", + "plane.bgtasks.file_asset_task", ) # Sentry Settings From 668dfd2e380d8d2cfeec57c9a7fedee906e6d6c1 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:00:36 +0530 Subject: [PATCH 3/3] chore: update exception detected screen action button (#2805) --- web/pages/_error.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/pages/_error.tsx b/web/pages/_error.tsx index e131c4e01..c24f6514b 100644 --- a/web/pages/_error.tsx +++ b/web/pages/_error.tsx @@ -57,8 +57,8 @@ const CustomErrorComponent = () => {

-