@iblai/data-layer 1.20.0 → 1.21.0
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.ts +412 -2
- package/dist/index.esm.js +194 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +205 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/src/features/courses/__tests__/completion.test.d.ts +1 -0
- package/dist/src/features/courses/__tests__/outline-fixture.d.ts +10 -0
- package/dist/src/features/courses/api-slice.d.ts +270 -0
- package/dist/src/features/courses/completion.d.ts +47 -0
- package/dist/src/features/courses/types.d.ts +94 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CompletionOutlineBlock } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Reduced from the live `endpoint=outline` response for
|
|
4
|
+
* course-v1:1718796901+C0+2025-09 ("Exam course for baba"). It keeps the
|
|
5
|
+
* quirks that matter: missing `children` on leaves and empty verticals,
|
|
6
|
+
* `complete` only on containers or when true, `resume_block` only along the
|
|
7
|
+
* path to the one completed leaf ("Raw HTML" in Section 3).
|
|
8
|
+
*/
|
|
9
|
+
export declare const COURSE_ID = "course-v1:1718796901+C0+2025-09";
|
|
10
|
+
export declare const outlineFixture: CompletionOutlineBlock;
|
|
@@ -8,6 +8,13 @@ export declare const coursesApiSlice: import("@reduxjs/toolkit/query").Api<impor
|
|
|
8
8
|
user_id: string | number;
|
|
9
9
|
query?: Record<string, string | number | boolean | undefined>;
|
|
10
10
|
}, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", EnrolledCourseResponse, "coursesApiSlice", unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Per-learner course outline with block-level completion. Name the learner
|
|
13
|
+
* with exactly one of `username` / `user_id` / `email`, even for one's own
|
|
14
|
+
* data. Errors keep their HTTP status; map them with
|
|
15
|
+
* `normalizeLearnerCompletionError`.
|
|
16
|
+
*/
|
|
17
|
+
getLearnerCourseOutline: import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>;
|
|
11
18
|
}, "coursesApiSlice", "user-enrolled-courses" | "user-assigned-courses", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/dist/query/react").reactHooksModuleName>;
|
|
12
19
|
export declare const useGetUserEnrolledCoursesQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
13
20
|
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
@@ -661,4 +668,267 @@ export declare const useGetUserEnrolledCoursesQuery: <R extends Record<string, a
|
|
|
661
668
|
user_id: string | number;
|
|
662
669
|
query?: Record<string, string | number | boolean | undefined>;
|
|
663
670
|
};
|
|
671
|
+
}], useGetLearnerCourseOutlineQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
672
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
673
|
+
originalArgs?: undefined | undefined;
|
|
674
|
+
data?: undefined | undefined;
|
|
675
|
+
error?: undefined | undefined;
|
|
676
|
+
requestId?: undefined | undefined;
|
|
677
|
+
endpointName?: string | undefined;
|
|
678
|
+
startedTimeStamp?: undefined | undefined;
|
|
679
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
680
|
+
} & {
|
|
681
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
682
|
+
isUninitialized: false;
|
|
683
|
+
isLoading: false;
|
|
684
|
+
isFetching: false;
|
|
685
|
+
isSuccess: false;
|
|
686
|
+
isError: false;
|
|
687
|
+
}, "isUninitialized"> & {
|
|
688
|
+
isUninitialized: true;
|
|
689
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
690
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
691
|
+
isUninitialized: false;
|
|
692
|
+
isLoading: false;
|
|
693
|
+
isFetching: false;
|
|
694
|
+
isSuccess: false;
|
|
695
|
+
isError: false;
|
|
696
|
+
}, {
|
|
697
|
+
isLoading: true;
|
|
698
|
+
isFetching: boolean;
|
|
699
|
+
data: undefined;
|
|
700
|
+
} | ({
|
|
701
|
+
isSuccess: true;
|
|
702
|
+
isFetching: true;
|
|
703
|
+
error: undefined;
|
|
704
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
705
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
706
|
+
isUninitialized: false;
|
|
707
|
+
isLoading: false;
|
|
708
|
+
isFetching: false;
|
|
709
|
+
isSuccess: false;
|
|
710
|
+
isError: false;
|
|
711
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
712
|
+
isSuccess: true;
|
|
713
|
+
isFetching: false;
|
|
714
|
+
error: undefined;
|
|
715
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
716
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
717
|
+
isUninitialized: false;
|
|
718
|
+
isLoading: false;
|
|
719
|
+
isFetching: false;
|
|
720
|
+
isSuccess: false;
|
|
721
|
+
isError: false;
|
|
722
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
723
|
+
isError: true;
|
|
724
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
725
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
726
|
+
isUninitialized: false;
|
|
727
|
+
isLoading: false;
|
|
728
|
+
isFetching: false;
|
|
729
|
+
isSuccess: false;
|
|
730
|
+
isError: false;
|
|
731
|
+
}, "error">>)>> & {
|
|
732
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
733
|
+
}>(arg: import("./types").LearnerCompletionArgs | typeof import("@reduxjs/toolkit/query").skipToken, options?: (import("@reduxjs/toolkit/query").SubscriptionOptions & {
|
|
734
|
+
skip?: boolean;
|
|
735
|
+
refetchOnMountOrArgChange?: boolean | number;
|
|
736
|
+
} & {
|
|
737
|
+
skip?: boolean;
|
|
738
|
+
selectFromResult?: ((state: import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
739
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
740
|
+
originalArgs?: undefined | undefined;
|
|
741
|
+
data?: undefined | undefined;
|
|
742
|
+
error?: undefined | undefined;
|
|
743
|
+
requestId?: undefined | undefined;
|
|
744
|
+
endpointName?: string | undefined;
|
|
745
|
+
startedTimeStamp?: undefined | undefined;
|
|
746
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
747
|
+
} & {
|
|
748
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
749
|
+
isUninitialized: false;
|
|
750
|
+
isLoading: false;
|
|
751
|
+
isFetching: false;
|
|
752
|
+
isSuccess: false;
|
|
753
|
+
isError: false;
|
|
754
|
+
}, "isUninitialized"> & {
|
|
755
|
+
isUninitialized: true;
|
|
756
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
757
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
758
|
+
isUninitialized: false;
|
|
759
|
+
isLoading: false;
|
|
760
|
+
isFetching: false;
|
|
761
|
+
isSuccess: false;
|
|
762
|
+
isError: false;
|
|
763
|
+
}, {
|
|
764
|
+
isLoading: true;
|
|
765
|
+
isFetching: boolean;
|
|
766
|
+
data: undefined;
|
|
767
|
+
} | ({
|
|
768
|
+
isSuccess: true;
|
|
769
|
+
isFetching: true;
|
|
770
|
+
error: undefined;
|
|
771
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
772
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
773
|
+
isUninitialized: false;
|
|
774
|
+
isLoading: false;
|
|
775
|
+
isFetching: false;
|
|
776
|
+
isSuccess: false;
|
|
777
|
+
isError: false;
|
|
778
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
779
|
+
isSuccess: true;
|
|
780
|
+
isFetching: false;
|
|
781
|
+
error: undefined;
|
|
782
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
783
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
784
|
+
isUninitialized: false;
|
|
785
|
+
isLoading: false;
|
|
786
|
+
isFetching: false;
|
|
787
|
+
isSuccess: false;
|
|
788
|
+
isError: false;
|
|
789
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
790
|
+
isError: true;
|
|
791
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
792
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
793
|
+
isUninitialized: false;
|
|
794
|
+
isLoading: false;
|
|
795
|
+
isFetching: false;
|
|
796
|
+
isSuccess: false;
|
|
797
|
+
isError: false;
|
|
798
|
+
}, "error">>)>> & {
|
|
799
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
800
|
+
}) => R) | undefined;
|
|
801
|
+
}) | undefined) => [R][R extends any ? 0 : never] & {
|
|
802
|
+
refetch: () => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>>;
|
|
803
|
+
}, useLazyGetLearnerCourseOutlineQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
804
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
805
|
+
originalArgs?: undefined | undefined;
|
|
806
|
+
data?: undefined | undefined;
|
|
807
|
+
error?: undefined | undefined;
|
|
808
|
+
requestId?: undefined | undefined;
|
|
809
|
+
endpointName?: string | undefined;
|
|
810
|
+
startedTimeStamp?: undefined | undefined;
|
|
811
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
812
|
+
} & {
|
|
813
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
814
|
+
isUninitialized: false;
|
|
815
|
+
isLoading: false;
|
|
816
|
+
isFetching: false;
|
|
817
|
+
isSuccess: false;
|
|
818
|
+
isError: false;
|
|
819
|
+
}, "isUninitialized"> & {
|
|
820
|
+
isUninitialized: true;
|
|
821
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
822
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
823
|
+
isUninitialized: false;
|
|
824
|
+
isLoading: false;
|
|
825
|
+
isFetching: false;
|
|
826
|
+
isSuccess: false;
|
|
827
|
+
isError: false;
|
|
828
|
+
}, {
|
|
829
|
+
isLoading: true;
|
|
830
|
+
isFetching: boolean;
|
|
831
|
+
data: undefined;
|
|
832
|
+
} | ({
|
|
833
|
+
isSuccess: true;
|
|
834
|
+
isFetching: true;
|
|
835
|
+
error: undefined;
|
|
836
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
837
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
838
|
+
isUninitialized: false;
|
|
839
|
+
isLoading: false;
|
|
840
|
+
isFetching: false;
|
|
841
|
+
isSuccess: false;
|
|
842
|
+
isError: false;
|
|
843
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
844
|
+
isSuccess: true;
|
|
845
|
+
isFetching: false;
|
|
846
|
+
error: undefined;
|
|
847
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
848
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
849
|
+
isUninitialized: false;
|
|
850
|
+
isLoading: false;
|
|
851
|
+
isFetching: false;
|
|
852
|
+
isSuccess: false;
|
|
853
|
+
isError: false;
|
|
854
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
855
|
+
isError: true;
|
|
856
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
857
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
858
|
+
isUninitialized: false;
|
|
859
|
+
isLoading: false;
|
|
860
|
+
isFetching: false;
|
|
861
|
+
isSuccess: false;
|
|
862
|
+
isError: false;
|
|
863
|
+
}, "error">>)>> & {
|
|
864
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
865
|
+
}>(options?: (import("@reduxjs/toolkit/query").SubscriptionOptions & Omit<{
|
|
866
|
+
skip?: boolean;
|
|
867
|
+
selectFromResult?: ((state: import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
868
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
869
|
+
originalArgs?: undefined | undefined;
|
|
870
|
+
data?: undefined | undefined;
|
|
871
|
+
error?: undefined | undefined;
|
|
872
|
+
requestId?: undefined | undefined;
|
|
873
|
+
endpointName?: string | undefined;
|
|
874
|
+
startedTimeStamp?: undefined | undefined;
|
|
875
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
876
|
+
} & {
|
|
877
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
878
|
+
isUninitialized: false;
|
|
879
|
+
isLoading: false;
|
|
880
|
+
isFetching: false;
|
|
881
|
+
isSuccess: false;
|
|
882
|
+
isError: false;
|
|
883
|
+
}, "isUninitialized"> & {
|
|
884
|
+
isUninitialized: true;
|
|
885
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
886
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
887
|
+
isUninitialized: false;
|
|
888
|
+
isLoading: false;
|
|
889
|
+
isFetching: false;
|
|
890
|
+
isSuccess: false;
|
|
891
|
+
isError: false;
|
|
892
|
+
}, {
|
|
893
|
+
isLoading: true;
|
|
894
|
+
isFetching: boolean;
|
|
895
|
+
data: undefined;
|
|
896
|
+
} | ({
|
|
897
|
+
isSuccess: true;
|
|
898
|
+
isFetching: true;
|
|
899
|
+
error: undefined;
|
|
900
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
901
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
902
|
+
isUninitialized: false;
|
|
903
|
+
isLoading: false;
|
|
904
|
+
isFetching: false;
|
|
905
|
+
isSuccess: false;
|
|
906
|
+
isError: false;
|
|
907
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
908
|
+
isSuccess: true;
|
|
909
|
+
isFetching: false;
|
|
910
|
+
error: undefined;
|
|
911
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
912
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
913
|
+
isUninitialized: false;
|
|
914
|
+
isLoading: false;
|
|
915
|
+
isFetching: false;
|
|
916
|
+
isSuccess: false;
|
|
917
|
+
isError: false;
|
|
918
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
919
|
+
isError: true;
|
|
920
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>> & {
|
|
921
|
+
currentData?: import("./types").CompletionOutlineBlock | undefined;
|
|
922
|
+
isUninitialized: false;
|
|
923
|
+
isLoading: false;
|
|
924
|
+
isFetching: false;
|
|
925
|
+
isSuccess: false;
|
|
926
|
+
isError: false;
|
|
927
|
+
}, "error">>)>> & {
|
|
928
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
929
|
+
}) => R) | undefined;
|
|
930
|
+
}, "skip">) | undefined) => [(arg: import("./types").LearnerCompletionArgs, preferCacheValue?: boolean) => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<import("./types").LearnerCompletionArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "user-enrolled-courses" | "user-assigned-courses", import("./types").CompletionOutlineBlock, "coursesApiSlice", unknown>>, [R][R extends any ? 0 : never] & {
|
|
931
|
+
reset: () => void;
|
|
932
|
+
}, {
|
|
933
|
+
lastArg: import("./types").LearnerCompletionArgs;
|
|
664
934
|
}];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { BaseQueryApi } from '@reduxjs/toolkit/query';
|
|
2
|
+
import { type ExtendedFetchBaseQueryError } from '../utils';
|
|
3
|
+
import type { CompletionOutlineBlock, CompletionOutlineSection, FlatCompletionOutlineEntry, LearnerCompletionArgs, LearnerCompletionEndpoint, LearnerCompletionError, NormalizedCompletionOutlineBlock } from './types';
|
|
4
|
+
export declare const LEARNER_COMPLETION_PATH = "/api/catalog/enrollment/courses/completion/";
|
|
5
|
+
/**
|
|
6
|
+
* Checks the args carry exactly one learner identifier plus `course_id` and
|
|
7
|
+
* `platform_key`. Returns a reason string when they don't.
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateLearnerCompletionArgs(args: LearnerCompletionArgs): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Builds the completion URL for one `endpoint` selector. Only the learner
|
|
12
|
+
* identifier, `course_id` and `platform_key` are sent; the DM forwards
|
|
13
|
+
* nothing else to edX.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildLearnerCompletionUrl(args: LearnerCompletionArgs, endpoint: LearnerCompletionEndpoint): string;
|
|
16
|
+
type QueryResult<T> = {
|
|
17
|
+
data: T;
|
|
18
|
+
} | {
|
|
19
|
+
error: ExtendedFetchBaseQueryError;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* One completion request through `iblFetchBaseQuery` (DM token, token
|
|
23
|
+
* refresh, registered error handlers). `iblFetchBaseQuery` throws on HTTP
|
|
24
|
+
* errors, which RTK would turn into a SerializedError without the status;
|
|
25
|
+
* catching here keeps `{ status, data }` so the UI can tell 403/404/502 apart.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fetchLearnerCompletion<T>(args: LearnerCompletionArgs, endpoint: LearnerCompletionEndpoint, api: BaseQueryApi, extraOptions?: Record<string, unknown>): Promise<QueryResult<T>>;
|
|
28
|
+
/**
|
|
29
|
+
* Maps a failed completion query onto the states the UI shows. 403 and 404
|
|
30
|
+
* are deliberately coarse on the backend (one body for every hidden case),
|
|
31
|
+
* so don't try to read more into them.
|
|
32
|
+
*/
|
|
33
|
+
export declare function normalizeLearnerCompletionError(error: unknown): LearnerCompletionError | null;
|
|
34
|
+
/** Fills the fields edX omits: `children ?? []`, `complete`/`resume_block ?? false`. */
|
|
35
|
+
export declare function normalizeOutline(block: CompletionOutlineBlock): NormalizedCompletionOutlineBlock;
|
|
36
|
+
/** Depth-first, course order. The root has depth 0 and `parentId` null. */
|
|
37
|
+
export declare function flattenOutline(root: CompletionOutlineBlock): FlatCompletionOutlineEntry[];
|
|
38
|
+
/**
|
|
39
|
+
* Follows `resume_block: true` from the root to the deepest marked node (the
|
|
40
|
+
* last-visited leaf). Returns null when the learner hasn't visited anything.
|
|
41
|
+
*/
|
|
42
|
+
export declare function findResumeBlock(root: CompletionOutlineBlock): CompletionOutlineBlock | null;
|
|
43
|
+
/** Counts leaves (blocks without children) by `type`. */
|
|
44
|
+
export declare function countByType(root: CompletionOutlineBlock): Record<string, number>;
|
|
45
|
+
/** Top-level sections (chapters) for a summary view, in course order. */
|
|
46
|
+
export declare function getSections(root: CompletionOutlineBlock): CompletionOutlineSection[];
|
|
47
|
+
export {};
|
|
@@ -24,3 +24,97 @@ export interface EnrolledCourseResponse {
|
|
|
24
24
|
previous_page: number | null;
|
|
25
25
|
results: EnrolledCourse[];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Learner course completion (DM proxy over Open edX completion).
|
|
29
|
+
* `GET /api/catalog/enrollment/courses/completion/`
|
|
30
|
+
*
|
|
31
|
+
* The learner must always be named explicitly, even when reading one's own
|
|
32
|
+
* data: edX ignores `username` for non-staff tokens, so the DM resolves the
|
|
33
|
+
* learner and checks the caller may read them.
|
|
34
|
+
*/
|
|
35
|
+
export type LearnerIdentifier = {
|
|
36
|
+
username: string;
|
|
37
|
+
user_id?: never;
|
|
38
|
+
email?: never;
|
|
39
|
+
} | {
|
|
40
|
+
user_id: string | number;
|
|
41
|
+
username?: never;
|
|
42
|
+
email?: never;
|
|
43
|
+
} | {
|
|
44
|
+
email: string;
|
|
45
|
+
username?: never;
|
|
46
|
+
user_id?: never;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* `endpoint` selector accepted by the DM. Only `outline` is implemented;
|
|
50
|
+
* the others are listed so sibling queries can reuse the URL builder.
|
|
51
|
+
*/
|
|
52
|
+
export type LearnerCompletionEndpoint = 'status' | 'outline' | 'blocks' | 'progress';
|
|
53
|
+
export type LearnerCompletionArgs = LearnerIdentifier & {
|
|
54
|
+
course_id: string;
|
|
55
|
+
platform_key: string;
|
|
56
|
+
};
|
|
57
|
+
export type LearnerCourseOutlineArgs = LearnerCompletionArgs;
|
|
58
|
+
export interface SpecialExamInfo {
|
|
59
|
+
short_description: string;
|
|
60
|
+
suggested_icon: string;
|
|
61
|
+
in_completed_state: boolean;
|
|
62
|
+
}
|
|
63
|
+
export interface CompletionOutlineBlock {
|
|
64
|
+
/** Full usage key; the only globally unique field. */
|
|
65
|
+
id: string;
|
|
66
|
+
block_id: string;
|
|
67
|
+
/** 'course' | 'chapter' | 'sequential' | 'vertical' | 'problem' | 'video' | 'html' | … */
|
|
68
|
+
type: string;
|
|
69
|
+
display_name: string;
|
|
70
|
+
lms_web_url: string;
|
|
71
|
+
legacy_web_url: string;
|
|
72
|
+
student_view_url: string;
|
|
73
|
+
graded: boolean;
|
|
74
|
+
start: string;
|
|
75
|
+
has_score: boolean;
|
|
76
|
+
scored: boolean;
|
|
77
|
+
num_graded_problems: number;
|
|
78
|
+
/** 0–100, computed by the backend. Display as-is; don't recompute. */
|
|
79
|
+
completion_percentage: number;
|
|
80
|
+
/** Absent on leaves and on empty containers. */
|
|
81
|
+
children?: CompletionOutlineBlock[];
|
|
82
|
+
/** Absent means false (leaves only carry it when true). */
|
|
83
|
+
complete?: boolean;
|
|
84
|
+
/** Leaves only; 0–1. */
|
|
85
|
+
completion?: number;
|
|
86
|
+
weight?: number;
|
|
87
|
+
/** Only present (true) along the path to the last-visited leaf. */
|
|
88
|
+
resume_block?: boolean;
|
|
89
|
+
special_exam_info?: SpecialExamInfo;
|
|
90
|
+
/** Root only. */
|
|
91
|
+
has_scheduled_content?: boolean;
|
|
92
|
+
}
|
|
93
|
+
/** Root node, `type === 'course'`. */
|
|
94
|
+
export type CompletionOutlineResponse = CompletionOutlineBlock;
|
|
95
|
+
export type NormalizedCompletionOutlineBlock = Omit<CompletionOutlineBlock, 'children' | 'complete' | 'resume_block'> & {
|
|
96
|
+
children: NormalizedCompletionOutlineBlock[];
|
|
97
|
+
complete: boolean;
|
|
98
|
+
resume_block: boolean;
|
|
99
|
+
};
|
|
100
|
+
export interface FlatCompletionOutlineEntry {
|
|
101
|
+
block: CompletionOutlineBlock;
|
|
102
|
+
depth: number;
|
|
103
|
+
parentId: string | null;
|
|
104
|
+
/** Display names from the root down to (and including) this block. */
|
|
105
|
+
path: string[];
|
|
106
|
+
}
|
|
107
|
+
export interface CompletionOutlineSection {
|
|
108
|
+
id: string;
|
|
109
|
+
display_name: string;
|
|
110
|
+
completion_percentage: number;
|
|
111
|
+
complete: boolean;
|
|
112
|
+
block: CompletionOutlineBlock;
|
|
113
|
+
}
|
|
114
|
+
export type LearnerCompletionErrorKind = 'invalid_request' | 'unauthorized' | 'forbidden' | 'not_enrolled' | 'unavailable' | 'unknown';
|
|
115
|
+
export interface LearnerCompletionError {
|
|
116
|
+
kind: LearnerCompletionErrorKind;
|
|
117
|
+
status?: number | string;
|
|
118
|
+
/** Only `unavailable` (502/503/504, network) is worth retrying. */
|
|
119
|
+
retryable: boolean;
|
|
120
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -43,6 +43,7 @@ export * from './features/catalog/api-slice';
|
|
|
43
43
|
export * from './features/per-learner/api-slice';
|
|
44
44
|
export * from './features/courses/api-slice';
|
|
45
45
|
export * from './features/courses/types';
|
|
46
|
+
export * from './features/courses/completion';
|
|
46
47
|
export * from './features/course-metadata/api-slice';
|
|
47
48
|
export * from './features/course-metadata/types';
|
|
48
49
|
export * from './features/edx-sso/api-slice';
|