diff --git a/client/src/app/pages/controls/business-services/business-services.tsx b/client/src/app/pages/controls/business-services/business-services.tsx index ebd53acce..e45f556af 100644 --- a/client/src/app/pages/controls/business-services/business-services.tsx +++ b/client/src/app/pages/controls/business-services/business-services.tsx @@ -4,30 +4,22 @@ import { useTranslation } from "react-i18next"; import { Button, ButtonVariant, + EmptyState, + EmptyStateBody, + EmptyStateIcon, Modal, + Title, + Toolbar, + ToolbarContent, ToolbarGroup, ToolbarItem, } from "@patternfly/react-core"; -import { - cellWidth, - ICell, - IRow, - sortable, - TableText, -} from "@patternfly/react-table"; +import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table"; import { BusinessService } from "@app/api/models"; import { getAxiosErrorMessage } from "@app/utils/utils"; import { BusinessServiceForm } from "./components/business-service-form"; -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 { controlsWriteScopes, RBAC, RBAC_TYPE } from "@app/rbac"; +import { FilterToolbar, FilterType } from "@app/components/FilterToolbar"; import { useFetchApplications } from "@app/queries/applications"; import { useDeleteBusinessServiceMutation, @@ -37,11 +29,15 @@ import { NotificationsContext } from "@app/components/NotificationsContext"; import { AppTableActionButtons } from "@app/components/AppTableActionButtons"; import { ConditionalRender } from "@app/components/ConditionalRender"; import { AppPlaceholder } from "@app/components/AppPlaceholder"; -import { AppTableWithControls } from "@app/components/AppTableWithControls"; -import { NoDataEmptyState } from "@app/components/NoDataEmptyState"; import { ConfirmDialog } from "@app/components/ConfirmDialog"; - -const ENTITY_FIELD = "entity"; +import { useLocalTableControls } from "@app/hooks/table-controls"; +import { SimplePagination } from "@app/components/SimplePagination"; +import { + TableHeaderContentWithControls, + ConditionalTableBody, + TableRowContentWithControls, +} from "@app/components/TableControls"; +import { CubesIcon } from "@patternfly/react-icons"; export const BusinessServices: React.FC = () => { const { t } = useTranslation(); @@ -60,7 +56,7 @@ export const BusinessServices: React.FC = () => { const businessServiceToUpdate = createUpdateModalState !== "create" ? createUpdateModalState : null; - const onDeleteBusinessServiceSuccess = (response: any) => { + const onDeleteBusinessServiceSuccess = () => { pushNotification({ title: t("terms.businessServiceDeleted"), variant: "success", @@ -84,127 +80,88 @@ export const BusinessServices: React.FC = () => { const { data: applications } = useFetchApplications(); - const filterCategories: FilterCategory< - BusinessService, - "name" | "description" | "owner" - >[] = [ - { - 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: "owner", - title: t("terms.createdBy"), - type: FilterType.search, - placeholderText: - t("actions.filterBy", { - what: t("terms.owner").toLowerCase(), - }) + "...", - getItemValue: (item) => { - return item.owner?.name || ""; - }, - }, - ]; - - const { filterValues, setFilterValues, filteredItems } = useLegacyFilterState( - businessServices || [], - filterCategories - ); - const getSortValues = (businessService: BusinessService) => [ - businessService?.name || "", - businessService?.description || "", - businessService.owner?.name || "", - "", // Action column - ]; - - const { sortBy, onSort, sortedItems } = useLegacySortState( - filteredItems, - getSortValues - ); - - const { currentPageItems, setPageNumber, paginationProps } = - useLegacyPaginationState(sortedItems, 10); - - const columns: ICell[] = [ - { title: t("terms.name"), transforms: [sortable, cellWidth(25)] }, - { title: t("terms.description"), transforms: [cellWidth(40)] }, - { title: t("terms.owner"), transforms: [sortable] }, - { - title: "", - props: { - className: "pf-v5-u-text-align-right", - }, + const tableControls = useLocalTableControls({ + idProperty: "name", + items: businessServices, + columnNames: { + name: t("terms.name"), + description: t("terms.description"), + owner: t("terms.owner"), }, - ]; - - const rows: IRow[] = []; - currentPageItems?.forEach((item) => { - const isAssignedToApplication = applications?.some( - (app) => app.businessService?.id === item.id - ); - rows.push({ - [ENTITY_FIELD]: item, - cells: [ - { - title: {item.name}, + isFilterEnabled: true, + isSortEnabled: true, + isPaginationEnabled: true, + 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 || ""; }, - { - title: ( - {item.description} - ), - }, - { - title: ( - {item.owner?.name} - ), + }, + { + key: "description", + title: t("terms.description"), + type: FilterType.search, + placeholderText: + t("actions.filterBy", { + what: t("terms.description").toLowerCase(), + }) + "...", + getItemValue: (item) => { + return item.description || ""; }, - { - title: ( - setCreateUpdateModalState(item)} - onDelete={() => deleteRow(item)} - /> - ), + }, + { + key: "owner", + title: t("terms.createdBy"), + type: FilterType.search, + placeholderText: + t("actions.filterBy", { + what: t("terms.owner").toLowerCase(), + }) + "...", + getItemValue: (item) => { + return item.owner?.name || ""; }, - ], - }); + }, + ], + initialItemsPerPage: 10, + sortableColumns: ["name", "description", "owner"], + initialSort: { columnKey: "name", direction: "asc" }, + getSortValues: (item) => ({ + name: item?.name || "", + description: item?.description || "", + owner: item?.owner?.name || "", + }), + isLoading: isFetching, }); + const { + currentPageItems, + numRenderedColumns, + propHelpers: { + toolbarProps, + filterToolbarProps, + paginationToolbarItemProps, + paginationProps, + tableProps, + getThProps, + getTrProps, + getTdProps, + }, + expansionDerivedState: { isCellExpanded }, + } = tableControls; + const deleteRow = (row: BusinessService) => { setBusinessServiceToDelete(row); setIsConfirmDialogOpen(true); }; - // Advanced filters - - const handleOnClearAllFilters = () => { - setFilterValues({}); - }; - - // Update Modal - const closeCreateUpdateModal = () => { setCreateUpdateModalState(null); refetch; @@ -216,62 +173,121 @@ export const BusinessServices: React.FC = () => { when={isFetching && !(businessServices || fetchError)} then={} > - - } - toolbarActions={ - - - +
+ + + + + - + + + + - - } - noDataState={ - + + + + + + + + + + + {t("composed.noDataStateTitle", { + what: t("terms.businessService").toLowerCase(), + })} + + + {t("composed.noDataStateBody", { + what: t("terms.businessService").toLowerCase(), + })} + + + } + numRenderedColumns={numRenderedColumns} + > + {currentPageItems?.map((businessService, rowIndex) => { + const isAssignedToApplication = applications?.some( + (app) => app.businessService?.id === businessService.id + ); + return ( + + + + + + + + + + + ); })} - /> - } - /> + +
+ + + +
+ {businessService.name} + + {businessService.description} + + {businessService.owner?.name} + + + setCreateUpdateModalState(businessService) + } + onDelete={() => deleteRow(businessService)} + /> +
+ +