mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
refactor: port MainLayout to TS/SWR (#684)
* refactor: add missing toast field to UI config * refactor: port MainLayout to TS/SWR * refactor: remove unused UI config state * refactor: fix makeStyles import
This commit is contained in:
parent
b291515fa4
commit
83778a9928
@ -3,16 +3,10 @@ import { Alert } from '@material-ui/lab';
|
|||||||
import ConditionallyRender from '../ConditionallyRender';
|
import ConditionallyRender from '../ConditionallyRender';
|
||||||
import { Typography } from '@material-ui/core';
|
import { Typography } from '@material-ui/core';
|
||||||
import { useStyles } from './Proclamation.styles';
|
import { useStyles } from './Proclamation.styles';
|
||||||
|
import { IProclamationToast } from '../../../interfaces/uiConfig';
|
||||||
|
|
||||||
interface IProclamationProps {
|
interface IProclamationProps {
|
||||||
toast?: IToast;
|
toast?: IProclamationToast;
|
||||||
}
|
|
||||||
|
|
||||||
interface IToast {
|
|
||||||
message: string;
|
|
||||||
id: string;
|
|
||||||
severity: 'success' | 'info' | 'warning' | 'error';
|
|
||||||
link: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderProclamation = (id: string) => {
|
const renderProclamation = (id: string) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||||
import { matchPath } from 'react-router';
|
import { matchPath } from 'react-router';
|
||||||
import MainLayout from '../MainLayout';
|
import { MainLayout } from '../MainLayout/MainLayout';
|
||||||
|
|
||||||
const LayoutPicker = ({ children, location }) => {
|
const LayoutPicker = ({ children, location }) => {
|
||||||
const standalonePages = () => {
|
const standalonePages = () => {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import React from 'react';
|
import React, { ReactNode } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { makeStyles } from '@material-ui/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
import { Grid } from '@material-ui/core';
|
import { Grid } from '@material-ui/core';
|
||||||
|
|
||||||
import styles from '../../styles.module.scss';
|
import styles from '../../styles.module.scss';
|
||||||
import ErrorContainer from '../../error/error-container';
|
import ErrorContainer from '../../error/error-container';
|
||||||
import Header from '../../menu/Header/Header';
|
import Header from '../../menu/Header/Header';
|
||||||
@ -11,6 +9,7 @@ import Footer from '../../menu/Footer/Footer';
|
|||||||
import Proclamation from '../../common/Proclamation/Proclamation';
|
import Proclamation from '../../common/Proclamation/Proclamation';
|
||||||
import BreadcrumbNav from '../../common/BreadcrumbNav/BreadcrumbNav';
|
import BreadcrumbNav from '../../common/BreadcrumbNav/BreadcrumbNav';
|
||||||
import { ReactComponent as Texture } from '../../../assets/img/texture.svg';
|
import { ReactComponent as Texture } from '../../../assets/img/texture.svg';
|
||||||
|
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
container: {
|
container: {
|
||||||
@ -27,18 +26,23 @@ const useStyles = makeStyles(theme => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const MainLayout = ({ children, location, uiConfig }) => {
|
interface IMainLayoutProps {
|
||||||
|
children: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MainLayout = ({ children }: IMainLayoutProps) => {
|
||||||
const muiStyles = useStyles();
|
const muiStyles = useStyles();
|
||||||
|
const { uiConfig } = useUiConfig();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header location={location} />
|
<Header />
|
||||||
<Grid container className={muiStyles.container}>
|
<Grid container className={muiStyles.container}>
|
||||||
<div className={classnames(styles.contentWrapper)}>
|
<div className={classnames(styles.contentWrapper)}>
|
||||||
<Grid item className={styles.content} xs={12} sm={12}>
|
<Grid item className={styles.content} xs={12} sm={12}>
|
||||||
<div
|
<div
|
||||||
className={muiStyles.contentContainer}
|
className={muiStyles.contentContainer}
|
||||||
style={{ zIndex: '200' }}
|
style={{ zIndex: 200 }}
|
||||||
>
|
>
|
||||||
<BreadcrumbNav />
|
<BreadcrumbNav />
|
||||||
<Proclamation toast={uiConfig.toast} />
|
<Proclamation toast={uiConfig.toast} />
|
||||||
@ -52,7 +56,7 @@ const MainLayout = ({ children, location, uiConfig }) => {
|
|||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
right: '0',
|
right: '0',
|
||||||
bottom: '-4px',
|
bottom: '-4px',
|
||||||
zIndex: '1',
|
zIndex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Texture />
|
<Texture />
|
||||||
@ -64,9 +68,3 @@ const MainLayout = ({ children, location, uiConfig }) => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
MainLayout.propTypes = {
|
|
||||||
location: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default MainLayout;
|
|
@ -1,10 +0,0 @@
|
|||||||
import { connect } from 'react-redux';
|
|
||||||
import MainLayout from './MainLayout';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => ({
|
|
||||||
uiConfig: state.uiConfig.toJS(),
|
|
||||||
location: ownProps.location,
|
|
||||||
children: ownProps.children,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(MainLayout);
|
|
@ -9,6 +9,14 @@ export interface IUiConfig {
|
|||||||
versionInfo: IVersionInfo;
|
versionInfo: IVersionInfo;
|
||||||
links: ILinks[];
|
links: ILinks[];
|
||||||
disablePasswordAuth?: boolean;
|
disablePasswordAuth?: boolean;
|
||||||
|
toast?: IProclamationToast
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IProclamationToast {
|
||||||
|
message: string;
|
||||||
|
id: string;
|
||||||
|
severity: 'success' | 'info' | 'warning' | 'error';
|
||||||
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IFlags {
|
export interface IFlags {
|
||||||
|
@ -8,7 +8,6 @@ import strategies from './strategy';
|
|||||||
import error from './error';
|
import error from './error';
|
||||||
import user from './user';
|
import user from './user';
|
||||||
import applications from './application';
|
import applications from './application';
|
||||||
import uiConfig from './ui-config';
|
|
||||||
import projects from './project';
|
import projects from './project';
|
||||||
import addons from './addons';
|
import addons from './addons';
|
||||||
import apiCalls from './api-calls';
|
import apiCalls from './api-calls';
|
||||||
@ -23,7 +22,6 @@ const unleashStore = combineReducers({
|
|||||||
error,
|
error,
|
||||||
user,
|
user,
|
||||||
applications,
|
applications,
|
||||||
uiConfig,
|
|
||||||
projects,
|
projects,
|
||||||
addons,
|
addons,
|
||||||
apiCalls,
|
apiCalls,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import api from './api';
|
import api from './api';
|
||||||
import { dispatchError } from '../util';
|
import { dispatchError } from '../util';
|
||||||
import { receiveConfig } from '../ui-config/actions';
|
|
||||||
import { receiveProjects } from '../project/actions';
|
import { receiveProjects } from '../project/actions';
|
||||||
import { receiveTagTypes } from '../tag-type/actions';
|
import { receiveTagTypes } from '../tag-type/actions';
|
||||||
import { receiveStrategies } from '../strategy/actions';
|
import { receiveStrategies } from '../strategy/actions';
|
||||||
@ -14,7 +13,6 @@ export function fetchUiBootstrap() {
|
|||||||
.fetchUIBootstrap()
|
.fetchUIBootstrap()
|
||||||
.then(json => {
|
.then(json => {
|
||||||
dispatch(receiveProjects(json.projects));
|
dispatch(receiveProjects(json.projects));
|
||||||
dispatch(receiveConfig(json.uiConfig));
|
|
||||||
dispatch(receiveTagTypes(json));
|
dispatch(receiveTagTypes(json));
|
||||||
dispatch(receiveStrategies(json.strategies));
|
dispatch(receiveStrategies(json.strategies));
|
||||||
})
|
})
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`should be default state 1`] = `
|
|
||||||
Object {
|
|
||||||
"environment": "",
|
|
||||||
"flags": Object {},
|
|
||||||
"headerBackground": undefined,
|
|
||||||
"links": Array [
|
|
||||||
Object {
|
|
||||||
"href": "https://docs.getunleash.io/docs?source=oss",
|
|
||||||
"icon": Object {
|
|
||||||
"$$typeof": Symbol(react.memo),
|
|
||||||
"compare": null,
|
|
||||||
"type": Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"render": [Function],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"title": "User documentation",
|
|
||||||
"value": "Documentation",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"href": "https://github.com/Unleash",
|
|
||||||
"icon": "c_github",
|
|
||||||
"title": "Source code on GitHub",
|
|
||||||
"value": "GitHub",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"name": "Unleash",
|
|
||||||
"slogan": "The enterprise ready feature toggle service.",
|
|
||||||
"version": "3.x",
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`should be merged state all 1`] = `
|
|
||||||
Object {
|
|
||||||
"environment": "dev",
|
|
||||||
"flags": Object {},
|
|
||||||
"headerBackground": "red",
|
|
||||||
"links": Array [
|
|
||||||
Object {
|
|
||||||
"href": "https://docs.getunleash.io/docs?source=oss",
|
|
||||||
"icon": Object {
|
|
||||||
"$$typeof": Symbol(react.memo),
|
|
||||||
"compare": null,
|
|
||||||
"type": Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"render": [Function],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"title": "User documentation",
|
|
||||||
"value": "Documentation",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"href": "https://github.com/Unleash",
|
|
||||||
"icon": "c_github",
|
|
||||||
"title": "Source code on GitHub",
|
|
||||||
"value": "GitHub",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"name": "Unleash",
|
|
||||||
"slogan": "hello",
|
|
||||||
"version": "3.x",
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`should only update headerBackground 1`] = `
|
|
||||||
Object {
|
|
||||||
"environment": "",
|
|
||||||
"flags": Object {},
|
|
||||||
"headerBackground": "black",
|
|
||||||
"links": Array [
|
|
||||||
Object {
|
|
||||||
"href": "https://docs.getunleash.io/docs?source=oss",
|
|
||||||
"icon": Object {
|
|
||||||
"$$typeof": Symbol(react.memo),
|
|
||||||
"compare": null,
|
|
||||||
"type": Object {
|
|
||||||
"$$typeof": Symbol(react.forward_ref),
|
|
||||||
"render": [Function],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"title": "User documentation",
|
|
||||||
"value": "Documentation",
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"href": "https://github.com/Unleash",
|
|
||||||
"icon": "c_github",
|
|
||||||
"title": "Source code on GitHub",
|
|
||||||
"value": "GitHub",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"name": "Unleash",
|
|
||||||
"slogan": "The enterprise ready feature toggle service.",
|
|
||||||
"version": "3.x",
|
|
||||||
}
|
|
||||||
`;
|
|
@ -1,31 +0,0 @@
|
|||||||
import reducer from '../index';
|
|
||||||
import { receiveConfig } from '../actions';
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
localStorage.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should be default state', () => {
|
|
||||||
const state = reducer(undefined, {});
|
|
||||||
expect(state.toJS()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should be merged state all', () => {
|
|
||||||
const uiConfig = {
|
|
||||||
headerBackground: 'red',
|
|
||||||
slogan: 'hello',
|
|
||||||
environment: 'dev',
|
|
||||||
};
|
|
||||||
|
|
||||||
const state = reducer(undefined, receiveConfig(uiConfig));
|
|
||||||
expect(state.toJS()).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should only update headerBackground', () => {
|
|
||||||
const uiConfig = {
|
|
||||||
headerBackground: 'black',
|
|
||||||
};
|
|
||||||
|
|
||||||
const state = reducer(undefined, receiveConfig(uiConfig));
|
|
||||||
expect(state.toJS()).toMatchSnapshot();
|
|
||||||
});
|
|
@ -1,18 +0,0 @@
|
|||||||
import api from './api';
|
|
||||||
import { dispatchError } from '../util';
|
|
||||||
|
|
||||||
export const RECEIVE_CONFIG = 'RECEIVE_CONFIG';
|
|
||||||
export const ERROR_RECEIVE_CONFIG = 'ERROR_RECEIVE_CONFIG';
|
|
||||||
|
|
||||||
export const receiveConfig = json => ({
|
|
||||||
type: RECEIVE_CONFIG,
|
|
||||||
value: json,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function fetchUIConfig() {
|
|
||||||
return dispatch =>
|
|
||||||
api
|
|
||||||
.fetchConfig()
|
|
||||||
.then(json => dispatch(receiveConfig(json)))
|
|
||||||
.catch(dispatchError(dispatch, ERROR_RECEIVE_CONFIG));
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { formatApiPath } from '../../utils/format-path';
|
|
||||||
import { throwIfNotSuccess } from '../api-helper';
|
|
||||||
|
|
||||||
const URI = formatApiPath('api/admin/ui-config');
|
|
||||||
|
|
||||||
function fetchConfig() {
|
|
||||||
return fetch(URI, { credentials: 'include' })
|
|
||||||
.then(throwIfNotSuccess)
|
|
||||||
.then(response => response.json());
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
fetchConfig,
|
|
||||||
};
|
|
@ -1,61 +0,0 @@
|
|||||||
import { Map as $Map } from 'immutable';
|
|
||||||
import { LibraryBooks } from '@material-ui/icons';
|
|
||||||
import { RECEIVE_CONFIG } from './actions';
|
|
||||||
|
|
||||||
import { getBasePath } from '../../utils/format-path';
|
|
||||||
|
|
||||||
const localStorage = window.localStorage || {
|
|
||||||
setItem: () => {},
|
|
||||||
getItem: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const basePath = getBasePath();
|
|
||||||
const UI_CONFIG = `${basePath}:ui_config`;
|
|
||||||
|
|
||||||
const DEFAULT = new $Map({
|
|
||||||
headerBackground: undefined,
|
|
||||||
name: 'Unleash',
|
|
||||||
version: '3.x',
|
|
||||||
environment: '',
|
|
||||||
slogan: 'The enterprise ready feature toggle service.',
|
|
||||||
flags: {},
|
|
||||||
links: [
|
|
||||||
{
|
|
||||||
value: 'Documentation',
|
|
||||||
icon: LibraryBooks,
|
|
||||||
href: 'https://docs.getunleash.io/docs?source=oss',
|
|
||||||
title: 'User documentation',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'GitHub',
|
|
||||||
icon: 'c_github',
|
|
||||||
href: 'https://github.com/Unleash',
|
|
||||||
title: 'Source code on GitHub',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
function getInitState() {
|
|
||||||
try {
|
|
||||||
const state = JSON.parse(localStorage.getItem(UI_CONFIG));
|
|
||||||
return state ? DEFAULT.merge(state) : DEFAULT;
|
|
||||||
} catch (e) {
|
|
||||||
return DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateConfig(state, config) {
|
|
||||||
localStorage.setItem(UI_CONFIG, JSON.stringify(config));
|
|
||||||
return state.merge(config);
|
|
||||||
}
|
|
||||||
|
|
||||||
const strategies = (state = getInitState(), action) => {
|
|
||||||
switch (action.type) {
|
|
||||||
case RECEIVE_CONFIG:
|
|
||||||
return updateConfig(state, action.value);
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default strategies;
|
|
Loading…
Reference in New Issue
Block a user