-
Notifications
You must be signed in to change notification settings - Fork 525
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #141 from BornaP/125-objects-sql-definitions
#125 objects sql definitions
- Loading branch information
Showing
10 changed files
with
329 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { getDBConnByName } from './connections'; | ||
import { updateQueryIfNeeded } from './queries'; | ||
|
||
|
||
export const GET_SCRIPT_REQUEST = 'GET_SCRIPT_REQUEST'; | ||
export const GET_SCRIPT_SUCCESS = 'GET_SCRIPT_SUCCESS'; | ||
export const GET_SCRIPT_FAILURE = 'GET_SCRIPT_FAILURE'; | ||
|
||
|
||
export function getSQLScriptIfNeeded(database, item, actionType, objectType) { | ||
return (dispatch, getState) => { | ||
const state = getState(); | ||
if (shouldFetchScript(state, database, item, actionType)) { | ||
return dispatch(getSQLScript(database, item, actionType, objectType)); | ||
} else if (isScriptAlreadyFetched(state, database, item, actionType)) { | ||
const script = getAlreadyFetchedScript(state, database, item, actionType); | ||
return dispatch(updateQueryIfNeeded(script)); | ||
} | ||
}; | ||
} | ||
|
||
function shouldFetchScript (state, database, item, actionType) { | ||
const scripts = state.sqlscripts; | ||
if (!scripts) return true; | ||
if (scripts.isFetching) return false; | ||
if (!scripts.scriptsByObject[database]) return true; | ||
if (!scripts.scriptsByObject[database][item]) return true; | ||
if (!scripts.scriptsByObject[database][item][actionType]) return true; | ||
return scripts.didInvalidate; | ||
} | ||
|
||
function isScriptAlreadyFetched (state, database, item, actionType) { | ||
const scripts = state.sqlscripts; | ||
if (!scripts.scriptsByObject[database]) return false; | ||
if (!scripts.scriptsByObject[database][item]) return false; | ||
if (scripts.scriptsByObject[database][item][actionType]) return true; | ||
return false; | ||
} | ||
|
||
function getAlreadyFetchedScript (state, database, item, actionType) { | ||
return state.sqlscripts.scriptsByObject[database][item][actionType]; | ||
} | ||
|
||
|
||
function getSQLScript (database, item, actionType, objectType) { | ||
return async (dispatch) => { | ||
dispatch({ type: GET_SCRIPT_REQUEST, database, item, actionType, objectType }); | ||
try { | ||
const dbConn = getDBConnByName(database); | ||
let script; | ||
if (actionType === 'CREATE') { | ||
[script] = objectType === 'Table' | ||
? await dbConn.getTableCreateScript(item) | ||
: (objectType === 'View') | ||
? await dbConn.getViewCreateScript(item) | ||
: await dbConn.getRoutineCreateScript(item, objectType); | ||
} else if (actionType === 'SELECT') { | ||
script = await dbConn.getTableSelectScript(item); | ||
} else if (actionType === 'INSERT') { | ||
script = await dbConn.getTableInsertScript(item); | ||
} else if (actionType === 'UPDATE') { | ||
script = await dbConn.getTableUpdateScript(item); | ||
} else if (actionType === 'DELETE') { | ||
script = await dbConn.getTableDeleteScript(item); | ||
} | ||
dispatch({ type: GET_SCRIPT_SUCCESS, database, item, script, actionType, objectType }); | ||
dispatch(updateQueryIfNeeded(script)); | ||
} catch (error) { | ||
dispatch({ type: GET_SCRIPT_FAILURE, error }); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import React, { Component, PropTypes } from 'react'; | ||
import TableSubmenu from './table-submenu.jsx'; | ||
import { Menu, MenuItem } from 'remote'; | ||
|
||
|
||
const STYLE = { | ||
item: { wordBreak: 'break-all', cursor: 'default' }, | ||
}; | ||
|
||
|
||
export default class DatabaseItem extends Component { | ||
static propTypes = { | ||
database: PropTypes.object.isRequired, | ||
item: PropTypes.object.isRequired, | ||
dbObjectType: PropTypes.string.isRequired, | ||
style: PropTypes.object, | ||
columnsByTable: PropTypes.object, | ||
triggersByTable: PropTypes.object, | ||
onSelectItem: PropTypes.func, | ||
onExecuteDefaultQuery: PropTypes.func, | ||
onGetSQLScript: PropTypes.func, | ||
} | ||
|
||
constructor(props, context) { | ||
super(props, context); | ||
this.state = {}; | ||
this.contextMenu; | ||
} | ||
|
||
// Context menu is built dinamically on click (if it does not exist), because building | ||
// menu onComponentDidMount or onComponentWillMount slows table listing when database | ||
// has a loads of tables, because menu will be created (unnecessarily) for every table shown | ||
onContextMenu(e){ | ||
e.preventDefault(); | ||
if (!this.contextMenu){ | ||
this.buildContextMenu(); | ||
} | ||
this.contextMenu.popup(e.clientX, e.clientY); | ||
} | ||
|
||
buildContextMenu(){ | ||
const { | ||
database, | ||
item, | ||
dbObjectType, | ||
onExecuteDefaultQuery, | ||
onGetSQLScript, | ||
} = this.props; | ||
const actionTypes = ['SELECT', 'INSERT', 'UPDATE', 'DELETE']; | ||
|
||
this.contextMenu = new Menu(); | ||
if (dbObjectType === 'Table' || dbObjectType === 'View') { | ||
this.contextMenu.append(new MenuItem({ | ||
label: 'Execute default query', | ||
click: onExecuteDefaultQuery.bind(this, database, item) | ||
})); | ||
} | ||
this.contextMenu.append(new MenuItem({ | ||
label: 'CREATE script', | ||
click: onGetSQLScript.bind(this, database, item, 'CREATE', dbObjectType) | ||
})); | ||
if (dbObjectType === 'Table') { | ||
actionTypes.map((actionType, index) => { | ||
this.contextMenu.append(new MenuItem({ | ||
label: `${actionType} script`, | ||
click: onGetSQLScript.bind(this, database, item, actionType, dbObjectType) | ||
})); | ||
}); | ||
} | ||
} | ||
|
||
toggleTableCollapse() { | ||
this.setState({ tableCollapsed: !this.state.tableCollapsed }); | ||
} | ||
|
||
renderSubItems(table) { | ||
const { columnsByTable, triggersByTable, database } = this.props; | ||
|
||
if (!columnsByTable || !columnsByTable[table]) { | ||
return null; | ||
} | ||
|
||
const displayStyle = {}; | ||
if (!this.state.tableCollapsed) { | ||
displayStyle.display = 'none'; | ||
} | ||
|
||
return ( | ||
<div style={displayStyle}> | ||
<TableSubmenu | ||
title="Columns" | ||
table={table} | ||
itemsByTable={columnsByTable} | ||
database={database}/> | ||
<TableSubmenu | ||
collapsed | ||
title="Triggers" | ||
table={table} | ||
itemsByTable={triggersByTable} | ||
database={database}/> | ||
</div> | ||
); | ||
} | ||
|
||
render() { | ||
const { database, item, style, onSelectItem, dbObjectType } = this.props; | ||
const hasChildElements = !!onSelectItem; | ||
const onSingleClick = hasChildElements | ||
? () => {onSelectItem(database, item); this.toggleTableCollapse();} | ||
: () => {}; | ||
|
||
const collapseCssClass = this.state.tableCollapsed ? 'down' : 'right'; | ||
const collapseIcon = ( | ||
<i className={`${collapseCssClass} triangle icon`} style={{float: 'left', margin: '0 0.15em 0 -1em'}}></i> | ||
); | ||
const tableIcon = ( | ||
<i className="table icon" style={{float: 'left', margin: '0 0.3em 0 0'}}></i> | ||
); | ||
|
||
return ( | ||
<div> | ||
<span | ||
style={style} | ||
className="item" | ||
onClick={onSingleClick} | ||
onContextMenu={::this.onContextMenu}> | ||
{ dbObjectType === 'Table' ? collapseIcon : null } | ||
{ dbObjectType === 'Table' ? tableIcon : null } | ||
{item.name} | ||
</span> | ||
{this.renderSubItems(item.name)} | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.