diff --git a/packages/api/src/controllers/jsldata.js b/packages/api/src/controllers/jsldata.js
index e233963c2..b5bd70cde 100644
--- a/packages/api/src/controllers/jsldata.js
+++ b/packages/api/src/controllers/jsldata.js
@@ -34,7 +34,7 @@ module.exports = {
openReader(jslid) {
const file = path.join(jsldir(), `${jslid}.jsonl`);
return new Promise((resolve, reject) =>
- lineReader.open(file, function (err, reader) {
+ lineReader.open(file, (err, reader) => {
if (err) reject(err);
resolve();
this.openedReaders[jslid] = {
@@ -50,7 +50,7 @@ module.exports = {
await this.closeReader();
}
if (!this.openedReaders[jslid]) {
- await this.openReader();
+ await this.openReader(jslid);
}
while (this.openedReaders[jslid].readedCount < offset) {
await this.readLine(jslid);
diff --git a/packages/datalib/src/ChangeSet.ts b/packages/datalib/src/ChangeSet.ts
index 58fd89b89..971f30eb1 100644
--- a/packages/datalib/src/ChangeSet.ts
+++ b/packages/datalib/src/ChangeSet.ts
@@ -40,11 +40,12 @@ export function findExistingChangeSetItem(
changeSet: ChangeSet,
definition: ChangeSetRowDefinition
): [keyof ChangeSet, ChangeSetItem] {
+ if (!changeSet) return ['updates', null];
if (definition.insertedRowIndex != null) {
return [
'inserts',
changeSet.inserts.find(
- x =>
+ (x) =>
x.pureName == definition.pureName &&
x.schemaName == definition.schemaName &&
x.insertedRowIndex == definition.insertedRowIndex
@@ -52,7 +53,7 @@ export function findExistingChangeSetItem(
];
} else {
const inUpdates = changeSet.updates.find(
- x =>
+ (x) =>
x.pureName == definition.pureName &&
x.schemaName == definition.schemaName &&
_.isEqual(x.condition, definition.condition)
@@ -60,7 +61,7 @@ export function findExistingChangeSetItem(
if (inUpdates) return ['updates', inUpdates];
const inDeletes = changeSet.deletes.find(
- x =>
+ (x) =>
x.pureName == definition.pureName &&
x.schemaName == definition.schemaName &&
_.isEqual(x.condition, definition.condition)
@@ -84,7 +85,7 @@ export function setChangeSetValue(
if (existingItem) {
return {
...changeSet,
- [fieldName]: changeSet[fieldName].map(item =>
+ [fieldName]: changeSet[fieldName].map((item) =>
item == existingItem
? {
...item,
@@ -164,7 +165,7 @@ export function batchUpdateChangeSet(
}
function extractFields(item: ChangeSetItem): UpdateField[] {
- return _.keys(item.fields).map(targetColumn => ({
+ return _.keys(item.fields).map((targetColumn) => ({
targetColumn,
exprType: 'value',
value: item.fields[targetColumn],
@@ -185,7 +186,7 @@ function insertToSql(item: ChangeSetItem): Insert {
function extractCondition(item: ChangeSetItem): Condition {
return {
conditionType: 'and',
- conditions: _.keys(item.condition).map(columnName => ({
+ conditions: _.keys(item.condition).map((columnName) => ({
conditionType: 'binary',
operator: '=',
left: {
@@ -248,7 +249,7 @@ export function revertChangeSetRowChanges(changeSet: ChangeSet, definition: Chan
if (item)
return {
...changeSet,
- [field]: changeSet[field].filter(x => x != item),
+ [field]: changeSet[field].filter((x) => x != item),
};
return changeSet;
}
@@ -280,8 +281,8 @@ export function deleteChangeSetRows(changeSet: ChangeSet, definition: ChangeSetR
export function getChangeSetInsertedRows(changeSet: ChangeSet, name?: NamedObjectInfo) {
if (!name) return [];
if (!changeSet) return [];
- const rows = changeSet.inserts.filter(x => x.pureName == name.pureName && x.schemaName == name.schemaName);
- const maxIndex = _.maxBy(rows, x => x.insertedRowIndex)?.insertedRowIndex;
+ const rows = changeSet.inserts.filter((x) => x.pureName == name.pureName && x.schemaName == name.schemaName);
+ const maxIndex = _.maxBy(rows, (x) => x.insertedRowIndex)?.insertedRowIndex;
if (maxIndex == null) return [];
const res = Array(maxIndex + 1).fill({});
for (const row of rows) {
diff --git a/packages/datalib/src/GridDisplay.ts b/packages/datalib/src/GridDisplay.ts
index aa68860b6..00eed6050 100644
--- a/packages/datalib/src/GridDisplay.ts
+++ b/packages/datalib/src/GridDisplay.ts
@@ -55,6 +55,9 @@ export abstract class GridDisplay {
columns: DisplayColumn[];
baseTable?: TableInfo;
changeSetKeyFields: string[] = null;
+ sortable = false;
+ filterable = false;
+ editable = false;
setColumnVisibility(uniquePath: string[], isVisible: boolean) {
const uniqueName = uniquePath.join('.');
diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts
index 9487dcea9..cf9dcd6e7 100644
--- a/packages/datalib/src/TableGridDisplay.ts
+++ b/packages/datalib/src/TableGridDisplay.ts
@@ -16,11 +16,14 @@ export class TableGridDisplay extends GridDisplay {
) {
super(config, setConfig, cache, setCache, getTableInfo, driver);
this.columns = this.getDisplayColumns(table, []);
+ this.filterable = true;
+ this.sortable = true;
+ this.editable = true;
this.baseTable = table;
if (table && table.columns) {
this.changeSetKeyFields = table.primaryKey
- ? table.primaryKey.columns.map(x => x.columnName)
- : table.columns.map(x => x.columnName);
+ ? table.primaryKey.columns.map((x) => x.columnName)
+ : table.columns.map((x) => x.columnName);
}
}
@@ -30,7 +33,7 @@ export class TableGridDisplay extends GridDisplay {
const select: Select = {
commandType: 'select',
from: { name: this.table, alias: 'basetbl' },
- columns: this.table.columns.map(col => ({
+ columns: this.table.columns.map((col) => ({
exprType: 'column',
alias: col.columnName,
source: { alias: 'basetbl' },
@@ -45,7 +48,7 @@ export class TableGridDisplay extends GridDisplay {
],
};
const displayedColumnInfo = _.keyBy(
- this.columns.map(col => ({ ...col, sourceAlias: 'basetbl' })),
+ this.columns.map((col) => ({ ...col, sourceAlias: 'basetbl' })),
'uniqueName'
);
const action = combineReferenceActions(
diff --git a/packages/web/src/TabContent.js b/packages/web/src/TabContent.js
index df68ce996..5cf081330 100644
--- a/packages/web/src/TabContent.js
+++ b/packages/web/src/TabContent.js
@@ -10,6 +10,7 @@ const TabContainer = styled.div`
top: 0;
right: 0;
bottom: 0;
+ display: flex;
visibility: ${props =>
// @ts-ignore
props.tabVisible ? 'visible' : 'hidden'};
diff --git a/packages/web/src/datagrid/ColumnHeaderControl.js b/packages/web/src/datagrid/ColumnHeaderControl.js
index 9acb87f09..ff9f6b844 100644
--- a/packages/web/src/datagrid/ColumnHeaderControl.js
+++ b/packages/web/src/datagrid/ColumnHeaderControl.js
@@ -12,7 +12,8 @@ const HeaderDiv = styled.div`
const LabelDiv = styled.div`
flex: 1;
min-width: 10px;
- padding-left: 2px;
+ // padding-left: 2px;
+ padding: 2px;
margin: auto;
`;
@@ -36,10 +37,12 @@ export default function ColumnHeaderControl({ column, setSort, order }) {
)}
-
- setSort('ASC')}>Sort ascending
- setSort('DESC')}>Sort descending
-
+ {setSort && (
+
+ setSort('ASC')}>Sort ascending
+ setSort('DESC')}>Sort descending
+
+ )}
);
}
diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js
index 7d3aafa65..af642907f 100644
--- a/packages/web/src/datagrid/DataGridCore.js
+++ b/packages/web/src/datagrid/DataGridCore.js
@@ -90,6 +90,7 @@ const TableHeaderCell = styled.td`
// border-collapse: collapse;
text-align: left;
padding: 0;
+ // padding: 2px;
margin: 0;
background-color: #f6f7f9;
overflow: hidden;
@@ -112,12 +113,10 @@ const FocusField = styled.input`
async function loadDataPage(props, offset, limit) {
const { display, conid, database, jslid } = props;
- console.log('LOAD PAGE', jslid);
-
if (jslid) {
const response = await axios.request({
url: 'jsldata/get-rows',
- method: 'post',
+ method: 'get',
params: {
jslid,
offset,
@@ -256,6 +255,7 @@ export default function DataGridCore(props) {
const [inplaceEditorState, dispatchInsplaceEditor] = React.useReducer((state, action) => {
switch (action.type) {
case 'show':
+ if (!display.editable) return {};
return {
cell: action.cell,
text: action.text,
@@ -914,39 +914,41 @@ export default function DataGridCore(props) {
>
display.setSort(col.uniqueName, order)}
+ setSort={display.sortable ? (order) => display.setSort(col.uniqueName, order) : null}
order={display.getSortOrder(col.uniqueName)}
/>
))}
-
-
- {filterCount > 0 && (
-
-
-
- )}
-
- {visibleRealColumns.map((col) => (
-
+
- display.setFilter(col.uniqueName, value)}
- />
-
- ))}
-
+ {filterCount > 0 && (
+
+
+
+ )}
+
+ {visibleRealColumns.map((col) => (
+
+ display.setFilter(col.uniqueName, value)}
+ />
+
+ ))}
+
+ )}
{loadedAndInsertedRows
diff --git a/packages/web/src/query/MessagesView.js b/packages/web/src/query/MessagesView.js
index 254621163..aaec9beb2 100644
--- a/packages/web/src/query/MessagesView.js
+++ b/packages/web/src/query/MessagesView.js
@@ -1,8 +1,13 @@
import React from 'react';
+import styled from 'styled-components';
+
+const StyledTable = styled.table`
+ flex: 1;
+`;
export default function MessagesView({ items }) {
return (
-
+
| Number |
Message |
@@ -19,6 +24,6 @@ export default function MessagesView({ items }) {
{row.line} |
))}
-
+
);
}
diff --git a/packages/web/src/tabs/QueryTab.js b/packages/web/src/tabs/QueryTab.js
index 6428d89fc..297993355 100644
--- a/packages/web/src/tabs/QueryTab.js
+++ b/packages/web/src/tabs/QueryTab.js
@@ -13,17 +13,18 @@ import SessionMessagesView from '../query/SessionMessagesView';
import { TabPage, TabControl } from '../widgets/TabControl';
import getResultTabs from '../sqleditor/ResultTabs';
import ResultTabs from '../sqleditor/ResultTabs';
+import { VerticalSplitter } from '../widgets/Splitter';
-const MainContainer = styled.div``;
+// const MainContainer = styled.div``;
-const EditorContainer = styled.div`
- height: 600px;
- position: relative;
-`;
+// const EditorContainer = styled.div`
+// height: 600px;
+// position: relative;
+// `;
-const MessagesContainer = styled.div`
- height: 200px;
-`;
+// const MessagesContainer = styled.div`
+// height: 200px;
+// `;
export default function QueryTab({ tabid, conid, database, tabVisible, toolbarPortalRef }) {
const localStorageKey = `sql_${tabid}`;
@@ -73,8 +74,8 @@ export default function QueryTab({ tabid, conid, database, tabVisible, toolbarPo
const handleKeyDown = (e) => {};
return (
-
-
+ <>
+
-
- {toolbarPortalRef &&
- toolbarPortalRef.current &&
- tabVisible &&
- ReactDOM.createPortal(
- ,
- toolbarPortalRef.current
- )}
-
-
-
-
+
+ {toolbarPortalRef &&
+ toolbarPortalRef.current &&
+ tabVisible &&
+ ReactDOM.createPortal(
+ ,
+ toolbarPortalRef.current
+ )}
+ >
);
}
diff --git a/packages/web/src/widgets/Splitter.js b/packages/web/src/widgets/Splitter.js
new file mode 100644
index 000000000..ab43bf7c4
--- /dev/null
+++ b/packages/web/src/widgets/Splitter.js
@@ -0,0 +1,30 @@
+import _ from 'lodash';
+import React from 'react';
+import styled from 'styled-components';
+
+const MainContainer = styled.div`
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+`;
+
+const ChildContainer = styled.div`
+ flex: 1;
+ // flex: 0 0 50%;
+// flex-basis: 100px;
+// flex-grow: 1;
+ display: flex;
+ position: relative;
+`;
+
+export function VerticalSplitter({ children }) {
+ if (!_.isArray(children) || children.length !== 2) {
+ throw new Error('Splitter must have exactly 2 children');
+ }
+ return (
+
+ {children[0]}
+ {children[1]}
+
+ );
+}
diff --git a/packages/web/src/widgets/TabControl.js b/packages/web/src/widgets/TabControl.js
index 18aeba1f8..70d1b200c 100644
--- a/packages/web/src/widgets/TabControl.js
+++ b/packages/web/src/widgets/TabControl.js
@@ -24,6 +24,7 @@ const TabNameWrapper = styled.span`
const TabContainer = styled.div`
position: relative;
+ display: flex;
flex-grow: 1;
`;
@@ -36,6 +37,7 @@ const TabsContainer = styled.div`
const MainContainer = styled.div`
display: flex;
+ flex: 1;
flex-direction: column;
`;