Skip to content

Commit

Permalink
Fix : Bugs from Foreign key feature (#9552)
Browse files Browse the repository at this point in the history
* Added tooltip when add relation button is disabled

* Set the values to no actions by default for action dropdowns

* Added tootip for add relation button when disabled

* Updated the UI of dropdowns in the actions section of foreign key drawer

* Disable the add relation button when less than 2 table are  present in edit mode and less than 1 in create mode

* Updated the logic to render option description in actions dropdown and highlight table names

* Adding conditional chaining to avoid app getting crashed

* Avoding showing toast message for crating foreign key in create column and table mode

* Updated tooltip description for add relation button

Added full stops to descriptions of options in actions dropdown

* Show tooltip on read docs regarding fk for column and table operations

* Updated description of foreign key relation text in create/edit table drawer

* Updated description of foreign key relation text in create/edit column drawer

* Type error fixed

* Show unuqie constaint info UI update

* Added copyrights for foreign keys
  • Loading branch information
manishkushare committed May 7, 2024
1 parent 1ad591c commit cfe980b
Show file tree
Hide file tree
Showing 15 changed files with 418 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ const DropDownSelect = ({
setReferencedColumnDetails,
shouldShowForeignKeyIcon = false,
cellColumnName,
tableName,
targetTable,
actions,
actionName,
fetchTables,
onTableClick,
}) => {
Expand Down Expand Up @@ -171,6 +175,10 @@ const DropDownSelect = ({
setTotalRecords={setTotalRecords}
pageNumber={pageNumber}
setPageNumber={setPageNumber}
tableName={tableName}
targetTable={targetTable}
actions={actions}
actionName={actionName}
/>
</Popover>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ function DataSourceSelect({
setTotalRecords,
pageNumber,
setPageNumber,
tableName,
targetTable,
actions,
actionName,
}) {
const [isLoadingFKDetails, setIsLoadingFKDetails] = useState(false);
const [searchValue, setSearchValue] = useState('');
Expand Down Expand Up @@ -240,11 +244,11 @@ function DataSourceSelect({
<div
style={{
display: 'flex',
justifyContent: showRedirection || showDescription ? 'space-between' : 'flex-start',
justifyContent: showRedirection ? 'space-between' : 'flex-start',
alignItems: 'center',
cursor: foreignKeyAccess && props.data.isDisabled && 'not-allowed',
}}
className="dd-select-option"
className={`dd-select-option ${showDescription && 'h-100'}`}
>
{isMulti && (
<div
Expand Down Expand Up @@ -283,9 +287,6 @@ function DataSourceSelect({
})}
>
{children}
{foreignKeyAccess && showDescription && (
<span className="action-description">{props.data.label}</span>
)}
</span>

{foreignKeyAccess && showRedirection && props.isFocused && (
Expand Down Expand Up @@ -329,23 +330,76 @@ function DataSourceSelect({
},
// }),
MenuList: useCallback(
(props) => (
<MenuList
{...props}
onAdd={onAdd}
addBtnLabel={addBtnLabel}
emptyError={emptyError}
foreignKeyAccess={foreignKeyAccess}
columnInfoForTable={columnInfoForTable}
showColumnInfo={showColumnInfo}
foreignKeyAccessInRowForm={foreignKeyAccessInRowForm}
scrollEventForColumnValus={scrollEventForColumnValus}
scrollContainerRef={scrollContainerRef}
foreignKeys={foreignKeys}
cellColumnName={cellColumnName}
isLoadingFKDetails={isLoadingFKDetails}
/>
),
(props) => {
const selectedOption =
props &&
props.children &&
Array.isArray(props.children) &&
props?.children?.reduce((accumulator, reactElement) => {
const props = reactElement?.props ?? {};
if (props?.isSelected) {
accumulator = { ...props?.data };
}
return accumulator;
}, {});
const focusedOption =
props &&
props.children &&
Array.isArray(props.children) &&
props?.children?.reduce((accumulator, reactElement) => {
const props = reactElement?.props ?? {};
if (props?.isFocused) {
accumulator = { ...props?.data };
}
return accumulator;
}, {});

return (
<React.Fragment>
<MenuList
{...props}
onAdd={onAdd}
addBtnLabel={addBtnLabel}
emptyError={emptyError}
foreignKeyAccess={foreignKeyAccess}
columnInfoForTable={columnInfoForTable}
showColumnInfo={showColumnInfo}
foreignKeyAccessInRowForm={foreignKeyAccessInRowForm}
scrollEventForColumnValus={scrollEventForColumnValus}
scrollContainerRef={scrollContainerRef}
foreignKeys={foreignKeys}
cellColumnName={cellColumnName}
isLoadingFKDetails={isLoadingFKDetails}
/>
{foreignKeyAccess && showDescription && actions && (
<>
<div style={{ borderTop: '1px solid var(--slate5)' }}></div>
<div
style={{
minHeight: '140px',
height: 'fit-content',
padding: '8px 12px',
}}
>
<div className="tj-header-h8 tj-text">
{!isEmpty(focusedOption) ? focusedOption?.label : selectedOption?.label}
</div>
<span className="tj-text-xsm" style={{ color: 'var(--slate9)' }}>
{
<GenerateActionsDescription
targetTable={targetTable?.value || targetTable?.label || targetTable?.name}
sourceTable={tableName}
actionName={actionName}
label={!isEmpty(focusedOption) ? focusedOption?.label : selectedOption?.label}
/>
}
</span>
</div>
</>
)}
</React.Fragment>
);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[onAdd, addBtnLabel, emptyError]
),
Expand Down Expand Up @@ -578,4 +632,116 @@ const CustomGroupHeading = (props) => {
);
};

const GenerateActionsDescription = ({ targetTable, sourceTable, actionName = '', label }) => {
const isActionOnUpdate = actionName === 'On update';

const Description = Object.freeze({
noAction: isActionOnUpdate ? (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will not be permitted for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
) : (
<>
Deleting a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will not be permitted for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
),
cascade: isActionOnUpdate ? (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will also update any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
) : (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will also delete any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
),
restrict: isActionOnUpdate ? (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will not be permitted for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
<br />
It is similar to NO ACTION but NO ACTION allows the check to be deferred until later in the transaction, whereas
RESTRICT does not.
</>
) : (
<>
Deleting a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will not be permitted for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table. <br />
It is similar to NO ACTION but NO ACTION allows the check to be deferred until later in the transaction, whereas
RESTRICT does not.
</>
),
setNull: isActionOnUpdate ? (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will set the NULL value for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
) : (
<>
Deleting a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will set the NULL value for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
),
setDefault: isActionOnUpdate ? (
<>
Updating a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will set the default value for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
) : (
<>
Deleting a record from{' '}
<span className="action-description-highlighter">{targetTable ? targetTable : '< target table name >'}</span>{' '}
table will set the default value for any records that references it in{' '}
<span className="action-description-highlighter">{sourceTable ? sourceTable : '< source table name >'}</span>{' '}
table.
</>
),
});

switch (label) {
case 'NO ACTION':
return Description.noAction;
case 'RESTRICT':
return Description.restrict;
case 'CASCADE':
return Description.cascade;
case 'SET NULL':
return Description.setNull;
case 'SET DEFAULT':
return Description.setDefault;
default:
break;
}
};

export default DataSourceSelect;
14 changes: 10 additions & 4 deletions frontend/src/TooljetDatabase/Forms/ColumnForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ const ColumnForm = ({

const handleCreateForeignKey = () => {
setIsForeignKeyDraweOpen(false);
toast.success(`Foreign key Added successfully for selected column`);
// toast.success(`Foreign key Added successfully for selected column`);
};

const referenceTableDetails = referencedColumnDetails?.map((item) => {
Expand Down Expand Up @@ -348,7 +348,9 @@ const ColumnForm = ({
</ToolTip>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">Foreign Key relation</p>
<p className="fw-400 secondary-text mb-2">Add foreign key to check referral integrity</p>
<p className="fw-400 secondary-text tj-text-xsm mb-2">
Adding a foreign key relation will link this column with a column in an existing table.
</p>
{foreignKeyDetails?.length > 0 &&
isForeignKey &&
foreignKeyDetails?.map((detail, index) => (
Expand All @@ -368,6 +370,9 @@ const ColumnForm = ({
</div>
</div>
))}
{foreignKeyDetails?.length > 0 && (
<p className="fw-400 secondary-text tj-text-xsm mb-2">Create column to add foreign key relation</p>
)}
</div>
</div>

Expand Down Expand Up @@ -424,7 +429,7 @@ const ColumnForm = ({
</div>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">{isNotNull ? 'NOT NULL' : 'NULL'}</p>
<p className="fw-400 secondary-text">
<p className="fw-400 secondary-text tj-text-xsm mb-2">
{isNotNull ? 'Not null constraint is added' : 'This field can accept NULL value'}
</p>
</div>
Expand All @@ -446,7 +451,7 @@ const ColumnForm = ({
</div>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">{isUniqueConstraint ? 'UNIQUE' : 'NOT UNIQUE'}</p>
<p className="fw-400 secondary-text">
<p className="fw-400 secondary-text tj-text-xsm">
{isUniqueConstraint ? 'Unique value constraint is added' : 'Unique value constraint is not added'}
</p>
</div>
Expand All @@ -461,6 +466,7 @@ const ColumnForm = ({
isEmpty(dataType) ||
(isNotNull === true && rows.length > 0 && isEmpty(defaultValue) && dataType?.value !== 'serial')
}
showToolTipForFkOnReadDocsSection={true}
/>
<ConfirmDialog
title={'Delete foreign key'}
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/TooljetDatabase/Forms/EditColumnForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,9 @@ const ColumnForm = ({
</ToolTip>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">Foreign Key relation</p>
<p className="fw-400 secondary-text mb-2">Add foreign key to check referral integrity</p>
<p className="fw-400 secondary-text tj-text-xsm mb-2">
Adding a foreign key relation will link this column with a column in an existing table.
</p>
{foreignKeyDetails?.length > 0 && isMatchingForeignKeyColumn(selectedColumn?.Header) && isForeignKey && (
<div className="foreignKey-details mt-0">
<span className="foreignKey-text">
Expand Down Expand Up @@ -707,7 +709,7 @@ const ColumnForm = ({
</div>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">{isNotNull ? 'NOT NULL' : 'NULL'}</p>
<p className="fw-400 secondary-text">
<p className="fw-400 secondary-text tj-text-xsm mb-2">
{isNotNull ? 'Not null constraint is added' : 'This field can accept NULL value'}
</p>
</div>
Expand Down Expand Up @@ -753,7 +755,7 @@ const ColumnForm = ({
</div>
<div className="col d-flex flex-column">
<p className="m-0 p-0 fw-500">{isUniqueConstraint ? 'UNIQUE' : 'NOT UNIQUE'}</p>
<p className="fw-400 secondary-text">
<p className="fw-400 secondary-text tj-text-xsm">
{isUniqueConstraint ? 'Unique value constraint is added' : 'Unique value constraint is not added'}
</p>
</div>
Expand All @@ -766,6 +768,7 @@ const ColumnForm = ({
onClose={onClose}
onEdit={handleEdit}
shouldDisableCreateBtn={columnName === ''}
showToolTipForFkOnReadDocsSection={true}
/>
</div>
<ConfirmDialog
Expand Down

0 comments on commit cfe980b

Please sign in to comment.