Add embedded Getting Started guide (#120)
* Add prompt to view embedded release notes. * Add Getting Started guide. * Correct the display condition
This commit is contained in:
Родитель
7e72d7b056
Коммит
44e0879f9a
|
@ -2,6 +2,7 @@ out
|
|||
node_modules
|
||||
packages
|
||||
.DS_Store
|
||||
*.dat
|
||||
*.db
|
||||
*.exe
|
||||
*.log
|
||||
|
|
|
@ -11,3 +11,4 @@ tasks/**
|
|||
packages/**
|
||||
samples/**
|
||||
*.exe
|
||||
*.dat
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.0.5",
|
||||
"displayname": "MSSQL support in VS Code",
|
||||
"description": "Connect to SQL Server and Azure SQL databases, run T-SQL queries and see results in a grid.",
|
||||
"publisher": "microsoft",
|
||||
"publisher": "Microsoft",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"aiKey": "AIF-5574968e-856d-40d2-af67-c89a14e76412",
|
||||
"icon": "images/sqlserver.png",
|
||||
|
@ -139,6 +139,11 @@
|
|||
"command": "extension.openConnectionSettingsFile",
|
||||
"title": "Open Connection Profile Settings",
|
||||
"category": "MSSQL"
|
||||
},
|
||||
{
|
||||
"command": "extension.showReleaseNotes",
|
||||
"title": "Getting Started Guide",
|
||||
"category": "MSSQL"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import * as events from 'events';
|
||||
import vscode = require('vscode');
|
||||
|
||||
import Constants = require('../models/constants');
|
||||
import Utils = require('../models/utils');
|
||||
import { SqlOutputContentProvider } from '../models/sqlOutputContentProvider';
|
||||
|
@ -13,7 +17,11 @@ import CodeAdapter from '../prompts/adapter';
|
|||
import Telemetry from '../models/telemetry';
|
||||
import VscodeWrapper from './vscodeWrapper';
|
||||
import { ISelectionData } from './../models/interfaces';
|
||||
import fs = require('fs');
|
||||
|
||||
/**
|
||||
* The main controller class that initializes the extension
|
||||
*/
|
||||
export default class MainController implements vscode.Disposable {
|
||||
private _context: vscode.ExtensionContext;
|
||||
private _event: events.EventEmitter = new events.EventEmitter();
|
||||
|
@ -24,6 +32,10 @@ export default class MainController implements vscode.Disposable {
|
|||
private _vscodeWrapper: VscodeWrapper;
|
||||
private _initialized: boolean = false;
|
||||
|
||||
/**
|
||||
* The main controller constructor
|
||||
* @constructor
|
||||
*/
|
||||
constructor(context: vscode.ExtensionContext,
|
||||
connectionManager?: ConnectionManager,
|
||||
vscodeWrapper?: VscodeWrapper) {
|
||||
|
@ -36,6 +48,9 @@ export default class MainController implements vscode.Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to setup command registrations
|
||||
*/
|
||||
private registerCommand(command: string): void {
|
||||
const self = this;
|
||||
this._context.subscriptions.push(vscode.commands.registerCommand(command, () => {
|
||||
|
@ -43,16 +58,25 @@ export default class MainController implements vscode.Disposable {
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the controller
|
||||
*/
|
||||
dispose(): void {
|
||||
this.deactivate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates the extension
|
||||
*/
|
||||
public deactivate(): void {
|
||||
Utils.logDebug(Constants.extensionDeactivated);
|
||||
this.onDisconnect();
|
||||
this._statusview.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the extension
|
||||
*/
|
||||
public activate(): Promise<boolean> {
|
||||
const self = this;
|
||||
|
||||
|
@ -73,65 +97,85 @@ export default class MainController implements vscode.Disposable {
|
|||
this._event.on(Constants.cmdChooseDatabase, () => { self.onChooseDatabase(); } );
|
||||
this.registerCommand(Constants.cmdOpenConnectionSettings);
|
||||
this._event.on(Constants.cmdOpenConnectionSettings, () => { self.onOpenConnectionSettings(); } );
|
||||
this.registerCommand(Constants.cmdShowReleaseNotes);
|
||||
this._event.on(Constants.cmdShowReleaseNotes, () => { self.launchReleaseNotesPage(); } );
|
||||
|
||||
this._vscodeWrapper = new VscodeWrapper();
|
||||
|
||||
return this.initialize(activationTimer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a flag indicating if the extension is initialized
|
||||
*/
|
||||
public isInitialized(): boolean {
|
||||
return this._initialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the extension
|
||||
*/
|
||||
public initialize(activationTimer: Utils.Timer): Promise<boolean> {
|
||||
const self = this;
|
||||
|
||||
// initialize language service client
|
||||
return new Promise<boolean>( (resolve, reject) => {
|
||||
SqlToolsServerClient.instance.initialize(this._context).then(() => {
|
||||
const self = this;
|
||||
SqlToolsServerClient.instance.initialize(self._context).then(() => {
|
||||
|
||||
// Init status bar
|
||||
this._statusview = new StatusView();
|
||||
self._statusview = new StatusView();
|
||||
|
||||
// Init CodeAdapter for use when user response to questions is needed
|
||||
this._prompter = new CodeAdapter();
|
||||
self._prompter = new CodeAdapter();
|
||||
|
||||
// Init content provider for results pane
|
||||
this._outputContentProvider = new SqlOutputContentProvider(self._context, self._statusview);
|
||||
self._outputContentProvider = new SqlOutputContentProvider(self._context, self._statusview);
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider(SqlOutputContentProvider.providerName, self._outputContentProvider);
|
||||
this._context.subscriptions.push(registration);
|
||||
self._context.subscriptions.push(registration);
|
||||
|
||||
// Init connection manager and connection MRU
|
||||
this._connectionMgr = new ConnectionManager(self._context, self._statusview, self._prompter);
|
||||
self._connectionMgr = new ConnectionManager(self._context, self._statusview, self._prompter);
|
||||
|
||||
activationTimer.end();
|
||||
|
||||
// telemetry for activation
|
||||
Telemetry.sendTelemetryEvent(this._context, 'ExtensionActivated', {},
|
||||
Telemetry.sendTelemetryEvent(self._context, 'ExtensionActivated', {},
|
||||
{ activationTime: activationTimer.getDuration() }
|
||||
);
|
||||
|
||||
self.showReleaseNotesPrompt();
|
||||
|
||||
Utils.logDebug(Constants.extensionActivated);
|
||||
this._initialized = true;
|
||||
self._initialized = true;
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Choose a new database from the current server
|
||||
/**
|
||||
* Choose a new database from the current server
|
||||
*/
|
||||
private onChooseDatabase(): Promise<boolean> {
|
||||
return this._connectionMgr.onChooseDatabase();
|
||||
}
|
||||
|
||||
// Close active connection, if any
|
||||
/**
|
||||
* Close active connection, if any
|
||||
*/
|
||||
private onDisconnect(): Promise<any> {
|
||||
return this._connectionMgr.onDisconnect();
|
||||
}
|
||||
|
||||
// Let users pick from a list of connections
|
||||
/**
|
||||
* Let users pick from a list of connections
|
||||
*/
|
||||
public onNewConnection(): Promise<boolean> {
|
||||
return this._connectionMgr.onNewConnection();
|
||||
}
|
||||
|
||||
// get the T-SQL query from the editor, run it and show output
|
||||
/**
|
||||
* get the T-SQL query from the editor, run it and show output
|
||||
*/
|
||||
public onRunQuery(): void {
|
||||
const self = this;
|
||||
if (!this._vscodeWrapper.isEditingSqlFile) {
|
||||
|
@ -171,12 +215,16 @@ export default class MainController implements vscode.Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
// Prompts to create a new SQL connection profile
|
||||
/**
|
||||
* Prompts to create a new SQL connection profile
|
||||
*/
|
||||
public onCreateProfile(): Promise<boolean> {
|
||||
return this._connectionMgr.onCreateProfile();
|
||||
}
|
||||
|
||||
// Prompts to remove a registered SQL connection profile
|
||||
/**
|
||||
* Prompts to remove a registered SQL connection profile
|
||||
*/
|
||||
public onRemoveProfile(): Promise<boolean> {
|
||||
return this._connectionMgr.onRemoveProfile();
|
||||
}
|
||||
|
@ -188,6 +236,9 @@ export default class MainController implements vscode.Disposable {
|
|||
this._connectionMgr.connectionUI.openConnectionProfileConfigFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a callback and logs any errors raised
|
||||
*/
|
||||
private runAndLogErrors<T>(promise: Promise<T>): Promise<T> {
|
||||
let self = this;
|
||||
return promise.catch(err => {
|
||||
|
@ -201,4 +252,62 @@ export default class MainController implements vscode.Disposable {
|
|||
public get connectionManager(): ConnectionManager {
|
||||
return this._connectionMgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user to view release notes if this is new extension install
|
||||
*/
|
||||
private showReleaseNotesPrompt(): void {
|
||||
let self = this;
|
||||
if (!this.doesExtensionLaunchedFileExist()) {
|
||||
// ask the user to view a scenario document
|
||||
let confirmText = 'View Now';
|
||||
this._vscodeWrapper.showInformationMessage(
|
||||
'View a walkthrough of common vscode-mssql scenarios?', confirmText)
|
||||
.then((choice) => {
|
||||
if (choice === confirmText) {
|
||||
self.launchReleaseNotesPage();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the release notes page in the preview browser
|
||||
*/
|
||||
private launchReleaseNotesPage(): void {
|
||||
// get the URI for the release notes page
|
||||
let docUri = vscode.Uri.file(
|
||||
this._context.asAbsolutePath(
|
||||
'out/src/views/htmlcontent/src/docs/index.html'));
|
||||
|
||||
// show the release notes page in the preview window
|
||||
vscode.commands.executeCommand(
|
||||
'vscode.previewHtml',
|
||||
docUri,
|
||||
vscode.ViewColumn.One,
|
||||
'vscode-mssql Release Notes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the extension launched file exists.
|
||||
* This is to detect when we are running in a clean install scenario.
|
||||
*/
|
||||
private doesExtensionLaunchedFileExist(): boolean {
|
||||
// check if file already exists on disk
|
||||
let filePath = this._context.asAbsolutePath('extensionlaunched.dat');
|
||||
try {
|
||||
// this will throw if the file does not exist
|
||||
fs.statSync(filePath);
|
||||
return true;
|
||||
} catch (err) {
|
||||
try {
|
||||
// write out the "first launch" file if it doesn't exist
|
||||
fs.writeFile(filePath, 'launched');
|
||||
} catch (err) {
|
||||
// ignore errors writing first launch file since there isn't really
|
||||
// anything we can do to recover in this situation.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import vscode = require('vscode');
|
||||
|
||||
|
||||
import * as Constants from './../models/constants';
|
||||
|
||||
export import TextEditor = vscode.TextEditor;
|
||||
|
@ -156,8 +158,8 @@ export default class VscodeWrapper {
|
|||
/**
|
||||
* Formats and shows a vscode information message
|
||||
*/
|
||||
public showInformationMessage(msg: string): Thenable<string> {
|
||||
return vscode.window.showInformationMessage(Constants.extensionName + ': ' + msg );
|
||||
public showInformationMessage(msg: string, ...items: string[]): Thenable<string> {
|
||||
return vscode.window.showInformationMessage(Constants.extensionName + ': ' + msg, ...items);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
import vscode = require('vscode');
|
||||
import MainController from './controllers/controller';
|
||||
import MainController from './controllers/mainController';
|
||||
|
||||
let controller: MainController = undefined;
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ export const cmdCreateProfile = 'extension.createprofile';
|
|||
export const cmdRemoveProfile = 'extension.removeprofile';
|
||||
export const cmdChooseDatabase = 'extension.chooseDatabase';
|
||||
export const cmdOpenConnectionSettings = 'extension.openConnectionSettingsFile';
|
||||
export const cmdShowReleaseNotes = 'extension.showReleaseNotes';
|
||||
|
||||
export const sqlDbPrefix = '.database.windows.net';
|
||||
export const defaultConnectionTimeout = 15;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -3,7 +3,7 @@ import vscode = require('vscode');
|
|||
|
||||
import * as Extension from '../src/extension';
|
||||
import ConnectionManager from '../src/controllers/connectionManager';
|
||||
import MainController from '../src/controllers/controller';
|
||||
import MainController from '../src/controllers/mainController';
|
||||
import Telemetry from '../src/models/telemetry';
|
||||
|
||||
function ensureExtensionIsActive(): Promise<any> {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { IPrompter } from '../src/prompts/question';
|
|||
import ConnectionManager from '../src/controllers/connectionManager';
|
||||
import { IConnectionCredentials, AuthenticationTypes } from '../src/models/interfaces';
|
||||
import * as ConnectionContracts from '../src/models/contracts/connection';
|
||||
import MainController from '../src/controllers/controller';
|
||||
import MainController from '../src/controllers/mainController';
|
||||
import * as Interfaces from '../src/models/interfaces';
|
||||
import { ConnectionStore } from '../src/models/connectionStore';
|
||||
import StatusView from '../src/views/statusView';
|
||||
|
|
Загрузка…
Ссылка в новой задаче