@speakableio/core 0.1.1 → 0.1.2
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.
- package/dist/index.d.mts +254 -22
- package/dist/index.d.ts +254 -22
- package/dist/index.js +283 -26
- package/dist/index.mjs +282 -25
- package/package.json +5 -2
package/dist/index.d.mts
CHANGED
|
@@ -2,17 +2,13 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
4
|
import { QueryClient } from '@tanstack/react-query';
|
|
5
|
-
import * as firebase_firestore from 'firebase/firestore';
|
|
6
5
|
import { Firestore } from 'firebase/firestore';
|
|
7
6
|
import { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';
|
|
8
7
|
|
|
9
|
-
interface AssignmentWithId extends Assignment {
|
|
10
|
-
ltiLineItemId: null;
|
|
11
|
-
id: string;
|
|
12
|
-
}
|
|
13
8
|
interface Assignment {
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
title: string;
|
|
10
|
+
description: string;
|
|
11
|
+
scheduledTime?: string | null;
|
|
16
12
|
dueTime?: {
|
|
17
13
|
hours: number;
|
|
18
14
|
minutes: number;
|
|
@@ -48,15 +44,122 @@ interface Assignment {
|
|
|
48
44
|
isAssessment: boolean;
|
|
49
45
|
isAvailable: boolean;
|
|
50
46
|
}
|
|
51
|
-
|
|
47
|
+
interface AssignmentWithId extends Assignment {
|
|
48
|
+
id: string;
|
|
49
|
+
isAvailable: boolean;
|
|
50
|
+
scores?: unknown;
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
declare const enum AssignmentAnalyticsType {
|
|
54
|
+
Macro = "macro",
|
|
55
|
+
Gradebook = "gradebook",
|
|
56
|
+
Cards = "cards",
|
|
57
|
+
Student = "student",
|
|
58
|
+
StudentSummary = "student_summary",
|
|
59
|
+
All = "all"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface GetAttachScoresParams {
|
|
63
|
+
assignments: AssignmentWithId[];
|
|
64
|
+
analyticType: AssignmentAnalyticsType;
|
|
65
|
+
studentId?: string;
|
|
66
|
+
currentUserId: string;
|
|
67
|
+
}
|
|
68
|
+
interface GetAssignmentScoresParams {
|
|
69
|
+
assignmentId: string;
|
|
70
|
+
currentUserId: string;
|
|
71
|
+
analyticType?: AssignmentAnalyticsType;
|
|
72
|
+
studentId?: string;
|
|
73
|
+
}
|
|
56
74
|
|
|
57
|
-
declare const createAssignmentRepo: (
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
declare const createAssignmentRepo: () => {
|
|
76
|
+
getAssignment: (params: GetAssignmentScoresParams) => Promise<AssignmentWithId | {
|
|
77
|
+
scores: any;
|
|
78
|
+
id: string;
|
|
79
|
+
isAvailable: boolean;
|
|
80
|
+
title: string;
|
|
81
|
+
description: string;
|
|
82
|
+
scheduledTime?: string | null;
|
|
83
|
+
dueTime?: {
|
|
84
|
+
hours: number;
|
|
85
|
+
minutes: number;
|
|
86
|
+
nanos: number;
|
|
87
|
+
};
|
|
88
|
+
speakableio: boolean;
|
|
89
|
+
owners: string[];
|
|
90
|
+
image: {
|
|
91
|
+
path: string | null;
|
|
92
|
+
url: string;
|
|
93
|
+
};
|
|
94
|
+
dueDate: {
|
|
95
|
+
day: number;
|
|
96
|
+
month: number;
|
|
97
|
+
year: number;
|
|
98
|
+
};
|
|
99
|
+
teacherName: string;
|
|
100
|
+
courseWorkId: string | null;
|
|
101
|
+
dueDateTimestamp: {
|
|
102
|
+
seconds: number;
|
|
103
|
+
nanoseconds: number;
|
|
104
|
+
};
|
|
105
|
+
scheduledTimeTimestamp: number;
|
|
106
|
+
active: boolean;
|
|
107
|
+
voice: string | null;
|
|
108
|
+
setId: string;
|
|
109
|
+
dateMade: {
|
|
110
|
+
seconds: number;
|
|
111
|
+
nanoseconds: number;
|
|
112
|
+
};
|
|
113
|
+
maxPoints: number;
|
|
114
|
+
courseId: string;
|
|
115
|
+
isAssessment: boolean;
|
|
116
|
+
} | null>;
|
|
117
|
+
attachScoresAssignment: (args_0: GetAttachScoresParams) => Promise<{
|
|
118
|
+
scores: any;
|
|
119
|
+
id: string;
|
|
120
|
+
isAvailable: boolean;
|
|
121
|
+
title: string;
|
|
122
|
+
description: string;
|
|
123
|
+
scheduledTime?: string | null;
|
|
124
|
+
dueTime?: {
|
|
125
|
+
hours: number;
|
|
126
|
+
minutes: number;
|
|
127
|
+
nanos: number;
|
|
128
|
+
};
|
|
129
|
+
speakableio: boolean;
|
|
130
|
+
owners: string[];
|
|
131
|
+
image: {
|
|
132
|
+
path: string | null;
|
|
133
|
+
url: string;
|
|
134
|
+
};
|
|
135
|
+
dueDate: {
|
|
136
|
+
day: number;
|
|
137
|
+
month: number;
|
|
138
|
+
year: number;
|
|
139
|
+
};
|
|
140
|
+
teacherName: string;
|
|
141
|
+
courseWorkId: string | null;
|
|
142
|
+
dueDateTimestamp: {
|
|
143
|
+
seconds: number;
|
|
144
|
+
nanoseconds: number;
|
|
145
|
+
};
|
|
146
|
+
scheduledTimeTimestamp: number;
|
|
147
|
+
active: boolean;
|
|
148
|
+
voice: string | null;
|
|
149
|
+
setId: string;
|
|
150
|
+
dateMade: {
|
|
151
|
+
seconds: number;
|
|
152
|
+
nanoseconds: number;
|
|
153
|
+
};
|
|
154
|
+
maxPoints: number;
|
|
155
|
+
courseId: string;
|
|
156
|
+
isAssessment: boolean;
|
|
157
|
+
}[]>;
|
|
158
|
+
getAssignmentScores: (args_0: GetAssignmentScoresParams) => Promise<{
|
|
159
|
+
scores: unknown;
|
|
160
|
+
id: string;
|
|
161
|
+
} | undefined>;
|
|
162
|
+
getAllAssignments: () => Promise<AssignmentWithId[]>;
|
|
60
163
|
};
|
|
61
164
|
|
|
62
165
|
declare const assignmentQueryKeys: {
|
|
@@ -64,21 +167,150 @@ declare const assignmentQueryKeys: {
|
|
|
64
167
|
byId: (id: string) => readonly ["assignments", string];
|
|
65
168
|
list: () => readonly ["assignments", "list"];
|
|
66
169
|
};
|
|
67
|
-
declare function useAssignment({
|
|
68
|
-
|
|
170
|
+
declare function useAssignment({ assignmentId, enabled, analyticType, userId, }: {
|
|
171
|
+
assignmentId: string;
|
|
69
172
|
enabled?: boolean;
|
|
70
|
-
|
|
173
|
+
analyticType?: AssignmentAnalyticsType;
|
|
174
|
+
userId: string;
|
|
175
|
+
}): _tanstack_react_query.UseQueryResult<AssignmentWithId | {
|
|
176
|
+
scores: any;
|
|
177
|
+
id: string;
|
|
178
|
+
isAvailable: boolean;
|
|
179
|
+
title: string;
|
|
180
|
+
description: string;
|
|
181
|
+
scheduledTime?: string | null;
|
|
182
|
+
dueTime?: {
|
|
183
|
+
hours: number;
|
|
184
|
+
minutes: number;
|
|
185
|
+
nanos: number;
|
|
186
|
+
};
|
|
187
|
+
speakableio: boolean;
|
|
188
|
+
owners: string[];
|
|
189
|
+
image: {
|
|
190
|
+
path: string | null;
|
|
191
|
+
url: string;
|
|
192
|
+
};
|
|
193
|
+
dueDate: {
|
|
194
|
+
day: number;
|
|
195
|
+
month: number;
|
|
196
|
+
year: number;
|
|
197
|
+
};
|
|
198
|
+
teacherName: string;
|
|
199
|
+
courseWorkId: string | null;
|
|
200
|
+
dueDateTimestamp: {
|
|
201
|
+
seconds: number;
|
|
202
|
+
nanoseconds: number;
|
|
203
|
+
};
|
|
204
|
+
scheduledTimeTimestamp: number;
|
|
205
|
+
active: boolean;
|
|
206
|
+
voice: string | null;
|
|
207
|
+
setId: string;
|
|
208
|
+
dateMade: {
|
|
209
|
+
seconds: number;
|
|
210
|
+
nanoseconds: number;
|
|
211
|
+
};
|
|
212
|
+
maxPoints: number;
|
|
213
|
+
courseId: string;
|
|
214
|
+
isAssessment: boolean;
|
|
215
|
+
} | null, Error>;
|
|
216
|
+
|
|
217
|
+
type FirebaseInstance = FirebaseFirestoreTypes.Module | Firestore;
|
|
71
218
|
|
|
72
219
|
type FsClient = ReturnType<typeof createFsClient>;
|
|
73
220
|
declare function createFsClient(db: FirebaseInstance, platform: 'web' | 'native'): Promise<{
|
|
74
221
|
assignmentRepo: {
|
|
75
|
-
|
|
76
|
-
|
|
222
|
+
getAssignment: (params: GetAssignmentScoresParams) => Promise<AssignmentWithId | {
|
|
223
|
+
scores: any;
|
|
224
|
+
id: string;
|
|
225
|
+
isAvailable: boolean;
|
|
226
|
+
title: string;
|
|
227
|
+
description: string;
|
|
228
|
+
scheduledTime?: string | null;
|
|
229
|
+
dueTime?: {
|
|
230
|
+
hours: number;
|
|
231
|
+
minutes: number;
|
|
232
|
+
nanos: number;
|
|
233
|
+
};
|
|
234
|
+
speakableio: boolean;
|
|
235
|
+
owners: string[];
|
|
236
|
+
image: {
|
|
237
|
+
path: string | null;
|
|
238
|
+
url: string;
|
|
239
|
+
};
|
|
240
|
+
dueDate: {
|
|
241
|
+
day: number;
|
|
242
|
+
month: number;
|
|
243
|
+
year: number;
|
|
244
|
+
};
|
|
245
|
+
teacherName: string;
|
|
246
|
+
courseWorkId: string | null;
|
|
247
|
+
dueDateTimestamp: {
|
|
248
|
+
seconds: number;
|
|
249
|
+
nanoseconds: number;
|
|
250
|
+
};
|
|
251
|
+
scheduledTimeTimestamp: number;
|
|
252
|
+
active: boolean;
|
|
253
|
+
voice: string | null;
|
|
254
|
+
setId: string;
|
|
255
|
+
dateMade: {
|
|
256
|
+
seconds: number;
|
|
257
|
+
nanoseconds: number;
|
|
258
|
+
};
|
|
259
|
+
maxPoints: number;
|
|
260
|
+
courseId: string;
|
|
261
|
+
isAssessment: boolean;
|
|
262
|
+
} | null>;
|
|
263
|
+
attachScoresAssignment: (args_0: GetAttachScoresParams) => Promise<{
|
|
264
|
+
scores: any;
|
|
265
|
+
id: string;
|
|
266
|
+
isAvailable: boolean;
|
|
267
|
+
title: string;
|
|
268
|
+
description: string;
|
|
269
|
+
scheduledTime?: string | null;
|
|
270
|
+
dueTime?: {
|
|
271
|
+
hours: number;
|
|
272
|
+
minutes: number;
|
|
273
|
+
nanos: number;
|
|
274
|
+
};
|
|
275
|
+
speakableio: boolean;
|
|
276
|
+
owners: string[];
|
|
277
|
+
image: {
|
|
278
|
+
path: string | null;
|
|
279
|
+
url: string;
|
|
280
|
+
};
|
|
281
|
+
dueDate: {
|
|
282
|
+
day: number;
|
|
283
|
+
month: number;
|
|
284
|
+
year: number;
|
|
285
|
+
};
|
|
286
|
+
teacherName: string;
|
|
287
|
+
courseWorkId: string | null;
|
|
288
|
+
dueDateTimestamp: {
|
|
289
|
+
seconds: number;
|
|
290
|
+
nanoseconds: number;
|
|
291
|
+
};
|
|
292
|
+
scheduledTimeTimestamp: number;
|
|
293
|
+
active: boolean;
|
|
294
|
+
voice: string | null;
|
|
295
|
+
setId: string;
|
|
296
|
+
dateMade: {
|
|
297
|
+
seconds: number;
|
|
298
|
+
nanoseconds: number;
|
|
299
|
+
};
|
|
300
|
+
maxPoints: number;
|
|
301
|
+
courseId: string;
|
|
302
|
+
isAssessment: boolean;
|
|
303
|
+
}[]>;
|
|
304
|
+
getAssignmentScores: (args_0: GetAssignmentScoresParams) => Promise<{
|
|
305
|
+
scores: unknown;
|
|
306
|
+
id: string;
|
|
307
|
+
} | undefined>;
|
|
308
|
+
getAllAssignments: () => Promise<AssignmentWithId[]>;
|
|
77
309
|
};
|
|
78
310
|
}>;
|
|
79
311
|
|
|
80
312
|
interface FsContext {
|
|
81
|
-
|
|
313
|
+
speakableApi: Awaited<FsClient>;
|
|
82
314
|
queryClient: QueryClient;
|
|
83
315
|
}
|
|
84
316
|
declare const FsCtx: React.Context<FsContext | null>;
|
|
@@ -88,6 +320,6 @@ declare function SpeakableProvider({ db, platform, children, queryClient, }: {
|
|
|
88
320
|
children: React.ReactNode;
|
|
89
321
|
queryClient: QueryClient;
|
|
90
322
|
}): react_jsx_runtime.JSX.Element | null;
|
|
91
|
-
declare function
|
|
323
|
+
declare function useSpeakableApi(): FsContext;
|
|
92
324
|
|
|
93
|
-
export { type Assignment, type
|
|
325
|
+
export { type Assignment, type AssignmentWithId, type FsClient, FsCtx, SpeakableProvider, assignmentQueryKeys, createAssignmentRepo, createFsClient, useAssignment, useSpeakableApi };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,17 +2,13 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
4
|
import { QueryClient } from '@tanstack/react-query';
|
|
5
|
-
import * as firebase_firestore from 'firebase/firestore';
|
|
6
5
|
import { Firestore } from 'firebase/firestore';
|
|
7
6
|
import { FirebaseFirestoreTypes } from '@react-native-firebase/firestore';
|
|
8
7
|
|
|
9
|
-
interface AssignmentWithId extends Assignment {
|
|
10
|
-
ltiLineItemId: null;
|
|
11
|
-
id: string;
|
|
12
|
-
}
|
|
13
8
|
interface Assignment {
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
title: string;
|
|
10
|
+
description: string;
|
|
11
|
+
scheduledTime?: string | null;
|
|
16
12
|
dueTime?: {
|
|
17
13
|
hours: number;
|
|
18
14
|
minutes: number;
|
|
@@ -48,15 +44,122 @@ interface Assignment {
|
|
|
48
44
|
isAssessment: boolean;
|
|
49
45
|
isAvailable: boolean;
|
|
50
46
|
}
|
|
51
|
-
|
|
47
|
+
interface AssignmentWithId extends Assignment {
|
|
48
|
+
id: string;
|
|
49
|
+
isAvailable: boolean;
|
|
50
|
+
scores?: unknown;
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
declare const enum AssignmentAnalyticsType {
|
|
54
|
+
Macro = "macro",
|
|
55
|
+
Gradebook = "gradebook",
|
|
56
|
+
Cards = "cards",
|
|
57
|
+
Student = "student",
|
|
58
|
+
StudentSummary = "student_summary",
|
|
59
|
+
All = "all"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface GetAttachScoresParams {
|
|
63
|
+
assignments: AssignmentWithId[];
|
|
64
|
+
analyticType: AssignmentAnalyticsType;
|
|
65
|
+
studentId?: string;
|
|
66
|
+
currentUserId: string;
|
|
67
|
+
}
|
|
68
|
+
interface GetAssignmentScoresParams {
|
|
69
|
+
assignmentId: string;
|
|
70
|
+
currentUserId: string;
|
|
71
|
+
analyticType?: AssignmentAnalyticsType;
|
|
72
|
+
studentId?: string;
|
|
73
|
+
}
|
|
56
74
|
|
|
57
|
-
declare const createAssignmentRepo: (
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
declare const createAssignmentRepo: () => {
|
|
76
|
+
getAssignment: (params: GetAssignmentScoresParams) => Promise<AssignmentWithId | {
|
|
77
|
+
scores: any;
|
|
78
|
+
id: string;
|
|
79
|
+
isAvailable: boolean;
|
|
80
|
+
title: string;
|
|
81
|
+
description: string;
|
|
82
|
+
scheduledTime?: string | null;
|
|
83
|
+
dueTime?: {
|
|
84
|
+
hours: number;
|
|
85
|
+
minutes: number;
|
|
86
|
+
nanos: number;
|
|
87
|
+
};
|
|
88
|
+
speakableio: boolean;
|
|
89
|
+
owners: string[];
|
|
90
|
+
image: {
|
|
91
|
+
path: string | null;
|
|
92
|
+
url: string;
|
|
93
|
+
};
|
|
94
|
+
dueDate: {
|
|
95
|
+
day: number;
|
|
96
|
+
month: number;
|
|
97
|
+
year: number;
|
|
98
|
+
};
|
|
99
|
+
teacherName: string;
|
|
100
|
+
courseWorkId: string | null;
|
|
101
|
+
dueDateTimestamp: {
|
|
102
|
+
seconds: number;
|
|
103
|
+
nanoseconds: number;
|
|
104
|
+
};
|
|
105
|
+
scheduledTimeTimestamp: number;
|
|
106
|
+
active: boolean;
|
|
107
|
+
voice: string | null;
|
|
108
|
+
setId: string;
|
|
109
|
+
dateMade: {
|
|
110
|
+
seconds: number;
|
|
111
|
+
nanoseconds: number;
|
|
112
|
+
};
|
|
113
|
+
maxPoints: number;
|
|
114
|
+
courseId: string;
|
|
115
|
+
isAssessment: boolean;
|
|
116
|
+
} | null>;
|
|
117
|
+
attachScoresAssignment: (args_0: GetAttachScoresParams) => Promise<{
|
|
118
|
+
scores: any;
|
|
119
|
+
id: string;
|
|
120
|
+
isAvailable: boolean;
|
|
121
|
+
title: string;
|
|
122
|
+
description: string;
|
|
123
|
+
scheduledTime?: string | null;
|
|
124
|
+
dueTime?: {
|
|
125
|
+
hours: number;
|
|
126
|
+
minutes: number;
|
|
127
|
+
nanos: number;
|
|
128
|
+
};
|
|
129
|
+
speakableio: boolean;
|
|
130
|
+
owners: string[];
|
|
131
|
+
image: {
|
|
132
|
+
path: string | null;
|
|
133
|
+
url: string;
|
|
134
|
+
};
|
|
135
|
+
dueDate: {
|
|
136
|
+
day: number;
|
|
137
|
+
month: number;
|
|
138
|
+
year: number;
|
|
139
|
+
};
|
|
140
|
+
teacherName: string;
|
|
141
|
+
courseWorkId: string | null;
|
|
142
|
+
dueDateTimestamp: {
|
|
143
|
+
seconds: number;
|
|
144
|
+
nanoseconds: number;
|
|
145
|
+
};
|
|
146
|
+
scheduledTimeTimestamp: number;
|
|
147
|
+
active: boolean;
|
|
148
|
+
voice: string | null;
|
|
149
|
+
setId: string;
|
|
150
|
+
dateMade: {
|
|
151
|
+
seconds: number;
|
|
152
|
+
nanoseconds: number;
|
|
153
|
+
};
|
|
154
|
+
maxPoints: number;
|
|
155
|
+
courseId: string;
|
|
156
|
+
isAssessment: boolean;
|
|
157
|
+
}[]>;
|
|
158
|
+
getAssignmentScores: (args_0: GetAssignmentScoresParams) => Promise<{
|
|
159
|
+
scores: unknown;
|
|
160
|
+
id: string;
|
|
161
|
+
} | undefined>;
|
|
162
|
+
getAllAssignments: () => Promise<AssignmentWithId[]>;
|
|
60
163
|
};
|
|
61
164
|
|
|
62
165
|
declare const assignmentQueryKeys: {
|
|
@@ -64,21 +167,150 @@ declare const assignmentQueryKeys: {
|
|
|
64
167
|
byId: (id: string) => readonly ["assignments", string];
|
|
65
168
|
list: () => readonly ["assignments", "list"];
|
|
66
169
|
};
|
|
67
|
-
declare function useAssignment({
|
|
68
|
-
|
|
170
|
+
declare function useAssignment({ assignmentId, enabled, analyticType, userId, }: {
|
|
171
|
+
assignmentId: string;
|
|
69
172
|
enabled?: boolean;
|
|
70
|
-
|
|
173
|
+
analyticType?: AssignmentAnalyticsType;
|
|
174
|
+
userId: string;
|
|
175
|
+
}): _tanstack_react_query.UseQueryResult<AssignmentWithId | {
|
|
176
|
+
scores: any;
|
|
177
|
+
id: string;
|
|
178
|
+
isAvailable: boolean;
|
|
179
|
+
title: string;
|
|
180
|
+
description: string;
|
|
181
|
+
scheduledTime?: string | null;
|
|
182
|
+
dueTime?: {
|
|
183
|
+
hours: number;
|
|
184
|
+
minutes: number;
|
|
185
|
+
nanos: number;
|
|
186
|
+
};
|
|
187
|
+
speakableio: boolean;
|
|
188
|
+
owners: string[];
|
|
189
|
+
image: {
|
|
190
|
+
path: string | null;
|
|
191
|
+
url: string;
|
|
192
|
+
};
|
|
193
|
+
dueDate: {
|
|
194
|
+
day: number;
|
|
195
|
+
month: number;
|
|
196
|
+
year: number;
|
|
197
|
+
};
|
|
198
|
+
teacherName: string;
|
|
199
|
+
courseWorkId: string | null;
|
|
200
|
+
dueDateTimestamp: {
|
|
201
|
+
seconds: number;
|
|
202
|
+
nanoseconds: number;
|
|
203
|
+
};
|
|
204
|
+
scheduledTimeTimestamp: number;
|
|
205
|
+
active: boolean;
|
|
206
|
+
voice: string | null;
|
|
207
|
+
setId: string;
|
|
208
|
+
dateMade: {
|
|
209
|
+
seconds: number;
|
|
210
|
+
nanoseconds: number;
|
|
211
|
+
};
|
|
212
|
+
maxPoints: number;
|
|
213
|
+
courseId: string;
|
|
214
|
+
isAssessment: boolean;
|
|
215
|
+
} | null, Error>;
|
|
216
|
+
|
|
217
|
+
type FirebaseInstance = FirebaseFirestoreTypes.Module | Firestore;
|
|
71
218
|
|
|
72
219
|
type FsClient = ReturnType<typeof createFsClient>;
|
|
73
220
|
declare function createFsClient(db: FirebaseInstance, platform: 'web' | 'native'): Promise<{
|
|
74
221
|
assignmentRepo: {
|
|
75
|
-
|
|
76
|
-
|
|
222
|
+
getAssignment: (params: GetAssignmentScoresParams) => Promise<AssignmentWithId | {
|
|
223
|
+
scores: any;
|
|
224
|
+
id: string;
|
|
225
|
+
isAvailable: boolean;
|
|
226
|
+
title: string;
|
|
227
|
+
description: string;
|
|
228
|
+
scheduledTime?: string | null;
|
|
229
|
+
dueTime?: {
|
|
230
|
+
hours: number;
|
|
231
|
+
minutes: number;
|
|
232
|
+
nanos: number;
|
|
233
|
+
};
|
|
234
|
+
speakableio: boolean;
|
|
235
|
+
owners: string[];
|
|
236
|
+
image: {
|
|
237
|
+
path: string | null;
|
|
238
|
+
url: string;
|
|
239
|
+
};
|
|
240
|
+
dueDate: {
|
|
241
|
+
day: number;
|
|
242
|
+
month: number;
|
|
243
|
+
year: number;
|
|
244
|
+
};
|
|
245
|
+
teacherName: string;
|
|
246
|
+
courseWorkId: string | null;
|
|
247
|
+
dueDateTimestamp: {
|
|
248
|
+
seconds: number;
|
|
249
|
+
nanoseconds: number;
|
|
250
|
+
};
|
|
251
|
+
scheduledTimeTimestamp: number;
|
|
252
|
+
active: boolean;
|
|
253
|
+
voice: string | null;
|
|
254
|
+
setId: string;
|
|
255
|
+
dateMade: {
|
|
256
|
+
seconds: number;
|
|
257
|
+
nanoseconds: number;
|
|
258
|
+
};
|
|
259
|
+
maxPoints: number;
|
|
260
|
+
courseId: string;
|
|
261
|
+
isAssessment: boolean;
|
|
262
|
+
} | null>;
|
|
263
|
+
attachScoresAssignment: (args_0: GetAttachScoresParams) => Promise<{
|
|
264
|
+
scores: any;
|
|
265
|
+
id: string;
|
|
266
|
+
isAvailable: boolean;
|
|
267
|
+
title: string;
|
|
268
|
+
description: string;
|
|
269
|
+
scheduledTime?: string | null;
|
|
270
|
+
dueTime?: {
|
|
271
|
+
hours: number;
|
|
272
|
+
minutes: number;
|
|
273
|
+
nanos: number;
|
|
274
|
+
};
|
|
275
|
+
speakableio: boolean;
|
|
276
|
+
owners: string[];
|
|
277
|
+
image: {
|
|
278
|
+
path: string | null;
|
|
279
|
+
url: string;
|
|
280
|
+
};
|
|
281
|
+
dueDate: {
|
|
282
|
+
day: number;
|
|
283
|
+
month: number;
|
|
284
|
+
year: number;
|
|
285
|
+
};
|
|
286
|
+
teacherName: string;
|
|
287
|
+
courseWorkId: string | null;
|
|
288
|
+
dueDateTimestamp: {
|
|
289
|
+
seconds: number;
|
|
290
|
+
nanoseconds: number;
|
|
291
|
+
};
|
|
292
|
+
scheduledTimeTimestamp: number;
|
|
293
|
+
active: boolean;
|
|
294
|
+
voice: string | null;
|
|
295
|
+
setId: string;
|
|
296
|
+
dateMade: {
|
|
297
|
+
seconds: number;
|
|
298
|
+
nanoseconds: number;
|
|
299
|
+
};
|
|
300
|
+
maxPoints: number;
|
|
301
|
+
courseId: string;
|
|
302
|
+
isAssessment: boolean;
|
|
303
|
+
}[]>;
|
|
304
|
+
getAssignmentScores: (args_0: GetAssignmentScoresParams) => Promise<{
|
|
305
|
+
scores: unknown;
|
|
306
|
+
id: string;
|
|
307
|
+
} | undefined>;
|
|
308
|
+
getAllAssignments: () => Promise<AssignmentWithId[]>;
|
|
77
309
|
};
|
|
78
310
|
}>;
|
|
79
311
|
|
|
80
312
|
interface FsContext {
|
|
81
|
-
|
|
313
|
+
speakableApi: Awaited<FsClient>;
|
|
82
314
|
queryClient: QueryClient;
|
|
83
315
|
}
|
|
84
316
|
declare const FsCtx: React.Context<FsContext | null>;
|
|
@@ -88,6 +320,6 @@ declare function SpeakableProvider({ db, platform, children, queryClient, }: {
|
|
|
88
320
|
children: React.ReactNode;
|
|
89
321
|
queryClient: QueryClient;
|
|
90
322
|
}): react_jsx_runtime.JSX.Element | null;
|
|
91
|
-
declare function
|
|
323
|
+
declare function useSpeakableApi(): FsContext;
|
|
92
324
|
|
|
93
|
-
export { type Assignment, type
|
|
325
|
+
export { type Assignment, type AssignmentWithId, type FsClient, FsCtx, SpeakableProvider, assignmentQueryKeys, createAssignmentRepo, createFsClient, useAssignment, useSpeakableApi };
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,265 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }// src/providers/SpeakableProvider.tsx
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/providers/SpeakableProvider.tsx
|
|
2
2
|
var _react = require('react');
|
|
3
3
|
|
|
4
|
+
// src/utils/error-handler.ts
|
|
5
|
+
var ServiceError = class extends Error {
|
|
6
|
+
constructor(message, originalError, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.originalError = originalError;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "ServiceError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function withErrorHandler(fn, serviceName) {
|
|
14
|
+
return async (...args) => {
|
|
15
|
+
try {
|
|
16
|
+
return await fn(...args);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error instanceof Error && "code" in error) {
|
|
19
|
+
const firebaseError = error;
|
|
20
|
+
throw new ServiceError(
|
|
21
|
+
`Error in ${serviceName}: ${firebaseError.message}`,
|
|
22
|
+
error,
|
|
23
|
+
firebaseError.code
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
throw new ServiceError(`Error in ${serviceName}: ${error.message}`, error);
|
|
28
|
+
}
|
|
29
|
+
throw new ServiceError(`Unknown error in ${serviceName}`, error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/lib/firebase/api.ts
|
|
35
|
+
var FirebaseAPI = class _FirebaseAPI {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
37
|
+
constructor() {
|
|
38
|
+
this.config = null;
|
|
39
|
+
}
|
|
40
|
+
static getInstance() {
|
|
41
|
+
if (!_FirebaseAPI.instance) {
|
|
42
|
+
_FirebaseAPI.instance = new _FirebaseAPI();
|
|
43
|
+
}
|
|
44
|
+
return _FirebaseAPI.instance;
|
|
45
|
+
}
|
|
46
|
+
initialize(config) {
|
|
47
|
+
this.config = config;
|
|
48
|
+
}
|
|
49
|
+
get db() {
|
|
50
|
+
if (!this.config) throw new Error("FirebaseAPI not initialized");
|
|
51
|
+
return this.config.db;
|
|
52
|
+
}
|
|
53
|
+
get helpers() {
|
|
54
|
+
if (!this.config) throw new Error("FirebaseAPI not initialized");
|
|
55
|
+
return this.config.helpers;
|
|
56
|
+
}
|
|
57
|
+
accessQueryConstraints() {
|
|
58
|
+
const { query, orderBy, limit, startAt, startAfter, endAt, endBefore } = this.helpers;
|
|
59
|
+
return {
|
|
60
|
+
query,
|
|
61
|
+
orderBy,
|
|
62
|
+
limit,
|
|
63
|
+
startAt,
|
|
64
|
+
startAfter,
|
|
65
|
+
endAt,
|
|
66
|
+
endBefore
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getDoc(path) {
|
|
70
|
+
const { getDoc, doc } = this.helpers;
|
|
71
|
+
const docRef = doc(this.db, path);
|
|
72
|
+
const docSnap = await getDoc(docRef);
|
|
73
|
+
return {
|
|
74
|
+
id: docSnap.id,
|
|
75
|
+
data: docSnap.exists() ? docSnap.data() : null
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async getDocs(path, ...queryConstraints) {
|
|
79
|
+
const { getDocs, query, collection } = this.helpers;
|
|
80
|
+
const collectionRef = collection(this.db, path);
|
|
81
|
+
const q = queryConstraints.length > 0 ? query(collectionRef, ...queryConstraints) : collectionRef;
|
|
82
|
+
const querySnapshot = await getDocs(q);
|
|
83
|
+
const data = querySnapshot.docs.map((doc) => ({
|
|
84
|
+
id: doc.id,
|
|
85
|
+
data: doc.data()
|
|
86
|
+
}));
|
|
87
|
+
return {
|
|
88
|
+
data,
|
|
89
|
+
querySnapshot
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async addDoc(path, data) {
|
|
93
|
+
const { addDoc, collection } = this.helpers;
|
|
94
|
+
const collectionRef = collection(this.db, path);
|
|
95
|
+
const docRef = await addDoc(collectionRef, data);
|
|
96
|
+
return docRef.id;
|
|
97
|
+
}
|
|
98
|
+
async setDoc(path, data) {
|
|
99
|
+
const { setDoc, doc } = this.helpers;
|
|
100
|
+
const docRef = doc(this.db, path);
|
|
101
|
+
await setDoc(docRef, data);
|
|
102
|
+
}
|
|
103
|
+
async updateDoc(path, data) {
|
|
104
|
+
const { updateDoc, doc } = this.helpers;
|
|
105
|
+
const docRef = doc(this.db, path);
|
|
106
|
+
await updateDoc(docRef, data);
|
|
107
|
+
}
|
|
108
|
+
async deleteDoc(path) {
|
|
109
|
+
const { deleteDoc, doc } = this.helpers;
|
|
110
|
+
const docRef = doc(this.db, path);
|
|
111
|
+
await deleteDoc(docRef);
|
|
112
|
+
}
|
|
113
|
+
async runTransaction(updateFunction) {
|
|
114
|
+
const { runTransaction } = this.helpers;
|
|
115
|
+
return runTransaction(this.db, updateFunction);
|
|
116
|
+
}
|
|
117
|
+
async runBatch(operations) {
|
|
118
|
+
const { writeBatch } = this.helpers;
|
|
119
|
+
const batch = writeBatch(this.db);
|
|
120
|
+
await Promise.all(operations.map((op) => op()));
|
|
121
|
+
await batch.commit();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var api = FirebaseAPI.getInstance();
|
|
125
|
+
|
|
126
|
+
// src/domains/assignment/assignment.constants.ts
|
|
127
|
+
var ASSIGNMENT_ANALYTICS_TYPES = [
|
|
128
|
+
"macro" /* Macro */,
|
|
129
|
+
"gradebook" /* Gradebook */,
|
|
130
|
+
"cards" /* Cards */,
|
|
131
|
+
"student" /* Student */,
|
|
132
|
+
"student_summary" /* StudentSummary */
|
|
133
|
+
];
|
|
134
|
+
var ASSIGNMENTS_COLLECTION = "assignments";
|
|
135
|
+
var ANALYTICS_SUBCOLLECTION = "analytics";
|
|
136
|
+
var SCORES_SUBCOLLECTION = "scores";
|
|
137
|
+
var refsAssignmentFiresotre = {
|
|
138
|
+
allAssignments: () => ASSIGNMENTS_COLLECTION,
|
|
139
|
+
assignment: (id) => `${ASSIGNMENTS_COLLECTION}/${id}`,
|
|
140
|
+
assignmentAllAnalytics: (id) => `${ASSIGNMENTS_COLLECTION}/${id}/${ANALYTICS_SUBCOLLECTION}`,
|
|
141
|
+
assignmentAnalytics: (id, type) => `${ASSIGNMENTS_COLLECTION}/${id}/${ANALYTICS_SUBCOLLECTION}/${type}`,
|
|
142
|
+
assignmentScores: (id, userId) => `${ASSIGNMENTS_COLLECTION}/${id}/${SCORES_SUBCOLLECTION}/${userId}`
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/domains/assignment/services/get-assignments-score.service.ts
|
|
146
|
+
var _getAssignmentScores = async ({
|
|
147
|
+
assignmentId,
|
|
148
|
+
analyticType = "macro" /* Macro */,
|
|
149
|
+
studentId,
|
|
150
|
+
currentUserId
|
|
151
|
+
}) => {
|
|
152
|
+
if (analyticType === "student" /* Student */) {
|
|
153
|
+
const path = refsAssignmentFiresotre.assignmentScores(assignmentId, currentUserId);
|
|
154
|
+
const response = await api.getDoc(path);
|
|
155
|
+
return { scores: response.data, id: assignmentId };
|
|
156
|
+
}
|
|
157
|
+
if (analyticType === "student_summary" /* StudentSummary */ && studentId) {
|
|
158
|
+
const path = refsAssignmentFiresotre.assignmentScores(assignmentId, studentId);
|
|
159
|
+
const response = await api.getDoc(path);
|
|
160
|
+
return { scores: response.data, id: assignmentId };
|
|
161
|
+
}
|
|
162
|
+
if (analyticType !== "all" /* All */ && ASSIGNMENT_ANALYTICS_TYPES.includes(analyticType)) {
|
|
163
|
+
const ref = refsAssignmentFiresotre.assignmentAnalytics(assignmentId, analyticType);
|
|
164
|
+
const docData = await api.getDoc(ref);
|
|
165
|
+
return { scores: docData.data, id: assignmentId };
|
|
166
|
+
} else if (analyticType === "all" /* All */) {
|
|
167
|
+
const ref = refsAssignmentFiresotre.assignmentAllAnalytics(assignmentId);
|
|
168
|
+
const response = await api.getDocs(ref);
|
|
169
|
+
const data = response.data.reduce((acc, curr) => {
|
|
170
|
+
acc[curr.id] = curr;
|
|
171
|
+
return acc;
|
|
172
|
+
}, {});
|
|
173
|
+
return { scores: data, id: assignmentId };
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
var getAssignmentScores = withErrorHandler(_getAssignmentScores, "getAssignmentScores");
|
|
177
|
+
|
|
178
|
+
// src/domains/assignment/services/attach-score-assignment.service.ts
|
|
179
|
+
var _attachScoresAssignment = async ({
|
|
180
|
+
assignments,
|
|
181
|
+
analyticType,
|
|
182
|
+
studentId,
|
|
183
|
+
currentUserId
|
|
184
|
+
}) => {
|
|
185
|
+
const scoresPromises = assignments.map((a) => {
|
|
186
|
+
return getAssignmentScores({
|
|
187
|
+
assignmentId: a.id,
|
|
188
|
+
analyticType,
|
|
189
|
+
studentId,
|
|
190
|
+
currentUserId
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
const scores = await Promise.all(scoresPromises);
|
|
194
|
+
const scoresObject = scores.reduce((acc, curr) => {
|
|
195
|
+
acc[curr.id] = curr.scores;
|
|
196
|
+
return acc;
|
|
197
|
+
}, {});
|
|
198
|
+
const assignmentsWithScores = assignments.map((a) => {
|
|
199
|
+
return {
|
|
200
|
+
...a,
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/ban-ts-comment
|
|
202
|
+
// @ts-ignore
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
204
|
+
scores: _nullishCoalesce(scoresObject[a.id], () => ( null))
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
return assignmentsWithScores;
|
|
208
|
+
};
|
|
209
|
+
var attachScoresAssignment = withErrorHandler(
|
|
210
|
+
_attachScoresAssignment,
|
|
211
|
+
"attachScoresAssignment"
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// src/domains/assignment/services/get-all-assignment.service.ts
|
|
215
|
+
async function _getAllAssignments() {
|
|
216
|
+
const path = refsAssignmentFiresotre.allAssignments();
|
|
217
|
+
const response = await api.getDocs(path);
|
|
218
|
+
return response.data;
|
|
219
|
+
}
|
|
220
|
+
var getAllAssignments = withErrorHandler(_getAllAssignments, "getAllAssignments");
|
|
221
|
+
|
|
222
|
+
// src/domains/assignment/utils/check-assignment-availability.ts
|
|
223
|
+
var _dayjs = require('dayjs'); var _dayjs2 = _interopRequireDefault(_dayjs);
|
|
224
|
+
var checkAssignmentAvailability = (scheduledTime) => {
|
|
225
|
+
if (!scheduledTime) return true;
|
|
226
|
+
const scheduledDate = typeof scheduledTime === "string" ? _dayjs2.default.call(void 0, scheduledTime) : _dayjs2.default.call(void 0, scheduledTime.toDate());
|
|
227
|
+
if (!scheduledDate.isValid()) return true;
|
|
228
|
+
return _dayjs2.default.call(void 0, ).isAfter(scheduledDate);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/domains/assignment/services/get-assignment.service.ts
|
|
232
|
+
async function _getAssignment(params) {
|
|
233
|
+
const path = refsAssignmentFiresotre.assignment(params.assignmentId);
|
|
234
|
+
const response = await api.getDoc(path);
|
|
235
|
+
if (!response.data) return null;
|
|
236
|
+
const assignment = response.data;
|
|
237
|
+
const isAvailable = checkAssignmentAvailability(assignment.scheduledTime);
|
|
238
|
+
const assignmentWithId = {
|
|
239
|
+
...assignment,
|
|
240
|
+
isAvailable,
|
|
241
|
+
id: params.assignmentId,
|
|
242
|
+
scheduledTime: _nullishCoalesce(assignment.scheduledTime, () => ( null))
|
|
243
|
+
};
|
|
244
|
+
if (params.analyticType) {
|
|
245
|
+
const assignmentsWithScores = await attachScoresAssignment({
|
|
246
|
+
assignments: [assignmentWithId],
|
|
247
|
+
analyticType: params.analyticType,
|
|
248
|
+
currentUserId: params.currentUserId
|
|
249
|
+
});
|
|
250
|
+
return assignmentsWithScores.length > 0 ? assignmentsWithScores[0] : assignmentWithId;
|
|
251
|
+
}
|
|
252
|
+
return assignmentWithId;
|
|
253
|
+
}
|
|
254
|
+
var getAssignment = withErrorHandler(_getAssignment, "getAssignment");
|
|
255
|
+
|
|
4
256
|
// src/domains/assignment/assignment.repo.ts
|
|
5
|
-
var createAssignmentRepo = (
|
|
6
|
-
const { doc, collection, getDoc, getDocs } = h;
|
|
257
|
+
var createAssignmentRepo = () => {
|
|
7
258
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return { id, ...data };
|
|
13
|
-
},
|
|
14
|
-
async list() {
|
|
15
|
-
const col = collection(db, "assignments");
|
|
16
|
-
const snap = await getDocs(col);
|
|
17
|
-
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
18
|
-
}
|
|
259
|
+
getAssignment,
|
|
260
|
+
attachScoresAssignment,
|
|
261
|
+
getAssignmentScores,
|
|
262
|
+
getAllAssignments
|
|
19
263
|
};
|
|
20
264
|
};
|
|
21
265
|
|
|
@@ -26,11 +270,20 @@ var assignmentQueryKeys = {
|
|
|
26
270
|
byId: (id) => [...assignmentQueryKeys.all, id],
|
|
27
271
|
list: () => [...assignmentQueryKeys.all, "list"]
|
|
28
272
|
};
|
|
29
|
-
function useAssignment({
|
|
30
|
-
|
|
273
|
+
function useAssignment({
|
|
274
|
+
assignmentId,
|
|
275
|
+
enabled = true,
|
|
276
|
+
analyticType,
|
|
277
|
+
userId
|
|
278
|
+
}) {
|
|
279
|
+
const { speakableApi } = useSpeakableApi();
|
|
31
280
|
return _reactquery.useQuery.call(void 0, {
|
|
32
|
-
queryKey: assignmentQueryKeys.byId(
|
|
33
|
-
queryFn: () =>
|
|
281
|
+
queryKey: assignmentQueryKeys.byId(assignmentId),
|
|
282
|
+
queryFn: () => speakableApi.assignmentRepo.getAssignment({
|
|
283
|
+
assignmentId,
|
|
284
|
+
analyticType,
|
|
285
|
+
currentUserId: userId
|
|
286
|
+
}),
|
|
34
287
|
enabled
|
|
35
288
|
});
|
|
36
289
|
}
|
|
@@ -39,8 +292,12 @@ function useAssignment({ id, enabled = true }) {
|
|
|
39
292
|
async function createFsClient(db, platform) {
|
|
40
293
|
const dbAsFirestore = db;
|
|
41
294
|
const helpers = platform === "web" ? await Promise.resolve().then(() => _interopRequireWildcard(require("firebase/firestore"))) : await Promise.resolve().then(() => _interopRequireWildcard(require("@react-native-firebase/firestore")));
|
|
295
|
+
api.initialize({
|
|
296
|
+
db: dbAsFirestore,
|
|
297
|
+
helpers
|
|
298
|
+
});
|
|
42
299
|
return {
|
|
43
|
-
assignmentRepo: createAssignmentRepo(
|
|
300
|
+
assignmentRepo: createAssignmentRepo()
|
|
44
301
|
};
|
|
45
302
|
}
|
|
46
303
|
|
|
@@ -53,27 +310,27 @@ function SpeakableProvider({
|
|
|
53
310
|
children,
|
|
54
311
|
queryClient
|
|
55
312
|
}) {
|
|
56
|
-
const [
|
|
313
|
+
const [speakableApi, setSpeakableApi] = _react.useState.call(void 0, null);
|
|
57
314
|
_react.useEffect.call(void 0, () => {
|
|
58
315
|
createFsClient(db, platform).then((repos) => {
|
|
59
|
-
|
|
316
|
+
setSpeakableApi(repos);
|
|
60
317
|
});
|
|
61
318
|
}, [db, platform]);
|
|
62
|
-
if (!
|
|
319
|
+
if (!speakableApi) return null;
|
|
63
320
|
return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
64
321
|
FsCtx.Provider,
|
|
65
322
|
{
|
|
66
323
|
value: {
|
|
67
|
-
|
|
324
|
+
speakableApi,
|
|
68
325
|
queryClient
|
|
69
326
|
},
|
|
70
327
|
children
|
|
71
328
|
}
|
|
72
329
|
);
|
|
73
330
|
}
|
|
74
|
-
function
|
|
331
|
+
function useSpeakableApi() {
|
|
75
332
|
const ctx = _react.useContext.call(void 0, FsCtx);
|
|
76
|
-
if (!ctx) throw new Error("
|
|
333
|
+
if (!ctx) throw new Error("useSpeakableApi must be used within a SpeakableProvider");
|
|
77
334
|
return ctx;
|
|
78
335
|
}
|
|
79
336
|
|
|
@@ -84,4 +341,4 @@ function useFs() {
|
|
|
84
341
|
|
|
85
342
|
|
|
86
343
|
|
|
87
|
-
exports.FsCtx = FsCtx; exports.SpeakableProvider = SpeakableProvider; exports.assignmentQueryKeys = assignmentQueryKeys; exports.createAssignmentRepo = createAssignmentRepo; exports.createFsClient = createFsClient; exports.useAssignment = useAssignment; exports.
|
|
344
|
+
exports.FsCtx = FsCtx; exports.SpeakableProvider = SpeakableProvider; exports.assignmentQueryKeys = assignmentQueryKeys; exports.createAssignmentRepo = createAssignmentRepo; exports.createFsClient = createFsClient; exports.useAssignment = useAssignment; exports.useSpeakableApi = useSpeakableApi;
|
package/dist/index.mjs
CHANGED
|
@@ -1,21 +1,265 @@
|
|
|
1
1
|
// src/providers/SpeakableProvider.tsx
|
|
2
2
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
3
3
|
|
|
4
|
+
// src/utils/error-handler.ts
|
|
5
|
+
var ServiceError = class extends Error {
|
|
6
|
+
constructor(message, originalError, code) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.originalError = originalError;
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "ServiceError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
function withErrorHandler(fn, serviceName) {
|
|
14
|
+
return async (...args) => {
|
|
15
|
+
try {
|
|
16
|
+
return await fn(...args);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error instanceof Error && "code" in error) {
|
|
19
|
+
const firebaseError = error;
|
|
20
|
+
throw new ServiceError(
|
|
21
|
+
`Error in ${serviceName}: ${firebaseError.message}`,
|
|
22
|
+
error,
|
|
23
|
+
firebaseError.code
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
if (error instanceof Error) {
|
|
27
|
+
throw new ServiceError(`Error in ${serviceName}: ${error.message}`, error);
|
|
28
|
+
}
|
|
29
|
+
throw new ServiceError(`Unknown error in ${serviceName}`, error);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/lib/firebase/api.ts
|
|
35
|
+
var FirebaseAPI = class _FirebaseAPI {
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
37
|
+
constructor() {
|
|
38
|
+
this.config = null;
|
|
39
|
+
}
|
|
40
|
+
static getInstance() {
|
|
41
|
+
if (!_FirebaseAPI.instance) {
|
|
42
|
+
_FirebaseAPI.instance = new _FirebaseAPI();
|
|
43
|
+
}
|
|
44
|
+
return _FirebaseAPI.instance;
|
|
45
|
+
}
|
|
46
|
+
initialize(config) {
|
|
47
|
+
this.config = config;
|
|
48
|
+
}
|
|
49
|
+
get db() {
|
|
50
|
+
if (!this.config) throw new Error("FirebaseAPI not initialized");
|
|
51
|
+
return this.config.db;
|
|
52
|
+
}
|
|
53
|
+
get helpers() {
|
|
54
|
+
if (!this.config) throw new Error("FirebaseAPI not initialized");
|
|
55
|
+
return this.config.helpers;
|
|
56
|
+
}
|
|
57
|
+
accessQueryConstraints() {
|
|
58
|
+
const { query, orderBy, limit, startAt, startAfter, endAt, endBefore } = this.helpers;
|
|
59
|
+
return {
|
|
60
|
+
query,
|
|
61
|
+
orderBy,
|
|
62
|
+
limit,
|
|
63
|
+
startAt,
|
|
64
|
+
startAfter,
|
|
65
|
+
endAt,
|
|
66
|
+
endBefore
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getDoc(path) {
|
|
70
|
+
const { getDoc, doc } = this.helpers;
|
|
71
|
+
const docRef = doc(this.db, path);
|
|
72
|
+
const docSnap = await getDoc(docRef);
|
|
73
|
+
return {
|
|
74
|
+
id: docSnap.id,
|
|
75
|
+
data: docSnap.exists() ? docSnap.data() : null
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async getDocs(path, ...queryConstraints) {
|
|
79
|
+
const { getDocs, query, collection } = this.helpers;
|
|
80
|
+
const collectionRef = collection(this.db, path);
|
|
81
|
+
const q = queryConstraints.length > 0 ? query(collectionRef, ...queryConstraints) : collectionRef;
|
|
82
|
+
const querySnapshot = await getDocs(q);
|
|
83
|
+
const data = querySnapshot.docs.map((doc) => ({
|
|
84
|
+
id: doc.id,
|
|
85
|
+
data: doc.data()
|
|
86
|
+
}));
|
|
87
|
+
return {
|
|
88
|
+
data,
|
|
89
|
+
querySnapshot
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
async addDoc(path, data) {
|
|
93
|
+
const { addDoc, collection } = this.helpers;
|
|
94
|
+
const collectionRef = collection(this.db, path);
|
|
95
|
+
const docRef = await addDoc(collectionRef, data);
|
|
96
|
+
return docRef.id;
|
|
97
|
+
}
|
|
98
|
+
async setDoc(path, data) {
|
|
99
|
+
const { setDoc, doc } = this.helpers;
|
|
100
|
+
const docRef = doc(this.db, path);
|
|
101
|
+
await setDoc(docRef, data);
|
|
102
|
+
}
|
|
103
|
+
async updateDoc(path, data) {
|
|
104
|
+
const { updateDoc, doc } = this.helpers;
|
|
105
|
+
const docRef = doc(this.db, path);
|
|
106
|
+
await updateDoc(docRef, data);
|
|
107
|
+
}
|
|
108
|
+
async deleteDoc(path) {
|
|
109
|
+
const { deleteDoc, doc } = this.helpers;
|
|
110
|
+
const docRef = doc(this.db, path);
|
|
111
|
+
await deleteDoc(docRef);
|
|
112
|
+
}
|
|
113
|
+
async runTransaction(updateFunction) {
|
|
114
|
+
const { runTransaction } = this.helpers;
|
|
115
|
+
return runTransaction(this.db, updateFunction);
|
|
116
|
+
}
|
|
117
|
+
async runBatch(operations) {
|
|
118
|
+
const { writeBatch } = this.helpers;
|
|
119
|
+
const batch = writeBatch(this.db);
|
|
120
|
+
await Promise.all(operations.map((op) => op()));
|
|
121
|
+
await batch.commit();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var api = FirebaseAPI.getInstance();
|
|
125
|
+
|
|
126
|
+
// src/domains/assignment/assignment.constants.ts
|
|
127
|
+
var ASSIGNMENT_ANALYTICS_TYPES = [
|
|
128
|
+
"macro" /* Macro */,
|
|
129
|
+
"gradebook" /* Gradebook */,
|
|
130
|
+
"cards" /* Cards */,
|
|
131
|
+
"student" /* Student */,
|
|
132
|
+
"student_summary" /* StudentSummary */
|
|
133
|
+
];
|
|
134
|
+
var ASSIGNMENTS_COLLECTION = "assignments";
|
|
135
|
+
var ANALYTICS_SUBCOLLECTION = "analytics";
|
|
136
|
+
var SCORES_SUBCOLLECTION = "scores";
|
|
137
|
+
var refsAssignmentFiresotre = {
|
|
138
|
+
allAssignments: () => ASSIGNMENTS_COLLECTION,
|
|
139
|
+
assignment: (id) => `${ASSIGNMENTS_COLLECTION}/${id}`,
|
|
140
|
+
assignmentAllAnalytics: (id) => `${ASSIGNMENTS_COLLECTION}/${id}/${ANALYTICS_SUBCOLLECTION}`,
|
|
141
|
+
assignmentAnalytics: (id, type) => `${ASSIGNMENTS_COLLECTION}/${id}/${ANALYTICS_SUBCOLLECTION}/${type}`,
|
|
142
|
+
assignmentScores: (id, userId) => `${ASSIGNMENTS_COLLECTION}/${id}/${SCORES_SUBCOLLECTION}/${userId}`
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// src/domains/assignment/services/get-assignments-score.service.ts
|
|
146
|
+
var _getAssignmentScores = async ({
|
|
147
|
+
assignmentId,
|
|
148
|
+
analyticType = "macro" /* Macro */,
|
|
149
|
+
studentId,
|
|
150
|
+
currentUserId
|
|
151
|
+
}) => {
|
|
152
|
+
if (analyticType === "student" /* Student */) {
|
|
153
|
+
const path = refsAssignmentFiresotre.assignmentScores(assignmentId, currentUserId);
|
|
154
|
+
const response = await api.getDoc(path);
|
|
155
|
+
return { scores: response.data, id: assignmentId };
|
|
156
|
+
}
|
|
157
|
+
if (analyticType === "student_summary" /* StudentSummary */ && studentId) {
|
|
158
|
+
const path = refsAssignmentFiresotre.assignmentScores(assignmentId, studentId);
|
|
159
|
+
const response = await api.getDoc(path);
|
|
160
|
+
return { scores: response.data, id: assignmentId };
|
|
161
|
+
}
|
|
162
|
+
if (analyticType !== "all" /* All */ && ASSIGNMENT_ANALYTICS_TYPES.includes(analyticType)) {
|
|
163
|
+
const ref = refsAssignmentFiresotre.assignmentAnalytics(assignmentId, analyticType);
|
|
164
|
+
const docData = await api.getDoc(ref);
|
|
165
|
+
return { scores: docData.data, id: assignmentId };
|
|
166
|
+
} else if (analyticType === "all" /* All */) {
|
|
167
|
+
const ref = refsAssignmentFiresotre.assignmentAllAnalytics(assignmentId);
|
|
168
|
+
const response = await api.getDocs(ref);
|
|
169
|
+
const data = response.data.reduce((acc, curr) => {
|
|
170
|
+
acc[curr.id] = curr;
|
|
171
|
+
return acc;
|
|
172
|
+
}, {});
|
|
173
|
+
return { scores: data, id: assignmentId };
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
var getAssignmentScores = withErrorHandler(_getAssignmentScores, "getAssignmentScores");
|
|
177
|
+
|
|
178
|
+
// src/domains/assignment/services/attach-score-assignment.service.ts
|
|
179
|
+
var _attachScoresAssignment = async ({
|
|
180
|
+
assignments,
|
|
181
|
+
analyticType,
|
|
182
|
+
studentId,
|
|
183
|
+
currentUserId
|
|
184
|
+
}) => {
|
|
185
|
+
const scoresPromises = assignments.map((a) => {
|
|
186
|
+
return getAssignmentScores({
|
|
187
|
+
assignmentId: a.id,
|
|
188
|
+
analyticType,
|
|
189
|
+
studentId,
|
|
190
|
+
currentUserId
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
const scores = await Promise.all(scoresPromises);
|
|
194
|
+
const scoresObject = scores.reduce((acc, curr) => {
|
|
195
|
+
acc[curr.id] = curr.scores;
|
|
196
|
+
return acc;
|
|
197
|
+
}, {});
|
|
198
|
+
const assignmentsWithScores = assignments.map((a) => {
|
|
199
|
+
return {
|
|
200
|
+
...a,
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/ban-ts-comment
|
|
202
|
+
// @ts-ignore
|
|
203
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
204
|
+
scores: scoresObject[a.id] ?? null
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
return assignmentsWithScores;
|
|
208
|
+
};
|
|
209
|
+
var attachScoresAssignment = withErrorHandler(
|
|
210
|
+
_attachScoresAssignment,
|
|
211
|
+
"attachScoresAssignment"
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// src/domains/assignment/services/get-all-assignment.service.ts
|
|
215
|
+
async function _getAllAssignments() {
|
|
216
|
+
const path = refsAssignmentFiresotre.allAssignments();
|
|
217
|
+
const response = await api.getDocs(path);
|
|
218
|
+
return response.data;
|
|
219
|
+
}
|
|
220
|
+
var getAllAssignments = withErrorHandler(_getAllAssignments, "getAllAssignments");
|
|
221
|
+
|
|
222
|
+
// src/domains/assignment/utils/check-assignment-availability.ts
|
|
223
|
+
import dayjs from "dayjs";
|
|
224
|
+
var checkAssignmentAvailability = (scheduledTime) => {
|
|
225
|
+
if (!scheduledTime) return true;
|
|
226
|
+
const scheduledDate = typeof scheduledTime === "string" ? dayjs(scheduledTime) : dayjs(scheduledTime.toDate());
|
|
227
|
+
if (!scheduledDate.isValid()) return true;
|
|
228
|
+
return dayjs().isAfter(scheduledDate);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// src/domains/assignment/services/get-assignment.service.ts
|
|
232
|
+
async function _getAssignment(params) {
|
|
233
|
+
const path = refsAssignmentFiresotre.assignment(params.assignmentId);
|
|
234
|
+
const response = await api.getDoc(path);
|
|
235
|
+
if (!response.data) return null;
|
|
236
|
+
const assignment = response.data;
|
|
237
|
+
const isAvailable = checkAssignmentAvailability(assignment.scheduledTime);
|
|
238
|
+
const assignmentWithId = {
|
|
239
|
+
...assignment,
|
|
240
|
+
isAvailable,
|
|
241
|
+
id: params.assignmentId,
|
|
242
|
+
scheduledTime: assignment.scheduledTime ?? null
|
|
243
|
+
};
|
|
244
|
+
if (params.analyticType) {
|
|
245
|
+
const assignmentsWithScores = await attachScoresAssignment({
|
|
246
|
+
assignments: [assignmentWithId],
|
|
247
|
+
analyticType: params.analyticType,
|
|
248
|
+
currentUserId: params.currentUserId
|
|
249
|
+
});
|
|
250
|
+
return assignmentsWithScores.length > 0 ? assignmentsWithScores[0] : assignmentWithId;
|
|
251
|
+
}
|
|
252
|
+
return assignmentWithId;
|
|
253
|
+
}
|
|
254
|
+
var getAssignment = withErrorHandler(_getAssignment, "getAssignment");
|
|
255
|
+
|
|
4
256
|
// src/domains/assignment/assignment.repo.ts
|
|
5
|
-
var createAssignmentRepo = (
|
|
6
|
-
const { doc, collection, getDoc, getDocs } = h;
|
|
257
|
+
var createAssignmentRepo = () => {
|
|
7
258
|
return {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return { id, ...data };
|
|
13
|
-
},
|
|
14
|
-
async list() {
|
|
15
|
-
const col = collection(db, "assignments");
|
|
16
|
-
const snap = await getDocs(col);
|
|
17
|
-
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
18
|
-
}
|
|
259
|
+
getAssignment,
|
|
260
|
+
attachScoresAssignment,
|
|
261
|
+
getAssignmentScores,
|
|
262
|
+
getAllAssignments
|
|
19
263
|
};
|
|
20
264
|
};
|
|
21
265
|
|
|
@@ -26,11 +270,20 @@ var assignmentQueryKeys = {
|
|
|
26
270
|
byId: (id) => [...assignmentQueryKeys.all, id],
|
|
27
271
|
list: () => [...assignmentQueryKeys.all, "list"]
|
|
28
272
|
};
|
|
29
|
-
function useAssignment({
|
|
30
|
-
|
|
273
|
+
function useAssignment({
|
|
274
|
+
assignmentId,
|
|
275
|
+
enabled = true,
|
|
276
|
+
analyticType,
|
|
277
|
+
userId
|
|
278
|
+
}) {
|
|
279
|
+
const { speakableApi } = useSpeakableApi();
|
|
31
280
|
return useQuery({
|
|
32
|
-
queryKey: assignmentQueryKeys.byId(
|
|
33
|
-
queryFn: () =>
|
|
281
|
+
queryKey: assignmentQueryKeys.byId(assignmentId),
|
|
282
|
+
queryFn: () => speakableApi.assignmentRepo.getAssignment({
|
|
283
|
+
assignmentId,
|
|
284
|
+
analyticType,
|
|
285
|
+
currentUserId: userId
|
|
286
|
+
}),
|
|
34
287
|
enabled
|
|
35
288
|
});
|
|
36
289
|
}
|
|
@@ -39,8 +292,12 @@ function useAssignment({ id, enabled = true }) {
|
|
|
39
292
|
async function createFsClient(db, platform) {
|
|
40
293
|
const dbAsFirestore = db;
|
|
41
294
|
const helpers = platform === "web" ? await import("firebase/firestore") : await import("@react-native-firebase/firestore");
|
|
295
|
+
api.initialize({
|
|
296
|
+
db: dbAsFirestore,
|
|
297
|
+
helpers
|
|
298
|
+
});
|
|
42
299
|
return {
|
|
43
|
-
assignmentRepo: createAssignmentRepo(
|
|
300
|
+
assignmentRepo: createAssignmentRepo()
|
|
44
301
|
};
|
|
45
302
|
}
|
|
46
303
|
|
|
@@ -53,27 +310,27 @@ function SpeakableProvider({
|
|
|
53
310
|
children,
|
|
54
311
|
queryClient
|
|
55
312
|
}) {
|
|
56
|
-
const [
|
|
313
|
+
const [speakableApi, setSpeakableApi] = useState(null);
|
|
57
314
|
useEffect(() => {
|
|
58
315
|
createFsClient(db, platform).then((repos) => {
|
|
59
|
-
|
|
316
|
+
setSpeakableApi(repos);
|
|
60
317
|
});
|
|
61
318
|
}, [db, platform]);
|
|
62
|
-
if (!
|
|
319
|
+
if (!speakableApi) return null;
|
|
63
320
|
return /* @__PURE__ */ jsx(
|
|
64
321
|
FsCtx.Provider,
|
|
65
322
|
{
|
|
66
323
|
value: {
|
|
67
|
-
|
|
324
|
+
speakableApi,
|
|
68
325
|
queryClient
|
|
69
326
|
},
|
|
70
327
|
children
|
|
71
328
|
}
|
|
72
329
|
);
|
|
73
330
|
}
|
|
74
|
-
function
|
|
331
|
+
function useSpeakableApi() {
|
|
75
332
|
const ctx = useContext(FsCtx);
|
|
76
|
-
if (!ctx) throw new Error("
|
|
333
|
+
if (!ctx) throw new Error("useSpeakableApi must be used within a SpeakableProvider");
|
|
77
334
|
return ctx;
|
|
78
335
|
}
|
|
79
336
|
export {
|
|
@@ -83,5 +340,5 @@ export {
|
|
|
83
340
|
createAssignmentRepo,
|
|
84
341
|
createFsClient,
|
|
85
342
|
useAssignment,
|
|
86
|
-
|
|
343
|
+
useSpeakableApi
|
|
87
344
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speakableio/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/Speakable-io/speakable-core.git"
|
|
@@ -60,5 +60,8 @@
|
|
|
60
60
|
"publishConfig": {
|
|
61
61
|
"access": "restricted"
|
|
62
62
|
},
|
|
63
|
-
"types": "dist/index.d.ts"
|
|
63
|
+
"types": "dist/index.d.ts",
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"dayjs": "^1.11.13"
|
|
66
|
+
}
|
|
64
67
|
}
|