|
|
@@ -4,6 +4,7 @@ import { FolderKanban, Plus, Trash2, UserPlus, X, Lock, Users } from 'lucide-rea
|
|
|
import { projectsApi, usersApi, Project } from '../api/users'
|
|
|
import { useAuthStore } from '../stores/authStore'
|
|
|
import { describeDuration } from '../components/workflow/WorkflowRetentionSettings'
|
|
|
+import { ConfirmModal } from '../components/workflow/ConfirmModal'
|
|
|
|
|
|
/**
|
|
|
* Projects: who work belongs to, and who may touch it.
|
|
|
@@ -39,6 +40,8 @@ export default function ProjectsPage() {
|
|
|
const [addUserId, setAddUserId] = useState('')
|
|
|
const [addRole, setAddRole] = useState('editor')
|
|
|
const [error, setError] = useState<string | null>(null)
|
|
|
+ const [deleteTarget, setDeleteTarget] = useState<Project | null>(null)
|
|
|
+ const [pendingRetention, setPendingRetention] = useState<{ project: Project; seconds: number } | null>(null)
|
|
|
|
|
|
const { data: projects = [], isLoading } = useQuery({
|
|
|
queryKey: ['projects'],
|
|
|
@@ -144,13 +147,7 @@ export default function ProjectsPage() {
|
|
|
disabled={!canManage || retentionMutation.isPending}
|
|
|
onChange={(e) => {
|
|
|
const seconds = Number(e.target.value)
|
|
|
- const count = project.workflowCount
|
|
|
- const warning =
|
|
|
- seconds === 0
|
|
|
- ? `Keep the data of "${project.name}" for ever?\n\nNothing is ever removed, and it outlives the workflows themselves. ${count} workflow${count === 1 ? '' : 's'} inherit this.`
|
|
|
- : `Keep the data of "${project.name}" for ${describeDuration(seconds)}?\n\nThis runs from when each record was written, so anything already older goes as soon as it is applied. ${count} workflow${count === 1 ? '' : 's'} inherit this - the ones that set their own are not touched.\n\nEach workflow's settings show exactly how much of its data this removes.`
|
|
|
- if (!confirm(warning)) return
|
|
|
- retentionMutation.mutate({ id: project._id, ttlSeconds: seconds })
|
|
|
+ setPendingRetention({ project, seconds })
|
|
|
}}
|
|
|
className="w-full px-2 py-1.5 text-xs border border-gray-300 dark:border-slate-600 rounded bg-white dark:bg-slate-900 text-gray-900 dark:text-gray-100 disabled:opacity-60"
|
|
|
>
|
|
|
@@ -175,11 +172,7 @@ export default function ProjectsPage() {
|
|
|
</button>
|
|
|
{canManage && (
|
|
|
<button
|
|
|
- onClick={() => {
|
|
|
- if (confirm(`Delete "${project.name}"? It has to be empty first.`)) {
|
|
|
- deleteMutation.mutate(project._id)
|
|
|
- }
|
|
|
- }}
|
|
|
+ onClick={() => setDeleteTarget(project)}
|
|
|
className="p-1 text-gray-500 hover:text-red-600 dark:hover:text-red-400 rounded"
|
|
|
title="Delete this project"
|
|
|
>
|
|
|
@@ -371,6 +364,38 @@ export default function ProjectsPage() {
|
|
|
</div>
|
|
|
</div>
|
|
|
)}
|
|
|
+
|
|
|
+ {deleteTarget && (
|
|
|
+ <ConfirmModal
|
|
|
+ title="Delete project?"
|
|
|
+ message={`Delete "${deleteTarget.name}"? It has to be empty first.`}
|
|
|
+ confirmLabel="Delete project"
|
|
|
+ tone="danger"
|
|
|
+ onConfirm={() => {
|
|
|
+ deleteMutation.mutate(deleteTarget._id)
|
|
|
+ setDeleteTarget(null)
|
|
|
+ }}
|
|
|
+ onCancel={() => setDeleteTarget(null)}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+
|
|
|
+ {pendingRetention && (
|
|
|
+ <ConfirmModal
|
|
|
+ title="Change retention?"
|
|
|
+ message={
|
|
|
+ pendingRetention.seconds === 0
|
|
|
+ ? `Keep the data of "${pendingRetention.project.name}" for ever?\n\nNothing is ever removed, and it outlives the workflows themselves. ${pendingRetention.project.workflowCount} workflow${pendingRetention.project.workflowCount === 1 ? '' : 's'} inherit this.`
|
|
|
+ : `Keep the data of "${pendingRetention.project.name}" for ${describeDuration(pendingRetention.seconds)}?\n\nThis runs from when each record was written, so anything already older goes as soon as it is applied. ${pendingRetention.project.workflowCount} workflow${pendingRetention.project.workflowCount === 1 ? '' : 's'} inherit this - the ones that set their own are not touched.\n\nEach workflow's settings show exactly how much of its data this removes.`
|
|
|
+ }
|
|
|
+ confirmLabel="Change retention"
|
|
|
+ tone="warning"
|
|
|
+ onConfirm={() => {
|
|
|
+ retentionMutation.mutate({ id: pendingRetention.project._id, ttlSeconds: pendingRetention.seconds })
|
|
|
+ setPendingRetention(null)
|
|
|
+ }}
|
|
|
+ onCancel={() => setPendingRetention(null)}
|
|
|
+ />
|
|
|
+ )}
|
|
|
</div>
|
|
|
)
|
|
|
}
|