diff --git a/client/src/app/pages/archetypes/components/archetype-form/archetype-form.tsx b/client/src/app/pages/archetypes/components/archetype-form/archetype-form.tsx index 2c85a294d..ea6b02694 100644 --- a/client/src/app/pages/archetypes/components/archetype-form/archetype-form.tsx +++ b/client/src/app/pages/archetypes/components/archetype-form/archetype-form.tsx @@ -26,7 +26,7 @@ import { import { duplicateNameCheck, getAxiosErrorMessage } from "@app/utils/utils"; import { type TagItemType, useFetchTagsWithTagItems } from "@app/queries/tags"; -import { useFetchStakeholderGroups } from "@app/queries/stakeholdergoups"; +import { useFetchStakeholderGroups } from "@app/queries/stakeholdergroups"; import { useFetchStakeholders } from "@app/queries/stakeholders"; import { HookFormAutocomplete } from "@app/components/HookFormPFFields"; import { matchItemsToRefs } from "@app/utils/model-utils"; diff --git a/client/src/app/pages/assessment/components/assessment-stakeholders-form/assessment-stakeholders-form.tsx b/client/src/app/pages/assessment/components/assessment-stakeholders-form/assessment-stakeholders-form.tsx index 6a3b388ad..6231f92be 100644 --- a/client/src/app/pages/assessment/components/assessment-stakeholders-form/assessment-stakeholders-form.tsx +++ b/client/src/app/pages/assessment/components/assessment-stakeholders-form/assessment-stakeholders-form.tsx @@ -11,7 +11,7 @@ import { import { useFormContext } from "react-hook-form"; import { useFetchStakeholders } from "@app/queries/stakeholders"; -import { useFetchStakeholderGroups } from "@app/queries/stakeholdergoups"; +import { useFetchStakeholderGroups } from "@app/queries/stakeholdergroups"; import { HookFormAutocomplete } from "@app/components/HookFormPFFields"; import { AssessmentWizardValues } from "../assessment-wizard/assessment-wizard"; diff --git a/client/src/app/pages/controls/stakeholder-groups/components/stakeholder-group-form.tsx b/client/src/app/pages/controls/stakeholder-groups/components/stakeholder-group-form.tsx index bba35c11c..a24b086a1 100644 --- a/client/src/app/pages/controls/stakeholder-groups/components/stakeholder-group-form.tsx +++ b/client/src/app/pages/controls/stakeholder-groups/components/stakeholder-group-form.tsx @@ -21,7 +21,7 @@ import { useCreateStakeholderGroupMutation, useFetchStakeholderGroups, useUpdateStakeholderGroupMutation, -} from "@app/queries/stakeholdergoups"; +} from "@app/queries/stakeholdergroups"; import { useForm } from "react-hook-form"; import { yupResolver } from "@hookform/resolvers/yup"; import { diff --git a/client/src/app/pages/controls/stakeholder-groups/stakeholder-groups.tsx b/client/src/app/pages/controls/stakeholder-groups/stakeholder-groups.tsx index 0597cd1c1..f50721898 100644 --- a/client/src/app/pages/controls/stakeholder-groups/stakeholder-groups.tsx +++ b/client/src/app/pages/controls/stakeholder-groups/stakeholder-groups.tsx @@ -1,8 +1,6 @@ import React from "react"; import { AxiosError } from "axios"; import { useTranslation } from "react-i18next"; -import { useSelectionState } from "@migtools/lib-ui"; - import { Button, ButtonVariant, @@ -10,51 +8,50 @@ import { DescriptionListDescription, DescriptionListGroup, DescriptionListTerm, + EmptyState, + EmptyStateBody, + EmptyStateIcon, Modal, ModalVariant, + Title, + Toolbar, + ToolbarContent, ToolbarGroup, ToolbarItem, } from "@patternfly/react-core"; import { - cellWidth, - expandable, - ICell, - IExtraData, - IRow, - IRowData, - sortable, - TableText, + ExpandableRowContent, + Table, + Tbody, + Td, + Th, + Thead, + Tr, } from "@patternfly/react-table"; import { getAxiosErrorMessage, numStr } from "@app/utils/utils"; import { StakeholderGroup } from "@app/api/models"; -import { useLegacyPaginationState } from "@app/hooks/useLegacyPaginationState"; -import { - FilterCategory, - FilterToolbar, - FilterType, -} from "@app/components/FilterToolbar"; -import { useLegacyFilterState } from "@app/hooks/useLegacyFilterState"; -import { useLegacySortState } from "@app/hooks/useLegacySortState"; +import { FilterToolbar, FilterType } from "@app/components/FilterToolbar"; import { controlsWriteScopes, RBAC, RBAC_TYPE } from "@app/rbac"; import { useDeleteStakeholderGroupMutation, useFetchStakeholderGroups, -} from "@app/queries/stakeholdergoups"; +} from "@app/queries/stakeholdergroups"; import { NotificationsContext } from "@app/components/NotificationsContext"; import { StakeholderGroupForm } from "./components/stakeholder-group-form"; import { AppTableActionButtons } from "@app/components/AppTableActionButtons"; import { ConditionalRender } from "@app/components/ConditionalRender"; -import { AppTableWithControls } from "@app/components/AppTableWithControls"; import { AppPlaceholder } from "@app/components/AppPlaceholder"; -import { NoDataEmptyState } from "@app/components/NoDataEmptyState"; import { ConfirmDialog } from "@app/components/ConfirmDialog"; - -const ENTITY_FIELD = "entity"; - -const getRow = (rowData: IRowData): StakeholderGroup => { - return rowData[ENTITY_FIELD]; -}; +import { SimplePagination } from "@app/components/SimplePagination"; +import { + TableHeaderContentWithControls, + ConditionalTableBody, + TableRowContentWithControls, +} from "@app/components/TableControls"; +import { useLocalTableControls } from "@app/hooks/table-controls"; +import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing"; +import CubesIcon from "@patternfly/react-icons/dist/js/icons/cubes-icon"; export const StakeholderGroups: React.FC = () => { const { t } = useTranslation(); @@ -70,7 +67,7 @@ export const StakeholderGroups: React.FC = () => { const stakeholderGroupToUpdate = createUpdateModalState !== "create" ? createUpdateModalState : null; - const onDeleteStakeholderGroupSuccess = (response: any) => { + const onDeleteStakeholderGroupSuccess = () => { pushNotification({ title: t("terms.stakeholderGroupDeleted"), variant: "success", @@ -92,237 +89,246 @@ export const StakeholderGroups: React.FC = () => { const { stakeholderGroups, isFetching, fetchError, refetch } = useFetchStakeholderGroups(); - const { - isItemSelected: isItemExpanded, - toggleItemSelected: toggleItemExpanded, - } = useSelectionState({ - items: stakeholderGroups || [], - isEqual: (a, b) => a.id === b.id, - }); - - const columns: ICell[] = [ - { - title: t("terms.name"), - transforms: [sortable, cellWidth(30)], - cellFormatters: [expandable], - }, - { title: t("terms.description"), transforms: [sortable, cellWidth(35)] }, - { - title: t("terms.memberCount"), - transforms: [sortable], - }, - { - title: "", - props: { - className: "pf-v5-u-text-align-right", - }, - }, - ]; - - const filterCategories: FilterCategory< - StakeholderGroup, - "name" | "description" | "stakeholders" - >[] = [ - { - key: "name", - title: t("terms.name"), - type: FilterType.search, - placeholderText: - t("actions.filterBy", { - what: t("terms.name").toLowerCase(), - }) + "...", - getItemValue: (item) => { - return item?.name || ""; - }, - }, - { - key: "description", - title: t("terms.description"), - type: FilterType.search, - placeholderText: - t("actions.filterBy", { - what: t("terms.description").toLowerCase(), - }) + "...", - getItemValue: (item) => { - return item?.description || ""; - }, - }, - { - key: "stakeholders", - title: t("terms.stakeholders"), - type: FilterType.search, - placeholderText: - t("actions.filterBy", { - what: t("terms.stakeholders").toLowerCase(), - }) + "...", - getItemValue: (item) => { - const stakeholders = item.stakeholders?.map( - (stakeholder) => stakeholder.name - ); - return stakeholders?.join(" ; ") || ""; - }, - }, - ]; - const { filterValues, setFilterValues, filteredItems } = useLegacyFilterState( - stakeholderGroups || [], - filterCategories - ); - const getSortValues = (item: StakeholderGroup) => [ - "", - item?.name || "", - item?.description || "", - numStr(item?.stakeholders?.length), - "", // Action column - ]; - - const { sortBy, onSort, sortedItems } = useLegacySortState( - filteredItems, - getSortValues - ); - const { currentPageItems, setPageNumber, paginationProps } = - useLegacyPaginationState(sortedItems, 10); - - const rows: IRow[] = []; - currentPageItems?.forEach((item) => { - const isExpanded = isItemExpanded(item); - rows.push({ - [ENTITY_FIELD]: item, - isOpen: isExpanded, - cells: [ - { - title: {item.name}, - }, - { - title: ( - {item.description} - ), - }, - { - title: item.stakeholders ? item.stakeholders.length : 0, - }, - { - title: ( - setCreateUpdateModalState(item)} - onDelete={() => deleteRow(item)} - /> - ), - }, - ], - }); - - if (isExpanded) { - rows.push({ - parent: rows.length - 1, - fullWidth: false, - cells: [ -
- - - - {t("terms.member(s)")} - - - {item.stakeholders?.map((f) => f.name).join(", ")} - - - -
, - ], - }); - } - }); - - // Rows - - const collapseRow = ( - event: React.MouseEvent, - rowIndex: number, - isOpen: boolean, - rowData: IRowData, - extraData: IExtraData - ) => { - const row = getRow(rowData); - toggleItemExpanded(row); - }; - const deleteRow = (row: StakeholderGroup) => { setStakeholderGroupToDelete(row); }; - // Advanced filters - - const handleOnClearAllFilters = () => { - setFilterValues({}); - }; - const closeCreateUpdateModal = () => { setCreateUpdateModalState(null); refetch; }; - // t("terms.stakeholderGroup") + const tableControls = useLocalTableControls({ + idProperty: "name", + items: stakeholderGroups, + columnNames: { + displayName: "Display name", + description: "Description", + count: "Member count", + }, + isFilterEnabled: true, + isSortEnabled: true, + isPaginationEnabled: true, + isExpansionEnabled: true, + expandableVariant: "single", + hasActionsColumn: true, + filterCategories: [ + { + key: "name", + title: t("terms.name"), + type: FilterType.search, + placeholderText: + t("actions.filterBy", { + what: t("terms.name").toLowerCase(), + }) + "...", + getItemValue: (item) => { + return item?.name || ""; + }, + }, + { + key: "description", + title: t("terms.description"), + type: FilterType.search, + placeholderText: + t("actions.filterBy", { + what: t("terms.description").toLowerCase(), + }) + "...", + getItemValue: (item) => { + return item?.description || ""; + }, + }, + { + key: "stakeholders", + title: t("terms.stakeholders"), + type: FilterType.search, + placeholderText: + t("actions.filterBy", { + what: t("terms.stakeholders").toLowerCase(), + }) + "...", + getItemValue: (item) => { + const stakeholders = item.stakeholders?.map( + (stakeholder) => stakeholder.name + ); + return stakeholders?.join(" ; ") || ""; + }, + }, + ], + sortableColumns: ["displayName", "description", "count"], + getSortValues: (item) => ({ + displayName: item?.name || "", + description: item?.description || "", + count: numStr(item?.stakeholders?.length), + }), + initialSort: { columnKey: "displayName", direction: "asc" }, + isLoading: isFetching, + }); + + const { + currentPageItems, + numRenderedColumns, + propHelpers: { + toolbarProps, + filterToolbarProps, + paginationToolbarItemProps, + paginationProps, + tableProps, + getThProps, + getTrProps, + getTdProps, + getExpandedContentTdProps, + }, + expansionDerivedState: { isCellExpanded }, + } = tableControls; + return ( <> } > - - } - toolbarActions={ - - - - - + + + + + + - - } - noDataState={ - + + + + + + + + + + + {t("composed.noDataStateTitle", { + what: t("terms.stakeholder").toLowerCase(), + })} + + + {t("composed.noDataStateBody", { + what: t("terms.stakeholder").toLowerCase(), + })} + + + } + numRenderedColumns={numRenderedColumns} + > + {currentPageItems?.map((stakeholderGroup, rowIndex) => { + return ( + + + + + + + + + + {isCellExpanded(stakeholderGroup) ? ( + + + + ) : null} + + ); })} - /> - } - /> + +
+ + + +
+ {stakeholderGroup.name} + + {stakeholderGroup.description} + + {stakeholderGroup.stakeholders?.length} + + + setCreateUpdateModalState(stakeholderGroup) + } + onDelete={() => deleteRow(stakeholderGroup)} + /> +
+ + + + + + {t("terms.member(s)")} + + {!!stakeholderGroup.stakeholders?.length && ( + + {stakeholderGroup.stakeholders + ?.map((f) => f.name) + .join(", ")} + + )} + + + +
+ +
- {