Commit 70d6f0b6 authored by Florent Chehab's avatar Florent Chehab

Settings added, color selection operationnal

parent b822f1d8
export const SAVE_MAIN_MAP_POSITION = 'SAVE_MAIN_MAP_POSITION';
export const SAVE_SELECTED_UNIVERSITIES = 'SAVE_SELECTED_UNIVERSITIES';
export const SAVE_FILTER_CONFIG = 'SAVE_FILTER_CONFIG';
export const SAVE_APP_THEME = 'SAVE_APP_THEME';
import {
SAVE_APP_THEME
} from "./action-types";
export function saveAppTheme(theme) {
return {
type: SAVE_APP_THEME,
theme
};
}
......@@ -35,6 +35,7 @@ import PageMap from './pages/PageMap';
import PageHome from './pages/PageHome';
import PageFilter from './pages/PageFilter';
import PageSearch from './pages/PageSearch';
import PageSettings from './pages/PageSettings';
const drawerWidth = 240;
......@@ -157,12 +158,11 @@ class App extends MyComponent {
</Drawer>
<main className={classes.content}>
<Route path="/app/" exact={true} component={PageHome} />
<Route path="/app/search" component={PageSearch} />
<Route path="/app/map" component={PageMap} />
<Route path="/app/filter" component={PageFilter} />
<Route path="/app/settings" component={PageSettings} />
</main>
</div>
</React.Fragment>
......@@ -191,4 +191,4 @@ const mapDispatchToProps = (dispatch) => {
};
};
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(App));
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles, { withTheme: true })(App));
import React from "react";
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import { connect } from "react-redux";
import { BrowserRouter as Router, Route } from 'react-router-dom';
class ThemeProvider extends React.Component {
render() {
console.log("ici")
return (
<div>
<MuiThemeProvider theme={createMuiTheme(this.props.theme)}>
<Router>
{this.props.children}
</Router>
</MuiThemeProvider>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
theme: state.app.appTheme
};
};
export default connect(mapStateToProps)(ThemeProvider);
......@@ -36,13 +36,13 @@ class UnivMap extends MyComponent {
}
saveLeafletInstance = (l) => {
this.setState(Object.assign(this.state, {
this.setState(Object.assign({},this.state, {
leaflet_instance: l,
}))
}
saveSelectedLayer = (e) => {
this.setState(Object.assign(this.state, {
this.setState(Object.assign({},this.state, {
selected_layer: e.name,
}))
}
......
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import Settings from '../settings/Settings';
import Paper from '@material-ui/core/Paper';
const styles = theme => ({
myPaper: {
padding: 16
}
});
class PageSettings extends React.Component {
render() {
const { classes } = this.props;
return (
<Paper className={classes.myPaper}>
<Grid container spacing={24}>
<Grid item xs={11}>
<Typography variant="display1" gutterBottom>
Paramètres
</Typography>
</Grid>
</Grid>
<Settings />
</Paper>
);
}
}
PageSettings.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(PageSettings);
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import Typography from '@material-ui/core/Typography';
import AddIcon from '@material-ui/icons/Add';
// import MarkdownElement from '@material-ui/docs/MarkdownElement';
const styles = theme => ({
root: {
position: 'relative',
overflow: 'hidden',
},
appFrame: {
position: 'relative',
height: 390,
backgroundColor: theme.palette.background.paper,
},
statusBar: {
width: '100%',
height: 24,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
code: {
marginTop: theme.spacing.unit,
'& pre': {
margin: '0px !important',
},
},
fab: {
position: 'absolute',
bottom: theme.spacing.unit * 2,
right: theme.spacing.unit * 2,
},
});
function ColorDemo(props) {
const { classes, data, theme } = props;
const primary = {
main: data.primary,
output:
data.primaryShade === 4
? `${data.primaryHue}`
: `{
main: '${data.primary}',
}`,
};
const secondary = {
main: data.secondary,
output:
data.secondaryShade === 11
? `${data.secondaryHue}`
: `{
main: '${data.secondary}',
}`,
};
theme.palette.augmentColor(primary);
theme.palette.augmentColor(secondary);
return (
<div className={classes.root}>
<div className={classes.appFrame}>
<div className={classes.statusBar} style={{ backgroundColor: primary.dark }} />
<AppBar position="static" style={{ backgroundColor: primary.main }}>
<Toolbar style={{ color: primary.contrastText }}>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon />
</IconButton>
<Typography variant="title" color="inherit">
Color sample
</Typography>
</Toolbar>
</AppBar>
{/* <MarkdownElement
dir="ltr"
className={classes.code}
text={`\`\`\`jsx
{
palette: {
primary: ${primary.output},
secondary: ${secondary.output},
},
}
\`\`\``}
/> */}
<Button variant="fab" className={classes.fab} style={{ backgroundColor: secondary.main }}>
<AddIcon nativeColor={secondary.contrastText} />
</Button>
</div>
</div>
);
}
ColorDemo.propTypes = {
classes: PropTypes.object.isRequired,
data: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
export default withStyles(styles, { withTheme: true })(ColorDemo);
\ No newline at end of file
// Taken from https://github.com/mui-org/material-ui/blob/master/docs/src/pages/style/color/ColorTool.js
// MIT Licence and modified
import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import compose from 'recompose/compose';
import { withStyles } from '@material-ui/core/styles';
import * as colors from '@material-ui/core/colors';
import Grid from '@material-ui/core/Grid';
import Input from '@material-ui/core/Input';
import Radio from '@material-ui/core/Radio';
import Tooltip from '@material-ui/core/Tooltip';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import CheckIcon from '@material-ui/icons/Check';
import Slider from '@material-ui/lab/Slider';
import { rgbToHex } from '@material-ui/core/styles/colorManipulator';
import { capitalize } from '@material-ui/core/utils/helpers';
// import actionTypes from 'docs/src/modules/redux/actionTypes';
import ColorDemo from './ColorDemo';
import { saveAppTheme } from '../../actions/theme';
const hues = Object.keys(colors).slice(1, 17);
const shades = [900, 800, 700, 600, 500, 400, 300, 200, 100, 50, 'A700', 'A400', 'A200', 'A100'];
const styles = theme => ({
radio: {
width: 48,
height: 48,
},
radioSelected: {
width: 48,
height: 48,
border: '1px solid white',
color: theme.palette.common.white,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
swatch: {
width: 192,
},
sliderContainer: {
display: 'flex',
alignItems: 'center',
marginTop: theme.spacing.unit * 2,
marginBottom: theme.spacing.unit,
},
slider: {
width: 'calc(100% - 80px)',
},
colorBar: {
marginTop: theme.spacing.unit * 2,
},
colorSquare: {
width: 64,
height: 64,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
},
});
class ColorTool extends React.Component {
state = {
primary: '#2196f3',
secondary: '#f50057',
primaryInput: '#2196f3',
secondaryInput: '#f50057',
primaryHue: 'blue',
secondaryHue: 'pink',
primaryShade: 4,
secondaryShade: 11,
};
handleChangeColor = name => event => {
const isRgb = string => /#?([0-9a-f]{6})/i.test(string);
const {
target: { value: color },
} = event;
this.setState({
[`${name}Input`]: color,
});
if (isRgb(color)) {
this.setState({
[name]: color,
});
}
};
handleChangeHue = name => event => {
const {
target: { value: hue },
} = event;
this.setState(state => {
const color = colors[hue][shades[state[`${name}Shade`]]];
return {
[`${name}Hue`]: hue,
[name]: color,
[`${name}Input`]: color,
};
});
};
handleChangeShade = name => (event, shade) => {
this.setState(state => {
const color = colors[state[`${name}Hue`]][shades[shade]];
return {
[`${name}Shade`]: shade,
[name]: color,
[`${name}Input`]: color,
};
});
};
handleChangeDocsColors = () => {
this.props.saveTheme({
palette: {
primary: { main: this.state.primary },
secondary: { main: this.state.secondary },
},
})
};
render() {
const { classes, theme } = this.props;
console.log(theme)
const { primaryShade, secondaryShade } = this.state;
const colorBar = color => {
const background = { main: color };
theme.palette.augmentColor(background);
return (
<Grid container className={classes.colorBar}>
{['dark', 'main', 'light'].map(key => (
<div
className={classes.colorSquare}
style={{ backgroundColor: background[key] }}
key={key}
>
<Typography
variant="caption"
style={{ color: theme.palette.getContrastText(background[key]) }}
>
{rgbToHex(background[key])}
</Typography>
</div>
))}
</Grid>
);
};
const colorPicker = intent => {
const intentInput = this.state[`${intent}Input`];
const intentShade = this.state[`${intent}Shade`];
const color = this.state[`${intent}`];
return (
<Grid item xs={12} sm={6} md={4}>
<Typography gutterBottom variant="title">
{capitalize(intent)}
</Typography>
<Input
id={intent}
value={intentInput}
onChange={this.handleChangeColor(intent)}
inputProps={{
'aria-label': `${capitalize(intent)} color`,
}}
fullWidth
/>
<div className={classes.sliderContainer}>
<Typography id={`${intent}ShadeSliderLabel`}>Shade:</Typography>
<Slider
className={classes.slider}
value={intentShade}
min={0}
max={13}
step={1}
onChange={this.handleChangeShade(intent)}
aria-labelledby={`${intent}ShadeSliderLabel`}
/>
<Typography>{shades[intentShade]}</Typography>
</div>
<div className={classes.swatch}>
{hues.map(hue => {
const shade = intent === 'primary' ? shades[primaryShade] : shades[secondaryShade];
const backgroundColor = colors[hue][shade];
return (
<Tooltip placement="right" title={hue} key={hue}>
<Radio
color="default"
checked={this.state[intent] === backgroundColor}
onChange={this.handleChangeHue(intent)}
value={hue}
name={intent}
aria-labelledby={`tooltip-${intent}-${hue}`}
icon={<div className={classes.radio} style={{ backgroundColor }} />}
checkedIcon={
<div className={classes.radioSelected} style={{ backgroundColor }}>
<CheckIcon style={{ fontSize: 30 }} />
</div>
}
/>
</Tooltip>
);
})}
</div>
{colorBar(color)}
</Grid>
);
};
return (
<Grid container spacing={40} className={classes.root}>
{colorPicker('primary')}
{colorPicker('secondary')}
<Grid item xs={12} sm={6} md={4}>
<ColorDemo data={this.state} />
</Grid>
<Grid item xs={12}>
<Button variant="contained" color="primary" onClick={this.handleChangeDocsColors}>
Set Docs Colors
</Button>
</Grid>
</Grid>
);
}
}
ColorTool.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => Object();
const mapDispatchToProps = (dispatch) => {
return {
saveTheme: (theme) => dispatch(saveAppTheme(theme))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles, { withTheme: true })(ColorTool));
import React from 'react';
import MyComponent from '../MyComponent'
import { connect } from "react-redux";
import _ from 'underscore';
import ColorTools from './ColorTools';
// import { saveSelectedUniversities, saveSettingsConfig } from '../../actions/Settings';
// import {
// universitiesFetchData,
// mainCampusesFetchData,
// citiesFetchData,
// countriesFetchData
// } from '../../generated/actions';
class Settings extends MyComponent {
myRender() {
return (
<ColorTools style={{backgroundColor:"#eeeeee"}}></ColorTools>
);
}
}
// const mapStateToProps = (state) => {
// return {
// universities: state.universities,
// mainCampuses: state.mainCampuses,
// cities: state.cities,
// countries: state.countries,
// contriesSettingsConfig: state.app.Settings.contriesSettings
// };
// };
// const mapDispatchToProps = (dispatch) => {
// return {
// fetchData: {
// universities: () => dispatch(universitiesFetchData()),
// mainCampuses: () => dispatch(mainCampusesFetchData()),
// cities: () => dispatch(citiesFetchData()),
// countries: () => dispatch(countriesFetchData())
// },
// saveSelection: (selectedUniversities) => dispatch(saveSelectedUniversities(selectedUniversities)),
// saveConfig: (config) => dispatch(saveSettingsConfig(config))
// };
// };
// export default connect(mapStateToProps, mapDispatchToProps)(Settings);
export default Settings;
......@@ -10,6 +10,7 @@ import BarChartIcon from '@material-ui/icons/BarChart';
import HomeIcon from '@material-ui/icons/Home';
import SearchIcon from '@material-ui/icons/Search';
import FilterIcon from '@material-ui/icons/FilterList';
import SettingsIcon from '@material-ui/icons/Settings';
import AssignmentIcon from '@material-ui/icons/Assignment';
import { NavLink } from 'react-router-dom'
......@@ -59,6 +60,15 @@ export const mainListItems = (
<ListItemText primary="Université" />
</ListItem>
<NavLink to={'/app/settings/'}>
<ListItem button>
<ListItemIcon>
<SettingsIcon />
</ListItemIcon>
<ListItemText primary="Paramètres" />
</ListItem>
</NavLink>
<ListItem button>
<ListItemIcon>
<PeopleIcon />
......
......@@ -7,14 +7,15 @@ import { BrowserRouter as Router, Route } from 'react-router-dom';
import store from "./store/index";
import App from "./components/App";
import ThemeProvider from './components/ThemeProvider'
const MainReactEntry = () => (
<Provider store={store}>
<Router>
<React.StrictMode>
<ThemeProvider>
<Route path="/:filter?" component={App} />
</ThemeProvider>
</React.StrictMode>
</Router>
</Provider>
);
......
......@@ -15,7 +15,7 @@ export function saveSelectedUniversities(state = [], action) {
export function saveFilterConfig(state = { contriesFilter: { selectedItems: [], inputValue: '' } }, action) {
switch (action.type) {
case SAVE_FILTER_CONFIG:
return Object.assign(state, action.config)
return Object.assign({}, state, action.config)
default:
return state;
......
......@@ -13,11 +13,13 @@ import {
import { saveMainMapPosition } from './map';
import { saveSelectedUniversities } from './filter';
import { saveFilterConfig } from './filter';
import { saveAppTheme } from './theme';
const appReducers = combineReducers({
mainMap: saveMainMapPosition,
selectedUniversities: saveSelectedUniversities,
filter: saveFilterConfig,
appTheme: saveAppTheme
})
const rootReducer = combineReducers({
......
import { SAVE_SELECTED_UNIVERSITIES, SAVE_FILTER_CONFIG } from '../actions/action-types'
export function saveSelectedUniversities(state = [], action) {
switch (action.type) {
case SAVE_SELECTED_UNIVERSITIES:
return {
selection: action.new_selection,
}
default:
return state;
}
}
export function saveFilterConfig(state = { contriesFilter: { selectedItems: [], inputValue: '' } }, action) {
switch (action.type) {
case SAVE_FILTER_CONFIG:
return Object.assign({}, state, action.config)
default:
return state;
}
}
import { SAVE_APP_THEME } from '../actions/action-types'
import indigo from '@material-ui/core/colors/indigo';
import pink from '@material-ui/core/colors/pink';
const defaultTheme = {
palette: {
primary: pink,
secondary: indigo, // Indigo is probably a good match with pink,
type: 'dark'
}
}
export function saveAppTheme(state = defaultTheme, action) {
switch (action.type) {
case SAVE_APP_THEME:
return Object.assign({}, state, action.theme)
default:
return state;
}
}
......@@ -2,7 +2,11 @@
<html>
<head>
<meta charset="utf-8">
<meta
charset="utf-8"
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
/>
<title>Outgoing REX</title>
</head>
......
......@@ -81,6 +81,17 @@
}
}
},
"@material-ui/docs": {
"version": "1.0.0-alpha.5",
"resolved": "https://registry.npmjs.org/@material-ui/docs/-/docs-1.0.0-alpha.5.tgz",
"integrity": "sha512-JeXSV4ICzL4xf9dZhAi/2N3EMkZT22z2GBF5tf/KjNXOKbb7yp93b2YLKl/Z1Ua4IIi28oh5YTRJ5v2mZK3MAQ==",
"requires": {
"@babel/runtime": "7.0.0-rc.1",
"marked": "^0.5.0",
"nprogress": "^0.2.0",
"prismjs": "^1.8.4"
}
},
"@material-ui/icons": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-2.0.3.tgz",
......@@ -91,6 +102,31 @@
"recompose": "^0.28.0"
}
},
"@material-ui/lab": {
"version": "3.0.0-alpha.14",
"resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-3.0.0-alpha.14.tgz",