Skip to content

Commit 1785a92

Browse files
committed
Merge branch '4.0.0-dev' into student_quiz_issues
2 parents b64e989 + aff2c8c commit 1785a92

30 files changed

Lines changed: 659 additions & 229 deletions

File tree

assets/core/scss/mixins/_buttons.scss

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@
4141

4242
&:disabled,
4343
&.disabled {
44-
color: $tutor-text-disabled;
44+
color: $tutor-text-subdued;
4545
cursor: not-allowed;
4646
pointer-events: none;
4747

4848
svg:not([class]) {
49-
color: $tutor-icon-disabled;
49+
color: $tutor-icon-subdued;
5050
}
5151
}
5252
}
@@ -103,7 +103,6 @@
103103
&:disabled,
104104
&.disabled {
105105
background-color: $tutor-button-disabled;
106-
color: $tutor-text-brand;
107106
--tutor-button-border-shadow: #{$tutor-button-primary-soft-border-shadow-disabled};
108107
}
109108
} @else if $variant == destructive {
@@ -130,7 +129,6 @@
130129
&:disabled,
131130
&.disabled {
132131
background-color: $tutor-button-disabled;
133-
color: $tutor-text-primary-inverse;
134132
--tutor-button-border-shadow: #{$tutor-button-destructive-border-shadow-disabled};
135133
}
136134
} @else if $variant == destructive-soft {

assets/src/js/frontend/learning-area/sidebar.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface ResetProgressPayload {
1616

1717
interface ResetProgressResponse {
1818
success: boolean;
19+
status_code?: number;
1920
message?: string;
2021
data?: {
2122
redirect_to: string;
@@ -54,8 +55,9 @@ export const sidebarComponent = ({
5455
(payload) => wpAjaxInstance.post(endpoints.RESET_COURSE_PROGRESS, payload),
5556
{
5657
onSuccess: (response) => {
57-
if (response.success && response.data?.redirect_to) {
58+
if (response.status_code === 200 && response.data?.redirect_to) {
5859
window.location.href = response.data.redirect_to;
60+
modal.closeModal(this.resetModalId);
5961
}
6062
},
6163
onError: (error: AxiosError) => {

assets/src/js/lib/utilities.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ window.jQuery(document).ready(function($) {
5151
.addClass('is-loading');
5252
},
5353
success: function(data) {
54-
if (data.success) {
54+
if (data.success || data.status_code === 200) {
5555
if (del) {
5656
$('#' + del).fadeOut(function() {
5757
$(this).remove();

assets/src/js/v3/@types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ declare global {
187187
enable_individual_tax_control: boolean;
188188
is_tax_included_in_price: boolean;
189189
pagination_per_page: string;
190+
quiz_attempts_allowed: string;
190191
};
191192
tutor_currency: {
192193
symbol: string;

assets/src/js/v3/entries/addon-list/components/App.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Global } from '@emotion/react';
22
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
33
import ToastProvider from '@TutorShared/atoms/Toast';
44
import RTLProvider from '@TutorShared/components/RTLProvider';
5+
import { SVGIconConfigProvider } from '@TutorShared/contexts/SVGIconConfigContext';
56
import { createGlobalCss } from '@TutorShared/utils/style-utils';
67
import { useState } from 'react';
78
import Main from './layout/Main';
@@ -27,10 +28,12 @@ function App() {
2728
return (
2829
<RTLProvider>
2930
<QueryClientProvider client={queryClient}>
30-
<ToastProvider position="bottom-center">
31-
<Global styles={createGlobalCss()} />
32-
<Main />
33-
</ToastProvider>
31+
<SVGIconConfigProvider>
32+
<ToastProvider position="bottom-center">
33+
<Global styles={createGlobalCss()} />
34+
<Main />
35+
</ToastProvider>
36+
</SVGIconConfigProvider>
3437
</QueryClientProvider>
3538
</RTLProvider>
3639
);

assets/src/js/v3/entries/coupon-details/components/App.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
33
import ToastProvider from '@TutorShared/atoms/Toast';
44
import { ModalProvider } from '@TutorShared/components/modals/Modal';
55
import RTLProvider from '@TutorShared/components/RTLProvider';
6+
import { SVGIconConfigProvider } from '@TutorShared/contexts/SVGIconConfigContext';
67
import { createGlobalCss } from '@TutorShared/utils/style-utils';
78
import { useState } from 'react';
89
import Main from './layout/Main';
@@ -27,12 +28,14 @@ function App() {
2728
return (
2829
<RTLProvider>
2930
<QueryClientProvider client={queryClient}>
30-
<ToastProvider position="bottom-center">
31-
<ModalProvider>
32-
<Global styles={createGlobalCss()} />
33-
<Main />
34-
</ModalProvider>
35-
</ToastProvider>
31+
<SVGIconConfigProvider>
32+
<ToastProvider position="bottom-center">
33+
<ModalProvider>
34+
<Global styles={createGlobalCss()} />
35+
<Main />
36+
</ModalProvider>
37+
</ToastProvider>
38+
</SVGIconConfigProvider>
3639
</QueryClientProvider>
3740
</RTLProvider>
3841
);

assets/src/js/v3/entries/course-builder/components/App.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { CourseBuilderSlotProvider } from '@CourseBuilderContexts/CourseBuilderS
33
import ToastProvider from '@TutorShared/atoms/Toast';
44
import RTLProvider from '@TutorShared/components/RTLProvider';
55
import { ModalProvider } from '@TutorShared/components/modals/Modal';
6+
import { SVGIconConfigProvider } from '@TutorShared/contexts/SVGIconConfigContext';
67
import { createGlobalCss } from '@TutorShared/utils/style-utils';
78
import { Global } from '@emotion/react';
89
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
@@ -32,14 +33,16 @@ const App = () => {
3233
return (
3334
<RTLProvider>
3435
<QueryClientProvider client={queryClient}>
35-
<ToastProvider position="bottom-center">
36-
<CourseBuilderSlotProvider>
37-
<ModalProvider>
38-
<Global styles={createGlobalCss()} />
39-
{routers}
40-
</ModalProvider>
41-
</CourseBuilderSlotProvider>
42-
</ToastProvider>
36+
<SVGIconConfigProvider>
37+
<ToastProvider position="bottom-center">
38+
<CourseBuilderSlotProvider>
39+
<ModalProvider>
40+
<Global styles={createGlobalCss()} />
41+
{routers}
42+
</ModalProvider>
43+
</CourseBuilderSlotProvider>
44+
</ToastProvider>
45+
</SVGIconConfigProvider>
4346
</QueryClientProvider>
4447
</RTLProvider>
4548
);

assets/src/js/v3/entries/course-builder/components/curriculum/QuestionList.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,27 @@ const QuestionList = ({ isEditing }: { isEditing: boolean }) => {
431431
};
432432

433433
const handleDeleteQuestion = (index: number, question: QuizQuestion) => {
434+
if (question._data_status === QuizDataStatus.NEW) {
435+
const isMaskQuestionType =
436+
question.question_type === 'draw_image' ||
437+
question.question_type === 'pin_image' ||
438+
question.question_type === 'puzzle';
439+
440+
if (isMaskQuestionType) {
441+
const tempMaskValues = (question.question_answers || [])
442+
.flatMap((answer) => [answer.answer_two_gap_match, answer.image_url])
443+
.map((value) => (typeof value === 'string' ? value.trim() : ''))
444+
.filter(Boolean);
445+
446+
if (tempMaskValues.length > 0) {
447+
form.setValue('deleted_temp_mask_values', [
448+
...(form.getValues('deleted_temp_mask_values') || []),
449+
...tempMaskValues,
450+
]);
451+
}
452+
}
453+
}
454+
434455
removeQuestion(index);
435456

436457
if (activeQuestionIndex === index) {

assets/src/js/v3/entries/course-builder/components/modals/QuizModal.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { POPOVER_PLACEMENTS } from '@TutorShared/hooks/usePortalPopover';
4444
import { validateQuizQuestion } from '@TutorShared/utils/quiz';
4545
import { type ID, isDefined, type TopicContentType } from '@TutorShared/utils/types';
4646
import { findSlotFields } from '@TutorShared/utils/util';
47+
import { tutorConfig } from '@TutorShared/config/config';
4748

4849
interface QuizModalProps extends ModalProps {
4950
quizId?: ID;
@@ -56,6 +57,7 @@ interface QuizModalProps extends ModalProps {
5657
type QuizTabs = 'details' | 'settings';
5758

5859
const courseId = getCourseId();
60+
const defaultQuizAttemptsAllowed = tutorConfig.settings?.quiz_attempts_allowed ?? 10;
5961

6062
const QuizModal = ({
6163
closeModal,
@@ -89,7 +91,7 @@ const QuizModal = ({
8991
hide_quiz_time_display: false,
9092
limit_attempts_allowed: false,
9193
limit_questions_to_answer: false,
92-
attempts_allowed: 10,
94+
attempts_allowed: defaultQuizAttemptsAllowed,
9395
passing_grade: 80,
9496
max_questions_for_answer: contentType === 'tutor_h5p_quiz' ? 0 : 10,
9597
quiz_auto_start: false,

assets/src/js/v3/entries/course-builder/services/quiz.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ interface QuizPayload {
6767
payload: QuizResponseWithStatus;
6868
deleted_question_ids?: ID[];
6969
deleted_answer_ids?: ID[];
70+
deleted_temp_mask_values?: string[];
7071
'content_drip_settings[unlock_date]'?: string;
7172
'content_drip_settings[after_xdays_of_enroll]'?: number;
7273
'content_drip_settings[prerequisites]'?: ID[] | string;
@@ -148,6 +149,7 @@ export interface QuizForm {
148149
questions: QuizQuestion[];
149150
deleted_question_ids: ID[];
150151
deleted_answer_ids: ID[];
152+
deleted_temp_mask_values: string[];
151153
}
152154

153155
interface QuizUpdateQuestionPayload {
@@ -163,6 +165,7 @@ interface QuizUpdateQuestionPayload {
163165
}
164166

165167
export const convertQuizResponseToFormData = (quiz: QuizDetailsResponse, slotFields: string[]): QuizForm => {
168+
const defaultQuizAttemptsAllowed = tutorConfig.settings?.quiz_attempts_allowed ?? 10;
166169
const legacyQuizOption = quiz.quiz_option as QuizDetailsResponse['quiz_option'] & {
167170
feedback_mode?: 'default' | 'reveal' | 'retry';
168171
};
@@ -182,7 +185,7 @@ export const convertQuizResponseToFormData = (quiz: QuizDetailsResponse, slotFie
182185
limit_attempts_allowed: isDefined(quiz.quiz_option.limit_attempts_allowed)
183186
? quiz.quiz_option.limit_attempts_allowed === '1'
184187
: legacyQuizOption.feedback_mode === 'retry',
185-
attempts_allowed: quiz.quiz_option.attempts_allowed ?? 10,
188+
attempts_allowed: quiz.quiz_option.attempts_allowed ?? defaultQuizAttemptsAllowed,
186189
pass_is_required: quiz.quiz_option.pass_is_required === '1',
187190
passing_grade: quiz.quiz_option.passing_grade ?? 80,
188191
limit_questions_to_answer: !!Number(quiz.quiz_option.max_questions_for_answer),
@@ -214,6 +217,7 @@ export const convertQuizResponseToFormData = (quiz: QuizDetailsResponse, slotFie
214217
questions: (quiz.questions || []).map((question) => convertedQuestion(question)),
215218
deleted_question_ids: [],
216219
deleted_answer_ids: [],
220+
deleted_temp_mask_values: [],
217221
...Object.fromEntries(slotFields.map((key) => [key, quiz[key as keyof QuizDetailsResponse]])),
218222
};
219223
};
@@ -363,6 +367,7 @@ export const convertQuizFormDataToPayload = (
363367
},
364368
deleted_question_ids: formData.deleted_question_ids,
365369
deleted_answer_ids: deletedAnswerIds,
370+
deleted_temp_mask_values: formData.deleted_temp_mask_values,
366371
...(isAddonEnabled(Addons.CONTENT_DRIP) &&
367372
contentDripType === 'unlock_by_date' && {
368373
'content_drip_settings[unlock_date]': formData.quiz_option.content_drip_settings.unlock_date,

0 commit comments

Comments
 (0)