-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
542 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import {GITLAB_SET_TITLE, GITLAB_SET_SNIPPET_ID, GITLAB_SET_URL} from './Actions' | ||
|
||
export function gitLabSetUrl(url) { | ||
return {type: GITLAB_SET_URL, url} | ||
} | ||
|
||
export function gitLabSetSnippetId(snippetId) { | ||
return {type: GITLAB_SET_SNIPPET_ID, snippetId} | ||
} | ||
|
||
export function gitLabSetTitle(title) { | ||
return {type: GITLAB_SET_TITLE, title} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import {exportError, exporting, exportSuccess} from './ExportActionCreators' | ||
import {importError, importing} from './ImportActionCreators' | ||
import {gitLabUrl, gitLabSnippetId, gitLabTitle} from '../reducers/Selectors' | ||
import {toJson} from '../common/Json' | ||
import {filter} from '../reducers/Configuration' | ||
import {isBlank} from '../common/Utils' | ||
import {gitLabSetSnippetId, gitLabSetTitle} from './GitLabActionCreators' | ||
import {createSnippet, updateSnippet, getSnippetMeta, getSnippetContent, send} from '../gateways/GitLabGateway' | ||
import {importData} from './ImportThunkActionCreators' | ||
|
||
export function restoreFromGitLab(accessToken) { | ||
return async (dispatch, getState) => { | ||
dispatch(importing()) | ||
|
||
const url = gitLabUrl(getState()) | ||
const snippetId = gitLabSnippetId(getState()) | ||
|
||
if (isBlank(snippetId)) { | ||
dispatch(importError(['You must provide a snippet ID to import from GitLab'])) | ||
} else { | ||
try { | ||
const resMeta = await send(getSnippetMeta(url, snippetId, accessToken)) | ||
await handleSnippetResponse(dispatch, resMeta) | ||
|
||
const content = await send(getSnippetContent(url, snippetId, accessToken)) | ||
dispatch(importData(content)) | ||
} catch (error) { | ||
dispatch(importError([`Unable to import from GitLab because of an error: ${error.message}`])) | ||
} | ||
} | ||
} | ||
} | ||
|
||
function handleSnippetResponse(dispatch, res) { | ||
const configuration = res.get('file_name') | ||
|
||
if (configuration !== 'configuration.json') { | ||
throw new Error('snippet does not contain the required configuration.json file') | ||
} else { | ||
dispatch(gitLabSetTitle(res.get('title'))) | ||
} | ||
} | ||
|
||
export function uploadToGitLab(accessToken) { | ||
return async (dispatch, getState) => { | ||
dispatch(exporting()) | ||
|
||
const url = gitLabUrl(getState()) | ||
const id = gitLabSnippetId(getState()) | ||
const title = gitLabTitle(getState()) | ||
const configuration = toJson(filter(getState().toJS())) | ||
|
||
if (isBlank(accessToken)) { | ||
dispatch(exportError(['You must provide an access token to upload to GitLab'])) | ||
} else { | ||
const createNewSnippet = isBlank(id) | ||
|
||
const req = createNewSnippet | ||
? createSnippet(url, title, configuration, accessToken) | ||
: updateSnippet(url, id, title, configuration, accessToken) | ||
|
||
try { | ||
const snippetJson = await send(req) | ||
const returnedSnippetId = snippetJson.get('id').toString() | ||
const successMessage = createNewSnippet | ||
? `Successfully created snippet ${returnedSnippetId}` | ||
: `Successfully updated snippet ${returnedSnippetId}` | ||
|
||
dispatch(exportSuccess([successMessage])) | ||
dispatch(gitLabSetSnippetId(returnedSnippetId)) | ||
} catch (error) { | ||
dispatch(exportError([`Unable to upload to GitLab because of an error: ${error.message}`])) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React, {Component} from 'react' | ||
import PropTypes from 'prop-types' | ||
import {Input} from '../common/forms/Input' | ||
import styles from './snippet-id-input.scss' | ||
|
||
export class GitLabSnippetInput extends Component { | ||
|
||
constructor(props) { | ||
super(props) | ||
this.state = { | ||
newSnippetId: props.snippetId | ||
} | ||
} | ||
|
||
snippetIdChanged = (evt) => { | ||
this.setState({newSnippetId: evt.target.value}) | ||
} | ||
|
||
setSnippetId = () => { | ||
this.props.setSnippetId(this.state.newSnippetId) | ||
} | ||
|
||
render() { | ||
const {newSnippetId} = this.state | ||
const {disabled} = this.props | ||
|
||
return ( | ||
<Input className={styles.snippetId} | ||
value={newSnippetId} | ||
onChange={this.snippetIdChanged} | ||
onBlur={this.setSnippetId} | ||
disabled={disabled}> | ||
<div className={styles.label}>snippet ID</div> | ||
</Input> | ||
) | ||
} | ||
} | ||
|
||
GitLabSnippetInput.propTypes = { | ||
snippetId: PropTypes.string.isRequired, | ||
setSnippetId: PropTypes.func.isRequired, | ||
disabled: PropTypes.bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React, {Component} from 'react' | ||
import PropTypes from 'prop-types' | ||
import {Input} from '../common/forms/Input' | ||
import styles from './snippet-id-input.scss' | ||
|
||
export class GitLabUrlInput extends Component { | ||
|
||
constructor(props) { | ||
super(props) | ||
this.state = { | ||
newUrl: props.url | ||
} | ||
} | ||
|
||
urlChanged = (evt) => { | ||
this.setState({newUrl: evt.target.value}) | ||
} | ||
|
||
setUrl = () => { | ||
this.props.setUrl(this.state.newUrl) | ||
} | ||
|
||
render() { | ||
const {newUrl} = this.state | ||
const {disabled} = this.props | ||
|
||
return ( | ||
<Input className={styles.srlId} | ||
value={newUrl} | ||
onChange={this.urlChanged} | ||
onBlur={this.setUrl} | ||
disabled={disabled}> | ||
<div className={styles.label}>url</div> | ||
</Input> | ||
) | ||
} | ||
} | ||
|
||
GitLabUrlInput.propTypes = { | ||
url: PropTypes.string.isRequired, | ||
setUrl: PropTypes.func.isRequired, | ||
disabled: PropTypes.bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import React, {Component, Fragment} from 'react' | ||
import PropTypes from 'prop-types' | ||
import {Input} from '../../../common/forms/Input' | ||
import {GitLabSnippetInput} from '../../GitLabSnippetInput' | ||
import {GitLabUrlInput} from '../../GitLabUrlInput' | ||
import {PrimaryButton} from '../../../common/forms/Button' | ||
import {iCloudUpload} from '../../../common/fonts/Icons' | ||
import {Password} from '../../../common/forms/Password' | ||
import styles from './gitlab.scss' | ||
|
||
export class GitLab extends Component { | ||
|
||
constructor(props) { | ||
super(props) | ||
this.state = { | ||
accessToken: '', | ||
newTitle: props.title | ||
} | ||
} | ||
|
||
accessTokenChanged = (evt) => { | ||
this.setState({accessToken: evt.target.value}) | ||
} | ||
|
||
titleChanged = (evt) => { | ||
this.setState({newTitle: evt.target.value}) | ||
} | ||
|
||
setTitle = () => { | ||
this.props.gitLabSetTitle(this.state.newTitle) | ||
} | ||
|
||
upload = () => { | ||
const {accessToken} = this.state | ||
this.props.uploadToGitLab(accessToken) | ||
} | ||
|
||
render() { | ||
const {loaded, snippetId, url, gitLabSetSnippetId, gitLabSetUrl} = this.props | ||
const {accessToken, newTitle} = this.state | ||
const disabled = !loaded | ||
|
||
return ( | ||
<Fragment> | ||
<GitLabUrlInput key={url} | ||
url={url} | ||
setUrl={gitLabSetUrl} | ||
disabled={disabled}> | ||
</GitLabUrlInput> | ||
<GitLabSnippetInput key={snippetId} | ||
snippetId={snippetId} | ||
setSnippetId={gitLabSetSnippetId} | ||
disabled={disabled}/> | ||
<Input value={newTitle} | ||
onChange={this.titleChanged} | ||
onBlur={this.setTitle} | ||
disabled={disabled} | ||
maxLength='256'> | ||
<div className={styles.label}>title</div> | ||
</Input> | ||
<Password className={styles.accessToken} | ||
onChange={this.accessTokenChanged} | ||
onBlur={this.accessTokenChanged} | ||
value={accessToken} | ||
disabled={disabled}> | ||
<div className={styles.label}>access token</div> | ||
</Password> | ||
<PrimaryButton className={styles.export} | ||
onClick={this.upload} | ||
disabled={disabled} | ||
icon={iCloudUpload}> | ||
export | ||
</PrimaryButton> | ||
</Fragment> | ||
) | ||
} | ||
} | ||
|
||
GitLab.propTypes = { | ||
loaded: PropTypes.bool, | ||
uploadToGitLab: PropTypes.func.isRequired, | ||
gitLabSetSnippetId: PropTypes.func.isRequired, | ||
gitLabSetTitle: PropTypes.func.isRequired, | ||
gitLabSetUrl:PropTypes.func.isRequired, | ||
snippetId: PropTypes.string.isRequired, | ||
url: PropTypes.string.isRequired, | ||
title: PropTypes.string.isRequired | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import {connect} from 'react-redux' | ||
import {bindActionCreators} from 'redux' | ||
import {GitLab} from './GitLab' | ||
import {uploadToGitLab} from '../../../actions/GitLabThunkActionCreators' | ||
import {gitLabSetTitle, gitLabSetUrl, gitLabSetSnippetId} from '../../../actions/GitLabActionCreators' | ||
import {gitLabUrl, gitLabSnippetId, gitLabTitle, importLoaded} from '../../../reducers/Selectors' | ||
|
||
function mapDispatchToProps(dispatch) { | ||
return bindActionCreators({ | ||
uploadToGitLab, | ||
gitLabSetTitle, | ||
gitLabSetUrl, | ||
gitLabSetSnippetId | ||
}, dispatch) | ||
} | ||
|
||
|
||
function mapStateToProps(state) { | ||
return { | ||
loaded: importLoaded(state), | ||
url: gitLabUrl(state), | ||
snippetId: gitLabSnippetId(state), | ||
title: gitLabTitle(state) | ||
} | ||
} | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(GitLab) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
@import '../../../common/variables'; | ||
@import '../../../common/layout'; | ||
|
||
$label-size: 6em; | ||
|
||
.export { | ||
@extend %blocking; | ||
} | ||
|
||
.label { | ||
width: $label-size; | ||
} | ||
|
||
.accessToken { | ||
@include respond-to(tablet, desktop) { | ||
width: 36em; | ||
} | ||
} | ||
|
||
.help { | ||
margin: 0 $margin-right 0 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
9aa32ea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, adding the extra tab for Gitlab makes the tabs overflow the container on my mobile (One Plus 2)
9aa32ea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for testing. I'll take a look
9aa32ea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if its better to combine the tabs into "remotely" and have a drop down where you select github or gitlab?
9aa32ea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but are we doing that because it's a better UI layout or to get around fixing the overflow of tabs? :)