forked from github/plane
Merge branch 'develop' of github.com:makeplane/plane into develop-deploy
This commit is contained in:
commit
4042da89e3
@ -39,10 +39,8 @@ class FileAssetEndpoint(BaseAPIView):
|
|||||||
def delete(self, request, workspace_id, asset_key):
|
def delete(self, request, workspace_id, asset_key):
|
||||||
asset_key = str(workspace_id) + "/" + asset_key
|
asset_key = str(workspace_id) + "/" + asset_key
|
||||||
file_asset = FileAsset.objects.get(asset=asset_key)
|
file_asset = FileAsset.objects.get(asset=asset_key)
|
||||||
# Delete the file from storage
|
file_asset.is_deleted = True
|
||||||
file_asset.asset.delete(save=False)
|
file_asset.save()
|
||||||
# Delete the file object
|
|
||||||
file_asset.delete()
|
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
|
||||||
|
29
apiserver/plane/bgtasks/file_asset_task.py
Normal file
29
apiserver/plane/bgtasks/file_asset_task.py
Normal file
@ -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()
|
||||||
|
|
@ -24,6 +24,10 @@ app.conf.beat_schedule = {
|
|||||||
"task": "plane.bgtasks.exporter_expired_task.delete_old_s3_link",
|
"task": "plane.bgtasks.exporter_expired_task.delete_old_s3_link",
|
||||||
"schedule": crontab(hour=0, minute=0),
|
"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.
|
# Load task modules from all registered Django app configs.
|
||||||
|
18
apiserver/plane/db/migrations/0051_fileasset_is_deleted.py
Normal file
18
apiserver/plane/db/migrations/0051_fileasset_is_deleted.py
Normal file
@ -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),
|
||||||
|
),
|
||||||
|
]
|
@ -36,6 +36,7 @@ class FileAsset(BaseModel):
|
|||||||
workspace = models.ForeignKey(
|
workspace = models.ForeignKey(
|
||||||
"db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets"
|
"db.Workspace", on_delete=models.CASCADE, null=True, related_name="assets"
|
||||||
)
|
)
|
||||||
|
is_deleted = models.BooleanField(default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = "File Asset"
|
verbose_name = "File Asset"
|
||||||
|
@ -285,6 +285,7 @@ else:
|
|||||||
CELERY_IMPORTS = (
|
CELERY_IMPORTS = (
|
||||||
"plane.bgtasks.issue_automation_task",
|
"plane.bgtasks.issue_automation_task",
|
||||||
"plane.bgtasks.exporter_expired_task",
|
"plane.bgtasks.exporter_expired_task",
|
||||||
|
"plane.bgtasks.file_asset_task",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sentry Settings
|
# Sentry Settings
|
||||||
|
@ -28,7 +28,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
const [createModal, setCreateModal] = useState(false);
|
const [createModal, setCreateModal] = useState(false);
|
||||||
// store
|
// store
|
||||||
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
const { project: projectStore, cycle: cycleStore } = useMobxStore();
|
||||||
const { currentProjectDetails } = projectStore;
|
const { projectCycles } = cycleStore
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { workspaceSlug, projectId, peekCycle } = router.query;
|
const { workspaceSlug, projectId, peekCycle } = router.query;
|
||||||
@ -73,6 +73,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
|
|
||||||
const cycleView = cycleStore?.cycleView;
|
const cycleView = cycleStore?.cycleView;
|
||||||
const cycleLayout = cycleStore?.cycleLayout;
|
const cycleLayout = cycleStore?.cycleLayout;
|
||||||
|
const totalCycles = projectCycles?.length ?? 0
|
||||||
|
|
||||||
if (!workspaceSlug || !projectId) return null;
|
if (!workspaceSlug || !projectId) return null;
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
|
|||||||
isOpen={createModal}
|
isOpen={createModal}
|
||||||
handleClose={() => setCreateModal(false)}
|
handleClose={() => setCreateModal(false)}
|
||||||
/>
|
/>
|
||||||
{currentProjectDetails?.total_cycles === 0 ? (
|
{totalCycles === 0 ? (
|
||||||
<div className="h-full grid place-items-center">
|
<div className="h-full grid place-items-center">
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title="Plan your project with cycles"
|
title="Plan your project with cycles"
|
||||||
|
@ -57,8 +57,8 @@ const CustomErrorComponent = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2 justify-center">
|
<div className="flex items-center gap-2 justify-center">
|
||||||
<Button variant="primary" size="md" onClick={() => router.back()}>
|
<Button variant="primary" size="md" onClick={() => router.reload()}>
|
||||||
Go back
|
Refresh
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="neutral-primary" size="md" onClick={handleSignOut}>
|
<Button variant="neutral-primary" size="md" onClick={handleSignOut}>
|
||||||
Sign out
|
Sign out
|
||||||
|
Loading…
Reference in New Issue
Block a user