Merge pull request #1760 from albertgasset/MOBILE-2188
MOBILE-2188 data: Don't fetch all entries when browsing entry by entry
This commit is contained in:
		
						commit
						575285077f
					
				| @ -30,6 +30,7 @@ export class AddonModDataActionComponent implements OnInit { | ||||
|     @Input() action: string; // The field to render.
 | ||||
|     @Input() entry?: any; // The value of the field.
 | ||||
|     @Input() database: any; // Database object.
 | ||||
|     @Input() offset?: number; // Offset of the entry.
 | ||||
| 
 | ||||
|     siteId: string; | ||||
|     rootUrl: string; | ||||
| @ -67,6 +68,9 @@ export class AddonModDataActionComponent implements OnInit { | ||||
|         switch (this.action) { | ||||
|             case 'more': | ||||
|                 this.url = this.rootUrl + '/mod/data/view.php?d= ' + this.entry.dataid + '&rid=' + this.entry.id; | ||||
|                 if (typeof this.offset == 'number') { | ||||
|                     this.url += '&mode=single&page=' + this.offset; | ||||
|                 } | ||||
|                 break; | ||||
|             case 'edit': | ||||
|                 this.url = this.rootUrl + '/mod/data/edit.php?d= ' + this.entry.dataid + '&rid=' + this.entry.id; | ||||
|  | ||||
| @ -47,7 +47,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|     timeAvailableToReadable: string | boolean; | ||||
|     isEmpty = false; | ||||
|     groupInfo: CoreGroupInfo; | ||||
|     entries = {}; | ||||
|     entries = []; | ||||
|     firstEntry = false; | ||||
|     canAdd = false; | ||||
|     canSearch = false; | ||||
| @ -317,6 +317,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|                 }); | ||||
| 
 | ||||
|                 return Promise.all(promises).then((entries) => { | ||||
|                     this.entries = entries; | ||||
| 
 | ||||
|                     let entriesHTML = this.data.listtemplateheader || ''; | ||||
| 
 | ||||
|                     // Get first entry from the whole list.
 | ||||
| @ -326,12 +328,15 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
| 
 | ||||
|                     const template = this.data.listtemplate || this.dataHelper.getDefaultTemplate('list', this.fieldsArray); | ||||
| 
 | ||||
|                     entries.forEach((entry) => { | ||||
|                         this.entries[entry.id] = entry; | ||||
|                     const entriesById = {}; | ||||
|                     entries.forEach((entry, index) => { | ||||
|                         entriesById[entry.id] = entry; | ||||
| 
 | ||||
|                         const actions = this.dataHelper.getActions(this.data, this.access, entry); | ||||
|                         const offset = this.search.page * AddonModDataProvider.PER_PAGE + index; | ||||
| 
 | ||||
|                         entriesHTML += this.dataHelper.displayShowFields(template, this.fieldsArray, entry, 'list', actions); | ||||
|                         entriesHTML += this.dataHelper.displayShowFields(template, this.fieldsArray, entry, offset, 'list', | ||||
|                                 actions); | ||||
|                     }); | ||||
|                     entriesHTML += this.data.listtemplatefooter || ''; | ||||
| 
 | ||||
| @ -340,7 +345,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|                     // Pass the input data to the component.
 | ||||
|                     this.jsData = { | ||||
|                         fields: this.fields, | ||||
|                         entries: this.entries, | ||||
|                         entries: entriesById, | ||||
|                         data: this.data, | ||||
|                         gotoEntry: this.gotoEntry.bind(this) | ||||
|                     }; | ||||
| @ -440,9 +445,16 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|             module: this.module, | ||||
|             courseId: this.courseId, | ||||
|             entryId: entryId, | ||||
|             group: this.selectedGroup | ||||
|             group: this.selectedGroup, | ||||
|             offset: null | ||||
|         }; | ||||
| 
 | ||||
|         // Try to find page number and offset of the entry.
 | ||||
|         const pageXOffset = this.entries.findIndex((entry) => entry.id == entryId); | ||||
|         if (pageXOffset >= 0) { | ||||
|             params.offset = this.search.page * AddonModDataProvider.PER_PAGE + pageXOffset; | ||||
|         } | ||||
| 
 | ||||
|         this.navCtrl.push('AddonModDataEntryPage', params); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -34,16 +34,16 @@ | ||||
|             <core-comments contextLevel="module" [instanceId]="data.coursemodule" component="mod_data" [itemId]="entry.id" area="database_entry"></core-comments> | ||||
|         </ion-item> | ||||
| 
 | ||||
|         <ion-grid *ngIf="previousId || nextId"> | ||||
|         <ion-grid *ngIf="previousOffset != null || nextOffset != null"> | ||||
|             <ion-row align-items-center> | ||||
|                 <ion-col *ngIf="previousId"> | ||||
|                     <button ion-button block outline icon-start (click)="gotoEntry(previousId)"> | ||||
|                 <ion-col *ngIf="previousOffset != null"> | ||||
|                     <button ion-button block outline icon-start (click)="gotoEntry(previousOffset)"> | ||||
|                         <ion-icon name="arrow-back" md="ios-arrow-back"></ion-icon> | ||||
|                         {{ 'core.previous' | translate }} | ||||
|                     </button> | ||||
|                 </ion-col> | ||||
|                 <ion-col *ngIf="nextId"> | ||||
|                     <button ion-button block icon-end (click)="gotoEntry(nextId)"> | ||||
|                 <ion-col *ngIf="nextOffset != null"> | ||||
|                     <button ion-button block icon-end (click)="gotoEntry(nextOffset)"> | ||||
|                         {{ 'core.next' | translate }} | ||||
|                         <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> | ||||
|                     </button> | ||||
|  | ||||
| @ -41,7 +41,7 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|     protected module: any; | ||||
|     protected entryId: number; | ||||
|     protected courseId: number; | ||||
|     protected page: number; | ||||
|     protected offset: number; | ||||
|     protected syncObserver: any; // It will observe the sync auto event.
 | ||||
|     protected entryChangedObserver: any; // It will observe the changed entry event.
 | ||||
|     protected fields = {}; | ||||
| @ -55,8 +55,8 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|     offlineActions = []; | ||||
|     hasOffline = false; | ||||
|     cssTemplate = ''; | ||||
|     previousId: number; | ||||
|     nextId: number; | ||||
|     previousOffset: number; | ||||
|     nextOffset: number; | ||||
|     access: any; | ||||
|     data: any; | ||||
|     groupInfo: any; | ||||
| @ -77,7 +77,7 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|         this.entryId = params.get('entryId') || null; | ||||
|         this.courseId = params.get('courseId'); | ||||
|         this.selectedGroup = params.get('group') || 0; | ||||
|         this.page = params.get('page') || null; | ||||
|         this.offset = params.get('offset'); | ||||
| 
 | ||||
|         this.siteId = sitesProvider.getCurrentSiteId(); | ||||
| 
 | ||||
| @ -133,7 +133,7 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|             this.data = data; | ||||
|             this.cssClass = 'addon-data-entries-' + data.id; | ||||
| 
 | ||||
|             return this.setEntryIdFromPage(data.id, this.page, this.selectedGroup).then(() => { | ||||
|             return this.setEntryIdFromOffset(data.id, this.offset, this.selectedGroup).then(() => { | ||||
|                 return this.dataProvider.getDatabaseAccessInformation(data.id); | ||||
|             }); | ||||
|         }).then((accessData) => { | ||||
| @ -177,7 +177,7 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|             const actions = this.dataHelper.getActions(this.data, this.access, this.entry); | ||||
| 
 | ||||
|             const templte = this.data.singletemplate || this.dataHelper.getDefaultTemplate('single', fieldsArray); | ||||
|             this.entryRendered = this.dataHelper.displayShowFields(templte, fieldsArray, this.entry, 'show', actions); | ||||
|             this.entryRendered = this.dataHelper.displayShowFields(templte, fieldsArray, this.entry, this.offset, 'show', actions); | ||||
|             this.showComments = actions.comments; | ||||
| 
 | ||||
|             const entries = {}; | ||||
| @ -189,11 +189,6 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|                 entries: entries, | ||||
|                 data: this.data | ||||
|             }; | ||||
| 
 | ||||
|             return this.dataHelper.getPageInfoByEntry(this.data.id, this.entryId, this.selectedGroup).then((result) => { | ||||
|                 this.previousId = result.previousId; | ||||
|                 this.nextId = result.nextId; | ||||
|             }); | ||||
|         }).catch((message) => { | ||||
|             if (!refresh) { | ||||
|                 // Some call failed, retry without using cache since it might be a new activity.
 | ||||
| @ -210,13 +205,13 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|     /** | ||||
|      * Go to selected entry without changing state. | ||||
|      * | ||||
|      * @param  {number}       entry Entry Id where to go. | ||||
|      * @return {Promise<any>}       Resolved when done. | ||||
|      * @param  {number} offset Entry offset. | ||||
|      * @return {Promise<any>} Resolved when done. | ||||
|      */ | ||||
|     gotoEntry(entry: number): Promise<any> { | ||||
|         this.entryId = entry; | ||||
|     gotoEntry(offset: number): Promise<any> { | ||||
|         this.offset = offset; | ||||
|         this.entryId = null; | ||||
|         this.entry = null; | ||||
|         this.page = null; | ||||
|         this.entryLoaded = false; | ||||
| 
 | ||||
|         return this.fetchEntryData(); | ||||
| @ -264,30 +259,56 @@ export class AddonModDataEntryPage implements OnDestroy { | ||||
|      */ | ||||
|     setGroup(groupId: number): Promise<any> { | ||||
|         this.selectedGroup = groupId; | ||||
|         this.offset = 0; | ||||
|         this.entry = null; | ||||
|         this.entryId = null; | ||||
|         this.entryLoaded = false; | ||||
| 
 | ||||
|         return this.setEntryIdFromPage(this.data.id, 0, this.selectedGroup).then(() => { | ||||
|             return this.fetchEntryData(); | ||||
|         }); | ||||
|         return this.fetchEntryData(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to translate page number to entry identifier. | ||||
|      * Convenience function to translate offset to entry identifier and set next/previous entries. | ||||
|      * | ||||
|      * @param  {number}       dataId       Data Id. | ||||
|      * @param  {number}       [pageNumber] Page number where to go | ||||
|      * @param  {number}       group        Group Id to get the entry. | ||||
|      * @return {Promise<any>}              Resolved when done. | ||||
|      * @param {number} dataId Data Id. | ||||
|      * @param {number} [offset] Offset of the entry. | ||||
|      * @param {number} [groupId] Group Id to get the entry. | ||||
|      * @return {Promise<any>} Resolved when done. | ||||
|      */ | ||||
|     protected setEntryIdFromPage(dataId: number, pageNumber?: number, group?: number): Promise<any> { | ||||
|         if (typeof pageNumber == 'number') { | ||||
|             return this.dataHelper.getPageInfoByPage(dataId, pageNumber, group).then((result) => { | ||||
|                 this.entryId = result.entryId; | ||||
|                 this.page = null; | ||||
|             }); | ||||
|     protected setEntryIdFromOffset(dataId: number, offset?: number, groupId?: number): Promise<any> { | ||||
|         if (typeof offset != 'number') { | ||||
|             // Entry id passed as navigation parameter instead of the offset.
 | ||||
|             // We don't display next/previous buttons in this case.
 | ||||
|             this.nextOffset = null; | ||||
|             this.previousOffset = null; | ||||
| 
 | ||||
|             return Promise.resolve(); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.resolve(); | ||||
|         const perPage = AddonModDataProvider.PER_PAGE; | ||||
|         const page = Math.floor(offset / perPage); | ||||
|         const pageOffset = offset % perPage; | ||||
| 
 | ||||
|         return this.dataProvider.getEntries(dataId, groupId, undefined, undefined, page, perPage).then((entries) => { | ||||
|             if (!entries || !entries.entries || !entries.entries.length || pageOffset >= entries.entries.length) { | ||||
|                 return Promise.reject(null); | ||||
|             } | ||||
| 
 | ||||
|             this.entryId = entries.entries[pageOffset].id; | ||||
|             this.previousOffset = offset > 0 ? offset - 1 : null; | ||||
|             if (pageOffset + 1 < entries.entries.length) { | ||||
|                 // Not the last entry on the page;
 | ||||
|                 this.nextOffset = offset + 1; | ||||
|             } else if (entries.entries.length < perPage) { | ||||
|                 // Last entry of the last page.
 | ||||
|                 this.nextOffset = null; | ||||
|             } else { | ||||
|                 // Last entry of the page, check if there are more pages.
 | ||||
|                 return this.dataProvider.getEntries(dataId, groupId, undefined, undefined, page + 1, perPage).then((entries) => { | ||||
|                     this.nextOffset = entries && entries.entries && entries.entries.length > 0 ? offset + 1 : null; | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -100,11 +100,12 @@ export class AddonModDataHelperProvider { | ||||
|      * @param {string} template   Template HMTL. | ||||
|      * @param {any[]}  fields     Fields that defines every content in the entry. | ||||
|      * @param {any}    entry      Entry. | ||||
|      * @param {number} offset     Entry offset. | ||||
|      * @param {string} mode       Mode list or show. | ||||
|      * @param {any}    actions    Actions that can be performed to the record. | ||||
|      * @return {string}           Generated HTML. | ||||
|      */ | ||||
|     displayShowFields(template: string, fields: any[], entry: any, mode: string, actions: any): string { | ||||
|     displayShowFields(template: string, fields: any[], entry: any, offset: number, mode: string, actions: any): string { | ||||
|         if (!template) { | ||||
|             return ''; | ||||
|         } | ||||
| @ -135,7 +136,7 @@ export class AddonModDataHelperProvider { | ||||
|                     render = this.translate.instant('addon.mod_data.' + (entry.approved ? 'approved' : 'notapproved')); | ||||
|                 } else { | ||||
|                     render = '<addon-mod-data-action action="' + action + '" [entry]="entries[' + entry.id + | ||||
|                                 ']" mode="' + mode + '" [database]="data"></addon-mod-data-action>'; | ||||
|                                 ']" mode="' + mode + '" [database]="data" [offset]="' + offset + '"></addon-mod-data-action>'; | ||||
|                 } | ||||
|                 template = template.replace(replace, render); | ||||
|             } else { | ||||
| @ -177,24 +178,6 @@ export class AddonModDataHelperProvider { | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Fetch all entries and return it's Id | ||||
|      * | ||||
|      * @param  {number}    dataId          Data ID. | ||||
|      * @param  {number}    groupId         Group ID. | ||||
|      * @param  {boolean}   [forceCache]    True to always get the value from cache, false otherwise. Default false. | ||||
|      * @param  {boolean}   [ignoreCache]   True if it should ignore cached data (it will always fail in offline or server down). | ||||
|      * @param  {string}    [siteId]        Site ID. Current if not defined. | ||||
|      * @return {Promise<any>}              Resolved with an array of entry ID. | ||||
|      */ | ||||
|     getAllEntriesIds(dataId: number, groupId: number, forceCache: boolean = false, ignoreCache: boolean = false, siteId?: string): | ||||
|             Promise<any> { | ||||
|         return this.dataProvider.fetchAllEntries(dataId, groupId, undefined, undefined, undefined, forceCache, ignoreCache, siteId) | ||||
|                 .then((entries) => { | ||||
|             return entries.map((entry) => entry.id); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the default template of a certain type. | ||||
|      * | ||||
| @ -398,67 +381,6 @@ export class AddonModDataHelperProvider { | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get page info related to an entry. | ||||
|      * | ||||
|      * @param  {number}    dataId          Data ID. | ||||
|      * @param  {number}    entryId         Entry ID. | ||||
|      * @param  {number}    groupId         Group ID. | ||||
|      * @param  {boolean}   [forceCache]    True to always get the value from cache, false otherwise. Default false. | ||||
|      * @param  {boolean}   [ignoreCache]   True if it should ignore cached data (it will always fail in offline or server down). | ||||
|      * @param  {string}    [siteId]        Site ID. Current if not defined. | ||||
|      * @return {Promise<any>}              Containing page number, if has next and have following page. | ||||
|      */ | ||||
|     getPageInfoByEntry(dataId: number, entryId: number, groupId: number, forceCache: boolean = false, | ||||
|             ignoreCache: boolean = false, siteId?: string): Promise<any> { | ||||
|         return this.getAllEntriesIds(dataId, groupId, forceCache, ignoreCache, siteId).then((entries) => { | ||||
|             const index = entries.findIndex((entry) => entry == entryId); | ||||
| 
 | ||||
|             if (index >= 0) { | ||||
|                 return { | ||||
|                     previousId: entries[index - 1] || false, | ||||
|                     nextId: entries[index + 1] || false, | ||||
|                     entryId: entryId, | ||||
|                     page: index + 1, // Parsed to natural language.
 | ||||
|                     numEntries: entries.length | ||||
|                 }; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get page info related to an entry by page number. | ||||
|      * | ||||
|      * @param  {number}    dataId          Data ID. | ||||
|      * @param  {number}    page            Page number. | ||||
|      * @param  {number}    groupId         Group ID. | ||||
|      * @param  {boolean}   [forceCache]    True to always get the value from cache, false otherwise. Default false. | ||||
|      * @param  {boolean}   [ignoreCache]   True if it should ignore cached data (it will always fail in offline or server down). | ||||
|      * @param  {string}    [siteId]        Site ID. Current if not defined. | ||||
|      * @return {Promise<any>}              Containing page number, if has next and have following page. | ||||
|      */ | ||||
|     getPageInfoByPage(dataId: number, page: number, groupId: number, forceCache: boolean = false, | ||||
|             ignoreCache: boolean = false, siteId?: string): Promise<any> { | ||||
|         return this.getAllEntriesIds(dataId, groupId, forceCache, ignoreCache, siteId).then((entries) => { | ||||
|             const index = page - 1, | ||||
|                 entryId = entries[index]; | ||||
| 
 | ||||
|             if (entryId) { | ||||
|                 return { | ||||
|                     previousId: entries[index - 1] || null, | ||||
|                     nextId: entries[index + 1] || null, | ||||
|                     entryId: entryId, | ||||
|                     page: page, // Parsed to natural language.
 | ||||
|                     numEntries: entries.length | ||||
|                 }; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a list of stored attachment files for a new entry. See $mmaModDataHelper#storeFiles. | ||||
|      * | ||||
|  | ||||
| @ -65,7 +65,7 @@ export class AddonModDataShowLinkHandler extends CoreContentLinksHandlerBase { | ||||
|                     } | ||||
| 
 | ||||
|                     if (params.mode && params.mode == 'single') { | ||||
|                         pageParams['page'] = page || 1; | ||||
|                         pageParams['offset'] = page || 0; | ||||
|                     } else if (rId) { | ||||
|                         pageParams['entryId'] = rId; | ||||
|                     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user