@speakableio/core 0.1.19 → 0.1.21
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 +19 -5
- package/dist/index.d.ts +19 -5
- package/dist/index.js +219 -83
- package/dist/index.mjs +167 -31
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -729,10 +729,11 @@ declare const useCreateNotification: () => {
|
|
|
729
729
|
};
|
|
730
730
|
|
|
731
731
|
type FsClient = ReturnType<typeof createFsClient>;
|
|
732
|
-
declare function createFsClient({ db, platform, httpsCallable, }: {
|
|
732
|
+
declare function createFsClient({ db, platform, httpsCallable, logEvent, }: {
|
|
733
733
|
db: FirebaseInstance;
|
|
734
734
|
platform: 'web' | 'native';
|
|
735
735
|
httpsCallable: (name: string) => CallableFunction;
|
|
736
|
+
logEvent: (name: string, data: any) => void;
|
|
736
737
|
}): Promise<{
|
|
737
738
|
assignmentRepo: {
|
|
738
739
|
getAssignment: (params: {
|
|
@@ -969,21 +970,27 @@ interface FsContext {
|
|
|
969
970
|
permissions: Permissions;
|
|
970
971
|
}
|
|
971
972
|
declare const FsCtx: React.Context<FsContext | null>;
|
|
972
|
-
declare function SpeakableProvider({ db, platform, children, queryClient, user, permissions, httpsCallable, }: {
|
|
973
|
+
declare function SpeakableProvider({ db, platform, children, queryClient, user, permissions, httpsCallable, logEvent, }: {
|
|
974
|
+
children: React.ReactNode;
|
|
973
975
|
user: User;
|
|
974
976
|
db: FirebaseInstance;
|
|
975
977
|
platform: 'web' | 'native';
|
|
976
978
|
queryClient: QueryClient;
|
|
977
979
|
permissions: Permissions;
|
|
978
980
|
httpsCallable: (name: string) => CallableFunction;
|
|
979
|
-
|
|
981
|
+
logEvent: (name: string, data: any) => void;
|
|
980
982
|
}): react_jsx_runtime.JSX.Element | null;
|
|
981
983
|
declare function useSpeakableApi(): FsContext;
|
|
982
984
|
|
|
983
|
-
declare function useActivity({ id, isAssignment, onAssignmentSubmitted, }: {
|
|
985
|
+
declare function useActivity({ id, isAssignment, onAssignmentSubmitted, ltiData, }: {
|
|
984
986
|
id: string;
|
|
985
987
|
isAssignment: boolean;
|
|
986
988
|
onAssignmentSubmitted: (assignmentId: string) => void;
|
|
989
|
+
ltiData?: {
|
|
990
|
+
lineItemId?: string;
|
|
991
|
+
lti_id?: string;
|
|
992
|
+
serviceKey?: string;
|
|
993
|
+
};
|
|
987
994
|
}): {
|
|
988
995
|
set: {
|
|
989
996
|
data: SetWithId | null | undefined;
|
|
@@ -1093,7 +1100,14 @@ declare function useActivity({ id, isAssignment, onAssignmentSubmitted, }: {
|
|
|
1093
1100
|
message?: undefined;
|
|
1094
1101
|
}>;
|
|
1095
1102
|
updateCard: (cardId: string, cardScore: CardScore) => void;
|
|
1096
|
-
logGradingStandardEntry: (
|
|
1103
|
+
logGradingStandardEntry: ({ cardId, gradingStandard, type, }: {
|
|
1104
|
+
cardId: string;
|
|
1105
|
+
gradingStandard: {
|
|
1106
|
+
level: string;
|
|
1107
|
+
justification: string;
|
|
1108
|
+
};
|
|
1109
|
+
type: "actfl" | "wida" | "custom";
|
|
1110
|
+
}) => void;
|
|
1097
1111
|
};
|
|
1098
1112
|
};
|
|
1099
1113
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -729,10 +729,11 @@ declare const useCreateNotification: () => {
|
|
|
729
729
|
};
|
|
730
730
|
|
|
731
731
|
type FsClient = ReturnType<typeof createFsClient>;
|
|
732
|
-
declare function createFsClient({ db, platform, httpsCallable, }: {
|
|
732
|
+
declare function createFsClient({ db, platform, httpsCallable, logEvent, }: {
|
|
733
733
|
db: FirebaseInstance;
|
|
734
734
|
platform: 'web' | 'native';
|
|
735
735
|
httpsCallable: (name: string) => CallableFunction;
|
|
736
|
+
logEvent: (name: string, data: any) => void;
|
|
736
737
|
}): Promise<{
|
|
737
738
|
assignmentRepo: {
|
|
738
739
|
getAssignment: (params: {
|
|
@@ -969,21 +970,27 @@ interface FsContext {
|
|
|
969
970
|
permissions: Permissions;
|
|
970
971
|
}
|
|
971
972
|
declare const FsCtx: React.Context<FsContext | null>;
|
|
972
|
-
declare function SpeakableProvider({ db, platform, children, queryClient, user, permissions, httpsCallable, }: {
|
|
973
|
+
declare function SpeakableProvider({ db, platform, children, queryClient, user, permissions, httpsCallable, logEvent, }: {
|
|
974
|
+
children: React.ReactNode;
|
|
973
975
|
user: User;
|
|
974
976
|
db: FirebaseInstance;
|
|
975
977
|
platform: 'web' | 'native';
|
|
976
978
|
queryClient: QueryClient;
|
|
977
979
|
permissions: Permissions;
|
|
978
980
|
httpsCallable: (name: string) => CallableFunction;
|
|
979
|
-
|
|
981
|
+
logEvent: (name: string, data: any) => void;
|
|
980
982
|
}): react_jsx_runtime.JSX.Element | null;
|
|
981
983
|
declare function useSpeakableApi(): FsContext;
|
|
982
984
|
|
|
983
|
-
declare function useActivity({ id, isAssignment, onAssignmentSubmitted, }: {
|
|
985
|
+
declare function useActivity({ id, isAssignment, onAssignmentSubmitted, ltiData, }: {
|
|
984
986
|
id: string;
|
|
985
987
|
isAssignment: boolean;
|
|
986
988
|
onAssignmentSubmitted: (assignmentId: string) => void;
|
|
989
|
+
ltiData?: {
|
|
990
|
+
lineItemId?: string;
|
|
991
|
+
lti_id?: string;
|
|
992
|
+
serviceKey?: string;
|
|
993
|
+
};
|
|
987
994
|
}): {
|
|
988
995
|
set: {
|
|
989
996
|
data: SetWithId | null | undefined;
|
|
@@ -1093,7 +1100,14 @@ declare function useActivity({ id, isAssignment, onAssignmentSubmitted, }: {
|
|
|
1093
1100
|
message?: undefined;
|
|
1094
1101
|
}>;
|
|
1095
1102
|
updateCard: (cardId: string, cardScore: CardScore) => void;
|
|
1096
|
-
logGradingStandardEntry: (
|
|
1103
|
+
logGradingStandardEntry: ({ cardId, gradingStandard, type, }: {
|
|
1104
|
+
cardId: string;
|
|
1105
|
+
gradingStandard: {
|
|
1106
|
+
level: string;
|
|
1107
|
+
justification: string;
|
|
1108
|
+
};
|
|
1109
|
+
type: "actfl" | "wida" | "custom";
|
|
1110
|
+
}) => void;
|
|
1097
1111
|
};
|
|
1098
1112
|
};
|
|
1099
1113
|
};
|
package/dist/index.js
CHANGED
|
@@ -57,6 +57,9 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
57
57
|
httpsCallable(functionName) {
|
|
58
58
|
return _optionalChain([this, 'access', _2 => _2.config, 'optionalAccess', _3 => _3.httpsCallable, 'call', _4 => _4(functionName)]);
|
|
59
59
|
}
|
|
60
|
+
logEvent(name, data) {
|
|
61
|
+
_optionalChain([this, 'access', _5 => _5.config, 'optionalAccess', _6 => _6.logEvent, 'call', _7 => _7(name, data)]);
|
|
62
|
+
}
|
|
60
63
|
accessQueryConstraints() {
|
|
61
64
|
const { query, orderBy, limit, startAt, startAfter, endAt, endBefore } = this.helpers;
|
|
62
65
|
return {
|
|
@@ -87,8 +90,6 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
87
90
|
id: docSnap.id,
|
|
88
91
|
...docSnap.data()
|
|
89
92
|
} : null;
|
|
90
|
-
console.log("getDoc", path);
|
|
91
|
-
console.log("getDoc db", this.db);
|
|
92
93
|
return {
|
|
93
94
|
id: docSnap.id,
|
|
94
95
|
data
|
|
@@ -99,8 +100,6 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
99
100
|
const collectionRef = collection(this.db, path);
|
|
100
101
|
const q = queryConstraints.length > 0 ? query(collectionRef, ...queryConstraints) : collectionRef;
|
|
101
102
|
const querySnapshot = await getDocs(q);
|
|
102
|
-
console.log("getDocs", path, queryConstraints);
|
|
103
|
-
console.log("getDocs db", this.db);
|
|
104
103
|
const data = querySnapshot.docs.map((doc) => ({
|
|
105
104
|
id: doc.id,
|
|
106
105
|
data: doc.data()
|
|
@@ -122,22 +121,16 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
122
121
|
async setDoc(path, data, options = {}) {
|
|
123
122
|
const { setDoc, doc } = this.helpers;
|
|
124
123
|
const docRef = doc(this.db, path);
|
|
125
|
-
console.log("setDoc", path, data);
|
|
126
|
-
console.log("setDoc db", this.db);
|
|
127
124
|
await setDoc(docRef, data, options);
|
|
128
125
|
}
|
|
129
126
|
async updateDoc(path, data) {
|
|
130
127
|
const { updateDoc, doc } = this.helpers;
|
|
131
|
-
console.log("updateDoc", path, data);
|
|
132
|
-
console.log("updateDoc db", this.db);
|
|
133
128
|
const docRef = doc(this.db, path);
|
|
134
129
|
await updateDoc(docRef, data);
|
|
135
130
|
}
|
|
136
131
|
async deleteDoc(path) {
|
|
137
132
|
const { deleteDoc, doc } = this.helpers;
|
|
138
133
|
const docRef = doc(this.db, path);
|
|
139
|
-
console.log("deleteDoc", path);
|
|
140
|
-
console.log("deleteDoc db", this.db);
|
|
141
134
|
await deleteDoc(docRef);
|
|
142
135
|
}
|
|
143
136
|
async runTransaction(updateFunction) {
|
|
@@ -505,7 +498,7 @@ var purify = (word) => {
|
|
|
505
498
|
return word.normalize("NFD").replace(/\/([^" "]*)/g, "").replace(/\([^()]*\)/g, "").replace(/([^()]*)/g, "").replace(/[\u0300-\u036f]/g, "").replace(/[-]/g, " ").replace(/[.,/#!¡¿?؟。,.?$%^&*;:{}=\-_`~()’'…\s]/g, "").replace(/\s\s+/g, " ").toLowerCase().trim();
|
|
506
499
|
};
|
|
507
500
|
var cleanString = (words) => {
|
|
508
|
-
const splitWords = _optionalChain([words, 'optionalAccess',
|
|
501
|
+
const splitWords = _optionalChain([words, 'optionalAccess', _8 => _8.split, 'call', _9 => _9("+")]);
|
|
509
502
|
if (splitWords && splitWords.length === 1) {
|
|
510
503
|
const newWord = purify(words);
|
|
511
504
|
return newWord;
|
|
@@ -519,13 +512,14 @@ var cleanString = (words) => {
|
|
|
519
512
|
var getWordHash = (word, language) => {
|
|
520
513
|
const cleanedWord = cleanString(word);
|
|
521
514
|
const wordHash = _jssha12.default.call(void 0, `${language}-${cleanedWord}`);
|
|
515
|
+
console.log("wordHash core library", wordHash);
|
|
522
516
|
return wordHash;
|
|
523
517
|
};
|
|
524
518
|
|
|
525
519
|
// src/domains/cards/services/get-card-verification-status.service.ts
|
|
526
520
|
var charactarLanguages = ["zh", "ja", "ko"];
|
|
527
521
|
var getVerificationStatus = async (target_text, language) => {
|
|
528
|
-
if (_optionalChain([target_text, 'optionalAccess',
|
|
522
|
+
if (_optionalChain([target_text, 'optionalAccess', _10 => _10.length]) < 3 && !charactarLanguages.includes(language)) {
|
|
529
523
|
return "NOT_RECOMMENDED" /* NOT_RECOMMENDED */;
|
|
530
524
|
}
|
|
531
525
|
const hash = getWordHash(target_text, language);
|
|
@@ -758,12 +752,13 @@ var SpeakableFirebaseFunctions = {
|
|
|
758
752
|
submitAssignmentV2: api.httpsCallable("submitLTIAssignmentScoreV2"),
|
|
759
753
|
submitAssessment: api.httpsCallable("submitAssessment"),
|
|
760
754
|
sendAssessmentScoredEmail: api.httpsCallable("sendAssessmentScoredEmail"),
|
|
761
|
-
createNotification: api.httpsCallable("createNotificationV2")
|
|
755
|
+
createNotification: api.httpsCallable("createNotificationV2"),
|
|
756
|
+
updateCourseAnalytics: api.httpsCallable("handleCouresAnalyticsEvent")
|
|
762
757
|
};
|
|
763
758
|
|
|
764
759
|
// src/domains/notification/services/send-notification.service.ts
|
|
765
760
|
var _sendNotification = async (sendTo, notification) => {
|
|
766
|
-
const results = await _optionalChain([SpeakableFirebaseFunctions, 'access',
|
|
761
|
+
const results = await _optionalChain([SpeakableFirebaseFunctions, 'access', _11 => _11.createNotification, 'optionalCall', _12 => _12({
|
|
767
762
|
sendTo,
|
|
768
763
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
769
764
|
notification
|
|
@@ -843,7 +838,7 @@ var createNewAssignmentNotification = async ({
|
|
|
843
838
|
link: `${WEB_BASE_URL}/assignment/${assignment.id}`,
|
|
844
839
|
messagePreview: `A new assignment "${assignment.name}" is now available. ${dueDate ? `Due ${dueDate}` : ""}`,
|
|
845
840
|
title: "New Assignment Available!",
|
|
846
|
-
imageUrl: _optionalChain([profile, 'access',
|
|
841
|
+
imageUrl: _optionalChain([profile, 'access', _13 => _13.image, 'optionalAccess', _14 => _14.url])
|
|
847
842
|
});
|
|
848
843
|
return results;
|
|
849
844
|
};
|
|
@@ -860,7 +855,7 @@ var createAssessmentSubmissionNotification = async ({
|
|
|
860
855
|
title: `Assessment Submitted!`,
|
|
861
856
|
senderName: studentName,
|
|
862
857
|
messagePreview: `${studentName} has submitted the assessment "${assignment.name}"`,
|
|
863
|
-
imageUrl: _optionalChain([profile, 'access',
|
|
858
|
+
imageUrl: _optionalChain([profile, 'access', _15 => _15.image, 'optionalAccess', _16 => _16.url])
|
|
864
859
|
});
|
|
865
860
|
return results;
|
|
866
861
|
};
|
|
@@ -878,13 +873,13 @@ var createAssessmentScoredNotification = async ({
|
|
|
878
873
|
link: `${WEB_BASE_URL}/assignment/${assignment.id}`,
|
|
879
874
|
title,
|
|
880
875
|
messagePreview,
|
|
881
|
-
imageUrl: _optionalChain([profile, 'access',
|
|
876
|
+
imageUrl: _optionalChain([profile, 'access', _17 => _17.image, 'optionalAccess', _18 => _18.url]),
|
|
882
877
|
senderName: teacherName
|
|
883
878
|
});
|
|
884
|
-
await _optionalChain([SpeakableFirebaseFunctions, 'access',
|
|
879
|
+
await _optionalChain([SpeakableFirebaseFunctions, 'access', _19 => _19.sendAssessmentScoredEmail, 'optionalCall', _20 => _20({
|
|
885
880
|
assessmentTitle: assignment.name,
|
|
886
881
|
link: `${WEB_BASE_URL}/assignment/${assignment.id}`,
|
|
887
|
-
senderImage: _optionalChain([profile, 'access',
|
|
882
|
+
senderImage: _optionalChain([profile, 'access', _21 => _21.image, 'optionalAccess', _22 => _22.url]) || "",
|
|
888
883
|
studentId: sendTo[0],
|
|
889
884
|
teacherName: profile.displayName
|
|
890
885
|
})]);
|
|
@@ -902,11 +897,11 @@ var useCreateNotification = () => {
|
|
|
902
897
|
const result = await createNotification({
|
|
903
898
|
type,
|
|
904
899
|
userId: user.auth.uid,
|
|
905
|
-
profile: _nullishCoalesce(_optionalChain([user, 'optionalAccess',
|
|
900
|
+
profile: _nullishCoalesce(_optionalChain([user, 'optionalAccess', _23 => _23.profile]), () => ( {})),
|
|
906
901
|
data
|
|
907
902
|
});
|
|
908
903
|
queryClient.invalidateQueries({
|
|
909
|
-
queryKey: notificationQueryKeys.byId(_nullishCoalesce(_optionalChain([user, 'optionalAccess',
|
|
904
|
+
queryKey: notificationQueryKeys.byId(_nullishCoalesce(_optionalChain([user, 'optionalAccess', _24 => _24.auth, 'access', _25 => _25.uid]), () => ( "")))
|
|
910
905
|
});
|
|
911
906
|
return result;
|
|
912
907
|
};
|
|
@@ -919,14 +914,16 @@ var useCreateNotification = () => {
|
|
|
919
914
|
async function createFsClient({
|
|
920
915
|
db,
|
|
921
916
|
platform,
|
|
922
|
-
httpsCallable
|
|
917
|
+
httpsCallable,
|
|
918
|
+
logEvent
|
|
923
919
|
}) {
|
|
924
920
|
const dbAsFirestore = db;
|
|
925
921
|
const helpers = platform === "web" ? await Promise.resolve().then(() => _interopRequireWildcard(require("firebase/firestore"))) : await Promise.resolve().then(() => _interopRequireWildcard(require("@react-native-firebase/firestore")));
|
|
926
922
|
api.initialize({
|
|
927
923
|
db: dbAsFirestore,
|
|
928
924
|
helpers,
|
|
929
|
-
httpsCallable
|
|
925
|
+
httpsCallable,
|
|
926
|
+
logEvent
|
|
930
927
|
});
|
|
931
928
|
return {
|
|
932
929
|
assignmentRepo: createAssignmentRepo(),
|
|
@@ -944,14 +941,16 @@ function SpeakableProvider({
|
|
|
944
941
|
queryClient,
|
|
945
942
|
user,
|
|
946
943
|
permissions,
|
|
947
|
-
httpsCallable
|
|
944
|
+
httpsCallable,
|
|
945
|
+
logEvent
|
|
948
946
|
}) {
|
|
949
947
|
const [speakableApi, setSpeakableApi] = _react.useState.call(void 0, null);
|
|
950
948
|
_react.useEffect.call(void 0, () => {
|
|
951
949
|
createFsClient({
|
|
952
950
|
db,
|
|
953
951
|
httpsCallable,
|
|
954
|
-
platform
|
|
952
|
+
platform,
|
|
953
|
+
logEvent
|
|
955
954
|
}).then((repos) => {
|
|
956
955
|
setSpeakableApi(repos);
|
|
957
956
|
});
|
|
@@ -1174,7 +1173,7 @@ var SpeakablePlanHierarchy = [
|
|
|
1174
1173
|
// src/hooks/usePermissions.ts
|
|
1175
1174
|
var usePermissions = () => {
|
|
1176
1175
|
const { permissions } = useSpeakableApi();
|
|
1177
|
-
const has = (permission) => _optionalChain([permissions, 'access',
|
|
1176
|
+
const has = (permission) => _optionalChain([permissions, 'access', _26 => _26.permissions, 'optionalAccess', _27 => _27.includes, 'call', _28 => _28(permission)]);
|
|
1178
1177
|
return {
|
|
1179
1178
|
plan: permissions.plan,
|
|
1180
1179
|
permissionsLoaded: permissions.loaded,
|
|
@@ -1213,8 +1212,8 @@ var useGoogleClassroom = () => {
|
|
|
1213
1212
|
message: "No Google Classroom ID found"
|
|
1214
1213
|
};
|
|
1215
1214
|
const { courseWorkId, maxPoints, owners, courseId } = assignment;
|
|
1216
|
-
const draftGrade = _optionalChain([scores, 'optionalAccess',
|
|
1217
|
-
const result = await _optionalChain([SpeakableFirebaseFunctions, 'access',
|
|
1215
|
+
const draftGrade = _optionalChain([scores, 'optionalAccess', _29 => _29.score]) ? _optionalChain([scores, 'optionalAccess', _30 => _30.score]) / 100 * maxPoints : 0;
|
|
1216
|
+
const result = await _optionalChain([SpeakableFirebaseFunctions, 'access', _31 => _31.submitAssignmentToGoogleClassroomV2, 'optionalCall', _32 => _32({
|
|
1218
1217
|
teacherId: owners[0],
|
|
1219
1218
|
courseId,
|
|
1220
1219
|
courseWorkId,
|
|
@@ -1231,6 +1230,61 @@ var useGoogleClassroom = () => {
|
|
|
1231
1230
|
};
|
|
1232
1231
|
};
|
|
1233
1232
|
|
|
1233
|
+
// src/lib/firebase/firebase-analytics/grading-standard.ts
|
|
1234
|
+
var logGradingStandardLog = (data) => {
|
|
1235
|
+
if (data.courseId && data.type && data.level) {
|
|
1236
|
+
_optionalChain([SpeakableFirebaseFunctions, 'access', _33 => _33.updateCourseAnalytics, 'optionalCall', _34 => _34({
|
|
1237
|
+
eventType: data.type || "custom",
|
|
1238
|
+
level: data.level,
|
|
1239
|
+
courseId: data.courseId
|
|
1240
|
+
})]);
|
|
1241
|
+
}
|
|
1242
|
+
api.logEvent("logGradingStandard", data);
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/constants/analytics.constants.ts
|
|
1246
|
+
var ANALYTICS_EVENT_TYPES = {
|
|
1247
|
+
VOICE_SUCCESS: "voice_success",
|
|
1248
|
+
VOICE_FAIL: "voice_fail",
|
|
1249
|
+
RESPOND_CARD_SUCCESS: "respond_card_success",
|
|
1250
|
+
RESPOND_CARD_FAIL: "respond_card_fail",
|
|
1251
|
+
RESPOND_WRITE_CARD_SUCCESS: "respond_write_card_success",
|
|
1252
|
+
RESPOND_WRITE_CARD_FAIL: "respond_write_card_fail",
|
|
1253
|
+
RESPOND_FREE_PLAN: "respond_free_plan",
|
|
1254
|
+
RESPOND_WRITE_FREE_PLAN: "respond_write_free_plan",
|
|
1255
|
+
SUBMISSION: "assignment_submitted",
|
|
1256
|
+
ASSIGNMENT_STARTED: "assignment_started",
|
|
1257
|
+
CREATE_ASSIGNMENT: "create_assignment",
|
|
1258
|
+
MC_SUCCESS: "multiple_choice_success",
|
|
1259
|
+
MC_FAIL: "multiple_choice_fail",
|
|
1260
|
+
ACTFL_LEVEL: "actfl_level",
|
|
1261
|
+
WIDA_LEVEL: "wida_level"
|
|
1262
|
+
};
|
|
1263
|
+
|
|
1264
|
+
// src/lib/firebase/firebase-analytics/assignment.ts
|
|
1265
|
+
var logOpenAssignment = (data = {}) => {
|
|
1266
|
+
api.logEvent("open_assignment", data);
|
|
1267
|
+
};
|
|
1268
|
+
var logOpenActivityPreview = (data = {}) => {
|
|
1269
|
+
api.logEvent("open_activity_preview", data);
|
|
1270
|
+
};
|
|
1271
|
+
var logSubmitAssignment = (data = {}) => {
|
|
1272
|
+
_optionalChain([SpeakableFirebaseFunctions, 'access', _35 => _35.updateCourseAnalytics, 'optionalCall', _36 => _36({
|
|
1273
|
+
eventType: ANALYTICS_EVENT_TYPES.SUBMISSION,
|
|
1274
|
+
...data
|
|
1275
|
+
})]);
|
|
1276
|
+
api.logEvent(ANALYTICS_EVENT_TYPES.SUBMISSION, data);
|
|
1277
|
+
};
|
|
1278
|
+
var logStartAssignment = (data = {}) => {
|
|
1279
|
+
if (data.courseId) {
|
|
1280
|
+
_optionalChain([SpeakableFirebaseFunctions, 'access', _37 => _37.updateCourseAnalytics, 'optionalCall', _38 => _38({
|
|
1281
|
+
eventType: ANALYTICS_EVENT_TYPES.ASSIGNMENT_STARTED,
|
|
1282
|
+
...data
|
|
1283
|
+
})]);
|
|
1284
|
+
}
|
|
1285
|
+
api.logEvent(ANALYTICS_EVENT_TYPES.ASSIGNMENT_STARTED, data);
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1234
1288
|
// src/domains/assignment/utils/create-default-score.ts
|
|
1235
1289
|
var defaultScore = (props) => {
|
|
1236
1290
|
const { serverTimestamp } = api.accessHelpers();
|
|
@@ -1269,7 +1323,7 @@ async function _createScore(params) {
|
|
|
1269
1323
|
id: params.activityId,
|
|
1270
1324
|
userId: params.userId
|
|
1271
1325
|
});
|
|
1272
|
-
await _optionalChain([SpeakableFirebaseFunctions, 'access',
|
|
1326
|
+
await _optionalChain([SpeakableFirebaseFunctions, 'access', _39 => _39.updateAssignmentGradebookStatus, 'optionalCall', _40 => _40({
|
|
1273
1327
|
assignmentId: params.activityId,
|
|
1274
1328
|
userId: params.userId,
|
|
1275
1329
|
status: "IN_PROGRESS",
|
|
@@ -1313,6 +1367,9 @@ async function getAssignmentScore({
|
|
|
1313
1367
|
}),
|
|
1314
1368
|
assignmentId: assignment.id
|
|
1315
1369
|
};
|
|
1370
|
+
logStartAssignment({
|
|
1371
|
+
courseId: assignment.courseId
|
|
1372
|
+
});
|
|
1316
1373
|
const result = await createScore({
|
|
1317
1374
|
activityId: assignment.id,
|
|
1318
1375
|
userId,
|
|
@@ -1371,16 +1428,15 @@ var getScore = withErrorHandler(_getScore, "getScore");
|
|
|
1371
1428
|
|
|
1372
1429
|
// src/domains/assignment/utils/calculateScoreAndProgress.ts
|
|
1373
1430
|
var calculateScoreAndProgress = (scores, cardsList, weights) => {
|
|
1374
|
-
console.log("calculateScoreAndProgress", scores, cardsList, weights);
|
|
1375
1431
|
const totalSetPoints = cardsList.reduce((acc, cardId) => {
|
|
1376
|
-
acc += _optionalChain([weights, 'optionalAccess',
|
|
1432
|
+
acc += _optionalChain([weights, 'optionalAccess', _41 => _41[cardId]]) || 1;
|
|
1377
1433
|
return acc;
|
|
1378
1434
|
}, 0);
|
|
1379
|
-
const totalPointsAwarded = Object.keys(_optionalChain([scores, 'optionalAccess',
|
|
1380
|
-
const cardScores = _optionalChain([scores, 'optionalAccess',
|
|
1381
|
-
if (_optionalChain([cardScores, 'optionalAccess',
|
|
1382
|
-
const score2 = _optionalChain([cardScores, 'optionalAccess',
|
|
1383
|
-
const weight = _optionalChain([weights, 'optionalAccess',
|
|
1435
|
+
const totalPointsAwarded = Object.keys(_optionalChain([scores, 'optionalAccess', _42 => _42.cards]) || {}).reduce((acc, cardId) => {
|
|
1436
|
+
const cardScores = _optionalChain([scores, 'optionalAccess', _43 => _43.cards, 'optionalAccess', _44 => _44[cardId]]);
|
|
1437
|
+
if (_optionalChain([cardScores, 'optionalAccess', _45 => _45.completed]) || _optionalChain([cardScores, 'optionalAccess', _46 => _46.score]) || _optionalChain([cardScores, 'optionalAccess', _47 => _47.score]) === 0) {
|
|
1438
|
+
const score2 = _optionalChain([cardScores, 'optionalAccess', _48 => _48.score]) || _optionalChain([cardScores, 'optionalAccess', _49 => _49.score]) === 0 ? Number(_nullishCoalesce(_optionalChain([cardScores, 'optionalAccess', _50 => _50.score]), () => ( 0))) : null;
|
|
1439
|
+
const weight = _optionalChain([weights, 'optionalAccess', _51 => _51[cardId]]) || 1;
|
|
1384
1440
|
const fraction = (_nullishCoalesce(score2, () => ( 0))) / 100;
|
|
1385
1441
|
if (score2 || score2 === 0) {
|
|
1386
1442
|
acc += weight * fraction;
|
|
@@ -1390,9 +1446,9 @@ var calculateScoreAndProgress = (scores, cardsList, weights) => {
|
|
|
1390
1446
|
}
|
|
1391
1447
|
return acc;
|
|
1392
1448
|
}, 0);
|
|
1393
|
-
const totalCompletedCards = Object.keys(_optionalChain([scores, 'optionalAccess',
|
|
1394
|
-
const cardScores = _optionalChain([scores, 'optionalAccess',
|
|
1395
|
-
if (_optionalChain([cardScores, 'optionalAccess',
|
|
1449
|
+
const totalCompletedCards = Object.keys(_optionalChain([scores, 'optionalAccess', _52 => _52.cards]) || {}).reduce((acc, cardId) => {
|
|
1450
|
+
const cardScores = _optionalChain([scores, 'optionalAccess', _53 => _53.cards, 'optionalAccess', _54 => _54[cardId]]);
|
|
1451
|
+
if (_optionalChain([cardScores, 'optionalAccess', _55 => _55.completed]) || _optionalChain([cardScores, 'optionalAccess', _56 => _56.score]) || _optionalChain([cardScores, 'optionalAccess', _57 => _57.score]) === 0) {
|
|
1396
1452
|
acc += 1;
|
|
1397
1453
|
}
|
|
1398
1454
|
return acc;
|
|
@@ -1526,7 +1582,7 @@ async function handleAssessment(assignment, userId, cardIds, setWeights, fieldsU
|
|
|
1526
1582
|
}
|
|
1527
1583
|
const { score: scoreCalculated } = calculateScoreAndProgress_default(response.data, cardIds, setWeights);
|
|
1528
1584
|
await api.updateDoc(path, { score: scoreCalculated, status: "PENDING_REVIEW" });
|
|
1529
|
-
await _optionalChain([SpeakableFirebaseFunctions, 'access',
|
|
1585
|
+
await _optionalChain([SpeakableFirebaseFunctions, 'access', _58 => _58.submitAssessment, 'optionalCall', _59 => _59({
|
|
1530
1586
|
assignmentId: assignment.id,
|
|
1531
1587
|
assignmentTitle: assignment.name,
|
|
1532
1588
|
userId,
|
|
@@ -1537,7 +1593,7 @@ async function handleAssessment(assignment, userId, cardIds, setWeights, fieldsU
|
|
|
1537
1593
|
return { success: true, fieldsUpdated };
|
|
1538
1594
|
}
|
|
1539
1595
|
async function handleCourseAssignment(assignment, userId) {
|
|
1540
|
-
await _optionalChain([SpeakableFirebaseFunctions, 'optionalAccess',
|
|
1596
|
+
await _optionalChain([SpeakableFirebaseFunctions, 'optionalAccess', _60 => _60.submitAssignmentV2, 'optionalCall', _61 => _61({
|
|
1541
1597
|
assignmentId: assignment.id,
|
|
1542
1598
|
userId
|
|
1543
1599
|
})]);
|
|
@@ -1602,7 +1658,7 @@ function useUpdateScore() {
|
|
|
1602
1658
|
});
|
|
1603
1659
|
},
|
|
1604
1660
|
onError: (_, variables, context) => {
|
|
1605
|
-
if (_optionalChain([context, 'optionalAccess',
|
|
1661
|
+
if (_optionalChain([context, 'optionalAccess', _62 => _62.previousData]))
|
|
1606
1662
|
queryClient.setQueryData(scoreQueryKeys.byId(variables.activityId), context.previousData);
|
|
1607
1663
|
},
|
|
1608
1664
|
onSettled: (_, err, variables) => {
|
|
@@ -1618,25 +1674,18 @@ function useUpdateScore() {
|
|
|
1618
1674
|
function useUpdateCardScore({
|
|
1619
1675
|
isAssignment,
|
|
1620
1676
|
activityId,
|
|
1621
|
-
userId
|
|
1677
|
+
userId,
|
|
1678
|
+
set
|
|
1622
1679
|
}) {
|
|
1623
1680
|
const { queryClient } = useSpeakableApi();
|
|
1624
|
-
const querySet = useSet({ setId: activityId });
|
|
1625
|
-
const dataCurrentSet = querySet.data;
|
|
1626
1681
|
const queryKey = scoreQueryKeys.byId(activityId);
|
|
1627
1682
|
const mutation = _reactquery.useMutation.call(void 0, {
|
|
1628
1683
|
mutationFn: async ({ cardId, cardScore }) => {
|
|
1629
1684
|
const previousScores = queryClient.getQueryData(queryKey);
|
|
1630
|
-
console.log("useUpdateCardScore", {
|
|
1631
|
-
previousScores: _nullishCoalesce(previousScores, () => ( {})),
|
|
1632
|
-
cardId,
|
|
1633
|
-
cardScore,
|
|
1634
|
-
activityId
|
|
1635
|
-
});
|
|
1636
1685
|
const { progress, score, newScoreUpdated, updatedCardScore } = getScoreUpdated({
|
|
1637
1686
|
previousScores: _nullishCoalesce(previousScores, () => ( {})),
|
|
1638
1687
|
cardId,
|
|
1639
|
-
set
|
|
1688
|
+
set,
|
|
1640
1689
|
cardScore
|
|
1641
1690
|
});
|
|
1642
1691
|
await updateCardScore({
|
|
@@ -1658,7 +1707,7 @@ function useUpdateCardScore({
|
|
|
1658
1707
|
score: previousScore,
|
|
1659
1708
|
cardId,
|
|
1660
1709
|
cardScore,
|
|
1661
|
-
set
|
|
1710
|
+
set
|
|
1662
1711
|
});
|
|
1663
1712
|
return {
|
|
1664
1713
|
...previousScore,
|
|
@@ -1685,7 +1734,7 @@ var getScoreUpdated = ({
|
|
|
1685
1734
|
previousScores,
|
|
1686
1735
|
set
|
|
1687
1736
|
}) => {
|
|
1688
|
-
const previousCard = _optionalChain([previousScores, 'access',
|
|
1737
|
+
const previousCard = _optionalChain([previousScores, 'access', _63 => _63.cards, 'optionalAccess', _64 => _64[cardId]]);
|
|
1689
1738
|
const newCardScore = {
|
|
1690
1739
|
..._nullishCoalesce(previousCard, () => ( {})),
|
|
1691
1740
|
...cardScore
|
|
@@ -1699,8 +1748,8 @@ var getScoreUpdated = ({
|
|
|
1699
1748
|
};
|
|
1700
1749
|
const { score, progress } = calculateScoreAndProgress_default(
|
|
1701
1750
|
newScores,
|
|
1702
|
-
_nullishCoalesce(_optionalChain([set, 'optionalAccess',
|
|
1703
|
-
_nullishCoalesce(_optionalChain([set, 'optionalAccess',
|
|
1751
|
+
_nullishCoalesce(_optionalChain([set, 'optionalAccess', _65 => _65.content]), () => ( [])),
|
|
1752
|
+
_nullishCoalesce(_optionalChain([set, 'optionalAccess', _66 => _66.weights]), () => ( {}))
|
|
1704
1753
|
);
|
|
1705
1754
|
return {
|
|
1706
1755
|
newScoreUpdated: newScores,
|
|
@@ -1715,7 +1764,7 @@ var handleOptimisticScore = ({
|
|
|
1715
1764
|
cardScore,
|
|
1716
1765
|
set
|
|
1717
1766
|
}) => {
|
|
1718
|
-
let cards = { ..._nullishCoalesce(_optionalChain([score, 'optionalAccess',
|
|
1767
|
+
let cards = { ..._nullishCoalesce(_optionalChain([score, 'optionalAccess', _67 => _67.cards]), () => ( {})) };
|
|
1719
1768
|
cards = {
|
|
1720
1769
|
...cards,
|
|
1721
1770
|
[cardId]: {
|
|
@@ -1729,8 +1778,8 @@ var handleOptimisticScore = ({
|
|
|
1729
1778
|
..._nullishCoalesce(score, () => ( {})),
|
|
1730
1779
|
cards
|
|
1731
1780
|
},
|
|
1732
|
-
_nullishCoalesce(_optionalChain([set, 'optionalAccess',
|
|
1733
|
-
_nullishCoalesce(_optionalChain([set, 'optionalAccess',
|
|
1781
|
+
_nullishCoalesce(_optionalChain([set, 'optionalAccess', _68 => _68.content]), () => ( [])),
|
|
1782
|
+
_nullishCoalesce(_optionalChain([set, 'optionalAccess', _69 => _69.weights]), () => ( {}))
|
|
1734
1783
|
);
|
|
1735
1784
|
return { cards, score: scoreValue, progress };
|
|
1736
1785
|
};
|
|
@@ -1740,7 +1789,7 @@ function useClearScore() {
|
|
|
1740
1789
|
mutationFn: clearScore,
|
|
1741
1790
|
onSettled: (result) => {
|
|
1742
1791
|
queryClient.invalidateQueries({
|
|
1743
|
-
queryKey: scoreQueryKeys.byId(_nullishCoalesce(_optionalChain([result, 'optionalAccess',
|
|
1792
|
+
queryKey: scoreQueryKeys.byId(_nullishCoalesce(_optionalChain([result, 'optionalAccess', _70 => _70.activityId]), () => ( "")))
|
|
1744
1793
|
});
|
|
1745
1794
|
}
|
|
1746
1795
|
});
|
|
@@ -1783,6 +1832,11 @@ function useSubmitAssignmentScore({
|
|
|
1783
1832
|
if (assignment.isAssessment) {
|
|
1784
1833
|
createNotification2(SpeakableNotificationTypes.ASSESSMENT_SUBMITTED, assignment);
|
|
1785
1834
|
}
|
|
1835
|
+
if (_optionalChain([assignment, 'optionalAccess', _71 => _71.id])) {
|
|
1836
|
+
logSubmitAssignment({
|
|
1837
|
+
courseId: _optionalChain([assignment, 'optionalAccess', _72 => _72.courseId])
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1786
1840
|
onAssignmentSubmitted(assignment.id);
|
|
1787
1841
|
queryClient.setQueryData(scoreQueryKeys.byId(assignment.id), {
|
|
1788
1842
|
...scores,
|
|
@@ -1843,6 +1897,13 @@ function useSubmitPracticeScore() {
|
|
|
1843
1897
|
// src/hooks/useActivity.ts
|
|
1844
1898
|
|
|
1845
1899
|
|
|
1900
|
+
// src/services/add-grading-standard.ts
|
|
1901
|
+
var addGradingStandardLog = async (gradingStandard, userId) => {
|
|
1902
|
+
logGradingStandardLog(gradingStandard);
|
|
1903
|
+
const path = `users/${userId}/grading_standard_logs`;
|
|
1904
|
+
await api.addDoc(path, gradingStandard);
|
|
1905
|
+
};
|
|
1906
|
+
|
|
1846
1907
|
// src/hooks/useActivityTracker.ts
|
|
1847
1908
|
|
|
1848
1909
|
function useActivityTracker({ userId }) {
|
|
@@ -1874,7 +1935,8 @@ function useActivityTracker({ userId }) {
|
|
|
1874
1935
|
function useActivity({
|
|
1875
1936
|
id,
|
|
1876
1937
|
isAssignment,
|
|
1877
|
-
onAssignmentSubmitted
|
|
1938
|
+
onAssignmentSubmitted,
|
|
1939
|
+
ltiData
|
|
1878
1940
|
}) {
|
|
1879
1941
|
const { queryClient, user } = useSpeakableApi();
|
|
1880
1942
|
const userId = user.auth.uid;
|
|
@@ -1884,12 +1946,12 @@ function useActivity({
|
|
|
1884
1946
|
enabled: isAssignment
|
|
1885
1947
|
});
|
|
1886
1948
|
const activeAssignment = assignmentQuery.data;
|
|
1887
|
-
const setId = isAssignment ? _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess',
|
|
1949
|
+
const setId = isAssignment ? _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess', _73 => _73.setId]), () => ( "")) : id;
|
|
1888
1950
|
const querySet = useSet({ setId });
|
|
1889
1951
|
const setData = querySet.data;
|
|
1890
|
-
const activityId = isAssignment ? _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess',
|
|
1952
|
+
const activityId = isAssignment ? _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess', _74 => _74.id]), () => ( "")) : setId;
|
|
1891
1953
|
const { cardsObject, cardsQueries, cards } = useCards({
|
|
1892
|
-
cardIds: _nullishCoalesce(_optionalChain([setData, 'optionalAccess',
|
|
1954
|
+
cardIds: _nullishCoalesce(_optionalChain([setData, 'optionalAccess', _75 => _75.content]), () => ( [])),
|
|
1893
1955
|
enabled: querySet.isSuccess,
|
|
1894
1956
|
asObject: true
|
|
1895
1957
|
});
|
|
@@ -1897,7 +1959,7 @@ function useActivity({
|
|
|
1897
1959
|
isAssignment,
|
|
1898
1960
|
activityId: id,
|
|
1899
1961
|
userId,
|
|
1900
|
-
courseId: _optionalChain([activeAssignment, 'optionalAccess',
|
|
1962
|
+
courseId: _optionalChain([activeAssignment, 'optionalAccess', _76 => _76.courseId]),
|
|
1901
1963
|
googleClassroomUserId: user.profile.googleClassroomUserId,
|
|
1902
1964
|
enabled: isAssignment ? assignmentQuery.isSuccess : querySet.isSuccess
|
|
1903
1965
|
});
|
|
@@ -1905,7 +1967,8 @@ function useActivity({
|
|
|
1905
1967
|
const { mutationUpdateCardScore } = useUpdateCardScore({
|
|
1906
1968
|
activityId,
|
|
1907
1969
|
isAssignment,
|
|
1908
|
-
userId
|
|
1970
|
+
userId,
|
|
1971
|
+
set: _nullishCoalesce(querySet.data, () => ( void 0))
|
|
1909
1972
|
});
|
|
1910
1973
|
const { mutationClearScore } = useClearScore();
|
|
1911
1974
|
const { submitAssignmentScore: submitAssignmentScore2 } = useSubmitAssignmentScore({
|
|
@@ -1928,12 +1991,12 @@ function useActivity({
|
|
|
1928
1991
|
cardId,
|
|
1929
1992
|
wasCompleted = true
|
|
1930
1993
|
}) => {
|
|
1931
|
-
const currentCard = _optionalChain([cardsObject, 'optionalAccess',
|
|
1932
|
-
if (_optionalChain([currentCard, 'optionalAccess',
|
|
1994
|
+
const currentCard = _optionalChain([cardsObject, 'optionalAccess', _77 => _77[cardId]]);
|
|
1995
|
+
if (_optionalChain([currentCard, 'optionalAccess', _78 => _78.type]) === "MULTIPLE_CHOICE" /* MULTIPLE_CHOICE */ || _optionalChain([currentCard, 'optionalAccess', _79 => _79.type]) === "READ_REPEAT" /* READ_REPEAT */) {
|
|
1933
1996
|
return;
|
|
1934
1997
|
}
|
|
1935
1998
|
const queryKeys = scoreQueryKeys.byId(activityId);
|
|
1936
|
-
const activeCardScores = _optionalChain([queryClient, 'access',
|
|
1999
|
+
const activeCardScores = _optionalChain([queryClient, 'access', _80 => _80.getQueryData, 'call', _81 => _81(queryKeys), 'optionalAccess', _82 => _82.cards, 'optionalAccess', _83 => _83[cardId]]);
|
|
1937
2000
|
if (activeCardScores === void 0) return;
|
|
1938
2001
|
mutationClearScore.mutate({
|
|
1939
2002
|
isAssignment,
|
|
@@ -1947,21 +2010,30 @@ function useActivity({
|
|
|
1947
2010
|
try {
|
|
1948
2011
|
let results;
|
|
1949
2012
|
if (isAssignment) {
|
|
1950
|
-
const cardScores = _optionalChain([scoreQuery, 'access',
|
|
2013
|
+
const cardScores = _optionalChain([scoreQuery, 'access', _84 => _84.data, 'optionalAccess', _85 => _85.cards]) || {};
|
|
1951
2014
|
const hasPendingReview = Object.values(cardScores).some(
|
|
1952
2015
|
(cardScore) => cardScore.status === "pending_review"
|
|
1953
2016
|
);
|
|
1954
2017
|
results = await submitAssignmentScore2({
|
|
1955
2018
|
assignment: assignmentQuery.data,
|
|
1956
2019
|
userId,
|
|
1957
|
-
cardIds: _nullishCoalesce(_optionalChain([setData, 'optionalAccess',
|
|
2020
|
+
cardIds: _nullishCoalesce(_optionalChain([setData, 'optionalAccess', _86 => _86.content]), () => ( [])),
|
|
1958
2021
|
scores: scoreQuery.data,
|
|
1959
|
-
setWeights: _nullishCoalesce(_optionalChain([setData, 'optionalAccess',
|
|
2022
|
+
setWeights: _nullishCoalesce(_optionalChain([setData, 'optionalAccess', _87 => _87.weights]), () => ( {})),
|
|
1960
2023
|
status: hasPendingReview ? "PENDING_REVIEW" : "FINALIZED"
|
|
1961
2024
|
});
|
|
2025
|
+
if (_optionalChain([assignmentQuery, 'access', _88 => _88.data, 'optionalAccess', _89 => _89.ltiDeeplink])) {
|
|
2026
|
+
submitLTIScore({
|
|
2027
|
+
maxPoints: _optionalChain([assignmentQuery, 'access', _90 => _90.data, 'optionalAccess', _91 => _91.maxPoints]),
|
|
2028
|
+
score: _nullishCoalesce(_optionalChain([scoreQuery, 'access', _92 => _92.data, 'optionalAccess', _93 => _93.score]), () => ( 0)),
|
|
2029
|
+
SERVICE_KEY: _nullishCoalesce(_optionalChain([ltiData, 'optionalAccess', _94 => _94.serviceKey]), () => ( "")),
|
|
2030
|
+
lineItemId: _nullishCoalesce(_optionalChain([ltiData, 'optionalAccess', _95 => _95.lineItemId]), () => ( "")),
|
|
2031
|
+
lti_id: _nullishCoalesce(_optionalChain([ltiData, 'optionalAccess', _96 => _96.lti_id]), () => ( ""))
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
1962
2034
|
} else {
|
|
1963
2035
|
results = await submitPracticeScore2({
|
|
1964
|
-
setId: _nullishCoalesce(_optionalChain([querySet, 'access',
|
|
2036
|
+
setId: _nullishCoalesce(_optionalChain([querySet, 'access', _97 => _97.data, 'optionalAccess', _98 => _98.id]), () => ( "")),
|
|
1965
2037
|
userId,
|
|
1966
2038
|
scores: scoreQuery.data
|
|
1967
2039
|
});
|
|
@@ -1974,6 +2046,41 @@ function useActivity({
|
|
|
1974
2046
|
};
|
|
1975
2047
|
}
|
|
1976
2048
|
};
|
|
2049
|
+
const logGradingStandardEntry = ({
|
|
2050
|
+
cardId,
|
|
2051
|
+
gradingStandard,
|
|
2052
|
+
type
|
|
2053
|
+
}) => {
|
|
2054
|
+
const card = _optionalChain([cardsObject, 'optionalAccess', _99 => _99[cardId]]);
|
|
2055
|
+
const scoresObject = queryClient.getQueryData(scoreQueryKeys.byId(activityId));
|
|
2056
|
+
const cardScore = _optionalChain([scoresObject, 'optionalAccess', _100 => _100.cards, 'optionalAccess', _101 => _101[cardId]]);
|
|
2057
|
+
const serverTimestamp = api.helpers.serverTimestamp;
|
|
2058
|
+
addGradingStandardLog(
|
|
2059
|
+
{
|
|
2060
|
+
assignmentId: _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess', _102 => _102.id]), () => ( "")),
|
|
2061
|
+
courseId: _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess', _103 => _103.courseId]), () => ( "")),
|
|
2062
|
+
teacherId: _nullishCoalesce(_optionalChain([activeAssignment, 'optionalAccess', _104 => _104.owners, 'access', _105 => _105[0]]), () => ( "")),
|
|
2063
|
+
setId: _nullishCoalesce(_optionalChain([setData, 'optionalAccess', _106 => _106.id]), () => ( "")),
|
|
2064
|
+
cardId,
|
|
2065
|
+
level: gradingStandard.level,
|
|
2066
|
+
justification: gradingStandard.justification,
|
|
2067
|
+
transcript: _nullishCoalesce(_optionalChain([cardScore, 'optionalAccess', _107 => _107.transcript]), () => ( "")),
|
|
2068
|
+
audioUrl: _nullishCoalesce(_optionalChain([cardScore, 'optionalAccess', _108 => _108.audio]), () => ( "")),
|
|
2069
|
+
prompt: _nullishCoalesce(_optionalChain([card, 'optionalAccess', _109 => _109.prompt]), () => ( "")),
|
|
2070
|
+
responseType: _optionalChain([card, 'optionalAccess', _110 => _110.type]) === "RESPOND_WRITE" /* RESPOND_WRITE */ ? "written" : "spoken",
|
|
2071
|
+
type,
|
|
2072
|
+
dateMade: serverTimestamp()
|
|
2073
|
+
},
|
|
2074
|
+
userId
|
|
2075
|
+
);
|
|
2076
|
+
};
|
|
2077
|
+
_react.useEffect.call(void 0, () => {
|
|
2078
|
+
if (isAssignment) {
|
|
2079
|
+
logOpenAssignment({ assignmentId: id });
|
|
2080
|
+
} else {
|
|
2081
|
+
logOpenActivityPreview({ setId: id });
|
|
2082
|
+
}
|
|
2083
|
+
}, []);
|
|
1977
2084
|
useInitActivity({
|
|
1978
2085
|
assignment: _nullishCoalesce(activeAssignment, () => ( void 0)),
|
|
1979
2086
|
set: _nullishCoalesce(setData, () => ( void 0)),
|
|
@@ -2002,8 +2109,7 @@ function useActivity({
|
|
|
2002
2109
|
clear: onClearScore,
|
|
2003
2110
|
submit: onSubmitScore,
|
|
2004
2111
|
updateCard: handleUpdateCardScore,
|
|
2005
|
-
logGradingStandardEntry
|
|
2006
|
-
}
|
|
2112
|
+
logGradingStandardEntry
|
|
2007
2113
|
}
|
|
2008
2114
|
}
|
|
2009
2115
|
};
|
|
@@ -2019,34 +2125,64 @@ var useInitActivity = ({
|
|
|
2019
2125
|
if (!enabled) return;
|
|
2020
2126
|
if (!assignment) {
|
|
2021
2127
|
trackActivity({
|
|
2022
|
-
activityName: _nullishCoalesce(_optionalChain([set, 'optionalAccess',
|
|
2128
|
+
activityName: _nullishCoalesce(_optionalChain([set, 'optionalAccess', _111 => _111.name]), () => ( "")),
|
|
2023
2129
|
activityType: "set",
|
|
2024
|
-
id: _optionalChain([set, 'optionalAccess',
|
|
2025
|
-
language: _optionalChain([set, 'optionalAccess',
|
|
2130
|
+
id: _optionalChain([set, 'optionalAccess', _112 => _112.id]),
|
|
2131
|
+
language: _optionalChain([set, 'optionalAccess', _113 => _113.language])
|
|
2026
2132
|
});
|
|
2027
2133
|
} else if (assignment.name) {
|
|
2028
2134
|
trackActivity({
|
|
2029
2135
|
activityName: assignment.name,
|
|
2030
2136
|
activityType: assignment.isAssessment ? "assessment" : "assignment",
|
|
2031
2137
|
id: assignment.id,
|
|
2032
|
-
language: _optionalChain([set, 'optionalAccess',
|
|
2138
|
+
language: _optionalChain([set, 'optionalAccess', _114 => _114.language])
|
|
2033
2139
|
});
|
|
2034
2140
|
}
|
|
2035
|
-
if (_optionalChain([set, 'optionalAccess',
|
|
2036
|
-
_optionalChain([SpeakableFirebaseFunctions, 'optionalAccess',
|
|
2141
|
+
if (_optionalChain([set, 'optionalAccess', _115 => _115.public])) {
|
|
2142
|
+
_optionalChain([SpeakableFirebaseFunctions, 'optionalAccess', _116 => _116.onSetOpened, 'optionalCall', _117 => _117({
|
|
2037
2143
|
setId: set.id,
|
|
2038
2144
|
language: set.language
|
|
2039
2145
|
})]);
|
|
2040
2146
|
}
|
|
2041
|
-
_optionalChain([SpeakableFirebaseFunctions, 'optionalAccess',
|
|
2147
|
+
_optionalChain([SpeakableFirebaseFunctions, 'optionalAccess', _118 => _118.updateAlgoliaIndex, 'optionalCall', _119 => _119({
|
|
2042
2148
|
updatePlays: true,
|
|
2043
|
-
objectID: _optionalChain([set, 'optionalAccess',
|
|
2149
|
+
objectID: _optionalChain([set, 'optionalAccess', _120 => _120.id])
|
|
2044
2150
|
})]);
|
|
2045
2151
|
};
|
|
2046
2152
|
_react.useEffect.call(void 0, () => {
|
|
2047
2153
|
init();
|
|
2048
2154
|
}, [set]);
|
|
2049
2155
|
};
|
|
2156
|
+
var submitLTIScore = async ({
|
|
2157
|
+
maxPoints,
|
|
2158
|
+
score,
|
|
2159
|
+
SERVICE_KEY,
|
|
2160
|
+
lineItemId,
|
|
2161
|
+
lti_id
|
|
2162
|
+
}) => {
|
|
2163
|
+
try {
|
|
2164
|
+
if (!SERVICE_KEY || !lineItemId || !lti_id) {
|
|
2165
|
+
throw new Error("Missing required LTI credentials");
|
|
2166
|
+
}
|
|
2167
|
+
const earnedPoints = score ? score / 100 * maxPoints : 0;
|
|
2168
|
+
const { data } = await _optionalChain([SpeakableFirebaseFunctions, 'optionalAccess', _121 => _121.submitLTIAssignmentScore, 'optionalCall', _122 => _122({
|
|
2169
|
+
SERVICE_KEY,
|
|
2170
|
+
scoreData: {
|
|
2171
|
+
lineItemId,
|
|
2172
|
+
userId: lti_id,
|
|
2173
|
+
maxPoints,
|
|
2174
|
+
earnedPoints
|
|
2175
|
+
}
|
|
2176
|
+
})]);
|
|
2177
|
+
return { success: true, data };
|
|
2178
|
+
} catch (error) {
|
|
2179
|
+
console.error("Failed to submit LTI score:", error);
|
|
2180
|
+
return {
|
|
2181
|
+
success: false,
|
|
2182
|
+
error: error instanceof Error ? error : new Error("Unknown error occurred")
|
|
2183
|
+
};
|
|
2184
|
+
}
|
|
2185
|
+
};
|
|
2050
2186
|
|
|
2051
2187
|
|
|
2052
2188
|
|
package/dist/index.mjs
CHANGED
|
@@ -57,6 +57,9 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
57
57
|
httpsCallable(functionName) {
|
|
58
58
|
return this.config?.httpsCallable(functionName);
|
|
59
59
|
}
|
|
60
|
+
logEvent(name, data) {
|
|
61
|
+
this.config?.logEvent(name, data);
|
|
62
|
+
}
|
|
60
63
|
accessQueryConstraints() {
|
|
61
64
|
const { query, orderBy, limit, startAt, startAfter, endAt, endBefore } = this.helpers;
|
|
62
65
|
return {
|
|
@@ -87,8 +90,6 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
87
90
|
id: docSnap.id,
|
|
88
91
|
...docSnap.data()
|
|
89
92
|
} : null;
|
|
90
|
-
console.log("getDoc", path);
|
|
91
|
-
console.log("getDoc db", this.db);
|
|
92
93
|
return {
|
|
93
94
|
id: docSnap.id,
|
|
94
95
|
data
|
|
@@ -99,8 +100,6 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
99
100
|
const collectionRef = collection(this.db, path);
|
|
100
101
|
const q = queryConstraints.length > 0 ? query(collectionRef, ...queryConstraints) : collectionRef;
|
|
101
102
|
const querySnapshot = await getDocs(q);
|
|
102
|
-
console.log("getDocs", path, queryConstraints);
|
|
103
|
-
console.log("getDocs db", this.db);
|
|
104
103
|
const data = querySnapshot.docs.map((doc) => ({
|
|
105
104
|
id: doc.id,
|
|
106
105
|
data: doc.data()
|
|
@@ -122,22 +121,16 @@ var FirebaseAPI = class _FirebaseAPI {
|
|
|
122
121
|
async setDoc(path, data, options = {}) {
|
|
123
122
|
const { setDoc, doc } = this.helpers;
|
|
124
123
|
const docRef = doc(this.db, path);
|
|
125
|
-
console.log("setDoc", path, data);
|
|
126
|
-
console.log("setDoc db", this.db);
|
|
127
124
|
await setDoc(docRef, data, options);
|
|
128
125
|
}
|
|
129
126
|
async updateDoc(path, data) {
|
|
130
127
|
const { updateDoc, doc } = this.helpers;
|
|
131
|
-
console.log("updateDoc", path, data);
|
|
132
|
-
console.log("updateDoc db", this.db);
|
|
133
128
|
const docRef = doc(this.db, path);
|
|
134
129
|
await updateDoc(docRef, data);
|
|
135
130
|
}
|
|
136
131
|
async deleteDoc(path) {
|
|
137
132
|
const { deleteDoc, doc } = this.helpers;
|
|
138
133
|
const docRef = doc(this.db, path);
|
|
139
|
-
console.log("deleteDoc", path);
|
|
140
|
-
console.log("deleteDoc db", this.db);
|
|
141
134
|
await deleteDoc(docRef);
|
|
142
135
|
}
|
|
143
136
|
async runTransaction(updateFunction) {
|
|
@@ -519,6 +512,7 @@ var cleanString = (words) => {
|
|
|
519
512
|
var getWordHash = (word, language) => {
|
|
520
513
|
const cleanedWord = cleanString(word);
|
|
521
514
|
const wordHash = sha1(`${language}-${cleanedWord}`);
|
|
515
|
+
console.log("wordHash core library", wordHash);
|
|
522
516
|
return wordHash;
|
|
523
517
|
};
|
|
524
518
|
|
|
@@ -758,7 +752,8 @@ var SpeakableFirebaseFunctions = {
|
|
|
758
752
|
submitAssignmentV2: api.httpsCallable("submitLTIAssignmentScoreV2"),
|
|
759
753
|
submitAssessment: api.httpsCallable("submitAssessment"),
|
|
760
754
|
sendAssessmentScoredEmail: api.httpsCallable("sendAssessmentScoredEmail"),
|
|
761
|
-
createNotification: api.httpsCallable("createNotificationV2")
|
|
755
|
+
createNotification: api.httpsCallable("createNotificationV2"),
|
|
756
|
+
updateCourseAnalytics: api.httpsCallable("handleCouresAnalyticsEvent")
|
|
762
757
|
};
|
|
763
758
|
|
|
764
759
|
// src/domains/notification/services/send-notification.service.ts
|
|
@@ -919,14 +914,16 @@ var useCreateNotification = () => {
|
|
|
919
914
|
async function createFsClient({
|
|
920
915
|
db,
|
|
921
916
|
platform,
|
|
922
|
-
httpsCallable
|
|
917
|
+
httpsCallable,
|
|
918
|
+
logEvent
|
|
923
919
|
}) {
|
|
924
920
|
const dbAsFirestore = db;
|
|
925
921
|
const helpers = platform === "web" ? await import("firebase/firestore") : await import("@react-native-firebase/firestore");
|
|
926
922
|
api.initialize({
|
|
927
923
|
db: dbAsFirestore,
|
|
928
924
|
helpers,
|
|
929
|
-
httpsCallable
|
|
925
|
+
httpsCallable,
|
|
926
|
+
logEvent
|
|
930
927
|
});
|
|
931
928
|
return {
|
|
932
929
|
assignmentRepo: createAssignmentRepo(),
|
|
@@ -944,14 +941,16 @@ function SpeakableProvider({
|
|
|
944
941
|
queryClient,
|
|
945
942
|
user,
|
|
946
943
|
permissions,
|
|
947
|
-
httpsCallable
|
|
944
|
+
httpsCallable,
|
|
945
|
+
logEvent
|
|
948
946
|
}) {
|
|
949
947
|
const [speakableApi, setSpeakableApi] = useState(null);
|
|
950
948
|
useEffect(() => {
|
|
951
949
|
createFsClient({
|
|
952
950
|
db,
|
|
953
951
|
httpsCallable,
|
|
954
|
-
platform
|
|
952
|
+
platform,
|
|
953
|
+
logEvent
|
|
955
954
|
}).then((repos) => {
|
|
956
955
|
setSpeakableApi(repos);
|
|
957
956
|
});
|
|
@@ -1231,6 +1230,61 @@ var useGoogleClassroom = () => {
|
|
|
1231
1230
|
};
|
|
1232
1231
|
};
|
|
1233
1232
|
|
|
1233
|
+
// src/lib/firebase/firebase-analytics/grading-standard.ts
|
|
1234
|
+
var logGradingStandardLog = (data) => {
|
|
1235
|
+
if (data.courseId && data.type && data.level) {
|
|
1236
|
+
SpeakableFirebaseFunctions.updateCourseAnalytics?.({
|
|
1237
|
+
eventType: data.type || "custom",
|
|
1238
|
+
level: data.level,
|
|
1239
|
+
courseId: data.courseId
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
api.logEvent("logGradingStandard", data);
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/constants/analytics.constants.ts
|
|
1246
|
+
var ANALYTICS_EVENT_TYPES = {
|
|
1247
|
+
VOICE_SUCCESS: "voice_success",
|
|
1248
|
+
VOICE_FAIL: "voice_fail",
|
|
1249
|
+
RESPOND_CARD_SUCCESS: "respond_card_success",
|
|
1250
|
+
RESPOND_CARD_FAIL: "respond_card_fail",
|
|
1251
|
+
RESPOND_WRITE_CARD_SUCCESS: "respond_write_card_success",
|
|
1252
|
+
RESPOND_WRITE_CARD_FAIL: "respond_write_card_fail",
|
|
1253
|
+
RESPOND_FREE_PLAN: "respond_free_plan",
|
|
1254
|
+
RESPOND_WRITE_FREE_PLAN: "respond_write_free_plan",
|
|
1255
|
+
SUBMISSION: "assignment_submitted",
|
|
1256
|
+
ASSIGNMENT_STARTED: "assignment_started",
|
|
1257
|
+
CREATE_ASSIGNMENT: "create_assignment",
|
|
1258
|
+
MC_SUCCESS: "multiple_choice_success",
|
|
1259
|
+
MC_FAIL: "multiple_choice_fail",
|
|
1260
|
+
ACTFL_LEVEL: "actfl_level",
|
|
1261
|
+
WIDA_LEVEL: "wida_level"
|
|
1262
|
+
};
|
|
1263
|
+
|
|
1264
|
+
// src/lib/firebase/firebase-analytics/assignment.ts
|
|
1265
|
+
var logOpenAssignment = (data = {}) => {
|
|
1266
|
+
api.logEvent("open_assignment", data);
|
|
1267
|
+
};
|
|
1268
|
+
var logOpenActivityPreview = (data = {}) => {
|
|
1269
|
+
api.logEvent("open_activity_preview", data);
|
|
1270
|
+
};
|
|
1271
|
+
var logSubmitAssignment = (data = {}) => {
|
|
1272
|
+
SpeakableFirebaseFunctions.updateCourseAnalytics?.({
|
|
1273
|
+
eventType: ANALYTICS_EVENT_TYPES.SUBMISSION,
|
|
1274
|
+
...data
|
|
1275
|
+
});
|
|
1276
|
+
api.logEvent(ANALYTICS_EVENT_TYPES.SUBMISSION, data);
|
|
1277
|
+
};
|
|
1278
|
+
var logStartAssignment = (data = {}) => {
|
|
1279
|
+
if (data.courseId) {
|
|
1280
|
+
SpeakableFirebaseFunctions.updateCourseAnalytics?.({
|
|
1281
|
+
eventType: ANALYTICS_EVENT_TYPES.ASSIGNMENT_STARTED,
|
|
1282
|
+
...data
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
api.logEvent(ANALYTICS_EVENT_TYPES.ASSIGNMENT_STARTED, data);
|
|
1286
|
+
};
|
|
1287
|
+
|
|
1234
1288
|
// src/domains/assignment/utils/create-default-score.ts
|
|
1235
1289
|
var defaultScore = (props) => {
|
|
1236
1290
|
const { serverTimestamp } = api.accessHelpers();
|
|
@@ -1313,6 +1367,9 @@ async function getAssignmentScore({
|
|
|
1313
1367
|
}),
|
|
1314
1368
|
assignmentId: assignment.id
|
|
1315
1369
|
};
|
|
1370
|
+
logStartAssignment({
|
|
1371
|
+
courseId: assignment.courseId
|
|
1372
|
+
});
|
|
1316
1373
|
const result = await createScore({
|
|
1317
1374
|
activityId: assignment.id,
|
|
1318
1375
|
userId,
|
|
@@ -1371,7 +1428,6 @@ var getScore = withErrorHandler(_getScore, "getScore");
|
|
|
1371
1428
|
|
|
1372
1429
|
// src/domains/assignment/utils/calculateScoreAndProgress.ts
|
|
1373
1430
|
var calculateScoreAndProgress = (scores, cardsList, weights) => {
|
|
1374
|
-
console.log("calculateScoreAndProgress", scores, cardsList, weights);
|
|
1375
1431
|
const totalSetPoints = cardsList.reduce((acc, cardId) => {
|
|
1376
1432
|
acc += weights?.[cardId] || 1;
|
|
1377
1433
|
return acc;
|
|
@@ -1618,25 +1674,18 @@ function useUpdateScore() {
|
|
|
1618
1674
|
function useUpdateCardScore({
|
|
1619
1675
|
isAssignment,
|
|
1620
1676
|
activityId,
|
|
1621
|
-
userId
|
|
1677
|
+
userId,
|
|
1678
|
+
set
|
|
1622
1679
|
}) {
|
|
1623
1680
|
const { queryClient } = useSpeakableApi();
|
|
1624
|
-
const querySet = useSet({ setId: activityId });
|
|
1625
|
-
const dataCurrentSet = querySet.data;
|
|
1626
1681
|
const queryKey = scoreQueryKeys.byId(activityId);
|
|
1627
1682
|
const mutation = useMutation2({
|
|
1628
1683
|
mutationFn: async ({ cardId, cardScore }) => {
|
|
1629
1684
|
const previousScores = queryClient.getQueryData(queryKey);
|
|
1630
|
-
console.log("useUpdateCardScore", {
|
|
1631
|
-
previousScores: previousScores ?? {},
|
|
1632
|
-
cardId,
|
|
1633
|
-
cardScore,
|
|
1634
|
-
activityId
|
|
1635
|
-
});
|
|
1636
1685
|
const { progress, score, newScoreUpdated, updatedCardScore } = getScoreUpdated({
|
|
1637
1686
|
previousScores: previousScores ?? {},
|
|
1638
1687
|
cardId,
|
|
1639
|
-
set
|
|
1688
|
+
set,
|
|
1640
1689
|
cardScore
|
|
1641
1690
|
});
|
|
1642
1691
|
await updateCardScore({
|
|
@@ -1658,7 +1707,7 @@ function useUpdateCardScore({
|
|
|
1658
1707
|
score: previousScore,
|
|
1659
1708
|
cardId,
|
|
1660
1709
|
cardScore,
|
|
1661
|
-
set
|
|
1710
|
+
set
|
|
1662
1711
|
});
|
|
1663
1712
|
return {
|
|
1664
1713
|
...previousScore,
|
|
@@ -1783,6 +1832,11 @@ function useSubmitAssignmentScore({
|
|
|
1783
1832
|
if (assignment.isAssessment) {
|
|
1784
1833
|
createNotification2(SpeakableNotificationTypes.ASSESSMENT_SUBMITTED, assignment);
|
|
1785
1834
|
}
|
|
1835
|
+
if (assignment?.id) {
|
|
1836
|
+
logSubmitAssignment({
|
|
1837
|
+
courseId: assignment?.courseId
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1786
1840
|
onAssignmentSubmitted(assignment.id);
|
|
1787
1841
|
queryClient.setQueryData(scoreQueryKeys.byId(assignment.id), {
|
|
1788
1842
|
...scores,
|
|
@@ -1843,6 +1897,13 @@ function useSubmitPracticeScore() {
|
|
|
1843
1897
|
// src/hooks/useActivity.ts
|
|
1844
1898
|
import { useEffect as useEffect2 } from "react";
|
|
1845
1899
|
|
|
1900
|
+
// src/services/add-grading-standard.ts
|
|
1901
|
+
var addGradingStandardLog = async (gradingStandard, userId) => {
|
|
1902
|
+
logGradingStandardLog(gradingStandard);
|
|
1903
|
+
const path = `users/${userId}/grading_standard_logs`;
|
|
1904
|
+
await api.addDoc(path, gradingStandard);
|
|
1905
|
+
};
|
|
1906
|
+
|
|
1846
1907
|
// src/hooks/useActivityTracker.ts
|
|
1847
1908
|
import { v4 as v42 } from "uuid";
|
|
1848
1909
|
function useActivityTracker({ userId }) {
|
|
@@ -1874,7 +1935,8 @@ function useActivityTracker({ userId }) {
|
|
|
1874
1935
|
function useActivity({
|
|
1875
1936
|
id,
|
|
1876
1937
|
isAssignment,
|
|
1877
|
-
onAssignmentSubmitted
|
|
1938
|
+
onAssignmentSubmitted,
|
|
1939
|
+
ltiData
|
|
1878
1940
|
}) {
|
|
1879
1941
|
const { queryClient, user } = useSpeakableApi();
|
|
1880
1942
|
const userId = user.auth.uid;
|
|
@@ -1905,7 +1967,8 @@ function useActivity({
|
|
|
1905
1967
|
const { mutationUpdateCardScore } = useUpdateCardScore({
|
|
1906
1968
|
activityId,
|
|
1907
1969
|
isAssignment,
|
|
1908
|
-
userId
|
|
1970
|
+
userId,
|
|
1971
|
+
set: querySet.data ?? void 0
|
|
1909
1972
|
});
|
|
1910
1973
|
const { mutationClearScore } = useClearScore();
|
|
1911
1974
|
const { submitAssignmentScore: submitAssignmentScore2 } = useSubmitAssignmentScore({
|
|
@@ -1959,6 +2022,15 @@ function useActivity({
|
|
|
1959
2022
|
setWeights: setData?.weights ?? {},
|
|
1960
2023
|
status: hasPendingReview ? "PENDING_REVIEW" : "FINALIZED"
|
|
1961
2024
|
});
|
|
2025
|
+
if (assignmentQuery.data?.ltiDeeplink) {
|
|
2026
|
+
submitLTIScore({
|
|
2027
|
+
maxPoints: assignmentQuery.data?.maxPoints,
|
|
2028
|
+
score: scoreQuery.data?.score ?? 0,
|
|
2029
|
+
SERVICE_KEY: ltiData?.serviceKey ?? "",
|
|
2030
|
+
lineItemId: ltiData?.lineItemId ?? "",
|
|
2031
|
+
lti_id: ltiData?.lti_id ?? ""
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
1962
2034
|
} else {
|
|
1963
2035
|
results = await submitPracticeScore2({
|
|
1964
2036
|
setId: querySet.data?.id ?? "",
|
|
@@ -1974,6 +2046,41 @@ function useActivity({
|
|
|
1974
2046
|
};
|
|
1975
2047
|
}
|
|
1976
2048
|
};
|
|
2049
|
+
const logGradingStandardEntry = ({
|
|
2050
|
+
cardId,
|
|
2051
|
+
gradingStandard,
|
|
2052
|
+
type
|
|
2053
|
+
}) => {
|
|
2054
|
+
const card = cardsObject?.[cardId];
|
|
2055
|
+
const scoresObject = queryClient.getQueryData(scoreQueryKeys.byId(activityId));
|
|
2056
|
+
const cardScore = scoresObject?.cards?.[cardId];
|
|
2057
|
+
const serverTimestamp = api.helpers.serverTimestamp;
|
|
2058
|
+
addGradingStandardLog(
|
|
2059
|
+
{
|
|
2060
|
+
assignmentId: activeAssignment?.id ?? "",
|
|
2061
|
+
courseId: activeAssignment?.courseId ?? "",
|
|
2062
|
+
teacherId: activeAssignment?.owners[0] ?? "",
|
|
2063
|
+
setId: setData?.id ?? "",
|
|
2064
|
+
cardId,
|
|
2065
|
+
level: gradingStandard.level,
|
|
2066
|
+
justification: gradingStandard.justification,
|
|
2067
|
+
transcript: cardScore?.transcript ?? "",
|
|
2068
|
+
audioUrl: cardScore?.audio ?? "",
|
|
2069
|
+
prompt: card?.prompt ?? "",
|
|
2070
|
+
responseType: card?.type === "RESPOND_WRITE" /* RESPOND_WRITE */ ? "written" : "spoken",
|
|
2071
|
+
type,
|
|
2072
|
+
dateMade: serverTimestamp()
|
|
2073
|
+
},
|
|
2074
|
+
userId
|
|
2075
|
+
);
|
|
2076
|
+
};
|
|
2077
|
+
useEffect2(() => {
|
|
2078
|
+
if (isAssignment) {
|
|
2079
|
+
logOpenAssignment({ assignmentId: id });
|
|
2080
|
+
} else {
|
|
2081
|
+
logOpenActivityPreview({ setId: id });
|
|
2082
|
+
}
|
|
2083
|
+
}, []);
|
|
1977
2084
|
useInitActivity({
|
|
1978
2085
|
assignment: activeAssignment ?? void 0,
|
|
1979
2086
|
set: setData ?? void 0,
|
|
@@ -2002,8 +2109,7 @@ function useActivity({
|
|
|
2002
2109
|
clear: onClearScore,
|
|
2003
2110
|
submit: onSubmitScore,
|
|
2004
2111
|
updateCard: handleUpdateCardScore,
|
|
2005
|
-
logGradingStandardEntry
|
|
2006
|
-
}
|
|
2112
|
+
logGradingStandardEntry
|
|
2007
2113
|
}
|
|
2008
2114
|
}
|
|
2009
2115
|
};
|
|
@@ -2047,6 +2153,36 @@ var useInitActivity = ({
|
|
|
2047
2153
|
init();
|
|
2048
2154
|
}, [set]);
|
|
2049
2155
|
};
|
|
2156
|
+
var submitLTIScore = async ({
|
|
2157
|
+
maxPoints,
|
|
2158
|
+
score,
|
|
2159
|
+
SERVICE_KEY,
|
|
2160
|
+
lineItemId,
|
|
2161
|
+
lti_id
|
|
2162
|
+
}) => {
|
|
2163
|
+
try {
|
|
2164
|
+
if (!SERVICE_KEY || !lineItemId || !lti_id) {
|
|
2165
|
+
throw new Error("Missing required LTI credentials");
|
|
2166
|
+
}
|
|
2167
|
+
const earnedPoints = score ? score / 100 * maxPoints : 0;
|
|
2168
|
+
const { data } = await SpeakableFirebaseFunctions?.submitLTIAssignmentScore?.({
|
|
2169
|
+
SERVICE_KEY,
|
|
2170
|
+
scoreData: {
|
|
2171
|
+
lineItemId,
|
|
2172
|
+
userId: lti_id,
|
|
2173
|
+
maxPoints,
|
|
2174
|
+
earnedPoints
|
|
2175
|
+
}
|
|
2176
|
+
});
|
|
2177
|
+
return { success: true, data };
|
|
2178
|
+
} catch (error) {
|
|
2179
|
+
console.error("Failed to submit LTI score:", error);
|
|
2180
|
+
return {
|
|
2181
|
+
success: false,
|
|
2182
|
+
error: error instanceof Error ? error : new Error("Unknown error occurred")
|
|
2183
|
+
};
|
|
2184
|
+
}
|
|
2185
|
+
};
|
|
2050
2186
|
export {
|
|
2051
2187
|
ALLOWED_CARD_ACTIVITY_TYPES_FOR_SUMMARY,
|
|
2052
2188
|
BASE_MULTIPLE_CHOICE_FIELD_VALUES,
|