mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-04 09:35:38 -05:00
Azure Arc extension (#10400)
Adds an extension for Azure Arc with some initial Postgres pages
This commit is contained in:
28
extensions/arc/src/ui/components/dashboard.ts
Normal file
28
extensions/arc/src/ui/components/dashboard.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
export abstract class Dashboard {
|
||||
|
||||
private dashboard!: azdata.window.ModelViewDashboard;
|
||||
|
||||
constructor(protected title: string) { }
|
||||
|
||||
public async showDashboard(): Promise<void> {
|
||||
this.dashboard = this.createDashboard();
|
||||
await this.dashboard.open();
|
||||
}
|
||||
|
||||
protected createDashboard(): azdata.window.ModelViewDashboard {
|
||||
const dashboard = azdata.window.createModelViewDashboard(this.title);
|
||||
dashboard.registerTabs(async modelView => {
|
||||
return await this.registerTabs(modelView);
|
||||
});
|
||||
return dashboard;
|
||||
}
|
||||
|
||||
protected abstract async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]>;
|
||||
}
|
||||
32
extensions/arc/src/ui/components/dashboardPage.ts
Normal file
32
extensions/arc/src/ui/components/dashboardPage.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import { InitializingComponent } from './initializingComponent';
|
||||
|
||||
export abstract class DashboardPage extends InitializingComponent {
|
||||
|
||||
constructor(protected modelView: azdata.ModelView) {
|
||||
super();
|
||||
}
|
||||
|
||||
public get tab(): azdata.DashboardTab {
|
||||
return {
|
||||
title: this.title,
|
||||
id: this.id,
|
||||
icon: this.icon,
|
||||
content: this.container,
|
||||
toolbar: this.toolbarContainer
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract get title(): string;
|
||||
protected abstract get id(): string;
|
||||
protected abstract get icon(): { dark: string; light: string; };
|
||||
protected abstract get container(): azdata.Component;
|
||||
protected abstract get toolbarContainer(): azdata.ToolbarContainer;
|
||||
|
||||
}
|
||||
|
||||
40
extensions/arc/src/ui/components/initializingComponent.ts
Normal file
40
extensions/arc/src/ui/components/initializingComponent.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Deferred } from '../../common/promise';
|
||||
|
||||
export abstract class InitializingComponent {
|
||||
|
||||
private _initialized: boolean = false;
|
||||
|
||||
private onInitializedPromise: Deferred<void> = new Deferred();
|
||||
|
||||
constructor() { }
|
||||
|
||||
protected get initialized(): boolean {
|
||||
return this._initialized;
|
||||
}
|
||||
|
||||
protected set initialized(value: boolean) {
|
||||
if (!this._initialized && value) {
|
||||
this._initialized = true;
|
||||
this.onInitializedPromise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the specified action when the component is initialized. If already initialized just runs
|
||||
* the action immediately.
|
||||
* @param action The action to be ran when the page is initialized
|
||||
*/
|
||||
protected eventuallyRunOnInitialized(action: () => void): void {
|
||||
if (!this._initialized) {
|
||||
this.onInitializedPromise.promise.then(() => action()).catch(error => console.error(`Unexpected error running onInitialized action: ${error}`));
|
||||
} else {
|
||||
action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
extensions/arc/src/ui/components/keyValueContainer.ts
Normal file
96
extensions/arc/src/ui/components/keyValueContainer.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as azdata from 'azdata';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import { IconPathHelper, cssStyles } from '../../constants';
|
||||
|
||||
/** A container with a single vertical column of KeyValue pairs */
|
||||
export class KeyValueContainer {
|
||||
public container: azdata.DivContainer;
|
||||
|
||||
constructor(private modelBuilder: azdata.ModelBuilder, pairs: KeyValue[]) {
|
||||
this.container = modelBuilder.divContainer().component();
|
||||
this.refresh(pairs);
|
||||
}
|
||||
|
||||
public refresh(pairs: KeyValue[]) {
|
||||
this.container.clearItems();
|
||||
this.container.addItems(
|
||||
pairs.map(p => p.getComponent(this.modelBuilder)),
|
||||
{ CSSStyles: { 'margin-bottom': '15px', 'min-height': '30px' } }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** A key value pair in the KeyValueContainer */
|
||||
export abstract class KeyValue {
|
||||
constructor(protected key: string, protected value: string) { }
|
||||
|
||||
/** Returns a component representing the entire KeyValue pair */
|
||||
public getComponent(modelBuilder: azdata.ModelBuilder) {
|
||||
const container = modelBuilder.flexContainer().withLayout({ flexWrap: 'wrap', alignItems: 'center' }).component();
|
||||
const key = modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: this.key,
|
||||
CSSStyles: { ...cssStyles.text, 'font-weight': 'bold', 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component();
|
||||
|
||||
container.addItem(key, { flex: `0 0 200px` });
|
||||
container.addItem(this.getValueComponent(modelBuilder), { flex: '1 1 250px' });
|
||||
return container;
|
||||
}
|
||||
|
||||
/** Returns a component representing the value of the KeyValue pair */
|
||||
protected abstract getValueComponent(modelBuilder: azdata.ModelBuilder): azdata.Component;
|
||||
}
|
||||
|
||||
/** Implementation of KeyValue where the value is text */
|
||||
export class TextKeyValue extends KeyValue {
|
||||
getValueComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
return modelBuilder.text().withProperties<azdata.TextComponentProperties>({
|
||||
value: this.value,
|
||||
CSSStyles: { ...cssStyles.text, 'margin-block-start': '0px', 'margin-block-end': '0px' }
|
||||
}).component();
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of KeyValue where the value is a readonly copyable input field */
|
||||
export class InputKeyValue extends KeyValue {
|
||||
getValueComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
const container = modelBuilder.flexContainer().withLayout({ alignItems: 'center' }).component();
|
||||
container.addItem(modelBuilder.inputBox().withProperties<azdata.InputBoxProperties>({
|
||||
value: this.value // TODO: Add a readOnly property to input boxes
|
||||
}).component());
|
||||
|
||||
const copy = modelBuilder.button().withProperties<azdata.ButtonProperties>({
|
||||
iconPath: IconPathHelper.copy, width: '17px', height: '17px'
|
||||
}).component();
|
||||
|
||||
copy.onDidClick(async () => {
|
||||
vscode.env.clipboard.writeText(this.value);
|
||||
vscode.window.showInformationMessage(loc.copiedToClipboard(this.key));
|
||||
});
|
||||
|
||||
container.addItem(copy, { CSSStyles: { 'margin-left': '10px' } });
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of KeyValue where the value is a clickable link */
|
||||
export class LinkKeyValue extends KeyValue {
|
||||
constructor(key: string, value: string, private onClick: (e: any) => any) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
getValueComponent(modelBuilder: azdata.ModelBuilder): azdata.Component {
|
||||
const link = modelBuilder.hyperlink().withProperties<azdata.HyperlinkComponentProperties>({
|
||||
label: this.value, url: ''
|
||||
}).component();
|
||||
|
||||
link.onDidClick(this.onClick);
|
||||
return link;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user