Add main chat toggle
This commit is contained in:
61
client/sagas/gitter-saga.js
Normal file
61
client/sagas/gitter-saga.js
Normal file
@ -0,0 +1,61 @@
|
||||
import { Observable } from 'rx';
|
||||
import Chat from 'gitter-sidecar';
|
||||
import types from '../../common/app/redux/types';
|
||||
|
||||
function createHeader(document) {
|
||||
const div = document.createElement('div');
|
||||
const span = document.createElement('span');
|
||||
const actionBar = document.querySelector(
|
||||
'#chat-embed-main > .gitter-chat-embed-action-bar'
|
||||
);
|
||||
span.appendChild(document.createTextNode('Free Code Camp\'s Main Chat'));
|
||||
div.className = 'chat-embed-main-title';
|
||||
div.appendChild(span);
|
||||
actionBar.insertBefore(div, actionBar.firstChild);
|
||||
}
|
||||
|
||||
export default function gitterSaga(actions$, getState, { document }) {
|
||||
let mainChatTitleAdded = false;
|
||||
const mainChatContainer = document.createElement('aside');
|
||||
mainChatContainer.id = 'chat-embed-main';
|
||||
mainChatContainer.className = 'gitter-chat-embed is-collapsed';
|
||||
document.body.appendChild(mainChatContainer);
|
||||
const mainChat = new Chat({
|
||||
room: 'freecodecamp/freecodecamp',
|
||||
activationElement: false,
|
||||
targetElement: mainChatContainer
|
||||
});
|
||||
|
||||
const mainChatToggle$ = Observable.fromEventPattern(
|
||||
h => mainChatContainer.addEventListener('gitter-chat-toggle', h),
|
||||
h => mainChatContainer.removeEventListener('gitter-chat-toggle', h)
|
||||
)
|
||||
.map(e => {
|
||||
const { isMainChatOpen } = getState().app;
|
||||
if (!mainChatTitleAdded) {
|
||||
mainChatTitleAdded = true;
|
||||
createHeader(document);
|
||||
}
|
||||
if (isMainChatOpen === e.detail.state) {
|
||||
return null;
|
||||
}
|
||||
return { type: types.toggleMainChat };
|
||||
});
|
||||
return Observable.merge(
|
||||
mainChatToggle$,
|
||||
actions$
|
||||
.filter(({ type }) => (
|
||||
type === types.openMainChat ||
|
||||
type === types.closeMainChat ||
|
||||
type === types.toggleMainChat
|
||||
))
|
||||
.map(() => {
|
||||
const { isMainChatOpen } = getState().app;
|
||||
mainChat.toggleChat(isMainChatOpen);
|
||||
if (!isMainChatOpen) {
|
||||
document.activeElement.blur();
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
}
|
@ -6,6 +6,7 @@ import windowSaga from './window-saga';
|
||||
import executeChallengeSaga from './execute-challenge-saga';
|
||||
import frameSaga from './frame-saga';
|
||||
import codeStorageSaga from './code-storage-saga';
|
||||
import gitterSaga from './gitter-saga';
|
||||
|
||||
export default [
|
||||
errSaga,
|
||||
@ -15,5 +16,6 @@ export default [
|
||||
windowSaga,
|
||||
executeChallengeSaga,
|
||||
frameSaga,
|
||||
codeStorageSaga
|
||||
codeStorageSaga,
|
||||
gitterSaga
|
||||
];
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
fetchUser,
|
||||
initWindowHeight,
|
||||
updateNavHeight,
|
||||
toggleMapDrawer
|
||||
toggleMapDrawer,
|
||||
toggleMainChat
|
||||
} from './redux/actions';
|
||||
|
||||
import { submitChallenge } from './routes/challenges/redux/actions';
|
||||
@ -53,7 +54,8 @@ const bindableActions = {
|
||||
updateNavHeight,
|
||||
fetchUser,
|
||||
submitChallenge,
|
||||
toggleMapDrawer
|
||||
toggleMapDrawer,
|
||||
toggleMainChat
|
||||
};
|
||||
|
||||
const fetchContainerOptions = {
|
||||
@ -79,7 +81,8 @@ export class FreeCodeCamp extends React.Component {
|
||||
submitChallenge: PropTypes.func,
|
||||
isMapDrawerOpen: PropTypes.bool,
|
||||
isMapAlreadyLoaded: PropTypes.bool,
|
||||
toggleMapDrawer: PropTypes.func
|
||||
toggleMapDrawer: PropTypes.func,
|
||||
toggleMainChat: PropTypes.func
|
||||
};
|
||||
|
||||
componentWillReceiveProps({
|
||||
@ -141,14 +144,16 @@ export class FreeCodeCamp extends React.Component {
|
||||
updateNavHeight,
|
||||
isMapDrawerOpen,
|
||||
isMapAlreadyLoaded,
|
||||
toggleMapDrawer
|
||||
toggleMapDrawer,
|
||||
toggleMainChat
|
||||
} = this.props;
|
||||
const navProps = {
|
||||
username,
|
||||
points,
|
||||
picture,
|
||||
updateNavHeight,
|
||||
toggleMapDrawer
|
||||
toggleMapDrawer,
|
||||
toggleMainChat
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -40,7 +40,8 @@ export default class extends React.Component {
|
||||
signedIn: PropTypes.bool,
|
||||
username: PropTypes.string,
|
||||
updateNavHeight: PropTypes.func,
|
||||
toggleMapDrawer: PropTypes.func
|
||||
toggleMapDrawer: PropTypes.func,
|
||||
toggleMainChat: PropTypes.func
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,6 +76,19 @@ export default class extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
renderChat(toggleMainChat) {
|
||||
return (
|
||||
<NavItem
|
||||
eventKey={ 2 }
|
||||
href='//gitter.im/freecodecamp/freecodecamp'
|
||||
onClick={ toggleMainChat }
|
||||
target='_blank'
|
||||
>
|
||||
Chat
|
||||
</NavItem>
|
||||
);
|
||||
}
|
||||
|
||||
renderLinks() {
|
||||
return navLinks.map(({ content, link, react, target }, index) => {
|
||||
if (react) {
|
||||
@ -144,7 +158,8 @@ export default class extends React.Component {
|
||||
username,
|
||||
points,
|
||||
picture,
|
||||
toggleMapDrawer
|
||||
toggleMapDrawer,
|
||||
toggleMainChat
|
||||
} = this.props;
|
||||
const { router } = this.context;
|
||||
const isOnMap = router.isActive('/map');
|
||||
@ -161,6 +176,7 @@ export default class extends React.Component {
|
||||
navbar={ true }
|
||||
pullRight={ true }>
|
||||
{ this.renderMapLink(isOnMap, toggleMapDrawer) }
|
||||
{ this.renderChat(toggleMainChat) }
|
||||
{ this.renderLinks() }
|
||||
{ this.renderPoints(username, points) }
|
||||
{ this.renderSignin(username, picture) }
|
||||
|
@ -1,8 +1,4 @@
|
||||
[{
|
||||
"content": "Chat",
|
||||
"link": "//gitter.im/FreeCodeCamp/FreeCodeCamp",
|
||||
"target": "_blank"
|
||||
},{
|
||||
"content": "Forum",
|
||||
"link": "http://forum.freecodecamp.com/",
|
||||
"target": "_blank"
|
||||
|
@ -53,3 +53,14 @@ export const toggleMapDrawer = createAction(
|
||||
types.toggleMapDrawer,
|
||||
e => e.preventDefault()
|
||||
);
|
||||
export const toggleWikiDrawer = createAction(types.toggleWikiDrawer);
|
||||
|
||||
// chat
|
||||
export const toggleMainChat = createAction(
|
||||
types.toggleMainChat,
|
||||
e => {
|
||||
if (!(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -9,7 +9,8 @@ const initialState = {
|
||||
isSignedIn: false,
|
||||
csrfToken: '',
|
||||
windowHeight: 0,
|
||||
navHeight: 0
|
||||
navHeight: 0,
|
||||
isMainChatOpen: false
|
||||
};
|
||||
|
||||
export default handleActions(
|
||||
@ -46,6 +47,10 @@ export default handleActions(
|
||||
...state,
|
||||
isMapAlreadyLoaded: true,
|
||||
isMapDrawerOpen: !state.isMapDrawerOpen
|
||||
}),
|
||||
[types.toggleMainChat]: state => ({
|
||||
...state,
|
||||
isMainChatOpen: !state.isMainChatOpen
|
||||
})
|
||||
},
|
||||
initialState
|
||||
|
@ -22,5 +22,11 @@ export default createTypes([
|
||||
'updateHikesData',
|
||||
|
||||
// drawers
|
||||
'toggleMapDrawer'
|
||||
'toggleMapDrawer',
|
||||
'toggleWikiDrawer',
|
||||
|
||||
// main chat
|
||||
'openMainChat',
|
||||
'closeMainChat',
|
||||
'toggleMainChat'
|
||||
], 'app');
|
||||
|
@ -50,6 +50,7 @@
|
||||
"express-validator": "^2.18.0",
|
||||
"fetchr": "~0.5.12",
|
||||
"frameguard": "^2.0.0",
|
||||
"gitter-sidecar": "^1.2.3",
|
||||
"helmet": "^2.0.0",
|
||||
"helmet-csp": "^1.0.3",
|
||||
"history": "^2.0.0",
|
||||
|
Reference in New Issue
Block a user