Skip to content

Commit

Permalink
Merge branch 'twentyhq:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ducksblock authored Feb 16, 2024
2 parents c153e42 + 990cb10 commit 7b68132
Show file tree
Hide file tree
Showing 50 changed files with 746 additions and 379 deletions.
4 changes: 3 additions & 1 deletion packages/twenty-docker/prod/twenty-website/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ WORKDIR /app/packages/twenty-website

COPY --from=twenty-website-build /app /app

WORKDIR /app/packages/twenty-website

LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the website."

CMD ["/bin/sh", "-c", "yarn nx start twenty-website"]
CMD ["/bin/sh", "-c", "yarn nx start"]

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type BlocklistItem = {
id: string;
handle: string;
workspaceMemberId: string;
createdAt: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export enum CoreObjectNameSingular {
ActivityTarget = 'activityTarget',
ApiKey = 'apiKey',
Attachment = 'attachment',
Blocklist = 'blocklist',
Comment = 'comment',
Company = 'company',
ConenctedAccount = 'conenctedAccount',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ describe('useFindManyRecords', () => {
setCurrentWorkspaceMember({
id: '32219445-f587-4c40-b2b1-6d3205ed96da',
name: { firstName: 'John', lastName: 'Connor' },
locale: 'en',
});

const mockObjectMetadataItems = getObjectMetadataItemsMock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { LightIconButton, MenuItem } from 'tsup.ui.index';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { RecordChip } from '@/object-record/components/RecordChip';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord.ts';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { usePersistField } from '@/object-record/record-field/hooks/usePersistField';
import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { IconDotsVertical, IconUnlink } from '@/ui/display/icon';
import { IconDotsVertical, IconTrash, IconUnlink } from '@/ui/display/icon';
import { CardContent } from '@/ui/layout/card/components/CardContent';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
Expand Down Expand Up @@ -75,6 +76,10 @@ export const RecordRelationFieldCardContent = ({
objectNameSingular: relationObjectMetadataNameSingular,
});

const { deleteOneRecord: deleteOneRelationRecord } = useDeleteOneRecord({
objectNameSingular: relationObjectMetadataNameSingular,
});

const dropdownScopeId = `record-field-card-menu-${relationRecord.id}`;

const { closeDropdown, isDropdownOpen } = useDropdown(dropdownScopeId);
Expand All @@ -101,13 +106,22 @@ export const RecordRelationFieldCardContent = ({
});
};

const handleDelete = async () => {
closeDropdown();
await deleteOneRelationRecord(relationRecord.id);
};

const isOpportunityCompanyRelation =
(objectMetadataNameSingular === CoreObjectNameSingular.Opportunity &&
relationObjectMetadataNameSingular === CoreObjectNameSingular.Company) ||
(objectMetadataNameSingular === CoreObjectNameSingular.Company &&
relationObjectMetadataNameSingular ===
CoreObjectNameSingular.Opportunity);

const isAccountOwnerRelation =
relationObjectMetadataNameSingular ===
CoreObjectNameSingular.WorkspaceMember;

return (
<StyledCardContent isDropdownOpen={isDropdownOpen} divider={divider}>
<RecordChip
Expand All @@ -134,6 +148,14 @@ export const RecordRelationFieldCardContent = ({
text="Detach"
onClick={handleDetach}
/>
{!isAccountOwnerRelation && (
<MenuItem
LeftIcon={IconTrash}
text="Delete"
accent="danger"
onClick={handleDelete}
/>
)}
</DropdownMenuItemsContainer>
}
dropdownHotkeyScope={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { TextInput } from '@/ui/input/components/TextInput';
const StyledContainer = styled.div`
display: flex;
flex-direction: row;
margin-bottom: 16px;
`;

const StyledLinkContainer = styled.div`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
import { useState } from 'react';
import { v4 } from 'uuid';
import { useRecoilValue } from 'recoil';

import { BlocklistItem } from '@/accounts/types/BlocklistItem';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsAccountsEmailsBlocklistInput } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistInput';
import { SettingsAccountsEmailsBlocklistTable } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTable';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Section } from '@/ui/layout/section/components/Section';
import { mockedBlockedEmailList } from '~/testing/mock-data/accounts';
import { formatDate } from '~/utils/date-utils';

export const SettingsAccountsEmailsBlocklistSection = () => {
const [blockedEmailList, setBlockedEmailList] = useState(
mockedBlockedEmailList,
);
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);

const { records: blocklist } = useFindManyRecords<BlocklistItem>({
objectNameSingular: CoreObjectNameSingular.Blocklist,
});

const { createOneRecord: createBlocklistItem } =
useCreateOneRecord<BlocklistItem>({
objectNameSingular: CoreObjectNameSingular.Blocklist,
});

const { deleteOneRecord: deleteBlocklistItem } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.Blocklist,
});

const handleBlockedEmailRemove = (id: string) => {
deleteBlocklistItem(id);
};

const updateBlockedEmailList = (handle: string) => {
createBlocklistItem({
handle,
workspaceMemberId: currentWorkspaceMember?.id,
});
};

const handleBlockedEmailRemove = (id: string) =>
setBlockedEmailList((previousBlockedEmailList) =>
previousBlockedEmailList.filter((blockedEmail) => blockedEmail.id !== id),
);

const updateBlockedEmailList = (email: string) =>
setBlockedEmailList((prevState) => [
...prevState,
{
id: v4(),
email: email,
blocked_at: formatDate(new Date(), 'dd/LL/yyyy'),
},
]);
return (
<Section>
<H2Title
Expand All @@ -37,7 +48,7 @@ export const SettingsAccountsEmailsBlocklistSection = () => {
updateBlockedEmailList={updateBlockedEmailList}
/>
<SettingsAccountsEmailsBlocklistTable
blockedEmailList={blockedEmailList}
blocklist={blocklist}
handleBlockedEmailRemove={handleBlockedEmailRemove}
/>
</Section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,49 @@
import styled from '@emotion/styled';

import { BlockedEmail } from '@/accounts/types/BlockedEmail';
import { BlocklistItem } from '@/accounts/types/BlocklistItem';
import { SettingsAccountsEmailsBlocklistTableRow } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistTableRow';
import { Table } from '@/ui/layout/table/components/Table';
import { TableBody } from '@/ui/layout/table/components/TableBody';
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
import { TableRow } from '@/ui/layout/table/components/TableRow';

type SettingsAccountsEmailsBlocklistTableProps = {
blockedEmailList: BlockedEmail[];
blocklist: BlocklistItem[];
handleBlockedEmailRemove: (id: string) => void;
};

const StyledTable = styled(Table)`
margin-top: ${({ theme }) => theme.spacing(4)};
`;

const StyledTableBody = styled(TableBody)`
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
`;

export const SettingsAccountsEmailsBlocklistTable = ({
blockedEmailList,
blocklist,
handleBlockedEmailRemove,
}: SettingsAccountsEmailsBlocklistTableProps) => {
return (
<Table>
<TableRow>
<TableHeader>Email/Domain</TableHeader>
<TableHeader>Added to blocklist</TableHeader>
<TableHeader></TableHeader>
</TableRow>
<StyledTableBody>
{blockedEmailList.map((blockedEmail) => (
<SettingsAccountsEmailsBlocklistTableRow
key={blockedEmail.id}
blockedEmail={blockedEmail}
onRemove={handleBlockedEmailRemove}
/>
))}
</StyledTableBody>
</Table>
<>
{blocklist.length > 0 && (
<StyledTable>
<TableRow>
<TableHeader>Email/Domain</TableHeader>
<TableHeader>Added to blocklist</TableHeader>
<TableHeader></TableHeader>
</TableRow>
<StyledTableBody>
{blocklist.map((blocklistItem) => (
<SettingsAccountsEmailsBlocklistTableRow
key={blocklistItem.id}
blocklistItem={blocklistItem}
onRemove={handleBlockedEmailRemove}
/>
))}
</StyledTableBody>
</StyledTable>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { BlockedEmail } from '@/accounts/types/BlockedEmail';
import { BlocklistItem } from '@/accounts/types/BlocklistItem';
import { IconX } from '@/ui/display/icon';
import { IconButton } from '@/ui/input/button/components/IconButton';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { formatToHumanReadableDate } from '~/utils';

type SettingsAccountsEmailsBlocklistTableRowProps = {
blockedEmail: BlockedEmail;
blocklistItem: BlocklistItem;
onRemove: (id: string) => void;
};

export const SettingsAccountsEmailsBlocklistTableRow = ({
blockedEmail,
blocklistItem,
onRemove,
}: SettingsAccountsEmailsBlocklistTableRowProps) => {
return (
<TableRow key={blockedEmail.id}>
<TableCell>{blockedEmail.email}</TableCell>
<TableCell>{blockedEmail.blocked_at}</TableCell>
<TableRow key={blocklistItem.id}>
<TableCell>{blocklistItem.handle}</TableCell>
<TableCell>
{formatToHumanReadableDate(blocklistItem.createdAt)}
</TableCell>
<TableCell align="right">
<IconButton
onClick={() => {
onRemove(blockedEmail.id);
onRemove(blocklistItem.id);
}}
variant="tertiary"
size="small"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type FeatureFlagKey =
| 'IS_MESSAGING_ENABLED'
| 'IS_BLOCKLIST_ENABLED'
| 'IS_INTEGRATIONS_ENABLED'
| 'IS_QUICK_ACTIONS_ENABLED'
| 'IS_NEW_RECORD_BOARD_ENABLED';
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { ConnectedAccount } from '@/accounts/types/ConnectedAccount';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { SettingsAccountsConnectedAccountsSection } from '@/settings/accounts/components/SettingsAccountsConnectedAccountsSection';
import { SettingsAccountsEmailsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistSection';
import { SettingsAccountsSettingsSection } from '@/settings/accounts/components/SettingsAccountsSettingsSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { IconSettings } from '@/ui/display/icon';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { SettingsAccountLoader } from '~/pages/settings/accounts/SettingsAccountLoader';

export const SettingsAccounts = () => {
Expand All @@ -23,6 +25,8 @@ export const SettingsAccounts = () => {
},
});

const isBlocklistEnabled = useIsFeatureEnabled('IS_BLOCKLIST_ENABLED');

return (
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
<SettingsPageContainer
Expand All @@ -39,6 +43,7 @@ export const SettingsAccounts = () => {
) : (
<>
<SettingsAccountsConnectedAccountsSection accounts={accounts} />
{isBlocklistEnabled && <SettingsAccountsEmailsBlocklistSection />}
<SettingsAccountsSettingsSection />
</>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { SettingsAccountsEmailsBlocklistSection } from '@/settings/accounts/components/SettingsAccountsEmailsBlocklistSection';
import { SettingsAccountsEmailsSyncSection } from '@/settings/accounts/components/SettingsAccountsEmailsSyncSection';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { IconSettings } from '@/ui/display/icon';
Expand All @@ -15,7 +14,6 @@ export const SettingsAccountsEmails = () => (
]}
/>
<SettingsAccountsEmailsSyncSection />
<SettingsAccountsEmailsBlocklistSection />
</SettingsPageContainer>
</SubMenuTopBarContainer>
);
38 changes: 0 additions & 38 deletions packages/twenty-front/src/testing/mock-data/accounts.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/twenty-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@
"@ptc-org/nestjs-query-graphql": "patch:@ptc-org/nestjs-query-graphql@4.2.0#./patches/@ptc-org+nestjs-query-graphql+4.2.0.patch",
"class-validator": "patch:class-validator@0.14.0#./patches/class-validator+0.14.0.patch",
"graphql-middleware": "^6.1.35",
"lodash.isequal": "^4.5.0",
"passport": "^0.7.0"
},
"devDependencies": {
"@nestjs/cli": "10.3.0",
"@nx/js": "17.2.8",
"@types/lodash.isempty": "^4.4.7",
"@types/lodash.isequal": "^4.5.8",
"@types/lodash.isobject": "^3.0.7",
"@types/lodash.omit": "^4.5.9",
"@types/lodash.snakecase": "^4.1.7",
Expand Down
Loading

0 comments on commit 7b68132

Please sign in to comment.