Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/improvement/2121-update-the-bran…
Browse files Browse the repository at this point in the history
…d-to-adapt-new-design' into w/2.5/improvement/2121-update-the-brand-to-adapt-new-design
  • Loading branch information
ChengYanJin committed Dec 17, 2019
2 parents 7c84e51 + a83dc21 commit 11b6df1
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 33 deletions.
2 changes: 1 addition & 1 deletion salt/metalk8s/addons/ui/deployed/ui.sls
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,4 @@ Create ui-branding ConfigMap:
namespace: metalk8s-ui
data:
theme.json: |
{"brand":{"base":"#19161D","baseContrast1":"#26232A","primary":"#e99121","secondary":"#2979ff","success":"#2bad8d","info":"#00B2A9","warning":"#F1B434","danger":"#EF3340","background":"#26232A","backgroundContrast1":"#2E2B32","backgroundContrast2":"#353239","text":"#ffffff","border":"#ffffff"}}
{"theme": {"light":{ "brand":{ "base": "#F7F6F9","baseContrast1": "#ECF4FF","primary": "#313B44","secondary": "#e99121","success": "#23AD56","info": "#00B2A9", "warning": "#F1B434","danger": "#EF3340","background": "#ffffff","backgroundContrast1": "#F7F6F9","backgroundContrast2": "#FAF9FB","text":"#000000","border":"#000000"},"logo_path":"/brand/assets/branding-light.svg"},"dark":{"brand":{"base": "#121214", "baseContrast1": "#192A41","primary": "#A7B6C3","secondary": "#2979ff","success": "#23AD56","info": "#00B2A9","warning": "#F1B434","danger": "#EF3340","background": "#0D0D0D","backgroundContrast1": "#1D1D21","backgroundContrast2": "#171717","text": "#ffffff","border": "#ffffff"},"logo_path":"/brand/assets/branding-dark.svg"},"custom":{}},"default": "light"}
File renamed without changes
50 changes: 50 additions & 0 deletions ui/public/brand/assets/branding-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 41 additions & 15 deletions ui/public/brand/theme.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,43 @@
{
"brand": {
"base": "#19161D",
"baseContrast1": "#26232A",
"primary": "#e99121",
"secondary": "#2979ff",
"success": "#006F62",
"info": "#00B2A9",
"warning": "#F1B434",
"danger": "#EF3340",
"background": "#26232A",
"backgroundContrast1": "#2E2B32",
"backgroundContrast2": "#353239",
"text": "#ffffff",
"border": "#ffffff"
}
"theme":{
"light":{
"brand":{
"base": "#F7F6F9",
"baseContrast1": "#ECF4FF",
"primary": "#313B44",
"secondary": "#e99121",
"success": "#23AD56",
"info": "#00B2A9",
"warning": "#F1B434",
"danger": "#EF3340",
"background": "#ffffff",
"backgroundContrast1": "#F7F6F9",
"backgroundContrast2": "#FAF9FB",
"text":"#000000",
"border":"#000000"
},
"logo_path":"/brand/assets/branding-light.svg"
},
"dark":{
"brand":{
"base": "#121214",
"baseContrast1": "#192A41",
"primary": "#A7B6C3",
"secondary": "#2979ff",
"success": "#23AD56",
"info": "#00B2A9",
"warning": "#F1B434",
"danger": "#EF3340",
"background": "#0D0D0D",
"backgroundContrast1": "#1D1D21",
"backgroundContrast2": "#171717",
"text": "#ffffff",
"border": "#ffffff"
},
"logo_path":"/brand/assets/branding-dark.svg"
},
"custom":{}
},
"default": "light"
}

2 changes: 1 addition & 1 deletion ui/src/containers/ClusterMonitoring.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ const QuestionMarkIcon = styled.i`
`;

const TooltipContent = styled.div`
color: ${props => props.theme.brand.secondary};
color: ${props => props.theme.brand.primary};
font-weight: ${fontWeight.bold};
`;

Expand Down
1 change: 1 addition & 0 deletions ui/src/containers/CreateVolume.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ const CreateVolume = props => {
type="button"
onClick={addLabel}
data-cy="add-volume-labels-button"
outlined
/>
</LabelsForm>
{!!Object.keys(values.labels).length && (
Expand Down
7 changes: 1 addition & 6 deletions ui/src/containers/Layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,7 @@ const Layout = props => {
onToggleClick: toggleSidebar,
productName: intl.messages.product_name,
rightActions,
logo: (
<img
alt="logo"
src={process.env.PUBLIC_URL + '/brand/assets/branding.svg'}
/>
),
logo: <img alt="logo" src={process.env.PUBLIC_URL + theme.logo_path} />,
};

return (
Expand Down
142 changes: 142 additions & 0 deletions ui/src/containers/Login.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Formik, Form } from 'formik';
import * as yup from 'yup';
import { Button, Input } from '@scality/core-ui';
import { brand, padding } from '@scality/core-ui/dist/style/theme';
import styled from 'styled-components';
import { authenticateAction } from '../ducks/login';
import { injectIntl } from 'react-intl';
import isEmpty from 'lodash.isempty';

const LoginFormContainer = styled.div`
height: 100vh;
background: url(${process.env.PUBLIC_URL + '/brand/assets/login.jpg'});
background-size: cover;
position: relative;
form {
padding: 200px 50px;
position: absolute;
background-color: rgba(70, 103, 127, 0.8);
top: 0;
bottom: 0;
.sc-input {
display: block;
margin: 30px 0;
.sc-input-label {
padding: 0;
font-weight: bold;
display: block;
margin-bottom: ${padding.smaller};
margin-top: ${padding.larger};
color: white;
}
}
}
`;

const Error = styled.span`
display: block;
color: ${brand.danger};
`;

const LogoContainer = styled.div`
position: absolute;
top: 45px;
`;

const LoginForm = props => {
const {
values,
touched,
errors,
dirty,
intl,
setFieldValue,
setFieldTouched,
asyncErrors,
} = props;
//handleChange of the Formik props does not update 'values' when field value is empty
const handleChange = field => e => {
const { value, checked, type } = e.target;
setFieldValue(field, type === 'checkbox' ? checked : value, true);
};
//touched is not "always" correctly set
const handleOnBlur = e => setFieldTouched(e.target.name, true);

return (
<Form autoComplete="off">
<LogoContainer>
<img
alt="logo"
src={process.env.PUBLIC_URL + '/brand/assets/branding-dark.svg'}
/>
</LogoContainer>
<Input
name="username"
type="text"
label={intl.messages.username}
error={touched.username && errors.username}
value={values.username}
onChange={handleChange('username')}
onBlur={handleOnBlur}
/>
<Input
name="password"
type="password"
label={intl.messages.password}
error={touched.password && errors.password}
value={values.password}
onChange={handleChange('password')}
onBlur={handleOnBlur}
/>
<Button
type="submit"
text={intl.messages.submit}
disabled={!dirty || !isEmpty(errors)}
/>
{asyncErrors && asyncErrors.authentication && (
<Error>{asyncErrors.authentication}</Error>
)}
</Form>
);
};

const initialValues = {
username: '',
password: '',
};

const validationSchema = yup.object().shape({
username: yup.string().required(),
password: yup.string().required(),
});

const Login = props => {
const asyncErrors = useSelector(state => state.login.errors);
const dispatch = useDispatch();
const authenticate = values => dispatch(authenticateAction(values));

return (
<LoginFormContainer>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={authenticate}
render={renderProps => {
const formikProps = {
...renderProps,
...props,
asyncErrors: asyncErrors,
};
return <LoginForm {...formikProps} />;
}}
/>
</LoginFormContainer>
);
};

export default injectIntl(Login);
9 changes: 8 additions & 1 deletion ui/src/containers/NodeVolumes.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ const LoaderContainer = styled(Loader)`
padding-right: ${padding.smaller};
`;

const TooltipContent = styled.div`
background-color: ${props => props.theme.brand.backgroundContrast2};
`;

const NodeVolumes = props => {
const { intl } = props;
const dispatch = useDispatch();
Expand Down Expand Up @@ -198,7 +202,10 @@ const NodeVolumes = props => {

return (
<>
<Tooltip placement="top" overlay={hintPopup()}>
<Tooltip
placement="top"
overlay={<TooltipContent>{hintPopup()}</TooltipContent>}
>
<Button
className="remove-volume-button"
onClick={e => {
Expand Down
20 changes: 17 additions & 3 deletions ui/src/ducks/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ export const SET_USER_MANAGER = 'SET_USER_MANAGER';
export const UPDATE_API_CONFIG = 'UPDATE_API_CONFIG';
export const LOGOUT = 'LOGOUT';
export const SET_USER_LOADED = 'SET_USER_LOADED';
export const SET_THEMES = 'SET_THEMES';

// Reducer
const defaultState = {
language: EN_LANG,
theme: {},
theme: {}, // current theme
api: null,
userManagerConfig: {
client_id: 'metalk8s-ui',
Expand All @@ -45,6 +46,7 @@ const defaultState = {
},
userManager: null,
isUserLoaded: false,
themes: {}, // include light, dark and custom
};

export default function reducer(state = defaultState, action = {}) {
Expand All @@ -67,6 +69,8 @@ export default function reducer(state = defaultState, action = {}) {
return { ...state, userManager: action.payload };
case SET_USER_LOADED:
return { ...state, isUserLoaded: action.payload };
case SET_THEMES:
return { ...state, themes: action.payload };
default:
return state;
}
Expand Down Expand Up @@ -121,12 +125,22 @@ export function logoutAction() {
return { type: LOGOUT };
}

export function setThemesAction(themes) {
return { type: SET_THEMES, payload: themes };
}

// Sagas
export function* fetchTheme() {
const result = yield call(Api.fetchTheme);
if (!result.error) {
result.brand = mergeTheme(result, defaultTheme);
yield put(setThemeAction(result));
// get the default theme from configMap
const defaultThemeMode = result.default;
result.theme[defaultThemeMode].brand = mergeTheme(
result.theme[defaultThemeMode],
defaultTheme,
);
yield put(setThemesAction(result.theme));
yield put(setThemeAction(result.theme[defaultThemeMode]));
}
}

Expand Down
Loading

0 comments on commit 11b6df1

Please sign in to comment.