Skip to content

Commit

Permalink
Merge branch 'main' into feat/record-group-add-new
Browse files Browse the repository at this point in the history
  • Loading branch information
magrinj committed Dec 11, 2024
2 parents 51cc744 + 2c4a77a commit 8a97d73
Show file tree
Hide file tree
Showing 54 changed files with 605 additions and 194 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,26 @@ import { WorkflowRunRecordActionMenuEntrySetterEffect } from '@/action-menu/acti
import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-ui';

export const RecordActionMenuEntriesSetter = () => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
contextStoreCurrentObjectMetadataIdComponentState,
);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);

if (!isDefined(contextStoreCurrentObjectMetadataId)) {
const objectMetadataItem = objectMetadataItems.find(
(item) => item.id === contextStoreCurrentObjectMetadataId,
);

if (
!isDefined(contextStoreCurrentObjectMetadataId) ||
!isDefined(objectMetadataItem)
) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useRecoilValue } from 'recoil';
import { IconHeart, IconHeartOff, isDefined } from 'twenty-ui';

Expand All @@ -34,6 +35,10 @@ export const useManageFavoritesSingleRecordAction = ({

const isFavorite = !!foundFavorite;

const isPageHeaderV2Enabled = useIsFeatureEnabled(
'IS_PAGE_HEADER_V2_ENABLED',
);

const registerManageFavoritesSingleRecordAction = ({
position,
}: {
Expand All @@ -47,6 +52,7 @@ export const useManageFavoritesSingleRecordAction = ({
type: ActionMenuEntryType.Standard,
scope: ActionMenuEntryScope.RecordSelection,
key: 'manage-favorites-single-record',
isPinned: isPageHeaderV2Enabled,
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
position,
Icon: isFavorite ? IconHeartOff : IconHeart,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-acti
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
import { RecordIndexActionMenuButtons } from '@/action-menu/components/RecordIndexActionMenuButtons';
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';

import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useIsMobile } from 'twenty-ui';

export const RecordIndexActionMenu = () => {
const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
Expand All @@ -17,6 +19,12 @@ export const RecordIndexActionMenu = () => {

const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');

const isPageHeaderV2Enabled = useIsFeatureEnabled(
'IS_PAGE_HEADER_V2_ENABLED',
);

const isMobile = useIsMobile();

return (
<>
{contextStoreCurrentObjectMetadataId && (
Expand All @@ -26,7 +34,11 @@ export const RecordIndexActionMenu = () => {
onActionExecutedCallback: () => {},
}}
>
<RecordIndexActionMenuBar />
{isPageHeaderV2Enabled ? (
<>{!isMobile && <RecordIndexActionMenuButtons />}</>
) : (
<RecordIndexActionMenuBar />
)}
<RecordIndexActionMenuDropdown />
<ActionMenuConfirmationModals />
<RecordIndexActionMenuEffect />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import styled from '@emotion/styled';

import { RecordIndexActionMenuBarAllActionsButton } from '@/action-menu/components/RecordIndexActionMenuBarAllActionsButton';
import { RecordIndexActionMenuBarEntry } from '@/action-menu/components/RecordIndexActionMenuBarEntry';
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
Expand All @@ -10,6 +8,7 @@ import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-sto
import { BottomBar } from '@/ui/layout/bottom-bar/components/BottomBar';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';

const StyledLabel = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
Expand All @@ -33,7 +32,6 @@ export const RecordIndexActionMenuBar = () => {
);

const pinnedEntries = actionMenuEntries.filter((entry) => entry.isPinned);

if (contextStoreNumberOfSelectedRecords === 0) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';

import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';

type RecordIndexActionMenuBarEntryProps = {
entry: ActionMenuEntry;
};
Expand All @@ -13,11 +12,9 @@ const StyledButton = styled.div`
cursor: pointer;
display: flex;
justify-content: center;
padding: ${({ theme }) => theme.spacing(2)};
transition: background ${({ theme }) => theme.animation.duration.fast} ease;
user-select: none;
&:hover {
background: ${({ theme }) => theme.background.tertiary};
}
Expand All @@ -32,6 +29,7 @@ export const RecordIndexActionMenuBarEntry = ({
entry,
}: RecordIndexActionMenuBarEntryProps) => {
const theme = useTheme();

return (
<StyledButton onClick={() => entry.onClick?.()}>
{entry.Icon && <entry.Icon size={theme.icon.size.md} />}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { Button } from 'twenty-ui';

export const RecordIndexActionMenuButtons = () => {
const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
contextStoreNumberOfSelectedRecordsComponentState,
);

const actionMenuEntries = useRecoilComponentValueV2(
actionMenuEntriesComponentSelector,
);

const pinnedEntries = actionMenuEntries.filter((entry) => entry.isPinned);

if (contextStoreNumberOfSelectedRecords === 0) {
return null;
}

return (
<>
{pinnedEntries.map((entry, index) => (
<Button
key={index}
Icon={entry.Icon}
size="small"
variant="secondary"
accent="default"
title={entry.label}
onClick={() => entry.onClick?.()}
ariaLabel={entry.label}
/>
))}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
import { RecordAgnosticActionsSetterEffect } from '@/action-menu/actions/record-agnostic-actions/components/RecordAgnosticActionsSetterEffect';
import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
import { RecordShowActionMenuButtons } from '@/action-menu/components/RecordShowActionMenuButtons';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';

import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
Expand Down Expand Up @@ -29,6 +30,10 @@ export const RecordShowActionMenu = ({

const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED');

const isPageHeaderV2Enabled = useIsFeatureEnabled(
'IS_PAGE_HEADER_V2_ENABLED',
);

// TODO: refactor RecordShowPageBaseHeader to use the context store

return (
Expand All @@ -40,15 +45,19 @@ export const RecordShowActionMenu = ({
onActionExecutedCallback: () => {},
}}
>
<RecordShowPageBaseHeader
{...{
isFavorite,
record,
objectMetadataItem,
objectNameSingular,
handleFavoriteButtonClick,
}}
/>
{isPageHeaderV2Enabled ? (
<RecordShowActionMenuButtons />
) : (
<RecordShowPageBaseHeader
{...{
isFavorite,
record,
objectMetadataItem,
objectNameSingular,
handleFavoriteButtonClick,
}}
/>
)}
<ActionMenuConfirmationModals />
<RecordActionMenuEntriesSetter />
{isWorkflowEnabled && <RecordAgnosticActionsSetterEffect />}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
import { PageHeaderOpenCommandMenuButton } from '@/ui/layout/page-header/components/PageHeaderOpenCommandMenuButton';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { Button, useIsMobile } from 'twenty-ui';

export const RecordShowActionMenuButtons = () => {
const actionMenuEntries = useRecoilComponentValueV2(
actionMenuEntriesComponentSelector,
);

const pinnedEntries = actionMenuEntries.filter((entry) => entry.isPinned);

const isMobile = useIsMobile();

return (
<>
{!isMobile &&
pinnedEntries.map((entry, index) => (
<Button
key={index}
Icon={entry.Icon}
size="small"
variant="secondary"
accent="default"
title={entry.label}
onClick={() => entry.onClick?.()}
ariaLabel={entry.label}
/>
))}
<PageHeaderOpenCommandMenuButton key="more" />
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import { expect, jest } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { RecoilRoot } from 'recoil';

import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
Expand All @@ -11,11 +7,14 @@ import {
ActionMenuEntryType,
} from '@/action-menu/types/ActionMenuEntry';
import { getActionBarIdFromActionMenuId } from '@/action-menu/utils/getActionBarIdFromActionMenuId';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
import { expect, jest } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, waitFor, within } from '@storybook/test';
import { RecoilRoot } from 'recoil';
import { IconTrash, RouterDecorator } from 'twenty-ui';

const deleteMock = jest.fn();
Expand All @@ -40,16 +39,13 @@ const meta: Meta<typeof RecordIndexActionMenuBar> = {
selectedRecordIds: ['1', '2', '3'],
},
);

set(
contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
instanceId: 'story-action-menu',
}),
3,
);

const map = new Map<string, ActionMenuEntry>();

map.set('delete', {
isPinned: true,
scope: ActionMenuEntryScope.RecordSelection,
Expand All @@ -60,14 +56,12 @@ const meta: Meta<typeof RecordIndexActionMenuBar> = {
Icon: IconTrash,
onClick: deleteMock,
});

set(
actionMenuEntriesComponentState.atomFamily({
instanceId: 'story-action-menu',
}),
map,
);

set(
isBottomBarOpenedComponentState.atomFamily({
instanceId: getActionBarIdFromActionMenuId('story-action-menu'),
Expand Down Expand Up @@ -117,10 +111,8 @@ export const WithButtonClicks: Story = {
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

const deleteButton = await canvas.findByText('Delete');
await userEvent.click(deleteButton);

await waitFor(() => {
expect(deleteMock).toHaveBeenCalled();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import {
import { expect, jest } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';

import { ComponentDecorator, IconCheckbox, IconTrash } from 'twenty-ui';

const meta: Meta<typeof RecordIndexActionMenuBarEntry> = {
title: 'Modules/ActionMenu/RecordIndexActionMenuBarEntry',
component: RecordIndexActionMenuBarEntry,
decorators: [ComponentDecorator],
};

export default meta;

type Story = StoryObj<typeof RecordIndexActionMenuBarEntry>;
Expand Down
5 changes: 3 additions & 2 deletions packages/twenty-front/src/modules/auth/components/Logo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import styled from '@emotion/styled';
import { getImageAbsoluteURI, isDefined } from 'twenty-ui';
import { isNonEmptyString } from '@sniptt/guards';
import { getImageAbsoluteURI } from 'twenty-ui';

type LogoProps = {
primaryLogo?: string | null;
Expand Down Expand Up @@ -48,7 +49,7 @@ export const Logo = (props: LogoProps) => {
const primaryLogoUrl = getImageAbsoluteURI(
props.primaryLogo ?? defaultPrimaryLogoUrl,
);
const secondaryLogoUrl = isDefined(props.secondaryLogo)
const secondaryLogoUrl = isNonEmptyString(props.secondaryLogo)
? getImageAbsoluteURI(props.secondaryLogo)
: null;

Expand Down
2 changes: 1 addition & 1 deletion packages/twenty-front/src/modules/auth/hooks/useAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTi
import { currentUserState } from '../states/currentUserState';
import { tokenPairState } from '../states/tokenPairState';

import { useLastAuthenticatedWorkspaceDomain } from '@/domain-manager/hooks/useLastAuthenticatedWorkspaceDomain';
import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWorkspaceEnabledState';
import { useIsCurrentLocationOnAWorkspaceSubdomain } from '@/domain-manager/hooks/useIsCurrentLocationOnAWorkspaceSubdomain';
import { useLastAuthenticatedWorkspaceDomain } from '@/domain-manager/hooks/useLastAuthenticatedWorkspaceDomain';
import { useReadWorkspaceSubdomainFromCurrentLocation } from '@/domain-manager/hooks/useReadWorkspaceSubdomainFromCurrentLocation';
import { domainConfigurationState } from '@/domain-manager/states/domainConfigurationState';

Expand Down
Loading

0 comments on commit 8a97d73

Please sign in to comment.