Skip to content

Commit 265abb8

Browse files
authored
Merge pull request #1 from flatlogic/theme_customizer
theme customizer
2 parents cf9e540 + c1f6691 commit 265abb8

File tree

12 files changed

+670
-27
lines changed

12 files changed

+670
-27
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
"react-dev-utils": "^6.0.5",
4141
"react-dom": "16.8.3",
4242
"react-draft-wysiwyg": "1.10.12",
43-
"react-mde": "2.3.4",
4443
"react-maskedinput": "^4.0.1",
44+
"react-mde": "2.3.4",
4545
"react-redux": "6.0.1",
4646
"react-router": "4.3.1",
4747
"react-router-dom": "4.3.1",

src/actions/layout.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export const CHANGE_THEME = 'CHANGE_THEME';
2+
export const CHANGE_SIDEBAR_COLOR = 'CHANGE_SIDEBAR_COLOR';
3+
export const CHANGE_NAVBAR_COLOR = 'CHANGE_NAVBAR_COLOR';
4+
export const NAVBAR_TYPE_TOGGLE = 'NAVBAR_TYPE_TOGGLE';
5+
export const SIDEBAR_TYPE_TOGGLE = 'SIDEBAR_TYPE_TOGGLE';
6+
7+
export function changeTheme(payload) {
8+
return {
9+
type: CHANGE_THEME,
10+
payload,
11+
};
12+
}
13+
14+
export function changeSidebarColor(payload) {
15+
return {
16+
type: CHANGE_SIDEBAR_COLOR,
17+
payload,
18+
};
19+
}
20+
21+
export function changeNavbarColor(payload) {
22+
return {
23+
type: CHANGE_NAVBAR_COLOR,
24+
payload,
25+
};
26+
}
27+
28+
export function navbarTypeToggle(value) {
29+
return {
30+
type: NAVBAR_TYPE_TOGGLE,
31+
payload: value
32+
}
33+
}
34+
35+
export function sidebarTypeToggle(value) {
36+
return {
37+
type: SIDEBAR_TYPE_TOGGLE,
38+
payload: value
39+
}
40+
}
41+

src/components/Header/Header.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { connect } from 'react-redux';
33
import PropTypes from 'prop-types';
44
import { withRouter } from 'react-router';
5+
import { NavbarTypes } from '../../reducers/layout';
56
import {
67
Navbar,
78
Nav,
@@ -19,6 +20,7 @@ import {
1920
Form,
2021
FormGroup,
2122
} from 'reactstrap';
23+
import chroma from 'chroma-js';
2224
import cx from 'classnames';
2325
import { logoutUser } from 'actions/auth';
2426
import { toggleSidebar, openSidebar, closeSidebar, changeActiveSidebarItem } from '../../actions/navigation';
@@ -52,12 +54,6 @@ class Header extends React.Component {
5254
};
5355
}
5456

55-
start = () => {
56-
this.setState({
57-
run: true,
58-
});
59-
};
60-
6157
toggleFocus = () => {
6258
this.setState({ focus: !this.state.focus })
6359
}
@@ -100,31 +96,33 @@ class Header extends React.Component {
10096
}
10197
render() {
10298
const { focus } = this.state;
103-
const { openUsersList } = this.props;
99+
const { navbarType, navbarColor, openUsersList } = this.props;
104100

105101
const user = this.props.currentUser;
106102
const avatar = user && user.avatar && user.avatar.length && user.avatar[0].publicUrl;
107103
const firstUserLetter = user && (user.firstName|| user.email)[0].toUpperCase();
108104

109105
return (
110-
<Navbar className={`${s.root} d-print-none`} style={{zIndex: !openUsersList ? 100 : 0}}>
106+
<Navbar className={`${s.root} d-print-none ${navbarType === NavbarTypes.FLOATING ? s.navbarFloatingType : ''}`} style={{backgroundColor: navbarColor, zIndex: !openUsersList ? 100 : 0}}>
111107
<Nav>
112108
<NavItem>
113109
<NavLink className="d-md-down-none ml-5" id="toggleSidebar" onClick={this.toggleSidebar}>
114-
<i className={`la la-bars`}/>
110+
<i className={`la la-bars ${chroma(navbarColor).luminance() < 0.4 ? "text-white" : ""}`}/>
115111
</NavLink>
116112
<UncontrolledTooltip placement="bottom" target="toggleSidebar">
117113
Turn on/off<br />sidebar<br />collapsing
118114
</UncontrolledTooltip>
119115
<NavLink className="fs-lg d-lg-none" onClick={this.switchSidebar}>
120116
<span
121117
className={`rounded rounded-lg d-md-none d-sm-down-block`}>
122-
<i
123-
className="la la-bars"
124-
style={{fontSize: 30}}
118+
<i
119+
className="la la-bars"
120+
style={{fontSize: 30, color: navbarColor === "#ffffff"
121+
? "#ffffff"
122+
: chroma(navbarColor).luminance() < 0.4 ? "#ffffff" : ""}}
125123
/>
126124
</span>
127-
<i className={`la la-bars ml-3 d-sm-down-none`}/>
125+
<i className={`la la-bars ml-3 d-sm-down-none ${chroma(navbarColor).luminance() < 0.4 ? "text-white" : ""}`}/>
128126
</NavLink>
129127
</NavItem>
130128
</Nav>
@@ -142,7 +140,7 @@ class Header extends React.Component {
142140
</FormGroup>
143141
</Form>
144142

145-
<NavLink className={`${s.navbarBrand} d-md-none`}>
143+
<NavLink className={`${s.navbarBrand} d-md-none ${chroma(navbarColor).luminance() < 0.4 ? "text-white" : ""}`}>
146144
<i className="la la-circle text-primary mr-n-sm" />
147145
<i className="la la-circle text-danger" />
148146
&nbsp;
@@ -156,16 +154,16 @@ class Header extends React.Component {
156154
<NavbarText>
157155
<span className={`${s.avatar} rounded-circle thumb-sm float-left mr-2`}>
158156
{avatar ? (
159-
<img src={avatar} alt="..."/>
157+
<img src={avatar} alt="..." title={user && (user.firstName || user.email)} />
160158
) : (
161-
<span>{firstUserLetter}</span>
159+
<span title={user && (user.firstName || user.email)}>{firstUserLetter}</span>
162160
)}
163161
</span>
164-
<span>{user && (user.firstName || user.email)}</span>
162+
<span className={`d-sm-down-none ${chroma(navbarColor).luminance() < 0.4 ? "text-white" : ""}`}>{user && (user.firstName || user.email)}</span>
165163
</NavbarText>
166-
<Dropdown nav isOpen={this.state.menuOpen} toggle={this.toggleMenu} className="d-sm-down-none tutorial-dropdown pr-4">
164+
<Dropdown nav isOpen={this.state.menuOpen} toggle={this.toggleMenu} className="tutorial-dropdown pr-4">
167165
<DropdownToggle nav>
168-
<i className={`la la-cog`} />
166+
<i className={`la la-cog ${chroma(navbarColor).luminance() < 0.4 ? "text-white" : ""}`} />
169167
</DropdownToggle>
170168
<DropdownMenu right className={`super-colors`}>
171169
<DropdownItem href="/#/app/profile"><i className="la la-user" /> My Account</DropdownItem>
@@ -183,6 +181,8 @@ function mapStateToProps(store) {
183181
sidebarOpened: store.navigation.sidebarOpened,
184182
sidebarStatic: store.navigation.sidebarStatic,
185183
currentUser: store.auth.currentUser,
184+
navbarType: store.layout.navbarType,
185+
navbarColor: store.layout.navbarColor,
186186
};
187187
}
188188

src/components/Header/Header.module.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
height: $navbar-height;
88
transition: background-color .2s ease, margin .2s ease, ;
99

10+
&.navbarFloatingType {
11+
margin: $spacer $content-padding 0;
12+
border-radius: $border-radius;
13+
14+
@media (max-width: breakpoint-max(sm)) {
15+
margin-left: $content-padding-sm;
16+
margin-right: $content-padding-sm;
17+
}
18+
}
19+
1020
a {
1121
color: #495057
1222
}

src/components/Helper/Helper.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import React, { Component } from 'react';
2+
import cx from 'classnames';
3+
import { Button } from 'reactstrap';
4+
import PropTypes from 'prop-types';
5+
import { connect } from 'react-redux';
6+
import { DashboardThemes, SidebarTypes, NavbarTypes } from '../../reducers/layout';
7+
import { changeTheme, changeSidebarColor, changeNavbarColor, navbarTypeToggle, sidebarTypeToggle } from '../../actions/layout';
8+
import CustomColorPicker from '../ColorPicker';
9+
import config from '../../config';
10+
11+
import Widget from '../Widget';
12+
13+
import s from './Helper.module.scss'; // eslint-disable-line
14+
15+
class Helper extends Component {
16+
static propTypes = {
17+
dispatch: PropTypes.func.isRequired,
18+
dashboardTheme: PropTypes.string
19+
};
20+
21+
static defaultProps = {
22+
dashboardTheme: DashboardThemes.DARK
23+
};
24+
25+
state = {
26+
isOpened: false,
27+
}
28+
29+
toggle = () => {
30+
this.setState({
31+
isOpened: !this.state.isOpened,
32+
});
33+
};
34+
35+
changeTheme = (state) => {
36+
this.props.dispatch(changeTheme(state));
37+
this.props.dispatch(changeSidebarColor(state))
38+
};
39+
40+
navbarStateToggle = (state) => {
41+
this.props.dispatch(navbarTypeToggle(state))
42+
}
43+
44+
sidebarStateToggle = (state) => {
45+
this.props.dispatch(sidebarTypeToggle(state))
46+
}
47+
48+
updateColor = (value) => {
49+
this.props.dispatch(changeNavbarColor(value))
50+
}
51+
52+
render() {
53+
const { isOpened } = this.state;
54+
const { navbarColor, sidebarColor, navbarType, sidebarType } = this.props;
55+
56+
return (
57+
<div className={cx(s.themeHelper, { [s.themeHelperOpened]: isOpened })}>
58+
<div className={`${s.themeHelperBtn} bg-primary helper-button`} onClick={this.toggle}>
59+
<div className={cx(s.themeHelperSpinner, 'text-white')}>
60+
<i className="la la-cog" />
61+
<i className="la la-cog" />
62+
</div>
63+
</div>
64+
<Widget
65+
className={s.themeHelperContent}
66+
>
67+
<div className={s.helperHeader}>
68+
<h5 className="m-0">Theme Customizer</h5>
69+
</div>
70+
71+
<div className="theme-settings">
72+
<h5 className="navbar-type-switcher">Navbar Type</h5>
73+
<div className="form-group row">
74+
<div className="abc-radio">
75+
<input onChange={() => this.navbarStateToggle(NavbarTypes.STATIC)} type="radio" checked={navbarType === NavbarTypes.STATIC ? true : ''} name="navbar-type" id="navbar_static" />
76+
<label htmlFor="navbar_static">Static</label>
77+
</div>
78+
79+
<div className="abc-radio">
80+
<input onChange={() => this.navbarStateToggle(NavbarTypes.FLOATING)} type="radio" checked={navbarType === NavbarTypes.FLOATING ? true : ''} name="navbar-type" id="navbar_floating" />
81+
<label htmlFor="navbar_floating">Floating</label>
82+
</div>
83+
</div>
84+
85+
<h5 className="mt-4 navbar-color-picker">Navbar Color</h5>
86+
<CustomColorPicker
87+
colors={config.app.colors}
88+
activeColor={navbarColor}
89+
updateColor={this.updateColor}
90+
customizationItem={"navbar"}
91+
/>
92+
93+
<h5 className="mt-4 sidebar-type-switcher">Sidebar Type</h5>
94+
<div className="form-group row">
95+
<div className="abc-radio">
96+
<input type="radio" onChange={() => this.sidebarStateToggle(SidebarTypes.TRANSPARENT)} checked={sidebarType === SidebarTypes.TRANSPARENT ? true : ''} name="sidebar-type" id="sidebar_transparent" />
97+
<label htmlFor="sidebar_transparent">Transparent</label>
98+
</div>
99+
100+
<div className="abc-radio">
101+
<input type="radio" onChange={() => this.sidebarStateToggle(SidebarTypes.SOLID)} checked={sidebarType === SidebarTypes.SOLID ? true : ''} name="sidebar-type" id="sidebar_solid" />
102+
<label htmlFor="sidebar_solid">Solid</label>
103+
</div>
104+
</div>
105+
106+
<h5 className="mt-4 sidebar-color-picker">Sidebar Color</h5>
107+
<CustomColorPicker
108+
colors={config.app.colors}
109+
activeColor={sidebarColor}
110+
updateColor={this.changeTheme}
111+
customizationItem={"sidebar"}
112+
/>
113+
114+
</div>
115+
<div className="mt-5">
116+
<Button
117+
href="https://flatlogic.com/admin-dashboards/sing-app-react"
118+
target="_blank"
119+
className="btn-rounded-f btn-block fs-mini purchase-button"
120+
color="info"
121+
>
122+
<span className="text-white">Purchase</span>
123+
</Button>
124+
<Button
125+
href="http://demo.flatlogic.com/sing-app/documentation/"
126+
target="_blank"
127+
className="btn-rounded-f btn-block fs-mini text-white"
128+
color="primary"
129+
>
130+
Documentation
131+
</Button>
132+
</div>
133+
<div className="d-flex justify-content-between mt-lg">
134+
<Button
135+
href="https://flatlogic.com/contact"
136+
target="_blank"
137+
className="btn-outline-default btn-rounded-f fs-mini text-muted px-2"
138+
>
139+
<i className="glyphicon glyphicon-headphones mr-xs" />
140+
Support
141+
</Button>
142+
<Button
143+
href="https://github.com/flatlogic/sing-app"
144+
target="_blank"
145+
className="btn-outline-default btn-rounded-f fs-mini text-muted px-2"
146+
>
147+
<i className="fa fa-github mr-xs" />
148+
Github
149+
</Button>
150+
</div>
151+
<div className="mt-lg d-flex flex-column align-items-center theme-helper__sharing">
152+
<span className="fs-sm">
153+
Thank you for sharing!
154+
</span>
155+
<div className="d-flex justify-content-center text-light mt-2">
156+
<a
157+
target="_blank"
158+
rel="noopener noreferrer"
159+
href="https://twitter.com/intent/tweet?text=Amazing%20dashboard%20built%20with%20NodeJS,%20React%20and%20Bootstrap!&url=https://github.com/flatlogic/react-dashboard&via=flatlogic"
160+
>
161+
<i className="fa fa-twitter pr-1" />
162+
</a>
163+
<a
164+
href="https://www.facebook.com/search/top/?q=flatlogic%20llc"
165+
target="_blank"
166+
rel="noopener noreferrer"
167+
>
168+
<i className="fa fa-facebook pl-1" />
169+
</a>
170+
</div>
171+
</div>
172+
</Widget>
173+
</div>
174+
);
175+
}
176+
}
177+
178+
function mapStateToProps(store) {
179+
return {
180+
dashboardTheme: store.layout.dashboardTheme,
181+
sidebarColor: store.layout.sidebarColor,
182+
navbarColor: store.layout.navbarColor,
183+
navbarType: store.layout.navbarType,
184+
sidebarType: store.layout.sidebarType
185+
};
186+
}
187+
188+
export default connect(mapStateToProps)(Helper);

0 commit comments

Comments
 (0)