Files
twenty/packages/twenty-front/src/modules/activities/notes/components/Notes.tsx
T
Joseph Chiang 9e49e87646 fix: correct inverted permission checks for create buttons (fix #12581) (#12614)
## Summary
This PR fixes inverted permission checks that were preventing authorized
users from seeing "Add New" and "Add note" buttons while showing them to
unauthorized users.

## Changes
- Fixed permission check in `SingleRecordPickerMenuItemsWithSearch`
component (2 locations)
- Fixed permission check in `Notes` component

## Issue
These permission checks were incorrectly using
`\!hasObjectUpdatePermissions` (NOT has permissions) when they should
have been checking `hasObjectUpdatePermissions` (has permissions).

This is similar to the issue mentioned in PR #12437.

## Test plan
- [ ] Verify that users WITH update permissions can see the "Add New"
button in record pickers
- [ ] Verify that users WITHOUT update permissions cannot see the "Add
New" button
- [ ] Verify that users WITH update permissions can see the "Add note"
button in Notes component
- [ ] Verify that users WITHOUT update permissions cannot see the "Add
note" button

🤖 Generated with Claude Code (https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-06-16 10:02:53 +02:00

111 lines
3.3 KiB
TypeScript

import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { NoteList } from '@/activities/notes/components/NoteList';
import { useNotes } from '@/activities/notes/hooks/useNotes';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
import styled from '@emotion/styled';
import { IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import {
AnimatedPlaceholder,
AnimatedPlaceholderEmptyContainer,
AnimatedPlaceholderEmptySubTitle,
AnimatedPlaceholderEmptyTextContainer,
AnimatedPlaceholderEmptyTitle,
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
} from 'twenty-ui/layout';
const StyledNotesContainer = styled.div`
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
overflow: auto;
`;
export const Notes = ({
targetableObject,
}: {
targetableObject: ActivityTargetableObject;
}) => {
const { notes, loading } = useNotes(targetableObject);
const openCreateActivity = useOpenCreateActivityDrawer({
activityObjectNameSingular: CoreObjectNameSingular.Note,
});
const isNotesEmpty = !notes || notes.length === 0;
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular: targetableObject.targetObjectNameSingular,
});
const objectPermissions = useObjectPermissionsForObject(
objectMetadataItem.id,
);
const hasObjectUpdatePermissions = objectPermissions.canUpdateObjectRecords;
if (loading && isNotesEmpty) {
return <SkeletonLoader />;
}
if (isNotesEmpty) {
return (
<AnimatedPlaceholderEmptyContainer
// eslint-disable-next-line react/jsx-props-no-spreading
{...EMPTY_PLACEHOLDER_TRANSITION_PROPS}
>
<AnimatedPlaceholder type="noNote" />
<AnimatedPlaceholderEmptyTextContainer>
<AnimatedPlaceholderEmptyTitle>
No notes
</AnimatedPlaceholderEmptyTitle>
<AnimatedPlaceholderEmptySubTitle>
There are no associated notes with this record.
</AnimatedPlaceholderEmptySubTitle>
</AnimatedPlaceholderEmptyTextContainer>
{hasObjectUpdatePermissions && (
<Button
Icon={IconPlus}
title="New note"
variant="secondary"
onClick={() =>
openCreateActivity({
targetableObjects: [targetableObject],
})
}
/>
)}
</AnimatedPlaceholderEmptyContainer>
);
}
return (
<StyledNotesContainer>
<NoteList
title="All"
notes={notes}
button={
hasObjectUpdatePermissions && (
<Button
Icon={IconPlus}
size="small"
variant="secondary"
title="Add note"
onClick={() =>
openCreateActivity({
targetableObjects: [targetableObject],
})
}
/>
)
}
/>
</StyledNotesContainer>
);
};