PLT-5702 Added special error page for private browsing error message (#5985)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
a0c91ef4af
Коммит
f7a4c75a21
@@ -2,14 +2,27 @@
|
|||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
import {Link} from 'react-router/es6';
|
import {Link} from 'react-router/es6';
|
||||||
|
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import {ErrorPageTypes} from 'utils/constants.jsx';
|
||||||
import * as TextFormatting from 'utils/text_formatting.jsx';
|
import * as TextFormatting from 'utils/text_formatting.jsx';
|
||||||
|
import * as Utils from 'utils/utils.jsx';
|
||||||
|
|
||||||
export default class ErrorPage extends React.Component {
|
export default class ErrorPage extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
location: React.PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.renderTitle = this.renderTitle.bind(this);
|
||||||
|
this.renderMessage = this.renderMessage.bind(this);
|
||||||
|
this.renderLink = this.renderLink.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
$('body').attr('class', 'sticky error');
|
$('body').attr('class', 'sticky error');
|
||||||
}
|
}
|
||||||
@@ -18,30 +31,97 @@ export default class ErrorPage extends React.Component {
|
|||||||
$('body').attr('class', '');
|
$('body').attr('class', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
linkFilter(link) {
|
||||||
let title = this.props.location.query.title;
|
return link.startsWith('https://docs.mattermost.com') || link.startsWith('https://forum.mattermost.org');
|
||||||
if (!title || title === '') {
|
}
|
||||||
title = Utils.localizeMessage('error.generic.title', 'Error');
|
|
||||||
|
renderTitle() {
|
||||||
|
if (this.props.location.query.type === ErrorPageTypes.LOCAL_STORAGE) {
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
id='error.local_storage.title'
|
||||||
|
defaultMessage='Cannot Load Mattermost'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.props.location.query.title) {
|
||||||
|
return this.props.location.query.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils.localizeMessage('error.generic.title', 'Error');
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessage() {
|
||||||
|
if (this.props.location.query.type === ErrorPageTypes.LOCAL_STORAGE) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<FormattedMessage
|
||||||
|
id='error.local_storage.message'
|
||||||
|
defaultMessage='Mattermost was unable to load because a setting in your browser prevents the use of its local storage features. To allow Mattermost to load, try the following actions:'
|
||||||
|
/>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<FormattedMessage
|
||||||
|
id='error.local_storage.help1'
|
||||||
|
defaultMessage='Enable cookies'
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FormattedMessage
|
||||||
|
id='error.local_storage.help2'
|
||||||
|
defaultMessage='Turn off private browsing'
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<FormattedMessage
|
||||||
|
id='error.local_storage.help3'
|
||||||
|
defaultMessage='Use a supported browser (IE 11, Chrome 43+, Firefox 38+, Safari 9, Edge)'
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = this.props.location.query.message;
|
let message = this.props.location.query.message;
|
||||||
if (!message || message === '') {
|
if (!message) {
|
||||||
message = Utils.localizeMessage('error.generic.message', 'An error has occoured.');
|
message = Utils.localizeMessage('error.generic.message', 'An error has occoured.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return <div dangerouslySetInnerHTML={{__html: TextFormatting.formatText(message, {linkFilter: this.linkFilter})}}/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderLink() {
|
||||||
let link = this.props.location.query.link;
|
let link = this.props.location.query.link;
|
||||||
if (!link || link === '') {
|
if (link) {
|
||||||
|
link = link.trim();
|
||||||
|
} else {
|
||||||
link = '/';
|
link = '/';
|
||||||
} else if (link.startsWith('javascript:') || link.startsWith('vbscript:') || link.startsWith('data:')) { // eslint-disable-line no-script-url
|
}
|
||||||
// Sanitize out any script links
|
|
||||||
|
if (!link.startsWith('/')) {
|
||||||
|
// Only allow relative links
|
||||||
link = '/';
|
link = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
let linkMessage = this.props.location.query.linkmessage;
|
let linkMessage = this.props.location.query.linkmessage;
|
||||||
if (!linkMessage || linkMessage === '') {
|
if (!linkMessage) {
|
||||||
linkMessage = Utils.localizeMessage('error.generic.link_message', 'Back to Mattermost');
|
linkMessage = Utils.localizeMessage('error.generic.link_message', 'Back to Mattermost');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={link}>
|
||||||
|
{linkMessage}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const title = this.renderTitle();
|
||||||
|
const message = this.renderMessage();
|
||||||
|
const link = this.renderLink();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='container-fluid'>
|
<div className='container-fluid'>
|
||||||
<div className='error__container'>
|
<div className='error__container'>
|
||||||
@@ -49,16 +129,10 @@ export default class ErrorPage extends React.Component {
|
|||||||
<i className='fa fa-exclamation-triangle'/>
|
<i className='fa fa-exclamation-triangle'/>
|
||||||
</div>
|
</div>
|
||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
<div dangerouslySetInnerHTML={{__html: TextFormatting.formatText(message)}}/>
|
{message}
|
||||||
<Link to={link}>{linkMessage}</Link>
|
{link}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorPage.defaultProps = {
|
|
||||||
};
|
|
||||||
ErrorPage.propTypes = {
|
|
||||||
location: React.PropTypes.object
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1307,8 +1307,6 @@
|
|||||||
"error.not_found.link_message": "Back to Mattermost",
|
"error.not_found.link_message": "Back to Mattermost",
|
||||||
"error.not_found.message": "The page you were trying to reach does not exist",
|
"error.not_found.message": "The page you were trying to reach does not exist",
|
||||||
"error.not_found.title": "Page not found",
|
"error.not_found.title": "Page not found",
|
||||||
"error.not_supported.message": "Private browsing is not supported",
|
|
||||||
"error.not_supported.title": "Browser not supported",
|
|
||||||
"error_bar.expired": "Enterprise license is expired and some features may be disabled. <a href='{link}' target='_blank'>Please renew.</a>",
|
"error_bar.expired": "Enterprise license is expired and some features may be disabled. <a href='{link}' target='_blank'>Please renew.</a>",
|
||||||
"error_bar.expiring": "Enterprise license expires on {date}. <a href='{link}' target='_blank'>Please renew.</a>",
|
"error_bar.expiring": "Enterprise license expires on {date}. <a href='{link}' target='_blank'>Please renew.</a>",
|
||||||
"error_bar.past_grace": "Enterprise license is expired and some features may be disabled. Please contact your System Administrator for details.",
|
"error_bar.past_grace": "Enterprise license is expired and some features may be disabled. Please contact your System Administrator for details.",
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
|
|
||||||
import {browserHistory} from 'react-router/es6';
|
import {browserHistory} from 'react-router/es6';
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
import Constants from 'utils/constants.jsx';
|
import {Constants, ErrorPageTypes} from 'utils/constants.jsx';
|
||||||
|
|
||||||
const notSupportedParams = {
|
|
||||||
title: Utils.localizeMessage('error.not_supported.title', 'Browser not supported'),
|
|
||||||
message: Utils.localizeMessage('error.not_supported.message', 'Private browsing is not supported')
|
|
||||||
};
|
|
||||||
|
|
||||||
function getPrefix() {
|
function getPrefix() {
|
||||||
if (global.window.mm_current_user_id) {
|
if (global.window.mm_current_user_id) {
|
||||||
@@ -200,7 +195,7 @@ class BrowserStoreClass {
|
|||||||
sessionStorage.removeItem('__testSession__');
|
sessionStorage.removeItem('__testSession__');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Session storage not usable, website is unusable
|
// Session storage not usable, website is unusable
|
||||||
browserHistory.push(window.location.origin + '/error?title=' + notSupportedParams.title + '&message=' + notSupportedParams.message);
|
browserHistory.push('/error?type=' + ErrorPageTypes.LOCAL_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hasCheckedLocalStorage = true;
|
this.hasCheckedLocalStorage = true;
|
||||||
|
|||||||
@@ -281,6 +281,10 @@ export const StatTypes = keyMirror({
|
|||||||
MONTHLY_ACTIVE_USERS: null
|
MONTHLY_ACTIVE_USERS: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const ErrorPageTypes = {
|
||||||
|
LOCAL_STORAGE: 'local_storage'
|
||||||
|
};
|
||||||
|
|
||||||
export const Constants = {
|
export const Constants = {
|
||||||
Preferences,
|
Preferences,
|
||||||
SocketEvents,
|
SocketEvents,
|
||||||
@@ -290,6 +294,8 @@ export const Constants = {
|
|||||||
UserSearchOptions,
|
UserSearchOptions,
|
||||||
TutorialSteps,
|
TutorialSteps,
|
||||||
PostTypes,
|
PostTypes,
|
||||||
|
ErrorPageTypes,
|
||||||
|
|
||||||
IGNORE_POST_TYPES: [PostTypes.JOIN_LEAVE, PostTypes.JOIN_CHANNEL, PostTypes.LEAVE_CHANNEL, PostTypes.REMOVE_FROM_CHANNEL, PostTypes.ADD_TO_CHANNEL, PostTypes.ADD_REMOVE],
|
IGNORE_POST_TYPES: [PostTypes.JOIN_LEAVE, PostTypes.JOIN_CHANNEL, PostTypes.LEAVE_CHANNEL, PostTypes.REMOVE_FROM_CHANNEL, PostTypes.ADD_TO_CHANNEL, PostTypes.ADD_REMOVE],
|
||||||
|
|
||||||
PayloadSources: keyMirror({
|
PayloadSources: keyMirror({
|
||||||
|
|||||||
@@ -163,6 +163,10 @@ class MattermostMarkdownRenderer extends marked.Renderer {
|
|||||||
link(href, title, text) {
|
link(href, title, text) {
|
||||||
let outHref = href;
|
let outHref = href;
|
||||||
|
|
||||||
|
if (this.formattingOptions.linkFilter && !this.formattingOptions.linkFilter(outHref)) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let unescaped = unescape(href);
|
let unescaped = unescape(href);
|
||||||
try {
|
try {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user