Skip to content

Commit

Permalink
Merge pull request #1597 from Vizzuality/MRXN23-520-fe-id-26-2-invent…
Browse files Browse the repository at this point in the history
…ory-panel

[MRXN23-520]: fixes menu action behaviour
agnlez authored Nov 22, 2023
2 parents eb3f222 + 76082b2 commit aca8a31
Showing 7 changed files with 81 additions and 43 deletions.
2 changes: 1 addition & 1 deletion app/hooks/features/index.ts
Original file line number Diff line number Diff line change
@@ -277,7 +277,7 @@ export function useSelectedFeatures(
max: amountMax,
},
color: featureColorQueryState
? featureColorQueryState.data.find(({ id }) => featureId === id)?.color
? featureColorQueryState?.data?.find(({ id }) => featureId === id)?.color
: null,

// SPLIT
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useCallback, useRef, useState } from 'react';

import { HiDotsHorizontal } from 'react-icons/hi';

import Checkbox from 'components/forms/checkbox';
@@ -18,6 +20,12 @@ const RowItem = ({
ActionsComponent,
}: RowItem) => {
const { id, name, scenarios, tag, isVisibleOnMap, isCustom } = item;
const [isMenuOpen, setIsMenuOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);

const onDismissMenu = useCallback(() => {
setIsMenuOpen(false);
}, []);

return (
<tr key={id} className="flex w-full align-top">
@@ -70,25 +78,35 @@ const RowItem = ({
/>
</button>

<Popover modal>
<Popover open={isMenuOpen}>
<PopoverTrigger asChild>
<button
type="button"
className={cn({
'h-5 w-5': true,
invisible: !isCustom,
})}
ref={buttonRef}
onClick={() => {
setIsMenuOpen((prevState) => !prevState);
}}
>
<HiDotsHorizontal className="h-4 w-4 text-white" />
<HiDotsHorizontal className="pointer-events-none h-4 w-4 text-white" />
</button>
</PopoverTrigger>
<PopoverContent
hideWhenDetached
className="w-auto rounded-2xl border-transparent p-0"
side="bottom"
sideOffset={5}
align="start"
onInteractOutside={(evt) => {
if (evt.target !== buttonRef.current) {
setIsMenuOpen(false);
}
}}
>
<ActionsComponent item={item} />
<ActionsComponent item={item} onDismissMenu={onDismissMenu} />
</PopoverContent>
</Popover>
</div>
Original file line number Diff line number Diff line change
@@ -7,5 +7,11 @@ export type RowItem = {
selectedIds: string[];
onSelectRow: (evt: ChangeEvent<HTMLInputElement>) => void;
onToggleSeeOnMap: (id: string) => void;
ActionsComponent: ({ item }: { item: DataItem }) => JSX.Element;
ActionsComponent: ({
item,
onDismissMenu,
}: {
item: DataItem;
onDismissMenu: () => void;
}) => JSX.Element;
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react';
import { ComponentProps, useCallback, useState } from 'react';

import Icon from 'components/icon';
import Modal from 'components/modal/component';
@@ -9,33 +9,33 @@ import { cn } from 'utils/cn';
import DELETE_SVG from 'svgs/ui/new-layout/delete.svg?sprite';
import TAG_SVG from 'svgs/ui/tag.svg?sprite';

import RowItem from '../../components/inventory-table/row-item';

const BUTTON_CLASSES =
'flex items-center px-4 py-2 w-full text-sm cursor-pointer bg-gray-800 hover:bg-gray-600 transition transition-colors space-x-2 group';

const ICON_CLASSES = 'h-5 w-5 text-gray-100 group-hover:text-white';

const ActionsMenu = ({
item,
}: {
item: {
id: string;
name: string;
scenarios: number;
tag: string;
custom: boolean;
};
}): JSX.Element => {
const isDeletable = !item.custom && !item.scenarios;
onDismissMenu,
}: Parameters<ComponentProps<typeof RowItem>['ActionsComponent']>[0]): JSX.Element => {
const isDeletable = !item.isCustom && !item.scenarios;

// item.isCustom && !item.scenarioUsageCount
const [modalState, setModalState] = useState<{ edit: boolean; delete: boolean }>({
edit: false,
delete: false,
});

const handleModal = useCallback((modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => ({ ...prevState, [modalKey]: isVisible }));
}, []);
const handleModal = useCallback(
(modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => {
if (!isVisible) onDismissMenu();
return { ...prevState, [modalKey]: isVisible };
});
},
[onDismissMenu]
);

return (
<ul className="rounded-2xl border-gray-600">
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useCallback, useState } from 'react';
import { ComponentProps, useCallback, useState } from 'react';

import Icon from 'components/icon';
import Modal from 'components/modal/component';
import { type DataItem } from 'layout/project/sidebar/project/inventory-panel/components/inventory-table';
import RowItem from 'layout/project/sidebar/project/inventory-panel/components/inventory-table/row-item';
import DeleteModal from 'layout/project/sidebar/project/inventory-panel/features/modals/delete';
import EditModal from 'layout/project/sidebar/project/inventory-panel/features/modals/edit';
import { cn } from 'utils/cn';
@@ -19,24 +19,35 @@ const ICON_CLASSES = 'h-5 w-5 text-gray-100 group-hover:text-white';

const ICON_DISABLED_CLASSES = 'text-gray-700';

const ActionsMenu = ({ item }: { item: DataItem }): JSX.Element => {
const ActionsMenu = ({
item,
onDismissMenu,
}: Parameters<ComponentProps<typeof RowItem>['ActionsComponent']>[0]): JSX.Element => {
const isDeletable = !item.isCustom || !item.scenarios;

const [modalState, setModalState] = useState<{ edit: boolean; delete: boolean }>({
edit: false,
delete: false,
});

const handleModal = useCallback((modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => ({ ...prevState, [modalKey]: isVisible }));
}, []);
const handleModal = useCallback(
(modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => {
if (!isVisible) onDismissMenu();
return { ...prevState, [modalKey]: isVisible };
});
},
[onDismissMenu]
);

return (
<ul className="rounded-2xl border-gray-600">
<li>
<button
type="button"
onClick={() => handleModal('edit', true)}
onClick={() => {
handleModal('edit', true);
}}
className={cn({
[BUTTON_CLASSES]: true,
'rounded-t-2xl': true,
@@ -50,7 +61,9 @@ const ActionsMenu = ({ item }: { item: DataItem }): JSX.Element => {
title="All features"
open={modalState.edit}
size="narrow"
onDismiss={() => handleModal('edit', false)}
onDismiss={() => {
handleModal('edit', false);
}}
>
<EditModal featureId={item.id} handleModal={handleModal} />
</Modal>
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
{
select: ({ data }) => {
return data?.map((feature) => {
const { color } = featureColorQueryState.data.find(({ id }) => feature.id === id) || {};
const { color } = featureColorQueryState?.data?.find(({ id }) => feature.id === id) || {};

return {
id: feature.id,
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useState } from 'react';
import { ComponentProps, useCallback, useState } from 'react';

import Icon from 'components/icon';
import Modal from 'components/modal/component';
@@ -9,32 +9,33 @@ import { cn } from 'utils/cn';
import DELETE_SVG from 'svgs/ui/new-layout/delete.svg?sprite';
import TAG_SVG from 'svgs/ui/tag.svg?sprite';

import RowItem from '../../components/inventory-table/row-item';

const BUTTON_CLASSES =
'flex items-center px-4 py-2 w-full text-sm cursor-pointer bg-gray-800 hover:bg-gray-600 transition transition-colors space-x-2 group';

const ICON_CLASSES = 'h-5 w-5 text-gray-100 group-hover:text-white';

const ActionsMenu = ({
item,
}: {
item: {
id: string;
name: string;
scenarios: number;
tag: string;
custom: boolean;
};
}): JSX.Element => {
const isDeletable = !item.custom && !item.scenarios;
onDismissMenu,
}: Parameters<ComponentProps<typeof RowItem>['ActionsComponent']>[0]): JSX.Element => {
const isDeletable = !item.isCustom && !item.scenarios;

const [modalState, setModalState] = useState<{ edit: boolean; delete: boolean }>({
edit: false,
delete: false,
});

const handleModal = useCallback((modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => ({ ...prevState, [modalKey]: isVisible }));
}, []);
const handleModal = useCallback(
(modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => {
if (!isVisible) onDismissMenu();
return { ...prevState, [modalKey]: isVisible };
});
},
[onDismissMenu]
);

return (
<ul className="rounded-2xl border-gray-600">

1 comment on commit aca8a31

@vercel
Copy link

@vercel vercel bot commented on aca8a31 Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

marxan – ./

marxan-vizzuality1.vercel.app
marxan23.vercel.app
marxan-git-develop-vizzuality1.vercel.app

Please sign in to comment.