From b003f3acc3e078f66e42e422c90eb9467e8c8b4b Mon Sep 17 00:00:00 2001 From: EnixCoda Date: Sat, 19 May 2018 14:19:02 +0800 Subject: [PATCH] feat(settings): button for access token input --- src/components/SettingsBar.js | 97 ++++++++++++++++++++++------------- src/components/SideBar.js | 24 ++++----- src/content.less | 29 ++++++++--- src/utils/GitHubHelper.js | 1 + 4 files changed, 97 insertions(+), 54 deletions(-) diff --git a/src/components/SettingsBar.js b/src/components/SettingsBar.js index 4a8e0b4..6494257 100644 --- a/src/components/SettingsBar.js +++ b/src/components/SettingsBar.js @@ -9,30 +9,48 @@ const ACCESS_TOKEN_REGEXP = /^[0-9a-f]{40}$/ export default class SettingsBar extends preact.Component { state = { hint: null, - tokenCleared: false, + hasAccessToken: false, + accessToken: '', } - handleAccessTokenChange = event => { - const value = event.target.value + componentWillMount() { const { hasAccessToken } = this.props - if (value === '') { - if (hasAccessToken) { - storageHelper.setAccessToken('') - this.setState({ tokenCleared: true }) - } else { - this.setState({ hint: '' }) - } - } else if (ACCESS_TOKEN_REGEXP.test(value)) { - storageHelper.setAccessToken(value) - this.setState({ hint: 'Your token is saved, refresh the page to make it work!' }) - } else { - this.setState({ hint: 'Invalid token' }) + this.setState({ hasAccessToken }) + } + + componentWillReceiveProps({ hasAccessToken }) { + this.setState({ hasAccessToken }) + } + + onInputAccessToken = event => { + const value = event.target.value + this.setState({ accessToken: value }) + this.setState({ + hint: ACCESS_TOKEN_REGEXP.test(value) + ? '' + : 'This token is in unknown format.' + }) + } + + saveToken = () => { + const { accessToken } = this.state + if (accessToken) { + storageHelper.setAccessToken(accessToken) + this.setState({ + hasAccessToken: true, + hint: 'Your token is saved, will work after reloading the page!', + }) } } + clearToken = () => { + storageHelper.setAccessToken('') + this.setState({ accessToken: '', hasAccessToken: false }) + } + render() { - const { hint, tokenCleared } = this.state - const { toggleShowSettings, activated, hasAccessToken } = this.props + const { hint, accessToken, hasAccessToken } = this.state + const { toggleShowSettings, activated} = this.props return (
@@ -47,31 +65,39 @@ export default class SettingsBar extends preact.Component {

Access Token

- With access token, Gitako will be able to browse your private repositories with no - API request time limit. + With access token provided, Gitako can access more repositories.
- How to create access token? + Help: how to create access token?
- Gitako stores the token in{' '} + Gitako stores the token in  chrome local storage - {' '} - locally and safely. + +  locally and safely.
- + + { hasAccessToken - ? tokenCleared ? 'Your token is cleared' : 'Your token is saved' - : 'Input your token here' + ? + : } - onInput={this.handleAccessTokenChange} - /> +
{hint && {hint}}
@@ -89,11 +115,12 @@ export default class SettingsBar extends preact.Component {

Issue

- - Draft a issue on Github. - -
- Report BUG or request feature. + + + Draft a issue on Github + +  for bug report or feature request. +
)} diff --git a/src/components/SideBar.js b/src/components/SideBar.js index c350e34..d885ea5 100644 --- a/src/components/SideBar.js +++ b/src/components/SideBar.js @@ -9,7 +9,7 @@ import SettingsBar from './SettingsBar' import cx from '../utils/cx' import DOMHelper, { REPO_TYPE_PRIVATE } from '../utils/DOMHelper' -import GitHubHelper, { NOT_FOUND } from '../utils/GitHubHelper' +import GitHubHelper, { NOT_FOUND, BAD_CREDENTIALS } from '../utils/GitHubHelper' import storageHelper from '../utils/storageHelper' import URLHelper from '../utils/URLHelper' @@ -22,7 +22,7 @@ export default class SideBar extends preact.Component { // whether pending for network request loading: true, // whether failed loading the repo due to it is private - errorDueToPrivateRepo: false, + errorDueToAuth: false, // got access token for GitHub hasAccessToken: null, // meta data for the repository @@ -37,7 +37,7 @@ export default class SideBar extends preact.Component { this.setState({ metaData: metaDataFromUrl }) DOMHelper.decorateGitHubPageContent() const accessToken = await storageHelper.getAccessToken() - this.setState({ hasAccessToken: !!accessToken }) + this.setState({ hasAccessToken: Boolean(accessToken) }) const metaDataFromAPI = await GitHubHelper.getRepoMeta({ ...metaDataFromUrl, accessToken }) const branchName = metaDataFromUrl.branchName || metaDataFromAPI['default_branch'] const metaData = { ...metaDataFromUrl, branchName, api: metaDataFromAPI } @@ -51,14 +51,14 @@ export default class SideBar extends preact.Component { window.addEventListener('pjax:complete', this.onPJAXEnd) } catch (err) { // TODO: detect request time exceeds limit - if (err.message === NOT_FOUND) { + if (err.message === NOT_FOUND || err.message === BAD_CREDENTIALS) { const repoPageType = await DOMHelper.getRepoPageType() - const errorDueToPrivateRepo = repoPageType === REPO_TYPE_PRIVATE + const errorDueToAuth = repoPageType === REPO_TYPE_PRIVATE || err.message === BAD_CREDENTIALS this.setState({ showSettings: repoPageType !== null, - errorDueToPrivateRepo, + errorDueToAuth, }) - this.setShouldShow(errorDueToPrivateRepo) + this.setShouldShow(errorDueToAuth) } else { console.error(err) this.setShouldShow(false) @@ -100,24 +100,24 @@ export default class SideBar extends preact.Component { this.setState({ showSettings: !showSettings }) } - renderPrivateRepoError() { + renderAccessDeniedError() { return (
Access Denied

- Gitako need access token with proper scopes (recommended: repo) to read this repository's - data. + Gitako needs access token with proper scopes (recommended: repo) to access this repository. + Please save it in the settings below.

) } renderContent() { - const { errorDueToPrivateRepo, metaData, treeData, showSettings } = this.state + const { errorDueToAuth, metaData, treeData, showSettings } = this.state return (
{metaData && } - {errorDueToPrivateRepo && this.renderPrivateRepoError()} + {errorDueToAuth && this.renderAccessDeniedError()} {metaData && treeData && }
) diff --git a/src/content.less b/src/content.less index f16faf0..296d606 100644 --- a/src/content.less +++ b/src/content.less @@ -95,7 +95,7 @@ } .action-icon { - color: #0366d6; + color: #0366d6d0; } } @@ -156,6 +156,7 @@ .meta-bar { position: relative; padding: 10px; + padding-right: 30px; font-size: 13px; line-height: 20px; color: #586069; @@ -247,7 +248,6 @@ .@{name}-settings-bar { border-top: 1px solid #eaecef; - box-shadow: 0px -2px 16px #666666dd; &-content { padding: 0 10px; &-section { @@ -256,11 +256,21 @@ } .access-token { border-bottom: none; // prevent overwrite by github style + .hint { + color: #6a737d; + } } - .access-token-input { - width: 100%; - margin-top: 4px; - box-shadow: none; + .access-token-input-control { + display: flex; + margin-top: 8px; + .access-token-input { + flex: 1; + box-shadow: none; + + &:disabled { + cursor: not-allowed; + } + } } .placeholder-row { display: flex; @@ -268,11 +278,16 @@ align-items: center; padding: 6px 10px; - .settings-icon { + .show-settings-icon { width: 20px; height: 20px; cursor: pointer; } + .hide-settings-icon { + width: 15px; + height: 24px; + cursor: pointer; + } } } } diff --git a/src/utils/GitHubHelper.js b/src/utils/GitHubHelper.js index a2a7713..e4760c2 100644 --- a/src/utils/GitHubHelper.js +++ b/src/utils/GitHubHelper.js @@ -1,4 +1,5 @@ export const NOT_FOUND = 'Repo Not Found' +export const BAD_CREDENTIALS = 'Bad credentials' async function request(url, { accessToken } = {}) { const headers = {}