feat(tool-panel): Make buttons look and act like current productiion (#16580)
This commit is contained in:
committed by
Quincy Larson
parent
4ce84166ed
commit
e3a522aa5e
@@ -1,95 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { Button, Modal } from 'react-bootstrap';
|
|
||||||
|
|
||||||
import ns from './ns.json';
|
|
||||||
import {
|
|
||||||
createIssue,
|
|
||||||
openIssueSearch,
|
|
||||||
closeBugModal,
|
|
||||||
|
|
||||||
bugModalSelector
|
|
||||||
} from './redux';
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({ isOpen: bugModalSelector(state) });
|
|
||||||
const mapDispatchToProps = { createIssue, openIssueSearch, closeBugModal };
|
|
||||||
const bugLink = 'http://forum.freecodecamp.org/t/how-to-report-a-bug/19543';
|
|
||||||
|
|
||||||
const propTypes = {
|
|
||||||
closeBugModal: PropTypes.func,
|
|
||||||
createIssue: PropTypes.func,
|
|
||||||
isOpen: PropTypes.bool,
|
|
||||||
openIssueSearch: PropTypes.func
|
|
||||||
};
|
|
||||||
|
|
||||||
export class BugModal extends PureComponent {
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
isOpen,
|
|
||||||
closeBugModal,
|
|
||||||
openIssueSearch,
|
|
||||||
createIssue
|
|
||||||
} = this.props;
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
show={ isOpen }
|
|
||||||
>
|
|
||||||
<Modal.Header className={ `${ns}-list-header` }>
|
|
||||||
Did you find a bug?
|
|
||||||
<span
|
|
||||||
className='close closing-x'
|
|
||||||
onClick={ closeBugModal }
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</span>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body className='text-center'>
|
|
||||||
<h3>
|
|
||||||
Before you submit a new issue,
|
|
||||||
read "How to Report a Bug" and
|
|
||||||
browse other issues with this challenge.
|
|
||||||
</h3>
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
href={ bugLink }
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
Read "How to Report a Bug"
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
onClick={ openIssueSearch }
|
|
||||||
>
|
|
||||||
Browse other issues with this challenge
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
onClick={ createIssue }
|
|
||||||
>
|
|
||||||
Create topic for issue in community forum
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
onClick={ closeBugModal }
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Modal.Body>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BugModal.displayName = 'BugModal';
|
|
||||||
BugModal.propTypes = propTypes;
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(BugModal);
|
|
@@ -6,20 +6,18 @@ import { Button, Modal } from 'react-bootstrap';
|
|||||||
import ns from './ns.json';
|
import ns from './ns.json';
|
||||||
import {
|
import {
|
||||||
createQuestion,
|
createQuestion,
|
||||||
openHelpChatRoom,
|
|
||||||
closeHelpModal,
|
closeHelpModal,
|
||||||
helpModalSelector
|
helpModalSelector
|
||||||
} from './redux';
|
} from './redux';
|
||||||
import { RSA } from '../../../utils/constantStrings.json';
|
import { RSA } from '../../../utils/constantStrings.json';
|
||||||
|
|
||||||
const mapStateToProps = state => ({ isOpen: helpModalSelector(state) });
|
const mapStateToProps = state => ({ isOpen: helpModalSelector(state) });
|
||||||
const mapDispatchToProps = { createQuestion, openHelpChatRoom, closeHelpModal };
|
const mapDispatchToProps = { createQuestion, closeHelpModal };
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
closeHelpModal: PropTypes.func,
|
closeHelpModal: PropTypes.func.isRequired,
|
||||||
createQuestion: PropTypes.func,
|
createQuestion: PropTypes.func.isRequired,
|
||||||
isOpen: PropTypes.bool,
|
isOpen: PropTypes.bool
|
||||||
openHelpChatRoom: PropTypes.func
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class HelpModal extends PureComponent {
|
export class HelpModal extends PureComponent {
|
||||||
@@ -27,7 +25,6 @@ export class HelpModal extends PureComponent {
|
|||||||
const {
|
const {
|
||||||
isOpen,
|
isOpen,
|
||||||
closeHelpModal,
|
closeHelpModal,
|
||||||
openHelpChatRoom,
|
|
||||||
createQuestion
|
createQuestion
|
||||||
} = this.props;
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
@@ -44,20 +41,11 @@ export class HelpModal extends PureComponent {
|
|||||||
</span>
|
</span>
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body className='text-center'>
|
<Modal.Body className='text-center'>
|
||||||
<h3>
|
<h3 className={`${ns}-help-modal-heading`}>
|
||||||
If you've already tried the Read-Search-Ask method,
|
If you've already tried the
|
||||||
then you can ask for help on the freeCodeCamp forum.
|
<a href={ RSA } title='Read, search, ask'>Read-Search-Ask</a>
|
||||||
|
method, then you can ask for help on the freeCodeCamp forum.
|
||||||
</h3>
|
</h3>
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
href={ RSA }
|
|
||||||
onClick={ closeHelpModal }
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
Learn about the Read-Search-Ask Methodology
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
block={ true }
|
block={ true }
|
||||||
bsSize='lg'
|
bsSize='lg'
|
||||||
@@ -66,14 +54,6 @@ export class HelpModal extends PureComponent {
|
|||||||
>
|
>
|
||||||
Create a help post on the forum
|
Create a help post on the forum
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsSize='lg'
|
|
||||||
bsStyle='primary'
|
|
||||||
onClick={ openHelpChatRoom }
|
|
||||||
>
|
|
||||||
Ask for help in the Gitter Chatroom
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
block={ true }
|
block={ true }
|
||||||
bsSize='lg'
|
bsSize='lg'
|
||||||
|
@@ -6,7 +6,6 @@ import { connect } from 'react-redux';
|
|||||||
|
|
||||||
import ns from './ns.json';
|
import ns from './ns.json';
|
||||||
|
|
||||||
import BugModal from './Bug-Modal.jsx';
|
|
||||||
import HelpModal from './Help-Modal.jsx';
|
import HelpModal from './Help-Modal.jsx';
|
||||||
import ToolPanel from './Tool-Panel.jsx';
|
import ToolPanel from './Tool-Panel.jsx';
|
||||||
import ChallengeTitle from './Challenge-Title.jsx';
|
import ChallengeTitle from './Challenge-Title.jsx';
|
||||||
@@ -14,7 +13,6 @@ import ChallengeDescription from './Challenge-Description.jsx';
|
|||||||
import TestSuite from './Test-Suite.jsx';
|
import TestSuite from './Test-Suite.jsx';
|
||||||
import Output from './Output.jsx';
|
import Output from './Output.jsx';
|
||||||
import {
|
import {
|
||||||
openBugModal,
|
|
||||||
openHelpModal,
|
openHelpModal,
|
||||||
updateHint,
|
updateHint,
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
@@ -24,7 +22,8 @@ import {
|
|||||||
testsSelector,
|
testsSelector,
|
||||||
outputSelector,
|
outputSelector,
|
||||||
hintIndexSelector,
|
hintIndexSelector,
|
||||||
codeLockedSelector
|
codeLockedSelector,
|
||||||
|
guideURLSelector
|
||||||
} from './redux';
|
} from './redux';
|
||||||
|
|
||||||
import { descriptionRegex } from './utils';
|
import { descriptionRegex } from './utils';
|
||||||
@@ -35,7 +34,6 @@ const mapDispatchToProps = {
|
|||||||
makeToast,
|
makeToast,
|
||||||
executeChallenge,
|
executeChallenge,
|
||||||
updateHint,
|
updateHint,
|
||||||
openBugModal,
|
|
||||||
openHelpModal,
|
openHelpModal,
|
||||||
unlockUntrustedCode
|
unlockUntrustedCode
|
||||||
};
|
};
|
||||||
@@ -46,13 +44,15 @@ const mapStateToProps = createSelector(
|
|||||||
outputSelector,
|
outputSelector,
|
||||||
hintIndexSelector,
|
hintIndexSelector,
|
||||||
codeLockedSelector,
|
codeLockedSelector,
|
||||||
|
guideURLSelector,
|
||||||
(
|
(
|
||||||
{ description, guideUrl },
|
{ description },
|
||||||
{ title },
|
{ title },
|
||||||
tests,
|
tests,
|
||||||
output,
|
output,
|
||||||
hintIndex,
|
hintIndex,
|
||||||
isCodeLocked,
|
isCodeLocked,
|
||||||
|
guideUrl
|
||||||
) => ({
|
) => ({
|
||||||
title,
|
title,
|
||||||
guideUrl,
|
guideUrl,
|
||||||
@@ -69,7 +69,6 @@ const propTypes = {
|
|||||||
hint: PropTypes.string,
|
hint: PropTypes.string,
|
||||||
isCodeLocked: PropTypes.bool,
|
isCodeLocked: PropTypes.bool,
|
||||||
makeToast: PropTypes.func,
|
makeToast: PropTypes.func,
|
||||||
openBugModal: PropTypes.func,
|
|
||||||
openHelpModal: PropTypes.func,
|
openHelpModal: PropTypes.func,
|
||||||
output: PropTypes.string,
|
output: PropTypes.string,
|
||||||
tests: PropTypes.arrayOf(PropTypes.object),
|
tests: PropTypes.arrayOf(PropTypes.object),
|
||||||
@@ -126,7 +125,6 @@ export class SidePanel extends PureComponent {
|
|||||||
executeChallenge,
|
executeChallenge,
|
||||||
updateHint,
|
updateHint,
|
||||||
makeToast,
|
makeToast,
|
||||||
openBugModal,
|
|
||||||
openHelpModal,
|
openHelpModal,
|
||||||
isCodeLocked,
|
isCodeLocked,
|
||||||
unlockUntrustedCode,
|
unlockUntrustedCode,
|
||||||
@@ -153,12 +151,10 @@ export class SidePanel extends PureComponent {
|
|||||||
hint={ hint }
|
hint={ hint }
|
||||||
isCodeLocked={ isCodeLocked }
|
isCodeLocked={ isCodeLocked }
|
||||||
makeToast={ makeToast }
|
makeToast={ makeToast }
|
||||||
openBugModal={ openBugModal }
|
|
||||||
openHelpModal={ openHelpModal }
|
openHelpModal={ openHelpModal }
|
||||||
unlockUntrustedCode={ unlockUntrustedCode }
|
unlockUntrustedCode={ unlockUntrustedCode }
|
||||||
updateHint={ updateHint }
|
updateHint={ updateHint }
|
||||||
/>
|
/>
|
||||||
<BugModal />
|
|
||||||
<HelpModal />
|
<HelpModal />
|
||||||
<Output
|
<Output
|
||||||
defaultOutput={
|
defaultOutput={
|
||||||
|
@@ -16,7 +16,6 @@ const propTypes = {
|
|||||||
hint: PropTypes.string,
|
hint: PropTypes.string,
|
||||||
isCodeLocked: PropTypes.bool,
|
isCodeLocked: PropTypes.bool,
|
||||||
makeToast: PropTypes.func.isRequired,
|
makeToast: PropTypes.func.isRequired,
|
||||||
openBugModal: PropTypes.func.isRequired,
|
|
||||||
openHelpModal: PropTypes.func.isRequired,
|
openHelpModal: PropTypes.func.isRequired,
|
||||||
unlockUntrustedCode: PropTypes.func.isRequired,
|
unlockUntrustedCode: PropTypes.func.isRequired,
|
||||||
updateHint: PropTypes.func.isRequired
|
updateHint: PropTypes.func.isRequired
|
||||||
@@ -97,7 +96,6 @@ export default class ToolPanel extends PureComponent {
|
|||||||
guideUrl,
|
guideUrl,
|
||||||
hint,
|
hint,
|
||||||
isCodeLocked,
|
isCodeLocked,
|
||||||
openBugModal,
|
|
||||||
openHelpModal,
|
openHelpModal,
|
||||||
unlockUntrustedCode
|
unlockUntrustedCode
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@@ -122,36 +120,28 @@ export default class ToolPanel extends PureComponent {
|
|||||||
Reset your code
|
Reset your code
|
||||||
</Button>
|
</Button>
|
||||||
<div className='button-spacer' />
|
<div className='button-spacer' />
|
||||||
|
{
|
||||||
|
guideUrl &&
|
||||||
|
<div>
|
||||||
|
<Button
|
||||||
|
block={ true }
|
||||||
|
bsStyle='primary'
|
||||||
|
className='btn-big'
|
||||||
|
href={ guideUrl }
|
||||||
|
target='_blank'
|
||||||
|
>
|
||||||
|
Get a hint
|
||||||
|
</Button>
|
||||||
|
<div className='button-spacer' />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<Button
|
<Button
|
||||||
block={ true }
|
block={ true }
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className='btn-big'
|
className='btn-big'
|
||||||
onClick={ openHelpModal }
|
onClick={ openHelpModal }
|
||||||
>
|
>
|
||||||
Get Help
|
Ask for help on the forum
|
||||||
</Button>
|
|
||||||
<div className='button-spacer' />
|
|
||||||
{guideUrl &&
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsStyle='primary'
|
|
||||||
className='btn-big'
|
|
||||||
href={ guideUrl }
|
|
||||||
target='_blank'
|
|
||||||
>
|
|
||||||
See Guide
|
|
||||||
</Button>
|
|
||||||
<div className='button-spacer' />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<Button
|
|
||||||
block={ true }
|
|
||||||
bsStyle='primary'
|
|
||||||
className='btn-big'
|
|
||||||
onClick={ openBugModal }
|
|
||||||
>
|
|
||||||
Report a Bug
|
|
||||||
</Button>
|
</Button>
|
||||||
<div className='button-spacer' />
|
<div className='button-spacer' />
|
||||||
</div>
|
</div>
|
||||||
|
@@ -234,4 +234,8 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.@{ns}-help-modal-heading > a {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
&{ @import "./views/index.less"; }
|
&{ @import "./views/index.less"; }
|
||||||
|
@@ -77,17 +77,10 @@ export const types = createTypes([
|
|||||||
createAsyncTypes('submitChallenge'),
|
createAsyncTypes('submitChallenge'),
|
||||||
'moveToNextChallenge',
|
'moveToNextChallenge',
|
||||||
|
|
||||||
// bug
|
|
||||||
'openBugModal',
|
|
||||||
'closeBugModal',
|
|
||||||
'openIssueSearch',
|
|
||||||
'createIssue',
|
|
||||||
|
|
||||||
// help
|
// help
|
||||||
'openHelpModal',
|
'openHelpModal',
|
||||||
'closeHelpModal',
|
'closeHelpModal',
|
||||||
'createQuestion',
|
'createQuestion',
|
||||||
'openHelpChatRoom',
|
|
||||||
|
|
||||||
// panes
|
// panes
|
||||||
'toggleClassicEditor',
|
'toggleClassicEditor',
|
||||||
@@ -157,17 +150,10 @@ export const submitChallengeComplete = createAction(
|
|||||||
|
|
||||||
export const moveToNextChallenge = createAction(types.moveToNextChallenge);
|
export const moveToNextChallenge = createAction(types.moveToNextChallenge);
|
||||||
|
|
||||||
// bug
|
|
||||||
export const openBugModal = createAction(types.openBugModal);
|
|
||||||
export const closeBugModal = createAction(types.closeBugModal);
|
|
||||||
export const openIssueSearch = createAction(types.openIssueSearch);
|
|
||||||
export const createIssue = createAction(types.createIssue);
|
|
||||||
|
|
||||||
// help
|
// help
|
||||||
export const openHelpModal = createAction(types.openHelpModal);
|
export const openHelpModal = createAction(types.openHelpModal);
|
||||||
export const closeHelpModal = createAction(types.closeHelpModal);
|
export const closeHelpModal = createAction(types.closeHelpModal);
|
||||||
export const createQuestion = createAction(types.createQuestion);
|
export const createQuestion = createAction(types.createQuestion);
|
||||||
export const openHelpChatRoom = createAction(types.openHelpChatRoom);
|
|
||||||
|
|
||||||
// code storage
|
// code storage
|
||||||
export const storedCodeFound = createAction(
|
export const storedCodeFound = createAction(
|
||||||
@@ -221,8 +207,9 @@ export const challengeModalSelector =
|
|||||||
challengeSelector(state).type !== 'backend'
|
challengeSelector(state).type !== 'backend'
|
||||||
);
|
);
|
||||||
|
|
||||||
export const bugModalSelector = state => getNS(state).isBugOpen;
|
|
||||||
export const helpModalSelector = state => getNS(state).isHelpOpen;
|
export const helpModalSelector = state => getNS(state).isHelpOpen;
|
||||||
|
export const guideURLSelector = state =>
|
||||||
|
`https://guide.freecodecamp.org/certificates/${getNS(state).challenge}`;
|
||||||
|
|
||||||
export const challengeRequiredSelector = state =>
|
export const challengeRequiredSelector = state =>
|
||||||
challengeSelector(state).required || [];
|
challengeSelector(state).required || [];
|
||||||
@@ -334,8 +321,6 @@ export default combineReducers(
|
|||||||
...state,
|
...state,
|
||||||
output: (state.output || '') + output
|
output: (state.output || '') + output
|
||||||
}),
|
}),
|
||||||
[types.openBugModal]: state => ({ ...state, isBugOpen: true }),
|
|
||||||
[types.closeBugModal]: state => ({ ...state, isBugOpen: false }),
|
|
||||||
[types.openHelpModal]: state => ({ ...state, isHelpOpen: true }),
|
[types.openHelpModal]: state => ({ ...state, isHelpOpen: true }),
|
||||||
[types.closeHelpModal]: state => ({ ...state, isHelpOpen: false })
|
[types.closeHelpModal]: state => ({ ...state, isHelpOpen: false })
|
||||||
}),
|
}),
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
import { combineEpics, ofType } from 'redux-epic';
|
import { ofType } from 'redux-epic';
|
||||||
import {
|
import {
|
||||||
types,
|
types,
|
||||||
chatRoomSelector,
|
|
||||||
closeBugModal,
|
|
||||||
closeHelpModal
|
closeHelpModal
|
||||||
} from '../redux';
|
} from '../redux';
|
||||||
|
|
||||||
@@ -30,81 +28,6 @@ function filesToMarkdown(files = {}) {
|
|||||||
}, '\n');
|
}, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openIssueSearchEpic(actions, { getState }, { window }) {
|
|
||||||
return actions::ofType(types.openIssueSearch).map(() => {
|
|
||||||
const state = getState();
|
|
||||||
const challengeName = currentChallengeSelector(state);
|
|
||||||
|
|
||||||
window.open(
|
|
||||||
'https://forum.freecodecamp.org/search?q=' +
|
|
||||||
window.encodeURIComponent(challengeName)
|
|
||||||
);
|
|
||||||
|
|
||||||
return closeBugModal();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createIssueEpic(actions, { getState }, { window }) {
|
|
||||||
return actions::ofType(types.createIssue).map(() => {
|
|
||||||
const state = getState();
|
|
||||||
const files = filesSelector(state);
|
|
||||||
const challengeName = currentChallengeSelector(state);
|
|
||||||
const {
|
|
||||||
navigator: { userAgent },
|
|
||||||
location: { href }
|
|
||||||
} = window;
|
|
||||||
const titleText = 'Need assistance in ' + challengeName;
|
|
||||||
let textMessage = [
|
|
||||||
'#### Challenge Name\n',
|
|
||||||
'[',
|
|
||||||
challengeName,
|
|
||||||
'](',
|
|
||||||
href,
|
|
||||||
') has an issue.\n',
|
|
||||||
'#### Issue Description\n',
|
|
||||||
'<!-- Describe below when the issue happens and how to ',
|
|
||||||
'reproduce it -->\n\n\n',
|
|
||||||
'#### Browser Information\n',
|
|
||||||
'<!-- Describe your workspace in which you are having issues-->\n',
|
|
||||||
'User Agent is: <code>',
|
|
||||||
userAgent,
|
|
||||||
'</code>.\n\n',
|
|
||||||
'#### Screenshot\n',
|
|
||||||
'<!-- Add a screenshot of your issue -->\n\n\n',
|
|
||||||
'#### Your Code'
|
|
||||||
].join('');
|
|
||||||
|
|
||||||
const body = filesToMarkdown(files);
|
|
||||||
if (body.length > 10) {
|
|
||||||
textMessage += body;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.open(
|
|
||||||
'https://forum.freecodecamp.org/new-topic'
|
|
||||||
+ '?category=General'
|
|
||||||
+ '&title=' + window.encodeURIComponent(titleText)
|
|
||||||
+ '&body=' + window.encodeURIComponent(textMessage),
|
|
||||||
'_blank'
|
|
||||||
);
|
|
||||||
|
|
||||||
return closeBugModal();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function openHelpChatRoomEpic(actions, { getState }, { window }) {
|
|
||||||
return actions::ofType(types.openHelpChatRoom).map(() => {
|
|
||||||
const state = getState();
|
|
||||||
const helpChatRoom = chatRoomSelector(state);
|
|
||||||
|
|
||||||
window.open(
|
|
||||||
'https://gitter.im/freecodecamp/' +
|
|
||||||
window.encodeURIComponent(helpChatRoom)
|
|
||||||
);
|
|
||||||
|
|
||||||
return closeHelpModal();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createQuestionEpic(actions, { getState }, { window }) {
|
export function createQuestionEpic(actions, { getState }, { window }) {
|
||||||
return actions::ofType(types.createQuestion).map(() => {
|
return actions::ofType(types.createQuestion).map(() => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
@@ -138,9 +61,4 @@ export function createQuestionEpic(actions, { getState }, { window }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default combineEpics(
|
export default createQuestionEpic;
|
||||||
openIssueSearchEpic,
|
|
||||||
createIssueEpic,
|
|
||||||
openHelpChatRoomEpic,
|
|
||||||
createQuestionEpic
|
|
||||||
);
|
|
||||||
|
@@ -6,7 +6,7 @@ import { Col, Image } from 'react-bootstrap';
|
|||||||
|
|
||||||
import SidePanel from './Side-Panel.jsx';
|
import SidePanel from './Side-Panel.jsx';
|
||||||
import ToolPanel from './Tool-Panel.jsx';
|
import ToolPanel from './Tool-Panel.jsx';
|
||||||
import BugModal from '../../Bug-Modal.jsx';
|
import HelpModal from '../../Help-Modal.jsx';
|
||||||
|
|
||||||
import { challengeMetaSelector } from '../../redux';
|
import { challengeMetaSelector } from '../../redux';
|
||||||
import { challengeSelector } from '../../../../redux';
|
import { challengeSelector } from '../../../../redux';
|
||||||
@@ -45,7 +45,7 @@ export class Project extends PureComponent {
|
|||||||
isCompleted,
|
isCompleted,
|
||||||
description
|
description
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const imageURL = '//i.imgur.com/' + image + '.png';
|
const imageURL = 'https://i.imgur.com/' + image + '.png';
|
||||||
return (
|
return (
|
||||||
<Col
|
<Col
|
||||||
md={ 8 }
|
md={ 8 }
|
||||||
@@ -63,8 +63,7 @@ export class Project extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<ToolPanel />
|
<ToolPanel />
|
||||||
<br />
|
<HelpModal />
|
||||||
<BugModal />
|
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -13,9 +13,10 @@ import { submittingSelector } from './redux';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
submitChallenge,
|
submitChallenge,
|
||||||
openBugModal,
|
|
||||||
|
|
||||||
chatRoomSelector
|
openHelpModal,
|
||||||
|
chatRoomSelector,
|
||||||
|
guideURLSelector
|
||||||
} from '../../redux';
|
} from '../../redux';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -28,32 +29,36 @@ import {
|
|||||||
} from '../../../../utils/challengeTypes';
|
} from '../../../../utils/challengeTypes';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
|
guideUrl: PropTypes.string,
|
||||||
helpChatRoom: PropTypes.string.isRequired,
|
helpChatRoom: PropTypes.string.isRequired,
|
||||||
isFrontEnd: PropTypes.bool,
|
isFrontEnd: PropTypes.bool,
|
||||||
isSignedIn: PropTypes.bool,
|
isSignedIn: PropTypes.bool,
|
||||||
isSimple: PropTypes.bool,
|
isSimple: PropTypes.bool,
|
||||||
isSubmitting: PropTypes.bool,
|
isSubmitting: PropTypes.bool,
|
||||||
openBugModal: PropTypes.func.isRequired,
|
openHelpModal: PropTypes.func.isRequired,
|
||||||
submitChallenge: PropTypes.func.isRequired
|
submitChallenge: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
submitChallenge,
|
openHelpModal,
|
||||||
openBugModal
|
submitChallenge
|
||||||
};
|
};
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
challengeSelector,
|
challengeSelector,
|
||||||
signInLoadingSelector,
|
signInLoadingSelector,
|
||||||
submittingSelector,
|
submittingSelector,
|
||||||
chatRoomSelector,
|
chatRoomSelector,
|
||||||
|
guideURLSelector,
|
||||||
(
|
(
|
||||||
{ challengeType = simpleProject },
|
{ challengeType = simpleProject },
|
||||||
showLoading,
|
showLoading,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
helpChatRoom,
|
helpChatRoom,
|
||||||
|
guideUrl
|
||||||
) => ({
|
) => ({
|
||||||
|
guideUrl,
|
||||||
|
helpChatRoom,
|
||||||
isSignedIn: !showLoading,
|
isSignedIn: !showLoading,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
helpChatRoom,
|
|
||||||
isSimple: challengeType === simpleProject,
|
isSimple: challengeType === simpleProject,
|
||||||
isFrontEnd: challengeType === frontEndProject
|
isFrontEnd: challengeType === frontEndProject
|
||||||
})
|
})
|
||||||
@@ -78,13 +83,14 @@ export class ToolPanel extends PureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
|
guideUrl,
|
||||||
|
helpChatRoom,
|
||||||
isFrontEnd,
|
isFrontEnd,
|
||||||
isSimple,
|
isSimple,
|
||||||
isSignedIn,
|
isSignedIn,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
helpChatRoom,
|
openHelpModal,
|
||||||
submitChallenge,
|
submitChallenge
|
||||||
openBugModal
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const FormElement = isFrontEnd ? FrontEndForm : BackEndForm;
|
const FormElement = isFrontEnd ? FrontEndForm : BackEndForm;
|
||||||
@@ -96,7 +102,7 @@ export class ToolPanel extends PureComponent {
|
|||||||
<FormElement isSubmitting={ isSubmitting }/>
|
<FormElement isSubmitting={ isSubmitting }/>
|
||||||
}
|
}
|
||||||
<div className='button-spacer' />
|
<div className='button-spacer' />
|
||||||
<ButtonGroup justified={ true }>
|
<ButtonGroup vertical={ true }>
|
||||||
<Button
|
<Button
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className='btn-primary-ghost btn-big'
|
className='btn-primary-ghost btn-big'
|
||||||
@@ -107,12 +113,21 @@ export class ToolPanel extends PureComponent {
|
|||||||
Help
|
Help
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
|
block={ true }
|
||||||
bsStyle='primary'
|
bsStyle='primary'
|
||||||
className='btn-primary-ghost btn-big'
|
className='btn-primary-ghost btn-big'
|
||||||
componentClass='div'
|
href={ guideUrl }
|
||||||
onClick={ openBugModal }
|
target='_blank'
|
||||||
>
|
>
|
||||||
Bug
|
Get a hint
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
block={ true }
|
||||||
|
bsStyle='primary'
|
||||||
|
className='btn-primary-ghost btn-big'
|
||||||
|
onClick={ openHelpModal }
|
||||||
|
>
|
||||||
|
Ask for help on the forum
|
||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user