Use remote file dialog for database and server properties dialogs (#24390)

This commit is contained in:
Cory Rivera
2023-09-13 10:49:10 -07:00
committed by GitHub
parent 4f155423dc
commit 08ded51e75
31 changed files with 108 additions and 97 deletions

View File

@@ -209,7 +209,7 @@
"update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-azuremonitor ./syntaxes/azuremonitor.tmLanguage"
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"figures": "^2.0.0",
"find-remove": "1.2.1",
"@microsoft/ads-service-downloader": "^1.2.1",

View File

@@ -75,9 +75,9 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -107,7 +107,7 @@
"dependencies": {
"@microsoft/ads-extension-telemetry": "^3.0.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"vscode-nls": "^5.2.0"
},
"devDependencies": {

View File

@@ -497,9 +497,9 @@ crypt@0.0.2:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -77,7 +77,7 @@
}
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"htmlparser2": "^3.10.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"@microsoft/ads-extension-telemetry": "^3.0.1",

View File

@@ -572,9 +572,9 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -427,7 +427,7 @@
}
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"figures": "^2.0.0",
"find-remove": "1.2.1",
"@microsoft/ads-service-downloader": "^1.2.1",

View File

@@ -124,9 +124,9 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -1,6 +1,6 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
"version": "4.10.0.1",
"version": "4.10.0.2",
"downloadFileNames": {
"Windows_86": "win-x86-net7.0.zip",
"Windows_64": "win-x64-net7.0.zip",

View File

@@ -1572,7 +1572,7 @@
"dependencies": {
"@microsoft/ads-extension-telemetry": "^3.0.1",
"@microsoft/ads-service-downloader": "^1.2.1",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"find-remove": "1.2.1",
"vscode-languageclient": "5.2.1",
"vscode-nls": "^4.0.0"

View File

@@ -62,16 +62,20 @@ export class AttachDatabaseDialog extends ObjectManagementDialogBase<Database, D
const buttonContainer = this.addButtonsForTable(this._databasesTable, addButton, removeButton);
this._nameField = this.createInputBox(async newValue => {
let selectedRow = this._databasesTable.selectedRows[0];
let dbFile = this._databasesToAttach[selectedRow];
dbFile.databaseName = newValue;
if (this._databasesTable.selectedRows?.length > 0) {
let selectedRow = this._databasesTable.selectedRows[0];
let dbFile = this._databasesToAttach[selectedRow];
dbFile.databaseName = newValue;
}
}, {});
this._nameContainer = this.createLabelInputContainer(loc.AttachAsText, this._nameField);
this._ownerDropdown = this.createDropdown(loc.OwnerText, async newValue => {
let selectedRow = this._databasesTable.selectedRows[0];
let dbFile = this._databasesToAttach[selectedRow];
dbFile.owner = newValue;
if (this._databasesTable.selectedRows?.length > 0) {
let selectedRow = this._databasesTable.selectedRows[0];
let dbFile = this._databasesToAttach[selectedRow];
dbFile.owner = newValue;
}
}, this.viewInfo.loginNames.options, this.viewInfo.loginNames.options[this.viewInfo.loginNames.defaultValueIndex]);
this._ownerContainer = this.createLabelInputContainer(loc.OwnerText, this._ownerDropdown);

View File

@@ -738,8 +738,9 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
defaultFileGrowthInMb: defaultFileGrowthInMb,
defaultFileGrowthInPercent: defaultFileGrowthInPercent,
defaultMaxFileSizeLimitedToInMb: defaultMaxFileSizeLimitedToInMb
}
});
},
connectionUri: this.options.connectionUri
}, this.objectManagementService);
await dialog.open();
return await dialog.waitForClose();
}

View File

@@ -4,13 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as path from 'path';
import { DefaultInputWidth, DialogBase } from '../../ui/dialogBase';
import * as localizedConstants from '../localizedConstants';
import { DatabaseFile, DatabaseViewInfo, FileGrowthType } from '../interfaces';
import { isUndefinedOrNull } from '../../types';
import { deepClone } from '../../util/objects';
import { IObjectManagementService } from 'mssql';
export interface NewDatabaseFileDialogOptions {
title: string;
@@ -27,6 +27,7 @@ export interface NewDatabaseFileDialogOptions {
defaultFileGrowthInMb: number,
defaultMaxFileSizeLimitedToInMb: number
};
connectionUri: string;
}
const fileSizeInputMaxValueInMbForDataType = 16776192; // Row type supports up to 16 TB (SSMS allows =~ 15.99TB)
@@ -58,7 +59,7 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
private originalFileName: string;
private isEditingFile: boolean;
constructor(private readonly options: NewDatabaseFileDialogOptions) {
constructor(private readonly options: NewDatabaseFileDialogOptions, private readonly objectManagementService: IObjectManagementService) {
super(options.title, 'DatabaseFileDialog');
}
@@ -296,23 +297,12 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
* Creates a file browser and sets the path to the filePath
*/
private async createFileBrowser(): Promise<void> {
let fileUris = await vscode.window.showOpenDialog(
{
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: vscode.Uri.file(this.options.databaseFile.path),
openLabel: localizedConstants.SelectText
}
);
if (!fileUris || fileUris.length === 0) {
return;
let dataFolder = await this.objectManagementService.getDataFolder(this.options.connectionUri);
let filePath = await azdata.window.openServerFileBrowserDialog(this.options.connectionUri, dataFolder, [{ label: localizedConstants.allFiles, filters: ['*'] }], true);
if (filePath?.length > 0) {
this.filePathTextBox.value = filePath;
this.result.path = filePath;
}
let fileUri = fileUris[0];
this.filePathTextBox.value = fileUri.fsPath;
this.result.path = fileUri.fsPath;
}
/**
@@ -332,7 +322,7 @@ export class DatabaseFileDialog extends DialogBase<DatabaseFile> {
if (selectedOption === localizedConstants.LogFiletype) {
fileGroupDdOptions = [localizedConstants.FileGroupForLogTypeText];
fileGroupDdValue = localizedConstants.FileGroupForLogTypeText;
fileSizeInputMaxValue = fileSizeInputMaxValueInMbForLogType
fileSizeInputMaxValue = fileSizeInputMaxValueInMbForLogType;
}
// File Stream
else if (selectedOption === localizedConstants.FilestreamFileType) {

View File

@@ -661,21 +661,8 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
}
public async selectFolder(location: string): Promise<string | undefined> {
const allFilesFilter = localizedConstants.allFiles;
let filter: any = {};
filter[allFilesFilter] = '*';
let uris = await vscode.window.showOpenDialog({
filters: filter,
canSelectFiles: false,
canSelectMany: false,
canSelectFolders: true,
defaultUri: vscode.Uri.file(location),
openLabel: localizedConstants.labelSelectFolder
});
if (uris && uris.length > 0) {
return uris[0].fsPath;
}
return undefined;
let dataFolder = await this.objectManagementService.getDataFolder(this.options.connectionUri);
return await azdata.window.openServerFileBrowserDialog(this.options.connectionUri, dataFolder, [{ label: localizedConstants.allFiles, filters: ['*'] }], true);
}
private initializeAdvancedSection(): void {

View File

@@ -511,9 +511,9 @@ crypt@~0.0.1:
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -162,7 +162,7 @@
]
},
"dependencies": {
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.7",
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#1.3.8",
"@microsoft/ads-service-downloader": "^1.2.1",
"@microsoft/ads-extension-telemetry": "^3.0.1",
"uuid": "^8.3.2",

View File

@@ -62,9 +62,9 @@ chownr@^2.0.0:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.7":
version "1.3.7"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/0f07d03394eeebc2924971746470ac8224348fa4"
"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#1.3.8":
version "1.3.8"
resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/828b7a5e5c1c077a0f6eb7f6acecd191fbaae13d"
dependencies:
vscode-languageclient "5.2.1"

View File

@@ -2068,9 +2068,14 @@ declare module 'azdata' {
* @param connectionUri The URI of the connection to the target server
* @param targetPath The file path on the server machine to open by default in the dialog
* @param fileFilters The filters used to limit which files are displayed in the file browser
* @param showFoldersOnly Optional argument to specify whether the browser should only show folders
* @returns The path of the file chosen from the dialog, and undefined if the dialog is closed without selecting anything.
*/
export function openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: FileFilters[]): Thenable<string | undefined>;
export function openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: FileFilters[], showFoldersOnly?: boolean): Thenable<string | undefined>;
}
export interface FileBrowserProvider extends DataProvider {
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Thenable<boolean>;
}
export interface TableComponent {

View File

@@ -338,8 +338,8 @@ export class MainThreadDataProtocol extends Disposable implements MainThreadData
public $registerFileBrowserProvider(providerId: string, handle: number): Promise<any> {
const self = this;
this._fileBrowserService.registerProvider(providerId, <azdata.FileBrowserProvider>{
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> {
return self._proxy.$openFileBrowser(handle, ownerUri, expandPath, fileFilters, changeFilter);
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Thenable<boolean> {
return self._proxy.$openFileBrowser(handle, ownerUri, expandPath, fileFilters, changeFilter, showFoldersOnly);
},
expandFolderNode(ownerUri: string, expandPath: string): Thenable<boolean> {
return self._proxy.$expandFolderNode(handle, ownerUri, expandPath);

View File

@@ -20,13 +20,13 @@ export class MainThreadWindow extends Disposable implements MainThreadWindowShap
super();
}
public async $openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[]): Promise<string | undefined> {
public async $openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[], showFoldersOnly?: boolean): Promise<string | undefined> {
let completion = new Promise<string | undefined>((resolve, reject) => {
try {
const handleOnClosed = (path: string | undefined) => {
resolve(path);
};
this._fileBrowserDialogService.showDialog(connectionUri, targetPath, fileFilters, '', true, handleOnClosed);
this._fileBrowserDialogService.showDialog(connectionUri, targetPath, fileFilters, '', true, handleOnClosed, showFoldersOnly);
} catch (error) {
reject(error);
}

View File

@@ -632,8 +632,8 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
/**
* Open a file browser
*/
public override $openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> {
return this._resolveProvider<azdata.FileBrowserProvider>(handle).openFileBrowser(ownerUri, expandPath, fileFilters, changeFilter);
public override $openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Thenable<boolean> {
return this._resolveProvider<azdata.FileBrowserProvider>(handle).openFileBrowser(ownerUri, expandPath, fileFilters, changeFilter, showFoldersOnly);
}
/**

View File

@@ -17,7 +17,7 @@ export class ExtHostWindow implements ExtHostWindowShape {
this._proxy = _mainContext.getProxy(SqlMainContext.MainThreadWindow);
}
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[]): Promise<string | undefined> {
return this._proxy.$openServerFileBrowserDialog(connectionUri, targetPath, fileFilters);
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[], showFoldersOnly?: boolean): Promise<string | undefined> {
return this._proxy.$openServerFileBrowserDialog(connectionUri, targetPath, fileFilters, showFoldersOnly);
}
}

View File

@@ -488,8 +488,8 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp
openCustomErrorDialog(options: sqlExtHostTypes.IErrorDialogOptions): Thenable<string | undefined> {
return extHostModelViewDialog.openCustomErrorDialog(options);
},
openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[]): Thenable<string | undefined> {
return extHostWindow.$openServerFileBrowserDialog(connectionUri, targetPath, fileFilters);
openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[], showFoldersOnly?: boolean): Thenable<string | undefined> {
return extHostWindow.$openServerFileBrowserDialog(connectionUri, targetPath, fileFilters, showFoldersOnly);
}
};

View File

@@ -355,7 +355,7 @@ export abstract class ExtHostDataProtocolShape {
/**
* Open a file browser
*/
$openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> { throw ni(); }
$openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Thenable<boolean> { throw ni(); }
/**
@@ -833,7 +833,7 @@ export interface ExtHostWorkspaceShape {
}
export interface ExtHostWindowShape {
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[]): Promise<string | undefined>;
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[], showFoldersOnly?: boolean): Promise<string | undefined>;
}
export interface MainThreadWorkspaceShape {
@@ -843,7 +843,7 @@ export interface MainThreadWorkspaceShape {
}
export interface MainThreadWindowShape {
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[]): Promise<string | undefined>;
$openServerFileBrowserDialog(connectionUri: string, targetPath: string, fileFilters: azdata.window.FileFilters[], showFoldersOnly?: boolean): Promise<string | undefined>;
}
export interface MainThreadBackgroundTaskManagementShape extends IDisposable {

View File

@@ -38,6 +38,8 @@ export class FileBrowserDialog extends Modal {
private _body: HTMLElement;
private _filePathInputBox: InputBox;
private _fileFilterSelectBox: SelectBox;
private _fileFilterRow: HTMLElement;
private _originalFilterDisplay: string;
private _okButton: Button;
private _onOk = new Emitter<string>();
public onOk: Event<string> = this._onOk.event;
@@ -99,6 +101,8 @@ export class FileBrowserDialog extends Modal {
this._fileFilterSelectBox.setAriaLabel(filterLabel);
let filterBuilder = DialogHelper.appendRow(tableContainer, filterLabel, 'file-input-label', 'file-input-box');
DialogHelper.appendInputSelectBox(filterBuilder, this._fileFilterSelectBox);
this._fileFilterRow = tableContainer.childNodes[1] as HTMLElement;
this._originalFilterDisplay = this._fileFilterRow.style.display;
this._okButton = this.addFooterButton(localize('fileBrowser.ok', "OK"), () => this.ok());
this._okButton.enabled = false;
@@ -112,10 +116,17 @@ export class FileBrowserDialog extends Modal {
expandPath: string,
fileFilters: [{ label: string, filters: string[] }],
fileValidationServiceType: string,
showFoldersOnly?: boolean
): void {
this._viewModel.initialize(ownerUri, expandPath, fileFilters, fileValidationServiceType);
this._viewModel.initialize(ownerUri, expandPath, fileFilters, fileValidationServiceType, showFoldersOnly);
this._viewModel.openFileBrowser(0, false).catch(err => onUnexpectedError(err));
this._fileFilterSelectBox.setOptions(this._viewModel.formattedFileFilters, 0);
if (showFoldersOnly) {
this._fileFilterSelectBox.setOptions([]);
this._fileFilterRow.style.display = 'none';
} else {
this._fileFilterSelectBox.setOptions(this._viewModel.formattedFileFilters, 0);
this._fileFilterRow.style.display = this._originalFilterDisplay;
}
this._filePathInputBox.value = expandPath;
this._isFolderSelected = true;
this.enableOkButton();
@@ -129,7 +140,7 @@ export class FileBrowserDialog extends Modal {
/* enter key */
protected override onAccept() {
if (this._okButton.enabled === true) {
if (this._okButton.enabled) {
this.ok();
}
}
@@ -140,7 +151,7 @@ export class FileBrowserDialog extends Modal {
}
private enableOkButton() {
if (strings.isFalsyOrWhitespace(this._selectedFilePath) || this._isFolderSelected === true) {
if (strings.isFalsyOrWhitespace(this._selectedFilePath) || (this._isFolderSelected && !this._viewModel.showFoldersOnly)) {
this._okButton.enabled = false;
} else {
this._okButton.enabled = true;
@@ -215,9 +226,11 @@ export class FileBrowserDialog extends Modal {
}
private registerListeners(): void {
this._register(this._fileFilterSelectBox.onDidSelect(selectData => {
this.onFilterSelectChanged(selectData.index).catch(err => onUnexpectedError(err));
}));
if (this._fileFilterSelectBox) {
this._register(this._fileFilterSelectBox.onDidSelect(selectData => {
this.onFilterSelectChanged(selectData.index).catch(err => onUnexpectedError(err));
}));
}
this._register(this._filePathInputBox.onDidChange(e => {
this.onFilePathChange(e);
}));

View File

@@ -25,7 +25,8 @@ export class FileBrowserDialogController implements IFileBrowserDialogController
fileFilters: [{ label: string, filters: string[] }],
fileValidationServiceType: string,
isWide: boolean,
handleOnClosed: (path: string | undefined) => void
handleOnClosed: (path: string | undefined) => void,
showFoldersOnly?: boolean
): void {
if (!this._fileBrowserDialog) {
this._fileBrowserDialog = this._instantiationService.createInstance(FileBrowserDialog, localize('filebrowser.selectFile', "Select a file"));
@@ -44,6 +45,6 @@ export class FileBrowserDialogController implements IFileBrowserDialogController
this._fileBrowserDialog = undefined;
});
this._fileBrowserDialog.open(ownerUri, expandPath, fileFilters, fileValidationServiceType);
this._fileBrowserDialog.open(ownerUri, expandPath, fileFilters, fileValidationServiceType, showFoldersOnly);
}
}

View File

@@ -9,10 +9,12 @@
padding-left: 12px;
padding-right: 12px;
box-sizing: border-box;
display: flex;
flex-flow: column;
}
.file-browser-dialog .tree-view {
height: calc(100% - 90px);
flex: 1 1 auto;
}
.file-table-content {
@@ -21,8 +23,8 @@
.file-browser-dialog .option-section {
padding-top: 10px;
height: 90px;
box-sizing: border-box;
flex: 0 1 auto;
}
.file-input-label {

View File

@@ -16,5 +16,6 @@ export interface IFileBrowserDialogController {
fileFilters: { label: string, filters: string[] }[],
fileValidationServiceType: string,
isWide: boolean,
handleOnOk: (path: string | undefined) => void): void;
handleOnOk: (path: string | undefined) => void,
showFoldersOnly?: boolean): void;
}

View File

@@ -46,11 +46,11 @@ export class FileBrowserService implements IFileBrowserService {
return this._onPathValidate.event;
}
public openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Promise<boolean> {
public openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
const provider = this.getProvider(ownerUri);
if (provider) {
provider.openFileBrowser(ownerUri, expandPath, fileFilters, changeFilter).then(result => {
provider.openFileBrowser(ownerUri, expandPath, fileFilters, changeFilter, showFoldersOnly).then(result => {
resolve(result);
}, error => {
reject(error);

View File

@@ -15,6 +15,7 @@ export class FileBrowserViewModel {
private _expandPath: string;
private _fileFilters: [{ label: string, filters: string[] }];
private _fileValidationServiceType: string;
private _showFoldersOnly: boolean;
public formattedFileFilters: string[];
constructor(@IFileBrowserService private _fileBrowserService: IFileBrowserService) {
@@ -28,14 +29,20 @@ export class FileBrowserViewModel {
this._fileBrowserService.onPathValidate(args => onPathValidateCallback(args));
}
public get showFoldersOnly(): boolean {
return this._showFoldersOnly;
}
public initialize(ownerUri: string,
expandPath: string,
fileFilters: [{ label: string, filters: string[] }],
fileValidationServiceType: string,
showFoldersOnly?: boolean
) {
this._ownerUri = ownerUri;
this._expandPath = expandPath;
this._fileValidationServiceType = fileValidationServiceType;
this._showFoldersOnly = !!showFoldersOnly;
if (!fileFilters) {
this._fileFilters = [{ label: localize('allFiles', "All files"), filters: ['*'] }];
@@ -55,7 +62,7 @@ export class FileBrowserViewModel {
public async openFileBrowser(filterIndex: number, changeFilter: boolean): Promise<void> {
if (this._fileFilters[filterIndex]) {
await this._fileBrowserService.openFileBrowser(this._ownerUri, this._expandPath, this._fileFilters[filterIndex].filters, changeFilter);
await this._fileBrowserService.openFileBrowser(this._ownerUri, this._expandPath, this._fileFilters[filterIndex].filters, changeFilter, this._showFoldersOnly);
}
}

View File

@@ -24,7 +24,7 @@ export interface IFileBrowserService {
/**
* Open file browser
*/
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Promise<boolean>;
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean, showFoldersOnly?: boolean): Promise<boolean>;
/**
* Event called when file browser is opened