diff --git a/CHANGELOG.md b/CHANGELOG.md
index 838e6320e59..902e45537a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,7 +25,6 @@
### Other changes
-- console: disable editing action relationships
- cli: fix typo in cli example for squash (fix #4047) (#4049)
- console: fix run_sql migration modal messaging (close #4020) (#4060)
- docs: add note on pg versions for actions (#4034)
diff --git a/console/src/components/Services/Actions/Relationships/Components/TypeRelationship.js b/console/src/components/Services/Actions/Relationships/Components/TypeRelationship.js
index 70331a77228..562e0e8e32c 100644
--- a/console/src/components/Services/Actions/Relationships/Components/TypeRelationship.js
+++ b/console/src/components/Services/Actions/Relationships/Components/TypeRelationship.js
@@ -138,7 +138,6 @@ const RelationshipEditor = ({
className={`${styles.select} form-control ${styles.add_pad_left}`}
placeholder="Enter relationship name"
data-test="rel-name"
- disabled={isDisabled}
title={relNameInputTitle}
value={name}
/>
@@ -371,7 +370,7 @@ const RelationshipEditor = ({
};
const RelEditor = props => {
- const { dispatch, relConfig, objectType } = props;
+ const { dispatch, relConfig, objectType, isNew } = props;
const [relConfigState, setRelConfigState] = React.useState(null);
@@ -382,7 +381,7 @@ const RelEditor = props => {
{relConfig.name}
- {getRelDef(relConfig)}
+ {getRelDef({ ...relConfig, typename: objectType.name })}
);
@@ -418,20 +417,24 @@ const RelEditor = props => {
);
}
dispatch(
- addActionRel({ ...relConfigState, typename: objectType.name }, toggle)
+ addActionRel(
+ { ...relConfigState, typename: objectType.name },
+ toggle,
+ isNew ? null : relConfig
+ )
);
};
// function to remove the relationship
let removeFunc;
- if (relConfig) {
+ if (!isNew) {
removeFunc = toggle => {
dispatch(removeActionRel(relConfig.name, objectType.name, toggle));
};
}
- const expandButtonText = relConfig ? 'Edit' : 'Add a relationship';
- const collapseButtonText = relConfig ? 'Close' : 'Cancel';
+ const expandButtonText = isNew ? 'Add a relationship' : 'Edit';
+ const collapseButtonText = isNew ? 'Cancel' : 'Close';
return (
);
diff --git a/console/src/components/Services/Actions/Relationships/utils.js b/console/src/components/Services/Actions/Relationships/utils.js
index 98ffc3fd1f6..1533b6669eb 100644
--- a/console/src/components/Services/Actions/Relationships/utils.js
+++ b/console/src/components/Services/Actions/Relationships/utils.js
@@ -76,7 +76,7 @@ export const getRelDef = relMeta => {
? `${relMeta.remote_table.schema}.${relMeta.remote_table.name}`
: relMeta.remote_table;
- return `${lcol} → ${tableLabel} . ${rcol}`;
+ return `${relMeta.typename} . ${lcol} → ${tableLabel} . ${rcol}`;
};
export const removeTypeRelationship = (types, typename, relName) => {
@@ -90,3 +90,15 @@ export const removeTypeRelationship = (types, typename, relName) => {
return t;
});
};
+
+export const validateRelTypename = (types, typename, relname) => {
+ for (let i = types.length - 1; i >= 0; i--) {
+ const type = types[i];
+ if (type.kind === 'object' && type.name === typename) {
+ if ((type.relationships || []).some(r => r.name === relname)) {
+ return `Relationship with name "${relname}" already exists.`;
+ }
+ }
+ }
+ return null;
+};
diff --git a/console/src/components/Services/Actions/ServerIO.js b/console/src/components/Services/Actions/ServerIO.js
index a6f44fdaa88..f50ad0acf74 100644
--- a/console/src/components/Services/Actions/ServerIO.js
+++ b/console/src/components/Services/Actions/ServerIO.js
@@ -22,6 +22,7 @@ import {
import {
injectTypeRelationship,
removeTypeRelationship,
+ validateRelTypename,
} from './Relationships/utils';
import { getConfirmation } from '../../Common/utils/jsUtils';
import {
@@ -406,11 +407,52 @@ export const deleteAction = currentAction => (dispatch, getState) => {
);
};
-export const addActionRel = (relConfig, successCb) => (dispatch, getState) => {
+export const addActionRel = (relConfig, successCb, existingRelConfig) => (
+ dispatch,
+ getState
+) => {
const { types: existingTypes } = getState().types;
- const typesWithRels = injectTypeRelationship(
- existingTypes,
+ let typesWithRels = [...existingTypes];
+
+ let validationError;
+
+ if (existingRelConfig) {
+ // modifying existing relationship
+ // if the relationship is being renamed
+ if (existingRelConfig.name !== relConfig.name) {
+ // validate the new name
+ validationError = validateRelTypename(
+ existingTypes,
+ relConfig.typename,
+ relConfig.name
+ );
+ // remove old relationship from types
+ typesWithRels = removeTypeRelationship(
+ existingTypes,
+ relConfig.typename,
+ existingRelConfig.name
+ );
+ }
+ } else {
+ // creating a new relationship
+
+ // validate the relationship name
+ validationError = validateRelTypename(
+ existingTypes,
+ relConfig.typename,
+ relConfig.name
+ );
+ }
+
+ const errorMsg = 'Saving relationship failed';
+ if (validationError) {
+ return dispatch(showErrorNotification(errorMsg, validationError));
+ }
+
+ // add modified relationship to types
+ typesWithRels = injectTypeRelationship(
+ typesWithRels,
relConfig.typename,
relConfig
);
@@ -426,10 +468,9 @@ export const addActionRel = (relConfig, successCb) => (dispatch, getState) => {
const upQueries = [customTypesQueryUp];
const downQueries = [customTypesQueryDown];
- const migrationName = 'add_action_rel'; // TODO: better migration name
- const requestMsg = 'Adding relationship...';
- const successMsg = 'Relationship added successfully';
- const errorMsg = 'Adding relationship failed';
+ const migrationName = `save_rel_${relConfig.name}_on_${relConfig.typename}`;
+ const requestMsg = 'Saving relationship...';
+ const successMsg = 'Relationship saved successfully';
const customOnSuccess = () => {
// dispatch(createActionRequestComplete());
dispatch(fetchCustomTypes());