Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/edit connection #209

Merged
merged 9 commits into from May 7, 2019
4 changes: 2 additions & 2 deletions .test-database/.vscode/settings.json
Expand Up @@ -33,8 +33,8 @@
{
"name": "PGSQL URI",
"dialect": "PostgreSQL",
"connectString": "postgress://root:root@localhost:5433/test_db",
"connectionTimeout": 15,
"connectString": "postgres://root:root@localhost:5433/test_db",
"connectionTimeout": 15
},
{
"name": "MSSQL",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -30,7 +30,7 @@
"compile": "yarn workspace @sqltools/formatter build && yarn workspace @sqltools/extension compile",
"compile:preview": "yarn workspace @sqltools/extension compile:preview",
"package:preview": "yarn run compile:preview && (cd ../dist && vsce package --yarn)",
"package": "yarn run compile && (cd ../dist && vsce package --yarn)",
"package": "cross-env NODE_ENV=production yarn run compile && (cd ../dist && cross-env NODE_ENV=production vsce package --yarn)",
"publish": "yarn run package && cd ../dist && vsce publish --yarn",
"postinstall": "git submodule update --init --recursive && yarn workspace @sqltools/formatter install",
"test:upcontainers": "bash ./.test-database/start-dbs.sh"
Expand Down
17 changes: 17 additions & 0 deletions packages/core/utils/get-connection-stuff.ts
@@ -0,0 +1,17 @@
import { ConnectionInterface } from '../interface';

export const idSep = '|';

export function getConnectionId(c: ConnectionInterface): string | null {
if (!c)
return null;
if (c.id) return c.id;

if (c.connectString) `${c.name}${idSep}${c.connectString}`.replace(/\./g, ':').replace(/\//g, '\\')
return `${c.name}${idSep}${c.dialect}${idSep}${c.server}${idSep}${c.database}`.replace(/\./g, ':').replace(/\//g, '\\');
}

export function getNameFromId(id: string) {
if (!id) return null;
return id.split(idSep)[0];
}
25 changes: 8 additions & 17 deletions packages/core/utils/index.ts
@@ -1,30 +1,20 @@
import path from 'path';
import * as query from './query';
import commandExists from './command-exists';
import { ConnectionInterface, DatabaseDialect } from '../interface';
export * from './get-home';
export * from './replacer';
export * from './telemetry';
export * from './timer';

const idSep = '|';
export * from './get-connection-stuff';

export function sortText(a: string, b: string) { return a.toString().localeCompare(b.toString()); }

export function getConnectionId(c: ConnectionInterface): string | null {
if (!c) return null;
return c.id || `${c.name}${idSep}${c.database}${idSep}${c.dialect}`.replace(/\./g, ':').replace(/\//g, '\\');
}

export function getNameFromId(id: string) {
if (!id) return null;
return id.split(idSep)[0];
}

export function asArray(obj: any) {
export function asArray<T>(obj: any) {
if (Array.isArray(obj)) {
return obj;
return obj as T[];
}
return Object.keys(obj).map((k) => obj[k]);
return Object.keys(obj).map((k) => obj[k]) as T[];
}

export function getConnectionDescription(c: ConnectionInterface): string | null {
Expand All @@ -40,8 +30,9 @@ export function getConnectionDescription(c: ConnectionInterface): string | null
return [
c.username,
c.username ? '@' : '',
c.server,
c.server && c.port ? ':' : '',
!c.socketPath && c.server,
!c.socketPath && c.server && c.port ? ':' : '',
c.socketPath && `socket:${path.basename(c.socketPath)}`,
c.port,
'/',
c.database,
Expand Down
19 changes: 10 additions & 9 deletions packages/extension/package.json
Expand Up @@ -208,9 +208,9 @@
}
},
{
"title": "Add new connection from arg",
"command": "SQLTools.addConnection",
"category": "SQLTools internal"
"title": "Edit connection",
"command": "SQLTools.openEditConnectionScreen",
"category": "SQLTools Management"
},
{
"title": "Delete connection",
Expand Down Expand Up @@ -549,10 +549,10 @@
"type": [
"object",
"null"
],
],
"default": {},
"required": false,
"description": "See https://vscode-sqltools.mteixeira.dev/connections/oracledb#2-3-specific-options for more details."
"description": "See https://vscode-sqltools.mteixeira.dev/connections/oracledb#2-3-specific-options for more details."
},
"connectionTimeout": {
"type": "number",
Expand Down Expand Up @@ -711,10 +711,6 @@
"command": "SQLTools.generateInsertQuery",
"when": "false"
},
{
"command": "SQLTools.addConnection",
"when": "false"
},
{
"command": "SQLTools.saveResults",
"when": "sqltools.Results.active"
Expand Down Expand Up @@ -765,6 +761,11 @@
"when": "view == SQLTools/connectionExplorer && viewItem == connectedConnection",
"group": "navigation@0"
},
{
"command": "SQLTools.openEditConnectionScreen",
"when": "view == SQLTools/connectionExplorer && viewItem =~ /^(connection|connectedConnection)$/",
"group": "navigation@1"
},
{
"command": "SQLTools.deleteConnection",
"when": "view == SQLTools/connectionExplorer && viewItem =~ /^(connection|connectedConnection)$/",
Expand Down
4 changes: 2 additions & 2 deletions packages/plugins/connection-manager/explorer/index.ts
Expand Up @@ -41,7 +41,7 @@ export class ConnectionExplorer implements TreeDataProvider<SidebarTreeItem> {
}

private getTreeItems() {
const items = asArray(this.tree);
const items = asArray<SidebarConnection>(this.tree);
if (items.length === 0) {
const addNew = new TreeItem('No Connections. Click here to add one', TreeItemCollapsibleState.None);
addNew.command = {
Expand All @@ -56,7 +56,7 @@ export class ConnectionExplorer implements TreeDataProvider<SidebarTreeItem> {
if (!element) {
return Promise.resolve(asArray(this.getTreeItems()));
}
const items: SidebarTreeItem[] = element.items;
const items = element.items as any[];
if (ConfigManager.flattenGroupsIfOne && items.length === 1) {
return this.getChildren(items[0]);
}
Expand Down
30 changes: 30 additions & 0 deletions packages/plugins/connection-manager/extension.ts
Expand Up @@ -143,6 +143,22 @@ export default class ConnectionManagerPlugin implements SQLTools.ExtensionPlugin
return this.settingsWebview.show();
}

private ext_openEditConnectionScreen = async (connIdOrNode?: string | SidebarConnection) => {
let id: string;
if (connIdOrNode) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identical blocks of code found in 2 locations. Consider refactoring.

id = connIdOrNode instanceof SidebarConnection ? connIdOrNode.getId() : <string>connIdOrNode;
} else {
const conn = await this._pickConnection();
id = conn ? getConnectionId(conn) : undefined;
}

if (!id) return;

const conn = this.explorer.getById(id);
this.settingsWebview.show();
this.settingsWebview.postMessage({ action: 'editConnection', payload: { conn } });
}

private ext_focusOnExplorer = () => {
return this.explorer.focus();
}
Expand Down Expand Up @@ -203,6 +219,18 @@ export default class ConnectionManagerPlugin implements SQLTools.ExtensionPlugin
return this.saveConnectionList(connList, ConfigurationTarget[writeTo]);
}

private ext_updateConnection = (oldId: string, connInfo: ConnectionInterface, writeTo?: keyof typeof ConfigurationTarget) => {
if (!connInfo) {
console.warn('Nothing to do. No parameter received');
return;
}

const connList = this.getConnectionList(ConfigurationTarget[writeTo] || undefined)
.filter(c => getConnectionId(c) !== oldId);
connList.push(connInfo);
return this.saveConnectionList(connList, ConfigurationTarget[writeTo]);
}

// internal utils
private async _getTableName(node?: SidebarTableOrView): Promise<string> {
if (node && node.conn) {
Expand Down Expand Up @@ -371,7 +399,9 @@ export default class ConnectionManagerPlugin implements SQLTools.ExtensionPlugin

// register extension commands
extension.registerCommand(`addConnection`, this.ext_addConnection)
.registerCommand(`updateConnection`, this.ext_updateConnection)
.registerCommand(`openAddConnectionScreen`, this.ext_openAddConnectionScreen)
.registerCommand(`openEditConnectionScreen`, this.ext_openEditConnectionScreen)
.registerCommand(`closeConnection`, this.ext_closeConnection)
.registerCommand(`deleteConnection`, this.ext_deleteConnection)
.registerCommand(`describeFunction`, this.ext_describeFunction)
Expand Down
5 changes: 5 additions & 0 deletions packages/plugins/connection-manager/screens/provider.ts
Expand Up @@ -75,6 +75,11 @@ export default abstract class WebviewProvider<State = any> implements Disposable
this.panel.reveal(this.wereToShow, this.preserveFocus);
this.postMessage({ action: 'reset' });
this.setPreviewActiveContext(true);
if (process.env.NODE_ENV) {
setTimeout(() => {
commands.executeCommand('workbench.action.webview.openDeveloperTools');
}, 1000);
}
}

private onDidReceiveMessage = ({ action, payload, ...rest}) => {
Expand Down
15 changes: 15 additions & 0 deletions packages/plugins/connection-manager/screens/settings.ts
Expand Up @@ -13,12 +13,27 @@ export default class SettingsWebview extends WebviewProvider {
switch (action) {
case 'createConnection':
return this.createConnection(payload);
case 'updateConnection':
return this.updateConnection(payload);
default:
break;
}
});
}

private updateConnection = async ({ connInfo, isGlobal, editId }) => {
console.log({ connInfo, isGlobal, editId });
commands.executeCommand(`${EXT_NAME}.updateConnection`, editId, connInfo, isGlobal ? 'Global' : undefined)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 2 locations. Consider refactoring.

.then(() => {
this.postMessage({ action: 'updateConnectionSuccess', payload: { isGlobal, connInfo: { ...connInfo, id: getConnectionId(connInfo) } } });
}, (payload = {}) => {
payload = {
message: (payload.message || payload || '').toString(),
}
this.postMessage({ action: 'updateConnectionError', payload });
});
}

private createConnection = async ({ connInfo, isGlobal }) => {
commands.executeCommand(`${EXT_NAME}.addConnection`, connInfo, isGlobal ? 'Global' : undefined)
.then(() => {
Expand Down
3 changes: 2 additions & 1 deletion packages/ui/components/Syntax.tsx
Expand Up @@ -4,6 +4,7 @@ import { clipboardInsert } from '../lib/utils';
interface SyntaxProps {
language?: string;
code: any;
strong?: boolean;
}

interface SyntaxState {
Expand Down Expand Up @@ -45,7 +46,7 @@ export default class Syntax extends React.Component<SyntaxProps, SyntaxState> {
<div className='relative'>
<div
id={this.id}
className={`syntax ${this.props.language}`}
className={`syntax ${this.props.language} ${this.props.strong ? 'strong-bg' : ''}`}
dangerouslySetInnerHTML={{ __html: this.renderCode(this.props.code) }}
></div>
<button className='btn copy-code' type='button' onClick={this.copyCode}>{this.state.copyMsg}</button>
Expand Down
1 change: 1 addition & 0 deletions packages/ui/lib/utils.ts
Expand Up @@ -6,6 +6,7 @@ export function int(v) {
return notEmpty(v) ? parseInt(v, 10) : null;
}
export function bool(v) {
if (typeof v === 'undefined') return false;
v = v.toString().toLowerCase();
return v === '1' || v === 'true' || v === 'yes' || v === 'y';
}
Expand Down
7 changes: 7 additions & 0 deletions packages/ui/sass/_syntax.scss
Expand Up @@ -28,6 +28,10 @@
}
}

.syntax.strong-bg {
background: rgba(0, 0, 0, 0.02);
}

.btn.copy-code {
position: absolute;
top: 0;
Expand All @@ -42,4 +46,7 @@

body.vscode-dark .syntax {
background: var(--vscode-editor-background, #222);
&.strong-bg {
background: rgba(255, 255, 255, 0.02);
}
}
11 changes: 4 additions & 7 deletions packages/ui/sass/_variables.scss
Expand Up @@ -67,15 +67,12 @@ input, select, select > option {
background: var(--vscode-settings-textInputBackground);
border: none;
color: var(--vscode-settings-textInputForeground);
padding: 4px;
padding: 4px 8px;
}
select {
padding: 4px 6px;
}

// .vscode-dark {
// input, select, select > option {
// background: $darkThemeWhite1;
// border-color: $darkThemeWhite2;
// }
// }

.fullscreen-container {
@include full-screen();
Expand Down
16 changes: 4 additions & 12 deletions packages/ui/sass/lib/_simple-grid.scss
Expand Up @@ -99,23 +99,15 @@ p {

$width: 96%;
$gutter: 4%;
$breakpoint-small: 33.75em; // 540px
$breakpoint-med: 45em; // 720px
$breakpoint-small: 0em; // 540px
$breakpoint-med: 1em; // 720px
$breakpoint-large: 60em; // 960px

.container {
width: 90%;
width: 100%;
margin-left: auto;
margin-right: auto;

@media only screen and (min-width: $breakpoint-small) {
width: 80%;
}

@media only screen and (min-width: $breakpoint-large) {
width: 75%;
max-width: 60rem;
}
max-width: 1024px;
}

.row {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/screens/Results/Screen.tsx
Expand Up @@ -30,7 +30,7 @@ export default class ResultsScreen extends React.Component<{}, QueryResultsState
}

messagesHandler = ({ action, payload }: WebviewMessageType<any>) => {
console.log('Message received', {action, payload});
console.log(`Message received: ${action}`, ...[ payload ]);
switch (action) {
case 'queryResults':
const results: DatabaseInterface.QueryResults[] = payload;
Expand Down