@iblai/web-utils 1.11.5 → 1.11.7
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/data-layer/src/features/analytics/api-slice.d.ts +134 -1
- package/dist/data-layer/src/features/analytics/constants.d.ts +4 -0
- package/dist/data-layer/src/features/analytics/types.d.ts +117 -0
- package/dist/data-layer/src/features/user/api-slice.d.ts +14 -14
- package/dist/data-layer/src/features/user/types.d.ts +6 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +73 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +73 -8
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AnalyticsDateParams, AnalyticsPaginationParams, OverviewSummaryResponse, ConversationSummaryResponse, TopicStatisticsResponse, TopicOverviewResponse, UserMetricsResponse, UserMetricsPieChartResponse, UserCohortsOverTimeResponse, TopStudentsResponse, TopicsSummaryResponse, AverageMessagesPerSessionResponse, TopicsStatsArgs, TopicsStatsResponse, UsersStatsResponse, UsersStatsArgs, SessionStatsArgs, SessionStatsResponse, TopicsDetailsStatsResponse, TopicsDetailsStatsArgs, AccessTimeHeatmapResponse, AccessTimeHeatmapArgs, UserDetailsStatsResponse, UserDetailsStatsArgs, FinancialStatsResponse, FinancialStatsArgs, DetailedFinancialStatsResponse, DetailedFinancialStatsArgs, TranscriptsMessagesArgs, TranscriptsMessagesResponse, TranscriptsMessagesDetailsArgs, TranscriptsMessagesDetailsResponse, TranscriptsConversationHeadlineArgs, TranscriptsConversationHeadlineResponse, TimeTrackingResponse, TimeTrackingRequest, ContentAnalyticsResponse, ContentAnalyticsArgs, ContentAnalyticsDetailsResponse, ContentAnalyticsDetailsArgs } from './types';
|
|
1
|
+
import type { AnalyticsDateParams, AnalyticsPaginationParams, OverviewSummaryResponse, ConversationSummaryResponse, TopicStatisticsResponse, TopicOverviewResponse, UserMetricsResponse, UserMetricsPieChartResponse, UserCohortsOverTimeResponse, TopStudentsResponse, TopicsSummaryResponse, AverageMessagesPerSessionResponse, TopicsStatsArgs, TopicsStatsResponse, UsersStatsResponse, UsersStatsArgs, SessionStatsArgs, SessionStatsResponse, TopicsDetailsStatsResponse, TopicsDetailsStatsArgs, AccessTimeHeatmapResponse, AccessTimeHeatmapArgs, UserDetailsStatsResponse, UserDetailsStatsArgs, FinancialStatsResponse, FinancialStatsArgs, DetailedFinancialStatsResponse, DetailedFinancialStatsArgs, TranscriptsMessagesArgs, TranscriptsMessagesResponse, TranscriptsMessagesDetailsArgs, TranscriptsMessagesDetailsResponse, TranscriptsConversationHeadlineArgs, TranscriptsConversationHeadlineResponse, TimeTrackingResponse, TimeTrackingRequest, ContentAnalyticsResponse, ContentAnalyticsArgs, ContentAnalyticsDetailsResponse, ContentAnalyticsDetailsArgs, LearnerDetailsResponse, LearnerDetailsArgs } from './types';
|
|
2
2
|
export declare const analyticsApiSlice: import("@reduxjs/toolkit/query").Api<import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, {
|
|
3
3
|
getOverviewSummary: import("@reduxjs/toolkit/query").QueryDefinition<AnalyticsDateParams, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", OverviewSummaryResponse, "analyticsApiSlice", unknown>;
|
|
4
4
|
getConversation: import("@reduxjs/toolkit/query").QueryDefinition<AnalyticsDateParams, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", ConversationSummaryResponse[], "analyticsApiSlice", unknown>;
|
|
@@ -27,6 +27,7 @@ export declare const analyticsApiSlice: import("@reduxjs/toolkit/query").Api<imp
|
|
|
27
27
|
getTranscriptsConversationHeadline: import("@reduxjs/toolkit/query").QueryDefinition<TranscriptsConversationHeadlineArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", TranscriptsConversationHeadlineResponse, "analyticsApiSlice", unknown>;
|
|
28
28
|
getContentAnalytics: import("@reduxjs/toolkit/query").QueryDefinition<ContentAnalyticsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", ContentAnalyticsResponse, "analyticsApiSlice", unknown>;
|
|
29
29
|
getContentAnalyticsDetails: import("@reduxjs/toolkit/query").QueryDefinition<ContentAnalyticsDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", ContentAnalyticsDetailsResponse, "analyticsApiSlice", unknown>;
|
|
30
|
+
getLearnerDetails: import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>;
|
|
30
31
|
}, "analyticsApiSlice", "Analytics", typeof import("@reduxjs/toolkit/query").coreModuleName | typeof import("@reduxjs/toolkit/dist/query/react").reactHooksModuleName>;
|
|
31
32
|
export declare const useGetOverviewSummaryQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
32
33
|
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
@@ -3620,4 +3621,136 @@ export declare const useGetOverviewSummaryQuery: <R extends Record<string, any>
|
|
|
3620
3621
|
}) => R) | undefined;
|
|
3621
3622
|
}) | undefined) => [R][R extends any ? 0 : never] & {
|
|
3622
3623
|
refetch: () => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<ContentAnalyticsDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", ContentAnalyticsDetailsResponse, "analyticsApiSlice", unknown>>;
|
|
3624
|
+
}, useGetLearnerDetailsQuery: <R extends Record<string, any> = import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
3625
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
3626
|
+
originalArgs?: undefined | undefined;
|
|
3627
|
+
data?: undefined | undefined;
|
|
3628
|
+
error?: undefined | undefined;
|
|
3629
|
+
requestId?: undefined | undefined;
|
|
3630
|
+
endpointName?: string | undefined;
|
|
3631
|
+
startedTimeStamp?: undefined | undefined;
|
|
3632
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
3633
|
+
} & {
|
|
3634
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3635
|
+
isUninitialized: false;
|
|
3636
|
+
isLoading: false;
|
|
3637
|
+
isFetching: false;
|
|
3638
|
+
isSuccess: false;
|
|
3639
|
+
isError: false;
|
|
3640
|
+
}, "isUninitialized"> & {
|
|
3641
|
+
isUninitialized: true;
|
|
3642
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3643
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3644
|
+
isUninitialized: false;
|
|
3645
|
+
isLoading: false;
|
|
3646
|
+
isFetching: false;
|
|
3647
|
+
isSuccess: false;
|
|
3648
|
+
isError: false;
|
|
3649
|
+
}, {
|
|
3650
|
+
isLoading: true;
|
|
3651
|
+
isFetching: boolean;
|
|
3652
|
+
data: undefined;
|
|
3653
|
+
} | ({
|
|
3654
|
+
isSuccess: true;
|
|
3655
|
+
isFetching: true;
|
|
3656
|
+
error: undefined;
|
|
3657
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3658
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3659
|
+
isUninitialized: false;
|
|
3660
|
+
isLoading: false;
|
|
3661
|
+
isFetching: false;
|
|
3662
|
+
isSuccess: false;
|
|
3663
|
+
isError: false;
|
|
3664
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
3665
|
+
isSuccess: true;
|
|
3666
|
+
isFetching: false;
|
|
3667
|
+
error: undefined;
|
|
3668
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3669
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3670
|
+
isUninitialized: false;
|
|
3671
|
+
isLoading: false;
|
|
3672
|
+
isFetching: false;
|
|
3673
|
+
isSuccess: false;
|
|
3674
|
+
isError: false;
|
|
3675
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
3676
|
+
isError: true;
|
|
3677
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3678
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3679
|
+
isUninitialized: false;
|
|
3680
|
+
isLoading: false;
|
|
3681
|
+
isFetching: false;
|
|
3682
|
+
isSuccess: false;
|
|
3683
|
+
isError: false;
|
|
3684
|
+
}, "error">>)>> & {
|
|
3685
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
3686
|
+
}>(arg: LearnerDetailsArgs | typeof import("@reduxjs/toolkit/query").skipToken, options?: (import("@reduxjs/toolkit/query").SubscriptionOptions & {
|
|
3687
|
+
skip?: boolean;
|
|
3688
|
+
refetchOnMountOrArgChange?: boolean | number;
|
|
3689
|
+
} & {
|
|
3690
|
+
skip?: boolean;
|
|
3691
|
+
selectFromResult?: ((state: import("@reduxjs/toolkit/query").TSHelpersId<(Omit<{
|
|
3692
|
+
status: import("@reduxjs/toolkit/query").QueryStatus.uninitialized;
|
|
3693
|
+
originalArgs?: undefined | undefined;
|
|
3694
|
+
data?: undefined | undefined;
|
|
3695
|
+
error?: undefined | undefined;
|
|
3696
|
+
requestId?: undefined | undefined;
|
|
3697
|
+
endpointName?: string | undefined;
|
|
3698
|
+
startedTimeStamp?: undefined | undefined;
|
|
3699
|
+
fulfilledTimeStamp?: undefined | undefined;
|
|
3700
|
+
} & {
|
|
3701
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3702
|
+
isUninitialized: false;
|
|
3703
|
+
isLoading: false;
|
|
3704
|
+
isFetching: false;
|
|
3705
|
+
isSuccess: false;
|
|
3706
|
+
isError: false;
|
|
3707
|
+
}, "isUninitialized"> & {
|
|
3708
|
+
isUninitialized: true;
|
|
3709
|
+
}) | import("@reduxjs/toolkit/query").TSHelpersOverride<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3710
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3711
|
+
isUninitialized: false;
|
|
3712
|
+
isLoading: false;
|
|
3713
|
+
isFetching: false;
|
|
3714
|
+
isSuccess: false;
|
|
3715
|
+
isError: false;
|
|
3716
|
+
}, {
|
|
3717
|
+
isLoading: true;
|
|
3718
|
+
isFetching: boolean;
|
|
3719
|
+
data: undefined;
|
|
3720
|
+
} | ({
|
|
3721
|
+
isSuccess: true;
|
|
3722
|
+
isFetching: true;
|
|
3723
|
+
error: undefined;
|
|
3724
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3725
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3726
|
+
isUninitialized: false;
|
|
3727
|
+
isLoading: false;
|
|
3728
|
+
isFetching: false;
|
|
3729
|
+
isSuccess: false;
|
|
3730
|
+
isError: false;
|
|
3731
|
+
}, "data" | "fulfilledTimeStamp">>) | ({
|
|
3732
|
+
isSuccess: true;
|
|
3733
|
+
isFetching: false;
|
|
3734
|
+
error: undefined;
|
|
3735
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3736
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3737
|
+
isUninitialized: false;
|
|
3738
|
+
isLoading: false;
|
|
3739
|
+
isFetching: false;
|
|
3740
|
+
isSuccess: false;
|
|
3741
|
+
isError: false;
|
|
3742
|
+
}, "data" | "fulfilledTimeStamp" | "currentData">>) | ({
|
|
3743
|
+
isError: true;
|
|
3744
|
+
} & Required<Pick<import("@reduxjs/toolkit/query").QuerySubState<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>> & {
|
|
3745
|
+
currentData?: LearnerDetailsResponse | undefined;
|
|
3746
|
+
isUninitialized: false;
|
|
3747
|
+
isLoading: false;
|
|
3748
|
+
isFetching: false;
|
|
3749
|
+
isSuccess: false;
|
|
3750
|
+
isError: false;
|
|
3751
|
+
}, "error">>)>> & {
|
|
3752
|
+
status: import("@reduxjs/toolkit/query").QueryStatus;
|
|
3753
|
+
}) => R) | undefined;
|
|
3754
|
+
}) | undefined) => [R][R extends any ? 0 : never] & {
|
|
3755
|
+
refetch: () => import("@reduxjs/toolkit/query").QueryActionCreatorResult<import("@reduxjs/toolkit/query").QueryDefinition<LearnerDetailsArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, "Analytics", LearnerDetailsResponse, "analyticsApiSlice", unknown>>;
|
|
3623
3756
|
};
|
|
@@ -111,6 +111,10 @@ export declare const NON_AI_ANALYTICS_ENDPOINTS: {
|
|
|
111
111
|
service: SERVICES;
|
|
112
112
|
path: (content_id: string) => string;
|
|
113
113
|
};
|
|
114
|
+
GET_LEARNER_DETAILS: {
|
|
115
|
+
service: SERVICES;
|
|
116
|
+
path: (username: string, platform_key: string, metrics: string, course_id?: string, include_edx_progress?: boolean, program_id?: string) => string;
|
|
117
|
+
};
|
|
114
118
|
};
|
|
115
119
|
export declare const ANALYTICS_QUERY_KEYS: {
|
|
116
120
|
GET_OVERVIEW_SUMMARY: () => string[];
|
|
@@ -577,3 +577,120 @@ export interface ContentAnalyticsDetailsResponse {
|
|
|
577
577
|
pagination: ContentAnalyticsPagination;
|
|
578
578
|
learners: ContentAnalyticsLearner[];
|
|
579
579
|
}
|
|
580
|
+
export interface LearnerDetailsArgs {
|
|
581
|
+
username: string;
|
|
582
|
+
platform_key: string;
|
|
583
|
+
metrics: string;
|
|
584
|
+
course_id?: string;
|
|
585
|
+
program_id?: string;
|
|
586
|
+
include_edx_progress?: boolean;
|
|
587
|
+
}
|
|
588
|
+
export interface LearnerDetailsUser {
|
|
589
|
+
user_id: number;
|
|
590
|
+
username: string;
|
|
591
|
+
email: string;
|
|
592
|
+
name: string;
|
|
593
|
+
is_active: boolean;
|
|
594
|
+
last_active: string;
|
|
595
|
+
date_joined: string;
|
|
596
|
+
}
|
|
597
|
+
export interface LearnerContentEnrollment {
|
|
598
|
+
created: string;
|
|
599
|
+
started: string | null;
|
|
600
|
+
ended: string | null;
|
|
601
|
+
active: boolean;
|
|
602
|
+
}
|
|
603
|
+
export interface LearnerContentCompletion {
|
|
604
|
+
completed: boolean;
|
|
605
|
+
completion_percentage: number;
|
|
606
|
+
passed: boolean;
|
|
607
|
+
passed_date: string | null;
|
|
608
|
+
}
|
|
609
|
+
export interface LearnerEdxCompletionSummary {
|
|
610
|
+
complete_count: number;
|
|
611
|
+
incomplete_count: number;
|
|
612
|
+
locked_count: number;
|
|
613
|
+
}
|
|
614
|
+
export interface LearnerEdxCourseGrade {
|
|
615
|
+
letter_grade: string | null;
|
|
616
|
+
percent: number;
|
|
617
|
+
is_passing: boolean;
|
|
618
|
+
}
|
|
619
|
+
export interface LearnerEdxAssignmentPolicy {
|
|
620
|
+
type: string;
|
|
621
|
+
short_label: string;
|
|
622
|
+
weight: number;
|
|
623
|
+
num_total: number;
|
|
624
|
+
num_droppable: number;
|
|
625
|
+
}
|
|
626
|
+
export interface LearnerEdxGradingPolicy {
|
|
627
|
+
assignment_policies: LearnerEdxAssignmentPolicy[];
|
|
628
|
+
grade_range: Record<string, number>;
|
|
629
|
+
}
|
|
630
|
+
export interface LearnerEdxSubsectionScore {
|
|
631
|
+
display_name: string;
|
|
632
|
+
block_key: string;
|
|
633
|
+
format?: string;
|
|
634
|
+
has_graded_assignment: boolean;
|
|
635
|
+
num_points_earned: number;
|
|
636
|
+
num_points_possible: number;
|
|
637
|
+
percent_graded: number;
|
|
638
|
+
problem_scores: Array<Record<string, unknown>>;
|
|
639
|
+
learner_has_access: boolean;
|
|
640
|
+
url: string;
|
|
641
|
+
}
|
|
642
|
+
export interface LearnerEdxSectionScore {
|
|
643
|
+
display_name: string;
|
|
644
|
+
subsections: LearnerEdxSubsectionScore[];
|
|
645
|
+
}
|
|
646
|
+
export interface LearnerEdxCertificateData {
|
|
647
|
+
cert_status: string | null;
|
|
648
|
+
cert_web_view_url: string | null;
|
|
649
|
+
download_url: string | null;
|
|
650
|
+
certificate_available_date: string | null;
|
|
651
|
+
}
|
|
652
|
+
export interface LearnerEdxProgress {
|
|
653
|
+
completion_summary?: LearnerEdxCompletionSummary;
|
|
654
|
+
course_grade?: LearnerEdxCourseGrade;
|
|
655
|
+
enrollment_mode?: string;
|
|
656
|
+
user_has_passing_grade?: boolean;
|
|
657
|
+
certificate_data?: LearnerEdxCertificateData;
|
|
658
|
+
grading_policy?: LearnerEdxGradingPolicy;
|
|
659
|
+
section_scores?: LearnerEdxSectionScore[];
|
|
660
|
+
}
|
|
661
|
+
export interface LearnerCourseDetail {
|
|
662
|
+
course_id: string;
|
|
663
|
+
name: string;
|
|
664
|
+
platform: string;
|
|
665
|
+
enrollment: LearnerContentEnrollment;
|
|
666
|
+
completion: LearnerContentCompletion | null;
|
|
667
|
+
time_spent: string;
|
|
668
|
+
time_spent_secs: number;
|
|
669
|
+
edx_progress?: LearnerEdxProgress | null;
|
|
670
|
+
}
|
|
671
|
+
export interface LearnerProgramDetail {
|
|
672
|
+
program_id: string;
|
|
673
|
+
name: string;
|
|
674
|
+
platform: string;
|
|
675
|
+
enrollment: LearnerContentEnrollment;
|
|
676
|
+
completion: LearnerContentCompletion | null;
|
|
677
|
+
time_spent: string;
|
|
678
|
+
time_spent_secs: number;
|
|
679
|
+
edx_progress?: LearnerEdxProgress | null;
|
|
680
|
+
}
|
|
681
|
+
export interface LearnerTimeSpentSummary {
|
|
682
|
+
courses: unknown[];
|
|
683
|
+
total_time_spent: string;
|
|
684
|
+
total_time_spent_secs: number;
|
|
685
|
+
}
|
|
686
|
+
export interface LearnerDetailsData {
|
|
687
|
+
courses?: LearnerCourseDetail[];
|
|
688
|
+
programs?: LearnerProgramDetail[];
|
|
689
|
+
pathways?: Array<Record<string, unknown>>;
|
|
690
|
+
skills?: Array<Record<string, unknown>>;
|
|
691
|
+
time_spent?: LearnerTimeSpentSummary;
|
|
692
|
+
}
|
|
693
|
+
export interface LearnerDetailsResponse {
|
|
694
|
+
user: LearnerDetailsUser;
|
|
695
|
+
data: LearnerDetailsData;
|
|
696
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { UserProfile, GetUserMetadataArgs, UpdateUserRoleRequest, UpdateUserAccountRequest, UploadProfileImageResponse, RemoveProfileImageResponse, UserPlatformMetadata, GetUserPlatformMetadataArgs, UpdateUserPlatformMetadataArgs } from './types';
|
|
1
|
+
import type { UserProfile, GetUserMetadataArgs, ResetPasswordArgs, UpdateUserRoleRequest, UpdateUserAccountRequest, UploadProfileImageResponse, RemoveProfileImageResponse, UserPlatformMetadata, GetUserPlatformMetadataArgs, UpdateUserPlatformMetadataArgs } from './types';
|
|
2
2
|
export declare const userApiSlice: import("@reduxjs/toolkit/query").Api<import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, {
|
|
3
3
|
getUserMetadata: import("@reduxjs/toolkit/query").QueryDefinition<GetUserMetadataArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, UserProfile, "userApiSlice", unknown>;
|
|
4
4
|
updateUserMetadata: import("@reduxjs/toolkit/query").MutationDefinition<UserProfile, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, unknown, "userApiSlice", unknown>;
|
|
5
5
|
updateUserAccount: import("@reduxjs/toolkit/query").MutationDefinition<UpdateUserAccountRequest, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, unknown, "userApiSlice", unknown>;
|
|
6
|
-
resetPassword: import("@reduxjs/toolkit/query").MutationDefinition<
|
|
6
|
+
resetPassword: import("@reduxjs/toolkit/query").MutationDefinition<ResetPasswordArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, void, "userApiSlice", unknown>;
|
|
7
7
|
updateUserRole: import("@reduxjs/toolkit/query").MutationDefinition<UpdateUserRoleRequest, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, unknown, "userApiSlice", unknown>;
|
|
8
8
|
getUserMetadataEdx: import("@reduxjs/toolkit/query").QueryDefinition<GetUserMetadataArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, Partial<UserProfile>, "userApiSlice", unknown>;
|
|
9
9
|
uploadProfileImage: import("@reduxjs/toolkit/query").MutationDefinition<{
|
|
@@ -624,14 +624,14 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
624
624
|
status: import("@reduxjs/toolkit/query").QueryStatus.fulfilled;
|
|
625
625
|
} & Omit<{
|
|
626
626
|
requestId: string;
|
|
627
|
-
data?:
|
|
627
|
+
data?: void | undefined;
|
|
628
628
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
629
629
|
endpointName: string;
|
|
630
630
|
startedTimeStamp: number;
|
|
631
631
|
fulfilledTimeStamp?: number;
|
|
632
632
|
}, "data" | "fulfilledTimeStamp"> & Required<Pick<{
|
|
633
633
|
requestId: string;
|
|
634
|
-
data?:
|
|
634
|
+
data?: void | undefined;
|
|
635
635
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
636
636
|
endpointName: string;
|
|
637
637
|
startedTimeStamp: number;
|
|
@@ -648,7 +648,7 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
648
648
|
status: import("@reduxjs/toolkit/query").QueryStatus.pending;
|
|
649
649
|
} & {
|
|
650
650
|
requestId: string;
|
|
651
|
-
data?:
|
|
651
|
+
data?: void | undefined;
|
|
652
652
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
653
653
|
endpointName: string;
|
|
654
654
|
startedTimeStamp: number;
|
|
@@ -665,14 +665,14 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
665
665
|
status: import("@reduxjs/toolkit/query").QueryStatus.rejected;
|
|
666
666
|
} & Omit<{
|
|
667
667
|
requestId: string;
|
|
668
|
-
data?:
|
|
668
|
+
data?: void | undefined;
|
|
669
669
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
670
670
|
endpointName: string;
|
|
671
671
|
startedTimeStamp: number;
|
|
672
672
|
fulfilledTimeStamp?: number;
|
|
673
673
|
}, "error"> & Required<Pick<{
|
|
674
674
|
requestId: string;
|
|
675
|
-
data?:
|
|
675
|
+
data?: void | undefined;
|
|
676
676
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
677
677
|
endpointName: string;
|
|
678
678
|
startedTimeStamp: number;
|
|
@@ -702,14 +702,14 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
702
702
|
status: import("@reduxjs/toolkit/query").QueryStatus.fulfilled;
|
|
703
703
|
} & Omit<{
|
|
704
704
|
requestId: string;
|
|
705
|
-
data?:
|
|
705
|
+
data?: void | undefined;
|
|
706
706
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
707
707
|
endpointName: string;
|
|
708
708
|
startedTimeStamp: number;
|
|
709
709
|
fulfilledTimeStamp?: number;
|
|
710
710
|
}, "data" | "fulfilledTimeStamp"> & Required<Pick<{
|
|
711
711
|
requestId: string;
|
|
712
|
-
data?:
|
|
712
|
+
data?: void | undefined;
|
|
713
713
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
714
714
|
endpointName: string;
|
|
715
715
|
startedTimeStamp: number;
|
|
@@ -726,7 +726,7 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
726
726
|
status: import("@reduxjs/toolkit/query").QueryStatus.pending;
|
|
727
727
|
} & {
|
|
728
728
|
requestId: string;
|
|
729
|
-
data?:
|
|
729
|
+
data?: void | undefined;
|
|
730
730
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
731
731
|
endpointName: string;
|
|
732
732
|
startedTimeStamp: number;
|
|
@@ -743,14 +743,14 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
743
743
|
status: import("@reduxjs/toolkit/query").QueryStatus.rejected;
|
|
744
744
|
} & Omit<{
|
|
745
745
|
requestId: string;
|
|
746
|
-
data?:
|
|
746
|
+
data?: void | undefined;
|
|
747
747
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
748
748
|
endpointName: string;
|
|
749
749
|
startedTimeStamp: number;
|
|
750
750
|
fulfilledTimeStamp?: number;
|
|
751
751
|
}, "error"> & Required<Pick<{
|
|
752
752
|
requestId: string;
|
|
753
|
-
data?:
|
|
753
|
+
data?: void | undefined;
|
|
754
754
|
error?: import("../utils").ExtendedFetchBaseQueryError | import("@reduxjs/toolkit").SerializedError | undefined;
|
|
755
755
|
endpointName: string;
|
|
756
756
|
startedTimeStamp: number;
|
|
@@ -763,8 +763,8 @@ export declare const useGetUserMetadataQuery: <R extends Record<string, any> = i
|
|
|
763
763
|
isError: true;
|
|
764
764
|
})) => R) | undefined;
|
|
765
765
|
fixedCacheKey?: string;
|
|
766
|
-
} | undefined) => readonly [(arg:
|
|
767
|
-
originalArgs?:
|
|
766
|
+
} | undefined) => readonly [(arg: ResetPasswordArgs) => import("@reduxjs/toolkit/query").MutationActionCreatorResult<import("@reduxjs/toolkit/query").MutationDefinition<ResetPasswordArgs, import("@reduxjs/toolkit/query").BaseQueryFn<import("../utils").CustomQueryArgs, unknown, import("../utils").ExtendedFetchBaseQueryError, Record<string, unknown>, import("@reduxjs/toolkit/query").FetchBaseQueryMeta>, string, void, "userApiSlice", unknown>>, import("@reduxjs/toolkit/query").TSHelpersNoInfer<R> & {
|
|
767
|
+
originalArgs?: ResetPasswordArgs | undefined;
|
|
768
768
|
reset: () => void;
|
|
769
769
|
}], useUpdateUserRoleMutation: <R extends Record<string, any> = ({
|
|
770
770
|
requestId?: undefined;
|
|
@@ -62,6 +62,12 @@ export interface GetUserMetadataArgs {
|
|
|
62
62
|
username: string;
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
|
+
export interface ResetPasswordArgs {
|
|
66
|
+
email: string;
|
|
67
|
+
platformKey?: string;
|
|
68
|
+
redirectTo?: string;
|
|
69
|
+
app?: string;
|
|
70
|
+
}
|
|
65
71
|
export interface UpdateUserAccountRequest {
|
|
66
72
|
username: string;
|
|
67
73
|
name?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1101,7 +1101,7 @@ declare const isNode: () => string | false;
|
|
|
1101
1101
|
declare const isExpo: () => any;
|
|
1102
1102
|
declare const isTauri: () => boolean;
|
|
1103
1103
|
declare function isSafariBrowser(): boolean;
|
|
1104
|
-
declare const getPlatform: () => "
|
|
1104
|
+
declare const getPlatform: () => "web" | "react-native" | "node" | "unknown";
|
|
1105
1105
|
declare const safeRequire: (moduleName: string) => any;
|
|
1106
1106
|
declare const getNextNavigation: () => any;
|
|
1107
1107
|
|
package/dist/index.esm.js
CHANGED
|
@@ -9375,6 +9375,14 @@ async function validateJwtToken(storageService) {
|
|
|
9375
9375
|
return false;
|
|
9376
9376
|
}
|
|
9377
9377
|
}
|
|
9378
|
+
/**
|
|
9379
|
+
* How long (ms) a redirect may be "in progress" before we assume the
|
|
9380
|
+
* navigation failed and allow a fresh attempt. Must be longer than the 3s
|
|
9381
|
+
* safety timer in `safeRedirectToAuthSpa` so the two don't fight; this is
|
|
9382
|
+
* the backstop for when that timer is lost because the page began
|
|
9383
|
+
* unloading and then survived (bfcache restore, aborted navigation).
|
|
9384
|
+
*/
|
|
9385
|
+
const REDIRECT_STUCK_MS = 5000;
|
|
9378
9386
|
function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure, redirectToAuthSpa, username, pathname, storageService, skipAuthCheck, token, enableStorageSync = true, }) {
|
|
9379
9387
|
const [isAuthenticating, setIsAuthenticating] = useState(true);
|
|
9380
9388
|
const [userIsAccessingPublicRoute, setUserIsAccessingPublicRoute] = useState(false);
|
|
@@ -9382,21 +9390,51 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
9382
9390
|
const cookieCheckIntervalRef = useRef(null);
|
|
9383
9391
|
const lastLogoutTimestampRef = useRef(null);
|
|
9384
9392
|
const lastLoginTimestampRef = useRef(null);
|
|
9385
|
-
// Guard to prevent poll from firing
|
|
9386
|
-
//
|
|
9393
|
+
// Guard to prevent the poll from firing redundant redirects while a
|
|
9394
|
+
// navigation to the auth SPA is already underway.
|
|
9387
9395
|
const isRedirectingRef = useRef(false);
|
|
9396
|
+
// Wall-clock time (ms) at which the in-progress redirect was started.
|
|
9397
|
+
// Used to self-heal a stuck guard: the browser discards our 3s safety
|
|
9398
|
+
// timer the instant navigation begins, so if navigation never actually
|
|
9399
|
+
// completes (page restored from bfcache, redirect aborted/slow, timers
|
|
9400
|
+
// throttled during unload) the boolean alone would latch ON forever and
|
|
9401
|
+
// suppress every future redirect. This timestamp lets the poll detect
|
|
9402
|
+
// that case and reset the guard. See `redirectInProgress`.
|
|
9403
|
+
const redirectStartedAtRef = useRef(0);
|
|
9388
9404
|
// RTK Query hook for refreshing JWT token
|
|
9389
9405
|
const [refreshJwtToken] = useLazyRefreshJwtTokenQuery();
|
|
9390
9406
|
/**
|
|
9391
|
-
*
|
|
9392
|
-
*
|
|
9407
|
+
* Whether a redirect is genuinely still in progress.
|
|
9408
|
+
*
|
|
9409
|
+
* Returns false (and resets the guard) when the redirect was started more
|
|
9410
|
+
* than REDIRECT_STUCK_MS ago, since at that point the page is clearly
|
|
9411
|
+
* still alive and the navigation must have failed. This is what lets the
|
|
9412
|
+
* app recover on its own instead of latching the guard ON forever and
|
|
9413
|
+
* needing a manual cookie clear / hard reload.
|
|
9414
|
+
*/
|
|
9415
|
+
const redirectInProgress = () => {
|
|
9416
|
+
if (!isRedirectingRef.current)
|
|
9417
|
+
return false;
|
|
9418
|
+
const elapsed = Date.now() - redirectStartedAtRef.current;
|
|
9419
|
+
if (elapsed > REDIRECT_STUCK_MS) {
|
|
9420
|
+
console.log("[AuthProvider] redirect guard stuck for", elapsed, "ms — navigation never completed, resetting so we can retry");
|
|
9421
|
+
isRedirectingRef.current = false;
|
|
9422
|
+
redirectStartedAtRef.current = 0;
|
|
9423
|
+
return false;
|
|
9424
|
+
}
|
|
9425
|
+
return true;
|
|
9426
|
+
};
|
|
9427
|
+
/**
|
|
9428
|
+
* Wrapper around redirectToAuthSpa that prevents redundant redirect calls
|
|
9429
|
+
* from racing while a navigation is already underway.
|
|
9393
9430
|
*/
|
|
9394
9431
|
const safeRedirectToAuthSpa = (...args) => {
|
|
9395
|
-
if (
|
|
9432
|
+
if (redirectInProgress()) {
|
|
9396
9433
|
console.log("[AuthProvider] Redirect already in progress, skipping");
|
|
9397
9434
|
return;
|
|
9398
9435
|
}
|
|
9399
9436
|
isRedirectingRef.current = true;
|
|
9437
|
+
redirectStartedAtRef.current = Date.now();
|
|
9400
9438
|
// NOTE: we intentionally do NOT clear the interval here.
|
|
9401
9439
|
// The isRedirectingRef guard prevents redundant redirects while navigation
|
|
9402
9440
|
// is in progress. Clearing the interval preemptively can permanently stop
|
|
@@ -9411,6 +9449,7 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
9411
9449
|
if (isRedirectingRef.current) {
|
|
9412
9450
|
console.log("[AuthProvider] safeRedirectToAuthSpa: navigation did not occur, resetting redirect guard");
|
|
9413
9451
|
isRedirectingRef.current = false;
|
|
9452
|
+
redirectStartedAtRef.current = 0;
|
|
9414
9453
|
}
|
|
9415
9454
|
}, 3000);
|
|
9416
9455
|
};
|
|
@@ -9437,6 +9476,7 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
9437
9476
|
}
|
|
9438
9477
|
// Reset redirect guard on effect setup (new mount / dep change)
|
|
9439
9478
|
isRedirectingRef.current = false;
|
|
9479
|
+
redirectStartedAtRef.current = 0;
|
|
9440
9480
|
// Initial sync on mount
|
|
9441
9481
|
async function initialSync() {
|
|
9442
9482
|
console.log("[AuthProvider] initialSync starting");
|
|
@@ -9467,8 +9507,11 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
9467
9507
|
initialSync();
|
|
9468
9508
|
// Poll for cookie changes every 2 seconds to detect cross-SPA updates
|
|
9469
9509
|
cookieCheckIntervalRef.current = setInterval(async () => {
|
|
9470
|
-
// If a redirect is
|
|
9471
|
-
|
|
9510
|
+
// If a redirect is genuinely still in progress, skip entirely.
|
|
9511
|
+
// redirectInProgress() self-heals a guard that got stuck because a
|
|
9512
|
+
// navigation was initiated but the page survived (bfcache, aborted
|
|
9513
|
+
// redirect), so this no longer latches ON forever.
|
|
9514
|
+
if (redirectInProgress()) {
|
|
9472
9515
|
console.log("[AuthProvider] interval: redirect already in progress, skipping");
|
|
9473
9516
|
return;
|
|
9474
9517
|
}
|
|
@@ -9541,6 +9584,27 @@ function useAuthProvider({ middleware = new Map(), onAuthSuccess, onAuthFailure,
|
|
|
9541
9584
|
window.addEventListener("storage", handleStorageChange);
|
|
9542
9585
|
return () => window.removeEventListener("storage", handleStorageChange);
|
|
9543
9586
|
}, [storageService, enableStorageSync]);
|
|
9587
|
+
/**
|
|
9588
|
+
* Reset the redirect guard when the page is restored from the back/forward
|
|
9589
|
+
* cache (web only). When a redirect calls window.location.href the browser
|
|
9590
|
+
* may freeze and bfcache the page rather than destroy it; navigating back
|
|
9591
|
+
* then restores it with isRedirectingRef still latched ON and the 3s safety
|
|
9592
|
+
* timer discarded. Clearing the guard here lets redirects fire again
|
|
9593
|
+
* without a manual cookie clear / hard reload.
|
|
9594
|
+
*/
|
|
9595
|
+
useEffect(() => {
|
|
9596
|
+
if (!isWeb$1() || skipAuthCheck)
|
|
9597
|
+
return;
|
|
9598
|
+
const handlePageShow = (event) => {
|
|
9599
|
+
if (event.persisted) {
|
|
9600
|
+
console.log("[AuthProvider] pageshow from bfcache — resetting redirect guard");
|
|
9601
|
+
isRedirectingRef.current = false;
|
|
9602
|
+
redirectStartedAtRef.current = 0;
|
|
9603
|
+
}
|
|
9604
|
+
};
|
|
9605
|
+
window.addEventListener("pageshow", handlePageShow);
|
|
9606
|
+
return () => window.removeEventListener("pageshow", handlePageShow);
|
|
9607
|
+
}, [skipAuthCheck]);
|
|
9544
9608
|
/**
|
|
9545
9609
|
* Performs the authentication check by:
|
|
9546
9610
|
* 1. Validating the auth token
|
|
@@ -10358,7 +10422,8 @@ function MentorProvider({ children, fallback, onAuthSuccess, onAuthFailure, redi
|
|
|
10358
10422
|
console.log("[determineMentorToRedirectTo] starredMentors ", starredMentors);
|
|
10359
10423
|
if (starredMentors && starredMentors.length > 0) {
|
|
10360
10424
|
const starredMentor = starredMentors[0];
|
|
10361
|
-
|
|
10425
|
+
// @ts-expect-error - mentor is not part of the starred mentor object
|
|
10426
|
+
if ((starredMentor === null || starredMentor === void 0 ? void 0 : starredMentor.unique_id) || (starredMentor === null || starredMentor === void 0 ? void 0 : starredMentor.mentor)) {
|
|
10362
10427
|
return starredMentor;
|
|
10363
10428
|
}
|
|
10364
10429
|
}
|