@appcorp/fusion-storybook 0.2.24 → 0.2.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -10,13 +10,17 @@ import { CSVS } from "../../constants";
|
|
|
10
10
|
import { teacherFormValidation } from "./validate";
|
|
11
11
|
import { TEACHER_API_ROUTES } from "./constants";
|
|
12
12
|
import { invalidateTeachersCache } from "./cache";
|
|
13
|
-
import {
|
|
13
|
+
import { TEACHER_ACTION_TYPES, useTeacherModule } from "./context";
|
|
14
14
|
import { useRef, useEffect, useCallback } from "react";
|
|
15
15
|
const workspace = getCachedWorkspaceSync();
|
|
16
16
|
const POLL_INTERVAL_MS = 2000;
|
|
17
17
|
const POLL_TIMEOUT_MS = 300000;
|
|
18
18
|
const handleGetAllRecords = async (schoolId) => {
|
|
19
|
-
const response = await fetch(`${TEACHER_API_ROUTES.UNIT}?pageLimit=1000¤tPage=1&schoolId=${schoolId}
|
|
19
|
+
const response = await fetch(`${TEACHER_API_ROUTES.UNIT}?pageLimit=1000¤tPage=1&schoolId=${schoolId}`, {
|
|
20
|
+
headers: {
|
|
21
|
+
"x-api-token": process.env.NEXT_PUBLIC_API_KEY,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
20
24
|
const result = await response.json();
|
|
21
25
|
const csv = await converter.json2csv(result.items || [], {});
|
|
22
26
|
const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
|
|
@@ -27,11 +31,14 @@ async function submitBulkJob(csvData, method, signal) {
|
|
|
27
31
|
const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
28
32
|
if (!schoolId)
|
|
29
33
|
throw new Error("School ID not found");
|
|
34
|
+
const apiKey = process.env.NEXT_PUBLIC_API_KEY;
|
|
35
|
+
if (!apiKey)
|
|
36
|
+
throw new Error("API key not configured");
|
|
30
37
|
const res = await fetch(TEACHER_API_ROUTES.BULK, {
|
|
31
38
|
method,
|
|
32
39
|
headers: {
|
|
33
40
|
"Content-Type": "application/json",
|
|
34
|
-
"x-api-token":
|
|
41
|
+
"x-api-token": apiKey,
|
|
35
42
|
},
|
|
36
43
|
body: JSON.stringify({ schoolId, csvData }),
|
|
37
44
|
signal,
|
|
@@ -55,9 +62,12 @@ async function pollBulkJob(jobId, signal, onProgress) {
|
|
|
55
62
|
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
56
63
|
if (signal.aborted)
|
|
57
64
|
throw new Error("Polling cancelled");
|
|
65
|
+
const apiKey = process.env.NEXT_PUBLIC_API_KEY;
|
|
66
|
+
if (!apiKey)
|
|
67
|
+
throw new Error("API key not configured");
|
|
58
68
|
const res = await fetch(TEACHER_API_ROUTES.BULK_STATUS(jobId), {
|
|
59
69
|
headers: {
|
|
60
|
-
"x-api-token":
|
|
70
|
+
"x-api-token": apiKey,
|
|
61
71
|
},
|
|
62
72
|
signal,
|
|
63
73
|
});
|
|
@@ -68,8 +78,7 @@ async function pollBulkJob(jobId, signal, onProgress) {
|
|
|
68
78
|
return data;
|
|
69
79
|
}
|
|
70
80
|
// Show progress toast every 10 seconds while running
|
|
71
|
-
if (data.status === "running" &&
|
|
72
|
-
Date.now() - lastProgressToast > 10000) {
|
|
81
|
+
if (data.status === "running" && Date.now() - lastProgressToast > 10000) {
|
|
73
82
|
lastProgressToast = Date.now();
|
|
74
83
|
onProgress === null || onProgress === void 0 ? void 0 : onProgress(data.processed, data.total);
|
|
75
84
|
}
|
|
@@ -86,7 +95,7 @@ function formatErrorSummary(errors) {
|
|
|
86
95
|
}
|
|
87
96
|
export const TeacherMoreActions = () => {
|
|
88
97
|
const t = useTranslations("teacher");
|
|
89
|
-
const { dispatch } =
|
|
98
|
+
const { dispatch, listFetchNow } = useTeacherModule();
|
|
90
99
|
const abortRef = useRef(null);
|
|
91
100
|
// Abort any in-flight polling on unmount
|
|
92
101
|
useEffect(() => {
|
|
@@ -95,14 +104,14 @@ export const TeacherMoreActions = () => {
|
|
|
95
104
|
(_a = abortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
|
|
96
105
|
};
|
|
97
106
|
}, []);
|
|
98
|
-
const closeDrawer = () => {
|
|
99
|
-
dispatch({
|
|
100
|
-
type: TEACHER_ACTION_TYPES.SET_DRAWER,
|
|
101
|
-
payload: { drawer: null },
|
|
102
|
-
});
|
|
103
|
-
};
|
|
104
107
|
const handleBulkFlow = useCallback(async (files, method) => {
|
|
105
108
|
var _a, _b, _c;
|
|
109
|
+
const closeDrawer = () => {
|
|
110
|
+
dispatch({
|
|
111
|
+
type: TEACHER_ACTION_TYPES.SET_DRAWER,
|
|
112
|
+
payload: { drawer: null },
|
|
113
|
+
});
|
|
114
|
+
};
|
|
106
115
|
// Cancel previous in-flight request
|
|
107
116
|
(_a = abortRef.current) === null || _a === void 0 ? void 0 : _a.abort();
|
|
108
117
|
const controller = new AbortController();
|
|
@@ -139,7 +148,14 @@ export const TeacherMoreActions = () => {
|
|
|
139
148
|
}
|
|
140
149
|
try {
|
|
141
150
|
showInfoToast(`Bulk ${label} job queued (${records.length} records). Processing...`);
|
|
142
|
-
|
|
151
|
+
let jobId;
|
|
152
|
+
try {
|
|
153
|
+
jobId = await submitBulkJob(text, method, signal);
|
|
154
|
+
}
|
|
155
|
+
catch (submitError) {
|
|
156
|
+
showErrorToast(`Failed to submit ${label} job: ${submitError instanceof Error ? submitError.message : "Unknown error"}`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
143
159
|
const status = await pollBulkJob(jobId, signal, (processed, total) => {
|
|
144
160
|
showInfoToast(`Processing ${processed}/${total} teachers...`);
|
|
145
161
|
});
|
|
@@ -158,6 +174,7 @@ export const TeacherMoreActions = () => {
|
|
|
158
174
|
showSuccessToast("Bulk operation completed successfully");
|
|
159
175
|
}
|
|
160
176
|
invalidateTeachersCache();
|
|
177
|
+
listFetchNow();
|
|
161
178
|
closeDrawer();
|
|
162
179
|
}
|
|
163
180
|
else {
|
|
@@ -173,7 +190,7 @@ export const TeacherMoreActions = () => {
|
|
|
173
190
|
return;
|
|
174
191
|
showErrorToast(`Bulk ${label} failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
175
192
|
}
|
|
176
|
-
}, [
|
|
193
|
+
}, [dispatch, listFetchNow]);
|
|
177
194
|
const handleBulkCreate = useCallback((files) => handleBulkFlow(files, "POST"), [handleBulkFlow]);
|
|
178
195
|
const handleBulkUpdate = useCallback((files) => handleBulkFlow(files, "PUT"), [handleBulkFlow]);
|
|
179
196
|
const create = [
|
package/components/timeline.js
CHANGED
|
@@ -9,7 +9,14 @@ export const Timeline = ({ heading, events, handleOnBulkCreate, }) => {
|
|
|
9
9
|
// EnhancedDropzone calls onChange synchronously during render.
|
|
10
10
|
queueMicrotask(() => setFiles(f));
|
|
11
11
|
}, []);
|
|
12
|
+
const handleUploadClick = useCallback(() => {
|
|
13
|
+
if (files.length > 0) {
|
|
14
|
+
handleOnBulkCreate === null || handleOnBulkCreate === void 0 ? void 0 : handleOnBulkCreate(files);
|
|
15
|
+
// Clear files after upload to allow resubmission
|
|
16
|
+
queueMicrotask(() => setFiles([]));
|
|
17
|
+
}
|
|
18
|
+
}, [files, handleOnBulkCreate]);
|
|
12
19
|
return (_jsxs("div", { className: "space-y-6", children: [_jsx("h2", { className: "text-foreground text-xl font-semibold", children: heading }), _jsxs("div", { className: "space-y-4", children: [events.map((event) => (_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("div", { className: "z-10 flex h-6 w-6 items-center justify-center", children: _jsx("div", { className: "bg-muted-foreground h-3 w-3 rounded-full" }) }), _jsxs("div", { className: "min-w-0 flex-1 pb-1", children: [_jsx("div", { onClick: event.handleOnClick, className: `text-muted-foreground text-sm ${event.handleOnClick ? "cursor-pointer underline" : ""}`, children: event.title }), event.description && (_jsx("div", { className: "text-foreground mt-1 text-sm", children: event.description }))] })] }, event.id))), _jsx(EnhancedDropzone, { className: "", label: "Upload CSV", id: "timeline-dropzone", info: "Drag and drop your CSV file here, or click to select.", error: "", accept: { "text/csv": [".csv"] }, maxFiles: 1, onChange: handleDropzoneChange, onRemoveRemote: () => {
|
|
13
20
|
// Handle remote file removal if needed
|
|
14
|
-
} }), _jsx(Button, { disabled: files.length === 0, onClick:
|
|
21
|
+
} }), _jsx(Button, { disabled: files.length === 0, onClick: handleUploadClick, children: "Upload and Process CSV" })] })] }));
|
|
15
22
|
};
|