1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-09 00:18:00 +01: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:
olav 2022-02-09 14:16:24 +01:00 committed by GitHub
parent b291515fa4
commit 83778a9928
12 changed files with 23 additions and 258 deletions

View File

@ -3,16 +3,10 @@ import { Alert } from '@material-ui/lab';
import ConditionallyRender from '../ConditionallyRender';
import { Typography } from '@material-ui/core';
import { useStyles } from './Proclamation.styles';
import { IProclamationToast } from '../../../interfaces/uiConfig';
interface IProclamationProps {
toast?: IToast;
}
interface IToast {
message: string;
id: string;
severity: 'success' | 'info' | 'warning' | 'error';
link: string;
toast?: IProclamationToast;
}
const renderProclamation = (id: string) => {

View File

@ -1,6 +1,6 @@
import ConditionallyRender from '../../common/ConditionallyRender';
import { matchPath } from 'react-router';
import MainLayout from '../MainLayout';
import { MainLayout } from '../MainLayout/MainLayout';
const LayoutPicker = ({ children, location }) => {
const standalonePages = () => {

View File

@ -1,9 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import React, { ReactNode } from 'react';
import classnames from 'classnames';
import { makeStyles } from '@material-ui/styles';
import { makeStyles } from '@material-ui/core/styles';
import { Grid } from '@material-ui/core';
import styles from '../../styles.module.scss';
import ErrorContainer from '../../error/error-container';
import Header from '../../menu/Header/Header';
@ -11,6 +9,7 @@ import Footer from '../../menu/Footer/Footer';
import Proclamation from '../../common/Proclamation/Proclamation';
import BreadcrumbNav from '../../common/BreadcrumbNav/BreadcrumbNav';
import { ReactComponent as Texture } from '../../../assets/img/texture.svg';
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
const useStyles = makeStyles(theme => ({
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 { uiConfig } = useUiConfig();
return (
<>
<Header location={location} />
<Header />
<Grid container className={muiStyles.container}>
<div className={classnames(styles.contentWrapper)}>
<Grid item className={styles.content} xs={12} sm={12}>
<div
className={muiStyles.contentContainer}
style={{ zIndex: '200' }}
style={{ zIndex: 200 }}
>
<BreadcrumbNav />
<Proclamation toast={uiConfig.toast} />
@ -52,7 +56,7 @@ const MainLayout = ({ children, location, uiConfig }) => {
position: 'fixed',
right: '0',
bottom: '-4px',
zIndex: '1',
zIndex: 1,
}}
>
<Texture />
@ -64,9 +68,3 @@ const MainLayout = ({ children, location, uiConfig }) => {
</>
);
};
MainLayout.propTypes = {
location: PropTypes.object.isRequired,
};
export default MainLayout;

View File

@ -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);

View File

@ -9,6 +9,14 @@ export interface IUiConfig {
versionInfo: IVersionInfo;
links: ILinks[];
disablePasswordAuth?: boolean;
toast?: IProclamationToast
}
export interface IProclamationToast {
message: string;
id: string;
severity: 'success' | 'info' | 'warning' | 'error';
link: string;
}
export interface IFlags {

View File

@ -8,7 +8,6 @@ import strategies from './strategy';
import error from './error';
import user from './user';
import applications from './application';
import uiConfig from './ui-config';
import projects from './project';
import addons from './addons';
import apiCalls from './api-calls';
@ -23,7 +22,6 @@ const unleashStore = combineReducers({
error,
user,
applications,
uiConfig,
projects,
addons,
apiCalls,

View File

@ -1,6 +1,5 @@
import api from './api';
import { dispatchError } from '../util';
import { receiveConfig } from '../ui-config/actions';
import { receiveProjects } from '../project/actions';
import { receiveTagTypes } from '../tag-type/actions';
import { receiveStrategies } from '../strategy/actions';
@ -14,7 +13,6 @@ export function fetchUiBootstrap() {
.fetchUIBootstrap()
.then(json => {
dispatch(receiveProjects(json.projects));
dispatch(receiveConfig(json.uiConfig));
dispatch(receiveTagTypes(json));
dispatch(receiveStrategies(json.strategies));
})

View File

@ -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",
}
`;

View File

@ -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();
});

View File

@ -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));
}

View File

@ -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,
};

View File

@ -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;