From 4f1beef160349591bf589280a9c9cddf0542a446 Mon Sep 17 00:00:00 2001 From: Shaurya Sharma <79473274+shaurya-sharma064@users.noreply.github.com> Date: Tue, 9 Jul 2024 12:25:06 +0530 Subject: [PATCH] Fixed issues related to date time data type for TJDB (#10253) * Fixed some issues * Added error borders and fixed some more issues * Added Tooltip for datatype label and added pill for create/edit row * Resolved few more issues * Resolved datetime input text colliding with clear button & create/edit row css collapsing * Import/export for configurations added * Minor Fixes * Fixed calendar not being updated on keydown * Fixed date formatting --- .../DateTimePicker/DateTimePicker.jsx | 109 ++++++++++++++--- .../DateTimePicker/styles.scss | 74 ++++++++++-- .../src/TooljetDatabase/Forms/ColumnForm.jsx | 4 +- .../TooljetDatabase/Forms/EditColumnForm.jsx | 16 +-- .../src/TooljetDatabase/Forms/EditRowForm.jsx | 82 +++++++++++-- .../src/TooljetDatabase/Forms/RowForm.jsx | 114 +++++++++++++++++- .../src/TooljetDatabase/Forms/TableSchema.jsx | 16 ++- .../src/TooljetDatabase/Forms/styles.scss | 6 + .../UniqueConstraintPopOver.jsx | 28 +++++ frontend/src/TooljetDatabase/Table/Header.jsx | 2 +- frontend/src/TooljetDatabase/Table/index.jsx | 34 +++--- .../src/TooljetDatabase/Table/styles.scss | 7 ++ frontend/src/TooljetDatabase/constants.js | 3 +- .../src/_ui/Drawer/DrawerFooter/index.jsx | 3 +- server/src/dto/tooljet-db.dto.ts | 3 +- .../tooljet_db_import_export_service.ts | 6 + 16 files changed, 429 insertions(+), 78 deletions(-) diff --git a/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/DateTimePicker.jsx b/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/DateTimePicker.jsx index eacc2f46c5..40818a3bb9 100644 --- a/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/DateTimePicker.jsx +++ b/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/DateTimePicker.jsx @@ -9,7 +9,8 @@ import { getLocalTimeZone, convertToDateType, formatDate } from '../util'; export const DateTimePicker = ({ enableDate = true, enableTime = true, - format = 'dd/MM/yyyy, h:mm aa', + format = 'dd/MM/yyyy, hh:mm aa', + timeFormat = 'hh:mm aa', isOpenOnStart = false, timestamp = null, setTimestamp, @@ -19,18 +20,28 @@ export const DateTimePicker = ({ saveFunction = () => {}, timezone = getLocalTimeZone(), isClearable = false, + isPlaceholderEnabled = false, + isDisabled = false, + errorMessage, }) => { - const transformedTimestamp = timestamp ? convertToDateType(timestamp, timezone) : null; + const startValue = useRef(timestamp); const timestampRef = useRef(timestamp); const prevTimestampRef = useRef(timestamp || new Date().toISOString()); + const transformedTimestamp = timestamp ? convertToDateType(timestamp, timezone) : null; + const [triggeredKeyPress, setTriggeredKeyPress] = useState(0); + const minDate = new Date(1800, 0, 1); + const maxDate = new Date(2200, 11, 31); const [isOpen, setIsOpen] = useState(isOpenOnStart); const handleKeyDown = (e) => { - if (e.key === 'Escape') { - handleCancel(); - } else if (e.key === 'Enter') { - handleSave(); - setIsOpen(false); + if (isEditCell) { + if (e.key === 'Escape') { + handleCancel(); + timestampRef.current = startValue.current; + setTimestamp(startValue.current); + } else if (e.key === 'Enter') { + handleSave(); + } } e.stopPropagation(); }; @@ -39,8 +50,12 @@ export const DateTimePicker = ({ setIsOpen(false); }; - const handleSave = () => { + const handleSave = (e) => { + if (e) { + e.stopPropagation(); + } saveFunction(timestampRef.current); + startValue.current = timestampRef.current; setIsOpen(false); }; @@ -56,6 +71,12 @@ export const DateTimePicker = ({ setTimestamp(stringifiedTimestamp, isTimeSelect); }; + useEffect(() => { + if (isOpen === false && isEditCell) { + setIsOpen(true); + } + }, [triggeredKeyPress]); + useEffect(() => { const currentTimeInMilliseconds = new Date(timestampRef.current).getTime(); const defaultValueInMilliseconds = new Date(defaultValue).getTime(); @@ -64,6 +85,13 @@ export const DateTimePicker = ({ } }, [timestampRef.current]); + useEffect(() => { + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, []); + const SaveChangesSection = () => { const [isNull, setIsNull] = useState(timestampRef.current === null); const [isDefault, setIsDefault] = useState(timestampRef.current === defaultValue); @@ -189,7 +217,7 @@ export const DateTimePicker = ({ Cancel handleSave(e)} disabled={timestamp == timestampRef.current ? true : false} variant="primary" size="sm" @@ -283,25 +311,45 @@ export const DateTimePicker = ({ }} > { setIsOpen(true); }} isClearable={isClearable} + value={transformedTimestamp} onClickOutside={() => setIsOpen(false)} - placeholderText="DD/MM/YYYY, 12:00pm" + placeholderText="dd/mm/yyyy, 12:00am/pm" selected={transformedTimestamp} + minDate={minDate} + maxDate={maxDate} onChange={(newTimestamp, event) => { if (isEditCell) { handleCellEditChange(newTimestamp); + if (event?.type === 'keydown') { + setTriggeredKeyPress((prev) => prev + 1); + setIsOpen(false); + } } else { if (event) { handleDefaultChange(newTimestamp); - setIsOpen(false); + if (event.type === 'click') { + setIsOpen(false); + } } else { handleDefaultChange(newTimestamp, true); } @@ -314,10 +362,11 @@ export const DateTimePicker = ({ showTimeSelectOnly={enableDate ? false : true} showMonthDropdown showYearDropdown + locale="en-GB" fixedHeight dropdownMode="select" customInput={ - transformedTimestamp ? ( + transformedTimestamp || isPlaceholderEnabled ? ( ) : (
@@ -352,9 +410,22 @@ export const DateTimePicker = ({ } timeInputLabel={
Time
} dateFormat={format} - {...(isEditCell && { calendarContainer: memoizedCustomCalendarContainer, onKeyDown: handleKeyDown })} + timeFormat={timeFormat} + {...(isEditCell && { calendarContainer: memoizedCustomCalendarContainer })} {...(!isEditCell && { calendarContainer: memoizedDefaultCalendarContainer })} /> + {errorMessage && ( + + {errorMessage} + + )}
); }; diff --git a/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/styles.scss b/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/styles.scss index 6329aed02d..95d2ab56e0 100644 --- a/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/styles.scss +++ b/frontend/src/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker/styles.scss @@ -32,10 +32,6 @@ } - - - - .datepicker-widget.theme-tjdb { .react-datepicker-wrapper{ width:100%; @@ -126,20 +122,26 @@ margin-left:20px } -.react-datepicker-wrapper { - position: relative; - padding-left: 8px; - margin-left:8px; - right:16px; + +.tjdb-datepicker-celledit-input{ + padding:0px !important; + font-size: 12px; } .tjdb-datepicker-reset { inset: 0px auto 0px auto; transform: none; margin-top: 0px; - margin-left:14px; } +.tjdb-datepicker-celledit-reset { + inset: 0px auto 0px auto; + transform: none; + margin-top: 0px; + margin-left:-10px; +} + + .tjdb-datepicker-wrapper { width: 101.7%; } @@ -161,3 +163,55 @@ position: relative; } +.input-error-border { + border: 1px solid #DB4324 !important; +} + +.form-control-disabled { + gap: 16px !important; + background: #f4f6fa !important; + border: 1px solid var(--slate7) !important; + border-radius: 6px !important; + margin-bottom: 4px !important; + color: var(--slate11) !important; + transition: none; + width: 100% !important; + padding: 7px 9px !important; + + &:hover { + background: #F1F3F5 !important; + border: 1px solid var(--slate7) !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + outline: none; + } +} + +.dark-form-control-disabled { + gap: 16px !important; + background: var(--base) !important; + border: 1px solid var(--slate7) !important; + border-radius: 6px !important; + margin-bottom: 4px !important; + color: var(--slate12) !important; + transition: none; + width: 100% !important; + padding: 7px 9px !important; + + &:hover { + background: var(--base) !important; + border: 1px solid var(--slate8) !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + outline: none; + } +} + +.null-value-padding { + padding: 0 9px !important; +} + +.input-value-padding { + box-sizing: border-box; + padding-right: 30px !important; +} \ No newline at end of file diff --git a/frontend/src/TooljetDatabase/Forms/ColumnForm.jsx b/frontend/src/TooljetDatabase/Forms/ColumnForm.jsx index 5faa7b5c73..102b59310e 100644 --- a/frontend/src/TooljetDatabase/Forms/ColumnForm.jsx +++ b/frontend/src/TooljetDatabase/Forms/ColumnForm.jsx @@ -20,6 +20,7 @@ import './styles.scss'; import Skeleton from 'react-loading-skeleton'; import DateTimePicker from '@/Editor/QueryManager/QueryEditors/TooljetDatabase/DateTimePicker'; import { getLocalTimeZone, timeZonesWithOffsets } from '@/Editor/QueryManager/QueryEditors/TooljetDatabase/util'; +import defaultStyles from '@/_ui/Select/styles'; const ColumnForm = ({ onCreate, @@ -302,7 +303,7 @@ const ColumnForm = ({ setTimezone(option.value); }} components={{ Option: CustomSelectOption, IndicatorSeparator: () => null }} - styles={customStyles} + styles={defaultStyles(darkMode, '100%')} /> )} @@ -323,6 +324,7 @@ const ColumnForm = ({ setTimestamp={setDefaultValue} timezone={timezone} isClearable={true} + isPlaceholderEnabled={true} /> ) : !foreignKeyDetails?.length > 0 && !isForeignKey ? ( { - if (isTimestamp) { - return ![ - timezone === columnConfigurations?.timezone, - defaultValue === selectedColumn?.column_default, - columnName === selectedColumn?.Header, - ].some((item) => item === false); - } - return true; - }; - const handleCreateForeignKeyinEditMode = async () => { const data = [ { @@ -579,8 +569,8 @@ const ColumnForm = ({ onChange={(option) => { setTimezone(option.value); }} + styles={defaultStyles(darkMode, '100%')} components={{ Option: CustomSelectOption, IndicatorSeparator: () => null }} - styles={customStyles} /> )} @@ -602,6 +592,7 @@ const ColumnForm = ({ setTimestamp={setDefaultValue} timezone={timezone} isClearable={true} + isPlaceholderEnabled={true} /> ) : !isMatchingForeignKeyColumn(selectedColumn?.Header) ? ( { const darkMode = localStorage.getItem('darkMode') === 'true'; - const { organizationId, selectedTable, columns, foreignKeys } = useContext(TooljetDatabaseContext); + const { organizationId, selectedTable, columns, foreignKeys, getConfigurationProperty } = + useContext(TooljetDatabaseContext); const inputRefs = useRef({}); const [fetching, setFetching] = useState(false); const [activeTab, setActiveTab] = useState(Array.isArray(columns) ? columns.map(() => 'Custom') : []); @@ -96,7 +99,7 @@ const EditRowForm = ({ editRowColumns.forEach(({ accessor }) => { if (rowData[accessor] != '') { const inputElement = inputRefs.current[accessor]; - inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFFFFF', 'important'); + inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFFFFF'); setErrorMap((prev) => { return { ...prev, [accessor]: '' }; }); @@ -214,7 +217,7 @@ const EditRowForm = ({ acc.newErrorMap[accessor] = 'Cannot be empty'; const inputElement = inputRefs.current?.[accessor]; - inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7', 'important'); + inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7'); } return acc; }, @@ -248,7 +251,14 @@ const EditRowForm = ({ return { ...prev, [columnName]: 'Value already exists' }; }); const inputElement = inputRefs.current?.[columnName]; - inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7', 'important'); + inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7'); + } else if (error?.code === postgresErrorCode.NotNullViolation) { + const columnName = error?.message.split('.')[1]; + setErrorMap((prev) => { + return { ...prev, [columnName]: 'Cannot be Null' }; + }); + const inputElement = inputRefs.current?.[columnName]; + inputElement?.style?.setProperty('background-color', '#FFF8F7'); } else if (error?.code === postgresErrorCode.DataTypeMismatch) { const errorMessageSplit = error?.message.split(':'); const columnValue = errorMessageSplit[1]?.slice(2, -1); @@ -263,7 +273,7 @@ const EditRowForm = ({ return { ...prev, [accessor]: `Data type mismatch` }; }); const inputElement = inputRefs.current?.[accessor]; - inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7', 'important'); + inputElement?.style?.setProperty('background-color', darkMode ? '#1f2936' : '#FFF8F7'); } }); } @@ -397,13 +407,42 @@ const EditRowForm = ({ case 'timestamp with time zone': return ( -
handleTabClick(index, 'Custom', column_default, isNullable, columnName, dataType)}> +
handleInputChange(index, value, columnName)} isOpenOnStart={false} isClearable={activeTab[index] === 'Custom'} + isPlaceholderEnabled={activeTab[index] === 'Custom'} + errorMessage={errorMap[columnName]} + timezone={getConfigurationProperty(columnName, 'timezone', getLocalTimeZone())} + isDisabled={inputValues[index]?.disabled || shouldInputBeDisabled} /> + {(inputValues[index]?.disabled || shouldInputBeDisabled) && ( +
+ handleDisabledInputClick( + index, + 'Custom', + column_default, + isNullable, + columnName, + dataType, + currentValue[columnName] + ) + } + style={{ + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: 4, + cursor: 'pointer', + backgroundColor: 'transparent', + }} + /> + )}
); @@ -495,12 +534,41 @@ const EditRowForm = ({ {renderDatatypeIcon(isSerialDataTypeColumn ? 'serial' : dataType)} - {headerText} + {headerText}} + show={dataType === 'timestamp with time zone' && headerText.length >= 20} + placement="top" + tooltipClassName="tjdb-table-tooltip" + > + + {headerText} + + {constraints_type?.is_primary_key === true && ( )} + {dataType === 'timestamp with time zone' && ( +
+ {`UTC ${getUTCOffset( + getConfigurationProperty(accessor, 'timezone', getLocalTimeZone()) + )}`} +
+ )} + { return Array.isArray(rowColumns) ? rowColumns.map((item, _index) => { + if (item.dataType === 'timestamp with time zone' && !item.column_default) { + return { value: new Date().toISOString(), checkboxValue: false, disabled: false, label: '' }; + } if (item.accessor === 'id') { return { value: '', checkboxValue: false, disabled: false, label: '' }; } @@ -119,8 +121,18 @@ const RowForm = ({ return matchingColumn; } + const handleDisabledInputClick = (index, tabData, defaultValue, nullValue, columnName, dataType, currentValue) => { + handleTabClick(index, tabData, defaultValue, nullValue, columnName, dataType, currentValue); + if (inputRefs.current[columnName]) { + setTimeout(() => { + inputRefs.current[columnName].focus(); + }, 0); + } + }; + const handleTabClick = (index, tabData, defaultValue, nullValue, columnName, dataType) => { const newActiveTabs = [...activeTab]; + const oldActiveTab = [...activeTab]; newActiveTabs[index] = tabData; setActiveTab(newActiveTabs); const newInputValues = [...inputValues]; @@ -141,6 +153,7 @@ const RowForm = ({ } else if (tabData === 'Custom' && dataType === 'character varying') { newInputValues[index] = { value: '', checkboxValue: false, disabled: false, label: '' }; } else if (tabData === 'Custom' && dataType === 'timestamp with time zone') { + if (oldActiveTab[index] === 'Custom') return; newInputValues[index] = { value: new Date().toISOString(), checkboxValue: false, disabled: false, label: '' }; } else { newInputValues[index] = { value: '', checkboxValue: false, disabled: false, label: '' }; @@ -204,6 +217,11 @@ const RowForm = ({ return result; } + if (column.dataType === 'timestamp with time zone') { + result[column.accessor] = column_default ? column_default : new Date().toISOString(); + return result; + } + result[column.accessor] = column_default ? column_default : ''; return result; }, {}); @@ -263,6 +281,13 @@ const RowForm = ({ }); const inputElement = inputRefs.current?.[columnName]; inputElement?.style?.setProperty('background-color', '#FFF8F7'); + } else if (error?.code === postgresErrorCode.NotNullViolation) { + const columnName = error?.message.split('.')[1]; + setErrorMap((prev) => { + return { ...prev, [columnName]: 'Cannot be Null' }; + }); + const inputElement = inputRefs.current?.[columnName]; + inputElement?.style?.setProperty('background-color', '#FFF8F7'); } else if (error?.message.includes('Invalid input syntax for type')) { const errorMessageSplit = error?.message.split(':'); const columnValue = errorMessageSplit[1]?.slice(2, -1); @@ -368,6 +393,31 @@ const RowForm = ({ ref={(el) => (inputRefs.current[columnName] = el)} /> )} + {inputValues[index]?.disabled && ( +
+ handleDisabledInputClick( + index, + 'Custom', + inputValues[index]?.column_default, + isNullable, + columnName, + dataType, + inputValues[index]?.value + ) + } + style={{ + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: 1, + cursor: 'pointer', + backgroundColor: 'transparent', + }} + /> + )} {inputValues[index].value === null && (

Null

)} @@ -405,14 +455,42 @@ const RowForm = ({ case 'timestamp with time zone': return ( -
handleTabClick(index, 'Custom', defaultValue, isNullable, columnName, dataType)}> +
handleInputChange(index, value, columnName)} isOpenOnStart={false} timezone={getConfigurationProperty(columnName, 'timezone', getLocalTimeZone())} isClearable={activeTab[index] === 'Custom'} + isPlaceholderEnabled={activeTab[index] === 'Custom'} + errorMessage={errorMap[columnName]} + isDisabled={inputValues[index]?.disabled} /> + {inputValues[index]?.disabled && ( +
+ handleDisabledInputClick( + index, + 'Custom', + inputValues[index]?.column_default, + isNullable, + columnName, + dataType, + inputValues[index]?.value + ) + } + style={{ + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: 1, + cursor: 'pointer', + backgroundColor: 'transparent', + }} + /> + )}
); @@ -456,12 +534,40 @@ const RowForm = ({ {renderDatatypeIcon(isSerialDataTypeColumn ? 'serial' : dataType)} - {headerText} + {headerText}} + show={dataType === 'timestamp with time zone' && headerText.length >= 20} + placement="top" + tooltipClassName="tjdb-table-tooltip" + > + + {headerText} + + {constraints_type?.is_primary_key === true && ( )} + {dataType === 'timestamp with time zone' && ( +
+ {`UTC ${getUTCOffset( + getConfigurationProperty(accessor, 'timezone', getLocalTimeZone()) + )}`} +
+ )} { return (
({ + ...provided, + backgroundColor: darkMode ? '#2b3547' : state.menuIsOpen ? '#F1F3F5' : '#fff', + }), + singleValue: (provided) => ({ + ...provided, + color: darkMode ? '#fff' : '#232e3c', + }), + input: (provided) => ({ + ...provided, + color: darkMode ? '#fff' : '#232e3c', + }), + menu: (provided) => ({ + ...provided, + backgroundColor: darkMode ? 'rgb(31,40,55)' : 'white', + }), + option: (provided) => ({ + ...provided, + backgroundColor: darkMode ? '#2b3547' : '#fff', + color: darkMode ? '#fff' : '#232e3c', + cursor: 'pointer', + ':hover': { + backgroundColor: darkMode ? '#323C4B' : '#d8dce9', + }, + }), + }} formatOptionLabel={formatOptionLabel} options={tzOptions} onChange={(option) => { diff --git a/frontend/src/TooljetDatabase/Table/Header.jsx b/frontend/src/TooljetDatabase/Table/Header.jsx index 92a0f41852..e62d5f67a7 100644 --- a/frontend/src/TooljetDatabase/Table/Header.jsx +++ b/frontend/src/TooljetDatabase/Table/Header.jsx @@ -166,7 +166,7 @@ const Header = ({ disabled={false} onClick={() => toggleAddNewDataMenu(true)} size="sm" - className="px-1 pe-3 ps-2 gap-0" + className="px-1 pe-3 ps-2 gap-1" > Add new data diff --git a/frontend/src/TooljetDatabase/Table/index.jsx b/frontend/src/TooljetDatabase/Table/index.jsx index 746caaf540..d5135460d6 100644 --- a/frontend/src/TooljetDatabase/Table/index.jsx +++ b/frontend/src/TooljetDatabase/Table/index.jsx @@ -587,7 +587,7 @@ const Table = ({ collapseSidebar }) => { cellValue === null ? setNullValue(true) : setNullValue(false); setDefaultValue(isCellValueDefault); setEditPopover(true); - document.getElementById('edit-input-blur').focus(); + document?.getElementById('edit-input-blur').focus(); } else if (e.key === 'Backspace' && !editPopover && shouldOpenCellEditMenu(selectedCellRef.current.columnIndex)) { const cellValue = rows[selectedCellRef.current.rowIndex].cells[selectedCellRef.current.columnIndex]?.value; const cellDataType = @@ -616,7 +616,8 @@ const Table = ({ collapseSidebar }) => { }; useEffect(() => { - if (!editPopover) { + const selectedDatatype = headerGroups[0]?.headers?.[selectedCellRef.current.columnIndex]?.dataType; + if (!editPopover && selectedDatatype !== 'timestamp with time zone') { document.addEventListener('keydown', handleKeyDown); } return () => { @@ -1630,21 +1631,22 @@ const Table = ({ collapseSidebar }) => { ); })} - {rows.length > 0 && ( -
{ - resetCellAndRowSelection(); - setIsCreateRowDrawerOpen(true); - }} - className={darkMode ? 'add-icon-row-dark' : 'add-icon-row'} - style={{ - zIndex: 3, - }} - > - + -
- )} +
+ {rows.length > 0 && ( +
{ + resetCellAndRowSelection(); + setIsCreateRowDrawerOpen(true); + }} + className={darkMode ? 'add-icon-row-dark' : 'add-icon-row'} + style={{ + zIndex: 3, + }} + > + + +
+ )} )} {rows.length === 0 && !loadingState && ( diff --git a/frontend/src/TooljetDatabase/Table/styles.scss b/frontend/src/TooljetDatabase/Table/styles.scss index 59593f43ab..d2369c11a1 100644 --- a/frontend/src/TooljetDatabase/Table/styles.scss +++ b/frontend/src/TooljetDatabase/Table/styles.scss @@ -15,11 +15,18 @@ // margin-right: 6px !important; // } +.tj-database-column-header:hover{ + .primaryKeyTooltip{ + width: 88% !important; + } +} + .primaryKeyTooltip { display: flex; align-items: center; justify-content: space-between; width: 100% !important; + height: 100% !important; .table-header-container { white-space: nowrap; diff --git a/frontend/src/TooljetDatabase/constants.js b/frontend/src/TooljetDatabase/constants.js index 7d4ace2dde..10e8ffaaab 100644 --- a/frontend/src/TooljetDatabase/constants.js +++ b/frontend/src/TooljetDatabase/constants.js @@ -264,7 +264,8 @@ export default function tjdbDropdownStyles( backgroundColor: state.isSelected && !darkMode ? '#F0F4FF' : state.isSelected && darkMode ? '#323C4B' : 'transparent', ':hover': { - backgroundColor: state.isFocused && !darkMode ? '#F0F4FF' : '#323C4B', + backgroundColor: + state.isFocused && !darkMode ? '#F0F4FF' : state.isFocused && darkMode ? '#323C4B' : 'transparent', }, color: darkMode ? '#fff' : '#232e3c', cursor: 'pointer', diff --git a/frontend/src/_ui/Drawer/DrawerFooter/index.jsx b/frontend/src/_ui/Drawer/DrawerFooter/index.jsx index 0238deae85..5af6833f3b 100644 --- a/frontend/src/_ui/Drawer/DrawerFooter/index.jsx +++ b/frontend/src/_ui/Drawer/DrawerFooter/index.jsx @@ -29,7 +29,6 @@ function DrawerFooter({ showToolTipForFkOnReadDocsSection = false, foreignKeyDetails = [], initiator, - isButtonDisabledForTimestamp = false, }) { useEffect(() => { const keyboardShortcutStore = useKeyboardShortcutStore.getState(); @@ -222,7 +221,7 @@ function DrawerFooter({ <> {isEditMode && ( ; } export class EditTableColumnsDto { diff --git a/server/src/services/tooljet_db_import_export_service.ts b/server/src/services/tooljet_db_import_export_service.ts index 6a1f174478..59b7acf99f 100644 --- a/server/src/services/tooljet_db_import_export_service.ts +++ b/server/src/services/tooljet_db_import_export_service.ts @@ -26,10 +26,16 @@ export class TooljetDbImportExportService { if (!internalTable) throw new NotFoundException('Tooljet database table not found'); + const { configurations = {} } = internalTable; const { columns, foreign_keys } = await this.tooljetDbService.perform(organizationId, 'view_table', { id: tjDbDto.table_id, }); + columns.forEach((column) => { + const columnUuid = configurations?.columns?.column_names?.[column.column_name]; + column.configurations = configurations?.columns?.configurations?.[columnUuid]; + }); + return { id: internalTable.id, table_name: internalTable.tableName,