Skip to content
This repository has been archived by the owner on Dec 28, 2022. It is now read-only.

Commit

Permalink
Merge 1d37325 into 4f17213
Browse files Browse the repository at this point in the history
  • Loading branch information
Gum-Joe committed Jul 23, 2016
2 parents 4f17213 + 1d37325 commit d42f2fc
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 16 deletions.
119 changes: 116 additions & 3 deletions app/helpers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@
*/
const schema = require('../util/schema');

// ID for next task
let nextTaskId = 0;

/**
* Add api stuff
* @param api {Api} Api class
*/
module.exports = (api) => {
api.addPlugin({

/**
* Sends a notification to the client
* @param notification {Object} notification to send
*/
fireNotification: function (notification) {
// Validate
schema({
Expand All @@ -22,24 +30,129 @@ module.exports = (api) => {
}
// Fire along
api.sockets.use((socket) => {
socket.emit('notification', notification);
socket.emit(
'notification',
notification
);
});
});
},

/**
* Creates a tasks and sends it to the client
* @param task {Object} inital task state
* @return Object
*/
createTask: function (task) {
const taskToSend = Object.assign({
id: nextTaskId,
status: "0%",
percentage: 0
}, task);

schema({
app: { required: true, type: 'string' },
status: 'string',
percentage: 'number'
}, task, (err) => {
if (err) {
this.logger.throw_noexit(err);
}
// Emit
api.sockets.use((socket) => {
socket.emit(
'task:new',
taskToSend
);
});
});
// Increase next task id
nextTaskId++;

// Task actions
return {
task: taskToSend,

/**
* Updates the status of a task
* @param newStatus {Object} new status of the task
*/
update(newStatus = {}) {
this.task = Object.assign(this.task, newStatus);
api.sockets.use((socket) => {
socket.emit(
'task:update',
this.task
);
});
},

/**
* Ends a task
* @param newStatus {Object} new status of the task
*/
end(newStatus = {}) {
this.task = Object.assign(
this.task,
{ status: 'Done!' },
newStatus,
{ percentage: '1' }
);
// Send
api.sockets.use((socket) => {
socket.emit(
'task:end',
this.task
);
});
},

/**
* Sets what to do in the case of the user cancelling the task
* @param cb {Function} what to do on canel
*/
onCancel(cb) {
const taskTmp = this.task;
api.sockets.use((socket) => {
socket.on(
'task:cancel',
(task) => {
if (task === taskTmp) {
return cb(() => {
// Tell it to end
socket.emit('task:end', taskTmp);
});
}
}
);
});

}
};
}
});

// For testing
api.fireNotification({
app: 'Test',
body: 'test',
body: Math.round(Math.random() * 100).toString(),
icon: '/img/home-icon.png'
});

const task = api.createTask({
app: 'Task',
status: 'Doing some stuff...',
percentage: '0'
});
task.update({
percentage: '0.6'
});

// For testing. Remove for final copy
api.app.get('/api/dev/fire/notification', (req, res) => {
api.io.emit('notification', {
app: 'Test',
body: 'test',
body: Math.round(Math.random() * 100).toString(),
icon: '/img/home-icon.png'
});
res.status(200);
Expand Down
14 changes: 10 additions & 4 deletions client/base/components/notifications.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { SidebarItem } from './navbar/sidebar';
import io from 'socket.io-client';
import '../../sass/notifications.scss';

// Socket
const socket = io.connect('/');

// Component
export const Notifications = React.createClass({
propTypes: {
Expand All @@ -17,9 +20,8 @@ export const Notifications = React.createClass({
updateStatus: PropTypes.func.isRequired
},
componentDidMount() {
this.socket = io.connect('/');
// Wacth for notification event
this.socket.on('notification', (notification) => {
socket.on('notification', (notification) => {
const date = new Date();
// From http://stackoverflow.com/questions/1760250/how-to-tell-if-browser-tab-is-active (document.hidden)
if (document.hidden) {
Expand All @@ -41,12 +43,16 @@ export const Notifications = React.createClass({
const notificationShown = Object.assign({
date: dateString
}, notification);
this.props.add(notificationShown);
// Check if not in already
console.log(notification);
if (!this.props.notifications.includes(notificationShown)) {
this.props.add(notificationShown);
}
});
},
render() {
return (
<div>
<div className="notifications-bar-body">
<div className="notify-header">
<h3>
<button onClick={() => this.props.updateStatus({ sidebar: { open: false, alreadyOpened: true } })} className="not-a-button close-notify-bar">
Expand Down
16 changes: 15 additions & 1 deletion client/base/components/sidebar.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Sidebar Component for notifications
import React, { Component, PropTypes } from 'react';
import FontAwesome from 'react-fontawesome';
import classnames from 'classnames';
import { Sidebar as SidebarBase } from './navbar/sidebar';
import { Notifications } from '../containers/Notifications';
import { Tabs, Tab, TabsHeader as Header, TabsBody as Body } from './tabs';
// Export
export class Sidebar extends Component {
constructor() {
Expand Down Expand Up @@ -38,7 +40,19 @@ export class Sidebar extends Component {
)
}
>
<Notifications updateStatus={this.props.updateStatus} />
<Tabs defaultTab={0}>
<Header count={2}>
<Tab id={0}>
<FontAwesome name="bell" />
</Tab>
<Tab id={1}>
<FontAwesome name="tasks" />
</Tab>
</Header>
<Body id={0}>
<Notifications updateStatus={this.props.updateStatus} />
</Body>
</Tabs>
</SidebarBase>
);
}
Expand Down
96 changes: 96 additions & 0 deletions client/base/components/tabs.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// JSX for tabs
import React, { Component, PropTypes } from 'react';
// Sass
import '../../sass/tabs.scss';

// Current tab
// Should be in component's state
let current; // eslint-disable-line

// Export
export class Tabs extends Component {
componentDidMount() {
if (!isNaN(this.props.defaultTab)) {
current = this.props.defaultTab;
}
}
render() {
return (
<div className="tab-wrap">{this.props.children}</div>
);
}
}

export class Tab extends Component {
render() {
return (
<li>
<button onClick={() => { current = this.props.id; }}>{this.props.children}</button>
</li>
);
}
}

export class TabsHeader extends Component {
render() {
return (
<div className="tabs-header">
<ul style={{ li: { width: `${100 / this.props.count}%` } }}>
{this.props.children}
</ul>
</div>
);
}
}

export class TabsBody extends Component {
constructor() {
super();
this.state = {
current
};
setInterval(this.updateState.bind(this), 100);
}
updateState() {
// Update the state
if (current !== this.state.current) {
this.setState({
current
});
}
}
render() {
if (this.state.current === this.props.id) {
return (
<div className="tab-wrap">
{this.props.children}
</div>
);
} else {
return (
<div></div>
);
}

}
}

Tabs.propTypes = {
children: PropTypes.object,
defaultTab: PropTypes.number
};

Tab.propTypes = {
children: PropTypes.object,
id: PropTypes.number.isRequired
};

TabsHeader.propTypes = {
children: PropTypes.object,
count: PropTypes.number.isRequired
};

TabsBody.propTypes = {
children: PropTypes.object,
id: PropTypes.number.isRequired
};
5 changes: 3 additions & 2 deletions client/base/reducers/Notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ADD_NOTIFY, REMOVE_NOTIFY, REMOVE_ALL_NOTIFY } from '../util/constants';

// ID for next notification
let nextNotificationId = 1;
let nextNotificationId = 0;

// Reducer
export const notifications = (state = [], action) => {
Expand All @@ -17,7 +17,8 @@ export const notifications = (state = [], action) => {
return n.id !== action.notification.id;
});
case REMOVE_ALL_NOTIFY:
return [];
nextNotificationId = 0;
return [];
default:
return state;

Expand Down
7 changes: 6 additions & 1 deletion client/sass/notifications.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

// Sidebar
.notifications-bar {
overflow-y: scroll;
@media screen and (min-width: 845px) {
width: 300px;
}
Expand Down Expand Up @@ -91,3 +90,9 @@ $dismiss-notify-pad-top: 6px;
padding-top: $dismiss-notify-pad-top + 2px !important;
opacity: 0.5;
}

// Notifications
.notifications-bar-body {
overflow-y: scroll;
height: 100%;
}
39 changes: 39 additions & 0 deletions client/sass/tabs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Styles for tabs
@import 'dashboard';

.tabs-header {
height: 35px;
width: 100%;
border-bottom-color: $navbar-text;
border-bottom-style: solid;
border-bottom-width: 1px;
text-align: center;
ul {
height: 100%;
width: 100%;
padding: 0;
list-style-type: none;
li {
float: left;
border-right-color: $navbar-text;
border-right-style: solid;
border-right-width: 1px;
height: 100% !important;
width: 50%;
button {
height: 100%;
width: 100%;
border: 0;
background: transparent;
}
}
li:hover {
background-color: $navbar-background-hover;
}
}
}

// Wrapper around tabs body
.tab-wrap {
height: 100%;
}
Loading

0 comments on commit d42f2fc

Please sign in to comment.