Files
twenty/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx
T
Raphaël Bosi c596a5e342 Rename twenty-ui to twenty-ui-deprecated and twenty-new-ui to twenty-ui to prepare package release (#21315)
## Description

Promotes the next-gen UI library (formerly `twenty-new-ui`) to the name
**`twenty-ui`** (v0.1.0, publishable) and renames the old package to
**`twenty-ui-deprecated`**. Rewrites ~1,730 `twenty-ui` imports →
`twenty-ui-deprecated`, updates all configs/CI/Docker/deps, and migrates
twenty-front's `Toggle` to the new package (first consumer) as a
drop-in.

## Next steps
- Wire the `ui/v*` publish dispatch (`cd-deploy-tag.yaml` +
`.yarnrc.yml`), then tag `ui/v0.1.0` to publish.
- Continue migrating components from `twenty-ui-deprecated` →
`twenty-ui`.
2026-06-08 18:12:28 +02:00

150 lines
5.9 KiB
TypeScript

import { styled } from '@linaria/react';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
import { UPDATE_VIEW_BUTTON_DROPDOWN_ID } from '@/views/constants/UpdateViewButtonDropdownId';
import { useHasFiltersInQueryParams } from '@/views/hooks/internal/useHasFiltersInQueryParams';
import { useAreViewFilterGroupsDifferentFromRecordFilterGroups } from '@/views/hooks/useAreViewFilterGroupsDifferentFromRecordFilterGroups';
import { useAreViewFiltersDifferentFromRecordFilters } from '@/views/hooks/useAreViewFiltersDifferentFromRecordFilters';
import { useAreViewSortsDifferentFromRecordSorts } from '@/views/hooks/useAreViewSortsDifferentFromRecordSorts';
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter } from '@/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter';
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { t } from '@lingui/core/macro';
import { IconChevronDown, IconPlus } from 'twenty-ui-deprecated/display';
import { Button, ButtonGroup, IconButton } from 'twenty-ui-deprecated/input';
import { MenuItem } from 'twenty-ui-deprecated/navigation';
import { themeCssVariables } from 'twenty-ui-deprecated/theme-constants';
const StyledContainer = styled.div`
border-radius: ${themeCssVariables.border.radius.md};
display: inline-flex;
margin-right: ${themeCssVariables.spacing[2]};
position: relative;
`;
export const UpdateViewButtonGroup = () => {
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
const { canPersistChanges } = useCanPersistViewChanges();
const { setViewPickerMode } = useViewPickerMode();
const contextStoreCurrentViewId = useAtomComponentStateValue(
contextStoreCurrentViewIdComponentState,
);
const { closeDropdown: closeUpdateViewButtonDropdown } = useCloseDropdown();
const { openDropdown: openViewPickerDropdown } = useOpenDropdown();
const { currentView } = useGetCurrentViewOnly();
const setViewPickerReferenceViewId = useSetAtomComponentState(
viewPickerReferenceViewIdComponentState,
);
const openViewPickerInCreateMode = () => {
if (!contextStoreCurrentViewId) {
return;
}
openViewPickerDropdown({
dropdownComponentInstanceIdFromProps: VIEW_PICKER_DROPDOWN_ID,
});
setViewPickerReferenceViewId(contextStoreCurrentViewId);
setViewPickerMode('create-from-current');
closeUpdateViewButtonDropdown(UPDATE_VIEW_BUTTON_DROPDOWN_ID);
};
const handleCreateViewClick = () => {
openViewPickerInCreateMode();
};
const handleSaveAsNewViewClick = () => {
openViewPickerInCreateMode();
};
const handleUpdateViewClick = async () => {
if (!canPersistChanges) return;
await saveCurrentViewFilterAndSorts();
};
const { hasFiltersQueryParams } = useHasFiltersInQueryParams();
const { viewFilterGroupsAreDifferentFromRecordFilterGroups } =
useAreViewFilterGroupsDifferentFromRecordFilterGroups();
const { viewFiltersAreDifferentFromRecordFilters } =
useAreViewFiltersDifferentFromRecordFilters();
const { viewSortsAreDifferentFromRecordSorts } =
useAreViewSortsDifferentFromRecordSorts();
const { viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter } =
useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter();
const canShowButton =
(viewFiltersAreDifferentFromRecordFilters ||
viewSortsAreDifferentFromRecordSorts ||
viewFilterGroupsAreDifferentFromRecordFilterGroups ||
viewAnyFieldFilterDifferentFromCurrentAnyFieldFilter) &&
!hasFiltersQueryParams;
if (!canShowButton) {
return <></>;
}
return (
<StyledContainer>
{currentView?.key !== 'INDEX' ? (
<ButtonGroup size="small" accent="blue">
<Button
title={t`Update view`}
onClick={handleUpdateViewClick}
disabled={!canPersistChanges}
/>
<Dropdown
dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID}
clickableComponent={
<IconButton
size="small"
accent="blue"
Icon={IconChevronDown}
position="right"
/>
}
dropdownComponents={
<DropdownContent>
<DropdownMenuItemsContainer>
<MenuItem
onClick={handleCreateViewClick}
LeftIcon={IconPlus}
text={t`Create view`}
/>
</DropdownMenuItemsContainer>
</DropdownContent>
}
/>
</ButtonGroup>
) : (
<Button
title={t`Save as new view`}
onClick={handleSaveAsNewViewClick}
accent="blue"
size="small"
variant="secondary"
/>
)}
</StyledContainer>
);
};