diff --git a/lib/controllers/github-tab-controller.js b/lib/controllers/github-tab-controller.js index 0c14c7dec5..2fc5de3313 100644 --- a/lib/controllers/github-tab-controller.js +++ b/lib/controllers/github-tab-controller.js @@ -4,6 +4,7 @@ import {autobind} from 'core-decorators'; import yubikiri from 'yubikiri'; import RemotePrController from './remote-pr-controller'; +import RemoteRepoController from './remote-repo-controller'; import GithubLoginModel from '../models/github-login-model'; import ObserveModel from '../views/observe-model'; import {RemotePropType} from '../prop-types'; @@ -114,7 +115,12 @@ export default class GithubTabController extends React.Component { selectRemote={this.handleRemoteSelect} /> } - {!remote && !manyRemotesAvailable && this.renderNoRemotes()} + {!remote && !manyRemotesAvailable && + + } ); @@ -154,14 +160,6 @@ export default class GithubTabController extends React.Component { return this.props.repository.getWorkingDirectoryPath(); } - renderNoRemotes() { - return ( -
- This repository does not have any remotes hosted at GitHub.com. -
- ); - } - @autobind handleRemoteSelect(e, remote) { e.preventDefault(); diff --git a/lib/controllers/remote-repo-controller.js b/lib/controllers/remote-repo-controller.js new file mode 100644 index 0000000000..250d3f0411 --- /dev/null +++ b/lib/controllers/remote-repo-controller.js @@ -0,0 +1,66 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {autobind} from 'core-decorators'; +import yubikiri from 'yubikiri'; + +import ObserveModelDecorator from '../decorators/observe-model'; +import GithubLoginView from '../views/github-login-view'; +import {UNAUTHENTICATED} from '../models/github-login-model'; +import {nullRemote} from '../models/remote'; +import RemoteRepoInputBox from '../views/remote-repo-input-box'; +import RemoteCreateForm from '../views/remote-create-form'; +import Octicon from '../views/octicon'; + +@ObserveModelDecorator({ + getModel: props => props.loginModel, + fetchData: (loginModel, {host}) => { + return yubikiri({ + token: loginModel.getToken(host), + }); + }, +}) +export default class RemoteRepoController extends React.Component { + static propTypes = { + loginModel: PropTypes.object.isRequired, + host: PropTypes.string, // fully qualified URI to the API endpoint, e.g. 'https://api.github.com' + token: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.symbol, + ]), + } + + static defaultProps = { + host: 'https://api.github.com', + remote: nullRemote, + token: null, + } + + render() { + const {token} = this.props; + return ( +
+ {token && token !== UNAUTHENTICATED && +
+
+ +

This repository does not have any remotes hosted at GitHub.com.

+ + +

You can manually add a remote to the current repo by entering its URL:

+
+ +

You can also create a new GitHub repo:

+
+
+
+ } + {(!token || token === UNAUTHENTICATED) && } +
+ ); + } + + @autobind + handleLogin(token) { + this.props.loginModel.setToken(this.props.host, token); + } +} diff --git a/lib/views/remote-create-form.js b/lib/views/remote-create-form.js new file mode 100644 index 0000000000..e568d10017 --- /dev/null +++ b/lib/views/remote-create-form.js @@ -0,0 +1,82 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {autobind} from 'core-decorators'; + +export default class RemoteCreateForm extends React.Component { + static propTypes = { + onSubmit: PropTypes.func.isRequired, + children: PropTypes.node, + } + + constructor(props, context) { + super(props, context); + this.state = { + repo: '', + description: '', + isPrivate: false, + }; + } + + render() { + return ( +
+ {this.props.children} + + + +
+ +
+
+ ); + } + + @autobind + handleSubmitFormClick(e) { + e.preventDefault(); + this.handleSubmitForm(); + } + + @autobind + handleSubmitForm() { + this.props.onSubmit(this.state.repo, this.state.description, this.state.private); + } + + @autobind + handleRepoChange(e) { + this.setState({repo: e.target.value}); + } + + @autobind + handleDescriptionChange(e) { + this.setState({url: e.target.value}); + } + + @autobind + handleIsPrivateBoxClick(e) { + this.setState({isPrivate: e.target.value}); + } +} diff --git a/lib/views/remote-repo-input-box.js b/lib/views/remote-repo-input-box.js new file mode 100644 index 0000000000..9d5d3d3590 --- /dev/null +++ b/lib/views/remote-repo-input-box.js @@ -0,0 +1,55 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {autobind} from 'core-decorators'; + +export default class RemoteRepoInputBox extends React.Component { + static propTypes = { + onSubmit: PropTypes.func.isRequired, + children: PropTypes.node, + } + + constructor(props, context) { + super(props, context); + this.state = { + repo: '', + }; + } + + render() { + return ( +
+ {this.props.children} + +
+ +
+
+ ); + } + + @autobind + handleSubmitRepoClick(e) { + e.preventDefault(); + this.handleSubmitRepo(); + } + + @autobind + handleSubmitRepo() { + this.props.onSubmit(this.state.url); + } + + @autobind + handleRepoChange(e) { + this.setState({repo: e.target.value}); + } +} diff --git a/styles/remote-repo-controller.less b/styles/remote-repo-controller.less new file mode 100644 index 0000000000..161d46eaa3 --- /dev/null +++ b/styles/remote-repo-controller.less @@ -0,0 +1,49 @@ + +@import "variables"; + +.github-RemoteRepoController { + display: flex; + flex: 1; + flex-direction: row; + + // TODO: Simplify selector + // Only add padding when inside this container + .github-RemoteRepoController-Subview { + padding: @component-padding * 2; + } + + .github-RemoteCreateForm-Subview { + margin-top: @component-padding * 2; + } + + &-Container { + flex: 1; + display: flex; + flex-direction: column; + + button, input[type=text], .btn, .input-label { + margin: @component-padding 0; + } + + .icon-octoface:before { + width: auto; + font-size: 48px; + color: @text-color-subtle; + } + + p { + font-size: 1.1em; + line-height: 1.5; + -webkit-user-select: none; + cursor: default; + + a { + color: @text-color-info; + } + } + + input[type=text] { + width: 100%; + } + } +}