MOBILE-4616 feedback: Fix tab selection after submit form
This commit is contained in:
		
							parent
							
								
									ce7243b1ae
								
							
						
					
					
						commit
						95756b5c13
					
				| @ -20,20 +20,13 @@ | |||||||
|         [courseId]="courseId" [hasDataToSync]="hasOffline" (completionChanged)="onCompletionChange()" /> |         [courseId]="courseId" [hasDataToSync]="hasOffline" (completionChanged)="onCompletionChange()" /> | ||||||
| 
 | 
 | ||||||
|     <core-tabs [hideUntil]="tabsReady" [selectedIndex]="firstSelectedTab"> |     <core-tabs [hideUntil]="tabsReady" [selectedIndex]="firstSelectedTab"> | ||||||
|         <core-tab [title]="'addon.mod_feedback.overview' | translate" id="overview" (ionSelect)="tabChanged('overview')"> |         <core-tab [title]="tabs.overview.label | translate" [id]="tabs.overview.name" (ionSelect)="tabChanged(tabs.overview.name)"> | ||||||
|             <ng-template> |             <ng-template> | ||||||
|                 <ng-container *ngTemplateOutlet="tabOverview" /> |                 <ng-container *ngTemplateOutlet="tabOverview" /> | ||||||
|             </ng-template> |             </ng-template> | ||||||
|         </core-tab> |         </core-tab> | ||||||
|         <core-tab *ngIf="showAnalysis && access && access.canviewreports" id="analysis" [title]="'addon.mod_feedback.analysis' | translate" |         <core-tab *ngIf="showAnalysis && access" [id]="tabs.analysis.name" [title]="tabs.analysis.label | translate" | ||||||
|             (ionSelect)="tabChanged('analysis')"> |             (ionSelect)="tabChanged(tabs.analysis.name)"> | ||||||
|             <ng-template> |  | ||||||
|                 <ng-container *ngTemplateOutlet="tabAnalysis" /> |  | ||||||
|             </ng-template> |  | ||||||
|         </core-tab> |  | ||||||
| 
 |  | ||||||
|         <core-tab *ngIf="showAnalysis && access && !access.canviewreports" id="analysis" |  | ||||||
|             [title]="'addon.mod_feedback.completed_feedbacks' | translate" (ionSelect)="tabChanged('analysis')"> |  | ||||||
|             <ng-template> |             <ng-template> | ||||||
|                 <ng-container *ngTemplateOutlet="tabAnalysis" /> |                 <ng-container *ngTemplateOutlet="tabAnalysis" /> | ||||||
|             </ng-template> |             </ng-template> | ||||||
| @ -101,7 +94,7 @@ | |||||||
| 
 | 
 | ||||||
| <!-- Template to render the overview. --> | <!-- Template to render the overview. --> | ||||||
| <ng-template #tabOverview> | <ng-template #tabOverview> | ||||||
|     <core-loading [hideUntil]="tabsLoaded.overview"> |     <core-loading [hideUntil]="tabs.overview.loaded"> | ||||||
|         <ng-container *ngTemplateOutlet="basicInfo" /> |         <ng-container *ngTemplateOutlet="basicInfo" /> | ||||||
| 
 | 
 | ||||||
|         <ion-card class="core-info-card" *ngIf="access && access.cancomplete && !access.isopen"> |         <ion-card class="core-info-card" *ngIf="access && access.cancomplete && !access.isopen"> | ||||||
| @ -153,7 +146,7 @@ | |||||||
| 
 | 
 | ||||||
| <!-- Template to render the analysis. --> | <!-- Template to render the analysis. --> | ||||||
| <ng-template #tabAnalysis> | <ng-template #tabAnalysis> | ||||||
|     <core-loading [hideUntil]="tabsLoaded.analysis"> |     <core-loading [hideUntil]="tabs.analysis.loaded"> | ||||||
|         <ng-container *ngTemplateOutlet="basicInfo" /> |         <ng-container *ngTemplateOutlet="basicInfo" /> | ||||||
| 
 | 
 | ||||||
|         <ng-container *ngIf="access && (access.canedititems || !access.isempty)"> |         <ng-container *ngIf="access && (access.canedititems || !access.isempty)"> | ||||||
|  | |||||||
| @ -38,7 +38,12 @@ import { | |||||||
|     AddonModFeedbackSyncResult, |     AddonModFeedbackSyncResult, | ||||||
| } from '../../services/feedback-sync'; | } from '../../services/feedback-sync'; | ||||||
| import { AddonModFeedbackPrefetchHandler } from '../../services/handlers/prefetch'; | import { AddonModFeedbackPrefetchHandler } from '../../services/handlers/prefetch'; | ||||||
| import { ADDON_MOD_FEEDBACK_COMPONENT, ADDON_MOD_FEEDBACK_FORM_SUBMITTED, ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants'; | import { | ||||||
|  |     ADDON_MOD_FEEDBACK_COMPONENT, | ||||||
|  |     ADDON_MOD_FEEDBACK_FORM_SUBMITTED, | ||||||
|  |     ADDON_MOD_FEEDBACK_PAGE_NAME, | ||||||
|  |     AddonModFeedbackIndexTabName, | ||||||
|  | } from '../../constants'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Component that displays a feedback index page. |  * Component that displays a feedback index page. | ||||||
| @ -51,7 +56,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
| 
 | 
 | ||||||
|     @ViewChild(CoreTabsComponent) tabsComponent?: CoreTabsComponent; |     @ViewChild(CoreTabsComponent) tabsComponent?: CoreTabsComponent; | ||||||
| 
 | 
 | ||||||
|     @Input() tab = 'overview'; |     @Input() selectedTab: AddonModFeedbackIndexTabName = AddonModFeedbackIndexTabName.OVERVIEW; | ||||||
|     @Input() group = 0; |     @Input() group = 0; | ||||||
| 
 | 
 | ||||||
|     component = ADDON_MOD_FEEDBACK_COMPONENT; |     component = ADDON_MOD_FEEDBACK_COMPONENT; | ||||||
| @ -75,9 +80,9 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|         closeTimeReadable: '', |         closeTimeReadable: '', | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     tabsLoaded = { |     tabs = { | ||||||
|         overview: false, |         overview: { name: AddonModFeedbackIndexTabName.OVERVIEW, label: 'addon.mod_feedback.overview', loaded: false }, | ||||||
|         analysis: false, |         analysis: { name: AddonModFeedbackIndexTabName.ANALYSIS, label: 'addon.mod_feedback.analysis', loaded: false }, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     protected submitObserver: CoreEventObserver; |     protected submitObserver: CoreEventObserver; | ||||||
| @ -92,12 +97,12 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
| 
 | 
 | ||||||
|         // Listen for form submit events.
 |         // Listen for form submit events.
 | ||||||
|         this.submitObserver = CoreEvents.on(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, async (data) => { |         this.submitObserver = CoreEvents.on(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, async (data) => { | ||||||
|             if (!this.feedback || data.feedbackId != this.feedback.id) { |             if (!this.feedback || data.feedbackId !== this.feedback.id) { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             this.tabsLoaded.analysis = false; |             this.tabs.analysis.loaded = false; | ||||||
|             this.tabsLoaded.overview = false; |             this.tabs.overview.loaded = false; | ||||||
|             this.showLoading = true; |             this.showLoading = true; | ||||||
| 
 | 
 | ||||||
|             // Prefetch data if needed.
 |             // Prefetch data if needed.
 | ||||||
| @ -110,7 +115,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Load the right tab.
 |             // Load the right tab.
 | ||||||
|             if (data.tab != this.tab) { |             if (data.tab !== this.selectedTab) { | ||||||
|                 this.tabChanged(data.tab); |                 this.tabChanged(data.tab); | ||||||
|             } else { |             } else { | ||||||
|                 this.loadContent(true); |                 this.loadContent(true); | ||||||
| @ -149,7 +154,9 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      */ |      */ | ||||||
|     protected callAnalyticsLogEvent(): void { |     protected callAnalyticsLogEvent(): void { | ||||||
|         this.analyticsLogEvent('mod_feedback_view_feedback', { |         this.analyticsLogEvent('mod_feedback_view_feedback', { | ||||||
|             url: this.tab === 'analysis' ? `/mod/feedback/analysis.php?id=${this.module.id}` : undefined, |             url: this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS | ||||||
|  |                 ? `/mod/feedback/analysis.php?id=${this.module.id}` | ||||||
|  |                 : undefined, | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -168,8 +175,8 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|             promises.push(AddonModFeedback.invalidateResumePageData(this.feedback.id)); |             promises.push(AddonModFeedback.invalidateResumePageData(this.feedback.id)); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.tabsLoaded.analysis = false; |         this.tabs.analysis.loaded = false; | ||||||
|         this.tabsLoaded.overview = false; |         this.tabs.overview.loaded = false; | ||||||
| 
 | 
 | ||||||
|         await Promise.all(promises); |         await Promise.all(promises); | ||||||
|     } |     } | ||||||
| @ -178,7 +185,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      * @inheritdoc |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     protected isRefreshSyncNeeded(syncEventData: AddonModFeedbackAutoSyncData): boolean { |     protected isRefreshSyncNeeded(syncEventData: AddonModFeedbackAutoSyncData): boolean { | ||||||
|         if (this.feedback && syncEventData.feedbackId == this.feedback.id) { |         if (syncEventData.feedbackId === this.feedback?.id) { | ||||||
|             // Refresh the data.
 |             // Refresh the data.
 | ||||||
|             this.content?.scrollToTop(); |             this.content?.scrollToTop(); | ||||||
| 
 | 
 | ||||||
| @ -207,12 +214,17 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, { cmId: this.module.id }); |             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, { cmId: this.module.id }); | ||||||
| 
 | 
 | ||||||
|             this.showAnalysis = (this.access.canviewreports || this.access.canviewanalysis) && !this.access.isempty; |             this.showAnalysis = (this.access.canviewreports || this.access.canviewanalysis) && !this.access.isempty; | ||||||
|  | 
 | ||||||
|  |             this.tabs.analysis.label = this.access.canviewreports | ||||||
|  |                 ? 'addon.mod_feedback.analysis' | ||||||
|  |                 : 'addon.mod_feedback.completed_feedbacks'; | ||||||
|  | 
 | ||||||
|             this.firstSelectedTab = 0; |             this.firstSelectedTab = 0; | ||||||
|             if (!this.showAnalysis) { |             if (!this.showAnalysis) { | ||||||
|                 this.tab = 'overview'; |                 this.selectedTab = AddonModFeedbackIndexTabName.OVERVIEW; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (this.tab == 'analysis') { |             if (this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS) { | ||||||
|                 this.firstSelectedTab = 1; |                 this.firstSelectedTab = 1; | ||||||
| 
 | 
 | ||||||
|                 return await this.fetchFeedbackAnalysisData(); |                 return await this.fetchFeedbackAnalysisData(); | ||||||
| @ -227,34 +239,36 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
| 
 | 
 | ||||||
|             if (this.tabsReady) { |             if (this.tabsReady) { | ||||||
|                 // Make sure the right tab is selected.
 |                 // Make sure the right tab is selected.
 | ||||||
|                 this.tabsComponent?.selectTab(this.tab || 'overview'); |                 this.tabsComponent?.selectTab(this.selectedTab ?? AddonModFeedbackIndexTabName.OVERVIEW); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Convenience function to get feedback overview data. |      * Convenience function to get feedback overview data. | ||||||
|      * |  | ||||||
|      * @returns Resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     protected async fetchFeedbackOverviewData(): Promise<void> { |     protected async fetchFeedbackOverviewData(): Promise<void> { | ||||||
|  |         if (!this.access || !this.feedback) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         const promises: Promise<void>[] = []; |         const promises: Promise<void>[] = []; | ||||||
| 
 | 
 | ||||||
|         if (this.access!.cancomplete && this.access!.cansubmit && this.access!.isopen) { |         if (this.access.cancomplete && this.access.cansubmit && this.access.isopen) { | ||||||
|             promises.push(AddonModFeedback.getResumePage(this.feedback!.id, { cmId: this.module.id }).then((goPage) => { |             promises.push(AddonModFeedback.getResumePage(this.feedback.id, { cmId: this.module.id }).then((goPage) => { | ||||||
|                 this.goPage = goPage > 0 ? goPage : undefined; |                 this.goPage = goPage > 0 ? goPage : undefined; | ||||||
| 
 | 
 | ||||||
|                 return; |                 return; | ||||||
|             })); |             })); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (this.access!.canedititems) { |         if (this.access.canedititems) { | ||||||
|             this.overview.timeopen = (this.feedback!.timeopen || 0) * 1000; |             this.overview.timeopen = (this.feedback.timeopen || 0) * 1000; | ||||||
|             this.overview.openTimeReadable = this.overview.timeopen ? CoreTimeUtils.userDate(this.overview.timeopen) : ''; |             this.overview.openTimeReadable = this.overview.timeopen ? CoreTimeUtils.userDate(this.overview.timeopen) : ''; | ||||||
|             this.overview.timeclose = (this.feedback!.timeclose || 0) * 1000; |             this.overview.timeclose = (this.feedback.timeclose || 0) * 1000; | ||||||
|             this.overview.closeTimeReadable = this.overview.timeclose ? CoreTimeUtils.userDate(this.overview.timeclose) : ''; |             this.overview.closeTimeReadable = this.overview.timeclose ? CoreTimeUtils.userDate(this.overview.timeclose) : ''; | ||||||
|         } |         } | ||||||
|         if (this.access!.canviewanalysis) { |         if (this.access.canviewanalysis) { | ||||||
|             // Get groups (only for teachers).
 |             // Get groups (only for teachers).
 | ||||||
|             promises.push(this.fetchGroupInfo(this.module.id)); |             promises.push(this.fetchGroupInfo(this.module.id)); | ||||||
|         } |         } | ||||||
| @ -262,7 +276,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|         try { |         try { | ||||||
|             await Promise.all(promises); |             await Promise.all(promises); | ||||||
|         } finally { |         } finally { | ||||||
|             this.tabsLoaded.overview = true; |             this.tabs.overview.loaded = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -273,15 +287,14 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      */ |      */ | ||||||
|     protected async fetchFeedbackAnalysisData(): Promise<void> { |     protected async fetchFeedbackAnalysisData(): Promise<void> { | ||||||
|         try { |         try { | ||||||
|             if (this.access!.canviewanalysis) { |             if (this.access?.canviewanalysis) { | ||||||
|                 // Get groups (only for teachers).
 |                 // Get groups (only for teachers).
 | ||||||
|                 await this.fetchGroupInfo(this.module.id); |                 await this.fetchGroupInfo(this.module.id); | ||||||
|             } else { |             } else { | ||||||
|                 this.tabChanged('overview'); |                 this.tabChanged(AddonModFeedbackIndexTabName.OVERVIEW); | ||||||
|             } |             } | ||||||
| 
 |  | ||||||
|         } finally { |         } finally { | ||||||
|             this.tabsLoaded.analysis = true; |             this.tabs.analysis.loaded = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -419,7 +432,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      * Open attempts page. |      * Open attempts page. | ||||||
|      */ |      */ | ||||||
|     openAttempts(): void { |     openAttempts(): void { | ||||||
|         if (!this.access!.canviewreports || this.completedCount <= 0) { |         if (!this.access || !this.access.canviewreports || this.completedCount <= 0) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -438,11 +451,11 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      * |      * | ||||||
|      * @param tabName New tab name. |      * @param tabName New tab name. | ||||||
|      */ |      */ | ||||||
|     tabChanged(tabName: string): void { |     tabChanged(tabName: AddonModFeedbackIndexTabName): void { | ||||||
|         const tabHasChanged = this.tab !== undefined && this.tab !== tabName; |         const tabHasChanged = this.selectedTab !== undefined && this.selectedTab !== tabName; | ||||||
|         this.tab = tabName; |         this.selectedTab = tabName; | ||||||
| 
 | 
 | ||||||
|         if (!this.tabsLoaded[this.tab]) { |         if (!this.tabs[this.selectedTab].loaded) { | ||||||
|             this.loadContent(false, false, true); |             this.loadContent(false, false, true); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -455,17 +468,20 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|      * Set group to see the analysis. |      * Set group to see the analysis. | ||||||
|      * |      * | ||||||
|      * @param groupId Group ID. |      * @param groupId Group ID. | ||||||
|      * @returns Resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     async setGroup(groupId: number): Promise<void> { |     async setGroup(groupId: number): Promise<void> { | ||||||
|  |         if (!this.feedback) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         this.group = groupId; |         this.group = groupId; | ||||||
| 
 | 
 | ||||||
|         const analysis = await AddonModFeedback.getAnalysis(this.feedback!.id, { groupId, cmId: this.module.id }); |         const analysis = await AddonModFeedback.getAnalysis(this.feedback.id, { groupId, cmId: this.module.id }); | ||||||
| 
 | 
 | ||||||
|         this.completedCount = analysis.completedcount; |         this.completedCount = analysis.completedcount; | ||||||
|         this.itemsCount = analysis.itemscount; |         this.itemsCount = analysis.itemscount; | ||||||
| 
 | 
 | ||||||
|         if (this.tab == 'analysis') { |         if (this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS) { | ||||||
|             let num = 1; |             let num = 1; | ||||||
| 
 | 
 | ||||||
|             this.items = <AddonModFeedbackItem[]> analysis.itemsdata.map((itemData) => { |             this.items = <AddonModFeedbackItem[]> analysis.itemsdata.map((itemData) => { | ||||||
|  | |||||||
| @ -24,3 +24,11 @@ export const ADDON_MOD_FEEDBACK_MULTICHOICE_HIDENOSELECT = 'h'; | |||||||
| export const ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP = '####'; | export const ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP = '####'; | ||||||
| 
 | 
 | ||||||
| export const ADDON_MOD_FEEDBACK_PER_PAGE = 20; | export const ADDON_MOD_FEEDBACK_PER_PAGE = 20; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Index Tabs. | ||||||
|  |  */ | ||||||
|  | export enum AddonModFeedbackIndexTabName { | ||||||
|  |     OVERVIEW = 'overview', | ||||||
|  |     ANALYSIS = 'analysis', | ||||||
|  | } | ||||||
|  | |||||||
| @ -36,8 +36,14 @@ import { | |||||||
| import { AddonModFeedbackFormItem, AddonModFeedbackHelper } from '../../services/feedback-helper'; | import { AddonModFeedbackFormItem, AddonModFeedbackHelper } from '../../services/feedback-helper'; | ||||||
| import { AddonModFeedbackSync } from '../../services/feedback-sync'; | import { AddonModFeedbackSync } from '../../services/feedback-sync'; | ||||||
| import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; | import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; | ||||||
| import { ADDON_MOD_FEEDBACK_COMPONENT, ADDON_MOD_FEEDBACK_FORM_SUBMITTED, ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants'; | import { | ||||||
|  |     ADDON_MOD_FEEDBACK_COMPONENT, | ||||||
|  |     ADDON_MOD_FEEDBACK_FORM_SUBMITTED, | ||||||
|  |     ADDON_MOD_FEEDBACK_PAGE_NAME, | ||||||
|  |     AddonModFeedbackIndexTabName, | ||||||
|  | } from '../../constants'; | ||||||
| import { CoreLoadings } from '@services/loadings'; | import { CoreLoadings } from '@services/loadings'; | ||||||
|  | import { CoreError } from '@classes/errors/error'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page that displays feedback form. |  * Page that displays feedback form. | ||||||
| @ -117,14 +123,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (!this.feedback) { |         if (!this.feedback || !this.module) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             await AddonModFeedback.logView(this.feedback.id, true); |             await AddonModFeedback.logView(this.feedback.id, true); | ||||||
| 
 | 
 | ||||||
|             CoreCourse.checkModuleCompletion(this.courseId, this.module!.completiondata); |             CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); | ||||||
|         } catch { |         } catch { | ||||||
|             // Ignore errors.
 |             // Ignore errors.
 | ||||||
|         } |         } | ||||||
| @ -183,7 +189,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
| 
 | 
 | ||||||
|             let page = 0; |             let page = 0; | ||||||
| 
 | 
 | ||||||
|             if (!this.preview && this.access!.cansubmit && !this.access!.isempty) { |             if (!this.preview && this.access?.cansubmit && !this.access?.isempty) { | ||||||
|                 page = this.currentPage ?? await this.fetchResumePage(options); |                 page = this.currentPage ?? await this.fetchResumePage(options); | ||||||
|             } else { |             } else { | ||||||
|                 this.preview = true; |                 this.preview = true; | ||||||
| @ -203,11 +209,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * Fetch access information. |      * Fetch access information. | ||||||
|      * |      * | ||||||
|      * @param options Options. |      * @param options Options. | ||||||
|      * @returns Promise resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     protected async fetchAccessData(options: CoreCourseCommonModWSOptions): Promise<void> { |     protected async fetchAccessData(options: CoreCourseCommonModWSOptions): Promise<void> { | ||||||
|  |         if (!this.feedback) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         try { |         try { | ||||||
|             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback!.id, options); |             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, options); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             if (this.offline || CoreUtils.isWebServiceError(error)) { |             if (this.offline || CoreUtils.isWebServiceError(error)) { | ||||||
|                 // Already offline or shouldn't go offline, fail.
 |                 // Already offline or shouldn't go offline, fail.
 | ||||||
| @ -218,7 +227,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|             this.offline = true; |             this.offline = true; | ||||||
|             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; |             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; | ||||||
| 
 | 
 | ||||||
|             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback!.id, options); |             this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, options); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -229,8 +238,12 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * @returns Promise resolved with the page to resume. |      * @returns Promise resolved with the page to resume. | ||||||
|      */ |      */ | ||||||
|     protected async fetchResumePage(options: CoreCourseCommonModWSOptions): Promise<number> { |     protected async fetchResumePage(options: CoreCourseCommonModWSOptions): Promise<number> { | ||||||
|  |         if (!this.feedback) { | ||||||
|  |             throw new CoreError('Cannot fetch resume page: missing feedback'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         try { |         try { | ||||||
|             return await AddonModFeedback.getResumePage(this.feedback!.id, options); |             return await AddonModFeedback.getResumePage(this.feedback.id, options); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             if (this.offline || CoreUtils.isWebServiceError(error)) { |             if (this.offline || CoreUtils.isWebServiceError(error)) { | ||||||
|                 // Already offline or shouldn't go offline, fail.
 |                 // Already offline or shouldn't go offline, fail.
 | ||||||
| @ -241,7 +254,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|             this.offline = true; |             this.offline = true; | ||||||
|             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; |             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; | ||||||
| 
 | 
 | ||||||
|             return AddonModFeedback.getResumePage(this.feedback!.id, options); |             return AddonModFeedback.getResumePage(this.feedback.id, options); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -249,7 +262,6 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * Fetch page data. |      * Fetch page data. | ||||||
|      * |      * | ||||||
|      * @param page Page to load. |      * @param page Page to load. | ||||||
|      * @returns Promise resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     protected async fetchFeedbackPageData(page: number = 0): Promise<void> { |     protected async fetchFeedbackPageData(page: number = 0): Promise<void> { | ||||||
|         this.items = []; |         this.items = []; | ||||||
| @ -274,6 +286,10 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * @returns Promise resolved with WS response. |      * @returns Promise resolved with WS response. | ||||||
|      */ |      */ | ||||||
|     protected async fetchPageItems(page: number): Promise<AddonModFeedbackPageItems> { |     protected async fetchPageItems(page: number): Promise<AddonModFeedbackPageItems> { | ||||||
|  |         if (!this.feedback) { | ||||||
|  |             throw new CoreError('Cannot fetch page items: missing feedback'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         const options = { |         const options = { | ||||||
|             cmId: this.cmId, |             cmId: this.cmId, | ||||||
|             readingStrategy: this.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK, |             readingStrategy: this.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK, | ||||||
| @ -281,7 +297,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         if (this.preview) { |         if (this.preview) { | ||||||
|             const response = await AddonModFeedback.getItems(this.feedback!.id, options); |             const response = await AddonModFeedback.getItems(this.feedback.id, options); | ||||||
| 
 | 
 | ||||||
|             return { |             return { | ||||||
|                 items: response.items, |                 items: response.items, | ||||||
| @ -295,7 +311,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|         let response: AddonModFeedbackPageItems; |         let response: AddonModFeedbackPageItems; | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             response = await AddonModFeedback.getPageItemsWithValues(this.feedback!.id, page, options); |             response = await AddonModFeedback.getPageItemsWithValues(this.feedback.id, page, options); | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             if (this.offline || CoreUtils.isWebServiceError(error)) { |             if (this.offline || CoreUtils.isWebServiceError(error)) { | ||||||
|                 // Already offline or shouldn't go offline, fail.
 |                 // Already offline or shouldn't go offline, fail.
 | ||||||
| @ -306,7 +322,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|             this.offline = true; |             this.offline = true; | ||||||
|             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; |             options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE; | ||||||
| 
 | 
 | ||||||
|             response = await AddonModFeedback.getPageItemsWithValues(this.feedback!.id, page, options); |             response = await AddonModFeedback.getPageItemsWithValues(this.feedback.id, page, options); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.hasPrevPage = !!response.hasprevpage; |         this.hasPrevPage = !!response.hasprevpage; | ||||||
| @ -319,9 +335,12 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * Function to allow page navigation through the questions form. |      * Function to allow page navigation through the questions form. | ||||||
|      * |      * | ||||||
|      * @param goPrevious If true it will go back to the previous page, if false, it will go forward. |      * @param goPrevious If true it will go back to the previous page, if false, it will go forward. | ||||||
|      * @returns Resolved when done. |  | ||||||
|      */ |      */ | ||||||
|     async gotoPage(goPrevious: boolean): Promise<void> { |     async gotoPage(goPrevious: boolean): Promise<void> { | ||||||
|  |         if (!this.feedback || this.currentPage === undefined) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         this.content?.scrollToTop(); |         this.content?.scrollToTop(); | ||||||
|         this.feedbackLoaded = false; |         this.feedbackLoaded = false; | ||||||
| 
 | 
 | ||||||
| @ -330,9 +349,9 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             // Sync other pages first.
 |             // Sync other pages first.
 | ||||||
|             await CoreUtils.ignoreErrors(AddonModFeedbackSync.syncFeedback(this.feedback!.id)); |             await CoreUtils.ignoreErrors(AddonModFeedbackSync.syncFeedback(this.feedback.id)); | ||||||
| 
 | 
 | ||||||
|             const response = await AddonModFeedback.processPage(this.feedback!.id, this.currentPage!, responses, { |             const response = await AddonModFeedback.processPage(this.feedback.id, this.currentPage, responses, { | ||||||
|                 goPrevious, |                 goPrevious, | ||||||
|                 formHasErrors, |                 formHasErrors, | ||||||
|                 courseId: this.courseId, |                 courseId: this.courseId, | ||||||
| @ -351,14 +370,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
| 
 | 
 | ||||||
|                 // Invalidate access information so user will see home page updated (continue form or completion messages).
 |                 // Invalidate access information so user will see home page updated (continue form or completion messages).
 | ||||||
|                 await Promise.all([ |                 await Promise.all([ | ||||||
|                     AddonModFeedback.invalidateFeedbackAccessInformationData(this.feedback!.id), |                     AddonModFeedback.invalidateFeedbackAccessInformationData(this.feedback.id), | ||||||
|                     AddonModFeedback.invalidateResumePageData(this.feedback!.id), |                     AddonModFeedback.invalidateResumePageData(this.feedback.id), | ||||||
|                 ]); |                 ]); | ||||||
| 
 | 
 | ||||||
|                 // If form has been submitted, the info has been already invalidated but we should update index view.
 |                 // If form has been submitted, the info has been already invalidated but we should update index view.
 | ||||||
|                 CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { |                 CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { | ||||||
|                     feedbackId: this.feedback!.id, |                     feedbackId: this.feedback.id, | ||||||
|                     tab: 'overview', |                     tab: AddonModFeedbackIndexTabName.OVERVIEW, | ||||||
|                     offline: this.completedOffline, |                     offline: this.completedOffline, | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
| @ -371,11 +390,11 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|                 // Errors on questions, stay in page.
 |                 // Errors on questions, stay in page.
 | ||||||
|             } else { |             } else { | ||||||
|                 // Invalidate access information so user will see home page updated (continue form).
 |                 // Invalidate access information so user will see home page updated (continue form).
 | ||||||
|                 await AddonModFeedback.invalidateResumePageData(this.feedback!.id); |                 await AddonModFeedback.invalidateResumePageData(this.feedback.id); | ||||||
| 
 | 
 | ||||||
|                 CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { |                 CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { | ||||||
|                     feedbackId: this.feedback!.id, |                     feedbackId: this.feedback.id, | ||||||
|                     tab: 'overview', |                     tab: AddonModFeedbackIndexTabName.OVERVIEW, | ||||||
|                     offline: this.completedOffline, |                     offline: this.completedOffline, | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
| @ -393,11 +412,15 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|      * Function to link implemented features. |      * Function to link implemented features. | ||||||
|      */ |      */ | ||||||
|     showAnalysis(): void { |     showAnalysis(): void { | ||||||
|  |         if (!this.feedback) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (this.fromIndex) { |         if (this.fromIndex) { | ||||||
|             // Previous page is the index page, go back.
 |             // Previous page is the index page, go back.
 | ||||||
|             CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { |             CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, { | ||||||
|                 feedbackId: this.feedback!.id, |                 feedbackId: this.feedback.id, | ||||||
|                 tab: 'analysis', |                 tab: AddonModFeedbackIndexTabName.ANALYSIS, | ||||||
|                 offline: this.completedOffline, |                 offline: this.completedOffline, | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
| @ -409,7 +432,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave { | |||||||
|         CoreNavigator.navigateToSitePath(ADDON_MOD_FEEDBACK_PAGE_NAME + `/${this.courseId}/${this.cmId}`, { |         CoreNavigator.navigateToSitePath(ADDON_MOD_FEEDBACK_PAGE_NAME + `/${this.courseId}/${this.cmId}`, { | ||||||
|             params: { |             params: { | ||||||
|                 module: this.module, |                 module: this.module, | ||||||
|                 tab: 'analysis', |                 tab: AddonModFeedbackIndexTabName.ANALYSIS, | ||||||
|             }, |             }, | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -16,6 +16,6 @@ | |||||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" /> |         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" /> | ||||||
|     </ion-refresher> |     </ion-refresher> | ||||||
| 
 | 
 | ||||||
|     <addon-mod-feedback-index [module]="module" [courseId]="courseId" [group]="selectedGroup" [tab]="selectedTab" |     <addon-mod-feedback-index [module]="module" [courseId]="courseId" [group]="selectedGroup" [selectedTab]="selectedTab" | ||||||
|         (dataRetrieved)="updateData($event)" /> |         (dataRetrieved)="updateData($event)" /> | ||||||
| </ion-content> | </ion-content> | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import { Component, OnInit, ViewChild } from '@angular/core'; | |||||||
| import { CoreCourseModuleMainActivityPage } from '@features/course/classes/main-activity-page'; | import { CoreCourseModuleMainActivityPage } from '@features/course/classes/main-activity-page'; | ||||||
| import { CoreNavigator } from '@services/navigator'; | import { CoreNavigator } from '@services/navigator'; | ||||||
| import { AddonModFeedbackIndexComponent } from '../../components/index/index'; | import { AddonModFeedbackIndexComponent } from '../../components/index/index'; | ||||||
|  | import { AddonModFeedbackIndexTabName } from '../../constants'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Page that displays a feedback. |  * Page that displays a feedback. | ||||||
| @ -28,7 +29,7 @@ export class AddonModFeedbackIndexPage extends CoreCourseModuleMainActivityPage< | |||||||
| 
 | 
 | ||||||
|     @ViewChild(AddonModFeedbackIndexComponent) activityComponent?: AddonModFeedbackIndexComponent; |     @ViewChild(AddonModFeedbackIndexComponent) activityComponent?: AddonModFeedbackIndexComponent; | ||||||
| 
 | 
 | ||||||
|     selectedTab?: string; |     selectedTab?: AddonModFeedbackIndexTabName; | ||||||
|     selectedGroup?: number; |     selectedGroup?: number; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -34,6 +34,7 @@ import { | |||||||
|     ADDON_MOD_FEEDBACK_MULTICHOICE_TYPE_SEP, |     ADDON_MOD_FEEDBACK_MULTICHOICE_TYPE_SEP, | ||||||
|     ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP, |     ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP, | ||||||
|     ADDON_MOD_FEEDBACK_PER_PAGE, |     ADDON_MOD_FEEDBACK_PER_PAGE, | ||||||
|  |     AddonModFeedbackIndexTabName, | ||||||
| } from '../constants'; | } from '../constants'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -1263,7 +1264,7 @@ declare module '@singletons/events' { | |||||||
|  */ |  */ | ||||||
| export type AddonModFeedbackFormSubmittedData = { | export type AddonModFeedbackFormSubmittedData = { | ||||||
|     feedbackId: number; |     feedbackId: number; | ||||||
|     tab: string; |     tab: AddonModFeedbackIndexTabName; | ||||||
|     offline: boolean; |     offline: boolean; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -19,7 +19,7 @@ import { CoreCourse } from '@features/course/services/course'; | |||||||
| import { CoreNavigator } from '@services/navigator'; | import { CoreNavigator } from '@services/navigator'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
| import { makeSingleton } from '@singletons'; | import { makeSingleton } from '@singletons'; | ||||||
| import { ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants'; | import { ADDON_MOD_FEEDBACK_PAGE_NAME, AddonModFeedbackIndexTabName } from '../../constants'; | ||||||
| import { CoreLoadings } from '@services/loadings'; | import { CoreLoadings } from '@services/loadings'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -59,7 +59,7 @@ export class AddonModFeedbackAnalysisLinkHandlerService extends CoreContentLinks | |||||||
|                         { |                         { | ||||||
|                             params: { |                             params: { | ||||||
|                                 module, |                                 module, | ||||||
|                                 tab: 'analysis', |                                 tab: AddonModFeedbackIndexTabName.ANALYSIS, | ||||||
|                             }, |                             }, | ||||||
|                             siteId, |                             siteId, | ||||||
|                         }, |                         }, | ||||||
|  | |||||||
| @ -221,7 +221,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn | |||||||
|         this.swiper.update(); |         this.swiper.update(); | ||||||
|         await CoreWait.nextTick(); |         await CoreWait.nextTick(); | ||||||
| 
 | 
 | ||||||
|         if (!this.hasSliddenToInitial && this.selectedIndex && this.selectedIndex >= this.swiper.slidesPerViewDynamic()) { |         if (!this.hasSliddenToInitial && this.selectedIndex >= this.swiper.slidesPerViewDynamic()) { | ||||||
|             this.hasSliddenToInitial = true; |             this.hasSliddenToInitial = true; | ||||||
|             this.shouldSlideToInitial = true; |             this.shouldSlideToInitial = true; | ||||||
| 
 | 
 | ||||||
| @ -233,7 +233,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn | |||||||
|             }, 400); |             }, 400); | ||||||
| 
 | 
 | ||||||
|             return; |             return; | ||||||
|         } else if (this.selectedIndex) { |         } else { | ||||||
|             this.hasSliddenToInitial = true; |             this.hasSliddenToInitial = true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -301,21 +301,21 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn | |||||||
|      * @returns Initial tab, undefined if no valid tab found. |      * @returns Initial tab, undefined if no valid tab found. | ||||||
|      */ |      */ | ||||||
|     protected calculateInitialTab(): T | undefined { |     protected calculateInitialTab(): T | undefined { | ||||||
|         const selectedTab: T | undefined = this.tabs[this.selectedIndex || 0] || undefined; |         const selectedTab: T | undefined = this.tabs[this.selectedIndex] || undefined; | ||||||
| 
 | 
 | ||||||
|         if (selectedTab && selectedTab.enabled) { |         if (selectedTab?.enabled) { | ||||||
|             return selectedTab; |             return selectedTab; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // The tab is not enabled or not shown. Get the first tab that is enabled.
 |         // The tab is not enabled or not shown. Get the first tab that is enabled.
 | ||||||
|         return this.tabs.find((tab) => tab.enabled) || undefined; |         return this.tabs.find((tab) => tab.enabled); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Method executed when the slides are changed. |      * Method executed when the slides are changed. | ||||||
|      */ |      */ | ||||||
|     slideChanged(): void { |     slideChanged(): void { | ||||||
|         if (!this.swiper) { |         if (!this.swiper || this.swiper.destroyed) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -340,7 +340,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn | |||||||
|      * Calculate the number of slides that can fit on the screen. |      * Calculate the number of slides that can fit on the screen. | ||||||
|      */ |      */ | ||||||
|     protected async calculateMaxSlides(): Promise<void> { |     protected async calculateMaxSlides(): Promise<void> { | ||||||
|         if (!this.swiper) { |         if (!this.swiper || this.swiper.destroyed) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -456,7 +456,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (this.selected && this.swiper) { |         if (this.selected && this.swiper && !this.swiper.destroyed) { | ||||||
|             // Check if we need to slide to the tab because it's not visible.
 |             // Check if we need to slide to the tab because it's not visible.
 | ||||||
|             const firstVisibleTab = this.swiper.activeIndex; |             const firstVisibleTab = this.swiper.activeIndex; | ||||||
|             const lastVisibleTab = firstVisibleTab + this.swiper.slidesPerViewDynamic() - 1; |             const lastVisibleTab = firstVisibleTab + this.swiper.slidesPerViewDynamic() - 1; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user