[MM-63015] Add more descriptive page titles to login/create account/password reset pages (#30857)
* [MM-63015] Add more descriptive page titles to login/create account/password reset pages * PR feedback * Fix e2e --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
0e806bf8e8
Коммит
c33dbe8d37
@@ -22,7 +22,7 @@ describe('Customization', () => {
|
||||
cy.visit('/login');
|
||||
|
||||
// * Verify that the head tag contains default title and without og:description
|
||||
cy.get('head').find('title').should('have.text', defaultTitle);
|
||||
cy.get('head').find('title').should('have.text', `${defaultDescription} - ${defaultTitle}`);
|
||||
cy.get('head').get('meta[property="og:description"]').should('not.exist');
|
||||
|
||||
// * Verify that the header contains default logo/image
|
||||
@@ -40,7 +40,7 @@ describe('Customization', () => {
|
||||
cy.visit('');
|
||||
|
||||
// * Verify that the head tag contains custom title and description
|
||||
cy.get('head').find('title').should('have.text', customTitle);
|
||||
cy.get('head').find('title').should('have.text', `${defaultDescription} - ${customTitle}`);
|
||||
cy.get('head').get('meta[property="og:description"]').should('have.attr', 'content', customDescription);
|
||||
|
||||
// * Verify that the header contains custom title
|
||||
|
||||
@@ -244,11 +244,17 @@ const Login = ({onCustomizeHeader}: LoginProps) => {
|
||||
formatMessage(
|
||||
{
|
||||
id: 'login.session_expired.title',
|
||||
defaultMessage: '* {siteName} - Session Expired',
|
||||
defaultMessage: '* Session Expired - {siteName}',
|
||||
},
|
||||
{siteName},
|
||||
)
|
||||
) : siteName;
|
||||
) : formatMessage(
|
||||
{
|
||||
id: 'login.pageTitle',
|
||||
defaultMessage: 'Log in - {siteName}',
|
||||
},
|
||||
{siteName},
|
||||
);
|
||||
}, [sessionExpired, siteName]);
|
||||
|
||||
const showSessionExpiredNotificationIfNeeded = useCallback(() => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, {useState, useRef, memo} from 'react';
|
||||
import React, {useState, useRef, memo, useEffect} from 'react';
|
||||
import {FormattedMessage, useIntl} from 'react-intl';
|
||||
import {useHistory} from 'react-router-dom';
|
||||
|
||||
@@ -27,6 +27,16 @@ const PasswordResetForm = ({location, siteName, actions}: Props) => {
|
||||
|
||||
const passwordInput = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = intl.formatMessage(
|
||||
{
|
||||
id: 'password_form.pageTitle',
|
||||
defaultMessage: 'Password Reset | {siteName}',
|
||||
},
|
||||
{siteName: siteName || 'Mattermost'},
|
||||
);
|
||||
}, [intl, siteName]);
|
||||
|
||||
const handlePasswordReset = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/PasswordResetSendLink should match snapshot 1`] = `
|
||||
<div>
|
||||
<BackButton
|
||||
url="/"
|
||||
/>
|
||||
<div
|
||||
className="col-sm-12"
|
||||
>
|
||||
<div
|
||||
className="signup-team__container"
|
||||
>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Password Reset"
|
||||
id="password_send.title"
|
||||
tagName="h1"
|
||||
/>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<p>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="To reset your password, enter the email address you used to sign up"
|
||||
id="password_send.description"
|
||||
/>
|
||||
</p>
|
||||
<div
|
||||
className="form-group"
|
||||
>
|
||||
<LocalizedPlaceholderInput
|
||||
autoFocus={true}
|
||||
className="form-control"
|
||||
id="passwordResetEmailInput"
|
||||
name="email"
|
||||
placeholder={
|
||||
Object {
|
||||
"defaultMessage": "Email",
|
||||
"id": "password_send.email",
|
||||
}
|
||||
}
|
||||
spellCheck="false"
|
||||
type="email"
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
id="passwordResetButton"
|
||||
type="submit"
|
||||
>
|
||||
<MemoizedFormattedMessage
|
||||
defaultMessage="Reset my password"
|
||||
id="password_send.reset"
|
||||
/>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -6,13 +6,20 @@ import {bindActionCreators} from 'redux';
|
||||
import type {Dispatch} from 'redux';
|
||||
|
||||
import {sendPasswordResetEmail} from 'mattermost-redux/actions/users';
|
||||
import {getConfig} from 'mattermost-redux/selectors/entities/general';
|
||||
|
||||
import type {GlobalState} from 'types/store';
|
||||
|
||||
import PasswordResetSendLink from './password_reset_send_link';
|
||||
|
||||
function mapStateToProps(state: GlobalState) {
|
||||
return {siteName: getConfig(state).SiteName};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
actions: bindActionCreators({
|
||||
sendPasswordResetEmail,
|
||||
}, dispatch),
|
||||
});
|
||||
|
||||
export default connect(null, mapDispatchToProps)(PasswordResetSendLink);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PasswordResetSendLink);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import {MemoryRouter} from 'react-router-dom';
|
||||
|
||||
import {mountWithIntl} from 'tests/helpers/intl-test-helper';
|
||||
|
||||
import PasswordResetSendLink from './password_reset_send_link';
|
||||
import type {PasswordResetSendLink as PasswordResetSendLinkType} from './password_reset_send_link';
|
||||
|
||||
describe('components/PasswordResetSendLink', () => {
|
||||
const baseProps = {
|
||||
@@ -16,11 +16,6 @@ describe('components/PasswordResetSendLink', () => {
|
||||
},
|
||||
};
|
||||
|
||||
it('should match snapshot', () => {
|
||||
const wrapper = shallow(<PasswordResetSendLink {...baseProps}/>);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should calls sendPasswordResetEmail() action on submit', () => {
|
||||
const props = {...baseProps};
|
||||
|
||||
@@ -28,9 +23,9 @@ describe('components/PasswordResetSendLink', () => {
|
||||
<MemoryRouter>
|
||||
<PasswordResetSendLink {...props}/>
|
||||
</MemoryRouter>,
|
||||
).children().children();
|
||||
).children().children().children();
|
||||
|
||||
(wrapper.instance() as PasswordResetSendLink).emailInput.current!.value = 'test@example.com';
|
||||
(wrapper.instance() as PasswordResetSendLinkType).emailInput.current!.value = 'test@example.com';
|
||||
wrapper.find('form').simulate('submit', {preventDefault: () => {}});
|
||||
|
||||
expect(props.actions.sendPasswordResetEmail).toHaveBeenCalledWith('test@example.com');
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {defineMessage, FormattedMessage} from 'react-intl';
|
||||
import {defineMessage, FormattedMessage, injectIntl} from 'react-intl';
|
||||
import type {IntlShape} from 'react-intl';
|
||||
|
||||
import type {ActionResult} from 'mattermost-redux/types/actions';
|
||||
import {isEmail} from 'mattermost-redux/utils/helpers';
|
||||
@@ -11,6 +12,8 @@ import BackButton from 'components/common/back_button';
|
||||
import LocalizedPlaceholderInput from 'components/localized_placeholder_input';
|
||||
|
||||
export interface Props {
|
||||
intl: IntlShape;
|
||||
siteName?: string;
|
||||
actions: {
|
||||
sendPasswordResetEmail: (email: string) => Promise<ActionResult>;
|
||||
};
|
||||
@@ -21,7 +24,7 @@ interface State {
|
||||
updateText: React.ReactNode;
|
||||
}
|
||||
|
||||
export default class PasswordResetSendLink extends React.PureComponent<Props, State> {
|
||||
export class PasswordResetSendLink extends React.PureComponent<Props, State> {
|
||||
state = {
|
||||
error: null,
|
||||
updateText: null,
|
||||
@@ -29,6 +32,17 @@ export default class PasswordResetSendLink extends React.PureComponent<Props, St
|
||||
resetForm = React.createRef<HTMLFormElement>();
|
||||
emailInput = React.createRef<HTMLInputElement>();
|
||||
|
||||
componentDidMount() {
|
||||
const {intl, siteName} = this.props;
|
||||
document.title = intl.formatMessage(
|
||||
{
|
||||
id: 'password_form.pageTitle',
|
||||
defaultMessage: 'Password Reset | {siteName}',
|
||||
},
|
||||
{siteName: siteName || 'Mattermost'},
|
||||
);
|
||||
}
|
||||
|
||||
handleSendLink = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -152,3 +166,5 @@ export default class PasswordResetSendLink extends React.PureComponent<Props, St
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default injectIntl(PasswordResetSendLink);
|
||||
|
||||
@@ -355,10 +355,14 @@ const Signup = ({onCustomizeHeader}: SignupProps) => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (SiteName) {
|
||||
document.title = SiteName;
|
||||
}
|
||||
}, [SiteName]);
|
||||
document.title = formatMessage(
|
||||
{
|
||||
id: 'signup.title',
|
||||
defaultMessage: 'Create Account | {siteName}',
|
||||
},
|
||||
{siteName: SiteName || 'Mattermost'},
|
||||
);
|
||||
}, [formatMessage, SiteName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (onCustomizeHeader) {
|
||||
|
||||
@@ -4390,12 +4390,13 @@
|
||||
"login.office365": "Entra ID",
|
||||
"login.openid": "Open ID",
|
||||
"login.or": "or log in with",
|
||||
"login.pageTitle": "Log in - {siteName}",
|
||||
"login.passwordChanged": " Password updated successfully",
|
||||
"login.placeholderOr": " or ",
|
||||
"login.saml": "SAML",
|
||||
"login.session_expired": "Your session has expired. Please log in again.",
|
||||
"login.session_expired.notification": "Session Expired: Please sign in to continue receiving notifications.",
|
||||
"login.session_expired.title": "* {siteName} - Session Expired",
|
||||
"login.session_expired.title": "* Session Expired - {siteName}",
|
||||
"login.subtitle": "Collaborate with your team in real-time",
|
||||
"login.terms_rejected": "You must agree to the terms of use before accessing {siteName}. Please contact your System Administrator for more details.",
|
||||
"login.title": "Log in to your account",
|
||||
@@ -4717,6 +4718,7 @@
|
||||
"ONE_TO_50": "1-50",
|
||||
"password_form.change": "Change my password",
|
||||
"password_form.enter": "Enter a new password for your {siteName} account.",
|
||||
"password_form.pageTitle": "Password Reset | {siteName}",
|
||||
"password_form.pwd": "Password",
|
||||
"password_form.title": "Password Reset",
|
||||
"password_send.checkInbox": "Please check your inbox.",
|
||||
@@ -5372,6 +5374,7 @@
|
||||
"signup_user_completed.validEmail": "Please enter a valid email address",
|
||||
"signup.agreement": "By proceeding to create your account and use {siteName}, you agree to our <a1>Terms of Use</a1> and <a2>Privacy Policy</a2>. If you do not agree, you cannot use {siteName}.",
|
||||
"signup.ldap": "AD/LDAP Credentials",
|
||||
"signup.title": "Create Account | {siteName}",
|
||||
"single_image_view.copied_link_tooltip": "Copied",
|
||||
"single_image_view.copy_link_tooltip": "Copy link",
|
||||
"single_image_view.download_tooltip": "Download",
|
||||
|
||||
Ссылка в новой задаче
Block a user