-
Notifications
You must be signed in to change notification settings - Fork 228
feat(data-modeling): add rename collection to side panel COMPASS-9658 #7174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b63e03c
975bb26
c483f82
15ad8fc
0a62d72
19ca3c9
e4d0f09
e8c49a9
73976e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import React from 'react'; | ||
import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import toNS from 'mongodb-ns'; | ||
import type { Relationship } from '../../services/data-model-storage'; | ||
import { | ||
Badge, | ||
|
@@ -15,6 +16,7 @@ import { | |
import { | ||
createNewRelationship, | ||
deleteRelationship, | ||
renameCollection, | ||
selectCurrentModelFromState, | ||
selectRelationship, | ||
updateCollectionNote, | ||
|
@@ -29,12 +31,14 @@ import { useChangeOnBlur } from './use-change-on-blur'; | |
|
||
type CollectionDrawerContentProps = { | ||
namespace: string; | ||
namespaces: string[]; | ||
note?: string; | ||
relationships: Relationship[]; | ||
onCreateNewRelationshipClick: (namespace: string) => void; | ||
onEditRelationshipClick: (rId: string) => void; | ||
onDeleteRelationshipClick: (rId: string) => void; | ||
note?: string; | ||
onNoteChange: (namespace: string, note: string) => void; | ||
onRenameCollection: (fromNS: string, toNS: string) => void; | ||
}; | ||
|
||
const titleBtnStyles = css({ | ||
|
@@ -70,17 +74,77 @@ const relationshipContentStyles = css({ | |
marginTop: spacing[400], | ||
}); | ||
|
||
export function getIsCollectionNameValid( | ||
collectionName: string, | ||
namespaces: string[], | ||
namespace: string | ||
): { | ||
isValid: boolean; | ||
errorMessage?: string; | ||
} { | ||
if (collectionName.trim().length === 0) { | ||
return { | ||
isValid: false, | ||
errorMessage: 'Collection name cannot be empty.', | ||
}; | ||
} | ||
|
||
const namespacesWithoutCurrent = namespaces.filter((ns) => ns !== namespace); | ||
|
||
const isDuplicate = namespacesWithoutCurrent.some( | ||
(ns) => | ||
ns === `${toNS(namespace).database}.${collectionName}` || | ||
ns === `${toNS(namespace).database}.${collectionName.trim()}` | ||
); | ||
|
||
return { | ||
isValid: !isDuplicate, | ||
errorMessage: isDuplicate ? 'Collection name must be unique.' : undefined, | ||
}; | ||
} | ||
|
||
const CollectionDrawerContent: React.FunctionComponent< | ||
CollectionDrawerContentProps | ||
> = ({ | ||
namespace, | ||
namespaces, | ||
note = '', | ||
relationships, | ||
onCreateNewRelationshipClick, | ||
onEditRelationshipClick, | ||
onDeleteRelationshipClick, | ||
note = '', | ||
onNoteChange, | ||
onRenameCollection, | ||
}) => { | ||
const [collectionName, setCollectionName] = useState( | ||
() => toNS(namespace).collection | ||
); | ||
|
||
const { | ||
isValid: isCollectionNameValid, | ||
errorMessage: collectionNameEditErrorMessage, | ||
} = useMemo( | ||
() => getIsCollectionNameValid(collectionName, namespaces, namespace), | ||
[collectionName, namespaces, namespace] | ||
); | ||
|
||
useLayoutEffect(() => { | ||
setCollectionName(toNS(namespace).collection); | ||
}, [namespace]); | ||
|
||
const onBlurCollectionName = useCallback(() => { | ||
const trimmedName = collectionName.trim(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just FYI, added a shared hook for that in another PR when adding notes #7171 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good mention, I was thinking about using this, however we have some additional logic around the invalid states. It felt like it would be passing around too many things or keep two collection name state around. Maybe there is something we could do for the validation to have it nicely wrapped in. Not going to include in this pr. This'll come up again in field renaming as well so we can take another look there. |
||
if (trimmedName === toNS(namespace).collection) { | ||
return; | ||
} | ||
|
||
if (!isCollectionNameValid) { | ||
return; | ||
} | ||
|
||
onRenameCollection(namespace, `${toNS(namespace).database}.${trimmedName}`); | ||
}, [collectionName, namespace, onRenameCollection, isCollectionNameValid]); | ||
|
||
const noteInputProps = useChangeOnBlur(note, (newNote) => { | ||
onNoteChange(namespace, newNote); | ||
}); | ||
|
@@ -92,8 +156,13 @@ const CollectionDrawerContent: React.FunctionComponent< | |
<TextInput | ||
label="Name" | ||
sizeVariant="small" | ||
value={namespace} | ||
disabled={true} | ||
value={collectionName} | ||
state={isCollectionNameValid ? undefined : 'error'} | ||
errorMessage={collectionNameEditErrorMessage} | ||
onChange={(e) => { | ||
setCollectionName(e.target.value); | ||
}} | ||
onBlur={onBlurCollectionName} | ||
/> | ||
</DMFormFieldContainer> | ||
</DMDrawerSection> | ||
|
@@ -175,6 +244,7 @@ export default connect( | |
model.collections.find((collection) => { | ||
return collection.ns === ownProps.namespace; | ||
})?.note ?? '', | ||
namespaces: model.collections.map((c) => c.ns), | ||
relationships: model.relationships.filter((r) => { | ||
const [local, foreign] = r.relationship; | ||
return ( | ||
|
@@ -188,5 +258,6 @@ export default connect( | |
onEditRelationshipClick: selectRelationship, | ||
onDeleteRelationshipClick: deleteRelationship, | ||
onNoteChange: updateCollectionNote, | ||
onRenameCollection: renameCollection, | ||
} | ||
)(CollectionDrawerContent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The duplicate check logic is redundant - checking both trimmed and untrimmed versions when the second condition will always include the first. Consider simplifying to only check the trimmed version.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, obviously Copilot's suggestion behaves differently from the current logic, but I think you could actually condense this into a single condition if you want to, e.g.