diff --git a/public/locales/en.json b/public/locales/en.json
index 1e0e2b7e3..1a1a4f95d 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -4972,6 +4972,21 @@
"trigger": "Trigger",
"when": "When"
},
+ "groupJoinRequest": {
+ "title": "Group Join Request",
+ "approve": "Approve",
+ "decline": "Decline",
+ "requester": "Requester",
+ "group": "Group",
+ "requestedDate": "Requested",
+ "message": "Message from requester",
+ "resolved": "This join request task is closed.",
+ "declineTitle": "Decline Join Request",
+ "declinePrompt": "Optionally provide a reason for declining this join request.",
+ "reasonOptional": "Reason (optional)",
+ "approveError": "Unable to approve join request.",
+ "declineError": "Unable to decline join request."
+ },
"myCards": {
"noCards": "You have no assigned cards.",
"title": "My Cards"
@@ -5145,4 +5160,4 @@
"title": "Workflows"
}
}
-}
+}
\ No newline at end of file
diff --git a/src/dashboard/DashboardPage.tsx b/src/dashboard/DashboardPage.tsx
index d141cbadd..be1839f80 100644
--- a/src/dashboard/DashboardPage.tsx
+++ b/src/dashboard/DashboardPage.tsx
@@ -60,7 +60,7 @@ export const DashboardPage = () => {
-
+
diff --git a/src/serving/tasks/TaskPage.tsx b/src/serving/tasks/TaskPage.tsx
index c968f39ad..c738abc78 100644
--- a/src/serving/tasks/TaskPage.tsx
+++ b/src/serving/tasks/TaskPage.tsx
@@ -7,6 +7,7 @@ import { HeaderPrimaryButton, HeaderSecondaryButton } from "../../components/ui"
import { ContentPicker } from "./components/ContentPicker";
import UserContext from "../../UserContext";
import { RequestedChanges } from "./components/RequestedChanges";
+import { GroupJoinRequestTask } from "./components/GroupJoinRequestTask";
import { TaskReminderEdit } from "./components/TaskReminderEdit";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Person as PersonIcon, Group as GroupIcon, CheckCircle as CompletedIcon, RadioButtonUnchecked as OpenIcon, Checklist as ChecklistIcon } from "@mui/icons-material";
@@ -99,7 +100,7 @@ export const TaskPage = () => {
}
title={`#${task.data.taskNumber} - ${task.data?.title}`}
- subtitle={`${Locale.label("tasks.taskPage.created")} ${DateHelper.getDisplayDuration(DateHelper.toDate(task.data?.dateCreated))} ${Locale.label("tasks.taskPage.ago")} ${Locale.label("tasks.taskPage.by")} ${task.data.createdByLabel} • ${Locale.label("tasks.taskPage.associated")}: ${task.data.associatedWithLabel || Locale.label("tasks.taskPage.notSpec")} • ${Locale.label("tasks.taskPage.assigned")}: ${task.data.assignedToLabel || Locale.label("tasks.taskPage.unassigned")}`}>
+ subtitle={`${Locale.label("tasks.taskPage.created")} ${task.data?.dateCreated ? `${DateHelper.getDisplayDuration(new Date(task.data.dateCreated))} ${Locale.label("tasks.taskPage.ago")}` : ""}${task.data?.createdByLabel ? ` ${Locale.label("tasks.taskPage.by")} ${task.data.createdByLabel}` : ""} • ${Locale.label("tasks.taskPage.associated")}: ${task.data?.associatedWithLabel || Locale.label("tasks.taskPage.notSpec")} • ${Locale.label("tasks.taskPage.assigned")}: ${task.data?.assignedToLabel || Locale.label("tasks.taskPage.unassigned")}`}>
+ }
+ disabled={submitting}
+ onClick={() => setDeclineOpen(true)}
+ data-testid="decline-join-request-button"
+ sx={{ borderRadius: 2, textTransform: "none", fontWeight: 600 }}
+ >
+ {Locale.label("tasks.groupJoinRequest.decline") || "Decline"}
+
+
+ )}
+
+
+ {error && setError("")}>{error}}
+
+
+
+
+
+
+ {Locale.label("tasks.groupJoinRequest.requester") || "Requester"}:{" "}
+ {personId ? (
+
+ {personName}
+
+ ) : (
+ personName
+ )}
+
+
+
+
+
+
+ {Locale.label("tasks.groupJoinRequest.group") || "Group"}:{" "}
+ {groupId ? (
+
+ {groupName}
+
+ ) : (
+ groupName
+ )}
+
+
+
+ {task.dateCreated && (
+
+
+
+ {Locale.label("tasks.groupJoinRequest.requestedDate") || "Requested"}: {DateHelper.getDisplayDuration(new Date(task.dateCreated))} {Locale.label("tasks.taskPage.ago")} ({new Date(task.dateCreated).toLocaleString()})
+
+
+ )}
+
+ {message && (
+
+
+
+
+
+ {Locale.label("tasks.groupJoinRequest.message") || "Message from requester"}:
+
+
+ "{message}"
+
+
+
+
+ )}
+
+
+
+ {isClosed && (
+
+
+ {Locale.label("tasks.groupJoinRequest.resolved") || "This join request task is closed."}
+
+
+ )}
+
+
+
+
+
+ );
+};
diff --git a/src/serving/tasks/components/TaskList.tsx b/src/serving/tasks/components/TaskList.tsx
index 92d10536f..5f6887990 100644
--- a/src/serving/tasks/components/TaskList.tsx
+++ b/src/serving/tasks/components/TaskList.tsx
@@ -38,9 +38,11 @@ export const TaskList = memo((props: Props) => {
const [showAdd, setShowAdd] = React.useState(false);
const [tab, setTab] = React.useState(0);
const context = React.useContext(UserContext);
+ const isClosed = props.status === "Closed" || props.status === Locale.label("tasks.taskPage.closed");
+ const queryStatus = isClosed ? "Closed" : "Open";
const tasks = useQuery({
- queryKey: props.status === Locale.label("tasks.taskPage.closed") ? ["/tasks/closed", "DoingApi"] : ["/tasks", "DoingApi"],
+ queryKey: isClosed ? ["/tasks/closed", "DoingApi"] : ["/tasks", "DoingApi"],
placeholderData: []
});
@@ -58,12 +60,12 @@ export const TaskList = memo((props: Props) => {
}, [groupMembers.data]);
const groupTasks = useQuery({
- queryKey: ["/tasks/loadForGroups", "DoingApi", groupIds, props.status],
+ queryKey: ["/tasks/loadForGroups", "DoingApi", groupIds, queryStatus],
enabled: groupIds.length > 0,
placeholderData: [],
queryFn: async () => {
if (groupIds.length === 0) return [];
- return ApiHelper.post("/tasks/loadForGroups", { groupIds, status: props.status }, "DoingApi");
+ return ApiHelper.post("/tasks/loadForGroups", { groupIds, status: queryStatus }, "DoingApi");
}
});
@@ -135,8 +137,9 @@ export const TaskList = memo((props: Props) => {
- #{task.taskNumber} {Locale.label("tasks.taskPage.opened")} {DateHelper.getDisplayDuration(DateHelper.toDate(task.dateCreated))} {Locale.label("tasks.taskPage.ago")}{" "}
- {Locale.label("tasks.taskPage.by")} {task.createdByLabel}
+ #{task.taskNumber} {Locale.label("tasks.taskPage.opened")}{" "}
+ {task.dateCreated ? `${DateHelper.getDisplayDuration(new Date(task.dateCreated))} ${Locale.label("tasks.taskPage.ago")}` : ""}
+ {task.createdByLabel ? ` ${Locale.label("tasks.taskPage.by")} ${task.createdByLabel}` : ` ${Locale.label("tasks.taskPage.by")} ${task.associatedWithLabel}`}
diff --git a/src/serving/tasks/components/index.ts b/src/serving/tasks/components/index.ts
index 7947250b7..63890f1ae 100644
--- a/src/serving/tasks/components/index.ts
+++ b/src/serving/tasks/components/index.ts
@@ -1,3 +1,6 @@
export * from "../../../components";
export { NewTask } from "./NewTask";
export { SelectGroup } from "./SelectGroup";
+export { GroupJoinRequestTask } from "./GroupJoinRequestTask";
+export { RequestedChanges } from "./RequestedChanges";
+