diff --git a/scripts/langindex.json b/scripts/langindex.json index fc60c508f..fd18b45de 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1520,6 +1520,7 @@ "core.confirmloss": "local_moodlemobileapp", "core.confirmopeninbrowser": "local_moodlemobileapp", "core.considereddigitalminor": "moodle", + "core.contactsupport": "local_moodlemobileapp", "core.content": "moodle", "core.contenteditingsynced": "local_moodlemobileapp", "core.contentlinks.chooseaccount": "local_moodlemobileapp", diff --git a/src/core/classes/errors/siteerror.ts b/src/core/classes/errors/siteerror.ts index a459a0257..57ab96d42 100644 --- a/src/core/classes/errors/siteerror.ts +++ b/src/core/classes/errors/siteerror.ts @@ -13,6 +13,8 @@ // limitations under the License. import { CoreError } from '@classes/errors/error'; +import { CoreSitePublicConfigResponse } from '@classes/site'; +import { CoreUserSupport } from '@features/user/services/support'; /** * Error returned when performing operations regarding a site (check if it exists, authenticate user, etc.). @@ -22,20 +24,52 @@ export class CoreSiteError extends CoreError { errorcode?: string; critical?: boolean; loggedOut?: boolean; + contactSupport?: boolean; + siteConfig?: CoreSitePublicConfigResponse; - constructor(protected error: SiteError) { - super(error.message); + constructor(options: CoreSiteErrorOptions) { + super(options.message); - this.errorcode = error.errorcode; - this.critical = error.critical; - this.loggedOut = error.loggedOut; + this.errorcode = options.errorcode; + this.critical = options.critical; + this.loggedOut = options.loggedOut; + this.contactSupport = options.contactSupport; + this.siteConfig = options.siteConfig; + } + + /** + * Get a url to contact site support. + * + * @returns Support page url. + */ + getSupportPageUrl(): string { + if (!this.siteConfig) { + throw new CoreError('Can\'t get support page url'); + } + + return CoreUserSupport.getSupportPageUrl(this.siteConfig); + } + + /** + * Check whether the handling of this error allows users to contact support or not. + * + * @returns Whether to contact support or not. + */ + canContactSupport(): boolean { + if (!this.contactSupport || !this.siteConfig) { + return false; + } + + return CoreUserSupport.canContactSupport(this.siteConfig); } } -export type SiteError = { +export type CoreSiteErrorOptions = { message: string; errorcode?: string; critical?: boolean; // Whether the error is important enough to abort the operation. loggedOut?: boolean; // Whether site has been marked as logged out. + contactSupport?: boolean; + siteConfig?: CoreSitePublicConfigResponse; }; diff --git a/src/core/features/login/pages/site/site.ts b/src/core/features/login/pages/site/site.ts index 9d900b2f2..5d26319d4 100644 --- a/src/core/features/login/pages/site/site.ts +++ b/src/core/features/login/pages/site/site.ts @@ -40,6 +40,8 @@ import { CoreCustomURLSchemes, CoreCustomURLSchemesHandleError } from '@services import { CoreTextUtils } from '@services/utils/text'; import { CoreForms } from '@singletons/form'; import { AlertButton } from '@ionic/core'; +import { CoreSiteError } from '@classes/errors/siteerror'; +import { CoreUserSupport } from '@features/user/services/support'; /** * Site (url) chooser when adding a new site. @@ -382,6 +384,13 @@ export class CoreLoginSitePage implements OnInit { */ protected showLoginIssue(url: string | null, error: CoreError): void { let errorMessage = CoreDomUtils.getErrorMessage(error); + let siteExists = false; + let supportPageUrl: string | null = null; + + if (error instanceof CoreSiteError) { + siteExists = !!error.siteConfig; + supportPageUrl = error.canContactSupport() ? error.getSupportPageUrl() : null; + } if (errorMessage == Translate.instant('core.cannotconnecttrouble')) { const found = this.sites.find((site) => site.url == url); @@ -392,19 +401,25 @@ export class CoreLoginSitePage implements OnInit { } let message = '

' + errorMessage + '

'; - if (url) { + if (!siteExists && url) { const fullUrl = CoreUrlUtils.isAbsoluteURL(url) ? url : 'https://' + url; message += '

' + url + '

'; } const buttons: AlertButton[] = [ - { - text: Translate.instant('core.needhelp'), - cssClass: 'core-login-need-help', - handler: (): void => { - this.showHelp(); + supportPageUrl + ? { + text: Translate.instant('core.contactsupport'), + handler: () => CoreUserSupport.contact({ + supportPageUrl, + subject: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }), + }), + } + : { + text: Translate.instant('core.needhelp'), + cssClass: 'core-login-need-help', + handler: () => this.showHelp(), }, - }, { text: Translate.instant('core.tryagain'), role: 'cancel', diff --git a/src/core/lang.json b/src/core/lang.json index 4a6262737..94aff25d5 100644 --- a/src/core/lang.json +++ b/src/core/lang.json @@ -54,6 +54,7 @@ "confirmloss": "Are you sure? All changes will be lost.", "confirmopeninbrowser": "Do you want to open it in a web browser?", "considereddigitalminor": "You are too young to create an account on this site.", + "contactsupport": "Contact support", "content": "Content", "contenteditingsynced": "The content you are editing has been synced.", "continue": "Continue", diff --git a/src/core/services/sites.ts b/src/core/services/sites.ts index c6d56dffd..d9dd0a655 100644 --- a/src/core/services/sites.ts +++ b/src/core/services/sites.ts @@ -299,11 +299,15 @@ export class CoreSitesProvider { throw new CoreSiteError({ message: Translate.instant('core.login.webservicesnotenabled'), critical: true, + contactSupport: true, + siteConfig: config, }); } else if (!config.enablemobilewebservice) { throw new CoreSiteError({ message: Translate.instant('core.login.mobileservicesnotenabled'), critical: true, + contactSupport: true, + siteConfig: config, }); } else if (config.maintenanceenabled) { let message = Translate.instant('core.sitemaintenance');