Skip to content

Commit

Permalink
Create Modal class (mirror Toast) (#3294)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattseddon authored Feb 16, 2023
1 parent d8ae4a0 commit 7390615
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 38 deletions.
4 changes: 2 additions & 2 deletions extension/src/cli/dvc/actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Args, Flag } from './constants'
import { Prompt } from './output'
import { MaybeConsoleError } from '../error'
import { warnOfConsequences } from '../../vscode/modal'
import { Modal } from '../../vscode/modal'
import { CommandId, InternalCommands } from '../../commands/internal'
import { Response } from '../../vscode/response'

Expand All @@ -15,7 +15,7 @@ const offerToForce = async (
Prompt.TRY_FORCE,
'\n\nWould you like to force this action?'
)
const response = await warnOfConsequences(text, Response.FORCE)
const response = await Modal.warnOfConsequences(text, Response.FORCE)
if (response !== Response.FORCE) {
return
}
Expand Down
4 changes: 2 additions & 2 deletions extension/src/connect/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { Title } from '../vscode/title'
import { openUrl } from '../vscode/external'
import { ContextKey, setContextValue } from '../vscode/context'
import { RegisteredCommands } from '../commands/external'
import { showInformation } from '../vscode/modal'
import { Modal } from '../vscode/modal'

export class Connect extends BaseRepository<undefined> {
public readonly viewKey = ViewKey.CONNECT
Expand Down Expand Up @@ -96,7 +96,7 @@ export class Connect extends BaseRepository<undefined> {
const storedToken = await this.getStudioAccessToken()
if (isStudioAccessToken(storedToken)) {
if (this.deferred.state === 'resolved') {
void showInformation(
void Modal.showInformation(
'Studio is now connected. Use the "Share to Studio" command from an experiment\'s context menu to share experiments.'
)
}
Expand Down
6 changes: 4 additions & 2 deletions extension/src/repository/commands/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { join } from 'path'
import { Uri } from 'vscode'
import { getResourceCommand, getRootCommand, getSimpleResourceCommand } from '.'
import { warnOfConsequences } from '../../vscode/modal'
import { Modal } from '../../vscode/modal'
import { CommandId, InternalCommands } from '../../commands/internal'
import { OutputChannel } from '../../vscode/outputChannel'
import { WorkspaceRepositories } from '../workspace'

const mockedFunc = jest.fn()
const mockedGetWarningResponse = jest.mocked(warnOfConsequences)
const mockedModal = jest.mocked(Modal)
const mockedGetWarningResponse = jest.fn()
mockedModal.warnOfConsequences = mockedGetWarningResponse
const mockedDvcRoot = join('some', 'path')
const mockedRelPath = join('with', 'a', 'target')
const mockedTarget = join(mockedDvcRoot, mockedRelPath)
Expand Down
4 changes: 2 additions & 2 deletions extension/src/repository/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
InternalCommands
} from '../../commands/internal'
import { relativeWithUri } from '../../fileSystem'
import { warnOfConsequences } from '../../vscode/modal'
import { Modal } from '../../vscode/modal'
import { Response } from '../../vscode/response'
import { WorkspaceRepositories } from '../workspace'

Expand Down Expand Up @@ -135,7 +135,7 @@ export const getResetRootCommand =
return
}

const response = await warnOfConsequences(
const response = await Modal.warnOfConsequences(
'Are you sure you want to discard ALL workspace changes?\n' +
'This is IRREVERSIBLE!\n' +
'Your current working set will be FOREVER LOST if you proceed.',
Expand Down
4 changes: 2 additions & 2 deletions extension/src/repository/model/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { sendViewOpenedTelemetryEvent } from '../../telemetry'
import { EventName } from '../../telemetry/constants'
import { getInput } from '../../vscode/inputBox'
import { pickResources } from '../../vscode/resourcePicker'
import { warnOfConsequences } from '../../vscode/modal'
import { Modal } from '../../vscode/modal'
import { Response } from '../../vscode/response'
import { Title } from '../../vscode/title'
import { Disposable } from '../../class/dispose'
Expand Down Expand Up @@ -229,7 +229,7 @@ export class RepositoriesTree
async ({ resourceUri: destination }) => {
const targets = await pickResources(Title.CHOOSE_RESOURCES)
if (targets) {
const response = await warnOfConsequences(
const response = await Modal.warnOfConsequences(
'Are you sure you want to move the selected data into this dataset?',
Response.MOVE
)
Expand Down
42 changes: 25 additions & 17 deletions extension/src/vscode/modal.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { window } from 'vscode'
import { warnOfConsequences } from './modal'
import { Modal } from './modal'
import { Response } from './response'

const mockedWindow = jest.mocked(window)
Expand All @@ -14,28 +14,36 @@ beforeEach(() => {
jest.resetAllMocks()
})

describe('warnOfConsequences', () => {
it('should return the text of the response provided by the user', async () => {
const userSelection = Response.YES
const options = [userSelection, Response.NO, Response.NEVER]
describe('Modal', () => {
describe('warnOfConsequences', () => {
it('should return the text of the response provided by the user', async () => {
const userSelection = Response.YES
const options = [userSelection, Response.NO, Response.NEVER]

mockedShowWarningMessage.mockResolvedValueOnce(Response.YES)
mockedShowWarningMessage.mockResolvedValueOnce(Response.YES)

const response = await warnOfConsequences('WHAT DO I DO?', ...options)
const response = await Modal.warnOfConsequences(
'WHAT DO I DO?',
...options
)

expect(response).toStrictEqual(userSelection)
expect(mockedShowWarningMessage).toHaveBeenCalledTimes(1)
})
expect(response).toStrictEqual(userSelection)
expect(mockedShowWarningMessage).toHaveBeenCalledTimes(1)
})

it('should return undefined if the modal is cancelled', async () => {
const modalCancelled = undefined
const options = [Response.YES, Response.NO, Response.NEVER]
it('should return undefined if the modal is cancelled', async () => {
const modalCancelled = undefined
const options = [Response.YES, Response.NO, Response.NEVER]

mockedShowWarningMessage.mockResolvedValueOnce(modalCancelled)
mockedShowWarningMessage.mockResolvedValueOnce(modalCancelled)

const response = await warnOfConsequences('WHAT DO I DO?', ...options)
const response = await Modal.warnOfConsequences(
'WHAT DO I DO?',
...options
)

expect(response).toStrictEqual(modalCancelled)
expect(mockedShowWarningMessage).toHaveBeenCalledTimes(1)
expect(response).toStrictEqual(modalCancelled)
expect(mockedShowWarningMessage).toHaveBeenCalledTimes(1)
})
})
})
33 changes: 22 additions & 11 deletions extension/src/vscode/modal.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { window } from 'vscode'
import { Response } from './response'

export const warnOfConsequences = (
text: string,
...items: Response[]
): Thenable<string | undefined> =>
window.showWarningMessage(text, { modal: true }, ...items)

export const showInformation = (
text: string,
...items: Response[]
): Thenable<string | undefined> =>
window.showInformationMessage(text, { modal: true }, ...items)
enum Level {
INFORMATION = 'Information',
WARNING = 'Warning'
}

export class Modal {
public static showInformation(text: string, ...items: Response[]) {
return Modal.show(Level.INFORMATION, text, ...items)
}

public static warnOfConsequences(text: string, ...items: Response[]) {
return Modal.show(Level.WARNING, text, ...items)
}

private static show(
level: Level,
message: string,
...items: Response[]
): Thenable<Response | undefined> {
return window[`show${level}Message`](message, { modal: true }, ...items)
}
}

0 comments on commit 7390615

Please sign in to comment.