// (C) Copyright 2015 Martin Dougiamas // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { Component, Optional, Injector, Input, ViewChild } from '@angular/core'; import { Content, NavController, PopoverController, ViewController } from 'ionic-angular'; import { CoreGroupsProvider } from '@providers/groups'; import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; import { CoreUserProvider } from '@core/user/providers/user'; import { AddonModWikiProvider, AddonModWikiSubwikiListData } from '../../providers/wiki'; import { AddonModWikiOfflineProvider } from '../../providers/wiki-offline'; import { AddonModWikiSyncProvider } from '../../providers/wiki-sync'; import { CoreTabsComponent } from '@components/tabs/tabs'; import { AddonModWikiSubwikiPickerComponent } from '../../components/subwiki-picker/subwiki-picker'; /** * Component that displays a wiki entry page. */ @Component({ selector: 'addon-mod-wiki-index', templateUrl: 'addon-mod-wiki-index.html', }) export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComponent { @ViewChild(CoreTabsComponent) tabs: CoreTabsComponent; @Input() action: string; @Input() pageId: number; @Input() pageTitle: string; @Input() wikiId: number; @Input() subwikiId: number; @Input() userId: number; @Input() groupId: number; component = AddonModWikiProvider.COMPONENT; componentId: number; moduleName = 'wiki'; wiki: any; // The wiki instance. isMainPage: boolean; // Whether the user is viewing wiki's main page (just entered the wiki). canEdit = false; // Whether user can edit the page. pageStr = ''; pageWarning: string; // Message telling that the page was discarded. loadedSubwikis: any[] = []; // The loaded subwikis. pageIsOffline: boolean; // Whether the loaded page is an offline page. pageContent: string; // Page content to display. showHomeButton: boolean; // Whether to display the home button. selectedTab = 0; // Tab to select at start. map: any[] = []; // Map of pages, categorized by letter. subwikiData: AddonModWikiSubwikiListData = { // Data for the subwiki selector. subwikiSelected: 0, userSelected: 0, groupSelected: 0, subwikis: [], count: 0 }; protected syncEventName = AddonModWikiSyncProvider.AUTO_SYNCED; protected currentSubwiki: any; // Current selected subwiki. protected currentPage: number; // Current loaded page ID. protected currentPageObj: any; // Object of the current loaded page. protected subwikiPages: any[]; // List of subwiki pages. protected newPageObserver: any; // Observer to check for new pages. protected ignoreManualSyncEvent: boolean; // Whether manual sync event should be ignored. protected manualSyncObserver: any; // An observer to watch for manual sync events. protected currentUserId: number; // Current user ID. protected hasEdited = false; // Whether the user has opened the edit page. protected mapInitialized = false; // Whether the map was initialized. protected initHomeButton = true; // Whether the init home button must be initialized. constructor(injector: Injector, protected wikiProvider: AddonModWikiProvider, @Optional() protected content: Content, protected wikiOffline: AddonModWikiOfflineProvider, protected wikiSync: AddonModWikiSyncProvider, protected navCtrl: NavController, protected utils: CoreUtilsProvider, protected groupsProvider: CoreGroupsProvider, protected userProvider: CoreUserProvider, private popoverCtrl: PopoverController) { super(injector, content); this.pageStr = this.translate.instant('addon.mod_wiki.wikipage'); } /** * Component being initialized. */ ngOnInit(): void { super.ngOnInit(); this.currentUserId = this.sitesProvider.getCurrentSiteUserId(); this.isMainPage = !this.pageId && !this.pageTitle; this.currentPage = this.pageId; this.selectedTab = this.action == 'map' ? 1 : 0; this.loadContent(false, true).then(() => { if (!this.wiki) { return; } if (this.isMainPage) { this.wikiProvider.logView(this.wiki.id, this.wiki.name).then(() => { this.courseProvider.checkModuleCompletion(this.courseId, this.module.completiondata); }).catch((error) => { // Ignore errors. }); } else { this.wikiProvider.logPageView(this.pageId, this.wiki.id, this.wiki.name).catch(() => { // Ignore errors. }); } }); // Listen for manual sync events. this.manualSyncObserver = this.eventsProvider.on(AddonModWikiSyncProvider.MANUAL_SYNCED, (data) => { if (data && this.wiki && data.wikiId == this.wiki.id) { if (this.ignoreManualSyncEvent) { // Event needs to be ignored. this.ignoreManualSyncEvent = false; return; } if (this.currentSubwiki) { this.checkPageCreatedOrDiscarded(data.subwikis[this.currentSubwiki.id]); } if (!this.pageWarning) { this.showLoadingAndFetch(false, false); } } }, this.siteId); } /** * Check if the current page was created or discarded. * * @param {any} data Data about created and deleted pages. */ protected checkPageCreatedOrDiscarded(data: any): void { if (!this.currentPage && data) { // This is an offline page. Check if the page was created. let pageId; for (let i = 0, len = data.created.length; i < len; i++) { const page = data.created[i]; if (page.title == this.pageTitle) { pageId = page.pageId; break; } } if (pageId) { // Page was created, set the ID so it's retrieved from server. this.currentPage = pageId; this.pageIsOffline = false; } else { // Page not found in created list, check if it was discarded. for (let i = 0, len = data.discarded.length; i < len; i++) { const page = data.discarded[i]; if (page.title == this.pageTitle) { // Page discarded, show warning. this.pageWarning = page.warning; this.pageContent = ''; this.pageIsOffline = false; this.hasOffline = false; } } } } } /** * Construct the map of pages. * * @param {any[]} subwikiPages List of pages. */ constructMap(subwikiPages: any[]): void { let letter, initialLetter; this.map = []; this.mapInitialized = true; subwikiPages.sort((a, b) => { const compareA = a.title.toLowerCase().trim(), compareB = b.title.toLowerCase().trim(); return compareA.localeCompare(compareB); }); subwikiPages.forEach((page) => { const letterCandidate = page.title.charAt(0).toLocaleUpperCase(); // Should we create a new grouping? if (letterCandidate !== initialLetter) { initialLetter = letterCandidate; letter = {label: letterCandidate, pages: []}; this.map.push(letter); } // Add the subwiki to the currently active grouping. letter.pages.push(page); }); } /** * Get the wiki data. * * @param {boolean} [refresh=false] If it's refreshing content. * @param {boolean} [sync=false] If it should try to sync. * @param {boolean} [showErrors=false] If show errors to the user of hide them. * @return {Promise} Promise resolved when done. */ protected fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise { // Get the wiki instance. let promise; if (this.module.id) { promise = this.wikiProvider.getWiki(this.courseId, this.module.id); } else { promise = this.wikiProvider.getWikiById(this.courseId, this.wikiId); } return promise.then((wiki) => { this.wiki = wiki; this.dataRetrieved.emit(this.wiki); if (sync) { // Try to synchronize the wiki. return this.syncActivity(showErrors).catch(() => { // Ignore errors. }); } }).then(() => { if (this.pageWarning) { // Page discarded, stop getting data. return Promise.reject(null); } if (this.isCurrentView || this.initHomeButton) { this.initHomeButton = false; this.showHomeButton = !!this.getWikiHomeView(); } // Get module instance if it's empty. let promise; if (!this.module.id) { promise = this.courseProvider.getModule(this.wiki.coursemodule, this.wiki.course, undefined, true); } else { promise = Promise.resolve(this.module); } return promise.then((mod) => { this.module = mod; this.description = this.wiki.intro || this.module.description; this.externalUrl = this.module.url; this.componentId = this.module.id; // Get real groupmode, in case it's forced by the course. return this.groupsProvider.getActivityGroupMode(this.wiki.coursemodule).then((groupMode) => { if (groupMode === CoreGroupsProvider.SEPARATEGROUPS || groupMode === CoreGroupsProvider.VISIBLEGROUPS) { // Get the groups available for the user. promise = this.groupsProvider.getActivityAllowedGroups(this.wiki.coursemodule); } else { promise = Promise.resolve([]); } return promise.then((userGroups) => { return this.fetchSubwikis(this.wiki.id).then(() => { // Get the subwiki list data from the cache. const subwikiList = this.wikiProvider.getSubwikiList(this.wiki.id); if (!subwikiList) { // Not found in cache, create a new one. return this.createSubwikiList(userGroups); } this.subwikiData.count = subwikiList.count; this.setSelectedWiki(this.subwikiId, this.userId, this.groupId); // If nothing was selected using nav params, use the selected from cache. if (!this.isAnySubwikiSelected()) { this.setSelectedWiki(subwikiList.subwikiSelected, subwikiList.userSelected, subwikiList.groupSelected); } this.subwikiData.subwikis = subwikiList.subwikis; }); }).then(() => { if (!this.isAnySubwikiSelected() || this.subwikiData.count <= 0) { return Promise.reject(this.translate.instant('addon.mod_wiki.errornowikiavailable')); } }).then(() => { return this.fetchWikiPage(); }); }); }); }).then(() => { // All data obtained, now fill the context menu. this.fillContextMenu(refresh); }).catch((error) => { if (this.pageWarning) { // Warning is already shown in screen, no need to show a modal. return; } return Promise.reject(error); }); } /** * Get wiki page contents. * * @param {number} pageId Page to get. * @return {Promise} Promise resolved with the page data. */ protected fetchPageContents(pageId: number): Promise { if (!pageId) { const title = this.pageTitle || this.wiki.firstpagetitle; // No page ID but we received a title. This means we're trying to load an offline page. return this.wikiOffline.getNewPage(title, this.currentSubwiki.id, this.currentSubwiki.wikiid, this.currentSubwiki.userid, this.currentSubwiki.groupid).then((offlinePage) => { this.pageIsOffline = true; if (!this.newPageObserver) { // It's an offline page, listen for new pages event to detect if the user goes to Edit and submits the page. this.newPageObserver = this.eventsProvider.on(AddonModWikiProvider.PAGE_CREATED_EVENT, (data) => { if (data.subwikiId == this.currentSubwiki.id && data.pageTitle == title) { // The page has been submitted. Get the page from the server. this.currentPage = data.pageId; this.showLoadingAndFetch(true, false).then(() => { this.wikiProvider.logPageView(this.currentPage, this.wiki.id, this.wiki.name).catch(() => { // Ignore errors. }); }); // Stop listening for new page events. this.newPageObserver.off(); this.newPageObserver = undefined; } }, this.sitesProvider.getCurrentSiteId()); } return offlinePage; }).catch(() => { // Page not found, ignore. }); } this.pageIsOffline = false; return this.wikiProvider.getPageContents(pageId); } /** * Fetch the list of pages of a subwiki. * * @param {any} subwiki Subwiki. */ protected fetchSubwikiPages(subwiki: any): Promise { let subwikiPages; return this.wikiProvider.getSubwikiPages(subwiki.wikiid, subwiki.groupid, subwiki.userid).then((pages) => { subwikiPages = pages; // If no page specified, search first page. if (!this.currentPage && !this.pageTitle) { for (const i in subwikiPages) { const page = subwikiPages[i]; if (page.firstpage) { this.currentPage = page.id; break; } } } // Now get the offline pages. return this.wikiOffline.getSubwikiNewPages(subwiki.id, subwiki.wikiid, subwiki.userid, subwiki.groupid); }).then((offlinePages) => { // If no page specified, search page title in the offline pages. if (!this.currentPage) { const searchTitle = this.pageTitle ? this.pageTitle : this.wiki.firstpagetitle, pageExists = offlinePages.some((page) => { return page.title == searchTitle; }); if (pageExists) { this.pageTitle = searchTitle; } } this.subwikiPages = this.wikiProvider.sortPagesByTitle(subwikiPages.concat(offlinePages)); this.constructMap(this.subwikiPages); // Reject if no currentPage selected from the subwikis given (if no subwikis available, do not reject). if (!this.currentPage && !this.pageTitle && this.subwikiPages.length > 0) { return Promise.reject(null); } }); } /** * Get the subwikis. * * @param {number} wikiId Wiki ID. */ protected fetchSubwikis(wikiId: number): Promise { return this.wikiProvider.getSubwikis(wikiId).then((subwikis) => { this.loadedSubwikis = subwikis; return this.wikiOffline.subwikisHaveOfflineData(subwikis).then((hasOffline) => { this.hasOffline = hasOffline; }); }); } /** * Fetch the page to be shown. * * @return {Promise} [description] */ protected fetchWikiPage(): Promise { // Search the current Subwiki. this.currentSubwiki = this.loadedSubwikis.find((subwiki) => { return this.isSubwikiSelected(subwiki); }); if (!this.currentSubwiki) { return Promise.reject(null); } this.setSelectedWiki(this.currentSubwiki.id, this.currentSubwiki.userid, this.currentSubwiki.groupid); return this.fetchSubwikiPages(this.currentSubwiki).then(() => { // Check can edit before to have the value if there's no valid page. this.canEdit = this.currentSubwiki.canedit; return this.fetchPageContents(this.currentPage).then((pageContents) => { if (pageContents) { this.dataRetrieved.emit(pageContents.title); this.setSelectedWiki(pageContents.subwikiid, pageContents.userid, pageContents.groupid); this.pageContent = this.replaceEditLinks(pageContents.cachedcontent); this.canEdit = pageContents.caneditpage; this.currentPageObj = pageContents; } }); }); } /** * Get the wiki home view. If cannot determine or it's current view, return undefined. * * @return {ViewController} The view controller of the home view */ protected getWikiHomeView(): ViewController { if (!this.wiki.id) { return; } const views = this.navCtrl.getViews(); // Go back in history until we find a page that doesn't belong to current wiki. for (let i = views.length - 2; i >= 0; i--) { const view = views[i]; if (view.component.name != 'AddonModWikiIndexPage') { if (i == views.length - 2) { // Next view is current view, return undefined. return; } // This view is no longer from wiki, return the next view. return views[i + 1]; } // Check that the view belongs to the same wiki as current view. const wikiId = view.data.wikiId ? view.data.wikiId : view.data.module.instance; if (!wikiId || wikiId != this.wiki.id) { // Wiki has changed, return the next view. return views[i + 1]; } } } /** * Go back to the initial page of the wiki. */ goToWikiHome(): void { const homeView = this.getWikiHomeView(); if (homeView) { this.navCtrl.popTo(homeView); } } /** * Open the view to create the first page of the wiki. */ protected goToCreateFirstPage(): void { this.navCtrl.push('AddonModWikiEditPage', { module: this.module, courseId: this.courseId, pageTitle: this.wiki.firstpagetitle, wikiId: this.currentSubwiki.wikiid, userId: this.currentSubwiki.userid, groupId: this.currentSubwiki.groupid }); } /** * Open the view to edit the current page. */ goToEditPage(): void { if (!this.canEdit) { return; } if (this.currentPageObj) { // Current page exists, go to edit it. const pageParams: any = { module: this.module, courseId: this.courseId, pageId: this.currentPageObj.id, pageTitle: this.currentPageObj.title, subwikiId: this.currentPageObj.subwikiid }; if (this.currentSubwiki) { pageParams.wikiId = this.currentSubwiki.wikiid; pageParams.userId = this.currentSubwiki.userid; pageParams.groupId = this.currentSubwiki.groupid; } this.navCtrl.push('AddonModWikiEditPage', pageParams); } else if (this.currentSubwiki) { // No page loaded, the wiki doesn't have first page. this.goToCreateFirstPage(); } } /** * Go to the view to create a new page. */ goToNewPage(): void { if (!this.canEdit) { return; } if (this.currentPageObj) { // Current page exists, go to edit it. const pageParams: any = { module: this.module, courseId: this.courseId, subwikiId: this.currentPageObj.subwikiid }; if (this.currentSubwiki) { pageParams.wikiId = this.currentSubwiki.wikiid; pageParams.userId = this.currentSubwiki.userid; pageParams.groupId = this.currentSubwiki.groupid; } this.navCtrl.push('AddonModWikiEditPage', pageParams); } else if (this.currentSubwiki) { // No page loaded, the wiki doesn't have first page. this.goToCreateFirstPage(); } } /** * Go to view a certain page. * * @param {any} page Page to view. */ goToPage(page: any): void { if (!page.id) { // It's an offline page. Check if we are already in the same offline page. if (this.currentPage || !this.pageTitle || page.title != this.pageTitle) { this.navCtrl.push('AddonModWikiIndexPage', { module: this.module, courseId: this.courseId, pageTitle: page.title, wikiId: this.wiki.id, subwikiId: page.subwikiid, action: 'page' }); return; } } else if (this.currentPage != page.id) { // Add a new State. this.fetchPageContents(page.id).then((page) => { this.navCtrl.push('AddonModWikiIndexPage', { module: this.module, courseId: this.courseId, pageTitle: page.title, pageId: page.id, wikiId: page.wikiid, subwikiId: page.subwikiid, action: 'page' }); }); return; } // No changes done. this.tabs.selectTab(0); } /** * Go to the page to view a certain subwiki. * * @param {number} subwikiId Subwiki ID. * @param {number} userId User ID of the subwiki. * @param {number} groupId Group ID of the subwiki. * @param {boolean} canEdit Whether the subwiki can be edited. */ goToSubwiki(subwikiId: number, userId: number, groupId: number, canEdit: boolean): void { // Check if the subwiki is disabled. if (subwikiId > 0 || canEdit) { if (subwikiId != this.currentSubwiki.id || userId != this.currentSubwiki.userid || groupId != this.currentSubwiki.groupid) { this.navCtrl.push('AddonModWikiIndexPage', { module: this.module, courseId: this.courseId, wikiId: this.wiki.id, subwikiId: subwikiId, userId: userId, groupId: groupId, action: this.tabs.selected == 0 ? 'page' : 'map' }); } } } /** * Checks if there is any subwiki selected. * * @return {boolean} Whether there is any subwiki selected. */ protected isAnySubwikiSelected(): boolean { return this.subwikiData.subwikiSelected > 0 || this.subwikiData.userSelected > 0 || this.subwikiData.groupSelected > 0; } /** * Checks if the given subwiki is the one picked on the subwiki picker. * * @param {any} subwiki Subwiki to check. * @return {boolean} Whether it's the selected subwiki. */ protected isSubwikiSelected(subwiki: any): boolean { const subwikiId = parseInt(subwiki.id, 10) || 0; if (subwikiId > 0 && this.subwikiData.subwikiSelected > 0) { return subwikiId == this.subwikiData.subwikiSelected; } const userId = parseInt(subwiki.userid, 10) || 0, groupId = parseInt(subwiki.groupid, 10) || 0; return userId == this.subwikiData.userSelected && groupId == this.subwikiData.groupSelected; } /** * Replace edit links to have full url. * * @param {string} content Content to treat. * @return {string} Treated content. */ protected replaceEditLinks(content: string): string { content = content.trim(); if (content.length > 0) { const editUrl = this.textUtils.concatenatePaths(this.sitesProvider.getCurrentSite().getURL(), '/mod/wiki/edit.php'); content = content.replace(/href="edit\.php/g, 'href="' + editUrl); } return content; } /** * Sets the selected subwiki for the subwiki picker. * * @param {number} subwikiId Subwiki ID to select. * @param {number} userId User ID of the subwiki to select. * @param {number} groupId Group ID of the subwiki to select. */ protected setSelectedWiki(subwikiId: number, userId: number, groupId: number): void { this.subwikiData.subwikiSelected = this.wikiOffline.convertToPositiveNumber(subwikiId); this.subwikiData.userSelected = this.wikiOffline.convertToPositiveNumber(userId); this.subwikiData.groupSelected = this.wikiOffline.convertToPositiveNumber(groupId); } /** * Checks if sync has succeed from result sync data. * * @param {any} result Data returned on the sync function. * @return {boolean} If suceed or not. */ protected hasSyncSucceed(result: any): boolean { result.wikiId = this.wiki.id; if (result.updated) { // Trigger event. this.ignoreManualSyncEvent = true; this.eventsProvider.trigger(AddonModWikiSyncProvider.MANUAL_SYNCED, result); } if (this.currentSubwiki) { this.checkPageCreatedOrDiscarded(result.subwikis[this.currentSubwiki.id]); } return result.updated; } /** * User entered the page that contains the component. */ ionViewDidEnter(): void { super.ionViewDidEnter(); this.tabs && this.tabs.ionViewDidEnter(); if (this.hasEdited) { this.hasEdited = false; this.showLoadingAndRefresh(true, false); } } /** * User left the page that contains the component. */ ionViewDidLeave(): void { super.ionViewDidLeave(); this.tabs && this.tabs.ionViewDidLeave(); if (this.navCtrl.getActive().component.name == 'AddonModWikiEditPage') { this.hasEdited = true; } } /** * Perform the invalidate content function. * * @return {Promise} Resolved when done. */ protected invalidateContent(): Promise { const promises = []; promises.push(this.wikiProvider.invalidateWikiData(this.courseId)); if (this.wiki) { promises.push(this.wikiProvider.invalidateSubwikis(this.wiki.id)); promises.push(this.groupsProvider.invalidateActivityAllowedGroups(this.wiki.coursemodule)); promises.push(this.groupsProvider.invalidateActivityGroupMode(this.wiki.coursemodule)); } if (this.currentSubwiki) { promises.push(this.wikiProvider.invalidateSubwikiPages(this.currentSubwiki.wikiid)); promises.push(this.wikiProvider.invalidateSubwikiFiles(this.currentSubwiki.wikiid)); } if (this.currentPage) { promises.push(this.wikiProvider.invalidatePage(this.currentPage)); } return Promise.all(promises); } /** * Compares sync event data with current data to check if refresh content is needed. * * @param {any} syncEventData Data receiven on sync observer. * @return {boolean} True if refresh is needed, false otherwise. */ protected isRefreshSyncNeeded(syncEventData: any): boolean { if (this.currentSubwiki && syncEventData.subwikiId == this.currentSubwiki.id && syncEventData.wikiId == this.currentSubwiki.wikiid && syncEventData.userId == this.currentSubwiki.userid && syncEventData.groupId == this.currentSubwiki.groupid) { if (this.isCurrentView && syncEventData.warnings && syncEventData.warnings.length) { // Show warnings. this.domUtils.showErrorModal(syncEventData.warnings[0]); } // Check if current page was created or discarded. this.checkPageCreatedOrDiscarded(syncEventData); } return !this.pageWarning; } /** * Show the TOC. * * @param {MouseEvent} event Event. */ showSubwikiPicker(event: MouseEvent): void { const popover = this.popoverCtrl.create(AddonModWikiSubwikiPickerComponent, { subwikis: this.subwikiData.subwikis, currentSubwiki: this.currentSubwiki }); popover.onDidDismiss((subwiki) => { if (subwiki) { this.goToSubwiki(subwiki.id, subwiki.userid, subwiki.groupid, subwiki.canedit); } }); popover.present({ ev: event }); } /** * Performs the sync of the activity. * * @return {Promise} Promise resolved when done. */ protected sync(): Promise { return this.wikiSync.syncWiki(this.wiki.id, this.courseId, this.wiki.coursemodule); } /** * Component being destroyed. */ ngOnDestroy(): void { super.ngOnDestroy(); this.manualSyncObserver && this.manualSyncObserver.off(); this.newPageObserver && this.newPageObserver.off(); } /** * Create the subwiki list for the selector and store it in the cache. * * @param {any[]} userGroups Groups. * @return {Promise} Promise resolved when done. */ protected createSubwikiList(userGroups: any[]): Promise { const subwikiList = [], promises = []; let userGroupsIds = [], allParticipants = false, showMyGroupsLabel = false, multiLevelList = false; this.subwikiData.subwikis = []; this.setSelectedWiki(this.subwikiId, this.userId, this.groupId); this.subwikiData.count = 0; // Group mode available. if (userGroups.length > 0) { userGroupsIds = userGroups.map((g) => { return g.id; }); } // Add the subwikis to the subwikiList. this.loadedSubwikis.forEach((subwiki) => { const groupId = parseInt(subwiki.groupid, 10), userId = parseInt(subwiki.userid, 10); let groupLabel = ''; if (groupId == 0 && userId == 0) { // Add 'All participants' subwiki if needed at the start. if (!allParticipants) { subwikiList.unshift({ name: this.translate.instant('core.allparticipants'), id: subwiki.id, userid: userId, groupid: groupId, groupLabel: '', canedit: subwiki.canedit }); allParticipants = true; } } else { if (groupId != 0 && userGroupsIds.length > 0) { // Get groupLabel if it has groupId. const groupIdPosition = userGroupsIds.indexOf(groupId); if (groupIdPosition > -1) { groupLabel = userGroups[groupIdPosition].name; } } else { groupLabel = this.translate.instant('addon.mod_wiki.notingroup'); } if (userId != 0) { // Get user if it has userId. promises.push(this.userProvider.getProfile(userId, this.courseId, true).then((user) => { subwikiList.push({ name: user.fullname, id: subwiki.id, userid: userId, groupid: groupId, groupLabel: groupLabel, canedit: subwiki.canedit }); })); if (!multiLevelList && groupId != 0) { multiLevelList = true; } } else { subwikiList.push({ name: groupLabel, id: subwiki.id, userid: userId, groupid: groupId, groupLabel: groupLabel, canedit: subwiki.canedit }); showMyGroupsLabel = true; } } }); return Promise.all(promises).then(() => { this.fillSubwikiData(subwikiList, showMyGroupsLabel, multiLevelList); }); } /** * Fill the subwiki data. * * @param {any[]} subwikiList List of subwikis. * @param {boolean} showMyGroupsLabel Whether subwikis should be grouped in "My groups" and "Other groups". * @param {boolean} multiLevelList Whether it's a multi level list. */ protected fillSubwikiData(subwikiList: any[], showMyGroupsLabel: boolean, multiLevelList: boolean): void { let groupValue = -1, grouping; subwikiList.sort((a, b) => { return a.groupid - b.groupid; }); this.subwikiData.count = subwikiList.length; // If no subwiki is received as view param, select always the most appropiate. if ((!this.subwikiId || (!this.userId && !this.groupId)) && !this.isAnySubwikiSelected() && subwikiList.length > 0) { let firstCanEdit, candidateNoFirstPage, candidateFirstPage; for (const i in subwikiList) { const subwiki = subwikiList[i]; if (subwiki.canedit) { let candidateSubwikiId; if (subwiki.userid > 0) { // Check if it's the current user. if (this.currentUserId == subwiki.userid) { candidateSubwikiId = subwiki.id; } } else if (subwiki.groupid > 0) { // Check if it's a current user' group. if (showMyGroupsLabel) { candidateSubwikiId = subwiki.id; } } else if (subwiki.id > 0) { candidateSubwikiId = subwiki.id; } if (typeof candidateSubwikiId != 'undefined') { if (candidateSubwikiId > 0) { // Subwiki found and created, no need to keep looking. candidateFirstPage = i; break; } else if (typeof candidateNoFirstPage == 'undefined') { candidateNoFirstPage = i; } } else if (typeof firstCanEdit == 'undefined') { firstCanEdit = i; } } } let subWikiToTake; if (typeof candidateFirstPage != 'undefined') { // Take the candidate that already has the first page created. subWikiToTake = candidateFirstPage; } else if (typeof candidateNoFirstPage != 'undefined') { // No first page created, take the first candidate. subWikiToTake = candidateNoFirstPage; } else if (typeof firstCanEdit != 'undefined') { // None selected, take the first the user can edit. subWikiToTake = firstCanEdit; } else { // Otherwise take the very first. subWikiToTake = 0; } const subwiki = subwikiList[subWikiToTake]; if (typeof subwiki != 'undefined') { this.setSelectedWiki(subwiki.id, subwiki.userid, subwiki.groupid); } } if (multiLevelList) { // As we loop over each subwiki, add it to the current group for (const i in subwikiList) { const subwiki = subwikiList[i]; // Should we create a new grouping? if (subwiki.groupid !== groupValue) { grouping = {label: subwiki.groupLabel, subwikis: []}; groupValue = subwiki.groupid; this.subwikiData.subwikis.push(grouping); } // Add the subwiki to the currently active grouping. grouping.subwikis.push(subwiki); } } else if (showMyGroupsLabel) { const noGrouping = {label: '', subwikis: []}, myGroupsGrouping = {label: this.translate.instant('core.mygroups'), subwikis: []}, otherGroupsGrouping = {label: this.translate.instant('core.othergroups'), subwikis: []}; // As we loop over each subwiki, add it to the current group for (const i in subwikiList) { const subwiki = subwikiList[i]; // Add the subwiki to the currently active grouping. if (typeof subwiki.canedit == 'undefined') { noGrouping.subwikis.push(subwiki); } else if (subwiki.canedit) { myGroupsGrouping.subwikis.push(subwiki); } else { otherGroupsGrouping.subwikis.push(subwiki); } } // Add each grouping to the subwikis if (noGrouping.subwikis.length > 0) { this.subwikiData.subwikis.push(noGrouping); } if (myGroupsGrouping.subwikis.length > 0) { this.subwikiData.subwikis.push(myGroupsGrouping); } if (otherGroupsGrouping.subwikis.length > 0) { this.subwikiData.subwikis.push(otherGroupsGrouping); } } else { this.subwikiData.subwikis.push({label: '', subwikis: subwikiList}); } this.wikiProvider.setSubwikiList(this.wiki.id, this.subwikiData.subwikis, this.subwikiData.count, this.subwikiData.subwikiSelected, this.subwikiData.userSelected, this.subwikiData.groupSelected); } }