Commit 3a1c4db9 authored by Elias Nahum's avatar Elias Nahum

Layout when logged in

parent 0d99c595
...@@ -54,7 +54,7 @@ stop-server: ...@@ -54,7 +54,7 @@ stop-server:
@echo Stopping ZBox Manager 2.0 Test Server @echo Stopping ZBox Manager 2.0 Test Server
@for PROCID in $$(ps -ef | grep "[b]abel-node.*server" | awk '{ print $$2 }'); do \ @for PROCID in $$(ps -ef | grep "[b]abel-node.*server" | awk '{ print $$2 }'); do \
echo stopping webpack watch $$PROCID; \ echo stopping server $$PROCID; \
kill $$PROCID; \ kill $$PROCID; \
done done
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
const http = require('http'); const http = require('http');
const fs = require('fs'); const fs = require('fs');
const path = require('path');
const mimes = { const mimes = {
js: 'text/javascript', js: 'text/javascript',
...@@ -21,7 +22,8 @@ const server = http.createServer((req, res) => { ...@@ -21,7 +22,8 @@ const server = http.createServer((req, res) => {
const mime = /^\/[a-zA-Z0-9\/]*\.(js|json|css|jpg|png|gif|svg|ttf|eot|woff|woff2)$/.exec(req.url.toString()); const mime = /^\/[a-zA-Z0-9\/]*\.(js|json|css|jpg|png|gif|svg|ttf|eot|woff|woff2)$/.exec(req.url.toString());
if (mime) { if (mime) {
const ext = mime[1]; const ext = mime[1];
return sendFileContent(res, 'dist/' + req.url.toString().substring(1), mimes[ext]); const filename = path.join(__dirname, 'dist', req.url.toString().substring(1));
return sendFileContent(res, filename, mimes[ext]);
} }
return sendFileContent(res, 'dist/index.html', 'text/html'); return sendFileContent(res, 'dist/index.html', 'text/html');
}); });
......
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import Constants from '../utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
export function emitStartLoading() {
AppDispatcher.handleViewAction({
type: ActionTypes.START_LOADING
});
}
export function emitEndLoading() {
AppDispatcher.handleViewAction({
type: ActionTypes.END_LOADING
});
}
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
import $ from 'jquery';
import React from 'react';
import * as GlobalActions from '../action_creators/global_actions.jsx';
export default class Accounts extends React.Component {
componentDidMount() {
$('#sidebar-accounts').addClass('active');
GlobalActions.emitEndLoading();
}
componentWillUnmount() {
$('#sidebar-accounts').removeClass('active');
}
render() {
return <div/>;
}
}
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import * as GlobalActions from '../action_creators/global_actions.jsx';
import {browserHistory, Link} from 'react-router';
import logo from '../images/logo.png';
export default class Header extends React.Component {
constructor(props) {
super(props);
this.handleSearch = this.handleSearch.bind(this);
this.toggleSidebar = this.toggleSidebar.bind(this);
}
handleSearch(e) {
e.preventDefault();
const search = ReactDOM.findDOMNode(this.refs.query);
const term = search.value.trim();
const utf8 = ReactDOM.findDOMNode(this.refs.utf8).value.trim();
search.value = '';
GlobalActions.emitStartLoading();
browserHistory.push(`search/global?utf8=${utf8}&query=${encodeURIComponent(term)}`);
}
toggleSidebar() {
$('body').toggleClass('hide-sidebar');
}
render() {
return (
<div id='header'>
<div className='color-line'></div>
<div
id='logo'
className='light-version'
>
<img
title='ZBox Manager'
className='logo'
src={logo}
alt='ZBox Manager'
/>
</div>
<nav role='navigation'>
<div
className='header-link hide-menu'
onClick={() => this.toggleSidebar()}
>
<i className='fa fa-bars'></i>
</div>
<div className='small-logo'>
<span className='text-primary'>
{'ZBox Manager'}
</span>
</div>
<form
className='navbar-form-custom'
acceptCharset='UTF-8'
onSubmit={(e) => this.handleSearch(e)}
>
<input
ref='utf8'
name='utf8'
type='hidden'
value='✓'
/>
<input
ref='query'
type='text'
name='query'
id='query'
placeholder='Buscar'
autoComplete='off'
className='form-control'
/>
</form>
<div className='navbar-right'>
<ul className='nav navbar-nav no-borders'>
<li className='dropdown'>
<Link
to='/logout'
>
<i className='fa fa-sign-out'></i>
</Link>
</li>
</ul>
</div>
</nav>
</div>
);
}
}
...@@ -2,32 +2,31 @@ ...@@ -2,32 +2,31 @@
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import React from 'react'; import React from 'react';
import NProgress from 'nprogress';
import EventStore from '../stores/event_store.jsx';
export default class LoadingScreen extends React.Component { export default class LoadingScreen extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {};
this.onLoadingStart = this.onLoadingStart.bind(this);
this.onLoadingEnd = this.onLoadingEnd.bind(this);
}
componentDidMount() {
EventStore.addStartLoadingListener(this.onLoadingStart);
EventStore.addEndLoadingListener(this.onLoadingEnd);
}
componentWillUmount() {
EventStore.removeStartLoadingListener(this.onLoadingStart);
EventStore.removeEndLoadingListener(this.onLoadingEnd);
}
onLoadingStart() {
NProgress.start();
}
onLoadingEnd() {
NProgress.done();
} }
render() { render() {
return ( return <div/>;
<div
className='loading-screen'
style={{position: this.props.position}}
>
<div className='loading__content'>
<h3>{'Cargando'}</h3>
<div className='round round-1'></div>
<div className='round round-2'></div>
<div className='round round-3'></div>
</div>
</div>
);
} }
} }
LoadingScreen.defaultProps = {
position: 'relative'
};
LoadingScreen.propTypes = {
position: React.PropTypes.oneOf(['absolute', 'fixed', 'relative', 'static', 'inherit'])
};
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved. // Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information. // See LICENSE.txt for license information.
import $ from 'jquery'; import LoadingScreen from './loading_screen.jsx';
import Header from './header.jsx';
import Sidebar from './sidebar.jsx';
import React from 'react'; import React from 'react';
export default class LoggedIn extends React.Component { export default class LoggedIn extends React.Component {
componentWillMount() {
// Asignar aqui los css que correspondan
$('#root').attr('class', 'manager-view');
// Device tracking setup
var iOS = (/(iPad|iPhone|iPod)/g).test(navigator.userAgent);
if (iOS) {
$('body').addClass('ios');
}
}
componentWillUnmount() {
$('#root').attr('class', '');
}
render() { render() {
let content = [];
if (this.props.children) {
content = this.props.children;
} else {
content.push(
this.props.sidebar
);
}
return ( return (
<div className=''> <div>
<div className='container-fluid'> <LoadingScreen/>
{content} <Header/>
<Sidebar/>
<div className='wrapper'>
{this.props.children}
</div> </div>
</div> </div>
); );
...@@ -46,7 +29,5 @@ LoggedIn.propTypes = { ...@@ -46,7 +29,5 @@ LoggedIn.propTypes = {
children: React.PropTypes.oneOfType([ children: React.PropTypes.oneOfType([
React.PropTypes.arrayOf(React.PropTypes.element), React.PropTypes.arrayOf(React.PropTypes.element),
React.PropTypes.element React.PropTypes.element
]), ])
sidebar: React.PropTypes.element,
center: React.PropTypes.element
}; };
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
import UserStore from '../stores/user_store.jsx';
import SidebarMenu from './sidebar_menu.jsx';
import React from 'react';
import {Link} from 'react-router';
export default class Sidebar extends React.Component {
constructor(props) {
super(props);
this.state = this.getStateFromStores();
}
getStateFromStores() {
const user = UserStore.getCurrentUser();
// if user is null then get the user from Zimbra using the token
return {
user
};
}
render() {
if (this.state.user) {
return (
<aside id='menu'>
<div id='navigation'>
<div className='profile-picture'>
<div className='stats-label text-color'>
<span className='font-extra-bold font-uppercase'>
<Link
to={`/mailboxes/${this.state.user.id}`}
>
{this.state.user.email}
</Link>
<small className='text-muted'></small>
</span>
</div>
</div>
<SidebarMenu/>
</div>
</aside>
);
}
return <div/>;
}
}
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {Link} from 'react-router';
export default class SidebarMenu extends React.Component {
render() {
return (
<ul
className='nav'
id='side-menu'
>
<li id='sidebar-dashboards'>
<Link to='/dashboards'>
<span className='nav-label'>{'dashboards'}</span>
</Link>
</li>
<li id='sidebar-accounts'>
<Link to='/accounts'>
<span className='nav-label'>{'cuentas'}</span>
</Link>
</li>
<li ref='sidebar-domains'>
<Link to='/domains'>
<span className='nav-label'>{'dominios'}</span>
</Link>
</li>
<li ref='sidebar-mailboxes'>
<Link to='/mailboxes'>
<span className='nav-label'>{'casillas'}</span>
</Link>
</li>
<li>
<a
className='nav-label'
target='_blank'
href='http://ayuda.zboxapp.com'
>
{'Documentación'}
</a>
</li>
</ul>
);
}
}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
import * as Flux from 'flux'; import * as Flux from 'flux';
import Constants from 'utils/constants.jsx'; import Constants from '../utils/constants.jsx';
const PayloadSources = Constants.PayloadSources; const PayloadSources = Constants.PayloadSources;
const AppDispatcher = Object.assign(new Flux.Dispatcher(), { const AppDispatcher = Object.assign(new Flux.Dispatcher(), {
......
src/images/logo.png

11.6 KB | W: | H:

src/images/logo.png

32.1 KB | W: | H:

src/images/logo.png
src/images/logo.png
src/images/logo.png
src/images/logo.png
  • 2-up
  • Swipe
  • Onion skin
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<base href="/">
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'> <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>
<meta name='robots' content='noindex, nofollow'> <meta name='robots' content='noindex, nofollow'>
......
...@@ -3,18 +3,21 @@ ...@@ -3,18 +3,21 @@
import './sass/styles.scss'; import './sass/styles.scss';
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import {Router, Route, IndexRedirect, Redirect, browserHistory} from 'react-router';
import Root from './components/root.jsx'; import Root from './components/root.jsx';
import ErrorPage from './components/error_page.jsx'; import ErrorPage from './components/error_page.jsx';
import LoggedIn from './components/logged_in.jsx'; import LoggedIn from './components/logged_in.jsx';
import NotLoggedIn from './components/not_logged_in.jsx'; import NotLoggedIn from './components/not_logged_in.jsx';
import Login from './components/login/login.jsx'; import Login from './components/login/login.jsx';
import Accounts from './components/accounts.jsx';
import * as Client from './utils/client.jsx'; import * as Client from './utils/client.jsx';
import * as Utils from './utils/utils.jsx'; import * as Utils from './utils/utils.jsx';
import $ from 'jquery';
import React from 'react';
import ReactDOM from 'react-dom';
import {Router, Route, IndexRedirect, Redirect, browserHistory} from 'react-router';
const notFoundParams = { const notFoundParams = {
title: 'Página no encontrada', title: 'Página no encontrada',
message: 'La página que estás intentando acceder no existe', message: 'La página que estás intentando acceder no existe',
...@@ -53,11 +56,12 @@ function onPreLoggedIn(nextState, replace, callback) { ...@@ -53,11 +56,12 @@ function onPreLoggedIn(nextState, replace, callback) {
}); });
} }
function onLoggedOut() { function onLoggedOut(nextState, replace) {
Client.logout( Client.logout(
() => { () => {
// window.location.href = '/login' replace({
browserHistory.replace('/login'); pathname: '/login'
});
} }
); );
} }
...@@ -79,6 +83,13 @@ function renderRootComponent() { ...@@ -79,6 +83,13 @@ function renderRootComponent() {
component={LoggedIn} component={LoggedIn}
onEnter={onPreLoggedIn} onEnter={onPreLoggedIn}
> >
<Route
path='accounts'
component={Accounts}
/>
<Route
path='search/global'
/>
<Route <Route
path='logout' path='logout'
onEnter={onLoggedOut} onEnter={onLoggedOut}
......
...@@ -266,10 +266,14 @@ ...@@ -266,10 +266,14 @@
background-color: $color-navy-blue; background-color: $color-navy-blue;
float: left; float: left;
height: 56px; height: 56px;
padding: 18px 10px 18px 18px; padding: 5px 10px 18px 18px;
text-align: center; text-align: center;
width: $menu-width; width: $menu-width;
img {
width: 100px;
}
span { span {
color: $white; color: $white;
font-size: 14px; font-size: 14px;
...@@ -610,10 +614,10 @@ a { ...@@ -610,10 +614,10 @@ a {
float: left; float: left;
height: 52px; height: 52px;
padding: 0; padding: 0;
width: 180px; width: 80%;
.form-control { .form-control {
background: none repeat scroll 0 0 $black; background: none repeat scroll 0 0 $transparent;
border: medium none; border: medium none;
font-size: 13px; font-size: 13px;
height: 52px; height: 52px;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
@import '~jasny-bootstrap/dist/css/jasny-bootstrap.css'; @import '~jasny-bootstrap/dist/css/jasny-bootstrap.css';
@import '~perfect-scrollbar/dist/css/perfect-scrollbar.css'; @import '~perfect-scrollbar/dist/css/perfect-scrollbar.css';
@import '~font-awesome/css/font-awesome.css'; @import '~font-awesome/css/font-awesome.css';
@import '~nprogress/nprogress.css';
// styles.scss // styles.scss
@import 'utils/module'; @import 'utils/module';
@import 'layout/module'; @import 'layout/module';
......
...@@ -6,6 +6,7 @@ $primary-color--hover: darken($primary-color, 10%); ...@@ -6,6 +6,7 @@ $primary-color--hover: darken($primary-color, 10%);
$bg--gray: rgb(245, 245, 245); $bg--gray: rgb(245, 245, 245);
$white: rgb(255, 255, 255); $white: rgb(255, 255, 255);
$black: rgb(0, 0, 0); $black: rgb(0, 0, 0);
$transparent: rgba(0, 0, 0, 0);
$red: rgb(229, 101, 101); $red: rgb(229, 101, 101);
$yellow: rgb(255, 255, 0); $yellow: rgb(255, 255, 0);
$light-gray: rgba(0, 0, 0, .15); $light-gray: rgba(0, 0, 0, .15);
......
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import EventEmitter from 'events';
import Constants from '../utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
const START_LOADING_EVENT = 'start_loading';
const END_LOADING_EVENT = 'end_loading';
class EventStoreClass extends EventEmitter {
emitStartLoading() {
this.emit(START_LOADING_EVENT);
}
addStartLoadingListener(callback) {
this.on(START_LOADING_EVENT, callback);
}
removeStartLoadingListener(callback) {
this.removeListener(START_LOADING_EVENT, callback);
}
emitEndLoading() {
this.emit(END_LOADING_EVENT);
}
addEndLoadingListener(callback) {
this.on(END_LOADING_EVENT, callback);
}
removeEndLoadingListener(callback) {
this.removeListener(END_LOADING_EVENT, callback);
}
}
var EventStore = new EventStoreClass();
EventStore.setMaxListeners(0);
EventStore.dispatchToken = AppDispatcher.register((payload) => {
var action = payload.action;
switch (action.type) {
case ActionTypes.START_LOADING:
EventStore.emitStartLoading();
break;
case ActionTypes.END_LOADING:
EventStore.emitEndLoading();
break;
default:
}
});
export default EventStore;
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
class UserStoreClass {
constructor() {
this.currentUser = {};
}
getCurrentUser() {
return this.currentUser;
}
setCurrentUser(user) {
this.currentUser = user;
}
getCurrentId() {
var user = this.getCurrentUser();
if (user) {
return user.id;
}
return null;
}
}
var UserStore = new UserStoreClass();
export {UserStore as default};
// Copyright (c) 2016 ZBox, Spa. All Rights Reserved.
// See LICENSE.txt for license information.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
import $ from 'jquery'; import $ from 'jquery';
import jszimbra from 'js-zimbra'; import jszimbra from 'js-zimbra';
import UserStore from '../stores/user_store.jsx';
import * as Utils from './utils.jsx'; import * as Utils from './utils.jsx';
// import Domain from '../zimbra/domain.jsx'; // import Domain from '../zimbra/domain.jsx';
...@@ -34,7 +35,7 @@ function handleError(methodName, err) { ...@@ -34,7 +35,7 @@ function handleError(methodName, err) {
export function getClientConfig(success, error) { export function getClientConfig(success, error) {
return $.ajax({ return $.ajax({
url: 'config/config.json', url: '/config/config.json',
dataType: 'json', dataType: 'json',
success, success,
error: function onError(xhr, status, err) { error: function onError(xhr, status, err) {
...@@ -63,6 +64,10 @@ export function login(username, secret, success, error) { ...@@ -63,6 +64,10 @@ export function login(username, secret, success, error) {
} }
Utils.setCookie('token', zimbra.token, 3); Utils.setCookie('token', zimbra.token, 3);
UserStore.setCurrentUser({
token: zimbra.token,
email: username
});
return success(zimbra); return success(zimbra);
}); });
} }
...@@ -74,6 +79,7 @@ export function logout(callback) { ...@@ -74,6 +79,7 @@ export function logout(callback) {
if (cookie) { if (cookie) {
Utils.setCookie('token', '', -1); Utils.setCookie('token', '', -1);
} }
UserStore.setCurrentUser(null);
return callback(); return callback();
} }
......
...@@ -5,6 +5,8 @@ import keyMirror from 'keymirror'; ...@@ -5,6 +5,8 @@ import keyMirror from 'keymirror';
export default { export default {
ActionTypes: keyMirror({ ActionTypes: keyMirror({
START_LOADING: null,
END_LOADING: null,
RECEIVED_ERROR: null RECEIVED_ERROR: null
}), }),
......
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