Frontend: Consolidate table button props into objects (#11586)

This commit is contained in:
RachelElysia
2023-05-11 15:25:56 -04:00
committed by GitHub
parent 28600be584
commit 7470ea8dac
21 changed files with 131 additions and 133 deletions
@@ -1,5 +1,5 @@
import React, { useCallback } from "react";
import { kebabCase } from "lodash";
import { kebabCase, noop } from "lodash";
import PremiumFeatureIconWithTooltip from "components/PremiumFeatureIconWithTooltip";
import { ButtonVariant } from "components/buttons/Button/Button";
@@ -13,8 +13,8 @@ import TransferIcon from "../../../../../assets/images/icon-action-transfer-16x1
const baseClass = "action-button";
export interface IActionButtonProps {
name: string;
buttonText: string;
onActionButtonClick: (ids: number[]) => void | undefined;
buttonText: string | ((targetIds: number[]) => string);
onActionButtonClick?: (ids: number[]) => void;
targetIds?: number[]; // TODO figure out undefined case
variant?: ButtonVariant;
hideButton?: boolean | ((targetIds: number[]) => boolean);
@@ -46,7 +46,7 @@ const ActionButton = (buttonProps: IActionButtonProps): JSX.Element | null => {
iconPosition,
indicatePremiumFeature,
} = buttonProps;
const onButtonClick = useActionCallback(onActionButtonClick);
const onButtonClick = useActionCallback(onActionButtonClick || noop);
const iconLink = ((iconProp) => {
// check if using pre-defined short-hand otherwise otherwise return the prop
@@ -31,7 +31,6 @@ describe("DataTable - component", () => {
resultsTitle="users"
defaultPageSize={DEFAULT_PAGE_SIZE}
disableMultiRowSelect={false}
onPrimarySelectActionClick={noop}
/>
);
@@ -74,7 +73,6 @@ describe("DataTable - component", () => {
resultsTitle="users"
defaultPageSize={DEFAULT_PAGE_SIZE}
disableMultiRowSelect={false}
onPrimarySelectActionClick={noop}
/>
);
@@ -101,7 +99,6 @@ describe("DataTable - component", () => {
resultsTitle="users"
defaultPageSize={DEFAULT_PAGE_SIZE}
disableMultiRowSelect={false}
onPrimarySelectActionClick={noop}
/>
);
@@ -136,7 +133,6 @@ describe("DataTable - component", () => {
resultsTitle="users"
defaultPageSize={DEFAULT_PAGE_SIZE}
disableMultiRowSelect={false}
onPrimarySelectActionClick={noop}
/>
);
@@ -160,7 +156,6 @@ describe("DataTable - component", () => {
resultsTitle="users"
defaultPageSize={DEFAULT_PAGE_SIZE}
disableMultiRowSelect={false}
onPrimarySelectActionClick={noop}
/>
);
@@ -48,10 +48,7 @@ interface IDataTableProps {
resultsTitle: string;
defaultPageSize: number;
defaultPageIndex?: number;
primarySelectActionButtonVariant?: ButtonVariant;
primarySelectActionButtonIcon?: string;
primarySelectActionButtonText?: string | ((targetIds: number[]) => string);
onPrimarySelectActionClick: any; // figure out type
primarySelectAction?: IActionButtonProps;
secondarySelectActions?: IActionButtonProps[];
isClientSidePagination?: boolean;
onClientSidePaginationChange?: (pageIndex: number) => void; // Used to set URL to correct path and include page query param
@@ -91,10 +88,7 @@ const DataTable = ({
resultsTitle,
defaultPageSize,
defaultPageIndex,
primarySelectActionButtonIcon,
primarySelectActionButtonVariant,
onPrimarySelectActionClick,
primarySelectActionButtonText,
primarySelectAction,
secondarySelectActions,
isClientSidePagination,
onClientSidePaginationChange,
@@ -403,18 +397,18 @@ const DataTable = ({
const renderPrimarySelectAction = (): JSX.Element | null => {
const targetIds = selectedFlatRows.map((row: any) => row.original.id);
const buttonText =
typeof primarySelectActionButtonText === "function"
? primarySelectActionButtonText(targetIds)
: primarySelectActionButtonText;
typeof primarySelectAction?.buttonText === "function"
? primarySelectAction?.buttonText(targetIds)
: primarySelectAction?.buttonText;
const name = buttonText ? kebabCase(buttonText) : "primary-select-action";
const actionProps = {
name,
buttonText: buttonText || "",
onActionButtonClick: onPrimarySelectActionClick,
onActionButtonClick: primarySelectAction?.onActionButtonClick || noop,
targetIds,
variant: primarySelectActionButtonVariant,
icon: primarySelectActionButtonIcon,
variant: primarySelectAction?.variant,
icon: primarySelectAction?.icon,
};
return !buttonText ? null : renderActionButton(actionProps);
@@ -482,8 +476,7 @@ const DataTable = ({
{secondarySelectActions && renderSecondarySelectActions()}
</div>
<div className={"active-selection__inner-right"}>
{primarySelectActionButtonText &&
renderPrimarySelectAction()}
{primarySelectAction && renderPrimarySelectAction()}
</div>
{toggleAllPagesSelected && renderAreAllSelected()}
{shouldRenderToggleAllPages && (
@@ -36,10 +36,8 @@ interface ITableContainerProps {
defaultSortDirection?: string;
defaultSearchQuery?: string;
defaultPageIndex?: number;
actionButtonText?: string;
actionButtonIcon?: string;
actionButtonVariant?: ButtonVariant;
hideActionButton?: boolean;
/** Button visible above the table container next to search bar */
actionButton?: IActionButtonProps;
inputPlaceHolder?: string;
disableActionButton?: boolean;
disableMultiRowSelect?: boolean;
@@ -59,26 +57,26 @@ interface ITableContainerProps {
// The old page controls for server-side pagination render a no results screen
// with a back button. This fix instead disables the next button in that case.
disableCount?: boolean;
primarySelectActionButtonVariant?: ButtonVariant;
primarySelectActionButtonIcon?: string;
primarySelectActionButtonText?: string | ((targetIds: number[]) => string);
secondarySelectActions?: IActionButtonProps[]; // TODO create table actions interface
/** Main button after selecting a row */
primarySelectAction?: IActionButtonProps;
/** Secondary button/s after selecting a row */
secondarySelectActions?: IActionButtonProps[]; // TODO: Combine with primarySelectAction as these are all rendered in the same spot
filteredCount?: number;
searchToolTipText?: string;
searchQueryColumn?: string;
selectedDropdownFilter?: string;
isClientSidePagination?: boolean;
onClientSidePaginationChange?: (pageIndex: number) => void; // Used to set URL to correct path and include page query param
/** Used to set URL to correct path and include page query param */
onClientSidePaginationChange?: (pageIndex: number) => void;
isClientSideFilter?: boolean;
isMultiColumnFilter?: boolean; // isMultiColumnFilter is used to preserve the table headers
// in lieu of displaying the empty component when client-side filtering yields zero results
/** isMultiColumnFilter is used to preserve the table headers
in lieu of displaying the empty component when client-side filtering yields zero results */
isMultiColumnFilter?: boolean;
disableHighlightOnHover?: boolean;
pageSize?: number;
onActionButtonClick?: () => void;
onQueryChange?:
| ((queryData: ITableQueryData) => void)
| ((queryData: ITableQueryData) => number);
onPrimarySelectActionClick?: (selectedItemIds: number[]) => void;
customControl?: () => JSX.Element;
stackControls?: boolean;
onSelectSingleRow?: (value: Row | IRowProps) => void;
@@ -113,10 +111,7 @@ const TableContainer = ({
className,
disableActionButton,
disableMultiRowSelect = false,
actionButtonText,
actionButtonIcon,
actionButtonVariant = "brand",
hideActionButton,
actionButton,
showMarkAllPages,
isAllPagesSelected,
toggleAllPagesSelected,
@@ -125,9 +120,7 @@ const TableContainer = ({
disablePagination,
disableNextPage,
disableCount,
primarySelectActionButtonVariant = "brand",
primarySelectActionButtonIcon,
primarySelectActionButtonText,
primarySelectAction,
secondarySelectActions,
filteredCount,
searchToolTipText,
@@ -139,9 +132,7 @@ const TableContainer = ({
pageSize = DEFAULT_PAGE_SIZE,
selectedDropdownFilter,
searchQueryColumn,
onActionButtonClick,
onQueryChange,
onPrimarySelectActionClick,
customControl,
stackControls,
onSelectSingleRow,
@@ -333,19 +324,19 @@ const TableContainer = ({
)}
</span>
<span className={"controls"}>
{!hideActionButton && actionButtonText && (
{actionButton && !actionButton.hideButton && (
<Button
disabled={disableActionButton}
onClick={onActionButtonClick}
variant={actionButtonVariant}
onClick={actionButton.onActionButtonClick}
variant={actionButton.variant}
className={`${baseClass}__table-action-button`}
>
<>
{actionButtonText}
{actionButtonIcon && (
{actionButton.buttonText}
{actionButton.icon && (
<img
src={actionButtonIcon}
alt={`${actionButtonText} icon`}
src={actionButton.icon}
alt={`${actionButton.buttonText} icon`}
/>
)}
</>
@@ -436,12 +427,7 @@ const TableContainer = ({
resultsTitle={resultsTitle}
defaultPageSize={pageSize}
defaultPageIndex={defaultPageIndex}
primarySelectActionButtonVariant={
primarySelectActionButtonVariant
}
primarySelectActionButtonIcon={primarySelectActionButtonIcon}
primarySelectActionButtonText={primarySelectActionButtonText}
onPrimarySelectActionClick={onPrimarySelectActionClick}
primarySelectAction={primarySelectAction}
secondarySelectActions={secondarySelectActions}
onSelectSingleRow={onSelectSingleRow}
onResultsCountChange={onResultsCountChange}
@@ -90,14 +90,20 @@ const PackQueriesTable = ({
})
}
showMarkAllPages={false}
actionButtonText={"Add query"}
actionButtonIcon={AddQueryIcon}
actionButtonVariant={"text-icon"}
onActionButtonClick={onAddPackQuery}
onPrimarySelectActionClick={onRemovePackQueries}
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="close"
primarySelectActionButtonText={"Remove"}
actionButton={{
name: "add query",
buttonText: "Add query",
icon: AddQueryIcon,
variant: "text-icon",
onActionButtonClick: onAddPackQuery,
}}
primarySelectAction={{
name: "remove query",
buttonText: "Remove",
icon: "close",
variant: "text-icon",
onActionButtonClick: onRemovePackQueries,
}}
searchable
disablePagination
isAllPagesSelected={false}
@@ -117,14 +117,12 @@ const Mdm = ({
isLoading={isFetching}
defaultSortHeader={SOLUTIONS_DEFAULT_SORT_HEADER}
defaultSortDirection={DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"MDM"}
emptyComponent={EmptyMdmSolutions}
showMarkAllPages={false}
isAllPagesSelected={false}
isClientSidePagination
disableCount
disableActionButton
pageSize={PAGE_SIZE}
/>
)}
@@ -139,13 +137,11 @@ const Mdm = ({
isLoading={isFetching}
defaultSortHeader={STATUS_DEFAULT_SORT_HEADER}
defaultSortDirection={STATUS_DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"MDM"}
emptyComponent={EmptyMdmStatus}
showMarkAllPages={false}
isAllPagesSelected={false}
disableCount
disableActionButton
disablePagination
pageSize={PAGE_SIZE}
/>
@@ -74,7 +74,6 @@ const Munki = ({
isLoading={isMacAdminsFetching}
defaultSortHeader={DEFAULT_SORT_HEADER}
defaultSortDirection={DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"Munki"}
emptyComponent={() => (
<EmptyTable
@@ -87,7 +86,6 @@ const Munki = ({
isAllPagesSelected={false}
isClientSidePagination
disableCount
disableActionButton
disablePagination
pageSize={PAGE_SIZE}
/>
@@ -103,7 +101,6 @@ const Munki = ({
isLoading={isMacAdminsFetching}
defaultSortHeader={DEFAULT_SORT_HEADER}
defaultSortDirection={DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"Munki"}
emptyComponent={() => (
<EmptyTable
@@ -125,7 +122,6 @@ const Munki = ({
isAllPagesSelected={false}
isClientSidePagination
disableCount
disableActionButton
disablePagination
pageSize={PAGE_SIZE}
/>
@@ -157,13 +157,11 @@ const OperatingSystems = ({
isLoading={isFetching}
defaultSortHeader={DEFAULT_SORT_HEADER}
defaultSortDirection={DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"Operating systems"}
emptyComponent={() => EmptyOperatingSystems(selectedPlatform)}
showMarkAllPages={false}
isAllPagesSelected={false}
disableCount
disableActionButton
isClientSidePagination={showPaginationControls}
disablePagination={!showPaginationControls}
pageSize={PAGE_SIZE}
@@ -94,7 +94,6 @@ const Software = ({
isLoading={isSoftwareFetching}
defaultSortHeader={SOFTWARE_DEFAULT_SORT_DIRECTION}
defaultSortDirection={SOFTWARE_DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"software"}
emptyComponent={() => (
<EmptySoftwareTable
@@ -105,7 +104,6 @@ const Software = ({
showMarkAllPages={false}
isAllPagesSelected={false}
disableCount
disableActionButton
pageSize={SOFTWARE_DEFAULT_PAGE_SIZE}
onQueryChange={onQueryChange}
disableMultiRowSelect
@@ -123,7 +121,6 @@ const Software = ({
isLoading={isSoftwareFetching}
defaultSortHeader={SOFTWARE_DEFAULT_SORT_HEADER}
defaultSortDirection={SOFTWARE_DEFAULT_SORT_DIRECTION}
hideActionButton
resultsTitle={"software"}
emptyComponent={() => (
<EmptySoftwareTable
@@ -135,7 +132,6 @@ const Software = ({
showMarkAllPages={false}
isAllPagesSelected={false}
disableCount
disableActionButton
pageSize={SOFTWARE_DEFAULT_PAGE_SIZE}
onQueryChange={onQueryChange}
disableMultiRowSelect
@@ -412,10 +412,13 @@ const Integrations = (): JSX.Element => {
isLoading={isLoadingIntegrations}
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
actionButtonText={"Add integration"}
hideActionButton={!tableData?.length}
actionButtonVariant={"brand"}
onActionButtonClick={toggleAddIntegrationModal}
actionButton={{
name: "add integration",
buttonText: "Add integration",
variant: "brand",
onActionButtonClick: toggleAddIntegrationModal,
hideButton: !tableData?.length,
}}
resultsTitle={"integrations"}
emptyComponent={() =>
EmptyTable({
@@ -436,12 +436,15 @@ const MembersPage = ({ location, router }: IMembersPageProps): JSX.Element => {
isLoading={isLoadingMembers}
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
onActionButtonClick={
isGlobalAdmin ? toggleAddUserModal : toggleCreateMemberModal
}
actionButtonText={isGlobalAdmin ? "Add member" : "Create user"}
actionButtonVariant={"brand"}
hideActionButton={memberIds.length === 0 && searchString === ""}
actionButton={{
name: isGlobalAdmin ? "add member" : "create user",
buttonText: isGlobalAdmin ? "Add member" : "Create user",
variant: "brand",
onActionButtonClick: isGlobalAdmin
? toggleAddUserModal
: toggleCreateMemberModal,
hideButton: memberIds.length === 0 && searchString === "",
}}
onQueryChange={({ searchQuery }) => setSearchString(searchQuery)}
inputPlaceHolder={"Search"}
emptyComponent={() =>
@@ -276,12 +276,13 @@ const TeamManagementPage = (): JSX.Element => {
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
inputPlaceHolder={"Search"}
actionButtonText={"Create team"}
actionButtonVariant={"brand"}
hideActionButton={
teams && teams.length === 0 && searchString === ""
}
onActionButtonClick={toggleCreateTeamModal}
actionButton={{
name: "create team",
buttonText: "Create team",
variant: "brand",
onActionButtonClick: toggleCreateTeamModal,
hideButton: teams && teams.length === 0 && searchString === "",
}}
onQueryChange={onQueryChange}
resultsTitle={"teams"}
emptyComponent={() =>
@@ -538,8 +538,11 @@ const UsersTable = ({ router }: IUsersTableProps): JSX.Element => {
defaultSortHeader={"name"}
defaultSortDirection={"asc"}
inputPlaceHolder={"Search"}
actionButtonText={"Create user"}
onActionButtonClick={toggleCreateUserModal}
actionButton={{
name: "create user",
buttonText: "Create user",
onActionButtonClick: toggleCreateUserModal,
}}
onQueryChange={onTableQueryChange}
resultsTitle={"users"}
emptyComponent={() => EmptyTable(emptyState)}
@@ -1448,14 +1448,22 @@ const ManageHostsPage = ({
defaultPageIndex={page || DEFAULT_PAGE_INDEX}
defaultSearchQuery={searchQuery}
pageSize={50}
actionButtonText="Edit columns"
actionButtonIcon={EditColumnsIcon}
actionButtonVariant="text-icon"
additionalQueries={JSON.stringify(selectedFilters)}
inputPlaceHolder={HOSTS_SEARCH_BOX_PLACEHOLDER}
primarySelectActionButtonText="Delete"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonVariant={"text-icon"}
actionButton={{
name: "edit columns",
buttonText: "Edit columns",
icon: EditColumnsIcon,
variant: "text-icon",
onActionButtonClick: toggleEditColumnsModal,
}}
primarySelectAction={{
name: "delete host",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
onActionButtonClick: onDeleteHostsClick,
}}
secondarySelectActions={secondarySelectActions}
showMarkAllPages
isAllPagesSelected={isAllMatchingHostsSelected}
@@ -1469,8 +1477,6 @@ const ManageHostsPage = ({
})
}
customControl={renderCustomControls}
onActionButtonClick={toggleEditColumnsModal}
onPrimarySelectActionClick={onDeleteHostsClick}
onQueryChange={onTableQueryChange}
toggleAllPagesSelected={toggleAllMatchingHosts}
resetPageIndex={resetPageIndex}
@@ -115,10 +115,13 @@ const PacksTable = ({
inputPlaceHolder="Search by name"
searchable={packs && packs.length > 0}
disablePagination
onPrimarySelectActionClick={onDeletePackClick}
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonText={"Delete"}
primarySelectAction={{
name: "delete pack",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
onActionButtonClick: onDeletePackClick,
}}
secondarySelectActions={secondarySelectActions}
emptyComponent={() =>
EmptyTable({
@@ -145,10 +145,13 @@ const PoliciesTable = ({
manualSortBy
showMarkAllPages={false}
isAllPagesSelected={false}
onPrimarySelectActionClick={onDeletePolicyClick}
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonText={"Delete"}
primarySelectAction={{
name: "delete policy",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
onActionButtonClick: onDeletePolicyClick,
}}
emptyComponent={() =>
EmptyTable({
iconName: emptyState().iconName,
@@ -49,9 +49,12 @@ const PoliciesTable = ({
showMarkAllPages={false}
isAllPagesSelected={false}
disablePagination
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonText={"Delete"}
primarySelectAction={{
name: "delete policy",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
}}
emptyComponent={NoPolicyQueries}
onQueryChange={noop}
disableCount
@@ -48,9 +48,12 @@ const PoliciesTable = ({
showMarkAllPages={false}
isAllPagesSelected={false}
isClientSidePagination
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonText={"Delete"}
primarySelectAction={{
name: "delete policy",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
}}
emptyComponent={NoPolicyQueries}
onQueryChange={noop}
disableCount
@@ -301,10 +301,13 @@ const QueriesTable = ({
isClientSidePagination
onClientSidePaginationChange={onClientSidePaginationChange}
isClientSideFilter
onPrimarySelectActionClick={onDeleteQueryClick}
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="delete"
primarySelectActionButtonText="Delete"
primarySelectAction={{
name: "delete query",
buttonText: "Delete",
icon: "delete",
variant: "text-icon",
onActionButtonClick: onDeleteQueryClick,
}}
selectedDropdownFilter={platform}
/>
</div>
@@ -31,7 +31,7 @@ const TAGGED_TEMPLATES = {
};
interface IScheduleTableProps {
router: InjectedRouter; // v3
onRemoveScheduledQueryClick?: (selectIds: number[]) => void;
onRemoveScheduledQueryClick?: (selectedIds: number[]) => void;
onEditScheduledQueryClick?: (selectedQuery: IEditScheduledQuery) => void;
onShowQueryClick?: (selectedQuery: IEditScheduledQuery) => void;
allScheduledQueriesList: IScheduledQuery[];
@@ -198,10 +198,13 @@ const ScheduleTable = ({
isAllPagesSelected={false}
inputPlaceHolder="Search"
searchable={false}
onPrimarySelectActionClick={onRemoveScheduledQueryClick}
primarySelectActionButtonVariant="text-icon"
primarySelectActionButtonIcon="remove"
primarySelectActionButtonText={"Remove"}
primarySelectAction={{
name: "remove scheduled query",
buttonText: "Remove",
icon: "remove",
variant: "text-icon",
onActionButtonClick: onRemoveScheduledQueryClick,
}}
emptyComponent={() =>
EmptyTable({
iconName: emptyState().iconName,
@@ -692,8 +692,6 @@ const ManageSoftwarePage = ({
stackControls
renderCount={renderSoftwareCount}
renderFooter={renderTableFooter}
disableActionButton
hideActionButton
disableMultiRowSelect
onSelectSingleRow={handleRowSelect}
/>