diff --git a/src/addon/mod/feedback/components/index/index.html b/src/addon/mod/feedback/components/index/index.html index 1cb45dff4..12040b63d 100644 --- a/src/addon/mod/feedback/components/index/index.html +++ b/src/addon/mod/feedback/components/index/index.html @@ -16,7 +16,7 @@ - + diff --git a/src/addon/mod/feedback/components/index/index.ts b/src/addon/mod/feedback/components/index/index.ts index 8fa071427..10dd875b8 100644 --- a/src/addon/mod/feedback/components/index/index.ts +++ b/src/addon/mod/feedback/components/index/index.ts @@ -61,6 +61,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity }; showTabs = false; tabsReady = false; + firstSelectedTab: number; protected submitObserver: any; @@ -165,7 +166,10 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity this.access = accessData; this.showTabs = (accessData.canviewreports || accessData.canviewanalysis) && !accessData.isempty; + this.firstSelectedTab = 0; if (this.tab == 'analysis') { + this.firstSelectedTab = 1; + return this.fetchFeedbackAnalysisData(this.access); } diff --git a/src/addon/mod/feedback/feedback.module.ts b/src/addon/mod/feedback/feedback.module.ts index 2c412f694..3a1f67923 100644 --- a/src/addon/mod/feedback/feedback.module.ts +++ b/src/addon/mod/feedback/feedback.module.ts @@ -21,6 +21,9 @@ import { AddonModFeedbackComponentsModule } from './components/components.module import { AddonModFeedbackModuleHandler } from './providers/module-handler'; import { AddonModFeedbackProvider } from './providers/feedback'; import { AddonModFeedbackLinkHandler } from './providers/link-handler'; +import { AddonModFeedbackAnalysisLinkHandler } from './providers/analysis-link-handler'; +import { AddonModFeedbackShowEntriesLinkHandler } from './providers/show-entries-link-handler'; +import { AddonModFeedbackShowNonRespondentsLinkHandler } from './providers/show-non-respondents-link-handler'; import { AddonModFeedbackHelperProvider } from './providers/helper'; import { AddonModFeedbackPrefetchHandler } from './providers/prefetch-handler'; import { AddonModFeedbackSyncProvider } from './providers/sync'; @@ -39,6 +42,9 @@ import { AddonModFeedbackOfflineProvider } from './providers/offline'; AddonModFeedbackPrefetchHandler, AddonModFeedbackHelperProvider, AddonModFeedbackLinkHandler, + AddonModFeedbackAnalysisLinkHandler, + AddonModFeedbackShowEntriesLinkHandler, + AddonModFeedbackShowNonRespondentsLinkHandler, AddonModFeedbackSyncCronHandler, AddonModFeedbackSyncProvider, AddonModFeedbackOfflineProvider @@ -48,10 +54,16 @@ export class AddonModFeedbackModule { constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModFeedbackModuleHandler, prefetchDelegate: CoreCourseModulePrefetchDelegate, prefetchHandler: AddonModFeedbackPrefetchHandler, contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModFeedbackLinkHandler, - cronDelegate: CoreCronDelegate, syncHandler: AddonModFeedbackSyncCronHandler) { + cronDelegate: CoreCronDelegate, syncHandler: AddonModFeedbackSyncCronHandler, + analysisLinkHandler: AddonModFeedbackAnalysisLinkHandler, + showEntriesLinkHandler: AddonModFeedbackShowEntriesLinkHandler, + showNonRespondentsLinkHandler: AddonModFeedbackShowNonRespondentsLinkHandler) { moduleDelegate.registerHandler(moduleHandler); prefetchDelegate.registerHandler(prefetchHandler); contentLinksDelegate.registerHandler(linkHandler); + contentLinksDelegate.registerHandler(analysisLinkHandler); + contentLinksDelegate.registerHandler(showEntriesLinkHandler); + contentLinksDelegate.registerHandler(showNonRespondentsLinkHandler); cronDelegate.register(syncHandler); } } diff --git a/src/addon/mod/feedback/pages/respondents/respondents.ts b/src/addon/mod/feedback/pages/respondents/respondents.ts index f281c5374..2f3fb82b0 100644 --- a/src/addon/mod/feedback/pages/respondents/respondents.ts +++ b/src/addon/mod/feedback/pages/respondents/respondents.ts @@ -162,7 +162,7 @@ export class AddonModFeedbackRespondentsPage { gotoAttempt(attempt: any): void { this.attemptId = attempt.id; this.splitviewCtrl.push('AddonModFeedbackAttemptPage', { - attemptid: attempt.id, + attemptId: attempt.id, attempt: attempt, feedbackId: this.feedbackId, moduleId: this.moduleId diff --git a/src/addon/mod/feedback/providers/analysis-link-handler.ts b/src/addon/mod/feedback/providers/analysis-link-handler.ts new file mode 100644 index 000000000..12f03a387 --- /dev/null +++ b/src/addon/mod/feedback/providers/analysis-link-handler.ts @@ -0,0 +1,93 @@ +// (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 { Injectable } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonModFeedbackProvider } from './feedback'; +import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; + +/** + * Content links handler for a feedback analysis. + * Match mod/feedback/analysis.php with a valid feedback id. + */ +@Injectable() +export class AddonModFeedbackAnalysisLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonModFeedbackAnalysisLinkHandler'; + featureName = '$mmCourseDelegate_mmaModFeedback'; + pattern = /\/mod\/feedback\/analysis\.php.*([\&\?]id=\d+)/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private feedbackProvider: AddonModFeedbackProvider, + private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + return [{ + action: (siteId, navCtrl?): void => { + const modal = this.domUtils.showModalLoading(), + moduleId = params.id; + + this.courseProvider.getModuleBasicInfo(moduleId, siteId).then((module) => { + const stateParams = { + module: module, + courseId: module.course, + tab: 'analysis' + }; + + return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackIndexPage', stateParams, siteId); + }).finally(() => { + modal.dismiss(); + }); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + return this.feedbackProvider.isPluginEnabled(siteId).then((enabled) => { + if (!enabled) { + return false; + } + + if (typeof params.id == 'undefined') { + // Cannot treat the URL. + return false; + } + + return true; + }); + } +} diff --git a/src/addon/mod/feedback/providers/feedback.ts b/src/addon/mod/feedback/providers/feedback.ts index 7c960b4e5..bc85041c1 100644 --- a/src/addon/mod/feedback/providers/feedback.ts +++ b/src/addon/mod/feedback/providers/feedback.ts @@ -80,6 +80,64 @@ export class AddonModFeedbackProvider { return this.getFeedbackDataPrefixCacheKey(feedbackId) + ':analysis:'; } + /** + * Find an attempt in all responses analysis. + * + * @param {number} feedbackId Feedback ID. + * @param {number} attemptId Attempt id to find. + * @param {string} [siteId] Site ID. If not defined, current site. + * @param {any} [previous] Only for recurrent use. Object with the previous fetched info. + * @return {Promise} Promise resolved when the info is retrieved. + */ + getAttempt(feedbackId: number, attemptId: number, siteId?: string, previous?: any): Promise { + siteId = siteId || this.sitesProvider.getCurrentSiteId(); + if (typeof previous == 'undefined') { + previous = { + page: 0, + attemptsLoaded: 0, + anonAttemptsLoaded: 0 + }; + } + + return this.getResponsesAnalysis(feedbackId, 0, previous.page, siteId).then((responses) => { + let attempt; + + attempt = responses.attempts.find((attempt) => { + return attemptId == attempt.id; + }); + + if (attempt) { + return attempt; + } + + attempt = responses.anonattempts.find((attempt) => { + return attemptId == attempt.id; + }); + + if (attempt) { + return attempt; + } + + if (previous.anonAttemptsLoaded < responses.totalanonattempts) { + previous.anonAttemptsLoaded += responses.anonattempts.length; + } + + if (previous.attemptsLoaded < responses.totalattempts) { + previous.attemptsLoaded += responses.attempts.length; + } + + if (previous.anonAttemptsLoaded < responses.totalanonattempts || previous.attemptsLoaded < responses.totalattempts) { + // Can load more. Check there. + previous.page++; + + return this.getAttempt(feedbackId, attemptId, siteId, previous); + } + + // Not found and all loaded. Reject. + return Promise.reject(null); + }); + } + /** * Get prefix cache key for feedback completion data WS calls. * diff --git a/src/addon/mod/feedback/providers/show-entries-link-handler.ts b/src/addon/mod/feedback/providers/show-entries-link-handler.ts new file mode 100644 index 000000000..74e61ff5e --- /dev/null +++ b/src/addon/mod/feedback/providers/show-entries-link-handler.ts @@ -0,0 +1,109 @@ +// (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 { Injectable } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonModFeedbackProvider } from './feedback'; +import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; + +/** + * Content links handler for feedback show entries questions. + * Match mod/feedback/show_entries.php with a valid feedback id. + */ +@Injectable() +export class AddonModFeedbackShowEntriesLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonModFeedbackShowEntriesLinkHandler'; + featureName = '$mmCourseDelegate_mmaModFeedback'; + pattern = /\/mod\/feedback\/show_entries\.php.*([\?\&](id|showcompleted)=\d+)/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private feedbackProvider: AddonModFeedbackProvider, + private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + return [{ + action: (siteId, navCtrl?): void => { + const modal = this.domUtils.showModalLoading(), + moduleId = params.id; + + this.courseProvider.getModuleBasicInfo(moduleId, siteId).then((module) => { + let stateParams; + + if (typeof params.showcompleted == 'undefined') { + // Param showcompleted not defined. Show entry list. + stateParams = { + moduleId: module.id, + module: module, + courseId: module.course + }; + + return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackRespondentsPage', stateParams, siteId); + } + + return this.feedbackProvider.getAttempt(module.instance, params.showcompleted, siteId).then((attempt) => { + stateParams = { + moduleId: module.id, + attempt: attempt, + attemptId: attempt.id, + feedbackId: module.instance + }; + + return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackAttemptPage', stateParams, siteId); + }); + }).finally(() => { + modal.dismiss(); + }); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + return this.feedbackProvider.isPluginEnabled(siteId).then((enabled) => { + if (!enabled) { + return false; + } + + if (typeof params.id == 'undefined') { + // Cannot treat the URL. + return false; + } + + return true; + }); + } +} diff --git a/src/addon/mod/feedback/providers/show-non-respondents-link-handler.ts b/src/addon/mod/feedback/providers/show-non-respondents-link-handler.ts new file mode 100644 index 000000000..5d1ab4cb3 --- /dev/null +++ b/src/addon/mod/feedback/providers/show-non-respondents-link-handler.ts @@ -0,0 +1,93 @@ +// (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 { Injectable } from '@angular/core'; +import { CoreContentLinksHandlerBase } from '@core/contentlinks/classes/base-handler'; +import { CoreContentLinksAction } from '@core/contentlinks/providers/delegate'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; +import { AddonModFeedbackProvider } from './feedback'; +import { CoreCourseProvider } from '@core/course/providers/course'; +import { CoreDomUtilsProvider } from '@providers/utils/dom'; + +/** + * Content links handler for feedback show non respondents. + * Match mod/feedback/show_nonrespondents.php with a valid feedback id. + */ +@Injectable() +export class AddonModFeedbackShowNonRespondentsLinkHandler extends CoreContentLinksHandlerBase { + name = 'AddonModFeedbackShowNonRespondentsLinkHandler'; + featureName = '$mmCourseDelegate_mmaModFeedback'; + pattern = /\/mod\/feedback\/show_nonrespondents\.php.*([\?\&](id)=\d+)/; + + constructor(private linkHelper: CoreContentLinksHelperProvider, private feedbackProvider: AddonModFeedbackProvider, + private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider) { + super(); + } + + /** + * Get the list of actions for a link (url). + * + * @param {string[]} siteIds List of sites the URL belongs to. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {CoreContentLinksAction[]|Promise} List of (or promise resolved with list of) actions. + */ + getActions(siteIds: string[], url: string, params: any, courseId?: number): + CoreContentLinksAction[] | Promise { + return [{ + action: (siteId, navCtrl?): void => { + const modal = this.domUtils.showModalLoading(), + moduleId = params.id; + + this.courseProvider.getModuleBasicInfo(moduleId, siteId).then((module) => { + const stateParams = { + module: module, + moduleId: module.id, + courseId: module.course + }; + + return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackNonRespondentsPage', stateParams, siteId); + }).finally(() => { + modal.dismiss(); + }); + } + }]; + } + + /** + * Check if the handler is enabled for a certain site (site + user) and a URL. + * If not defined, defaults to true. + * + * @param {string} siteId The site ID. + * @param {string} url The URL to treat. + * @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1} + * @param {number} [courseId] Course ID related to the URL. Optional but recommended. + * @return {boolean|Promise} Whether the handler is enabled for the URL and site. + */ + isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise { + return this.feedbackProvider.isPluginEnabled(siteId).then((enabled) => { + if (!enabled) { + return false; + } + + if (typeof params.id == 'undefined') { + // Cannot treat the URL. + return false; + } + + return true; + }); + } +}