feat: allow custom logo on auth page (#1818)
This commit is contained in:
parent
ede1bad97c
commit
c6ae1e8fc0
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import styled from 'react-emotion';
|
import styled from 'react-emotion';
|
||||||
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
import { NetlifyAuthenticator } from 'netlify-cms-lib-auth';
|
||||||
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
import { AuthenticationPage, Icon } from 'netlify-cms-ui-default';
|
||||||
@ -15,6 +16,7 @@ export default class BitbucketAuthenticationPage extends React.Component {
|
|||||||
base_url: PropTypes.string,
|
base_url: PropTypes.string,
|
||||||
siteId: PropTypes.string,
|
siteId: PropTypes.string,
|
||||||
authEndpoint: PropTypes.string,
|
authEndpoint: PropTypes.string,
|
||||||
|
config: ImmutablePropTypes.map,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {};
|
state = {};
|
||||||
@ -41,13 +43,14 @@ export default class BitbucketAuthenticationPage extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { inProgress } = this.props;
|
const { inProgress, config } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthenticationPage
|
<AuthenticationPage
|
||||||
onLogin={this.handleLogin}
|
onLogin={this.handleLogin}
|
||||||
loginDisabled={inProgress}
|
loginDisabled={inProgress}
|
||||||
loginErrorMessage={this.state.loginError}
|
loginErrorMessage={this.state.loginError}
|
||||||
|
logoUrl={config.get('logo_url')}
|
||||||
renderButtonContent={() => (
|
renderButtonContent={() => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<LoginButtonIcon type="bitbucket" />
|
<LoginButtonIcon type="bitbucket" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'react-emotion';
|
import styled from 'react-emotion';
|
||||||
import { partial } from 'lodash';
|
import { partial } from 'lodash';
|
||||||
@ -100,6 +101,7 @@ export default class GitGatewayAuthenticationPage extends React.Component {
|
|||||||
onLogin: PropTypes.func.isRequired,
|
onLogin: PropTypes.func.isRequired,
|
||||||
inProgress: PropTypes.bool.isRequired,
|
inProgress: PropTypes.bool.isRequired,
|
||||||
error: PropTypes.node,
|
error: PropTypes.node,
|
||||||
|
config: ImmutablePropTypes.map,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = { email: '', password: '', errors: {} };
|
state = { email: '', password: '', errors: {} };
|
||||||
@ -140,11 +142,12 @@ export default class GitGatewayAuthenticationPage extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errors } = this.state;
|
const { errors } = this.state;
|
||||||
const { error, inProgress } = this.props;
|
const { error, inProgress, config } = this.props;
|
||||||
|
|
||||||
if (window.netlifyIdentity) {
|
if (window.netlifyIdentity) {
|
||||||
return (
|
return (
|
||||||
<AuthenticationPage
|
<AuthenticationPage
|
||||||
|
logoUrl={config.get('logo_url')}
|
||||||
onLogin={this.handleIdentity}
|
onLogin={this.handleIdentity}
|
||||||
renderButtonContent={() => 'Login with Netlify Identity'}
|
renderButtonContent={() => 'Login with Netlify Identity'}
|
||||||
/>
|
/>
|
||||||
@ -153,6 +156,7 @@ export default class GitGatewayAuthenticationPage extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthenticationPage
|
<AuthenticationPage
|
||||||
|
logoUrl={config.get('logo_url')}
|
||||||
renderPageContent={() => (
|
renderPageContent={() => (
|
||||||
<AuthForm onSubmit={this.handleLogin}>
|
<AuthForm onSubmit={this.handleLogin}>
|
||||||
{!error ? null : <ErrorMessage>{error}</ErrorMessage>}
|
{!error ? null : <ErrorMessage>{error}</ErrorMessage>}
|
||||||
|
@ -44,12 +44,13 @@ export default class GitHubAuthenticationPage extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { inProgress } = this.props;
|
const { inProgress, config } = this.props;
|
||||||
return (
|
return (
|
||||||
<AuthenticationPage
|
<AuthenticationPage
|
||||||
onLogin={this.handleLogin}
|
onLogin={this.handleLogin}
|
||||||
loginDisabled={inProgress}
|
loginDisabled={inProgress}
|
||||||
loginErrorMessage={this.state.loginError}
|
loginErrorMessage={this.state.loginError}
|
||||||
|
logoUrl={config.get('logo_url')}
|
||||||
renderButtonContent={() => (
|
renderButtonContent={() => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<LoginButtonIcon type="github" /> {inProgress ? 'Logging in...' : 'Login with GitHub'}
|
<LoginButtonIcon type="github" /> {inProgress ? 'Logging in...' : 'Login with GitHub'}
|
||||||
|
@ -63,12 +63,13 @@ export default class GitLabAuthenticationPage extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { inProgress } = this.props;
|
const { inProgress, config } = this.props;
|
||||||
return (
|
return (
|
||||||
<AuthenticationPage
|
<AuthenticationPage
|
||||||
onLogin={this.handleLogin}
|
onLogin={this.handleLogin}
|
||||||
loginDisabled={inProgress}
|
loginDisabled={inProgress}
|
||||||
loginErrorMessage={this.state.loginError}
|
loginErrorMessage={this.state.loginError}
|
||||||
|
logoUrl={config.get('logo_url')}
|
||||||
renderButtonContent={() => (
|
renderButtonContent={() => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<LoginButtonIcon type="gitlab" /> {inProgress ? 'Logging in...' : 'Login with GitLab'}
|
<LoginButtonIcon type="gitlab" /> {inProgress ? 'Logging in...' : 'Login with GitLab'}
|
||||||
|
@ -36,6 +36,7 @@ const getConfigSchema = () => ({
|
|||||||
required: ['name'],
|
required: ['name'],
|
||||||
},
|
},
|
||||||
display_url: { type: 'string', examples: ['https://example.com'] },
|
display_url: { type: 'string', examples: ['https://example.com'] },
|
||||||
|
logo_url: { type: 'string', examples: ['https://example.com/images/logo.svg'] },
|
||||||
media_folder: { type: 'string', examples: ['assets/uploads'] },
|
media_folder: { type: 'string', examples: ['assets/uploads'] },
|
||||||
public_folder: { type: 'string', examples: ['/uploads'] },
|
public_folder: { type: 'string', examples: ['/uploads'] },
|
||||||
media_library: {
|
media_library: {
|
||||||
|
@ -12,11 +12,38 @@ const StyledAuthenticationPage = styled.section`
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const PageLogoIcon = styled(Icon)`
|
const CustomIconWrapper = styled.span`
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
margin-top: -150px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const NetlifyLogoIcon = styled(Icon)`
|
||||||
color: #c4c6d2;
|
color: #c4c6d2;
|
||||||
margin-top: -300px;
|
margin-top: -300px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const NetlifyCreditIcon = styled(Icon)`
|
||||||
|
color: #c4c6d2;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const CustomLogoIcon = ({ url }) => {
|
||||||
|
return (
|
||||||
|
<CustomIconWrapper>
|
||||||
|
<img src={url} alt="Logo" />
|
||||||
|
</CustomIconWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPageLogo = logoUrl => {
|
||||||
|
if (logoUrl) {
|
||||||
|
return <CustomLogoIcon url={logoUrl} />;
|
||||||
|
}
|
||||||
|
return <NetlifyLogoIcon size="300px" type="netlify-cms" />;
|
||||||
|
};
|
||||||
|
|
||||||
const LoginButton = styled.button`
|
const LoginButton = styled.button`
|
||||||
${buttons.button};
|
${buttons.button};
|
||||||
${shadows.dropDeep};
|
${shadows.dropDeep};
|
||||||
@ -39,10 +66,11 @@ const AuthenticationPage = ({
|
|||||||
loginErrorMessage,
|
loginErrorMessage,
|
||||||
renderButtonContent,
|
renderButtonContent,
|
||||||
renderPageContent,
|
renderPageContent,
|
||||||
|
logoUrl,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<StyledAuthenticationPage>
|
<StyledAuthenticationPage>
|
||||||
<PageLogoIcon size="300px" type="netlify-cms" />
|
{renderPageLogo(logoUrl)}
|
||||||
{loginErrorMessage ? <p>{loginErrorMessage}</p> : null}
|
{loginErrorMessage ? <p>{loginErrorMessage}</p> : null}
|
||||||
{!renderPageContent ? null : renderPageContent()}
|
{!renderPageContent ? null : renderPageContent()}
|
||||||
{!renderButtonContent ? null : (
|
{!renderButtonContent ? null : (
|
||||||
@ -50,12 +78,14 @@ const AuthenticationPage = ({
|
|||||||
{renderButtonContent()}
|
{renderButtonContent()}
|
||||||
</LoginButton>
|
</LoginButton>
|
||||||
)}
|
)}
|
||||||
|
{logoUrl ? <NetlifyCreditIcon size="100px" type="netlify-cms" /> : null}
|
||||||
</StyledAuthenticationPage>
|
</StyledAuthenticationPage>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AuthenticationPage.propTypes = {
|
AuthenticationPage.propTypes = {
|
||||||
onLogin: PropTypes.func,
|
onLogin: PropTypes.func,
|
||||||
|
logoUrl: PropTypes.string,
|
||||||
loginDisabled: PropTypes.bool,
|
loginDisabled: PropTypes.bool,
|
||||||
loginErrorMessage: PropTypes.node,
|
loginErrorMessage: PropTypes.node,
|
||||||
renderButtonContent: PropTypes.func,
|
renderButtonContent: PropTypes.func,
|
||||||
|
@ -95,6 +95,16 @@ When the `display_url` setting is specified, the CMS UI will include a link in t
|
|||||||
display_url: https://your-site.com
|
display_url: https://your-site.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Logo
|
||||||
|
|
||||||
|
When the `logo_url` setting is specified, the CMS UI will change the logo displayed at the top of the login page, allowing you to brand the CMS with your own logo. `logo_url` is assumed to be a URL to an image file.
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
logo_url: https://your-site.com/images/logo.svg
|
||||||
|
```
|
||||||
|
|
||||||
## Slug Type
|
## Slug Type
|
||||||
|
|
||||||
The `slug` option allows you to change how filenames for entries are created and sanitized. For modifying the actual data in a slug, see the per-collection option below.
|
The `slug` option allows you to change how filenames for entries are created and sanitized. For modifying the actual data in a slug, see the per-collection option below.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user