Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Commit

Permalink
feat(UIKIT-375,NewDataGrid): Реализована блокировка строки при выполн…
Browse files Browse the repository at this point in the history
…ении действий (#1100)

Co-authored-by: ooops_o_O <[email protected]>
  • Loading branch information
pan1caisreal and mfrolov89 authored Aug 23, 2024
1 parent fc3579a commit 19cf54f
Show file tree
Hide file tree
Showing 35 changed files with 1,447 additions and 103 deletions.
1 change: 1 addition & 0 deletions .cspell-ignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ mobx
monokai
navpanes
nextjs
newactioncell
newdatagrid
newdatagridinfinite
noopener
Expand Down
6 changes: 5 additions & 1 deletion packages/components/src/ActionCell/ActionCell.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { type DataGridColumns, NewDataGrid } from '../NewDataGrid';
import { ActionCell, type Actions } from './ActionCell';

/**
* **❗️❗️❗️ Компонент устарел и больше не будет поддерживаться.**
* **Используйте [NewActionCell](/docs/components-newactioncell--docs)
* Причина отказа от поддержки: ActionCell не работает с контекстом NewDataGrid, и не позволяет
* управлять состояниями строки при взаимодействии с действиями
* ### [Figma]()
* ### [Guide]()
*/
Expand Down Expand Up @@ -203,13 +207,13 @@ export const BlockingOperations = () => {
}, [deleteLoading, saveLoading]);

const FAKE_ACTIONS: Actions<DataTypeActions> = {
isBlockingOperation: true,
main: [
{
icon: <BinOutlineMd />,
name: 'Удалить',
onClick: () => setDeleteLoading((prevState) => !prevState),
loading: deleteLoading,
isBlockingOperation: true,
},
{
icon: <SaveOutlineMd />,
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/ActionCell/ActionCell.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ describe('ActionCell', () => {

it('Кнопки заблокированы, при isBlockingOperation=true и loading=true', async () => {
const fakeAction: Actions<DataTypeActions> = {
isBlockingOperation: true,
main: [
{
icon: <svg />,
name: 'Удалить',
loading: true,
isBlockingOperation: true,
},
],
secondary: [
Expand Down
9 changes: 5 additions & 4 deletions packages/components/src/ActionCell/ActionCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ export type Actions<T> = {
* Второстепенные действия
*/
secondary?: SecondaryActionKind<T>[];
/**
* Если true, блокирует взаимодействие с actions, если одна из них имеет состояние loading
*/
isBlockingOperation?: boolean;
};

export type ActionsCellProps<T> = {
Expand All @@ -41,6 +37,11 @@ const TOOLTIP_PLACEMENT: Record<string, TooltipProps['placement']> = {
secondaryAction: 'left',
};

/**
* @deprecated
* Используйте NewActionCell. Причина отказа от поддержки: ActionCell не работает с контекстом NewDataGrid, и не позволяет
* управлять состояниями строки при взаимодействии с действиями
*/
export const ActionCell = <T,>(props: ActionsCellProps<T>) => {
const {
isSecondaryActionsAvailable,
Expand Down
17 changes: 15 additions & 2 deletions packages/components/src/ActionCell/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { IconButtonProps } from '../IconButton';
export type SecondaryActionKind<T> = MenuItemProps &
SingleAction<T> & {
/**
* Причина дизейбла
* Причина блокировки
*/
disabledReason?: TooltipProps['title'];
};
Expand All @@ -17,6 +17,7 @@ export type NestedAction<T> = MenuItemProps & {
* Обработчик действия
*/
onClick?: (row: T) => void;

/**
* Название действия
*/
Expand All @@ -25,40 +26,52 @@ export type NestedAction<T> = MenuItemProps & {

export type SingleAction<T> = {
/**
* Причина дизейбла
* Причина блокировки
*/
disabledReason?: TooltipProps['title'];

/**
* Иконка действия
*/
icon?: ReactNode;

/**
* Обработчик действия
*/
onClick?: (row: T) => void;

/**
* Название действия
*/
name: string;

/**
* Флаг показа выпадающего списка при клике
*/
nested?: false;

/**
* Если true, блокирует взаимодействие с actions
*/
isBlockingOperation?: boolean;
};

export type MultipleAction<T> = MenuItemProps & {
/**
* Иконка действия
*/
icon: ReactNode;

/**
* Список действий для выпадающего списка
*/
actions: Array<NestedAction<T>>;

/**
* Флаг показа выпадающего списка при клике
*/
nested: true;

/**
* Название действия
*/
Expand Down
8 changes: 3 additions & 5 deletions packages/components/src/ActionCell/useLogic/useLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export const useLogic = <TRowData>({
actions,
row,
}: UseLogicParams<TRowData>) => {
const { main, secondary, isBlockingOperation = false } = actions;
const { main, secondary } = actions;

const isLoading = main.some((action) => {
const isDisabledAction = main.some((action) => {
if ('actions' in action) {
return false;
}

return action?.loading;
return action?.isBlockingOperation && action?.loading;
});

const handleActionClick = useCallback(
Expand All @@ -37,8 +37,6 @@ export const useLogic = <TRowData>({

const isSecondaryActionsAvailable = secondary && secondary.length >= 1;

const isDisabledAction = isLoading && isBlockingOperation;

return {
isSecondaryActionsAvailable,
handleActionClick,
Expand Down
95 changes: 95 additions & 0 deletions packages/components/src/NewActionCell/MainAction/MainAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import type { ActionCellHandler, MainActionKind } from '../types';
import { Tooltip, type TooltipProps } from '../../Tooltip';
import { IconDropdownButton } from '../../IconDropdownButton';
import { MenuItem } from '../../MenuItem';
import { IconButton } from '../../IconButton';

type MainActionProps<TAction> = {
/**
* Основные действия
*/
action: MainActionKind<TAction>;
/**
* Обработчик клика на действие
*/
onActionClick: ActionCellHandler<TAction>;
/**
* Если true, action не доступен
*/
isDisabled?: boolean;
/**
* Положение тултипа
*/
tooltipPlacement?: TooltipProps['placement'];
};

export const MainAction = <TAction,>({
action,
onActionClick,
isDisabled,
tooltipPlacement,
}: MainActionProps<TAction>) => {
if ('actions' in action) {
const { disabled, icon, name, disabledReason, actions } = action;

return (
<Tooltip
key={name}
title={disabledReason || name}
withoutContainer={!disabled}
placement={tooltipPlacement}
>
<IconDropdownButton
icon={icon}
variant="text"
disabled={isDisabled || disabled}
>
{actions.map(
({ name: nestedActionName, onClick: onClickNested, ...props }) => (
<MenuItem
{...props}
key={nestedActionName}
onClick={onActionClick(onClickNested)}
>
{nestedActionName}
</MenuItem>
),
)}
</IconDropdownButton>
</Tooltip>
);
}

const {
onClick,
name,
icon,
disabledReason,
disabled,
loading,
isBlockingOperation,
loadingNote,
...actions
} = action;

const title = !loading && (disabledReason || name);

return (
<Tooltip
key={name}
title={title}
withoutContainer={!disabled}
placement={tooltipPlacement}
>
<IconButton
disabled={isDisabled || disabled}
loading={loading}
{...actions}
variant="text"
onClick={onActionClick(onClick)}
>
{icon}
</IconButton>
</Tooltip>
);
};
1 change: 1 addition & 0 deletions packages/components/src/NewActionCell/MainAction/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './MainAction';
Loading

0 comments on commit 19cf54f

Please sign in to comment.