diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/edit/ActivityDuration.vue b/contentcuration/contentcuration/frontend/channelEdit/components/edit/ActivityDuration.vue index 2209dda4ac..2afa529798 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/edit/ActivityDuration.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/edit/ActivityDuration.vue @@ -23,6 +23,7 @@ :items="availableNumbers" :menu-props="menuProps" :attach="attach" + :rules="minutesRules" /> @@ -102,10 +103,7 @@ if (this.audioVideoUpload) { return false; } - return ( - this.selectedDuration !== DurationDropdownMap.EXACT_TIME && - this.selectedCompletion === CompletionDropdownMap.completeDuration - ); + return this.selectedCompletion === CompletionDropdownMap.completeDuration; }, showOptionalLabel() { return this.selectedDuration !== DurationDropdownMap.EXACT_TIME; @@ -153,8 +151,13 @@ return getShortActivityDurationValidators().map(translateValidator); } else if (this.selectedDuration === DurationDropdownMap.LONG_ACTIVITY) { return getLongActivityDurationValidators().map(translateValidator); + } else if ( + this.selectedDuration === DurationDropdownMap.EXACT_TIME && + this.selectedCompletion === CompletionDropdownMap.completeDuration + ) { + return getActivityDurationValidators().map(translateValidator); } - return getActivityDurationValidators().map(translateValidator); + return []; }, }, created() { diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/edit/CompletionOptions.vue b/contentcuration/contentcuration/frontend/channelEdit/components/edit/CompletionOptions.vue index 78d23af0df..59aeb4d31e 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/edit/CompletionOptions.vue +++ b/contentcuration/contentcuration/frontend/channelEdit/components/edit/CompletionOptions.vue @@ -175,15 +175,9 @@ hideDurationDropdown() { // named "hide" instead of "show" because "show" is the default behavior if (this.value) { - if (this.kind === ContentKindsNames.H5P) { - return true; - } return ( - this.currentCompletionDropdown === CompletionDropdownMap.reference || - (this.value.model === CompletionCriteriaModels.REFERENCE && - !this.currentCompletionDropdown) || - //should be hidden if model is reference and we're getting this from the BE - this.currentCompletionDropdown === CompletionDropdownMap.determinedByResource + this.value.model == CompletionCriteriaModels.REFERENCE || + this.value.model == CompletionCriteriaModels.DETERMINED_BY_RESOURCE ); } return false; @@ -221,22 +215,15 @@ - Long activity, short activity, or exact time are chosen in HTML5 */ if (this.value) { - const switchingFromReferenceBetweenAllContentViewedAndCompleteDuration = - this.value.suggested_duration === null || this.value.suggested_duration_type === null; + if ( + this.value.model == CompletionCriteriaModels.REFERENCE || + this.value.model == CompletionCriteriaModels.DETERMINED_BY_RESOURCE + ) { + return false; + } if (!this.audioVideoResource) { - if (this.kind === ContentKindsNames.HTML5 || this.kind === ContentKindsNames.H5P) { - if (this.value.model !== CompletionCriteriaModels.REFERENCE) { - if (!this.currentCompletionDropdown) { - return true; - } - return this.currentCompletionDropdown === CompletionDropdownMap.completeDuration; - } - } - return !( - this.value.model === CompletionCriteriaModels.REFERENCE || - switchingFromReferenceBetweenAllContentViewedAndCompleteDuration - ); + return true; } } return this.audioVideoResource && this.value.model !== CompletionCriteriaModels.REFERENCE; @@ -250,6 +237,10 @@ return CompletionDropdownMap.completeDuration; } + if (this.value.model === CompletionCriteriaModels.REFERENCE) { + return CompletionDropdownMap.reference; + } + if (this.kind === ContentKindsNames.DOCUMENT) { if (!this.value['model']) { return CompletionDropdownMap.allContent; @@ -268,11 +259,13 @@ if ( !this.value['model'] || this.value.model === CompletionCriteriaModels.APPROX_TIME || - this.value.model === CompletionCriteriaModels.TIME || - this.value.model === CompletionCriteriaModels.REFERENCE + this.value.model === CompletionCriteriaModels.TIME ) { return CompletionDropdownMap.completeDuration; + } else if (this.value.model === CompletionCriteriaModels.REFERENCE) { + return CompletionDropdownMap.reference; } + return CompletionDropdownMap.determinedByResource; } @@ -287,8 +280,7 @@ } if (this.kind === ContentKindsNames.EXERCISE) { - // if the practice quiz flag is set, return "practice quiz" - if (this.practiceQuizzesAllowed && this.value.modality === ContentModalities.QUIZ) { + if (this.value.modality === ContentModalities.QUIZ) { return CompletionDropdownMap.practiceQuiz; } return CompletionDropdownMap.goal; @@ -308,6 +300,12 @@ threshold: null, }; } + if (value === CompletionDropdownMap.completeDuration) { + update.completion_criteria = { + model: CompletionCriteriaModels.TIME, + threshold: this.fileDuration || this.value.suggested_duration, + }; + } // FOR DOCUMENTS if (this.kind === ContentKindsNames.DOCUMENT) { @@ -324,6 +322,13 @@ model: CompletionCriteriaModels.REFERENCE, threshold: null, }; + } else if (value === CompletionDropdownMap.completeDuration) { + // set to '1' as the minimum here, due to validation rules requiring > 0 + update.suggested_duration = this.value.suggested_duration || 60; + update.completion_criteria = { + model: CompletionCriteriaModels.TIME, + threshold: this.value.suggested_duration || 60, + }; } else { update.suggested_duration_type = this.value.suggested_duration_type; update.suggested_duration = this.value.suggested_duration; @@ -357,6 +362,12 @@ model: CompletionCriteriaModels.DETERMINED_BY_RESOURCE, threshold: null, }; + } else if (value === CompletionDropdownMap.completeDuration) { + update.suggested_duration = this.value.suggested_duration || 60; + update.completion_criteria = { + model: CompletionCriteriaModels.TIME, + threshold: this.value.suggested_duration || 60, + }; } } @@ -365,8 +376,8 @@ if (value === CompletionDropdownMap.practiceQuiz) { update.modality = ContentModalities.QUIZ; update.completion_criteria = { - model: this.value.model, - threshold: this.value.threshold, + model: this.value.model || CompletionCriteriaModels.MASTERY, + threshold: this.value.threshold || { mastery_model: MasteryModelsNames.DO_ALL }, }; } else { update.modality = null; @@ -572,7 +583,10 @@ ) { if (duration === DurationDropdownMap.EXACT_TIME) { update.suggested_duration_type = SuggestedDurationTypesMap.TIME; - update.suggested_duration = this.value.suggested_duration || 60; + update.suggested_duration = this.handleMinutesInputFromActivityDuration( + this.value.suggested_duration, + duration + ); } if (duration === DurationDropdownMap.SHORT_ACTIVITY) { update.suggested_duration_type = SuggestedDurationTypesMap.APPROX_TIME; @@ -623,7 +637,10 @@ } if (duration === DurationDropdownMap.EXACT_TIME) { update.suggested_duration_type = SuggestedDurationTypesMap.TIME; - update.suggested_duration = this.value.suggested_duration || 60; + update.suggested_duration = this.handleMinutesInputFromActivityDuration( + this.value.suggested_duration, + duration + ); update.completion_criteria = { model: CompletionCriteriaModels.TIME, threshold: update.suggested_duration, @@ -657,7 +674,10 @@ } if (duration === DurationDropdownMap.EXACT_TIME) { update.suggested_duration_type = SuggestedDurationTypesMap.TIME; - update.suggested_duration = this.value.suggested_duration || 60; + update.suggested_duration = this.handleMinutesInputFromActivityDuration( + this.value.suggested_duration, + duration + ); update.completion_criteria = { model: this.value.model, threshold: this.value.threshold, @@ -776,18 +796,13 @@ return false; }, durationRules() { - const defaultStateForDocument = this.currentCompletionDropdown === null; - if (this.value) { - const allContentViewedIsChosenInCompletionDropdown = - this.currentCompletionDropdown === CompletionDropdownMap.allContent || - (this.value.model === CompletionCriteriaModels.PAGES && - this.currentCompletionDropdown === CompletionDropdownMap.allContent); - - if (defaultStateForDocument || allContentViewedIsChosenInCompletionDropdown) { - return []; - } + if ( + this.currentCompletionDropdown === CompletionDropdownMap.completeDuration || + this.completionDropdown === CompletionDropdownMap.completeDuration + ) { + return getDurationValidators().map(translateValidator); } - return getDurationValidators().map(translateValidator); + return []; }, }, methods: { diff --git a/contentcuration/contentcuration/frontend/channelEdit/components/edit/__tests__/completionOptions.spec.js b/contentcuration/contentcuration/frontend/channelEdit/components/edit/__tests__/completionOptions.spec.js index 5361515e52..8e92f8acbe 100644 --- a/contentcuration/contentcuration/frontend/channelEdit/components/edit/__tests__/completionOptions.spec.js +++ b/contentcuration/contentcuration/frontend/channelEdit/components/edit/__tests__/completionOptions.spec.js @@ -83,23 +83,23 @@ describe('CompletionOptions', () => { }); expect(wrapper.vm.completionDropdown).toBe('allContent'); }); - it(`'All content viewed' should be displayed if the model in the backend is 'reference'`, () => { + it(`'All content viewed' should be displayed if the model in the backend is 'pages'`, () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'document', - value: { model: 'reference' }, + value: { model: 'pages', threshold: '100%' }, }, }); expect(wrapper.vm.completionDropdown).toBe('allContent'); }); - it(`'All content viewed' should be displayed if the model in the backend is 'pages'`, () => { + it(`'Reference' should be displayed if the model in the backend is 'reference'`, () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'document', - value: { model: 'pages', threshold: '100%' }, + value: { model: 'reference' }, }, }); - expect(wrapper.vm.completionDropdown).toBe('allContent'); + expect(wrapper.vm.completionDropdown).toBe('reference'); }); it(`'Complete duration' should be displayed if 'exact time'`, () => { const wrapper = mount(CompletionOptions, { @@ -145,7 +145,7 @@ describe('CompletionOptions', () => { }); }); describe(`exercise`, () => { - it(`'Practice until goal is met' should be displayed by default if 'practice quiz' is enabled `, () => { + it(`'When goal is met' should be displayed by default`, () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'exercise', @@ -156,7 +156,7 @@ describe('CompletionOptions', () => { }); }); describe(`html5 or h5p`, () => { - it(`'Complete duration' should be displayed by default for html5`, () => { + it(`'When time spent is equal to duration' should be displayed by default for html5 and h5p`, () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'html5', @@ -165,15 +165,6 @@ describe('CompletionOptions', () => { }); expect(wrapper.vm.completionDropdown).toBe('completeDuration'); }); - it(`'Determined by this resource' should be displayed if there is no model in the backend for h5p`, () => { - const wrapper = mount(CompletionOptions, { - propsData: { - kind: 'h5p', - value: { model: null }, - }, - }); - expect(wrapper.vm.completionDropdown).toBe('determinedByResource'); - }); }); }); describe(`changing states`, () => { @@ -191,11 +182,10 @@ describe('CompletionOptions', () => { expect(wrapper.emitted('input')).toBeTruthy(); }); }); - describe(`audio/video`, () => { + describe(`reference hint`, () => { it(`'Reference hint is visible when 'Reference' is selected`, () => { const wrapper = mount(CompletionOptions, { propsData: { - kind: 'audio', value: { model: 'reference' }, }, }); @@ -203,7 +193,7 @@ describe('CompletionOptions', () => { }); }); describe(`exercise`, () => { - it(`Goal and MofN components should not be displayed when switching to PQ from PUGIM`, async () => { + it(`Goal and MofN components should not be displayed when 'Practice Quiz' is selected`, async () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'exercise', @@ -278,7 +268,10 @@ describe('CompletionOptions', () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'h5p', - value: { suggested_duration: null }, + value: { + suggested_duration: null, + model: CompletionCriteriaModels.DETERMINED_BY_RESOURCE, + }, }, }); const dropdown = wrapper.find({ ref: 'duration' }); @@ -625,7 +618,7 @@ describe('CompletionOptions', () => { }); describe(`html5 or h5p`, () => { describe(`when completion dropdown is 'Determined by this resource'`, () => { - it(`minutes input is displayed when 'Short activity' is selected`, async () => { + it(`duration dropdown is always hidden`, async () => { const wrapper = mount(CompletionOptions, { propsData: { kind: 'html5', @@ -635,40 +628,9 @@ describe('CompletionOptions', () => { }, }, }); - wrapper.find({ ref: 'duration' }).vm.$emit('input', 'shortActivity'); - await wrapper.vm.$nextTick(); - expect(wrapper.find({ ref: 'activity_duration' }).exists()).toBe(true); - expect(wrapper.vm.showActivityDurationInput).toBe(true); - }); - it(`minutes input is displayed when 'Long activity' is selected`, async () => { - const wrapper = mount(CompletionOptions, { - propsData: { - kind: 'html5', - value: { - suggested_duration: null, - model: CompletionCriteriaModels.DETERMINED_BY_RESOURCE, - }, - }, - }); - wrapper.find({ ref: 'duration' }).vm.$emit('input', 'longActivity'); - await wrapper.vm.$nextTick(); - expect(wrapper.find({ ref: 'activity_duration' }).exists()).toBe(true); - expect(wrapper.vm.showActivityDurationInput).toBe(true); - }); - it(`minutes input is displayed when 'Exact time' is selected`, async () => { - const wrapper = mount(CompletionOptions, { - propsData: { - kind: 'html5', - value: { - suggested_duration: null, - model: CompletionCriteriaModels.DETERMINED_BY_RESOURCE, - }, - }, - }); - wrapper.find({ ref: 'duration' }).vm.$emit('input', 'exactTime'); - await wrapper.vm.$nextTick(); - expect(wrapper.find({ ref: 'activity_duration' }).exists()).toBe(true); - expect(wrapper.vm.showActivityDurationInput).toBe(true); + expect(wrapper.find({ ref: 'activity_duration' }).exists()).toBe(false); + expect(wrapper.find({ ref: 'duration' }).exists()).toBe(false); + expect(wrapper.vm.showActivityDurationInput).toBe(false); }); it(`minutes input is hidden and reference hint is displayed when 'Reference' is selected`, () => { const wrapper = mount(CompletionOptions, {