shared list in request detail screen
This commit is contained in:
parent
fb4e73e077
commit
0435159e2f
@ -1,2 +1,2 @@
|
|||||||
import{a as t}from"./index-CitEAM_S.js";import"./radix-vendor-BP4rDxsU.js";import"./charts-vendor-Cji9-Yri.js";import"./utils-vendor-DHm03ykU.js";import"./ui-vendor-DB5PynB_.js";import"./socket-vendor-TjCxX7sJ.js";import"./router-vendor-1fSSvDCY.js";async function l(n){return(await t.post(`/conclusions/${n}/generate`)).data.data}async function m(n,o){return(await t.post(`/conclusions/${n}/finalize`,{finalRemark:o})).data.data}async function d(n){return(await t.get(`/conclusions/${n}`)).data.data}export{m as finalizeConclusion,l as generateConclusion,d as getConclusion};
|
import{a as t}from"./index-C-Pt4yOr.js";import"./radix-vendor-BP4rDxsU.js";import"./charts-vendor-Cji9-Yri.js";import"./utils-vendor-DHm03ykU.js";import"./ui-vendor-DB5PynB_.js";import"./socket-vendor-TjCxX7sJ.js";import"./router-vendor-1fSSvDCY.js";async function l(n){return(await t.post(`/conclusions/${n}/generate`)).data.data}async function m(n,o){return(await t.post(`/conclusions/${n}/finalize`,{finalRemark:o})).data.data}async function d(n){return(await t.get(`/conclusions/${n}`)).data.data}export{m as finalizeConclusion,l as generateConclusion,d as getConclusion};
|
||||||
//# sourceMappingURL=conclusionApi-BboC4LaF.js.map
|
//# sourceMappingURL=conclusionApi-DaHT8E_1.js.map
|
||||||
@ -1 +1 @@
|
|||||||
{"version":3,"file":"conclusionApi-BboC4LaF.js","sources":["../../src/services/conclusionApi.ts"],"sourcesContent":["import apiClient from './authApi';\r\n\r\nexport interface ConclusionRemark {\r\n conclusionId: string;\r\n requestId: string;\r\n aiGeneratedRemark: string | null;\r\n aiModelUsed: string | null;\r\n aiConfidenceScore: number | null;\r\n finalRemark: string | null;\r\n editedBy: string | null;\r\n isEdited: boolean;\r\n editCount: number;\r\n approvalSummary: any;\r\n documentSummary: any;\r\n keyDiscussionPoints: string[];\r\n generatedAt: string | null;\r\n finalizedAt: string | null;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n/**\r\n * Generate AI-powered conclusion remark\r\n */\r\nexport async function generateConclusion(requestId: string): Promise<{\r\n conclusionId: string;\r\n aiGeneratedRemark: string;\r\n keyDiscussionPoints: string[];\r\n confidence: number;\r\n generatedAt: string;\r\n}> {\r\n const response = await apiClient.post(`/conclusions/${requestId}/generate`);\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Update conclusion remark (edit by initiator)\r\n */\r\nexport async function updateConclusion(requestId: string, finalRemark: string): Promise<ConclusionRemark> {\r\n const response = await apiClient.put(`/conclusions/${requestId}`, { finalRemark });\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Finalize conclusion and close request\r\n */\r\nexport async function finalizeConclusion(requestId: string, finalRemark: string): Promise<{\r\n conclusionId: string;\r\n requestNumber: string;\r\n status: string;\r\n finalRemark: string;\r\n finalizedAt: string;\r\n}> {\r\n const response = await apiClient.post(`/conclusions/${requestId}/finalize`, { finalRemark });\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Get conclusion for a request\r\n */\r\nexport async function getConclusion(requestId: string): Promise<ConclusionRemark> {\r\n const response = await apiClient.get(`/conclusions/${requestId}`);\r\n return response.data.data;\r\n}\r\n\r\n"],"names":["generateConclusion","requestId","apiClient","finalizeConclusion","finalRemark","getConclusion"],"mappings":"0PAwBA,eAAsBA,EAAmBC,EAMtC,CAED,OADiB,MAAMC,EAAU,KAAK,gBAAgBD,CAAS,WAAW,GAC1D,KAAK,IACvB,CAaA,eAAsBE,EAAmBF,EAAmBG,EAMzD,CAED,OADiB,MAAMF,EAAU,KAAK,gBAAgBD,CAAS,YAAa,CAAE,YAAAG,EAAa,GAC3E,KAAK,IACvB,CAKA,eAAsBC,EAAcJ,EAA8C,CAEhF,OADiB,MAAMC,EAAU,IAAI,gBAAgBD,CAAS,EAAE,GAChD,KAAK,IACvB"}
|
{"version":3,"file":"conclusionApi-DaHT8E_1.js","sources":["../../src/services/conclusionApi.ts"],"sourcesContent":["import apiClient from './authApi';\r\n\r\nexport interface ConclusionRemark {\r\n conclusionId: string;\r\n requestId: string;\r\n aiGeneratedRemark: string | null;\r\n aiModelUsed: string | null;\r\n aiConfidenceScore: number | null;\r\n finalRemark: string | null;\r\n editedBy: string | null;\r\n isEdited: boolean;\r\n editCount: number;\r\n approvalSummary: any;\r\n documentSummary: any;\r\n keyDiscussionPoints: string[];\r\n generatedAt: string | null;\r\n finalizedAt: string | null;\r\n createdAt: string;\r\n updatedAt: string;\r\n}\r\n\r\n/**\r\n * Generate AI-powered conclusion remark\r\n */\r\nexport async function generateConclusion(requestId: string): Promise<{\r\n conclusionId: string;\r\n aiGeneratedRemark: string;\r\n keyDiscussionPoints: string[];\r\n confidence: number;\r\n generatedAt: string;\r\n}> {\r\n const response = await apiClient.post(`/conclusions/${requestId}/generate`);\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Update conclusion remark (edit by initiator)\r\n */\r\nexport async function updateConclusion(requestId: string, finalRemark: string): Promise<ConclusionRemark> {\r\n const response = await apiClient.put(`/conclusions/${requestId}`, { finalRemark });\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Finalize conclusion and close request\r\n */\r\nexport async function finalizeConclusion(requestId: string, finalRemark: string): Promise<{\r\n conclusionId: string;\r\n requestNumber: string;\r\n status: string;\r\n finalRemark: string;\r\n finalizedAt: string;\r\n}> {\r\n const response = await apiClient.post(`/conclusions/${requestId}/finalize`, { finalRemark });\r\n return response.data.data;\r\n}\r\n\r\n/**\r\n * Get conclusion for a request\r\n */\r\nexport async function getConclusion(requestId: string): Promise<ConclusionRemark> {\r\n const response = await apiClient.get(`/conclusions/${requestId}`);\r\n return response.data.data;\r\n}\r\n\r\n"],"names":["generateConclusion","requestId","apiClient","finalizeConclusion","finalRemark","getConclusion"],"mappings":"0PAwBA,eAAsBA,EAAmBC,EAMtC,CAED,OADiB,MAAMC,EAAU,KAAK,gBAAgBD,CAAS,WAAW,GAC1D,KAAK,IACvB,CAaA,eAAsBE,EAAmBF,EAAmBG,EAMzD,CAED,OADiB,MAAMF,EAAU,KAAK,gBAAgBD,CAAS,YAAa,CAAE,YAAAG,EAAa,GAC3E,KAAK,IACvB,CAKA,eAAsBC,EAAcJ,EAA8C,CAEhF,OADiB,MAAMC,EAAU,IAAI,gBAAgBD,CAAS,EAAE,GAChD,KAAK,IACvB"}
|
||||||
File diff suppressed because one or more lines are too long
1
build/assets/index-C-Pt4yOr.js.map
Normal file
1
build/assets/index-C-Pt4yOr.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -52,7 +52,7 @@
|
|||||||
transition: transform 0.2s ease;
|
transition: transform 0.2s ease;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="module" crossorigin src="/assets/index-CitEAM_S.js"></script>
|
<script type="module" crossorigin src="/assets/index-C-Pt4yOr.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/charts-vendor-Cji9-Yri.js">
|
<link rel="modulepreload" crossorigin href="/assets/charts-vendor-Cji9-Yri.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/radix-vendor-BP4rDxsU.js">
|
<link rel="modulepreload" crossorigin href="/assets/radix-vendor-BP4rDxsU.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/utils-vendor-DHm03ykU.js">
|
<link rel="modulepreload" crossorigin href="/assets/utils-vendor-DHm03ykU.js">
|
||||||
|
|||||||
@ -77,6 +77,24 @@ export class SummaryController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of users who received shared summary
|
||||||
|
* GET /api/v1/summaries/:summaryId/recipients
|
||||||
|
*/
|
||||||
|
async getSharedRecipients(req: AuthenticatedRequest, res: Response): Promise<void> {
|
||||||
|
try {
|
||||||
|
const userId = (req as any).user?.userId || (req as any).user?.id || (req as any).auth?.userId;
|
||||||
|
const { summaryId } = req.params;
|
||||||
|
|
||||||
|
const recipients = await summaryService.getSharedRecipients(summaryId, userId);
|
||||||
|
ResponseHandler.success(res, recipients, 'Shared recipients retrieved successfully');
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
|
const statusCode = errorMessage.includes('not found') || errorMessage.includes('Only the initiator') ? 404 : 500;
|
||||||
|
ResponseHandler.error(res, 'Failed to get shared recipients', statusCode, errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List summaries shared with current user
|
* List summaries shared with current user
|
||||||
* GET /api/v1/summaries/shared
|
* GET /api/v1/summaries/shared
|
||||||
|
|||||||
@ -44,6 +44,12 @@ router.post(
|
|||||||
asyncHandler(summaryController.shareSummary.bind(summaryController))
|
asyncHandler(summaryController.shareSummary.bind(summaryController))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get shared recipients for a summary (MUST come before /:summaryId)
|
||||||
|
router.get(
|
||||||
|
'/:summaryId/recipients',
|
||||||
|
asyncHandler(summaryController.getSharedRecipients.bind(summaryController))
|
||||||
|
);
|
||||||
|
|
||||||
// Get summary details (MUST come last - it's a catch-all for UUIDs)
|
// Get summary details (MUST come last - it's a catch-all for UUIDs)
|
||||||
router.get(
|
router.get(
|
||||||
'/:summaryId',
|
'/:summaryId',
|
||||||
|
|||||||
@ -556,6 +556,55 @@ export class SummaryService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of users who received shared summary for a specific summary
|
||||||
|
* Only accessible by the initiator
|
||||||
|
*/
|
||||||
|
async getSharedRecipients(summaryId: string, userId: string): Promise<any[]> {
|
||||||
|
try {
|
||||||
|
// Verify summary exists and user is the initiator
|
||||||
|
const summary = await RequestSummary.findByPk(summaryId);
|
||||||
|
if (!summary) {
|
||||||
|
throw new Error('Summary not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((summary as any).initiatorId !== userId) {
|
||||||
|
throw new Error('Only the initiator can view shared recipients');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all shared summaries for this summary with user details
|
||||||
|
const sharedSummaries = await SharedSummary.findAll({
|
||||||
|
where: { summaryId },
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
as: 'sharedWithUser',
|
||||||
|
attributes: ['userId', 'email', 'displayName', 'designation', 'department']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
order: [['sharedAt', 'DESC']]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Format the response
|
||||||
|
return sharedSummaries.map((shared: any) => {
|
||||||
|
const user = (shared as any).sharedWithUser || {};
|
||||||
|
return {
|
||||||
|
userId: user.userId || (shared as any).sharedWith,
|
||||||
|
email: user.email || 'N/A',
|
||||||
|
displayName: user.displayName || 'Unknown',
|
||||||
|
designation: user.designation || null,
|
||||||
|
department: user.department || null,
|
||||||
|
sharedAt: (shared as any).sharedAt,
|
||||||
|
viewedAt: (shared as any).viewedAt,
|
||||||
|
isRead: (shared as any).isRead || false
|
||||||
|
};
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`[Summary] Failed to get shared recipients for summary ${summaryId}:`, error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List summaries shared with current user
|
* List summaries shared with current user
|
||||||
* userId can be either Okta ID or internal UUID - we'll convert to UUID
|
* userId can be either Okta ID or internal UUID - we'll convert to UUID
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user