Skip to content

Commit

Permalink
fix(instance) move selection notification below table
Browse files Browse the repository at this point in the history
  • Loading branch information
edlerd committed Oct 10, 2023
1 parent 04ed261 commit cbe5af4
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 108 deletions.
20 changes: 17 additions & 3 deletions src/components/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { Button, Icon, Input, Select } from "@canonical/react-components";
import React, { FC, HTMLAttributes, useEffect, useState } from "react";
import React, {
FC,
HTMLAttributes,
ReactNode,
useEffect,
useState,
} from "react";
import { paginationOptions } from "util/pagination";
import useEventListener from "@use-it/event-listener";
import { MainTableRow } from "@canonical/react-components/dist/components/MainTable/MainTable";
import classnames from "classnames";

const figureSmallScreen = () => {
const descriptionElement = document.getElementById("pagination-description");
Expand All @@ -13,6 +20,7 @@ const figureSmallScreen = () => {
};

type Props = {
className?: string;
pageSize: number;
setPageSize: (val: number) => void;
currentPage: number;
Expand All @@ -25,9 +33,11 @@ type Props = {
itemsPerPage?: number;
totalItems?: number;
updateSort?: (sort?: string | null) => void;
selectedNotification?: ReactNode;
} & HTMLAttributes<HTMLDivElement>;

const Pagination: FC<Props> = ({
className,
pageSize,
setPageSize,
currentPage,
Expand All @@ -40,6 +50,7 @@ const Pagination: FC<Props> = ({
itemsPerPage: _itemsPerPage,
totalItems: _totalItems,
updateSort: _updateSort,
selectedNotification,
...divProps
}) => {
const [isSmallScreen, setSmallScreen] = useState(figureSmallScreen());
Expand All @@ -51,9 +62,11 @@ const Pagination: FC<Props> = ({
useEffect(resize, []);

return (
<div className="pagination" {...divProps}>
<div className={classnames("pagination", className)} {...divProps}>
<div className="description" id="pagination-description">
{isSmallScreen
{selectedNotification
? selectedNotification
: isSmallScreen
? `${visibleCount}\xa0out\xa0of\xa0${totalCount}`
: `Showing ${visibleCount} out of ${totalCount} ${keyword}${
totalCount !== 1 ? "s" : ""
Expand Down Expand Up @@ -105,6 +118,7 @@ const Pagination: FC<Props> = ({
<Icon name="chevron-down" />
</Button>
<Select
className="items-per-page"
label="Items per page"
labelClassName="u-off-screen"
id="itemsPerPage"
Expand Down
60 changes: 1 addition & 59 deletions src/components/SelectableMainTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,14 @@ import {
Props as MainTableProps,
} from "@canonical/react-components/dist/components/MainTable/MainTable";
import {
Button,
CheckboxInput,
ContextualMenu,
Icon,
MainTable,
Notification,
} from "@canonical/react-components";
import classnames from "classnames";

interface SelectableMainTableProps {
totalCount: number;
filteredNames: string[];
itemName: string;
parentName: string;
Expand All @@ -27,7 +24,6 @@ interface SelectableMainTableProps {
type Props = SelectableMainTableProps & MainTableProps;

const SelectableMainTable: FC<Props> = ({
totalCount,
filteredNames,
itemName,
parentName,
Expand Down Expand Up @@ -133,65 +129,11 @@ const SelectableMainTable: FC<Props> = ({
return row;
});

const selectionState = isSomeSelected
? [
{
className: "select-notification",
key: "select-info",
expanded: true,
expandedContent: (
<Notification
borderless
className="u-no-margin--bottom"
title="Selection"
>
{isAllSelected ? (
<>
{filteredNames.length === 1 ? (
<>
<b>1</b> {itemName} is selected.{" "}
</>
) : (
<>
All <b>{filteredNames.length}</b> {itemName}s selected.{" "}
</>
)}
<Button
appearance="link"
className="u-no-margin--bottom u-no-padding--top"
onClick={selectNone}
>
Clear selection
</Button>
</>
) : (
<>
<b>{selectedNames.length}</b> {itemName}
{selectedNames.length > 1 && "s"} selected.{" "}
<Button
appearance="link"
className="u-no-margin--bottom u-no-padding--top"
onClick={selectAll}
>
Select all <b>{filteredNames.length}</b>{" "}
{filteredNames.length === totalCount
? parentName
: "filtered"}{" "}
{itemName}s
</Button>
</>
)}
</Notification>
),
},
]
: [];

return (
<MainTable
expanding={true}
headers={headersWithCheckbox}
rows={[...selectionState, ...rowsWithCheckbox]}
rows={[...rowsWithCheckbox]}
{...props}
/>
);
Expand Down
71 changes: 71 additions & 0 deletions src/components/SelectedTableNotification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { FC } from "react";
import { Button } from "@canonical/react-components";

interface Props {
totalCount: number;
filteredNames: string[];
itemName: string;
parentName: string;
selectedNames: string[];
setSelectedNames: (val: string[]) => void;
}

const SelectedTableNotification: FC<Props> = ({
totalCount,
filteredNames,
itemName,
parentName,
selectedNames,
setSelectedNames,
}: Props) => {
const isAllSelected = selectedNames.length === filteredNames.length;

const selectAll = () => {
setSelectedNames(filteredNames);
};

const selectNone = () => {
setSelectedNames([]);
};

return (
<div>
{isAllSelected ? (
<>
{filteredNames.length === 1 ? (
<>
<b>1</b> {itemName} is selected.{" "}
</>
) : (
<>
All <b>{filteredNames.length}</b> {itemName}s selected.{" "}
</>
)}
<Button
appearance="link"
className="u-no-margin--bottom u-no-padding--top"
onClick={selectNone}
>
Clear selection
</Button>
</>
) : (
<>
<b>{selectedNames.length}</b> {itemName}
{selectedNames.length > 1 && "s"} selected.{" "}
<Button
appearance="link"
className="u-no-margin--bottom u-no-padding--top"
onClick={selectAll}
>
Select all <b>{filteredNames.length}</b>{" "}
{filteredNames.length === totalCount ? parentName : "filtered"}{" "}
{itemName}s
</Button>
</>
)}
</div>
);
};

export default SelectedTableNotification;
1 change: 0 additions & 1 deletion src/pages/cluster/ClusterGroupForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ const ClusterGroupForm: FC<Props> = ({ group }) => {
void formik.setFieldValue("members", newMembers)
}
processingNames={[]}
totalCount={members.length}
/>
</Col>
</Row>
Expand Down
50 changes: 27 additions & 23 deletions src/pages/instances/InstanceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
import { getInstanceName } from "util/operations";
import ScrollableTable from "components/ScrollableTable";
import NotificationRow from "components/NotificationRow";
import SelectedTableNotification from "components/SelectedTableNotification";
import CustomLayout from "components/CustomLayout";

const loadHidden = () => {
Expand Down Expand Up @@ -490,15 +491,6 @@ const InstanceList: FC = () => {
onStart={setProcessingNames}
onFinish={() => setProcessingNames([])}
/>
<Button
appearance="link"
className="clear-selection-btn u-no-margin--bottom u-no-padding--top"
hasIcon
onClick={() => setSelectedNames([])}
>
<span>Clear selection</span>
<Icon name="close" className="clear-selection-icon" />
</Button>
</>
)}
{hasInstances && selectedNames.length === 0 && (
Expand Down Expand Up @@ -530,6 +522,32 @@ const InstanceList: FC = () => {
<Col size={12}>
{hasInstances && (
<>
<Pagination
{...pagination}
id="pagination"
className="u-no-margin--top"
totalCount={totalInstanceCount}
selectedNotification={
selectedNames.length > 0 && (
<SelectedTableNotification
totalCount={totalInstanceCount}
itemName="instance"
parentName="project"
selectedNames={selectedNames}
setSelectedNames={setSelectedNames}
filteredNames={filteredInstances.map(
(instance) => instance.name
)}
/>
)
}
visibleCount={
filteredInstances.length === instances.length
? pagination.pageData.length
: filteredInstances.length + creationOperations.length
}
keyword="instance"
/>
<TableColumnsSelect
columns={[TYPE, DESCRIPTION, IPV4, IPV6, SNAPSHOTS]}
hidden={userHidden}
Expand All @@ -539,7 +557,6 @@ const InstanceList: FC = () => {
})}
/>
<ScrollableTable
belowId="pagination"
dependencies={[filteredInstances, notify.notification]}
>
<SelectableMainTable
Expand All @@ -558,24 +575,12 @@ const InstanceList: FC = () => {
selectedNames={selectedNames}
setSelectedNames={setSelectedNames}
processingNames={processingNames}
totalCount={instances.length}
filteredNames={filteredInstances.map(
(instance) => instance.name
)}
onUpdateSort={pagination.updateSort}
/>
</ScrollableTable>
<Pagination
{...pagination}
id="pagination"
totalCount={totalInstanceCount}
visibleCount={
filteredInstances.length === instances.length
? pagination.pageData.length
: filteredInstances.length + creationOperations.length
}
keyword="instance"
/>
<div id="instance-table-measure">
<SelectableMainTable
headers={getHeaders(userHidden)}
Expand All @@ -586,7 +591,6 @@ const InstanceList: FC = () => {
selectedNames={selectedNames}
setSelectedNames={setSelectedNames}
processingNames={processingNames}
totalCount={instances.length}
filteredNames={filteredInstances.map(
(instance) => instance.name
)}
Expand Down
1 change: 0 additions & 1 deletion src/pages/instances/InstanceSnapshots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ const InstanceSnapshots: FC<Props> = ({ instance }) => {
selectedNames={selectedNames}
setSelectedNames={setSelectedNames}
processingNames={processingNames}
totalCount={instance.snapshots?.length ?? 0}
filteredNames={filteredSnapshots.map((snapshot) => snapshot.name)}
onUpdateSort={pagination.updateSort}
defaultSort="created_at"
Expand Down
4 changes: 0 additions & 4 deletions src/sass/_cluster_group_form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@
}

.cluster-group-select-members {
.select-notification {
display: none;
}

.multiselect-checkbox {
margin-top: $spv--large;
}
Expand Down
15 changes: 5 additions & 10 deletions src/sass/_instance_list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,6 @@
}
}

@media screen and (max-width: 830px) {
.clear-selection-btn {
display: none;
}
}

.clear-selection-btn {
padding-top: 8px;
}

.instance-header-left {
display: flex;
flex: 2;
Expand All @@ -48,6 +38,7 @@
}

.search-wrapper {
margin-bottom: 3.5px !important; // to align with the selected instances state
max-width: 70vw;
width: 100%;
}
Expand Down Expand Up @@ -152,6 +143,10 @@
justify-content: flex-end;
}

.items-per-page {
margin-bottom: 0;
}

#instance-table-measure {
max-height: 1px;
overflow: hidden;
Expand Down
Loading

0 comments on commit cbe5af4

Please sign in to comment.