MOBILE-4059 core: Update cannot connect messages
parent
c4952133f1
commit
e1035e9a4b
|
@ -1471,9 +1471,6 @@
|
|||
"core.calculating": "local_moodlemobileapp",
|
||||
"core.cancel": "moodle",
|
||||
"core.cannotconnect": "local_moodlemobileapp",
|
||||
"core.cannotconnecttrouble": "local_moodlemobileapp",
|
||||
"core.cannotconnecttroublewithoutsupport": "local_moodlemobileapp",
|
||||
"core.cannotconnectverify": "local_moodlemobileapp",
|
||||
"core.cannotdownloadfiles": "local_moodlemobileapp",
|
||||
"core.cannotinstallapk": "local_moodlemobileapp",
|
||||
"core.cannotlogoutpageblocks": "local_moodlemobileapp",
|
||||
|
@ -1520,6 +1517,7 @@
|
|||
"core.confirmleaveunknownchanges": "local_moodlemobileapp",
|
||||
"core.confirmloss": "local_moodlemobileapp",
|
||||
"core.confirmopeninbrowser": "local_moodlemobileapp",
|
||||
"core.connectionlost": "local_moodlemobileapp",
|
||||
"core.considereddigitalminor": "moodle",
|
||||
"core.contactsupport": "local_moodlemobileapp",
|
||||
"core.content": "moodle",
|
||||
|
@ -2273,6 +2271,9 @@
|
|||
"core.sitehome.sitehome": "moodle",
|
||||
"core.sitehome.sitenews": "moodle",
|
||||
"core.sitemaintenance": "admin",
|
||||
"core.sitenotfound": "local_moodlemobileapp",
|
||||
"core.sitenotfoundhelp": "local_moodlemobileapp",
|
||||
"core.siteunavailablehelp": "local_moodlemobileapp",
|
||||
"core.size": "moodle",
|
||||
"core.sizeb": "moodle",
|
||||
"core.sizegb": "moodle",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreCourseActivitySyncBaseProvider } from '@features/course/classes/activity-sync';
|
||||
import { CoreCourse, CoreCourseModuleBasicInfo } from '@features/course/services/course';
|
||||
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
||||
|
@ -313,7 +314,7 @@ export class AddonModQuizSyncProvider extends CoreCourseActivitySyncBaseProvider
|
|||
|
||||
if (!CoreNetwork.isOnline()) {
|
||||
// Cannot sync in offline.
|
||||
throw new CoreError(Translate.instant('core.cannotconnect'));
|
||||
throw new CoreError(Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }));
|
||||
}
|
||||
|
||||
const offlineAttempt = offlineAttempts.pop()!;
|
||||
|
|
|
@ -19,12 +19,14 @@ import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror';
|
|||
*/
|
||||
export class CoreLoginError extends CoreSiteError {
|
||||
|
||||
title?: string;
|
||||
critical?: boolean;
|
||||
loggedOut?: boolean;
|
||||
|
||||
constructor(options: CoreLoginErrorOptions) {
|
||||
super(options);
|
||||
|
||||
this.title = options.title;
|
||||
this.critical = options.critical;
|
||||
this.loggedOut = options.loggedOut;
|
||||
}
|
||||
|
@ -32,6 +34,7 @@ export class CoreLoginError extends CoreSiteError {
|
|||
}
|
||||
|
||||
export type CoreLoginErrorOptions = CoreSiteErrorOptions & {
|
||||
title?: string; // Error title.
|
||||
critical?: boolean; // Whether the error is important enough to abort the operation.
|
||||
loggedOut?: boolean; // Whether site has been marked as logged out.
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ export class CoreSiteError extends CoreError {
|
|||
supportConfig?: CoreUserSupportConfig;
|
||||
|
||||
constructor(options: CoreSiteErrorOptions) {
|
||||
super(getErrorMessage(options));
|
||||
super(options.message);
|
||||
|
||||
this.errorcode = options.errorcode;
|
||||
this.errorDetails = options.errorDetails;
|
||||
|
@ -34,23 +34,8 @@ export class CoreSiteError extends CoreError {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message to use in the error.
|
||||
*
|
||||
* @param options Error options.
|
||||
* @returns Error message.
|
||||
*/
|
||||
function getErrorMessage(options: CoreSiteErrorOptions): string {
|
||||
if ('supportConfig' in options && !options.supportConfig?.canContactSupport()) {
|
||||
return options.fallbackMessage ?? options.message;
|
||||
}
|
||||
|
||||
return options.message;
|
||||
}
|
||||
|
||||
export type CoreSiteErrorOptions = {
|
||||
message: string;
|
||||
fallbackMessage?: string; // Message to use when contacting support is not possible but warranted.
|
||||
errorcode?: string; // Technical error code useful for technical assistance.
|
||||
errorDetails?: string; // Technical error details useful for technical assistance.
|
||||
|
||||
|
|
|
@ -810,9 +810,7 @@ export class CoreSite {
|
|||
): Promise<T> {
|
||||
if (preSets.forceOffline) {
|
||||
// Don't call the WS, just fail.
|
||||
throw new CoreError(
|
||||
Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }),
|
||||
);
|
||||
throw new CoreError(Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }));
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -1134,8 +1132,7 @@ export class CoreSite {
|
|||
if (!data || !data.responses) {
|
||||
throw new CoreSiteError({
|
||||
supportConfig: new CoreUserAuthenticatedSupportConfig(this),
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
message: Translate.instant('core.siteunavailablehelp', { site: this.siteUrl }),
|
||||
errorcode: 'invalidresponse',
|
||||
errorDetails: Translate.instant('core.errorinvalidresponse', { method: 'tool_mobile_call_external_functions' }),
|
||||
});
|
||||
|
@ -1726,9 +1723,7 @@ export class CoreSite {
|
|||
.catch(async () => {
|
||||
if (cachePreSets.forceOffline) {
|
||||
// Don't call the WS, just fail.
|
||||
throw new CoreError(
|
||||
Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }),
|
||||
);
|
||||
throw new CoreError(Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }));
|
||||
}
|
||||
|
||||
// Call the WS.
|
||||
|
|
|
@ -27,7 +27,6 @@ import {
|
|||
CoreLoginSiteFinderSettings,
|
||||
CoreLoginSiteSelectorListMethod,
|
||||
} from '@features/login/services/login-helper';
|
||||
import { CoreSite } from '@classes/site';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
import { Translate } from '@singletons';
|
||||
|
@ -45,6 +44,8 @@ import { CoreUserSupport } from '@features/user/services/support';
|
|||
import { CoreErrorInfoComponent } from '@components/error-info/error-info';
|
||||
import { CoreUserSupportConfig } from '@features/user/classes/support/support-config';
|
||||
import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
|
||||
import { CoreLoginError } from '@classes/errors/loginerror';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Site (url) chooser when adding a new site.
|
||||
|
@ -389,6 +390,7 @@ export class CoreLoginSitePage implements OnInit {
|
|||
let errorMessage = CoreDomUtils.getErrorMessage(error);
|
||||
let siteExists = false;
|
||||
let supportConfig: CoreUserSupportConfig | undefined = undefined;
|
||||
let errorTitle: string | undefined;
|
||||
let errorDetails: string | undefined;
|
||||
let errorCode: string | undefined;
|
||||
|
||||
|
@ -399,32 +401,21 @@ export class CoreLoginSitePage implements OnInit {
|
|||
siteExists = supportConfig instanceof CoreUserGuestSupportConfig;
|
||||
}
|
||||
|
||||
if (
|
||||
!siteExists && (
|
||||
errorMessage === Translate.instant('core.cannotconnecttrouble') ||
|
||||
errorMessage === Translate.instant('core.cannotconnecttroublewithoutsupport')
|
||||
)
|
||||
) {
|
||||
const found = this.sites.find((site) => site.url == url);
|
||||
|
||||
if (!found) {
|
||||
errorMessage += ' ' + Translate.instant('core.cannotconnectverify');
|
||||
}
|
||||
}
|
||||
|
||||
errorMessage = '<p>' + errorMessage + '</p>';
|
||||
if (!siteExists && url) {
|
||||
const fullUrl = CoreUrlUtils.isAbsoluteURL(url) ? url : 'https://' + url;
|
||||
errorMessage += '<p padding><a href="' + fullUrl + '" core-link>' + url + '</a></p>';
|
||||
if (error instanceof CoreLoginError) {
|
||||
errorTitle = error.title;
|
||||
}
|
||||
|
||||
if (errorDetails) {
|
||||
errorMessage += '<div class="core-error-info-container"></div>';
|
||||
errorMessage = `<p>${errorMessage}</p><div class="core-error-info-container"></div>`;
|
||||
}
|
||||
|
||||
const alertSupportConfig = supportConfig;
|
||||
const buttons: AlertButton[] = [
|
||||
alertSupportConfig
|
||||
const buttons = [
|
||||
{
|
||||
text: Translate.instant('core.tryagain'),
|
||||
role: 'cancel',
|
||||
},
|
||||
alertSupportConfig?.canContactSupport()
|
||||
? {
|
||||
text: Translate.instant('core.contactsupport'),
|
||||
handler: () => CoreUserSupport.contact({
|
||||
|
@ -433,22 +424,26 @@ export class CoreLoginSitePage implements OnInit {
|
|||
message: `Error: ${errorCode}\n\n${errorDetails}`,
|
||||
}),
|
||||
}
|
||||
: {
|
||||
text: Translate.instant('core.needhelp'),
|
||||
cssClass: 'core-login-need-help',
|
||||
handler: () => this.showHelp(),
|
||||
},
|
||||
{
|
||||
text: Translate.instant('core.tryagain'),
|
||||
role: 'cancel',
|
||||
},
|
||||
];
|
||||
: (
|
||||
!siteExists
|
||||
? {
|
||||
text: Translate.instant('core.needhelp'),
|
||||
cssClass: 'core-login-need-help',
|
||||
handler: () => this.showHelp(),
|
||||
}
|
||||
: null
|
||||
),
|
||||
].filter(button => !!button);
|
||||
|
||||
// @TODO: Remove CoreSite.MINIMUM_MOODLE_VERSION, not used on translations since 3.9.0.
|
||||
const alertElement = await CoreDomUtils.showAlertWithOptions({
|
||||
header: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }),
|
||||
message: errorMessage,
|
||||
buttons,
|
||||
header: errorTitle ?? (
|
||||
siteExists
|
||||
? Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION })
|
||||
: Translate.instant('core.sitenotfound')
|
||||
),
|
||||
message: errorMessage ?? Translate.instant('core.sitenotfoundhelp'),
|
||||
buttons: buttons as AlertButton[],
|
||||
});
|
||||
|
||||
if (errorDetails) {
|
||||
|
|
|
@ -39,14 +39,10 @@ Feature: Test basic usage of login in app
|
|||
But I should not find "Log in" in the app
|
||||
|
||||
Scenario: Add a non existing account
|
||||
When I enter the app
|
||||
And I log in as "student1"
|
||||
When I log out in the app
|
||||
And I press "Add" in the app
|
||||
And I set the field "Your site" to "Wrong Site Address" in the app
|
||||
And I press enter in the app
|
||||
Then I should find "Cannot connect" in the app
|
||||
And I should find "Wrong Site Address" in the app
|
||||
When I launch the app
|
||||
And I set the field "Your site" to "wrongsiteaddress" in the app
|
||||
And I press "Connect to your site" in the app
|
||||
Then I should find "Site not found" in the app
|
||||
|
||||
Scenario: Add a non existing account from accounts switcher
|
||||
When I enter the app
|
||||
|
@ -55,10 +51,9 @@ Feature: Test basic usage of login in app
|
|||
And I press "Switch account" in the app
|
||||
And I press "Add" in the app
|
||||
And I wait the app to restart
|
||||
And I set the field "Your site" to "Wrong Site Address" in the app
|
||||
And I press enter in the app
|
||||
Then I should find "Cannot connect" in the app
|
||||
And I should find "Wrong Site Address" in the app
|
||||
And I set the field "Your site" to "wrongsiteaddress" in the app
|
||||
And I press "Connect to your site" in the app
|
||||
Then I should find "Site not found" in the app
|
||||
|
||||
Scenario: Log out from the app
|
||||
Given I entered the app as "student1"
|
||||
|
|
|
@ -53,10 +53,7 @@ export default function(): void {
|
|||
supportConfig: CoreSites.getCurrentSite()
|
||||
? CoreUserAuthenticatedSupportConfig.forCurrentSite()
|
||||
: new CoreUserNullSupportConfig(),
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
errorcode: 'invalidurlscheme',
|
||||
errorDetails: Translate.instant('core.errorurlschemeinvalidscheme', { $a: urlScheme }),
|
||||
message: Translate.instant('core.errorurlschemeinvalidscheme', { $a: urlScheme }),
|
||||
}));
|
||||
|
||||
return;
|
||||
|
|
|
@ -14,10 +14,7 @@
|
|||
"browser": "Browser",
|
||||
"calculating": "Calculating",
|
||||
"cancel": "Cancel",
|
||||
"cannotconnect": "Cannot connect",
|
||||
"cannotconnecttrouble": "We're having trouble connecting to your site.",
|
||||
"cannotconnecttroublewithoutsupport": "We're having trouble connecting to your site, please contact your institution.",
|
||||
"cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
||||
"cannotconnect": "Can't connect to site",
|
||||
"cannotdownloadfiles": "This institution has disabled downloading files.",
|
||||
"cannotinstallapk": "For security reasons, you can't install unknown apps on your device from this app. Please open the file using a browser.",
|
||||
"cannotlogoutpageblocks": "Please save or discard your changes before continuing.",
|
||||
|
@ -54,6 +51,7 @@
|
|||
"confirmleaveunknownchanges": "Are you sure you want to leave this page? If you have unsaved changes they will be lost.",
|
||||
"confirmloss": "Are you sure? All changes will be lost.",
|
||||
"confirmopeninbrowser": "Do you want to open it in a web browser?",
|
||||
"connectionlost": "Connection to site lost",
|
||||
"considereddigitalminor": "You are too young to create an account on this site.",
|
||||
"contactsupport": "Contact support",
|
||||
"content": "Content",
|
||||
|
@ -282,6 +280,9 @@
|
|||
"showmore": "Show more...",
|
||||
"site": "Site",
|
||||
"sitemaintenance": "The site is undergoing maintenance and is currently not available",
|
||||
"sitenotfound": "Site not found",
|
||||
"sitenotfoundhelp": "We can't find the site you entered. Please check for typos or try again later. If you keep seeing this message, contact your school or learning provider.",
|
||||
"siteunavailablehelp": "The site \"{{site}}\" is not available right now. Please try again later or contact your school or learning provider.",
|
||||
"size": "Size",
|
||||
"sizeb": "bytes",
|
||||
"sizegb": "GB",
|
||||
|
|
|
@ -55,6 +55,7 @@ import { lazyMap, LazyMap } from '../utils/lazy-map';
|
|||
import { asyncInstance, AsyncInstance } from '../utils/async-instance';
|
||||
import { CoreText } from '@singletons/text';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/*
|
||||
* Factory for handling downloading files and retrieve downloaded files.
|
||||
|
@ -509,7 +510,7 @@ export class CoreFilepoolProvider {
|
|||
} else {
|
||||
if (!CoreNetwork.isOnline()) {
|
||||
// Cannot check size in offline, stop.
|
||||
throw new CoreError(Translate.instant('core.cannotconnect'));
|
||||
throw new CoreError(Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }));
|
||||
}
|
||||
|
||||
size = await CoreWS.getRemoteFileSize(fileUrl);
|
||||
|
|
|
@ -246,7 +246,7 @@ export class CoreSitesProvider {
|
|||
} else if (CoreTextUtils.getErrorMessageFromError(secondError)) {
|
||||
throw secondError;
|
||||
} else {
|
||||
throw new CoreError(Translate.instant('core.cannotconnecttrouble'));
|
||||
throw new CoreError(Translate.instant('core.sitenotfoundhelp'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,14 +297,14 @@ export class CoreSitesProvider {
|
|||
|
||||
// Check that the user can authenticate.
|
||||
if (!config.enablewebservices) {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(config.httpswwwroot || config.wwwroot, {
|
||||
supportConfig: new CoreUserGuestSupportConfig(config),
|
||||
errorcode: 'webservicesnotenabled',
|
||||
errorDetails: Translate.instant('core.login.webservicesnotenabled'),
|
||||
critical: true,
|
||||
});
|
||||
} else if (!config.enablemobilewebservice) {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(config.httpswwwroot || config.wwwroot, {
|
||||
supportConfig: new CoreUserGuestSupportConfig(config),
|
||||
errorcode: 'mobileservicesnotenabled',
|
||||
errorDetails: Translate.instant('core.login.mobileservicesnotenabled'),
|
||||
|
@ -333,11 +333,12 @@ export class CoreSitesProvider {
|
|||
* @param options Error options.
|
||||
* @return Cannot connect error.
|
||||
*/
|
||||
protected createCannotConnectLoginError(options?: Partial<CoreLoginErrorOptions>): CoreLoginError {
|
||||
protected createCannotConnectLoginError(siteUrl: string | null, options?: Partial<CoreLoginErrorOptions>): CoreLoginError {
|
||||
return new CoreLoginError({
|
||||
...options,
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
message: !this.isLoggedIn() && siteUrl === null
|
||||
? Translate.instant('core.sitenotfoundhelp')
|
||||
: Translate.instant('core.siteunavailablehelp', { site: siteUrl ?? this.currentSite?.siteUrl }),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -355,7 +356,10 @@ export class CoreSitesProvider {
|
|||
if (error instanceof CoreAjaxError || !('errorcode' in error)) {
|
||||
// The WS didn't return data, probably cannot connect.
|
||||
return new CoreLoginError({
|
||||
message: error.message || '',
|
||||
title: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }),
|
||||
message: Translate.instant('core.siteunavailablehelp', { site: siteUrl }),
|
||||
errorcode: 'publicconfigfailed',
|
||||
errorDetails: error.message || '',
|
||||
critical: false, // Allow fallback to http if siteUrl uses https.
|
||||
});
|
||||
}
|
||||
|
@ -363,30 +367,27 @@ export class CoreSitesProvider {
|
|||
// Service supported but an error happened. Return error.
|
||||
const options: CoreLoginErrorOptions = {
|
||||
critical: true,
|
||||
message: error.message,
|
||||
title: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION }),
|
||||
message: Translate.instant('core.siteunavailablehelp', { site: siteUrl }),
|
||||
errorcode: error.errorcode,
|
||||
supportConfig: error.supportConfig,
|
||||
errorDetails: error.errorDetails,
|
||||
errorDetails: error.errorDetails ?? error.message,
|
||||
};
|
||||
|
||||
if (error.errorcode === 'codingerror') {
|
||||
// This could be caused by a redirect. Check if it's the case.
|
||||
const redirect = await CoreUtils.checkRedirect(siteUrl);
|
||||
|
||||
options.message = Translate.instant('core.siteunavailablehelp', { site: siteUrl });
|
||||
|
||||
if (redirect) {
|
||||
options.message = Translate.instant('core.cannotconnecttrouble');
|
||||
options.fallbackMessage = Translate.instant('core.cannotconnecttroublewithoutsupport');
|
||||
options.errorcode = 'sitehasredirect';
|
||||
options.errorDetails = Translate.instant('core.login.sitehasredirect');
|
||||
options.critical = false; // Keep checking fallback URLs.
|
||||
} else {
|
||||
// We can't be sure if there is a redirect or not. Display cannot connect error.
|
||||
options.message = Translate.instant('core.cannotconnecttrouble');
|
||||
}
|
||||
} else if (error.errorcode === 'invalidrecord') {
|
||||
// WebService not found, site not supported.
|
||||
options.message = Translate.instant('core.cannotconnecttrouble');
|
||||
options.fallbackMessage = Translate.instant('core.cannotconnecttroublewithoutsupport');
|
||||
options.message = Translate.instant('core.siteunavailablehelp', { site: siteUrl });
|
||||
options.errorcode = 'invalidmoodleversion';
|
||||
options.errorDetails = Translate.instant('core.login.invalidmoodleversion', { $a: CoreSite.MINIMUM_MOODLE_VERSION });
|
||||
} else if (error.errorcode === 'redirecterrordetected') {
|
||||
|
@ -413,7 +414,7 @@ export class CoreSitesProvider {
|
|||
data = await Http.post(siteUrl + '/login/token.php', { appsitecheck: 1 }).pipe(timeout(CoreWS.getRequestTimeout()))
|
||||
.toPromise();
|
||||
} catch (error) {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(null, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
errorcode: 'sitecheckfailed',
|
||||
errorDetails: CoreDomUtils.getErrorMessage(error) ?? undefined,
|
||||
|
@ -422,7 +423,7 @@ export class CoreSitesProvider {
|
|||
|
||||
if (data === null) {
|
||||
// Cannot connect.
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(null, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
errorcode: 'appsitecheckfailed',
|
||||
errorDetails: 'A request to /login/token.php with appsitecheck=1 returned an empty response',
|
||||
|
@ -430,7 +431,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(siteUrl, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
critical: data.errorcode == 'enablewsdescription',
|
||||
errorcode: data.errorcode,
|
||||
|
@ -439,7 +440,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
|
||||
if (data.error && data.error == 'Web services must be enabled in Advanced features.') {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(siteUrl, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
critical: true,
|
||||
errorcode: 'enablewsdescription',
|
||||
|
@ -483,11 +484,19 @@ export class CoreSitesProvider {
|
|||
try {
|
||||
data = await Http.post(loginUrl, params).pipe(timeout(CoreWS.getRequestTimeout())).toPromise();
|
||||
} catch (error) {
|
||||
throw new CoreError(Translate.instant('core.cannotconnecttrouble'));
|
||||
throw new CoreError(
|
||||
this.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: this.currentSite?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp'),
|
||||
);
|
||||
}
|
||||
|
||||
if (data === undefined) {
|
||||
throw new CoreError(Translate.instant('core.cannotconnecttrouble'));
|
||||
throw new CoreError(
|
||||
this.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: this.currentSite?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp'),
|
||||
);
|
||||
} else {
|
||||
if (data.token !== undefined) {
|
||||
return { token: data.token, siteUrl, privateToken: data.privatetoken };
|
||||
|
@ -503,7 +512,7 @@ export class CoreSitesProvider {
|
|||
const redirect = await CoreUtils.checkRedirect(loginUrl);
|
||||
|
||||
if (redirect) {
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(siteUrl, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
errorcode: 'sitehasredirect',
|
||||
errorDetails: Translate.instant('core.login.sitehasredirect'),
|
||||
|
@ -511,7 +520,7 @@ export class CoreSitesProvider {
|
|||
}
|
||||
}
|
||||
|
||||
throw this.createCannotConnectLoginError({
|
||||
throw this.createCannotConnectLoginError(siteUrl, {
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
errorcode: data.errorcode,
|
||||
errorDetails: data.error,
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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 { CoreDomUtilsProvider } from '@services/utils/dom';
|
||||
import { AlertController, Translate } from '@singletons';
|
||||
|
||||
import { mock, mockSingleton, mockTranslate } from '@/testing/utils';
|
||||
import { CoreSiteError } from '@classes/errors/siteerror';
|
||||
import { CoreSites } from '@services/sites';
|
||||
|
||||
describe('CoreDomUtilsProvider', () => {
|
||||
|
||||
let domUtils: CoreDomUtilsProvider;
|
||||
|
||||
beforeEach(() => {
|
||||
domUtils = new CoreDomUtilsProvider();
|
||||
});
|
||||
|
||||
it('shows site unavailable errors', async () => {
|
||||
// Arrange.
|
||||
mockTranslate({
|
||||
'core.siteunavailablehelp': 'The site "{{site}}" is not available right now.',
|
||||
});
|
||||
|
||||
const message = Translate.instant('core.siteunavailablehelp', { site: 'https://campus.example.edu' });
|
||||
const mockAlert = mock<HTMLIonAlertElement>({
|
||||
present: () => Promise.resolve(),
|
||||
onDidDismiss: async <T>() => new Promise<T>(() => {
|
||||
// Never resolve.
|
||||
}),
|
||||
});
|
||||
|
||||
mockSingleton(AlertController, mock({ create: () => Promise.resolve(mockAlert) }));
|
||||
mockSingleton(CoreSites, mock({ isLoggedIn: () => true }));
|
||||
|
||||
// Act.
|
||||
await domUtils.showErrorModal(new CoreSiteError({ message }));
|
||||
|
||||
// Assert.
|
||||
expect(mockAlert.present).toHaveBeenCalled();
|
||||
expect(AlertController.create).toHaveBeenCalledWith({
|
||||
message,
|
||||
header: Translate.instant('core.connectionlost'),
|
||||
buttons: [Translate.instant('core.ok')],
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -57,6 +57,7 @@ import { CoreNetwork } from '@services/network';
|
|||
import { CoreSiteError } from '@classes/errors/siteerror';
|
||||
import { CoreUserSupport } from '@features/user/services/support';
|
||||
import { CoreErrorInfoComponent } from '@components/error-info/error-info';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/*
|
||||
* "Utils" service with helper functions for UI, DOM elements and HTML code.
|
||||
|
@ -576,6 +577,20 @@ export class CoreDomUtilsProvider {
|
|||
error instanceof CoreNetworkError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a message, check if it's a site unavailable error.
|
||||
*
|
||||
* @param message Message text.
|
||||
* @returns Whether the message is a site unavailable error.
|
||||
*/
|
||||
protected isSiteUnavailableError(message: string): boolean {
|
||||
let siteUnavailableMessage = Translate.instant('core.siteunavailablehelp', { site: 'SITEURLPLACEHOLDER' });
|
||||
siteUnavailableMessage = CoreTextUtils.escapeForRegex(siteUnavailableMessage);
|
||||
siteUnavailableMessage = siteUnavailableMessage.replace('SITEURLPLACEHOLDER', '.*');
|
||||
|
||||
return new RegExp(siteUnavailableMessage).test(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the error message from an error, including debug data if needed.
|
||||
*
|
||||
|
@ -1345,14 +1360,20 @@ export class CoreDomUtilsProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
const alertOptions: AlertOptions = {
|
||||
message: message,
|
||||
};
|
||||
const alertOptions: AlertOptions = { message };
|
||||
|
||||
if (this.isNetworkError(message, error)) {
|
||||
alertOptions.cssClass = 'core-alert-network-error';
|
||||
} else if (typeof error !== 'string' && 'title' in error) {
|
||||
}
|
||||
|
||||
if (typeof error !== 'string' && 'title' in error && error.title) {
|
||||
alertOptions.header = error.title || undefined;
|
||||
} else if (message === Translate.instant('core.sitenotfoundhelp')) {
|
||||
alertOptions.header = Translate.instant('core.sitenotfound');
|
||||
} else if (this.isSiteUnavailableError(message)) {
|
||||
alertOptions.header = CoreSites.isLoggedIn()
|
||||
? Translate.instant('core.connectionlost')
|
||||
: Translate.instant('core.cannotconnect', { $a: CoreSite.MINIMUM_MOODLE_VERSION });
|
||||
} else {
|
||||
alertOptions.header = Translate.instant('core.error');
|
||||
}
|
||||
|
@ -1360,13 +1381,14 @@ export class CoreDomUtilsProvider {
|
|||
if (typeof error !== 'string' && 'buttons' in error && typeof error.buttons !== 'undefined') {
|
||||
alertOptions.buttons = error.buttons;
|
||||
} else if (error instanceof CoreSiteError) {
|
||||
alertOptions.buttons = [];
|
||||
|
||||
if (error.errorDetails) {
|
||||
alertOptions.message += '<div class="core-error-info-container"></div>';
|
||||
alertOptions.message = `<p>${alertOptions.message}</p><div class="core-error-info-container"></div>`;
|
||||
}
|
||||
|
||||
const supportConfig = error.supportConfig;
|
||||
|
||||
alertOptions.buttons = [Translate.instant('core.ok')];
|
||||
|
||||
if (supportConfig?.canContactSupport()) {
|
||||
alertOptions.buttons.push({
|
||||
text: Translate.instant('core.contactsupport'),
|
||||
|
@ -1377,8 +1399,6 @@ export class CoreDomUtilsProvider {
|
|||
}),
|
||||
});
|
||||
}
|
||||
|
||||
alertOptions.buttons.push(Translate.instant('core.ok'));
|
||||
} else {
|
||||
alertOptions.buttons = [Translate.instant('core.ok')];
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import { CorePromisedValue } from '@classes/promised-value';
|
|||
import { CorePlatform } from '@services/platform';
|
||||
import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror';
|
||||
import { CoreUserGuestSupportConfig } from '@features/user/classes/support/guest-support-config';
|
||||
import { CoreSites } from '@services/sites';
|
||||
|
||||
/**
|
||||
* This service allows performing WS calls and download/upload files.
|
||||
|
@ -469,10 +470,13 @@ export class CoreWSProvider {
|
|||
|
||||
// Check if error. Ajax layer should always return an object (if error) or an array (if success).
|
||||
if (!data || typeof data != 'object') {
|
||||
const message = CoreSites.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: CoreSites.getCurrentSite()?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp');
|
||||
|
||||
throw new CoreAjaxError({
|
||||
message,
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(preSets.siteUrl),
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
errorcode: 'invalidresponse',
|
||||
errorDetails: Translate.instant('core.serverconnection', {
|
||||
details: Translate.instant('core.errorinvalidresponse', { method }),
|
||||
|
@ -491,10 +495,13 @@ export class CoreWSProvider {
|
|||
|
||||
return data.data;
|
||||
}, async (data: HttpErrorResponse) => {
|
||||
const message = CoreSites.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: CoreSites.getCurrentSite()?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp');
|
||||
|
||||
const options: CoreSiteErrorOptions = {
|
||||
message,
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(preSets.siteUrl),
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
};
|
||||
|
||||
switch (data.status) {
|
||||
|
@ -988,7 +995,9 @@ export class CoreWSProvider {
|
|||
*/
|
||||
protected createHttpError(error: CoreTextErrorObject, status: number): CoreHttpError {
|
||||
const message = CoreTextUtils.buildSeveralParagraphsMessage([
|
||||
Translate.instant('core.cannotconnecttrouble'),
|
||||
CoreSites.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: CoreSites.getCurrentSite()?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp'),
|
||||
CoreTextUtils.getHTMLBodyContent(CoreTextUtils.getErrorMessageFromError(error) || ''),
|
||||
]);
|
||||
|
||||
|
@ -1130,8 +1139,9 @@ export class CoreWSProvider {
|
|||
return new CoreSiteError({
|
||||
...options,
|
||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
||||
message: Translate.instant('core.cannotconnecttrouble'),
|
||||
fallbackMessage: Translate.instant('core.cannotconnecttroublewithoutsupport'),
|
||||
message: CoreSites.isLoggedIn()
|
||||
? Translate.instant('core.siteunavailablehelp', { site: CoreSites.getCurrentSite()?.siteUrl })
|
||||
: Translate.instant('core.sitenotfoundhelp'),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -392,8 +392,15 @@ export function wait(time: number): Promise<void> {
|
|||
*/
|
||||
export function mockTranslate(translations: Record<string, string> = {}): void {
|
||||
mockSingleton(Translate as CoreSingletonProxy<TranslateService>, {
|
||||
instant: (key) => Array.isArray(key)
|
||||
? key.map(k => translations[k] ?? k)
|
||||
: translations[key] ?? key,
|
||||
instant: (key, replacements) => {
|
||||
const applyReplacements = (text: string): string => Object.entries(replacements ?? {}).reduce(
|
||||
(text, [name, value]) => text.replace(`{{${name}}}`, value),
|
||||
text,
|
||||
);
|
||||
|
||||
return Array.isArray(key)
|
||||
? key.map(k => applyReplacements(translations[k] ?? k))
|
||||
: applyReplacements(translations[key] ?? key);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue