Skip to content

Commit

Permalink
feat(instance) add cluster member column and filter to instance list (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
edlerd authored Nov 1, 2024
2 parents 7dfe60f + e174532 commit e5d0067
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 21 deletions.
76 changes: 58 additions & 18 deletions src/pages/instances/InstanceList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
DESCRIPTION,
IPV4,
IPV6,
CLUSTER_MEMBER,
NAME,
SIZE_HIDEABLE_COLUMNS,
SNAPSHOTS,
Expand All @@ -58,6 +59,8 @@ import useSortTableData from "util/useSortTableData";
import PageHeader from "components/PageHeader";
import InstanceDetailPanel from "./InstanceDetailPanel";
import { useSmallScreen } from "context/useSmallScreen";
import { useSettings } from "context/useSettings";
import { isClusteredServer } from "util/settings";

const loadHidden = () => {
const saved = localStorage.getItem("instanceListHiddenColumns");
Expand All @@ -80,6 +83,8 @@ const InstanceList: FC = () => {
const [createButtonLabel, _setCreateButtonLabel] =
useState<string>("Create instance");
const [searchParams] = useSearchParams();
const { data: settings } = useSettings();
const isClustered = isClusteredServer(settings);

const filters: InstanceFilters = {
queries: searchParams.getAll("query"),
Expand All @@ -89,7 +94,8 @@ const InstanceList: FC = () => {
types: searchParams
.getAll("type")
.map((value) => (value === "VM" ? "virtual-machine" : "container")),
profileQueries: searchParams.getAll("profile"),
profiles: searchParams.getAll("profile"),
clusterMembers: searchParams.getAll("member"),
};
const [userHidden, setUserHidden] = useState<string[]>(loadHidden());
const [sizeHidden, setSizeHidden] = useState<string[]>([]);
Expand Down Expand Up @@ -178,10 +184,14 @@ const InstanceList: FC = () => {
return false;
}
if (
filters.profileQueries.length > 0 &&
!filters.profileQueries.every((profile) =>
item.profiles.includes(profile),
)
filters.profiles.length > 0 &&
!filters.profiles.every((profile) => item.profiles.includes(profile))
) {
return false;
}
if (
filters.clusterMembers.length > 0 &&
!filters.clusterMembers.includes(item.location)
) {
return false;
}
Expand Down Expand Up @@ -212,6 +222,15 @@ const InstanceList: FC = () => {
sortKey: "type",
style: { width: `${COLUMN_WIDTHS[TYPE]}px` },
},
...(isClustered
? [
{
content: CLUSTER_MEMBER,
sortKey: "member",
style: { width: `${COLUMN_WIDTHS[CLUSTER_MEMBER]}px` },
},
]
: []),
{
content: DESCRIPTION,
sortKey: "description",
Expand Down Expand Up @@ -262,7 +281,7 @@ const InstanceList: FC = () => {
content: getInstanceName(operation),
className: "u-truncate",
title: getInstanceName(operation),
role: "rowheader",
role: "cell",
"aria-label": NAME,
style: { width: `${COLUMN_WIDTHS[NAME]}px` },
},
Expand All @@ -280,7 +299,7 @@ const InstanceList: FC = () => {
))}
</i>
),
role: "rowheader",
role: "cell",
colSpan: 5 - hiddenCols.length,
style: { width: `${spannedWidth}px` },
},
Expand All @@ -295,7 +314,7 @@ const InstanceList: FC = () => {
<Spinner className="status-icon" /> Setting up
</>
),
role: "rowheader",
role: "cell",
"aria-label": STATUS,
style: { width: `${COLUMN_WIDTHS[STATUS]}px` },
},
Expand All @@ -304,7 +323,7 @@ const InstanceList: FC = () => {
content: (
<CancelOperationBtn operation={operation} project={project} />
),
role: "rowheader",
role: "cell",
className: classnames("u-align--right", {
"u-hide": panelParams.instance,
}),
Expand Down Expand Up @@ -338,7 +357,7 @@ const InstanceList: FC = () => {
content: <InstanceLink instance={instance} />,
className: "u-truncate",
title: `Instance ${instance.name}`,
role: "rowheader",
role: "cell",
style: { width: `${COLUMN_WIDTHS[NAME]}px` },
"aria-label": NAME,
onClick: openSummary,
Expand All @@ -353,51 +372,64 @@ const InstanceList: FC = () => {
}
</>
),
role: "rowheader",
role: "cell",
"aria-label": TYPE,
onClick: openSummary,
className: "clickable-cell",
style: { width: `${COLUMN_WIDTHS[TYPE]}px` },
},
...(isClustered
? [
{
content: instance.location,
role: "cell",
"aria-label": CLUSTER_MEMBER,
onClick: openSummary,
className: "clickable-cell u-truncate",
title: instance.location,
style: { width: `${COLUMN_WIDTHS[CLUSTER_MEMBER]}px` },
},
]
: []),
{
content: (
<div className="u-truncate" title={instance.description}>
{instance.description}
</div>
),
role: "rowheader",
role: "cell",
"aria-label": DESCRIPTION,
onClick: openSummary,
className: "clickable-cell",
style: { width: `${COLUMN_WIDTHS[DESCRIPTION]}px` },
},
{
content: ipv4.length > 1 ? `${ipv4.length} addresses` : ipv4,
role: "rowheader",
role: "cell",
className: "u-align--right clickable-cell",
"aria-label": IPV4,
onClick: openSummary,
style: { width: `${COLUMN_WIDTHS[IPV4]}px` },
},
{
content: ipv6.length > 1 ? `${ipv6.length} addresses` : ipv6,
role: "rowheader",
role: "cell",
"aria-label": IPV6,
onClick: openSummary,
className: "clickable-cell",
style: { width: `${COLUMN_WIDTHS[IPV6]}px` },
},
{
content: instance.snapshots?.length ?? "0",
role: "rowheader",
role: "cell",
className: "u-align--right clickable-cell",
"aria-label": SNAPSHOTS,
onClick: openSummary,
style: { width: `${COLUMN_WIDTHS[SNAPSHOTS]}px` },
},
{
content: <InstanceStatusIcon instance={instance} />,
role: "rowheader",
role: "cell",
className: "clickable-cell",
"aria-label": STATUS,
onClick: openSummary,
Expand All @@ -416,7 +448,7 @@ const InstanceList: FC = () => {
instance={instance}
/>
),
role: "rowheader",
role: "cell",
className: classnames("u-align--right", {
"u-hide": panelParams.instance,
}),
Expand All @@ -426,6 +458,7 @@ const InstanceList: FC = () => {
].filter((item) => !hiddenCols.includes(item["aria-label"])),
sortData: {
name: instance.name.toLowerCase(),
member: instance.location,
description: instance.description.toLowerCase(),
status: instance.status,
type: instance.type,
Expand Down Expand Up @@ -579,7 +612,14 @@ const InstanceList: FC = () => {
}
>
<TableColumnsSelect
columns={[TYPE, DESCRIPTION, IPV4, IPV6, SNAPSHOTS]}
columns={[
TYPE,
CLUSTER_MEMBER,
DESCRIPTION,
IPV4,
IPV6,
SNAPSHOTS,
]}
hidden={userHidden}
sizeHidden={sizeHidden}
setHidden={setHidden}
Expand Down
22 changes: 21 additions & 1 deletion src/pages/instances/InstanceSearchFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,34 @@ import {
paramsFromSearchData,
searchParamsToChips,
} from "util/searchAndFilter";
import { useSettings } from "context/useSettings";
import { isClusteredServer } from "util/settings";

export const QUERY = "query";
export const STATUS = "status";
export const TYPE = "type";
export const PROFILE = "profile";
export const CLUSTER_MEMBER = "member";

const QUERY_PARAMS = [QUERY, STATUS, TYPE, PROFILE];
const QUERY_PARAMS = [QUERY, STATUS, TYPE, PROFILE, CLUSTER_MEMBER];

interface Props {
instances: LxdInstance[];
}

const InstanceSearchFilter: FC<Props> = ({ instances }) => {
const [searchParams, setSearchParams] = useSearchParams();
const { data: settings } = useSettings();
const isClustered = isClusteredServer(settings);

const profileSet = [
...new Set(instances.flatMap((instance) => instance.profiles)),
];

const locationSet = [
...new Set(instances.flatMap((instance) => instance.location)),
];

const searchAndFilterData: SearchAndFilterData[] = [
{
id: 1,
Expand All @@ -52,6 +61,17 @@ const InstanceSearchFilter: FC<Props> = ({ instances }) => {
return { lead: PROFILE, value: profile };
}),
},
...(isClustered
? [
{
id: 4,
heading: "Cluster member",
chips: locationSet.map((location) => {
return { lead: CLUSTER_MEMBER, value: location };
}),
},
]
: []),
];

const onSearchDataChange = (searchData: SearchAndFilterChip[]) => {
Expand Down
3 changes: 2 additions & 1 deletion src/util/instanceFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ export interface InstanceFilters {
queries: string[];
statuses: LxdInstanceStatus[];
types: string[];
profileQueries: string[];
profiles: string[];
clusterMembers: string[];
}

export const instanceStatuses: LxdInstanceStatus[] = [
Expand Down
2 changes: 2 additions & 0 deletions src/util/instanceTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const STATUS = "Status";
export const NAME = "Name";
export const TYPE = "Type";
export const CLUSTER_MEMBER = "Cluster member";
export const DESCRIPTION = "Description";
export const IPV4 = "IPv4";
export const IPV6 = "IPv6";
Expand All @@ -10,6 +11,7 @@ export const ACTIONS = "Actions";
export const COLUMN_WIDTHS: Record<string, number> = {
[NAME]: 170,
[TYPE]: 130,
[CLUSTER_MEMBER]: 150,
[DESCRIPTION]: 150,
[IPV4]: 150,
[IPV6]: 330,
Expand Down
4 changes: 3 additions & 1 deletion tests/instances.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ test("Bulk start, pause, unpause and stop instances", async ({ page }) => {

//Bulk start instances
await page
.getByRole("row", { name: "select Name Type Description Status Actions" })
.getByRole("row", {
name: "select Name Type Cluster member Status Actions",
})
.getByLabel("multiselect rows")
.click();
await page
Expand Down

0 comments on commit e5d0067

Please sign in to comment.