From 3af8313b425ed6e3eec03c9bb61594024618d629 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 7 Jan 2022 19:27:18 -0600 Subject: [PATCH 1/2] Developers: add challenge to become a developer --- .../developers/developers_challenge.js | 84 +++++++++++++++++++ .../features/developers/developers_menu.js | 60 +++++++++++++ app/soapbox/features/developers/index.js | 62 ++++---------- app/soapbox/features/preferences/index.js | 4 - app/soapbox/features/ui/index.js | 2 +- app/styles/application.scss | 1 + app/styles/developers.scss | 21 +++++ 7 files changed, 182 insertions(+), 52 deletions(-) create mode 100644 app/soapbox/features/developers/developers_challenge.js create mode 100644 app/soapbox/features/developers/developers_menu.js create mode 100644 app/styles/developers.scss diff --git a/app/soapbox/features/developers/developers_challenge.js b/app/soapbox/features/developers/developers_challenge.js new file mode 100644 index 000000000..fe150e2ea --- /dev/null +++ b/app/soapbox/features/developers/developers_challenge.js @@ -0,0 +1,84 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; +import Column from '../ui/components/column'; +import { SimpleForm, TextInput } from 'soapbox/features/forms'; +import { changeSetting } from 'soapbox/actions/settings'; +import snackbar from 'soapbox/actions/snackbar'; + +const messages = defineMessages({ + heading: { id: 'column.developers', defaultMessage: 'Developers' }, + answerLabel: { id: 'developers.challenge.answer_label', defaultMessage: 'Answer' }, + answerPlaceholder: { id: 'developers.challenge.answer_placeholder', defaultMessage: 'Your answer' }, + success: { id: 'developers.challenge.success', defaultMessage: 'You are now a developer' }, + fail: { id: 'developers.challenge.fail', defaultMessage: 'Wrong answer' }, +}); + +export default @connect() +@injectIntl +class DevelopersChallenge extends React.Component { + + static propTypes = { + intl: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + } + + state = { + answer: '', + } + + handleChangeAnswer = e => { + this.setState({ answer: e.target.value }); + } + + handleSubmit = e => { + const { intl, dispatch } = this.props; + const { answer } = this.state; + + if (answer === 'buzzfizz') { + dispatch(changeSetting(['isDeveloper'], true)); + dispatch(snackbar.success(intl.formatMessage(messages.success))); + } else { + dispatch(snackbar.error(intl.formatMessage(messages.fail))); + } + } + + render() { + const { intl } = this.props; + + const challenge = `function fizzbuzz() { + return 'fizz|buzz'.split('|').reverse().join(''); +}`; + + return ( + +
+ + fizzbuzz() }} + /> +
+              {challenge}
+            
+ +
+ +
+
+
+
+ ); + } + +} diff --git a/app/soapbox/features/developers/developers_menu.js b/app/soapbox/features/developers/developers_menu.js new file mode 100644 index 000000000..44e0d1523 --- /dev/null +++ b/app/soapbox/features/developers/developers_menu.js @@ -0,0 +1,60 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; +import { Link } from 'react-router-dom'; +import Column from '../ui/components/column'; +import Icon from 'soapbox/components/icon'; + +const messages = defineMessages({ + heading: { id: 'column.developers', defaultMessage: 'Developers' }, +}); + +export default @injectIntl +class DevelopersMenu extends React.Component { + + static propTypes = { + intl: PropTypes.object.isRequired, + } + + render() { + const { intl } = this.props; + + return ( + +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+ ); + } + +} diff --git a/app/soapbox/features/developers/index.js b/app/soapbox/features/developers/index.js index 3c5734857..1302eab92 100644 --- a/app/soapbox/features/developers/index.js +++ b/app/soapbox/features/developers/index.js @@ -1,60 +1,28 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; -import { Link } from 'react-router-dom'; -import Column from '../ui/components/column'; -import Icon from 'soapbox/components/icon'; +import { connect } from 'react-redux'; +import { getSettings } from 'soapbox/actions/settings'; +import DevelopersMenu from './developers_menu'; +import DevelopersChallenge from './developers_challenge'; -const messages = defineMessages({ - heading: { id: 'column.developers', defaultMessage: 'Developers' }, -}); +const mapStateToProps = state => { + const settings = getSettings(state); -export default @injectIntl + return { + isDeveloper: settings.get('isDeveloper'), + }; +}; + +export default @connect(mapStateToProps) class Developers extends React.Component { static propTypes = { - intl: PropTypes.object.isRequired, + isDeveloper: PropTypes.bool.isRequired, } render() { - const { intl } = this.props; - - return ( - -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
- -
- -
-
-
- ); + const { isDeveloper } = this.props; + return isDeveloper ? : ; } } diff --git a/app/soapbox/features/preferences/index.js b/app/soapbox/features/preferences/index.js index f904e62a2..39a394d2f 100644 --- a/app/soapbox/features/preferences/index.js +++ b/app/soapbox/features/preferences/index.js @@ -282,10 +282,6 @@ class Preferences extends ImmutablePureComponent { hint={} path={['demetricator']} /> - } - path={['isDeveloper']} - /> diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index 2f69499a9..a8c2d4475 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -324,7 +324,7 @@ class SwitchingColumnsArea extends React.PureComponent { - + diff --git a/app/styles/application.scss b/app/styles/application.scss index 2918173a9..41ef7cf14 100644 --- a/app/styles/application.scss +++ b/app/styles/application.scss @@ -31,6 +31,7 @@ @import 'navigation'; @import 'placeholder'; @import 'autosuggest'; +@import 'developers'; // COMPONENTS @import 'components/buttons'; diff --git a/app/styles/developers.scss b/app/styles/developers.scss new file mode 100644 index 000000000..b33877120 --- /dev/null +++ b/app/styles/developers.scss @@ -0,0 +1,21 @@ +.developers-challenge { + .code { + font-family: 'Roboto Mono', monospace; + cursor: text; + background-color: var(--background-color); + } + + span.code { + padding: 2px 4px; + border-radius: 4px; + } + + pre.code { + line-height: 1.6em; + overflow-x: auto; + border-radius: 6px; + padding: 8px 12px; + margin: 20px 0; + word-break: break-all; + } +} From ef49cf911ce6d3017e55c448fa2a5a7277651dd1 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 7 Jan 2022 19:48:14 -0600 Subject: [PATCH 2/2] Developers: add "Leave developers" button --- .../features/developers/developers_menu.js | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/app/soapbox/features/developers/developers_menu.js b/app/soapbox/features/developers/developers_menu.js index 44e0d1523..3caa036d8 100644 --- a/app/soapbox/features/developers/developers_menu.js +++ b/app/soapbox/features/developers/developers_menu.js @@ -1,19 +1,39 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; import { FormattedMessage, injectIntl, defineMessages } from 'react-intl'; import { Link } from 'react-router-dom'; import Column from '../ui/components/column'; import Icon from 'soapbox/components/icon'; +import { changeSetting } from 'soapbox/actions/settings'; +import snackbar from 'soapbox/actions/snackbar'; const messages = defineMessages({ heading: { id: 'column.developers', defaultMessage: 'Developers' }, + leave: { id: 'developers.leave', defaultMessage: 'You have left developers' }, }); -export default @injectIntl +export default @connect() +@injectIntl class DevelopersMenu extends React.Component { + static contextTypes = { + router: PropTypes.object, + }; + static propTypes = { intl: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + } + + leaveDevelopers = e => { + const { intl, dispatch } = this.props; + + dispatch(changeSetting(['isDeveloper'], false)); + dispatch(snackbar.success(intl.formatMessage(messages.leave))); + + this.context.router.history.push('/'); + e.preventDefault(); } render() { @@ -52,6 +72,16 @@ class DevelopersMenu extends React.Component { + );