mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Add "Schedule Picker" dialog (#1759)
* Merge master * Add pick schedule dialog 1 * Add Pick Schedule button to create job dialog * Cleanup Pick Schedule dialog * Hook-up onClose event for Pick Schedule * Code review feedback
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
|
||||
import * as sqlops from 'sqlops';
|
||||
import { AgentUtils } from '../agentUtils';
|
||||
import { runInThisContext } from 'vm';
|
||||
|
||||
export class CreateJobData {
|
||||
|
||||
@@ -66,21 +65,16 @@ export class CreateJobData {
|
||||
|
||||
public async initialize() {
|
||||
this._agentService = await AgentUtils.getAgentService();
|
||||
let jobDefaults = await this._agentService.getJobDefaults(this.ownerUri);
|
||||
if (jobDefaults && jobDefaults.success) {
|
||||
this._jobCategories = jobDefaults.categories.map((cat) => {
|
||||
return cat.name;
|
||||
});
|
||||
|
||||
// TODO: fetch real data using agent service
|
||||
//
|
||||
this._defaultOwner = jobDefaults.owner;
|
||||
|
||||
this._jobCategories = [
|
||||
'[Uncategorized (Local)]',
|
||||
'Jobs from MSX'
|
||||
];
|
||||
|
||||
// await this._agentService.getOperators(this.ownerUri).then(result => {
|
||||
// this._operators = result.operators.map(o => o.name);
|
||||
// });
|
||||
|
||||
this._operators = ['', 'alanren'];
|
||||
this._defaultOwner = 'REDMOND\\alanren';
|
||||
this._operators = ['', this._defaultOwner];
|
||||
}
|
||||
|
||||
this._jobCompletionActionConditions = [{
|
||||
displayName: this.JobCompletionActionCondition_OnSuccess,
|
||||
@@ -92,6 +86,8 @@ export class CreateJobData {
|
||||
displayName: this.JobCompletionActionCondition_Always,
|
||||
name: sqlops.JobCompletionActionCondition.Always.toString()
|
||||
}];
|
||||
|
||||
this.jobSchedules = [];
|
||||
}
|
||||
|
||||
public async save() {
|
||||
@@ -140,8 +136,15 @@ export class CreateJobData {
|
||||
}
|
||||
|
||||
return {
|
||||
valid: validationErrors.length > 0,
|
||||
valid: validationErrors.length === 0,
|
||||
errorMessages: validationErrors
|
||||
};
|
||||
}
|
||||
|
||||
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
|
||||
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
|
||||
if (!existingSchedule) {
|
||||
this.jobSchedules.push(schedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
extensions/agent/client/src/data/pickScheduleData.ts
Normal file
29
extensions/agent/client/src/data/pickScheduleData.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as sqlops from 'sqlops';
|
||||
import { AgentUtils } from '../agentUtils';
|
||||
|
||||
export class PickScheduleData {
|
||||
public ownerUri: string;
|
||||
public schedules: sqlops.AgentJobScheduleInfo[];
|
||||
public selectedSchedule: sqlops.AgentJobScheduleInfo;
|
||||
|
||||
constructor(ownerUri:string) {
|
||||
this.ownerUri = ownerUri;
|
||||
}
|
||||
|
||||
public async initialize() {
|
||||
let agentService = await AgentUtils.getAgentService();
|
||||
let result = await agentService.getJobSchedules(this.ownerUri);
|
||||
if (result && result.success) {
|
||||
this.schedules = result.schedules;
|
||||
}
|
||||
}
|
||||
|
||||
public async save() {
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
import * as sqlops from 'sqlops';
|
||||
import { CreateJobData } from '../data/createJobData';
|
||||
import { CreateStepDialog } from './createStepDialog';
|
||||
import { PickScheduleDialog } from './pickScheduleDialog';
|
||||
|
||||
export class CreateJobDialog {
|
||||
|
||||
@@ -13,7 +14,7 @@ export class CreateJobDialog {
|
||||
// Top level
|
||||
//
|
||||
private readonly DialogTitle: string = 'New Job';
|
||||
private readonly OkButtonText: string = 'Ok';
|
||||
private readonly OkButtonText: string = 'OK';
|
||||
private readonly CancelButtonText: string = 'Cancel';
|
||||
private readonly GeneralTabText: string = 'General';
|
||||
private readonly StepsTabText: string = 'Steps';
|
||||
@@ -49,6 +50,9 @@ export class CreateJobDialog {
|
||||
private readonly EventLogCheckBoxString: string = 'Write to the Windows Application event log';
|
||||
private readonly DeleteJobCheckBoxString: string = 'Automatically delete job';
|
||||
|
||||
// Schedules tab strings
|
||||
private readonly PickScheduleButtonString: string = 'Pick Schedule';
|
||||
|
||||
// UI Components
|
||||
//
|
||||
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||
@@ -74,7 +78,6 @@ export class CreateJobDialog {
|
||||
private deleteStepButton: sqlops.ButtonComponent;
|
||||
|
||||
// Notifications tab controls
|
||||
//
|
||||
private notificationsTabTopLabel: sqlops.TextComponent;
|
||||
private emailCheckBox: sqlops.CheckBoxComponent;
|
||||
private emailOperatorDropdown: sqlops.DropDownComponent;
|
||||
@@ -87,6 +90,10 @@ export class CreateJobDialog {
|
||||
private deleteJobCheckBox: sqlops.CheckBoxComponent;
|
||||
private deleteJobConditionDropdown: sqlops.DropDownComponent;
|
||||
|
||||
// Schedule tab controls
|
||||
private schedulesTable: sqlops.TableComponent;
|
||||
private pickScheduleButton: sqlops.ButtonComponent;
|
||||
|
||||
private model: CreateJobData;
|
||||
|
||||
constructor(ownerUri: string) {
|
||||
@@ -221,6 +228,56 @@ export class CreateJobDialog {
|
||||
}
|
||||
|
||||
private initializeSchedulesTab() {
|
||||
this.schedulesTab.registerContent(async view => {
|
||||
this.schedulesTable = view.modelBuilder.table()
|
||||
.withProperties({
|
||||
columns: [
|
||||
'Schedule Name'
|
||||
],
|
||||
data: [],
|
||||
height: 600,
|
||||
width: 400
|
||||
}).component();
|
||||
|
||||
this.pickScheduleButton = view.modelBuilder.button().withProperties({
|
||||
label: this.PickScheduleButtonString,
|
||||
width: 80
|
||||
}).component();
|
||||
|
||||
this.pickScheduleButton.onDidClick((e)=>{
|
||||
let pickScheduleDialog = new PickScheduleDialog(this.model.ownerUri);
|
||||
pickScheduleDialog.onSuccess((dialogModel) => {
|
||||
let selectedSchedule = dialogModel.selectedSchedule;
|
||||
if (selectedSchedule) {
|
||||
this.model.addJobSchedule(selectedSchedule);
|
||||
this.populateScheduleTable();
|
||||
}
|
||||
});
|
||||
pickScheduleDialog.showDialog();
|
||||
});
|
||||
|
||||
let formModel = view.modelBuilder.formContainer()
|
||||
.withFormItems([{
|
||||
component: this.schedulesTable,
|
||||
title: this.JobStepsTopLabelString,
|
||||
actions: [this.pickScheduleButton]
|
||||
}]).withLayout({ width: '100%' }).component();
|
||||
|
||||
await view.initializeModel(formModel);
|
||||
|
||||
this.populateScheduleTable();
|
||||
});
|
||||
}
|
||||
|
||||
private populateScheduleTable() {
|
||||
if (this.model.jobSchedules) {
|
||||
let data: any[][] = [];
|
||||
for (let i = 0; i < this.model.jobSchedules.length; ++i) {
|
||||
let schedule = this.model.jobSchedules[i];
|
||||
data[i] = [ schedule.name ];
|
||||
}
|
||||
this.schedulesTable.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
private initializeNotificationsTab() {
|
||||
|
||||
94
extensions/agent/client/src/dialogs/pickScheduleDialog.ts
Normal file
94
extensions/agent/client/src/dialogs/pickScheduleDialog.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import * as sqlops from 'sqlops';
|
||||
import * as vscode from 'vscode';
|
||||
import { PickScheduleData } from '../data/pickScheduleData';
|
||||
|
||||
export class PickScheduleDialog {
|
||||
|
||||
// TODO: localize
|
||||
// Top level
|
||||
private readonly DialogTitle: string = 'Job Schedules';
|
||||
private readonly OkButtonText: string = 'OK';
|
||||
private readonly CancelButtonText: string = 'Cancel';
|
||||
private readonly SchedulesTabText: string = 'Schedules';
|
||||
|
||||
// UI Components
|
||||
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||
private scheduleTab: sqlops.window.modelviewdialog.DialogTab;
|
||||
private schedulesTable: sqlops.TableComponent;
|
||||
|
||||
private model: PickScheduleData;
|
||||
|
||||
private _onSuccess: vscode.EventEmitter<PickScheduleData> = new vscode.EventEmitter<PickScheduleData>();
|
||||
public readonly onSuccess: vscode.Event<PickScheduleData> = this._onSuccess.event;
|
||||
|
||||
constructor(ownerUri: string) {
|
||||
this.model = new PickScheduleData(ownerUri);
|
||||
}
|
||||
|
||||
public async showDialog() {
|
||||
await this.model.initialize();
|
||||
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
|
||||
this.scheduleTab = sqlops.window.modelviewdialog.createTab(this.SchedulesTabText);
|
||||
this.initializeContent();
|
||||
this.dialog.okButton.onClick(async () => await this.execute());
|
||||
this.dialog.cancelButton.onClick(async () => await this.cancel());
|
||||
this.dialog.okButton.label = this.OkButtonText;
|
||||
this.dialog.cancelButton.label = this.CancelButtonText;
|
||||
|
||||
sqlops.window.modelviewdialog.openDialog(this.dialog);
|
||||
}
|
||||
|
||||
private initializeContent() {
|
||||
this.dialog.registerContent(async view => {
|
||||
this.schedulesTable = view.modelBuilder.table()
|
||||
.withProperties({
|
||||
columns: [
|
||||
'Schedule Name'
|
||||
],
|
||||
data: [],
|
||||
height: 600,
|
||||
width: 400
|
||||
}).component();
|
||||
|
||||
let formModel = view.modelBuilder.formContainer()
|
||||
.withFormItems([{
|
||||
component: this.schedulesTable,
|
||||
title: 'Schedules'
|
||||
}]).withLayout({ width: '100%' }).component();
|
||||
|
||||
await view.initializeModel(formModel);
|
||||
|
||||
if (this.model.schedules) {
|
||||
let data: any[][] = [];
|
||||
for (let i = 0; i < this.model.schedules.length; ++i) {
|
||||
let schedule = this.model.schedules[i];
|
||||
data[i] = [ schedule.name ];
|
||||
}
|
||||
this.schedulesTable.data = data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async execute() {
|
||||
this.updateModel();
|
||||
await this.model.save();
|
||||
this._onSuccess.fire(this.model);
|
||||
}
|
||||
|
||||
private async cancel() {
|
||||
}
|
||||
|
||||
private updateModel() {
|
||||
let selectedRows = this.schedulesTable.selectedRows;
|
||||
if (selectedRows && selectedRows.length > 0) {
|
||||
let selectedRow = selectedRows[0];
|
||||
this.model.selectedSchedule = this.model.schedules[selectedRow];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import * as vscode from 'vscode';
|
||||
import { ApiWrapper } from './apiWrapper';
|
||||
import { CreateJobDialog } from './dialogs/createJobDialog';
|
||||
import { CreateStepDialog } from './dialogs/createStepDialog';
|
||||
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
|
||||
|
||||
/**
|
||||
* The main controller class that initializes the extension
|
||||
@@ -19,8 +20,6 @@ export class MainController {
|
||||
public constructor(context: vscode.ExtensionContext, apiWrapper?: ApiWrapper) {
|
||||
this._apiWrapper = apiWrapper || new ApiWrapper();
|
||||
this._context = context;
|
||||
|
||||
console.log('Got: ' + apiWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,10 +29,6 @@ export class MainController {
|
||||
}
|
||||
|
||||
public activate(): void {
|
||||
this._apiWrapper.registerWebviewProvider('data-management-agent', webview => {
|
||||
webview.html = '<div><h1>SQL Agent</h1></div>';
|
||||
});
|
||||
|
||||
vscode.commands.registerCommand('agent.openCreateJobDialog', (ownerUri: string) => {
|
||||
let dialog = new CreateJobDialog(ownerUri);
|
||||
dialog.showDialog();
|
||||
@@ -41,7 +36,11 @@ export class MainController {
|
||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, jobId: string, server: string, stepId: number) => {
|
||||
let dialog = new CreateStepDialog(ownerUri, jobId, server, stepId);
|
||||
dialog.openNewStepDialog();
|
||||
});
|
||||
});
|
||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string) => {
|
||||
let dialog = new PickScheduleDialog(ownerUri);
|
||||
dialog.showDialog();
|
||||
});
|
||||
}
|
||||
|
||||
private updateJobStepDialog() {
|
||||
|
||||
Reference in New Issue
Block a user