diff --git a/package.json b/package.json index 73f888a..d16f258 100644 --- a/package.json +++ b/package.json @@ -147,6 +147,7 @@ "@octokit/rest": "^18.5.2", "@radix-ui/react-dropdown-menu": "^0.0.17", "@types/isomorphic-fetch": "^0.0.35", + "@vscode/webview-ui-toolkit": "^0.9.0", "classcat": "^5.0.3", "cronstrue": "^1.110.0", "downshift": "^6.1.2", diff --git a/src/extension.ts b/src/extension.ts index 08935d8..d845931 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -9,22 +9,24 @@ export async function activate(context: vscode.ExtensionContext) { const editor = FlatConfigEditor.register(context) context.subscriptions.push(editor) - const showEditor = ({ isPreview = false, onSide = false }) => () => { - const workspaceRootUri = vscode.workspace.workspaceFolders?.[0].uri - if (!workspaceRootUri) return - const flatFileUri = vscode.Uri.joinPath( - workspaceRootUri, - '.github/workflows', - 'flat.yml' - ) + const showEditor = + ({ isPreview = false, onSide = false }) => + () => { + const workspaceRootUri = vscode.workspace.workspaceFolders?.[0].uri + if (!workspaceRootUri) return + const flatFileUri = vscode.Uri.joinPath( + workspaceRootUri, + '.github/workflows', + 'flat.yml' + ) - vscode.commands.executeCommand( - 'vscode.openWith', - flatFileUri, - isPreview ? 'flat.config' : 'default', - onSide ? { viewColumn: vscode.ViewColumn.Beside, preview: false } : {} - ) - } + vscode.commands.executeCommand( + 'vscode.openWith', + flatFileUri, + isPreview ? 'flat.config' : 'default', + onSide ? { viewColumn: vscode.ViewColumn.Beside, preview: false } : {} + ) + } context.subscriptions.push( vscode.commands.registerCommand( @@ -65,9 +67,6 @@ export async function activate(context: vscode.ExtensionContext) { const flatYmlPath = path.join(workflowsDir, 'flat.yml') if (fs.existsSync(flatYmlPath)) { - vscode.window.showInformationMessage( - 'flat.yml already exists! Opening it for you...' - ) showEditor({ isPreview: true })() return } diff --git a/src/flatConfigEditor.ts b/src/flatConfigEditor.ts index 036294c..a85d5bd 100644 --- a/src/flatConfigEditor.ts +++ b/src/flatConfigEditor.ts @@ -74,9 +74,20 @@ export class FlatConfigEditor implements vscode.CustomTextEditorProvider { enableScripts: true, } - webviewPanel.webview.html = await this.getHtmlForWebview( - webviewPanel.webview - ) + try { + webviewPanel.webview.html = await this.getHtmlForWebview( + webviewPanel.webview + ) + } catch (e) { + await vscode.window.showErrorMessage( + "Please make sure you're in a repository with a valid upstream GitHub remote" + ) + await vscode.commands.executeCommand( + 'workbench.action.revertAndCloseActiveEditor' + ) + // For whatever reason, this doesn't close the webview. + await webviewPanel.dispose() + } // Receive message from the webview. webviewPanel.webview.onDidReceiveMessage(async e => { @@ -101,6 +112,11 @@ export class FlatConfigEditor implements vscode.CustomTextEditorProvider { case 'getUrlContents': this.loadUrlContents(webviewPanel, e.data) break + case 'refreshGitDetails': + webviewPanel.webview.html = await this.getHtmlForWebview( + webviewPanel.webview + ) + break case 'previewFile': const workspaceRootUri = vscode.workspace.workspaceFolders?.[0].uri if (!workspaceRootUri) { @@ -168,7 +184,27 @@ export class FlatConfigEditor implements vscode.CustomTextEditorProvider { workspaceRootUri.path.lastIndexOf('/') + 1 ) - const { owner, name } = await this.getRepoDetails() + let name, + owner = '' + + try { + const details = await vscode.window.withProgress( + { + location: vscode.ProgressLocation.Notification, + }, + async progress => { + progress.report({ + message: `Checking for GitHub repository in directory: ${dirName}`, + }) + + return await this.getRepoDetails() + } + ) + owner = details.owner || '' + name = details.name + } catch (e) { + console.error('Error getting GitHub repository details', e) + } const gitRepo = owner && name ? `${owner}/${name}` : '' @@ -399,14 +435,14 @@ export class FlatConfigEditor implements vscode.CustomTextEditorProvider { try { const gitClient = new VSCodeGit() await gitClient.activateExtension() - await gitClient.waitForRepo(5) + await gitClient.waitForRepo(3) // Next, let's grab the repo name. const { name, owner } = gitClient.repoDetails resolve({ name, owner }) } catch (e) { - resolve({}) + reject('Couldnt activate git') } }) } diff --git a/src/git.ts b/src/git.ts index 9553fdd..c59c88c 100644 --- a/src/git.ts +++ b/src/git.ts @@ -31,10 +31,9 @@ export class VSCodeGit { waitForRepo(times: number): Promise<{ name: string; owner: string }> { let count = 0 - const timeToStop = count === times return new Promise((resolve, reject) => { - const checkRepoExists = setInterval(() => { + let interval = setInterval(() => { try { const remotes = this.repository._repository.remotes if (remotes.length > 0) { @@ -42,15 +41,14 @@ export class VSCodeGit { const parsed = GitUrlParse(remote.pushUrl) resolve({ name: parsed.name, owner: parsed.owner }) } else { - if (timeToStop) { + if (count === times) { + clearInterval(interval) reject(new Error("Couldn't get repo details")) } count++ } } catch (e) { reject(new Error("Couldn't get repo details")) - } finally { - clearInterval(checkRepoExists) } }, 1000) }) diff --git a/src/webviews/src/App.tsx b/src/webviews/src/App.tsx index 9922919..7969e72 100644 --- a/src/webviews/src/App.tsx +++ b/src/webviews/src/App.tsx @@ -7,12 +7,17 @@ import Triggers from './Triggers' import { flatStateValidationSchema } from './validation' import { VSCodeAPI } from './VSCodeAPI' import { FlatStep, PullSqlConfig } from '../../types' +import { ErrorState } from './error-state' interface AppProps {} function App({}: AppProps) { const { state, setErrors, isStubData, gitRepo } = useFlatConfigStore() + if (!gitRepo) { + return + } + const showErrorState = state.jobs.scheduled.steps .filter(step => step.uses.includes('githubocto/flat')) .some(step => { diff --git a/src/webviews/src/error-state.tsx b/src/webviews/src/error-state.tsx new file mode 100644 index 0000000..f092a1a --- /dev/null +++ b/src/webviews/src/error-state.tsx @@ -0,0 +1,29 @@ +import React, { useState } from 'react' +import { VSCodeButton } from '@vscode/webview-ui-toolkit/react' + +import { VSCodeAPI } from './VSCodeAPI' + +export function ErrorState() { + const [isRefreshing, setIsRefreshing] = useState(false) + + const handleRetry = () => { + setIsRefreshing(true) + VSCodeAPI.postMessage({ + type: 'refreshGitDetails', + }) + } + + return ( +
+

+ Please ensure you're working out of a Git repository with a valid + upstream remote set. +

+
+ + {isRefreshing ? 'Refreshing...' : 'Refresh'} + +
+
+ ) +} diff --git a/yarn.lock b/yarn.lock index 8d99684..0f42254 100644 --- a/yarn.lock +++ b/yarn.lock @@ -938,6 +938,36 @@ dependencies: purgecss "^3.1.3" +"@microsoft/fast-element@^1.6.2", "@microsoft/fast-element@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@microsoft/fast-element/-/fast-element-1.7.0.tgz#7e4b164c77c07d93b28f057231b37e7e2e8fed04" + integrity sha512-2qpAWuiOSdQfH/XdO8ZtVhlvQVCjHlojWUPoGbvHJDizBccZib+4uGReG87RIBp2Fi0s7ngYPRUioS1Lr+Xe0A== + +"@microsoft/fast-foundation@^2.30.0", "@microsoft/fast-foundation@^2.32.2": + version "2.32.2" + resolved "https://registry.yarnpkg.com/@microsoft/fast-foundation/-/fast-foundation-2.32.2.tgz#c309c734965c5b2e3e264b5d05843aeb6c633229" + integrity sha512-xbagdbnNyKGg3Uvx+llTgN6C47FYYN1Wo5bRL8r3QcNalBkgsA/4T5fZFOoEypxUPzRDlEH/A81G1c8CJwHdLw== + dependencies: + "@microsoft/fast-element" "^1.7.0" + "@microsoft/fast-web-utilities" "^5.1.0" + tabbable "^5.2.0" + tslib "^1.13.0" + +"@microsoft/fast-react-wrapper@^0.1.18": + version "0.1.25" + resolved "https://registry.yarnpkg.com/@microsoft/fast-react-wrapper/-/fast-react-wrapper-0.1.25.tgz#905d07d6e2056668ada0cfbcf0484c68f028fdb0" + integrity sha512-0qWU/pUY31/YKLgHzgn0+1Ye5klvTrp4/9X6PGzQk5GAU2jjN9dv1Atzsf5bz+BdkE3oWfBhiV6UOJvA/YbnmA== + dependencies: + "@microsoft/fast-element" "^1.7.0" + "@microsoft/fast-foundation" "^2.32.2" + +"@microsoft/fast-web-utilities@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@microsoft/fast-web-utilities/-/fast-web-utilities-5.1.0.tgz#e060fea2b47c2dcfb4a9ba90a55559f0844d1cdb" + integrity sha512-S2PCxI4XqtIxLM1N7i/NuIAgx+mJM01+mDzyB3vZlYibAkOT0bzp5YZCp+coXowokSin/nK5T2kqShMXEzI6Jg== + dependencies: + exenv-es6 "^1.0.0" + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -1585,6 +1615,15 @@ "@typescript-eslint/types" "4.23.0" eslint-visitor-keys "^2.0.0" +"@vscode/webview-ui-toolkit@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@vscode/webview-ui-toolkit/-/webview-ui-toolkit-0.9.0.tgz#a3472f62bc17d4076d9540070aeb3db83080b4f6" + integrity sha512-F67LSz0yURKqPomSZA4xTu9d8VC+MtjlpCk2KygX8m2R3tvTSOjpntQ/6U1gjPVG0Pmw1m3YB2Yhhyo8E/c0zw== + dependencies: + "@microsoft/fast-element" "^1.6.2" + "@microsoft/fast-foundation" "^2.30.0" + "@microsoft/fast-react-wrapper" "^0.1.18" + "@webassemblyjs/ast@1.11.0": version "1.11.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.0.tgz#a5aa679efdc9e51707a4207139da57920555961f" @@ -2889,6 +2928,11 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" +exenv-es6@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/exenv-es6/-/exenv-es6-1.0.0.tgz#bd459136369af17cf33f959b5af58803d4068c80" + integrity sha512-fcG/TX8Ruv9Ma6PBaiNsUrHRJzVzuFMP6LtPn/9iqR+nr9mcLeEOGzXQGLC5CVQSXGE98HtzW2mTZkrCA3XrDg== + extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -5579,6 +5623,11 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +tabbable@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-5.2.1.tgz#e3fda7367ddbb172dcda9f871c0fdb36d1c4cd9c" + integrity sha512-40pEZ2mhjaZzK0BnI+QGNjJO8UYx9pP5v7BGe17SORTO0OEuuaAwQTkAp8whcZvqon44wKFOikD+Al11K3JICQ== + table@^6.0.4: version "6.7.0" resolved "https://registry.yarnpkg.com/table/-/table-6.7.0.tgz#26274751f0ee099c547f6cb91d3eff0d61d155b2" @@ -5735,7 +5784,7 @@ ts-loader@^8.1.0: micromatch "^4.0.0" semver "^7.3.4" -tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.0.0, tslib@^1.10.0, tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==