mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Adding Chart component (#24357)
* added doughnut chart component * Changing chart to doughnutChart * reverting to genreic chart component * adding more chart supoort * fix minor errors * resolve some PR comments * native chartjs, keyboard navigation and chart options * fix build errors * fix chart.js/auto error * resolve PR comments * modify chartdataset API * Refactoring (#24327) * working - displaying chart data with convert * working - introduced typed properties * working, added BarChartConfiguration to type param * removed ChartProperties type param * Adding doughnut support * Correcting number vs. point issue * including the right changes this time * commenting out no-longer-used labels prop * remove hardcoded canvasID, enabled Scatterplot config * Moved graph testing to sample extension * Reorganizing types; adding test back to assessment dialog * Adding example for bubble chart * Polar area working * cleanup * adding draw when options isn't set * Moving chart example configs to other file * some cleanup * added some docstrings * add multiple datasets to test scatter plot * update scatter plot example in sample * Adding height/width support * swapping to `as` cast * title working * Settling chart title and legend display * Adding comments * updating data working * Updating samples * Typo in comment * Reverting changes made for development * Elaborating on color in docstrings * Separating Data and Options in component payloads * Removing chartId as an exposed property * Changing chartType property to TChartType * Fleshing out types file comments * fixing scoping of chart component properties; renaming chart canvas ID prop * correct internal chart options typing * removing commented-out code * removing unused ChartClickEvent type until data selection eventing is implemented * renaming function * deleted commented-out code * Adding options setters that went missing after splitting Config to Data + Options * adding type predicates for data conversion * Adding back type setting (dropped when chart type conversion moved) * Narrowing type for 'type' * Fixing typos in docstring --------- Co-authored-by: Deepak Saini <deepaksaini@microsoft.com> Co-authored-by: Charles Gagnon <chgagnon@microsoft.com> Co-authored-by: Aasim Khan <aaskhan@microsoft.com> Co-authored-by: Deepak Saini <deepak.saini1996@gmail.com>
This commit is contained in:
@@ -10,8 +10,7 @@ This is a sample extension that will show some basic model-backed UI scenarios a
|
||||
- `yarn install` - to install dependencies
|
||||
- `yarn build` - to build the code
|
||||
- Launch VSCode and open the azuredatastudio's code folder, run the 'Launch azuredatastudio' debug option (to work around the issue. The next step won't work without doing this first)
|
||||
- Launch VSCode and open this folder, run the 'Debug in enlistment'. To debug, [install the `sqlops-debug` extension](https://github.com/Microsoft/azuredatastudio/wiki/Debugging-an-Extension-with-VS-Code) in VS Code.
|
||||
- Launch VSCode and open this folder, run the 'Debug in enlistment'
|
||||
- Launch VSCode and open this folder, run the 'Debug in enlistment' target. To debug, [install the `sqlops-debug` extension](https://github.com/Microsoft/azuredatastudio/wiki/Debugging-an-Extension-with-VS-Code) in VS Code.
|
||||
- Once ADS launches, you should be able to run the sqlservices commands, for example: `sqlservices.openDialog`.
|
||||
|
||||
## Consuming `azdata` typing changes during development
|
||||
|
||||
312
samples/sqlservices/src/chartExamples.ts
Normal file
312
samples/sqlservices/src/chartExamples.ts
Normal file
@@ -0,0 +1,312 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 const barData: azdata.BarChartData = {
|
||||
datasets: [
|
||||
{
|
||||
data: [3, 4, 5, 4],
|
||||
backgroundColor: 'rgb(0, 0, 0, 0.8)',
|
||||
borderColor: 'black',
|
||||
dataLabel: 'Black Stripes'
|
||||
},
|
||||
{
|
||||
data: [4, 4.5, 4, 3.5],
|
||||
backgroundColor: 'rgb(255, 255, 0, 0.8)',
|
||||
borderColor: 'yellow',
|
||||
dataLabel: 'Yellow Stripes'
|
||||
},
|
||||
{
|
||||
data: [5, 3.5, 3, 4],
|
||||
backgroundColor: 'rgb(255, 0, 0, 0.8)',
|
||||
borderColor: 'red',
|
||||
dataLabel: 'Red Stripes'
|
||||
}
|
||||
],
|
||||
labels: ['Een', 'Twee', 'Drie', 'Vier']
|
||||
};
|
||||
|
||||
export const barOptions: azdata.BarChartOptions = {
|
||||
chartTitle: 'Test Bar Chart - Belgian Flag',
|
||||
scales: {
|
||||
x: {
|
||||
max: 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const horizontalBarData: azdata.HorizontalBarChartData = {
|
||||
datasets: [
|
||||
{
|
||||
data: [3, 8],
|
||||
backgroundColor: '#FF8800BB',
|
||||
borderColor: 'orange',
|
||||
dataLabel: 'Orange Stripes'
|
||||
},
|
||||
{
|
||||
data: [3.5, 7],
|
||||
backgroundColor: '#FFFFFFBB',
|
||||
borderColor: 'white',
|
||||
dataLabel: 'White Stripes'
|
||||
},
|
||||
{
|
||||
data: [4, 9],
|
||||
backgroundColor: '#008800BB',
|
||||
borderColor: '#008800',
|
||||
dataLabel: 'Green Stripes'
|
||||
}
|
||||
],
|
||||
labels: ['Ek', 'Do']
|
||||
};
|
||||
|
||||
export const horizontalBarOptions: azdata.HorizontalBarChartOptions = {
|
||||
chartTitle: 'Test Horizontal Bar Chart - Indian Flag',
|
||||
scales: {
|
||||
x: {
|
||||
max: 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const lineData: azdata.LineChartData = {
|
||||
datasets: [
|
||||
{
|
||||
data: [2, 3, 4],
|
||||
backgroundColor: '#FFFF88',
|
||||
borderColor: '#FFFF00',
|
||||
dataLabel: 'By One'
|
||||
},
|
||||
{
|
||||
data: [3.5, 4, 4.5],
|
||||
backgroundColor: '#88FFFF',
|
||||
borderColor: '#00FFFF',
|
||||
dataLabel: 'By Half'
|
||||
},
|
||||
{
|
||||
data: [1, 3, 5],
|
||||
backgroundColor: '#FF88FF',
|
||||
borderColor: '#FF00FF',
|
||||
dataLabel: 'By Two'
|
||||
}
|
||||
],
|
||||
labels: ['uno', 'dos', 'tres', 'quatro']
|
||||
};
|
||||
|
||||
export const lineOptions: azdata.LineChartOptions = {
|
||||
chartTitle: 'Test Line Chart',
|
||||
scales: {
|
||||
x: {
|
||||
max: 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const pieData: azdata.PieChartData = {
|
||||
dataset: [
|
||||
{
|
||||
value: 3,
|
||||
backgroundColor: 'rgb(255, 255, 0, 0.5)',
|
||||
borderColor: 'yellow',
|
||||
dataLabel: 'Pacman'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
backgroundColor: 'rgb(50, 50, 50, 0.5)',
|
||||
borderColor: 'black',
|
||||
dataLabel: 'Not Pacman'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const pieOptions: azdata.PieChartOptions = {
|
||||
chartTitle: 'Test Pie Chart - Pacman',
|
||||
rotation: 135
|
||||
};
|
||||
|
||||
export const doughnutData: azdata.DoughnutChartData = {
|
||||
dataset: [
|
||||
{
|
||||
value: 50,
|
||||
backgroundColor: 'rgb(50, 50, 50, 0.5)',
|
||||
borderColor: 'black',
|
||||
dataLabel: 'Eaten'
|
||||
},
|
||||
{
|
||||
value: 100,
|
||||
backgroundColor: 'rgb(180, 130, 85, 0.5)',
|
||||
borderColor: 'brown',
|
||||
dataLabel: 'No Icing'
|
||||
},
|
||||
{
|
||||
value: 300,
|
||||
backgroundColor: 'rgb(255, 150, 200, 0.5)',
|
||||
borderColor: 'pink',
|
||||
dataLabel: 'Icing'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const doughnutOptions: azdata.DoughnutChartOptions = {
|
||||
chartTitle: 'Test Doughnut Chart - Strawberry Doughnut'
|
||||
};
|
||||
|
||||
export const scatterData: azdata.ScatterplotData = {
|
||||
datasets: [
|
||||
{
|
||||
data: [
|
||||
{ x: -10, y: 0 },
|
||||
{ x: 0, y: 10 },
|
||||
{ x: 10, y: 5 },
|
||||
{ x: 0.5, y: 5.5 }
|
||||
],
|
||||
backgroundColor: 'rgb(255, 99, 132)',
|
||||
borderColor: 'rgb(0, 255, 132)',
|
||||
dataLabel: 'Rojo'
|
||||
},
|
||||
{
|
||||
data:
|
||||
[
|
||||
{ x: -5, y: 2 },
|
||||
{ x: 4, y: 8 },
|
||||
{ x: -1, y: 6 }
|
||||
],
|
||||
backgroundColor: 'rgb(0, 102, 204)',
|
||||
borderColor: 'rgb(0, 102, 204)',
|
||||
dataLabel: 'Azul'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const scatterOptions: azdata.ScatterplotOptions = {
|
||||
chartTitle: 'Test Scatter Chart',
|
||||
scales: {
|
||||
x: {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const bubbleData: azdata.BubbleChartData = {
|
||||
datasets: [
|
||||
{
|
||||
data:
|
||||
[
|
||||
{ x: 0, y: -5, r: 2 },
|
||||
{ x: -2, y: -4.6, r: 4 },
|
||||
{ x: -3.5, y: -3.5, r: 6 },
|
||||
{ x: -4.6, y: -2, r: 8 },
|
||||
{ x: -5, y: 0, r: 10 },
|
||||
{ x: -4.6, y: 2, r: 12 },
|
||||
{ x: -3.5, y: 3.5, r: 14 },
|
||||
{ x: -2, y: 4.6, r: 16 },
|
||||
{ x: 0, y: 5, r: 18 }
|
||||
],
|
||||
backgroundColor: '#FFFFFF88',
|
||||
borderColor: 'white',
|
||||
dataLabel: 'Yin'
|
||||
},
|
||||
{
|
||||
data:
|
||||
[
|
||||
{ x: 0, y: 5, r: 2 },
|
||||
{ x: 2, y: 4.6, r: 4 },
|
||||
{ x: 3.5, y: 3.5, r: 6 },
|
||||
{ x: 4.6, y: 2, r: 8 },
|
||||
{ x: 5, y: 0, r: 10 },
|
||||
{ x: 4.6, y: -2, r: 12 },
|
||||
{ x: 3.5, y: -3.5, r: 14 },
|
||||
{ x: 2, y: -4.6, r: 16 },
|
||||
{ x: 0, y: -5, r: 18 }
|
||||
],
|
||||
backgroundColor: '#00000088',
|
||||
borderColor: 'black',
|
||||
dataLabel: 'Yang'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const bubbleOptions: azdata.BubbleChartOptions = {
|
||||
chartTitle: 'Test Bubble Chart - Yin and Yang',
|
||||
scales: {
|
||||
x: {
|
||||
position: 'bottom'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const polarData: azdata.PolarAreaChartData = {
|
||||
dataset:
|
||||
[
|
||||
{
|
||||
value: 1,
|
||||
dataLabel: 'Rouge',
|
||||
backgroundColor: '#FF0000',
|
||||
borderColor: '#880000'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
dataLabel: 'Orange',
|
||||
backgroundColor: '#FF8800',
|
||||
borderColor: '#884400'
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
dataLabel: 'Jaune',
|
||||
backgroundColor: '#FFFF00',
|
||||
borderColor: '#888800'
|
||||
},
|
||||
{
|
||||
value: 4,
|
||||
dataLabel: 'Vert',
|
||||
backgroundColor: '#00FF00',
|
||||
borderColor: '#008800'
|
||||
},
|
||||
{
|
||||
value: 5,
|
||||
dataLabel: 'Bleu',
|
||||
backgroundColor: '#0000FF',
|
||||
borderColor: '#000088'
|
||||
},
|
||||
{
|
||||
value: 6,
|
||||
dataLabel: 'Violet',
|
||||
backgroundColor: '#8800FF',
|
||||
borderColor: '#440088'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export const polarOptions: azdata.PolarAreaChartOptions = {
|
||||
chartTitle: 'Test Polar Chart - Rainbow'
|
||||
};
|
||||
|
||||
export const radarData: azdata.RadarChartData = {
|
||||
datasets: [
|
||||
{
|
||||
data: [2, 2, 2, 2, 4, 7, 10, 11, 12, 2],
|
||||
dataLabel: 'Left Wing',
|
||||
backgroundColor: '#FF000033',
|
||||
borderColor: '#FF0000'
|
||||
},
|
||||
{
|
||||
data: [2, 2, 12, 11, 10, 7, 4, 2, 2, 2],
|
||||
dataLabel: 'Right Wing',
|
||||
backgroundColor: '#FF880033',
|
||||
borderColor: '#FF8800'
|
||||
},
|
||||
{
|
||||
data: [8, 6, 2, 1, 1, 1, 1, 1, 2, 6],
|
||||
dataLabel: 'Head',
|
||||
backgroundColor: '#FFFF0033',
|
||||
borderColor: '#FFFF00'
|
||||
}
|
||||
],
|
||||
labels: ['She\'ll', 'Be', 'Coming', 'Around', 'The', 'Firebird', 'When', 'She', 'Comes', 'Encore']
|
||||
};
|
||||
|
||||
export const radarOptions: azdata.RadarChartOptions = {
|
||||
chartTitle: 'Test Radar Chart - Firebird'
|
||||
};
|
||||
@@ -16,6 +16,7 @@ import * as dashboard from './modelViewDashboard';
|
||||
import { ConnectionProvider } from '../featureProviders/connectionProvider';
|
||||
import { IconProvider } from '../featureProviders/iconProvider';
|
||||
import { ObjectExplorerProvider } from '../featureProviders/objectExplorerProvider';
|
||||
import * as chartExamples from '../chartExamples';
|
||||
|
||||
/**
|
||||
* The main controller class that initializes the extension
|
||||
@@ -116,6 +117,12 @@ export default class MainController implements vscode.Disposable {
|
||||
});
|
||||
dialog.content.push(treeTab);
|
||||
|
||||
const graphTab = azdata.window.createTab('Graphs');
|
||||
graphTab.registerContent(async (view) => {
|
||||
await this.getGraphTabContent(view);
|
||||
});
|
||||
dialog.content.push(graphTab);
|
||||
|
||||
// Open the dialog
|
||||
|
||||
azdata.window.openDialog(dialog);
|
||||
@@ -701,9 +708,141 @@ export default class MainController implements vscode.Disposable {
|
||||
await view.initializeModel(formWrapper);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
private async getGraphTabContent(view: azdata.ModelView): Promise<void> {
|
||||
const barChart = view.modelBuilder.chart<'bar', azdata.BarChartData, azdata.BarChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'bar',
|
||||
data: chartExamples.barData,
|
||||
options: chartExamples.barOptions,
|
||||
width: '500px',
|
||||
height: '300px'
|
||||
}).component();
|
||||
|
||||
//#region Registrations
|
||||
const horizontalBarChart = view.modelBuilder.chart<'horizontalBar', azdata.HorizontalBarChartData, azdata.HorizontalBarChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'horizontalBar',
|
||||
data: chartExamples.horizontalBarData,
|
||||
options: chartExamples.horizontalBarOptions,
|
||||
width: '500px',
|
||||
height: '300px'
|
||||
}).component();
|
||||
|
||||
const lineChart = view.modelBuilder.chart<'line', azdata.LineChartData, azdata.LineChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'line',
|
||||
data: chartExamples.lineData,
|
||||
options: chartExamples.lineOptions,
|
||||
width: '500px',
|
||||
height: '300px'
|
||||
}).component();
|
||||
|
||||
const pieChart = view.modelBuilder.chart<'pie', azdata.PieChartData, azdata.PieChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'pie',
|
||||
data: chartExamples.pieData,
|
||||
options: chartExamples.pieOptions,
|
||||
width: '300px',
|
||||
height: '300px'
|
||||
}).component();
|
||||
|
||||
const doughnutChart = view.modelBuilder.chart<'doughnut', azdata.DoughnutChartData, azdata.DoughnutChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'doughnut',
|
||||
data: chartExamples.doughnutData,
|
||||
options: chartExamples.doughnutOptions,
|
||||
width: '400px',
|
||||
height: '400px'
|
||||
}).component();
|
||||
|
||||
const scatterplot = view.modelBuilder.chart<'scatter', azdata.ScatterplotData, azdata.ScatterplotOptions>()
|
||||
.withProps({
|
||||
chartType: 'scatter',
|
||||
data: chartExamples.scatterData,
|
||||
options: chartExamples.scatterOptions,
|
||||
width: '400px',
|
||||
height: '400px'
|
||||
}).component();
|
||||
|
||||
const bubbleChart = view.modelBuilder.chart<'bubble', azdata.BubbleChartData, azdata.BubbleChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'bubble',
|
||||
data: chartExamples.bubbleData,
|
||||
options: chartExamples.bubbleOptions,
|
||||
width: '500px',
|
||||
height: '500px'
|
||||
}).component();
|
||||
|
||||
const polarChart = view.modelBuilder.chart<'polarArea', azdata.PolarAreaChartData, azdata.PolarAreaChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'polarArea',
|
||||
data: chartExamples.polarData,
|
||||
options: chartExamples.polarOptions,
|
||||
width: '500px',
|
||||
height: '500px'
|
||||
}).component();
|
||||
|
||||
const radarChart = view.modelBuilder.chart<'radar', azdata.RadarChartData, azdata.RadarChartOptions>()
|
||||
.withProps({
|
||||
chartType: 'radar',
|
||||
data: chartExamples.radarData,
|
||||
options: chartExamples.radarOptions,
|
||||
width: '500px',
|
||||
height: '500px'
|
||||
}).component();
|
||||
|
||||
const button = view.modelBuilder.button()
|
||||
.withProps({
|
||||
label: 'Click to change bar chart data'
|
||||
}).component();
|
||||
|
||||
button.onDidClick(async () => {
|
||||
// To update data, a new data object must be created and passed.
|
||||
// If the existing one is updated, it's detected as the same object, and "saves" the effort of send propertyChanged events.
|
||||
|
||||
const newDataSets: azdata.BarChartDataSet[] = [];
|
||||
|
||||
for (let i = 0; i < chartExamples.barData.datasets.length; i++) {
|
||||
const newSet: azdata.BarChartDataSet = {
|
||||
...chartExamples.barData.datasets[i], // spread to preserve existing colors and label
|
||||
data: []
|
||||
};
|
||||
|
||||
for (let j = 0; j < chartExamples.barData.datasets[i].data.length; j++) {
|
||||
newSet.data.push(Math.random() * 8);
|
||||
}
|
||||
|
||||
newDataSets.push(newSet);
|
||||
}
|
||||
|
||||
const newData: azdata.BarChartData = {
|
||||
labels: chartExamples.barData.labels,
|
||||
datasets: newDataSets
|
||||
};
|
||||
|
||||
await barChart.updateProperty('data', newData);
|
||||
});
|
||||
|
||||
const flexContainer = view.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.withProps({ CSSStyles: { 'padding': '20px 15px' } })
|
||||
.component();
|
||||
|
||||
flexContainer.addItem(button, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(barChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(horizontalBarChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(lineChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(pieChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(doughnutChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(scatterplot, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(bubbleChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(polarChart, { flex: '0 0 auto' });
|
||||
flexContainer.addItem(radarChart, { flex: '0 0 auto' });
|
||||
|
||||
const flexWrapper = view.modelBuilder.loadingComponent().withItem(flexContainer).component();
|
||||
flexWrapper.loading = false;
|
||||
|
||||
await view.initializeModel(flexWrapper);
|
||||
}
|
||||
|
||||
private registerSqlServicesModelView(): void {
|
||||
azdata.ui.registerModelViewProvider('sqlservices', async (view) => {
|
||||
|
||||
Reference in New Issue
Block a user