Skip to content

Commit

Permalink
inventory: features in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgnlez committed Feb 12, 2024
1 parent 582295b commit c4f971c
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 21 deletions.
3 changes: 2 additions & 1 deletion app/hooks/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export function useAllFeatures<T = { data: Feature[] }>(
) {
const { data: session } = useSession();

const { filters = {}, search, sort, disablePagination } = options;
const { filters = {}, search, sort, includeInProgress = false } = options;

const parsedFilters = Object.keys(filters).reduce((acc, k) => {
return {
Expand All @@ -160,6 +160,7 @@ export function useAllFeatures<T = { data: Feature[] }>(
...(sort && {
sort,
}),
includeInProgress,
disablePagination: true,
},
}).then(({ data }) => data);
Expand Down
1 change: 1 addition & 0 deletions app/hooks/features/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ export interface UseFeaturesOptionsProps {
sort?: string;
filters?: Record<string, unknown>;
disablePagination?: boolean;
includeInProgress?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,27 @@ const RowItem = ({
onSelectTag,
ActionsComponent,
}: RowItem) => {
const { id, name, scenarios, tag, isVisibleOnMap, isCustom } = item;
const { id, name, scenarios, tag, isVisibleOnMap, isCustom, isFeature, creationStatus } = item;
const [isMenuOpen, setIsMenuOpen] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);

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

const renderScenarioUsage = useCallback((scenarios: (typeof item)['scenarios']) => {
return (
<div className="mt-1.5 text-xs text-gray-400">
Currently in use in{' '}
<span className="rounded bg-blue-600 bg-opacity-10 px-1 text-blue-600">{scenarios}</span>{' '}
scenarios.
</div>
);
}, []);

const isFeatureRunning = isFeature && creationStatus === 'running';
const isFeatureFailed = isFeature && creationStatus === 'failure';

return (
<tr key={id} className="flex w-full align-top">
<td className="pb-2 pr-1 pt-5">
Expand All @@ -38,7 +51,7 @@ const RowItem = ({
onChange={onSelectRow}
value={id}
checked={isCustom && selectedIds.includes(id)}
disabled={!isCustom}
disabled={!isCustom || isFeatureRunning}
/>
</td>
<td
Expand All @@ -48,15 +61,21 @@ const RowItem = ({
})}
>
<span className="inline-flex break-all">{name}</span>
{isCustom && (
<div className="mt-1.5 text-xs text-gray-400">
Currently in use in{' '}
<span className="rounded bg-blue-600 bg-opacity-10 px-1 text-blue-600">
{scenarios}
</span>{' '}
scenarios.
</div>

{isFeature && (
<>
{isCustom && creationStatus === 'created' && renderScenarioUsage(scenarios)}

{creationStatus === 'failure' && (
<div className="mt-1.5 text-xs text-red-600">Feature could not be processed</div>
)}

{creationStatus === 'running' && (
<div className="mt-1.5 text-xs text-gray-400">Feature is being processed...</div>
)}
</>
)}
{isCustom && !isFeature && renderScenarioUsage(scenarios)}
</td>
{tag && (
<td className="w-28 px-6 pb-2 pt-5 text-xs">
Expand All @@ -76,11 +95,16 @@ const RowItem = ({
)}
<td className="w-22 ml-auto pb-2 pl-1 pr-2 pt-5">
<div className="flex gap-6">
<button type="button" onClick={() => onToggleSeeOnMap(id)}>
<button
type="button"
onClick={() => onToggleSeeOnMap(id)}
disabled={isFeatureRunning || isFeatureFailed}
>
<Icon
className={cn({
'h-5 w-5 text-gray-600': true,
'text-blue-500': isVisibleOnMap,
'text-gray-700': isFeatureRunning || isFeatureFailed,
})}
icon={isVisibleOnMap ? SHOW_SVG : HIDE_SVG}
/>
Expand All @@ -98,8 +122,13 @@ const RowItem = ({
onClick={() => {
setIsMenuOpen((prevState) => !prevState);
}}
disabled={isFeatureRunning}
>
<HiDotsHorizontal className="pointer-events-none h-4 w-4 text-white" />
<HiDotsHorizontal
className={cn('pointer-events-none h-4 w-4 text-white', {
'text-gray-700': isFeatureRunning,
})}
/>
</button>
</PopoverTrigger>
<PopoverContent
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeEvent } from 'react';

import { Feature } from 'types/api/feature';
import { WDPA } from 'types/api/wdpa';

export type DataItem = {
Expand All @@ -10,6 +11,8 @@ export type DataItem = {
tag?: string;
isVisibleOnMap: boolean;
isCustom?: boolean;
creationStatus?: Feature['creationStatus'];
isFeature?: boolean;
};

export type InventoryTable = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ const ActionsMenu = ({
item,
onDismissMenu,
}: Parameters<ComponentProps<typeof RowItem>['ActionsComponent']>[0]): JSX.Element => {
const isDeletable = item.isCustom && !item.scenarios;
const isDeletable = (item.isCustom && !item.scenarios) || item.creationStatus === 'failure';

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

const isEditable = item.creationStatus === 'created';

const handleModal = useCallback(
(modalKey: keyof typeof modalState, isVisible: boolean) => {
setModalState((prevState) => {
Expand All @@ -51,9 +53,17 @@ const ActionsMenu = ({
className={cn({
[BUTTON_CLASSES]: true,
'rounded-t-2xl': true,
[BUTTON_DISABLED_CLASSES]: !isEditable,
})}
disabled={!isEditable}
>
<Icon icon={TAG_SVG} className={ICON_CLASSES} />
<Icon
icon={TAG_SVG}
className={cn({
[ICON_CLASSES]: true,
[ICON_DISABLED_CLASSES]: !isEditable,
})}
/>
<span>Edit</span>
</button>
<Modal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
{
...{
...filters,
includeInProgress: true,
// ? if tag sorting is chosen, sort by tag and then by name
...(['tag', '-tag'].includes(filters.sort) && {
sort: `${filters.sort},featureClassName`,
Expand All @@ -79,6 +80,12 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
isCustom: feature.isCustom,
color,
amountRange: feature.amountRange,
isFeature: true,
creationStatus: feature.creationStatus,
// ! keep for testing. Remove once done.
// creationStatus: 'created',
// creationStatus: 'running',
// creationStatus: 'failure',
};
});
},
Expand Down Expand Up @@ -195,13 +202,15 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
return d;
}, [allFeaturesQuery.data, layerSettings, selectedTag]);

const featureIds = data?.filter(({ isCustom }) => isCustom).map((feature) => feature.id);

const handleSelectAll = useCallback(
(evt: ChangeEvent<HTMLInputElement>) => {
setSelectedFeaturesIds(evt.target.checked ? featureIds : []);
const allSelectableFeatues = allFeaturesQuery.data
?.filter(({ isCustom, creationStatus }) => isCustom && creationStatus !== 'running')
.map(({ id }) => id);

setSelectedFeaturesIds(evt.target.checked ? allSelectableFeatues : []);
},
[featureIds]
[allFeaturesQuery.data]
);

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const DeleteModal = ({
Boolean(scenarioUsageCount)
);

const haveFeaturesRunning = selectedFeatures.some(
({ creationStatus }) => creationStatus === 'running'
);

const handleBulkDelete = useCallback(() => {
const deletableFeatureIds = selectedFeatures.map(({ id }) => id);

Expand Down Expand Up @@ -109,7 +113,8 @@ const DeleteModal = ({
<div className="flex items-center space-x-1.5 rounded border-l-[5px] border-red-700 bg-red-100/50 px-1.5 py-4">
<Icon className="h-10 w-10 text-red-700" icon={ALERT_SVG} />
<p className="font-sans text-xs font-medium text-black">
A feature can be deleted ONLY if it&apos;s not being used by any scenario
A feature can be deleted ONLY if it&apos;s not being used by any scenario and it is not
being processed at the moment of deletion.
</p>
</div>
<div className="flex w-full justify-between space-x-3 px-10 py-2">
Expand All @@ -120,7 +125,7 @@ const DeleteModal = ({
theme="danger-alt"
size="lg"
className="w-full"
disabled={haveScenarioAssociated}
disabled={haveScenarioAssociated || haveFeaturesRunning}
onClick={handleBulkDelete}
>
Delete
Expand Down
1 change: 1 addition & 0 deletions app/types/api/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export interface Feature {
min: number;
max: number;
};
creationStatus: 'created' | 'failure' | 'running';
}

0 comments on commit c4f971c

Please sign in to comment.