diff --git a/front/src/modules/companies/board/components/CompanyBoard.tsx b/front/src/modules/companies/board/components/CompanyBoard.tsx
new file mode 100644
index 000000000..f195140e2
--- /dev/null
+++ b/front/src/modules/companies/board/components/CompanyBoard.tsx
@@ -0,0 +1,40 @@
+import {
+ EntityBoard,
+ type EntityBoardProps,
+} from '@/ui/board/components/EntityBoard';
+import { EntityBoardActionBar } from '@/ui/board/components/EntityBoardActionBar';
+import { EntityBoardContextMenu } from '@/ui/board/components/EntityBoardContextMenu';
+import { useBoardViews } from '@/views/hooks/useBoardViews';
+
+import { HooksCompanyBoard } from '../../components/HooksCompanyBoard';
+import { CompanyBoardRecoilScopeContext } from '../../states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
+
+type OwnProps = Pick<
+ EntityBoardProps,
+ 'boardOptions' | 'onColumnAdd' | 'onColumnDelete' | 'onEditColumnTitle'
+>;
+
+export const CompanyBoard = ({ boardOptions, ...props }: OwnProps) => {
+ const { handleViewsChange, handleViewSubmit } = useBoardViews({
+ availableFilters: boardOptions.filters,
+ availableSorts: boardOptions.sorts,
+ objectId: 'company',
+ scopeContext: CompanyBoardRecoilScopeContext,
+ });
+
+ return (
+ <>
+
+
+
+
+ >
+ );
+};
diff --git a/front/src/modules/ui/board/components/BoardHeader.tsx b/front/src/modules/ui/board/components/BoardHeader.tsx
index 2572d948b..2ba60c0a5 100644
--- a/front/src/modules/ui/board/components/BoardHeader.tsx
+++ b/front/src/modules/ui/board/components/BoardHeader.tsx
@@ -1,50 +1,52 @@
-import type { ComponentProps, Context, ReactNode } from 'react';
-import styled from '@emotion/styled';
+import { type ComponentProps, useCallback } from 'react';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
-import { TopBar } from '@/ui/top-bar/TopBar';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
-import { FilterDropdownButton } from '@/ui/view-bar/components/FilterDropdownButton';
-import { SortDropdownButton } from '@/ui/view-bar/components/SortDropdownButton';
-import ViewBarDetails from '@/ui/view-bar/components/ViewBarDetails';
-import { FiltersHotkeyScope } from '@/ui/view-bar/types/FiltersHotkeyScope';
-import { SortType } from '@/ui/view-bar/types/interface';
+import { ViewBar, type ViewBarProps } from '@/ui/view-bar/components/ViewBar';
import type { BoardColumnDefinition } from '../types/BoardColumnDefinition';
+import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
import { BoardOptionsHotkeyScope } from '../types/BoardOptionsHotkeyScope';
import { BoardOptionsDropdown } from './BoardOptionsDropdown';
-type OwnProps = ComponentProps<'div'> & {
- viewName: string;
- viewIcon?: ReactNode;
- availableSorts?: Array>;
+export type BoardHeaderProps = ComponentProps<'div'> & {
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
- context: Context;
-};
-
-const StyledIcon = styled.div`
- display: flex;
- margin-left: ${({ theme }) => theme.spacing(1)};
- margin-right: ${({ theme }) => theme.spacing(2)};
-
- & > svg {
- font-size: ${({ theme }) => theme.icon.size.sm};
- }
-`;
+} & Pick<
+ ViewBarProps,
+ | 'availableSorts'
+ | 'defaultViewName'
+ | 'onViewsChange'
+ | 'onViewSubmit'
+ | 'scopeContext'
+ >;
export function BoardHeader({
- viewName,
- viewIcon,
- availableSorts,
onStageAdd,
- context,
+ onViewsChange,
+ scopeContext,
...props
-}: OwnProps) {
+}: BoardHeaderProps) {
+ const OptionsDropdownButton = useCallback(
+ () => (
+
+ ),
+ [onStageAdd, onViewsChange, scopeContext],
+ );
+
return (
-
diff --git a/front/src/modules/ui/board/components/BoardOptionsDropdown.tsx b/front/src/modules/ui/board/components/BoardOptionsDropdown.tsx
index d43525519..8b82455c0 100644
--- a/front/src/modules/ui/board/components/BoardOptionsDropdown.tsx
+++ b/front/src/modules/ui/board/components/BoardOptionsDropdown.tsx
@@ -1,28 +1,29 @@
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
-import type { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
-import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
import { BoardOptionsDropdownButton } from './BoardOptionsDropdownButton';
-import { BoardOptionsDropdownContent } from './BoardOptionsDropdownContent';
+import {
+ BoardOptionsDropdownContent,
+ type BoardOptionsDropdownContentProps,
+} from './BoardOptionsDropdownContent';
-type BoardOptionsDropdownProps = {
- customHotkeyScope: HotkeyScope;
- onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
-};
+type BoardOptionsDropdownProps = Pick<
+ BoardOptionsDropdownContentProps,
+ 'customHotkeyScope' | 'onStageAdd' | 'onViewsChange' | 'scopeContext'
+>;
export function BoardOptionsDropdown({
customHotkeyScope,
- onStageAdd,
+ ...props
}: BoardOptionsDropdownProps) {
return (
}
dropdownComponents={
}
dropdownHotkeyScope={customHotkeyScope}
diff --git a/front/src/modules/ui/board/components/BoardOptionsDropdownContent.tsx b/front/src/modules/ui/board/components/BoardOptionsDropdownContent.tsx
index 69bd1ae0a..cc4e3de00 100644
--- a/front/src/modules/ui/board/components/BoardOptionsDropdownContent.tsx
+++ b/front/src/modules/ui/board/components/BoardOptionsDropdownContent.tsx
@@ -1,7 +1,7 @@
-import { useRef, useState } from 'react';
+import { type Context, useRef, useState } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
-import { useRecoilState } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { v4 } from 'uuid';
@@ -22,14 +22,21 @@ import { MenuItemNavigate } from '@/ui/menu-item/components/MenuItemNavigate';
import { ThemeColor } from '@/ui/theme/constants/colors';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
+import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
+import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
+import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
+import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
+import type { View } from '@/ui/view-bar/types/View';
import { boardColumnsState } from '../states/boardColumnsState';
import type { BoardColumnDefinition } from '../types/BoardColumnDefinition';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
-type BoardOptionsDropdownContentProps = {
+export type BoardOptionsDropdownContentProps = {
customHotkeyScope: HotkeyScope;
onStageAdd?: (boardColumn: BoardColumnDefinition) => void;
+ onViewsChange?: (views: View[]) => void | Promise;
+ scopeContext: Context;
};
const StyledIconSettings = styled(IconSettings)`
@@ -51,10 +58,13 @@ type ColumnForCreate = {
export function BoardOptionsDropdownContent({
customHotkeyScope,
onStageAdd,
+ onViewsChange,
+ scopeContext,
}: BoardOptionsDropdownContentProps) {
const theme = useTheme();
const stageInputRef = useRef(null);
+ const viewEditInputRef = useRef(null);
const [currentMenu, setCurrentMenu] = useState<
BoardOptionsMenu | undefined
@@ -62,7 +72,8 @@ export function BoardOptionsDropdownContent({
const [boardColumns, setBoardColumns] = useRecoilState(boardColumnsState);
- const resetMenu = () => setCurrentMenu(undefined);
+ const viewsById = useRecoilScopedValue(viewsByIdScopedSelector, scopeContext);
+ const viewEditMode = useRecoilValue(viewEditModeState);
const handleStageSubmit = () => {
if (
@@ -85,6 +96,23 @@ export function BoardOptionsDropdownContent({
onStageAdd?.(columnToCreate);
};
+ const { upsertView } = useUpsertView({
+ onViewsChange,
+ scopeContext,
+ });
+
+ const handleViewNameSubmit = async () => {
+ const name = viewEditInputRef.current?.value;
+ await upsertView(name);
+ };
+
+ const resetMenu = () => setCurrentMenu(undefined);
+
+ const handleMenuNavigate = (menu: BoardOptionsMenu) => {
+ handleViewNameSubmit();
+ setCurrentMenu(menu);
+ };
+
const { closeDropdownButton } = useDropdownButton({
key: BoardOptionsDropdownKey,
});
@@ -101,6 +129,7 @@ export function BoardOptionsDropdownContent({
Key.Enter,
() => {
handleStageSubmit();
+ handleViewNameSubmit();
closeDropdownButton();
},
customHotkeyScope.scope,
@@ -110,14 +139,29 @@ export function BoardOptionsDropdownContent({
{!currentMenu && (
<>
-
-
- Settings
-
+ {!!viewEditMode.mode ? (
+
+ ) : (
+
+
+ Settings
+
+ )}
setCurrentMenu(BoardOptionsMenu.Stages)}
+ onClick={() => handleMenuNavigate(BoardOptionsMenu.Stages)}
LeftIcon={IconLayoutKanban}
text="Stages"
/>
diff --git a/front/src/modules/ui/board/components/EntityBoard.tsx b/front/src/modules/ui/board/components/EntityBoard.tsx
index 6bb1f7165..29159b172 100644
--- a/front/src/modules/ui/board/components/EntityBoard.tsx
+++ b/front/src/modules/ui/board/components/EntityBoard.tsx
@@ -1,17 +1,17 @@
-import { useCallback, useRef } from 'react';
+import { type Context, useCallback, useRef } from 'react';
import { getOperationName } from '@apollo/client/utilities';
-import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { DragDropContext, OnDragEndResponder } from '@hello-pangea/dnd'; // Atlassian dnd does not support StrictMode from RN 18, so we use a fork @hello-pangea/dnd https://github.com/atlassian/react-beautiful-dnd/issues/2350
import { useRecoilState } from 'recoil';
-import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
import { GET_PIPELINE_PROGRESS } from '@/pipeline/graphql/queries/getPipelineProgress';
import { PageHotkeyScope } from '@/types/PageHotkeyScope';
-import { BoardHeader } from '@/ui/board/components/BoardHeader';
+import {
+ BoardHeader,
+ type BoardHeaderProps,
+} from '@/ui/board/components/BoardHeader';
import { StyledBoard } from '@/ui/board/components/StyledBoard';
import { BoardColumnIdContext } from '@/ui/board/contexts/BoardColumnIdContext';
-import { IconList } from '@/ui/icon';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useListenClickOutsideByClassName } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
@@ -22,6 +22,7 @@ import {
PipelineStage,
useUpdateOnePipelineProgressStageMutation,
} from '~/generated/graphql';
+import { PipelineProgressOrderByWithRelationInput as PipelineProgresses_Order_By } from '~/generated/graphql';
import { useCurrentCardSelected } from '../hooks/useCurrentCardSelected';
import { useSetCardSelected } from '../hooks/useSetCardSelected';
@@ -33,6 +34,17 @@ import { BoardOptions } from '../types/BoardOptions';
import { EntityBoardColumn } from './EntityBoardColumn';
+export type EntityBoardProps = {
+ boardOptions: BoardOptions;
+ onColumnAdd?: (boardColumn: BoardColumnDefinition) => void;
+ onColumnDelete?: (boardColumnId: string) => void;
+ onEditColumnTitle: (columnId: string, title: string, color: string) => void;
+ scopeContext: Context;
+} & Pick<
+ BoardHeaderProps,
+ 'defaultViewName' | 'onViewsChange' | 'onViewSubmit'
+>;
+
const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
@@ -46,19 +58,17 @@ const StyledBoardHeader = styled(BoardHeader)`
export function EntityBoard({
boardOptions,
+ defaultViewName,
onColumnAdd,
onColumnDelete,
onEditColumnTitle,
-}: {
- boardOptions: BoardOptions;
- onColumnAdd?: (boardColumn: BoardColumnDefinition) => void;
- onColumnDelete?: (boardColumnId: string) => void;
- onEditColumnTitle: (columnId: string, title: string, color: string) => void;
-}) {
+ onViewsChange,
+ onViewSubmit,
+ scopeContext,
+}: EntityBoardProps) {
const [boardColumns] = useRecoilState(boardColumnsState);
const setCardSelected = useSetCardSelected();
- const theme = useTheme();
const [updatePipelineProgressStage] =
useUpdateOnePipelineProgressStageMutation();
@@ -131,11 +141,12 @@ export function EntityBoard({
return (boardColumns?.length ?? 0) > 0 ? (
}
+ defaultViewName={defaultViewName}
availableSorts={boardOptions.sorts}
onStageAdd={onColumnAdd}
- context={CompanyBoardRecoilScopeContext}
+ onViewsChange={onViewsChange}
+ onViewSubmit={onViewSubmit}
+ scopeContext={scopeContext}
/>
diff --git a/front/src/modules/ui/table/options/components/TableOptionsDropdownContent.tsx b/front/src/modules/ui/table/options/components/TableOptionsDropdownContent.tsx
index fd8eee340..663c6e531 100644
--- a/front/src/modules/ui/table/options/components/TableOptionsDropdownContent.tsx
+++ b/front/src/modules/ui/table/options/components/TableOptionsDropdownContent.tsx
@@ -1,7 +1,6 @@
-import { type FormEvent, useCallback, useRef, useState } from 'react';
-import { useRecoilCallback, useRecoilState } from 'recoil';
+import { useRef, useState } from 'react';
+import { useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
-import { v4 } from 'uuid';
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
@@ -11,22 +10,14 @@ import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDrop
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
-import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
-import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
-import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
-import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
-import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
-import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
+import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
-import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
-import { viewsScopedState } from '@/ui/view-bar/states/viewsScopedState';
import type { View } from '@/ui/view-bar/types/View';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
-import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector';
import { visibleTableColumnsScopedSelector } from '../../states/selectors/visibleTableColumnsScopedSelector';
import { TableOptionsDropdownKey } from '../../types/TableOptionsDropdownKey';
@@ -35,31 +26,27 @@ import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
import { TableOptionsDropdownColumnVisibility } from './TableOptionsDropdownSection';
type TableOptionsDropdownButtonProps = {
- onViewsChange?: (views: View[]) => void;
+ onViewsChange?: (views: View[]) => void | Promise;
onImport?: () => void;
};
-enum Option {
- Properties = 'Properties',
-}
+type TableOptionsMenu = 'properties';
export function TableOptionsDropdownContent({
onViewsChange,
onImport,
}: TableOptionsDropdownButtonProps) {
- const tableScopeId = useContextScopeId(TableRecoilScopeContext);
-
const { closeDropdownButton } = useDropdownButton({
key: TableOptionsDropdownKey,
});
- const [selectedOption, setSelectedOption] = useState