diff --git a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts index 16870069e3..758fa340a2 100644 --- a/apps/remix-ide-e2e/src/tests/workspace_git.test.ts +++ b/apps/remix-ide-e2e/src/tests/workspace_git.test.ts @@ -139,7 +139,7 @@ module.exports = { .click('[data-id="fileSystem-modal-footer-ok-react"]') .pause(5000) .waitForElementVisible('[data-id="cloneGitRepositoryModalDialogModalBody-react"]') - .waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin') + .waitForElementContainsText('[data-id="cloneGitRepositoryModalDialogModalBody-react"]', 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in the Git plugin') .click('[data-id="cloneGitRepository-modal-footer-ok-react"]') }, diff --git a/apps/remix-ide/src/app/files/dgitProvider.ts b/apps/remix-ide/src/app/files/dgitProvider.ts index a1e76b5999..75bb064be7 100644 --- a/apps/remix-ide/src/app/files/dgitProvider.ts +++ b/apps/remix-ide/src/app/files/dgitProvider.ts @@ -19,7 +19,7 @@ import { Octokit, App } from "octokit" import { OctokitResponse } from '@octokit/types' import { Endpoints } from "@octokit/types" import { IndexedDBStorage } from './filesystems/indexedDB' -import { GitHubUser, RateLimit, branch, commitChange, remote, pagedCommits, remoteCommitsInputType, cloneInputType, fetchInputType, pullInputType, pushInputType, currentBranchInput, branchInputType, addInput, rmInput, resolveRefInput, readBlobInput, repositoriesInput, commitInput, branchDifference, compareBranchesInput, initInput } from '@remix-ui/git' +import { GitHubUser, RateLimit, branch, commitChange, remote, pagedCommits, remoteCommitsInputType, cloneInputType, fetchInputType, pullInputType, pushInputType, currentBranchInput, branchInputType, addInput, rmInput, resolveRefInput, readBlobInput, repositoriesInput, commitInput, branchDifference, compareBranchesInput, initInput, userEmails } from '@remix-ui/git' import { LibraryProfile, StatusEvents } from '@remixproject/plugin-utils' import { ITerminal } from '@remixproject/plugin-api/src/lib/terminal' @@ -1004,7 +1004,8 @@ class DGitProvider extends Plugin { async getGitHubUser(input: { token: string }): Promise<{ user: GitHubUser, - ratelimit: RateLimit + ratelimit: RateLimit, + emails: userEmails, scopes: string[] }> { const octokit = new Octokit({ @@ -1023,6 +1024,8 @@ class DGitProvider extends Plugin { console.log('rate limit', localResetTimeString) const user = await octokit.request('GET /user') + const emails = await octokit.request('GET /user/emails') + const scopes = user.headers['x-oauth-scopes']; @@ -1030,6 +1033,7 @@ class DGitProvider extends Plugin { return { user: user.data, + emails: emails.data, ratelimit: ratelimit.data, scopes: scopes.split(',') } diff --git a/apps/remix-ide/src/app/plugins/git.tsx b/apps/remix-ide/src/app/plugins/git.tsx index 3d8b6ef02c..d28d93f1ac 100644 --- a/apps/remix-ide/src/app/plugins/git.tsx +++ b/apps/remix-ide/src/app/plugins/git.tsx @@ -2,13 +2,18 @@ import { ViewPlugin } from '@remixproject/engine-web'; import React from 'react' // eslint-disable-line import { gitState, GitUI } from '@remix-ui/git'; +import * as packageJson from '../../../../../package.json' + const profile = { name: 'dgit', desciption: 'Git plugin for Remix', methods: ['pull', 'track', 'diff', 'clone', 'open'], events: [''], - version: '0.0.1', + version: packageJson.version, + maintainedBy: 'Remix', + permission: true, + description: 'Use this plugin to interact with your git repositories', location: 'sidePanel', icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTIxLjAwNyA4LjIyMTY4QzIxLjAxMDUgNy41Mjc5MiAyMC44MjA3IDYuODQ2ODkgMjAuNDU5MSA2LjI1NDg1QzIwLjA5NzQgNS42NjI4MSAxOS41NzggNS4xODMxNSAxOC45NTkyIDQuODY5NTdDMTguMzQwMyA0LjU1NiAxNy42NDYzIDQuNDIwOTEgMTYuOTU1MSA0LjQ3OTQxQzE2LjI2MzcgNC41Mzc5MyAxNS42MDI1IDQuNzg3NzMgMTUuMDQ1IDUuMjAwODVDMTQuNDg3NyA1LjYxMzk3IDE0LjA1NjMgNi4xNzQwOSAxMy43OTkzIDYuODE4NUMxMy41NDI0IDcuNDYyOSAxMy40Njk3IDguMTY2MTMgMTMuNTg5OCA4Ljg0OTQ0QzEzLjcwOTkgOS41MzI3NCAxNC4wMTc3IDEwLjE2OTIgMTQuNDc4OSAxMC42ODc0QzE0Ljk0MDIgMTEuMjA1NiAxNS41MzY3IDExLjU4NTIgMTYuMjAxNSAxMS43ODM2QzE1Ljk1NiAxMi4yODI0IDE1LjU3NjMgMTIuNzAzIDE1LjEwNDkgMTIuOTk3OUMxNC42MzM2IDEzLjI5MjkgMTQuMDg5NCAxMy40NTA1IDEzLjUzMzQgMTMuNDUzMkgxMC41NDRDOS40MzcyNiAxMy40NTcxIDguMzcxNjMgMTMuODcyNyA3LjU1NDUxIDE0LjYxOTFWNy4zOTgwOUM4LjQ2MTg0IDcuMjEyODggOS4yNjgwOCA2LjY5NzM3IDkuODE2OTIgNS45NTE1MUMxMC4zNjU4IDUuMjA1NjUgMTAuNjE4MSA0LjI4MjU2IDEwLjUyNSAzLjM2MTIxQzEwLjQzMTkgMi40Mzk4NyAxMC4wMDAxIDEuNTg1OSA5LjMxMzE2IDAuOTY0ODczQzguNjI2MjQgMC4zNDM4NDUgNy43MzMxOSAwIDYuODA3MTYgMEM1Ljg4MTEyIDAgNC45ODgwNyAwLjM0Mzg0NSA0LjMwMTE0IDAuOTY0ODczQzMuNjE0MjIgMS41ODU5IDMuMTgyMzYgMi40Mzk4NyAzLjA4OTI4IDMuMzYxMjFDMi45OTYyIDQuMjgyNTYgMy4yNDg1NSA1LjIwNTY1IDMuNzk3MzkgNS45NTE1MUM0LjM0NjIzIDYuNjk3MzcgNS4xNTI0NyA3LjIxMjg4IDYuMDU5OCA3LjM5ODA5VjE2LjUxNTlDNS4xNTQxOCAxNi42ODkxIDQuMzQzMjMgMTcuMTg3NyAzLjc3OTkzIDE3LjkxNzZDMy4yMTY2MyAxOC42NDc2IDIuOTM5OTIgMTkuNTU4NSAzLjAwMTk3IDIwLjQ3ODVDMy4wNjQwMyAyMS4zOTg0IDMuNDYwNTcgMjIuMjYzOSA0LjExNjggMjIuOTExNUM0Ljc3MzAzIDIzLjU1OTIgNS42NDM2IDIzLjk0NDQgNi41NjQyNyAyMy45OTQ0QzcuNDg0OTYgMjQuMDQ0NSA4LjM5MjExIDIzLjc1NTggOS4xMTQ2NCAyMy4xODNDOS44MzcxOCAyMi42MTAyIDEwLjMyNTEgMjEuNzkyOCAxMC40ODY1IDIwLjg4NUMxMC42NDc4IDE5Ljk3NzEgMTAuNDcxNCAxOS4wNDE3IDkuOTkwNDggMTguMjU1QzkuNTA5NTcgMTcuNDY4MyA4Ljc1NzQxIDE2Ljg4NDggNy44NzU4OCAxNi42MTQ1QzguMTIxNzYgMTYuMTE2MiA4LjUwMTY3IDE1LjY5NjMgOC45NzI5NiAxNS40MDE5QzkuNDQ0MjYgMTUuMTA3NCA5Ljk4ODI3IDE0Ljk1MDMgMTAuNTQ0IDE0Ljk0NzlIMTMuNTMzNEMxNC40NjYxIDE0Ljk0MzYgMTUuMzc0MiAxNC42NDg2IDE2LjEzMTMgMTQuMTAzOUMxNi44ODg0IDEzLjU1OTIgMTcuNDU2OCAxMi43OTIgMTcuNzU3NSAxMS45MDkxQzE4LjY1MzQgMTEuNzkxNCAxOS40NzYzIDExLjM1MjggMjAuMDczOCAxMC42NzQ4QzIwLjY3MTMgOS45OTY4IDIxLjAwMjggOS4xMjUzMyAyMS4wMDcgOC4yMjE2OFpNNC41NjUwOCAzLjczNzUyQzQuNTY1MDggMy4yOTQwOCA0LjY5NjU3IDIuODYwNiA0Ljk0MjkzIDIuNDkxOUM1LjE4OTMgMi4xMjMxOSA1LjUzOTQ3IDEuODM1ODEgNS45NDkxNSAxLjY2NjExQzYuMzU4ODQgMS40OTY0MiA2LjgwOTY1IDEuNDUyMDIgNy4yNDQ1NiAxLjUzODU0QzcuNjc5NDggMS42MjUwNCA4LjA3ODk4IDEuODM4NTcgOC4zOTI1NCAyLjE1MjE0QzguNzA2MTEgMi40NjU3IDguOTE5NjQgMi44NjUyIDkuMDA2MTUgMy4zMDAxMkM5LjA5MjY2IDMuNzM1MDQgOS4wNDgyNyA0LjE4NTg1IDguODc4NTcgNC41OTU1M0M4LjcwODg3IDUuMDA1MjEgOC40MjE0OSA1LjM1NTM5IDguMDUyNzggNS42MDE3NUM3LjY4NDA4IDUuODQ4MTEgNy4yNTA2IDUuOTc5NiA2LjgwNzE2IDUuOTc5NkM2LjIxMjUyIDUuOTc5NiA1LjY0MjI0IDUuNzQzMzkgNS4yMjE3NyA1LjMyMjkxQzQuODAxMjkgNC45MDI0NSA0LjU2NTA4IDQuMzMyMTYgNC41NjUwOCAzLjczNzUyWk05LjA0OTIzIDIwLjE3OTRDOS4wNDkyMyAyMC42MjI5IDguOTE3NzQgMjEuMDU2MyA4LjY3MTM4IDIxLjQyNUM4LjQyNTAxIDIxLjc5MzcgOC4wNzQ4NSAyMi4wODExIDcuNjY1MTYgMjIuMjUwOEM3LjI1NTQ3IDIyLjQyMDUgNi44MDQ2NiAyMi40NjQ5IDYuMzY5NzUgMjIuMzc4NEM1LjkzNDgzIDIyLjI5MiA1LjUzNTMzIDIyLjA3ODQgNS4yMjE3NyAyMS43NjQ4QzQuOTA4MjEgMjEuNDUxMiA0LjY5NDY3IDIxLjA1MTcgNC42MDgxNiAyMC42MTY5QzQuNTIxNjUgMjAuMTgxOSA0LjU2NjA1IDE5LjczMTEgNC43MzU3NSAxOS4zMjE0QzQuOTA1NDUgMTguOTExNyA1LjE5MjgyIDE4LjU2MTUgNS41NjE1MyAxOC4zMTUyQzUuOTMwMjMgMTguMDY4OSA2LjM2MzcxIDE3LjkzNzMgNi44MDcxNiAxNy45MzczQzcuNDAxNzkgMTcuOTM3MyA3Ljk3MjA3IDE4LjE3MzYgOC4zOTI1NCAxOC41OTRDOC44MTMwMiAxOS4wMTQ1IDkuMDQ5MjMgMTkuNTg0OCA5LjA0OTIzIDIwLjE3OTRaTTE3LjI3MDIgMTAuNDYzOEMxNi44MjY3IDEwLjQ2MzggMTYuMzkzMyAxMC4zMzIyIDE2LjAyNDYgMTAuMDg1OUMxNS42NTU5IDkuODM5NTQgMTUuMzY4NSA5LjQ4OTM3IDE1LjE5ODggOS4wNzk2OUMxNS4wMjkxIDguNjcgMTQuOTg0NyA4LjIxOTIgMTUuMDcxMiA3Ljc4NDI3QzE1LjE1NzYgNy4zNDkzNSAxNS4zNzEyIDYuOTQ5ODUgMTUuNjg0OCA2LjYzNjI5QzE1Ljk5ODQgNi4zMjI3MyAxNi4zOTc5IDYuMTA5MTkgMTYuODMyNyA2LjAyMjY4QzE3LjI2NzcgNS45MzYxNyAxNy43MTg1IDUuOTgwNTggMTguMTI4MSA2LjE1MDI3QzE4LjUzNzkgNi4zMTk5NyAxOC44ODgxIDYuNjA3MzQgMTkuMTM0NCA2Ljk3NjA1QzE5LjM4MDcgNy4zNDQ3NiAxOS41MTIzIDcuNzc4MjMgMTkuNTEyMyA4LjIyMTY4QzE5LjUxMjMgOC44MTYzMiAxOS4yNzYgOS4zODY2IDE4Ljg1NTYgOS44MDcwNkMxOC40MzUxIDEwLjIyNzUgMTcuODY0OCAxMC40NjM4IDE3LjI3MDIgMTAuNDYzOFoiIGZpbGw9IiM0MjQyNDIiLz4KPC9zdmc+Cg==" } diff --git a/apps/remix-ide/src/app/tabs/locales/en/filePanel.json b/apps/remix-ide/src/app/tabs/locales/en/filePanel.json index 5f033c3aad..9c189262e8 100644 --- a/apps/remix-ide/src/app/tabs/locales/en/filePanel.json +++ b/apps/remix-ide/src/app/tabs/locales/en/filePanel.json @@ -78,7 +78,7 @@ "filePanel.checkoutGitBranch": "Checkout Git Branch", "filePanel.findOrCreateABranch": "Find or create a branch.", "filePanel.initGitRepositoryLabel": "Initialize workspace as a new git repository", - "filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Settings panel.", + "filePanel.initGitRepositoryWarning": "To use Git features, add username and email to the Github section of the Git plugin.", "filePanel.workspaceName": "Workspace name", "filePanel.customizeTemplate": "Customize template", "filePanel.features": "Features", diff --git a/libs/remix-ui/git/src/components/github/devicecode.tsx b/libs/remix-ui/git/src/components/github/devicecode.tsx index be6081f335..eacb315e70 100644 --- a/libs/remix-ui/git/src/components/github/devicecode.tsx +++ b/libs/remix-ui/git/src/components/github/devicecode.tsx @@ -21,7 +21,7 @@ export const GetDeviceCode = () => { url: 'http://0.0.0.0:3000/github.com/login/device/code', data: { client_id: '2795b4e41e7197d6ea11', - scope: 'repo gist' + scope: 'repo gist user:email read:user' }, headers: { 'Content-Type': 'application/json', @@ -63,7 +63,7 @@ export const GetDeviceCode = () => { if (response.access_token) { setAuthorized(true) await pluginActions.saveToken(response.access_token) - await actions.getGitHubUser() + await actions.loadGitHubUserFromToken() } } @@ -72,11 +72,11 @@ export const GetDeviceCode = () => { setAuthorized(false) setGitHubResponse(null) await pluginActions.saveToken(null) - await actions.getGitHubUser() + await actions.loadGitHubUserFromToken() } const checkConnection = async () => { - //await actions.getGitHubUser() + //await actions.loadGitHubUserFromToken() } useEffect(() => { @@ -131,6 +131,9 @@ export const GetDeviceCode = () => { {context.gitHubUser.html_url} + {context.userEmails && context.userEmails.filter((email: any) => email.primary).map((email: any) => { + return

{email.email}
+ })}
diff --git a/libs/remix-ui/git/src/components/gitui.tsx b/libs/remix-ui/git/src/components/gitui.tsx index 604b218124..8140707171 100644 --- a/libs/remix-ui/git/src/components/gitui.tsx +++ b/libs/remix-ui/git/src/components/gitui.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useReducer, useState } from 'react' -import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, getGitHubUser, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentials, fetch, pull, push, setDefaultRemote, addRemote, removeRemote, sendToGitLog, clearGitLog, getBranchDifferences, getFileStatusMatrix } from '../lib/gitactions' +import { add, addall, checkout, checkoutfile, clone, commit, createBranch, remoteBranches, repositories, rm, getCommitChanges, diff, resolveRef, getBranchCommits, setUpstreamRemote, loadGitHubUserFromToken, getBranches, getRemotes, remoteCommits, saveGitHubCredentials, getGitHubCredentialsFromLocalStorage, fetch, pull, push, setDefaultRemote, addRemote, removeRemote, sendToGitLog, clearGitLog, getBranchDifferences, getFileStatusMatrix } from '../lib/gitactions' import { loadFiles, setCallBacks } from '../lib/listeners' import { openDiff, openFile, saveToken, setModifiedDecorator, setPlugin, setUntrackedDecorator, statusChanged } from '../lib/pluginActions' import { gitActionsContext, pluginActionsContext } from '../state/context' @@ -42,7 +42,8 @@ export const GitUI = (props: IGitUi) => { const plugin = props.plugin const [gitState, gitDispatch] = useReducer(gitReducer, defaultGitState) const [loaderState, loaderDispatch] = useReducer(loaderReducer, defaultLoaderState) - const [activePanel, setActivePanel] = useState("0"); + const [activePanel, setActivePanel] = useState("0") + const [setup, setSetup] = useState(false) useEffect(() => { setCallBacks(plugin, gitDispatch, loaderDispatch) @@ -51,6 +52,18 @@ export const GitUI = (props: IGitUi) => { console.log(props) }, []) + useEffect(() => { + async function checkconfig() { + + const username = await plugin.call('settings', 'get', 'settings/github-user-name') + const email = await plugin.call('settings', 'get', 'settings/github-email') + const token = await plugin.call('settings', 'get', 'settings/gist-access-token') + console.log('gitState', gitState, username, email, token) + setSetup(!(username && email)) + } + checkconfig() + },[gitState.gitHubAccessToken, gitState.gitHubUser, gitState.userEmails]) + useEffect(() => { async function setDecorators(gitState: gitState) { @@ -97,7 +110,7 @@ export const GitUI = (props: IGitUi) => { diff, resolveRef, setUpstreamRemote, - getGitHubUser, + loadGitHubUserFromToken: loadGitHubUserFromToken, getBranches, getRemotes, fetch, @@ -118,7 +131,7 @@ export const GitUI = (props: IGitUi) => { openDiff, saveToken, saveGitHubCredentials, - getGitHubCredentials + getGitHubCredentialsFromLocalStorage } return ( @@ -128,7 +141,7 @@ export const GitUI = (props: IGitUi) => { - + {setup? : null} diff --git a/libs/remix-ui/git/src/components/navigation/github.tsx b/libs/remix-ui/git/src/components/navigation/github.tsx index 8b8ce88237..f44792b729 100644 --- a/libs/remix-ui/git/src/components/navigation/github.tsx +++ b/libs/remix-ui/git/src/components/navigation/github.tsx @@ -21,7 +21,7 @@ export const GitHubNavigation = ({ eventKey, activePanel, callback }) => { { activePanel === eventKey ? : } - + diff --git a/libs/remix-ui/git/src/components/panels/github.tsx b/libs/remix-ui/git/src/components/panels/github.tsx deleted file mode 100644 index 3665875528..0000000000 --- a/libs/remix-ui/git/src/components/panels/github.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React, { useEffect } from "react"; -import { gitActionsContext, pluginActionsContext } from "../../state/context"; -import { gitPluginContext, loaderContext } from "../gitui"; -import axios from "axios"; -import { CopyToClipboard } from "@remix-ui/clipboard"; -import { Card } from "react-bootstrap"; - -export const GitHubAuth = () => { - const context = React.useContext(gitPluginContext) - const actions = React.useContext(gitActionsContext) - const loader = React.useContext(loaderContext) - const pluginActions = React.useContext(pluginActionsContext) - const [gitHubResponse, setGitHubResponse] = React.useState(null) - const [authorized, setAuthorized] = React.useState(false) - - useEffect(() => { - checkConnection() - }, [context.gitHubAccessToken, loader.plugin]) - - const checkConnection = async () => { - console.log('checkConnection', context.gitHubAccessToken) - await actions.getGitHubUser() - } - - useEffect(() => { - console.log('context.rateLimit', context.rateLimit) - }, [context.rateLimit]) - - return ( - <> - {(context.gitHubUser && context.gitHubUser.login) ? null : -
  • - Not connected to GitHub. Add a valid token.
  • - } - { - (context.gitHubUser && context.gitHubUser.login) ? -
    - - - Connected as {context.gitHubUser.login} - - - {context.gitHubUser.html_url} - - - -
    : null - } - - ) -} \ No newline at end of file diff --git a/libs/remix-ui/git/src/components/panels/githubcredentials.tsx b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx index 677df74bcd..f65ec02e38 100644 --- a/libs/remix-ui/git/src/components/panels/githubcredentials.tsx +++ b/libs/remix-ui/git/src/components/panels/githubcredentials.tsx @@ -6,10 +6,12 @@ import { CustomTooltip } from "@remix-ui/helper"; import { useIntl, FormattedMessage } from "react-intl"; import { CopyToClipboard } from "@remix-ui/clipboard"; + export const GitHubCredentials = () => { const context = React.useContext(gitPluginContext) const pluginactions = React.useContext(pluginActionsContext) const loader = React.useContext(loaderContext) + const actions = React.useContext(gitActionsContext) const [githubToken, setGithubToken] = React.useState('') const [githubUsername, setGithubUsername] = React.useState('') const [githubEmail, setGithubEmail] = React.useState('') @@ -17,7 +19,7 @@ export const GitHubCredentials = () => { useEffect(() => { refresh() - }, [loader.plugin, context.gitHubAccessToken]) + }, [loader.plugin, context.gitHubAccessToken, context.userEmails, context.gitHubUser]) function handleChangeTokenState(e: string): void { setGithubToken(e) @@ -40,7 +42,7 @@ export const GitHubCredentials = () => { } async function refresh() { - const credentials = await pluginactions.getGitHubCredentials() + const credentials = await pluginactions.getGitHubCredentialsFromLocalStorage() if (!credentials) return console.log('credentials', credentials) setGithubToken(credentials.token || '') diff --git a/libs/remix-ui/git/src/components/panels/setup.tsx b/libs/remix-ui/git/src/components/panels/setup.tsx index 6f6c6524a3..22eb35fe77 100644 --- a/libs/remix-ui/git/src/components/panels/setup.tsx +++ b/libs/remix-ui/git/src/components/panels/setup.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react' +import { GetDeviceCode } from '../github/devicecode' import { GitHubCredentials } from './githubcredentials' export const Setup = () => { @@ -9,12 +10,14 @@ export const Setup = () => { if (screen === 0) { return ( <> -
    SETUP - STEP 1
    +
    SETUP
    To ensure that your commits are properly attributed in Git, you need to configure a username and email address. These will be used to identify the author of the commit.
    + +
    diff --git a/libs/remix-ui/git/src/lib/gitactions.ts b/libs/remix-ui/git/src/lib/gitactions.ts index 90c974a0cb..f1313faa73 100644 --- a/libs/remix-ui/git/src/lib/gitactions.ts +++ b/libs/remix-ui/git/src/lib/gitactions.ts @@ -1,8 +1,8 @@ import { ViewPlugin } from "@remixproject/engine-web"; import { ReadBlobResult, ReadCommitResult } from "isomorphic-git"; import React from "react"; -import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog } from "../state/gitpayload"; -import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog, fileStatusResult, customGitApi, IGitApi, cloneInputType, fetchInputType, pullInputType, pushInputType, checkoutInput, rmInput, addInput, repository } from '../types'; +import { fileStatus, fileStatusMerge, setRemoteBranchCommits, resetRemoteBranchCommits, setBranches, setCanCommit, setCommitChanges, setCommits, setCurrentBranch, setGitHubUser, setLoading, setRateLimit, setRemoteBranches, setRemotes, setRepos, setUpstream, setLocalBranchCommits, setBranchDifferences, setRemoteAsDefault, setScopes, setLog, clearLog, setUserEmails } from "../state/gitpayload"; +import { GitHubUser, RateLimit, branch, commitChange, gitActionDispatch, statusMatrixType, gitState, branchDifference, remote, gitLog, fileStatusResult, customGitApi, IGitApi, cloneInputType, fetchInputType, pullInputType, pushInputType, checkoutInput, rmInput, addInput, repository, userEmails } from '../types'; import { removeSlash } from "../utils"; import { disableCallBacks, enableCallBacks } from "./listeners"; import { AlertModal, ModalTypes } from "@remix-ui/app"; @@ -532,7 +532,7 @@ export const saveGitHubCredentials = async (credentials: { username: string, ema } } -export const getGitHubCredentials = async () => { +export const getGitHubCredentialsFromLocalStorage = async () => { if (!plugin) return try { const username = await plugin.call('config', 'getAppParameter', 'settings/github-user-name') @@ -548,7 +548,7 @@ export const getGitHubCredentials = async () => { } } -export const getGitHubUser = async () => { +export const loadGitHubUserFromToken = async () => { if (!plugin) return try { const token = await tokenWarning(); @@ -557,14 +557,25 @@ export const getGitHubUser = async () => { user: GitHubUser, ratelimit: RateLimit scopes: string[] + emails: userEmails } = await plugin.call('dgitApi' as any, 'getGitHubUser', { token }); console.log('GET USER"', data) - - dispatch(setGitHubUser(data.user)) - dispatch(setRateLimit(data.ratelimit)) - dispatch(setScopes(data.scopes)) + if (data && data.emails && data.user && data.user.login) { + const primaryEmail = data.emails.find(email => email.primary) + if (primaryEmail) await plugin.call('config', 'setAppParameter', 'settings/github-email', primaryEmail.email) + data.user && data.user.login && await plugin.call('config', 'setAppParameter', 'settings/github-user-name', data.user.login) + dispatch(setGitHubUser(data.user)) + dispatch(setRateLimit(data.ratelimit)) + dispatch(setScopes(data.scopes)) + dispatch(setUserEmails(data.emails)) + } } else { + const credentials = await getGitHubCredentialsFromLocalStorage() + if (credentials) { + //dispatch(setGitHubUser({ login: credentials.username })) + //dispatch(setUserEmails([{ email: credentials.email, primary: true, visibility: 'public', verified: true }])) + } dispatch(setGitHubUser(null)) } } catch (e) { @@ -585,10 +596,6 @@ export const statusMatrix = async (filepaths: string[]) => { return result; } -export const diffFiles = async (filename: string | undefined) => { - -} - export const resolveRef = async (ref: string) => { const oid = await plugin.call('dgitApi', "resolveref", { ref, diff --git a/libs/remix-ui/git/src/lib/listeners.ts b/libs/remix-ui/git/src/lib/listeners.ts index 5d6f9a02d1..23de1c5f8f 100644 --- a/libs/remix-ui/git/src/lib/listeners.ts +++ b/libs/remix-ui/git/src/lib/listeners.ts @@ -1,9 +1,9 @@ import React from "react"; -import { setCanUseApp, setLoading, setRepoName, setGItHubToken, setLog } from "../state/gitpayload"; +import { setCanUseApp, setLoading, setRepoName, setGItHubToken, setLog, setGitHubUser, setUserEmails } from "../state/gitpayload"; import { gitActionDispatch } from "../types"; import { Plugin } from "@remixproject/engine"; -import { getBranches, getFileStatusMatrix, getGitHubUser, getRemotes, gitlog, setPlugin } from "./gitactions"; +import { getBranches, getFileStatusMatrix, loadGitHubUserFromToken, getRemotes, gitlog, setPlugin } from "./gitactions"; import { Profile } from "@remixproject/plugin-utils"; import { CustomRemixApi } from "@remix-api"; @@ -141,7 +141,7 @@ export const setCallBacks = (viewPlugin: Plugin, gitDispatcher: React.Dispatch) => { if (p.name === 'dgitApi') { - getGitHubUser(); + loadGitHubUserFromToken(); plugin.off('manager', 'pluginActivated'); } }) @@ -162,6 +162,10 @@ export const getGitConfig = async () => { const token = await plugin.call('settings', 'get', 'settings/gist-access-token') const config = { username, email, token } gitDispatch(setGItHubToken(config.token)) + gitDispatch(setGitHubUser({ + login: config.username, + })) + gitDispatch(setUserEmails([{ email: email, primary: true, visibility: 'public', verified: true }])) return config } diff --git a/libs/remix-ui/git/src/state/actions.ts b/libs/remix-ui/git/src/state/actions.ts new file mode 100644 index 0000000000..99e7fed793 --- /dev/null +++ b/libs/remix-ui/git/src/state/actions.ts @@ -0,0 +1,51 @@ +import { ReadCommitResult } from "isomorphic-git" +import { branch, branchDifference, commitChange, fileStatusResult, GitHubUser, gitLog, pagedCommits, remote, remoteBranch, repository, userEmails } from "../types" + +export interface ActionPayloadTypes { + FILE_STATUS: fileStatusResult[], + FILE_STATUS_MERGE: fileStatusResult[] + SET_COMMITS: ReadCommitResult[] + SET_BRANCHES: branch[] + SET_CURRENT_BRANCH: branch + SET_CAN_USE_APP: boolean + SET_REPO_NAME: string + SET_LOADING: boolean + SET_REPOS: repository[] + SET_REMOTE_BRANCHES: remoteBranch[] + SET_CAN_COMMIT: boolean + SET_REMOTES: remote[] + SET_UPSTREAM: remote + SET_COMMIT_CHANGES: commitChange[] + RESET_REMOTE_BRANCH_COMMITS: { + branch: branch + pagedCommits: pagedCommits[] + } + SET_REMOTE_BRANCH_COMMITS: { + branch: branch + commits: pagedCommits[] + } + SET_LOCAL_BRANCH_COMMITS: { + branch: branch + commits: ReadCommitResult[] + } + SET_BRANCH_DIFFERENCES: { + branch: branch + remote: remote + branchDifference: branchDifference + } + SET_GITHUB_USER: GitHubUser + SET_RATE_LIMIT: any + SET_GITHUB_ACCESS_TOKEN: string + SET_SCOPES: string[] + SET_DEFAULT_REMOTE: remote + SET_LOG: gitLog + CLEAR_LOG: void + SET_USER_EMAILS: userEmails +} + +export interface Action { + type: T, + payload: ActionPayloadTypes[T] +} + +export type Actions = {[A in keyof ActionPayloadTypes]: Action}[keyof ActionPayloadTypes] \ No newline at end of file diff --git a/libs/remix-ui/git/src/state/context.tsx b/libs/remix-ui/git/src/state/context.tsx index 3fe88c610a..519119b517 100644 --- a/libs/remix-ui/git/src/state/context.tsx +++ b/libs/remix-ui/git/src/state/context.tsx @@ -20,7 +20,7 @@ export interface gitActions { getCommitChanges(oid1: string, oid2: string, branch?: branch, remote?: remote): Promise getBranchCommits(branch: branch, page: number): Promise getBranchDifferences(branch: branch, remote?: remote, state?: gitState): Promise - getGitHubUser(): Promise + loadGitHubUserFromToken(): Promise diff(commitChange: commitChange): Promise resolveRef(ref: string): Promise setUpstreamRemote(upstream: remote): Promise @@ -46,7 +46,7 @@ export interface pluginActions { email, token }): Promise - getGitHubCredentials(): Promise<{ + getGitHubCredentialsFromLocalStorage(): Promise<{ username: string email: string token: string diff --git a/libs/remix-ui/git/src/state/gitpayload.ts b/libs/remix-ui/git/src/state/gitpayload.ts index 6099dac581..ec54f9117a 100644 --- a/libs/remix-ui/git/src/state/gitpayload.ts +++ b/libs/remix-ui/git/src/state/gitpayload.ts @@ -1,5 +1,5 @@ import { ReadCommitResult } from "isomorphic-git" -import { GitHubUser, branch, commitChange, fileStatusResult, remote, pagedCommits, branchDifference, gitLog, repository } from "../types" +import { GitHubUser, branch, commitChange, fileStatusResult, remote, pagedCommits, branchDifference, gitLog, repository, userEmails } from "../types" import { Endpoints } from "@octokit/types" export const fileStatus = (files: fileStatusResult[]) => { @@ -44,13 +44,20 @@ export const setRemoteBranches = (branches: any[]) => { } } -export const setGitHubUser = (user: any) => { +export const setGitHubUser = (user: GitHubUser) => { return { type: 'SET_GITHUB_USER', payload: user } } +export const setUserEmails = (emails: userEmails) => { + return { + type: 'SET_USER_EMAILS', + payload: emails + } +} + export const setRateLimit = (rateLimit: any) => { return { type: 'SET_RATE_LIMIT', diff --git a/libs/remix-ui/git/src/state/gitreducer.tsx b/libs/remix-ui/git/src/state/gitreducer.tsx index 8e66f2f005..4542272fd4 100644 --- a/libs/remix-ui/git/src/state/gitreducer.tsx +++ b/libs/remix-ui/git/src/state/gitreducer.tsx @@ -1,13 +1,9 @@ import { ReadCommitResult } from "isomorphic-git" import { allChangedButNotStagedFiles, getFilesByStatus, getFilesWithNotModifiedStatus } from "../lib/fileHelpers" import { branch, commitChange, defaultGitState, fileStatusResult, gitState, setRemoteBranchCommitsAction, setLocalBranchCommitsAction, setBranchDifferencesAction, setDefaultRemoteAction, setRemotesAction, setUpstreamAction } from "../types" +import { Actions } from "./actions" -interface Action { - type: string - payload: any -} - -export const gitReducer = (state: gitState = defaultGitState, action: Action): gitState => { +export const gitReducer = (state: gitState = defaultGitState, action: Actions): gitState => { ///console.log(action, state) switch (action.type) { @@ -104,7 +100,7 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g case 'SET_UPSTREAM': return { ...state, - upstream: (action as setUpstreamAction).payload + upstream: action.payload } case 'SET_COMMIT_CHANGES': @@ -119,8 +115,8 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g } case 'RESET_REMOTE_BRANCH_COMMITS': - if (state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]) { - delete state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name] + if (state.remoteBranchCommits[action.payload.branch.name]) { + delete state.remoteBranchCommits[action.payload.branch.name] } return { ...state, @@ -128,10 +124,10 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g } case 'SET_REMOTE_BRANCH_COMMITS': - if (state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name]) { - state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name].push(...(action as setRemoteBranchCommitsAction).payload.commits) + if (state.remoteBranchCommits[action.payload.branch.name]) { + state.remoteBranchCommits[action.payload.branch.name].push(...action.payload.commits) } else { - state.remoteBranchCommits[(action as setRemoteBranchCommitsAction).payload.branch.name] = (action as setRemoteBranchCommitsAction).payload.commits + state.remoteBranchCommits[action.payload.branch.name] = action.payload.commits } return { ...state, @@ -140,7 +136,7 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g case 'SET_LOCAL_BRANCH_COMMITS': - state.localBranchCommits[(action as setLocalBranchCommitsAction).payload.branch.name] = (action as setLocalBranchCommitsAction).payload.commits + state.localBranchCommits[action.payload.branch.name] = action.payload.commits return { ...state, localBranchCommits: { ...state.localBranchCommits } @@ -148,7 +144,7 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g case 'SET_BRANCH_DIFFERENCES': - state.branchDifferences[`${(action as setBranchDifferencesAction).payload.remote.name}/${(action as setBranchDifferencesAction).payload.branch.name}`] = (action as setBranchDifferencesAction).payload.branchDifference + state.branchDifferences[`${action.payload.remote.name}/${action.payload.branch.name}`] = action.payload.branchDifference return { ...state, @@ -180,10 +176,17 @@ export const gitReducer = (state: gitState = defaultGitState, action: Action): g gitHubScopes: action.payload } + case 'SET_USER_EMAILS': + return { + ...state, + userEmails: action.payload + } + + case 'SET_DEFAULT_REMOTE': return { ...state, - defaultRemote: (action as setDefaultRemoteAction).payload + defaultRemote: action.payload } case 'SET_LOG': diff --git a/libs/remix-ui/git/src/types/index.ts b/libs/remix-ui/git/src/types/index.ts index 71c9934ed1..019ce21c6d 100644 --- a/libs/remix-ui/git/src/types/index.ts +++ b/libs/remix-ui/git/src/types/index.ts @@ -2,8 +2,9 @@ import { Endpoints } from "@octokit/types" import { IRemixApi } from "@remixproject/plugin-api" import { LibraryProfile, StatusEvents } from "@remixproject/plugin-utils" import { CommitObject, ReadBlobResult, ReadCommitResult, StatusRow } from "isomorphic-git" -export type GitHubUser = Endpoints["GET /user"]["response"]['data'] +export type GitHubUser = Partial export type RateLimit = Endpoints["GET /rate_limit"]["response"]["data"] +export type userEmails = Endpoints["GET /user/emails"]["response"]["data"] export interface IGitApi { events: { @@ -180,6 +181,7 @@ export type gitState = { upstream: remote gitHubUser: GitHubUser rateLimit: RateLimit + userEmails: userEmails gitHubScopes: string[] gitHubAccessToken: string log: gitLog[] @@ -293,6 +295,7 @@ export const defaultGitState: gitState = { upstream: null, gitHubUser: {} as GitHubUser, rateLimit: {} as RateLimit, + userEmails: [] as userEmails, gitHubScopes: [], gitHubAccessToken: "", log: [] diff --git a/libs/remix-ui/workspace/src/lib/actions/workspace.ts b/libs/remix-ui/workspace/src/lib/actions/workspace.ts index e20543fb41..fb17518460 100644 --- a/libs/remix-ui/workspace/src/lib/actions/workspace.ts +++ b/libs/remix-ui/workspace/src/lib/actions/workspace.ts @@ -160,7 +160,7 @@ export const createWorkspace = async ( if (!currentBranch) { if (!name || !email) { - await plugin.call('notification', 'toast', 'To use Git features, add username and email to the Github section of the Settings panel.') + await plugin.call('notification', 'toast', 'To use Git features, add username and email to the Github section of the Git plugin.') } else { // commit the template as first commit plugin.call('notification', 'toast', 'Creating initial git commit ...') @@ -691,7 +691,7 @@ export const cloneRepository = async (url: string) => { id: 'cloneGitRepository', title: 'Clone Git Repository', message: - 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in Settings plugin', + 'An error occurred: Please check that you have the correct URL for the repo. If the repo is private, you need to add your github credentials (with the valid token permissions) in the Git plugin', modalType: 'modal', okLabel: plugin.registry.get('platform').api.isDesktop() ? 'Select or create folder':'OK', okFn: async () => {