Commit c5398c92 authored by Florent Chehab's avatar Florent Chehab

Work on post_date for color finished

parent 0f49c032
Pipeline #26974 passed with stages
in 2 minutes and 31 seconds
......@@ -39,6 +39,6 @@ class UserDataViewSet(MyModelViewSet):
permission_classes = get_viewset_permissions("UserDataViewSet")
serializer_class = UserDataSerializer
BYPASS_DICT_MODE = True
def get_queryset(self):
return UserData.objects.filter(owner=self.request.user) # pylint: disable=E1101
......@@ -68,7 +68,7 @@ function _ElSaveData(data, api_end_point, _ElIsSaving, _ElFetchDataSuccess, _ElI
let pk = "";
if ('id' in data){
method = "PUT";
pk = data.id;
pk = data.id + '/';
}
dispatch(_ElIsSaving(true));
......
......@@ -28,9 +28,6 @@ import {
import {
countriesFetchData,
currenciesFetchData,
userDataElFetchData,
userDataElSaveData,
userDataElFetchHasError,
} from '../generated/actions';
......@@ -110,24 +107,7 @@ class App extends MyComponent {
state = {
open: true,
};
myComponentDidUpdate() {
// load the correct user data
if (this.props.userDataEl.isLoading) {
return false;
}
const userData = this.getFetchedData("userDataEl");
if (userData instanceof Array) {
if (userData.length == 0) {
if (!this.props.userDataEl.isSaving) {
this.props.createUserData();
}
} else if (userData.length == 1) {
this.props.fetchUserDataSingle(userData[0].id)
} else {
throw Error("We shouldn't have more thant one here !")
}
}
}
handleDrawerOpen = () => {
this.setState({ open: true });
......@@ -200,19 +180,15 @@ const mapStateToProps = (state) => {
return {
countries: state.countries,
currencies: state.currencies,
userDataEl: state.userDataEl
}
};
const mapDispatchToProps = (dispatch) => {
return {
fetchUserDataSingle: (id) => dispatch(userDataElFetchData(id)),
fetchData: {
countries: () => dispatch(countriesFetchData()),
currencies: () => dispatch(currenciesFetchData()),
userDataEl: () => dispatch(userDataElFetchData("")),
},
createUserData: () => dispatch(userDataElSaveData(Object()))
};
};
......
......@@ -3,6 +3,28 @@ import Loading from './other/Loading';
class MyComponent extends Component {
customErrorHandlers = {}
requireUserData = false;
// If true,
// You need to import
// userDataElFetchData,
// userDataElSaveData,
//your mapStateToProps should contain:
// const mapStateToProps = (state) => {
// return {
// userDataEl: state.userDataEl
// }
// };
//
// And your mapDispatchToProps should have:
// const mapDispatchToProps = (dispatch) => {
// return {
// fetchUserDataSingle: (id) => dispatch(userDataElFetchData(id)),
// fetchData: {
// userDataEl: () => dispatch(userDataElFetchData("")),
// },
// createUserData: () => dispatch(userDataElSaveData(Object()))
// };
// };
getFetchedData(prop) {
return this.props[prop].fetched.data;
......@@ -10,8 +32,12 @@ class MyComponent extends Component {
getAllFetchedData() {
let out = Object()
for (let prop_key in this.props) {
let prop = this.props[prop_key];
const { props } = this;
for (let prop_key in props) {
let prop = props[prop_key];
if (typeof prop == 'boolean') {
continue;
}
if (prop && 'fetched' in prop) {
out[prop_key] = prop.fetched.data;
}
......@@ -29,8 +55,12 @@ class MyComponent extends Component {
}
checkProps(val) {
for (let el in this.props) {
let prop = this.props[el];
const { props } = this;
for (let el in props) {
let prop = props[el];
if (typeof prop == 'boolean') {
continue;
}
if (prop && val in prop && prop[val]) {
return true;
}
......@@ -39,11 +69,15 @@ class MyComponent extends Component {
}
checkPropsHasError() {
for (let prop_key in this.props) {
let prop = this.props[prop_key];
const { props } = this;
for (let prop_key in props) {
let prop = props[prop_key];
if (typeof prop == 'boolean') {
continue;
}
if (prop && 'fetchHasError' in prop) {
if (prop.fetchHasError.status) {
if (prop_key in this.customErrorHandlers){
if (prop_key in this.customErrorHandlers) {
console.log("icicicicici");
} else {
return true;
......@@ -67,15 +101,19 @@ class MyComponent extends Component {
}
loadPropsIfNeeded() {
if (this.checkPropsHasError()){
if (this.checkPropsHasError()) {
return false;
}
for (let prop_key in this.props) {
let prop = this.props[prop_key];
const { props } = this;
for (let prop_key in props) {
let prop = props[prop_key];
if (typeof prop == 'boolean') {
continue;
}
if (prop && 'fetched' in prop) {
if ((!prop.fetched.fetchedAt) || prop.invalidated) {
if (!prop.isLoading) {
this.props.fetchData[prop_key]();
props.fetchData[prop_key]();
}
}
}
......@@ -91,6 +129,27 @@ class MyComponent extends Component {
componentDidUpdate() {
// TODO ajouter expire date
this.loadPropsIfNeeded();
if (this.requireUserData) {
//TODO cleaner too many loads
// load the correct user data
const { userDataEl } = this.props;
if (userDataEl.isLoading || userDataEl.isSaving) {
return;
}
const userData = this.getFetchedData("userDataEl");
if (userData instanceof Array) {
if (userData.length == 0) {
if (!this.props.userDataEl.isSaving) {
this.props.createUserData();
}
} else if (userData.length == 1) {
this.props.fetchUserDataSingle(userData[0].id)
} else {
throw Error("We shouldn't have more thant one here !")
}
}
}
this.myComponentDidUpdate();
}
myComponentDidUpdate() { };
......
......@@ -4,15 +4,49 @@ 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';
import MyComponent from './MyComponent';
import areSameThemes from '../utils/areSameThemes';
import {
userDataElSaveData,
userDataElFetchData
} from '../generated/actions';
import { saveAppTheme } from '../actions/theme';
class ThemeProvider extends React.Component {
render() {
class ThemeProvider extends MyComponent {
requireUserData = true;
state = { theme: this.props.themeSavedInTheApp.theme };
myComponentDidUpdate() {
const currentTheme = this.state.theme;
const themeSavedInTheApp = this.props.themeSavedInTheApp.theme;
const themeSavedInTheAppAt = this.props.themeSavedInTheApp.savedAt;
let themeOnServer = Object();
let themeOnServerRetrievedAt = 0;
try {
themeOnServer = this.props.userDataEl.fetched.data.config.theme;
themeOnServerRetrievedAt = this.props.userDataEl.fetched.fetchedAt;
} catch (e) {
if (!e instanceof TypeError) {
throw e;
}
}
const themeToRender = themeSavedInTheAppAt > themeOnServerRetrievedAt ? themeSavedInTheApp : themeOnServer;
if ((!areSameThemes(themeToRender, currentTheme)) && typeof themeToRender != 'undefined') {
this.setState({ theme: themeToRender });
if (!areSameThemes(themeToRender, themeSavedInTheApp)){
this.props.saveTheme(themeToRender);
}
}
}
myRender() {
return (
<div>
<MuiThemeProvider theme={createMuiTheme(this.props.theme)}>
<MuiThemeProvider theme={createMuiTheme(this.state.theme)}>
<Router>
{this.props.children}
</Router>
......@@ -24,9 +58,20 @@ class ThemeProvider extends React.Component {
const mapStateToProps = (state) => {
return {
theme: state.app.appTheme
themeSavedInTheApp: state.app.appTheme,
userDataEl: state.userDataEl
};
};
const mapDispatchToProps = (dispatch) => {
return {
saveTheme: (theme) => dispatch(saveAppTheme(theme)),
fetchUserDataSingle: (id) => dispatch(userDataElFetchData(id)),
fetchData: {
userDataEl: () => dispatch(userDataElFetchData("")),
},
createUserData: () => dispatch(userDataElSaveData(Object()))
};
};
export default connect(mapStateToProps)(ThemeProvider);
export default connect(mapStateToProps, mapDispatchToProps)(ThemeProvider);
......@@ -8,7 +8,6 @@ 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';
......@@ -16,16 +15,23 @@ 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, saveAppColorPicker } from '../../actions/theme';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Switch from '@material-ui/core/Switch';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import MuiThemeProvider from '@material-ui/core/styles/MuiThemeProvider';
import areSameThemes from '../../utils/areSameThemes';
import areSameObjects from '../../utils/areSameObjets';
import MyComponent from '../MyComponent'
import { saveAppTheme, saveAppColorPicker } from '../../actions/theme';
import {
userDataElSaveData,
userDataElFetchData
} from '../../generated/actions';
const hues = Object.keys(colors).slice(1, 17);
const shades = [900, 800, 700, 600, 500, 400, 300, 200, 100, 50, 'A700', 'A400', 'A200', 'A100'];
......@@ -68,34 +74,46 @@ const styles = theme => ({
},
});
class ColorTool extends React.Component {
// TODO switch to my component
class ColorTool extends MyComponent {
requireUserData = true;
state = this.props.state
componentWillUnmount() {
this.props.saveColorPicker(this.state);
}
componentDidMount() {
if (JSON.stringify(this.props.state) != JSON.stringify(this.state)) {
myComponentDidMount() {
if (areSameObjects(this.props.state, this.state)) {
this.setState(this.props.state);
}
}
handleChangeColor = name => event => {
const isRgb = string => /#?([0-9a-f]{6})/i.test(string);
const {
target: { value: color },
} = event;
myComponentDidUpdate() {
this.setState({
[`${name}Input`]: color,
});
try {
const themeOnServerRetrievedAt = this.props.userDataEl.fetched.fetchedAt;
if (themeOnServerRetrievedAt > this.state.updatedAt) {
const configOnServer = this.props.userDataEl.fetched.data.config;
const colorPickerConfigOnServer = configOnServer.colorPicker;
const themeOnServer = configOnServer.theme;
// we need to set the color picker colors from server color
const primary = themeOnServer.palette.primary.main;
const secondary = themeOnServer.palette.secondary.main;
this.setState({
updatedAt: Date.now(),
primary,
secondary,
primaryHue: colorPickerConfigOnServer.primaryHue,
secondaryHue: colorPickerConfigOnServer.secondaryHue,
primaryShade: colorPickerConfigOnServer.primaryShade,
secondaryShade: colorPickerConfigOnServer.secondaryShade,
darkModeActivated: themeOnServer.palette.type == 'light' ? false : true
});
}
} catch (e) { if (!(e instanceof TypeError)) { throw e; } }
if (isRgb(color)) {
this.setState({
[name]: color,
});
}
};
}
handleChangeHue = name => event => {
const {
......@@ -107,7 +125,7 @@ class ColorTool extends React.Component {
return {
[`${name}Hue`]: hue,
[name]: color,
[`${name}Input`]: color,
updatedAt: Date.now()
};
});
};
......@@ -118,18 +136,19 @@ class ColorTool extends React.Component {
return {
[`${name}Shade`]: shade,
[name]: color,
[`${name}Input`]: color,
updatedAt: Date.now()
};
});
};
handleChangeNightMode() {
this.setState({
darkModeActivated: !this.state.darkModeActivated
darkModeActivated: !this.state.darkModeActivated,
updatedAt: Date.now()
})
}
handleChangeDocsColors = () => {
handleChangeColorSite = () => {
this.props.saveTheme(this.getThemeFromState());
};
......@@ -143,7 +162,32 @@ class ColorTool extends React.Component {
}
}
render() {
getThemeFromProps() {
const { currentUiTheme } = this.props;
const currentTheme = {
palette: {
primary: { main: currentUiTheme.palette.primary.main },
secondary: { main: currentUiTheme.palette.secondary.main },
type: currentUiTheme.palette.type
}
}
return currentTheme;
}
handleSendToServer = () => {
const userData = this.props.userDataEl.fetched.data;
let newUserData = Object.assign({}, userData);
newUserData.config.theme = this.getThemeFromProps();
newUserData.config.colorPicker = {
primaryHue: this.state.primaryHue,
secondaryHue: this.state.secondaryHue,
primaryShade: this.state.primaryShade,
secondaryShade: this.state.secondaryShade,
};
this.props.saveToServer(newUserData);
}
myRender() {
const { classes, theme } = this.props;
const { primaryShade, secondaryShade } = this.state;
......@@ -172,7 +216,6 @@ class ColorTool extends React.Component {
};
const colorPicker = intent => {
const intentInput = this.state[`${intent}Input`];
const intentShade = this.state[`${intent}Shade`];
const color = this.state[`${intent}`];
const caption = intent == 'primary' ? "Couleur primaire" : "Couleur secondaire";
......@@ -181,15 +224,6 @@ class ColorTool extends React.Component {
<Typography gutterBottom variant="title">
{caption}
</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`}>Nuance :</Typography>
<Slider
......@@ -233,14 +267,17 @@ class ColorTool extends React.Component {
);
};
const { currentUiTheme } = this.props;
const tmp = {
palette: {
primary: { main: currentUiTheme.palette.primary.main },
secondary: { main: currentUiTheme.palette.secondary.main }
}
const currentTheme = this.getThemeFromProps();
const userData = this.props.userDataEl.fetched.data;
let themeOnServer = null;
if (this.props.userDataEl.fetched.fetchedAt && 'config' in userData && 'theme' in userData.config) {
themeOnServer = userData.config.theme
}
const hasChanges = JSON.stringify(tmp) != JSON.stringify(this.getThemeFromState());
const themeIsDifferentOnServer = !areSameThemes(themeOnServer, currentTheme);
const hasChanges = !areSameThemes(currentTheme, this.getThemeFromState());
return (
<Grid container spacing={40} className={classes.root}>
......@@ -265,14 +302,18 @@ class ColorTool extends React.Component {
</MuiThemeProvider >
</Grid>
<Grid item xs={6}>
<Button variant="contained" color="secondary" disabled={!hasChanges} onClick={this.handleChangeDocsColors}>
<Button variant="contained" color="primary" disabled={!hasChanges} onClick={this.handleChangeColorSite}>
Appliquer à tout le site
</Button>
</Grid>
<Grid item xs={6}>
<Button variant="contained" color="primary" disabled={true} onClick={console.log("click")}>
Sauvegarder
<Button
variant="contained"
color="secondary"
disabled={!themeIsDifferentOnServer}
onClick={() => this.handleSendToServer()}
>
Sauvegarder le thème du site sur le serveur
</Button>
</Grid>
</Grid>
......@@ -288,15 +329,22 @@ ColorTool.propTypes = {
const mapStateToProps = (state) => {
return {
currentUiTheme: state.app.appTheme,
state: state.app.colorPickerState
currentUiTheme: state.app.appTheme.theme,
state: state.app.colorPickerState,
userDataEl: state.userDataEl
}
};
const mapDispatchToProps = (dispatch) => {
return {
saveTheme: (theme) => dispatch(saveAppTheme(theme)),
saveColorPicker: (partialState) => dispatch(saveAppColorPicker(partialState))
saveColorPicker: (partialState) => dispatch(saveAppColorPicker(partialState)),
saveToServer: (data) => dispatch(userDataElSaveData(data)),
fetchUserDataSingle: (id) => dispatch(userDataElFetchData(id)),
fetchData: {
userDataEl: () => dispatch(userDataElFetchData("")),
},
createUserData: () => dispatch(userDataElSaveData(Object()))
};
};
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles, { withTheme: true })(ColorTool));
......@@ -4,15 +4,19 @@ import pink from '@material-ui/core/colors/pink';
const defaultTheme = {
palette: {
primary: pink,
secondary: indigo, // Indigo is probably a good match with pink,
primary: {main: pink[500]},
secondary: {main: indigo['A400']},
type: 'dark'
}
}
export function saveAppTheme(state = defaultTheme, action) {
export function saveAppTheme(state = { theme: defaultTheme, savedAt: Date.now() }, action) {
switch (action.type) {
case SAVE_APP_THEME:
return Object.assign({}, state, action.theme)
return {
theme: action.theme,
savedAt: Date.now()
}
default:
return state;
......@@ -21,21 +25,19 @@ export function saveAppTheme(state = defaultTheme, action) {
const defaultColorPicker = {
primary: defaultTheme.palette.primary[500],
secondary: defaultTheme.palette.secondary['A400'],
primaryInput: '#2196f3',
secondaryInput: '#f50057',
primary: defaultTheme.palette.primary.main,
secondary: defaultTheme.palette.secondary.main,
primaryHue: 'blue',
secondaryHue: 'pink',
primaryShade: 4,
secondaryShade: 11,
darkModeActivated: defaultTheme.palette.type == 'dark'
darkModeActivated: defaultTheme.palette.type == 'dark',
updatedAt: Date.now()
};
export function saveAppColorPicker(state = defaultColorPicker, action) {
switch (action.type) {
case SAVE_APP_COLOR_PICKER:
console.log("je passe ici !")
return Object.assign({}, state, action.state)
default:
return state;
......
......@@ -4,7 +4,21 @@ import rootReducer from "../reducers/index";
import thunkMiddleware from 'redux-thunk';
import { createLogger } from 'redux-logger';
const loggerMiddleware = createLogger();
import {
SAVE_APP_COLOR_PICKER,
SAVE_APP_THEME
} from '../actions/action-types';
const loggerMiddleware = createLogger(
{ collapsed:
(getState, action, logEntry) => {
const {type} = action;
if (type == SAVE_APP_COLOR_PICKER || type == SAVE_APP_THEME ){
return false;
}
return true;
}
});
const store = createStore(
rootReducer,
......
export default function areSameObject (obj1, obj2) {
return JSON.stringify(obj1) == JSON.stringify(obj2);
}
\ No newline at end of file
import areSameObjets from './areSameObjets';
function extractTheme (theme) {
return {
palette: {
primary: {main: theme.palette.primary.main},
secondary: {main: theme.palette.secondary.main},
type: theme.palette.type
}
}
}
export default function areSameThemes (theme1, theme2) {
if ((!theme1) || (!theme2)){
return false;
}
const forCompareTheme1 = extractTheme(theme1);
const forCompareTheme2 = extractTheme(theme2);
return areSameObjets(forCompareTheme1, forCompareTheme2);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment