Enable thread file attachments
This commit is contained in:
1 parent
d5a7665893
commit
91d9b76281
2 files changed
+54
-7
No files matched your search
@@ -69,6 +69,7 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
const [openThreadId, setOpenThreadId] = useState<string | null>(null);
|
||||
const [createOpen, setCreateOpen] = useState(false);
|
||||
const [attachmentFileId, setAttachmentFileId] = useState<string>("");
|
||||
const [threadAttachmentFileId, setThreadAttachmentFileId] = useState<string>("");
|
||||
const composerRef = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const firstAvailableSpaceId = channels[0]?.id ?? directs[0]?.id ?? null;
|
||||
@@ -119,6 +120,16 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
);
|
||||
const pendingApprovalsInSpace = filterApprovalsForSpace(approvalsAll, activeSpace);
|
||||
|
||||
const openThread = (threadId: string) => {
|
||||
setOpenThreadId(threadId);
|
||||
setThreadAttachmentFileId("");
|
||||
};
|
||||
|
||||
const closeThread = () => {
|
||||
setOpenThreadId(null);
|
||||
setThreadAttachmentFileId("");
|
||||
};
|
||||
|
||||
const sendInChannel = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
if (!activeSpace) return;
|
||||
@@ -145,6 +156,7 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
const body = value(form, "message");
|
||||
if (!body) return;
|
||||
event.currentTarget.reset();
|
||||
setThreadAttachmentFileId("");
|
||||
void actions.run(() => window.agentCompany.sendMessage({
|
||||
orgId,
|
||||
spaceId: activeSpace.id,
|
||||
@@ -152,7 +164,7 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
senderType: "employee",
|
||||
senderId: employee.id,
|
||||
bodyMd: body,
|
||||
attachmentFileIds: [],
|
||||
attachmentFileIds: threadAttachmentFileId ? [threadAttachmentFileId] : [],
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -225,9 +237,17 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
}));
|
||||
|
||||
const attachFile = () => {
|
||||
importAttachment(setAttachmentFileId);
|
||||
};
|
||||
|
||||
const attachThreadFile = () => {
|
||||
importAttachment(setThreadAttachmentFileId);
|
||||
};
|
||||
|
||||
const importAttachment = (onSelect: (fileId: string) => void) => {
|
||||
void window.agentCompany.importFile({ orgId }).then((result) => {
|
||||
if (!result.ok) throw new Error(result.error.message);
|
||||
if (result.data) setAttachmentFileId(result.data);
|
||||
if (result.data) onSelect(result.data);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -248,7 +268,7 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
activeSpaceId={activeSpaceId}
|
||||
onSelect={(spaceId) => {
|
||||
setSelectedSpaceId(spaceId);
|
||||
setOpenThreadId(null);
|
||||
closeThread();
|
||||
}}
|
||||
onCreateSpace={() => setCreateOpen(true)}
|
||||
/>
|
||||
@@ -269,7 +289,7 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
currentEmployeeId={employee.id}
|
||||
onAttachmentChange={setAttachmentFileId}
|
||||
onAttach={attachFile}
|
||||
onOpenThread={setOpenThreadId}
|
||||
onOpenThread={openThread}
|
||||
onApprove={(approvalId) => decideApproval(approvalId, "approved")}
|
||||
onDecline={(approvalId) => decideApproval(approvalId, "declined")}
|
||||
onEditMessage={editChatMessage}
|
||||
@@ -292,7 +312,10 @@ export function ChatPage({ snapshot, actions }: PageProps) {
|
||||
auditEvents={threadAuditEvents}
|
||||
context={{ employees, agents }}
|
||||
canIntervene={canBoardIntervene}
|
||||
onClose={() => setOpenThreadId(null)}
|
||||
attachmentFileId={threadAttachmentFileId}
|
||||
onClose={closeThread}
|
||||
onAttachmentChange={setThreadAttachmentFileId}
|
||||
onAttach={attachThreadFile}
|
||||
onSubmit={sendInThread}
|
||||
onBoardSubmit={sendBoardIntervention}
|
||||
onOpenFile={openFile}
|
||||
|
||||
@@ -26,7 +26,10 @@ export function ChatThreadPanel({
|
||||
auditEvents,
|
||||
context,
|
||||
canIntervene,
|
||||
attachmentFileId,
|
||||
onClose,
|
||||
onAttachmentChange,
|
||||
onAttach,
|
||||
onSubmit,
|
||||
onBoardSubmit,
|
||||
onOpenFile,
|
||||
@@ -42,11 +45,15 @@ export function ChatThreadPanel({
|
||||
auditEvents: AuditEventRecord[];
|
||||
context: MessageContext;
|
||||
canIntervene: boolean;
|
||||
attachmentFileId: string;
|
||||
onClose: () => void;
|
||||
onAttachmentChange: (next: string) => void;
|
||||
onAttach: () => void;
|
||||
onSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
||||
onBoardSubmit: (event: FormEvent<HTMLFormElement>) => void;
|
||||
onOpenFile: (fileId: string) => void;
|
||||
}) {
|
||||
const attachment = files.find((file) => file.id === attachmentFileId) ?? null;
|
||||
return (
|
||||
<aside
|
||||
style={{
|
||||
@@ -126,8 +133,25 @@ export function ChatThreadPanel({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="row" style={{ paddingTop: 6, justifyContent: "flex-end" }}>
|
||||
<Button tone="primary" size="small" type="submit"><Icon name="send" size={12} /> Reply</Button>
|
||||
<div className="row" style={{ paddingTop: 6, gap: 4 }}>
|
||||
<IconButton icon="attach" label="Attach file" onClick={onAttach} />
|
||||
{attachment && (
|
||||
<span className="pill" style={{ maxWidth: 150 }}>
|
||||
<Icon name="file" size={11} />
|
||||
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{attachment.name}</span>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Remove thread attachment"
|
||||
onClick={() => onAttachmentChange("")}
|
||||
style={{ display: "inline-flex", border: 0, background: "transparent", padding: 0, color: "var(--text-3)", cursor: "pointer" }}
|
||||
>
|
||||
<Icon name="x" size={11} />
|
||||
</button>
|
||||
</span>
|
||||
)}
|
||||
<div style={{ marginLeft: "auto" }}>
|
||||
<Button tone="primary" size="small" type="submit"><Icon name="send" size={12} /> Reply</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in new issue
Block a user