-
Notifications
You must be signed in to change notification settings - Fork 108
data explorer: create "Copy as Code" modal #8537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+499
−7
Merged
Changes from all commits
Commits
Show all changes
66 commits
Select commit
Hold shift + click to select a range
02a2c28
make action and button
isabelizimm dc9ef57
Merge branch 'main' into export-to-code
isabelizimm 6f502e0
plumb through comms
isabelizimm dcf380b
export -> copy
isabelizimm 32eb2c0
add modal on filter bar
isabelizimm f9a2c01
ui updates
isabelizimm 2b9f962
make calls from modal
isabelizimm 5083889
clean up comms
isabelizimm 5be588b
clean up modal
isabelizimm d59fd66
linting for python
isabelizimm cc2d069
nit to modal
isabelizimm bae6ced
Merge branch 'export-as-code-comms' into copy-as-code-comms
isabelizimm 1c0c11a
add modal into new branch
isabelizimm 35a2114
update names and comments
isabelizimm 4d624bc
updates from copilot
isabelizimm ac12c66
nit
isabelizimm 0d6e7d9
cleanup
isabelizimm 2e71d12
rename title creation
isabelizimm 99e782f
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm c33df7c
updates from review
isabelizimm 45cd402
guess syntax immediately
isabelizimm d75c201
updates from review
isabelizimm 87ae32f
guess syntax immediately
isabelizimm 5d9eaa5
rearrange with new updates
isabelizimm 1adfc02
reorder guessing
isabelizimm 7a0d40b
no undefined for guessing
isabelizimm 47dc3e1
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm 776a44e
cleanup modal
isabelizimm 273b988
remove unused action id
isabelizimm 9cbe02a
python lint
isabelizimm 51893f0
Update positron/comms/data_explorer-backend-openrpc.json
isabelizimm 9517202
rename, early exits
isabelizimm 36bf5f5
use supported feature flag for syntaxes
isabelizimm da70e52
refactor
isabelizimm b6bbe5c
clean up comm names
isabelizimm 6e5bcfc
Apply suggestions from code review
isabelizimm 1525ad6
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm e85e6fe
fixes with comm updates
isabelizimm fbaf3cf
updates from review
isabelizimm 50974b7
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm ccd15c4
updates from review
isabelizimm 281ddac
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm b3aa955
updates to modal
isabelizimm 0cc6f14
tweaks to runtime
isabelizimm 744cc66
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm 0c0ffac
Merge branch 'main' into copy-as-code-comms
isabelizimm a85ef9f
lint post merge from main
isabelizimm 8806973
Merge branch 'copy-as-code-comms' into copy-as-code-modal
isabelizimm f8286a8
add feature flag for convert to code action
isabelizimm c108b91
clean up renderer
isabelizimm 4f6c40a
rename files
isabelizimm 38efe31
Update src/vs/workbench/browser/positronModalDialogs/convertToCodeMod…
isabelizimm 7f394bd
Fix ESLint import warning
dhruvisompura 28739b4
mark duckdb backends as unsupported
isabelizimm 6115af3
clean up actions
isabelizimm 4363bb7
always get code string
isabelizimm 74027f9
only show for supported backends
isabelizimm e978ca5
Merge branch 'main' into copy-as-code-modal
isabelizimm 781d7ae
Merge branch 'main' into copy-as-code-modal
isabelizimm 3d01ba4
add precondition for syntaxes
isabelizimm 2037e80
nit if no supported features
isabelizimm d8363e0
remove button if convertocode is missing
isabelizimm 02c4686
remove unecessary services
isabelizimm ecb7bc1
updates from review
isabelizimm 9b675eb
simplifying dropdown entry and onAccept
isabelizimm 98de592
rearrange context key
isabelizimm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/vs/workbench/browser/positronModalDialogs/components/dropdownEntry.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (C) 2025 Posit Software, PBC. All rights reserved. | ||
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
// React. | ||
import React from 'react'; | ||
|
||
/** | ||
* DropdownEntryProps interface. | ||
*/ | ||
interface DropdownEntryProps { | ||
title: string; | ||
subtitle?: string; | ||
group?: string; | ||
} | ||
|
||
/** | ||
* DropdownEntry component. | ||
* @param props The dropdown entry props. | ||
* @returns The rendered component | ||
*/ | ||
export const DropdownEntry = (props: DropdownEntryProps) => { | ||
// Render. | ||
return ( | ||
<div className='dropdown-entry'> | ||
<div className='dropdown-entry-title'> | ||
{props.title} | ||
</div> | ||
{props.group ? <div className='dropdown-entry-group'>{props.group}</div> : null} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be simplified as:
|
||
</div> | ||
); | ||
}; |
167 changes: 167 additions & 0 deletions
167
src/vs/workbench/browser/positronModalDialogs/convertToCodeModalDialog.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (C) 2025 Posit Software, PBC. All rights reserved. | ||
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
// React. | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
// Other dependencies. | ||
import { localize } from '../../../nls.js'; | ||
import { VerticalStack } from '../positronComponents/positronModalDialog/components/verticalStack.js'; | ||
import { OKCancelModalDialog } from '../positronComponents/positronModalDialog/positronOKCancelModalDialog.js'; | ||
import { IPositronDataExplorerInstance } from '../../services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.js'; | ||
import { PositronDataExplorerCommandId } from '../../contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.js'; | ||
import { DropDownListBox } from '../positronComponents/dropDownListBox/dropDownListBox.js'; | ||
import { DropDownListBoxItem } from '../positronComponents/dropDownListBox/dropDownListBoxItem.js'; | ||
import { DropdownEntry } from './components/dropdownEntry.js'; | ||
import { CodeSyntaxName } from '../../services/languageRuntime/common/positronDataExplorerComm.js'; | ||
import { PositronModalReactRenderer } from '../../../base/browser/positronModalReactRenderer.js'; | ||
import { usePositronReactServicesContext } from '../../../base/browser/positronReactRendererContext.js'; | ||
|
||
/** | ||
* Shows the convert to code modal dialog. | ||
* @param dataExplorerClientInstance The data explorer client instance. | ||
* @returns A promise that resolves when the dialog is closed. | ||
*/ | ||
export const showConvertToCodeModalDialog = async ( | ||
dataExplorerClientInstance: IPositronDataExplorerInstance, | ||
): Promise<void> => { | ||
isabelizimm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Create the renderer. | ||
const renderer = new PositronModalReactRenderer() | ||
|
||
// Show the copy as code dialog. | ||
renderer.render( | ||
<ConvertToCodeModalDialog | ||
dataExplorerClientInstance={dataExplorerClientInstance} | ||
renderer={renderer} | ||
/> | ||
); | ||
}; | ||
|
||
/** | ||
* ConvertToCodeDialogProps interface. | ||
*/ | ||
interface ConvertToCodeDialogProps { | ||
dataExplorerClientInstance: IPositronDataExplorerInstance | ||
renderer: PositronModalReactRenderer; | ||
} | ||
|
||
|
||
/** | ||
* ConvertToCodeModalDialog component. | ||
* @param props The component properties. | ||
* @returns The rendered component. | ||
*/ | ||
export const ConvertToCodeModalDialog = (props: ConvertToCodeDialogProps) => { | ||
isabelizimm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Service hooks. | ||
const services = usePositronReactServicesContext(); | ||
|
||
// State hooks. | ||
const instance = props.dataExplorerClientInstance.dataExplorerClientInstance; | ||
const codeSyntaxOptions = instance.cachedBackendState?.supported_features?.convert_to_code?.code_syntaxes ?? []; | ||
|
||
const [selectedSyntax, setSelectedSyntax] = useState<CodeSyntaxName | undefined>(instance.suggestedSyntax); | ||
|
||
const [codeString, setCodeString] = useState<string | undefined>(undefined); | ||
|
||
useEffect(() => { | ||
isabelizimm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const getCodeString = async () => { | ||
try { | ||
// Execute the command to get the code string based on the selected syntax. | ||
const result = await services.commandService.executeCommand(PositronDataExplorerCommandId.ConvertToCodeAction, selectedSyntax); | ||
setCodeString(result); | ||
} catch (error) { | ||
if (selectedSyntax) { | ||
setCodeString(localize( | ||
'positron.dataExplorer.getCodeStringWithSyntax', | ||
"Cannot generate code for type {0}", | ||
selectedSyntax.code_syntax_name | ||
)); | ||
} else { | ||
setCodeString(localize( | ||
'positron.dataExplorer.getCodeStringNoSyntax', | ||
"Cannot generate code" | ||
)); | ||
} | ||
} | ||
}; | ||
|
||
getCodeString(); // Call the async function | ||
}, [selectedSyntax, services.commandService]); | ||
|
||
// Construct the syntax options dropdown entries | ||
const syntaxDropdownEntries = () => { | ||
return syntaxInfoToDropDownItems(codeSyntaxOptions); | ||
}; | ||
|
||
const syntaxInfoToDropDownItems = ( | ||
syntaxes: CodeSyntaxName[] | ||
): DropDownListBoxItem<string, CodeSyntaxName>[] => { | ||
return syntaxes.map( | ||
(syntax) => | ||
new DropDownListBoxItem<string, CodeSyntaxName>({ | ||
identifier: syntax.code_syntax_name, | ||
value: syntax, | ||
}) | ||
); | ||
}; | ||
|
||
const syntaxDropdownTitle = (): string => { | ||
// if selectedSyntax is an object with code_syntax_name, return that name | ||
if (typeof selectedSyntax === 'object' && 'code_syntax_name' in selectedSyntax) { | ||
return (selectedSyntax as CodeSyntaxName).code_syntax_name; | ||
} | ||
return localize('positron.dataExplorer.selectCodeSyntax', 'Select Code Syntax'); | ||
} | ||
|
||
const onSelectionChanged = async (item: DropDownListBoxItem<string, CodeSyntaxName>) => { | ||
const typedItem = item as DropDownListBoxItem<string, CodeSyntaxName>; | ||
setSelectedSyntax(typedItem.options.value); | ||
|
||
// Execute the command to get the code string based on the selected syntax. | ||
try { | ||
const exc = await services.commandService.executeCommand(PositronDataExplorerCommandId.ConvertToCodeAction, typedItem.options.value); | ||
setCodeString(exc); | ||
} catch (error) { | ||
setCodeString(localize( | ||
'positron.dataExplorer.cannotGenerateCodeForType', | ||
"Cannot generate code for type {0}", | ||
typedItem.options.value.code_syntax_name | ||
)); | ||
} | ||
}; | ||
|
||
// Render. | ||
return ( | ||
<OKCancelModalDialog | ||
catchErrors | ||
height={300} | ||
renderer={props.renderer} | ||
title={(() => localize( | ||
'positronConvertToCodeModalDialogTitle', | ||
"Convert to Code" | ||
))()} | ||
width={400} | ||
onAccept={() => props.renderer.dispose()} | ||
onCancel={() => props.renderer.dispose()} | ||
> | ||
<VerticalStack> | ||
<DropDownListBox | ||
createItem={(item) => ( | ||
<DropdownEntry | ||
title={item.options.identifier} | ||
/> | ||
)} | ||
entries={syntaxDropdownEntries()} | ||
title={syntaxDropdownTitle()} | ||
onSelectionChanged={onSelectionChanged} | ||
/> | ||
<pre> | ||
{codeString} | ||
</pre> | ||
</VerticalStack> | ||
|
||
</OKCancelModalDialog> | ||
); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a similar component that the nee folder flow modal uses and its pretty similar to this one. I think there's opportunity here to consolidate both components. We could move this component into the same place where the dropdownlistbox component lives.
This can be a piece of polish/cleanup we do - not necessarily in this PR