diff --git a/frontend/src/components/dbfragments/showdata.tsx b/frontend/src/components/dbfragments/showdata.tsx
index dd20a576..f7eb4178 100644
--- a/frontend/src/components/dbfragments/showdata.tsx
+++ b/frontend/src/components/dbfragments/showdata.tsx
@@ -59,11 +59,11 @@ const DBShowDataFragment = (_: DBShowDataPropType) => {
}, [queryFilter])
- const fetchData = async (fetchCount: boolean) => {
+ const fetchData = async (isFirstFetch: boolean) => {
if (!dataModel) return
try {
- const result = await dispatch(getDBDataInDataModel({ tabId: currentTab.id, dbConnectionId: dbConnection!.id, schemaName: dataModel!.schemaName ?? '', name: dataModel!.name, queryLimit, queryOffset, fetchCount, queryFilter, querySort })).unwrap()
- if (fetchCount) {
+ const result = await dispatch(getDBDataInDataModel({ tabId: currentTab.id, dbConnectionId: dbConnection!.id, schemaName: dataModel!.schemaName ?? '', name: dataModel!.name, queryLimit, queryOffset, isFirstFetch, queryFilter, querySort })).unwrap()
+ if (isFirstFetch) {
setQueryCount(result.data.count)
}
} catch (e) {
diff --git a/frontend/src/components/dbfragments/table/editablecell.tsx b/frontend/src/components/dbfragments/table/editablecell.tsx
index 486fc342..7f740b15 100644
--- a/frontend/src/components/dbfragments/table/editablecell.tsx
+++ b/frontend/src/components/dbfragments/table/editablecell.tsx
@@ -34,7 +34,7 @@ const EditableCell = ({
}
const onSave = async () => {
- onSaveCell(original["0"], id, value)
+ onSaveCell(index, original, id, value)
}
const isEditingCell = editCell.length == 2 && editCell[0] === index && editCell[1] === id
diff --git a/frontend/src/components/dbfragments/table/table.tsx b/frontend/src/components/dbfragments/table/table.tsx
index 88582f61..f7e32734 100644
--- a/frontend/src/components/dbfragments/table/table.tsx
+++ b/frontend/src/components/dbfragments/table/table.tsx
@@ -1,12 +1,12 @@
import styles from './table.module.scss'
-import React, { useState, useRef, useContext } from 'react'
+import React, { useState, useContext } from 'react'
import { Cell, useRowSelect, useTable } from 'react-table'
import toast from 'react-hot-toast'
import { DBConnection, DBQueryData, Tab } from '../../../data/models'
import EditableCell from './editablecell'
import AddModal from './addmodal'
import ConfirmModal from '../../widgets/confirmModal'
-import { useAppDispatch, useAppSelector } from '../../../redux/hooks'
+import { useAppDispatch } from '../../../redux/hooks'
import { deleteDBData, setQueryData, updateDBSingleData } from '../../../redux/dataModelSlice'
import { DBConnType } from '../../../data/defaults'
import TabContext from '../../layouts/tabcontext'
@@ -41,7 +41,7 @@ const Table = ({ queryData, dbConnection, mSchema, mName, isEditable, showHeader
[queryData]
)
- const displayColumns = queryData.columns.filter(col => col !== 'ctid')
+ const displayColumns = dbConnection.type === DBConnType.POSTGRES ? queryData.columns.filter(col => col !== 'ctid') : queryData.columns
const ctidExists = queryData.columns.length !== displayColumns.length
const columns = React.useMemo(
@@ -65,14 +65,21 @@ const Table = ({ queryData, dbConnection, mSchema, mName, isEditable, showHeader
setEditCell([])
}
- const onSaveCell = async (ctid: string, columnIdx: string, newValue: string) => {
+ const onSaveCell = async (rowIdx: number, originalValue: any, columnIdx: string, newValue: string) => {
+ if (dbConnection.type === DBConnType.MYSQL && queryData.pkeys?.length === 0) {
+ return toast.error("to perform edit operation primary keys are required on the table!")
+ }
const columnName = queryData.columns[parseInt(columnIdx)]
- const result = await dispatch(updateDBSingleData({ dbConnectionId: dbConnection.id, schemaName: mSchema, name: mName, id: ctid, columnName, newValue, columnIdx })).unwrap()
+ const uniqueId = dbConnection.type === DBConnType.POSTGRES ? originalValue["0"] : JSON.stringify(queryData.pkeys!.map((pkey) => ({ [pkey]: originalValue[queryData.columns.findIndex(x => x === pkey)] })).reduce(((r, c) => Object.assign(r, c)), {}))
+ const result = await dispatch(updateDBSingleData({ dbConnectionId: dbConnection.id, schemaName: mSchema, name: mName, id: uniqueId, columnName, newValue, columnIdx })).unwrap()
if (result.success) {
- const rowIdx = queryData!.rows.findIndex(x => x["0"] === ctid)
if (rowIdx !== -1) {
const newQueryData: DBQueryData = { ...queryData!, rows: [...queryData!.rows] }
- newQueryData!.rows[rowIdx] = { ...newQueryData!.rows[rowIdx], 0: result.data.ctid }
+ if (dbConnection.type === DBConnType.POSTGRES) {
+ newQueryData!.rows[rowIdx] = { ...newQueryData!.rows[rowIdx], 0: result.data.ctid }
+ } else {
+ newQueryData!.rows[rowIdx] = { ...newQueryData!.rows[rowIdx] }
+ }
newQueryData!.rows[rowIdx][columnIdx] = newValue
dispatch(setQueryData({ data: newQueryData, tabId: activeTab.id }))
} else {
@@ -116,11 +123,16 @@ const Table = ({ queryData, dbConnection, mSchema, mName, isEditable, showHeader
const newState: any = state // temporary typescript hack
const selectedRowIds: any = newState.selectedRowIds
const selectedRows: number[] = Object.keys(selectedRowIds).map(x => parseInt(x))
- const selectedCTIDs = rows.filter((_, i) => selectedRows.includes(i)).map(x => x.original['0']).filter(x => x)
+ const selectedIDs = dbConnection.type === DBConnType.POSTGRES ?
+ rows.filter((_, i) => selectedRows.includes(i)).map(x => x.original['0']).filter(x => x)
+ : rows.filter((_, i) => selectedRows.includes(i)).map(x => queryData.pkeys!.map((pkey) => ({ [pkey]: x.original[queryData.columns.findIndex(x => x === pkey)] }))).map(x => x.reduce(((r, c) => Object.assign(r, c)), {})).map(x => JSON.stringify(x))
const deleteRows = async () => {
- if (selectedCTIDs.length > 0) {
- const result = await dispatch(deleteDBData({ dbConnectionId: dbConnection.id, schemaName: mSchema, name: mName, selectedIDs: selectedCTIDs })).unwrap()
+ if (dbConnection.type === DBConnType.MYSQL && queryData.pkeys?.length === 0) {
+ return toast.error("to perform delete operation primary keys are required on the table!")
+ }
+ if (selectedIDs.length > 0) {
+ const result = await dispatch(deleteDBData({ dbConnectionId: dbConnection.id, schemaName: mSchema, name: mName, selectedIDs: selectedIDs })).unwrap()
if (result.success) {
toast.success('rows deleted')
const filteredRows = queryData!.rows.filter((_, i) => !selectedRows.includes(i))
@@ -150,6 +162,11 @@ const Table = ({ queryData, dbConnection, mSchema, mName, isEditable, showHeader
}
onFilterChanged(filter)
}
+ const onFilterClear = () => {
+ let filter: string[] | undefined = undefined
+ setFilterValue(['default', 'default', ''])
+ onFilterChanged(filter)
+ }
const changeSort = (newSortIdx: string) => {
if (!isEditable) {
@@ -216,11 +233,18 @@ const Table = ({ queryData, dbConnection, mSchema, mName, isEditable, showHeader
+ {(filterValue[0] !== 'default' || filterValue[1] !== 'default') &&
+
+
}
{isEditable &&
-
diff --git a/frontend/src/data/models.d.ts b/frontend/src/data/models.d.ts
index cce505ee..df2ff544 100644
--- a/frontend/src/data/models.d.ts
+++ b/frontend/src/data/models.d.ts
@@ -54,6 +54,7 @@ export interface DBQueryData {
keys: string[]
data: any[]
count?: number
+ pkeys?: string[]
}
export interface DBQueryResult {
diff --git a/frontend/src/events/eventService.ts b/frontend/src/events/eventService.ts
index f4ef9ebd..3c6def03 100644
--- a/frontend/src/events/eventService.ts
+++ b/frontend/src/events/eventService.ts
@@ -95,10 +95,10 @@ const deleteDBSingleDataModelIndex = async function (dbConnId: string, schemaNam
return response
}
-const getDBDataInDataModel = async function (dbConnId: string, schemaName: string, mName: string, limit: number, offset: number, fetchCount: boolean, filter?: string[], sort?: string[]): Promise> {
+const getDBDataInDataModel = async function (dbConnId: string, schemaName: string, mName: string, limit: number, offset: number, isFirstFetch: boolean, filter?: string[], sort?: string[]): Promise> {
const responseEventName = Events.GET_DATA.RESPONSE.replaceAll("[schema.name]", schemaName + "." + mName)
const response = responseEvent>(responseEventName)
- EventsEmit(Events.GET_DATA.REQUEST, responseEventName, { dbConnectionId: dbConnId, schema: schemaName, name: mName, fetchCount, limit, offset, filter, sort })
+ EventsEmit(Events.GET_DATA.REQUEST, responseEventName, { dbConnectionId: dbConnId, schema: schemaName, name: mName, isFirstFetch, limit, offset, filter, sort })
return response
}
diff --git a/frontend/src/pages/project/newdb.tsx b/frontend/src/pages/project/newdb.tsx
index f0ac4306..f6f61ea5 100644
--- a/frontend/src/pages/project/newdb.tsx
+++ b/frontend/src/pages/project/newdb.tsx
@@ -24,7 +24,7 @@ const NewDBPage: FunctionComponent<{}> = () => {
const [data, setData] = useState({
dbName: "",
- dbType: DBConnType.POSTGRES ,
+ dbType: DBConnType.POSTGRES,
dbScheme: "",
dbHost: "",
dbPort: "",
@@ -39,13 +39,13 @@ const NewDBPage: FunctionComponent<{}> = () => {
dbUseSSL: false,
})
- const handleChange = (e:React.ChangeEvent) => {
+ const handleChange = (e: React.ChangeEvent) => {
const type = e.target.type
const name = e.target.name
const value = type === "checkbox"
- ? (e.target as HTMLInputElement).checked
+ ? (e.target as HTMLInputElement).checked
: e.target.value
setData(prevData => ({
@@ -81,7 +81,7 @@ const NewDBPage: FunctionComponent<{}> = () => {
sshKeyFile: data.dbSSHKeyFile,
useSSL: data.dbUseSSL,
}
-
+
try {
await dispatch(addNewDBConn(payload)).unwrap()
navigate(Constants.APP_PATHS.PROJECT.path.replace('[id]', project.id))
@@ -97,17 +97,17 @@ const NewDBPage: FunctionComponent<{}> = () => {
handleChange(e)}
- placeholder="Enter a display name for database"
+ placeholder="Enter a display name for database"
/>
-