From 3adfe7eb1953cd05177b8fb3e96dba5ccf2355c7 Mon Sep 17 00:00:00 2001 From: Cheng Geng <47176493+ChengGeng97@users.noreply.github.com> Date: Thu, 17 Jun 2021 14:28:23 +0800 Subject: [PATCH] Playground Persistence Enhancement (fix issue #1787) (#1799) * fix: enhanced GitHub buttons in playground * style: yarn run format --- .../github/ControlBarGitHubButtons.tsx | 31 ++++++++++--------- .../gitHubOverlay/FileExplorerDialog.tsx | 3 +- .../__tests__/FileExplorerDialog.tsx | 6 ---- src/features/github/GitHubTypes.ts | 6 +++- src/features/github/GitHubUtils.tsx | 20 ++---------- src/features/playground/PlaygroundActions.ts | 7 +++-- src/pages/playground/Playground.tsx | 14 ++++++--- 7 files changed, 41 insertions(+), 46 deletions(-) diff --git a/src/commons/controlBar/github/ControlBarGitHubButtons.tsx b/src/commons/controlBar/github/ControlBarGitHubButtons.tsx index 8f11ac08bf..29cbf87a56 100644 --- a/src/commons/controlBar/github/ControlBarGitHubButtons.tsx +++ b/src/commons/controlBar/github/ControlBarGitHubButtons.tsx @@ -5,13 +5,14 @@ import { Octokit } from '@octokit/rest'; import * as React from 'react'; import { useMediaQuery } from 'react-responsive'; -import { GitHubState } from '../../../features/github/GitHubTypes'; +import { GitHubSaveInfo } from '../../../features/github/GitHubTypes'; import controlButton from '../../ControlButton'; import Constants from '../../utils/Constants'; export type ControlBarGitHubButtonsProps = { loggedInAs: Octokit; - githubSaveInfo: { repoName: string; filePath: string }; + githubSaveInfo: GitHubSaveInfo; + isDirty: boolean; onClickOpen?: () => void; onClickSave?: () => void; onClickSaveAs?: () => void; @@ -19,11 +20,6 @@ export type ControlBarGitHubButtonsProps = { onClickLogOut?: () => void; }; -const stateToIntent: { [state in GitHubState]: Intent } = { - LOGGED_OUT: Intent.NONE, - LOGGED_IN: Intent.NONE -}; - /** * GitHub buttons to be used specifically in the Playground. * Creates a dropdown upon click. @@ -32,16 +28,23 @@ const stateToIntent: { [state in GitHubState]: Intent } = { */ export const ControlBarGitHubButtons: React.FC = props => { const isMobileBreakpoint = useMediaQuery({ maxWidth: Constants.mobileBreakpoint }); - const isLoggedIn = props.loggedInAs !== undefined; + const filePath = props.githubSaveInfo.filePath || ''; + const fileName = (filePath.split('\\').pop() || '').split('/').pop() || ''; + + const isLoggedIn = props.loggedInAs !== undefined; const shouldDisableButtons = !isLoggedIn; - const shouldDisableSaveButton = - props.githubSaveInfo.repoName === '' || props.githubSaveInfo.filePath === ''; + const hasFilePath = filePath !== ''; + const hasOpenFile = isLoggedIn && hasFilePath; - const state: GitHubState = isLoggedIn ? 'LOGGED_IN' : 'LOGGED_OUT'; + const mainButtonDisplayText = hasOpenFile ? fileName : 'GitHub'; + let mainButtonIntent: Intent = Intent.NONE; + if (hasOpenFile) { + mainButtonIntent = props.isDirty ? Intent.WARNING : Intent.PRIMARY; + } - const mainButton = controlButton('GitHub', IconNames.GIT_BRANCH, null, { - intent: stateToIntent[state] + const mainButton = controlButton(mainButtonDisplayText, IconNames.GIT_BRANCH, null, { + intent: mainButtonIntent }); const openButton = controlButton( @@ -57,7 +60,7 @@ export const ControlBarGitHubButtons: React.FC = p IconNames.FLOPPY_DISK, props.onClickSave, undefined, - shouldDisableButtons || shouldDisableSaveButton + shouldDisableButtons || !hasOpenFile ); const saveAsButton = controlButton( diff --git a/src/commons/gitHubOverlay/FileExplorerDialog.tsx b/src/commons/gitHubOverlay/FileExplorerDialog.tsx index ef5539fbb6..8e2618d4a0 100644 --- a/src/commons/gitHubOverlay/FileExplorerDialog.tsx +++ b/src/commons/gitHubOverlay/FileExplorerDialog.tsx @@ -17,7 +17,6 @@ import { checkIfFileCanBeOpened, checkIfFileCanBeSavedAndGetSaveType, checkIfUserAgreesToOverwriteEditorData, - checkIfUserAgreesToPerformCreatingSave, checkIfUserAgreesToPerformOverwritingSave, openFileInEditor, performCreatingSave, @@ -134,7 +133,7 @@ const FileExplorerDialog: React.FC = props => { ); } - if (saveType === 'Create' && (await checkIfUserAgreesToPerformCreatingSave())) { + if (saveType === 'Create') { performCreatingSave( props.octokit, githubLoginID, diff --git a/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx b/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx index d0dad485fe..882f3648de 100644 --- a/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx +++ b/src/commons/gitHubOverlay/__tests__/FileExplorerDialog.tsx @@ -211,12 +211,6 @@ test('Performing creating save leads to appropriate function being called', asyn } ); - const checkIfUserAgreesToPerformCreatingSaveMock = jest.spyOn( - GitHubUtils, - 'checkIfUserAgreesToPerformCreatingSave' - ); - checkIfUserAgreesToPerformCreatingSaveMock.mockImplementation(async () => true); - const performCreatingSaveMock = jest.spyOn(GitHubUtils, 'performCreatingSave'); performCreatingSaveMock.mockImplementation( async ( diff --git a/src/features/github/GitHubTypes.ts b/src/features/github/GitHubTypes.ts index 142bc37024..36feee0724 100644 --- a/src/features/github/GitHubTypes.ts +++ b/src/features/github/GitHubTypes.ts @@ -2,4 +2,8 @@ export const GITHUB_OPEN_FILE = 'GITHUB_OPEN_FILE'; export const GITHUB_SAVE_FILE = 'GITHUB_SAVE_FILE'; export const GITHUB_SAVE_FILE_AS = 'GITHUB_SAVE_FILE_AS'; -export type GitHubState = 'LOGGED_IN' | 'LOGGED_OUT'; +export type GitHubSaveInfo = { + repoName: string; + filePath: string; + lastSaved?: Date; +}; diff --git a/src/features/github/GitHubUtils.tsx b/src/features/github/GitHubUtils.tsx index 0e05bfe465..aa0c31e7f8 100644 --- a/src/features/github/GitHubUtils.tsx +++ b/src/features/github/GitHubUtils.tsx @@ -173,20 +173,6 @@ export async function checkIfUserAgreesToPerformOverwritingSave() { }); } -export async function checkIfUserAgreesToPerformCreatingSave() { - return await showSimpleConfirmDialog({ - contents: ( -
-

Warning: You are creating a new file in the repository.

-

Please click 'Confirm' to continue, or 'Cancel' to go back.

-
- ), - negativeLabel: 'Cancel', - positiveIntent: 'primary', - positiveLabel: 'Confirm' - }); -} - export async function openFileInEditor( octokit: Octokit, repoOwner: string, @@ -207,7 +193,7 @@ export async function openFileInEditor( if (content) { const newEditorValue = Buffer.from(content, 'base64').toString(); store.dispatch(actions.updateEditorValue(newEditorValue, 'playground')); - store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath)); + store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath, new Date())); showSuccessMessage('Successfully loaded file!', 1000); } } @@ -259,7 +245,7 @@ export async function performOverwritingSave( committer: { name: githubName, email: githubEmail }, author: { name: githubName, email: githubEmail } }); - store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath)); + store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath, new Date())); showSuccessMessage('Successfully saved file!', 1000); } catch (err) { console.error(err); @@ -296,7 +282,7 @@ export async function performCreatingSave( committer: { name: githubName, email: githubEmail }, author: { name: githubName, email: githubEmail } }); - store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath)); + store.dispatch(actions.playgroundUpdateGitHubSaveInfo(repoName, filePath, new Date())); showSuccessMessage('Successfully created file!', 1000); } catch (err) { console.error(err); diff --git a/src/features/playground/PlaygroundActions.ts b/src/features/playground/PlaygroundActions.ts index 476b490097..d650dffd28 100644 --- a/src/features/playground/PlaygroundActions.ts +++ b/src/features/playground/PlaygroundActions.ts @@ -21,5 +21,8 @@ export const changeQueryString = (queryString: string) => action(CHANGE_QUERY_ST export const playgroundUpdatePersistenceFile = (file?: PersistenceFile) => action(PLAYGROUND_UPDATE_PERSISTENCE_FILE, file); -export const playgroundUpdateGitHubSaveInfo = (repoName: string, filePath: string) => - action(PLAYGROUND_UPDATE_GITHUB_SAVE_INFO, { repoName, filePath }); +export const playgroundUpdateGitHubSaveInfo = ( + repoName: string, + filePath: string, + lastSaved: Date +) => action(PLAYGROUND_UPDATE_GITHUB_SAVE_INFO, { repoName, filePath, lastSaved }); diff --git a/src/pages/playground/Playground.tsx b/src/pages/playground/Playground.tsx index 171f21fd3d..86700464d0 100644 --- a/src/pages/playground/Playground.tsx +++ b/src/pages/playground/Playground.tsx @@ -51,6 +51,7 @@ import { stringParamToInt } from '../../commons/utils/ParamParseHelper'; import { parseQuery } from '../../commons/utils/QueryHelper'; import Workspace, { WorkspaceProps } from '../../commons/workspace/Workspace'; import { initSession, log } from '../../features/eventLogging'; +import { GitHubSaveInfo } from '../../features/github/GitHubTypes'; import { PersistenceFile } from '../../features/persistence/PersistenceTypes'; import { CodeDelta, @@ -141,7 +142,7 @@ export type StateProps = { persistenceUser: string | undefined; persistenceFile: PersistenceFile | undefined; githubOctokitObject: { octokit: Octokit | undefined }; - githubSaveInfo: { repoName: string; filePath: string }; + githubSaveInfo: GitHubSaveInfo; }; const keyMap = { goGreen: 'h u l k' }; @@ -458,13 +459,17 @@ const Playground: React.FC = props => { ]); const githubOctokitObject = useSelector((store: any) => store.session.githubOctokitObject); + const githubSaveInfo = props.githubSaveInfo; + const githubPersistenceIsDirty = + githubSaveInfo && (!githubSaveInfo.lastSaved || githubSaveInfo.lastSaved < lastEdit); const githubButtons = React.useMemo(() => { const octokit = githubOctokitObject === undefined ? undefined : githubOctokitObject.octokit; return ( = props => { ); }, [ githubOctokitObject, - props.githubSaveInfo, + githubPersistenceIsDirty, + githubSaveInfo, props.handleGitHubOpenFile, props.handleGitHubSaveFileAs, props.handleGitHubSaveFile,