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 (
+
+ );
+ }
+
+ @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 (
+
+ );
+ }
+
+ @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%;
+ }
+ }
+}