Dashboard UI: Hosts change on team selection (#2839)

This commit is contained in:
RachelElysia 2021-11-09 12:48:23 -08:00 committed by GitHub
parent 2d1e4c0898
commit 81ccbab31f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 46 deletions

View file

@ -0,0 +1 @@
* Dashboard hosts change on team selection

View file

@ -92,6 +92,7 @@ describe(
cy.findByText(/back to queries/i).should("exist");
cy.visit("/queries/manage");
cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting
cy.findByText(/query all/i).click();
cy.wait(2000); // eslint-disable-line cypress/no-unnecessary-waiting

View file

@ -25,6 +25,12 @@ interface ITeamsResponse {
const baseClass = "homepage";
const TAGGED_TEMPLATES = {
hostsByTeamRoute: (teamId: number | undefined | null) => {
return `${teamId ? `/?team_id=${teamId}` : ""}`;
},
};
const Homepage = (): JSX.Element => {
const { MANAGE_HOSTS } = paths;
const {
@ -76,9 +82,14 @@ const Homepage = (): JSX.Element => {
<div className={`${baseClass}__section one-column`}>
<InfoCard
title="Hosts"
action={{ type: "link", to: MANAGE_HOSTS, text: "View all hosts" }}
action={{
type: "link",
to:
MANAGE_HOSTS + TAGGED_TEMPLATES.hostsByTeamRoute(currentTeam?.id),
text: "View all hosts",
}}
>
<HostsSummary />
<HostsSummary currentTeamId={currentTeam?.id} />
</InfoCard>
</div>
{isPreviewMode && (

View file

@ -1,61 +1,100 @@
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { reduce } from "lodash";
import React, { useState } from "react";
import { useQuery } from "react-query";
import { ILabel } from "interfaces/label";
// @ts-ignore
import { getLabels } from "redux/nodes/components/ManageHostsPage/actions";
import hostCountAPI from "services/entities/host_count";
import labelsAPI from "services/entities/labels";
import WindowsIcon from "../../../../../assets/images/icon-windows-48x48@2x.png";
import LinuxIcon from "../../../../../assets/images/icon-linux-48x48@2x.png";
import MacIcon from "../../../../../assets/images/icon-mac-48x48@2x.png";
const baseClass = "hosts-summary";
interface IRootState {
entities: {
labels: {
isLoading: boolean;
data: {
[id: number]: ILabel;
};
};
};
interface IHostsSummaryProps {
currentTeamId: number | undefined;
}
const PLATFORM_STRINGS = {
macOS: ["macOS"],
windows: ["MS Windows"],
linux: ["All Linux"],
};
interface ILabelsResponse {
labels: ILabel[];
}
const HostsSummary = (): JSX.Element => {
const dispatch = useDispatch();
interface IHostCountResponse {
count: number;
}
useEffect(() => {
dispatch(getLabels());
}, []);
const HostsSummary = ({ currentTeamId }: IHostsSummaryProps): JSX.Element => {
const [macCount, setMacCount] = useState<string | undefined>();
const [windowsCount, setWindowsCount] = useState<string | undefined>();
const [linuxCount, setLinuxCount] = useState<string | undefined>();
const labels = useSelector((state: IRootState) => state.entities.labels.data);
// Builtin labels from state populate os counts
const getCount = (platformTitles: string[]) => {
return reduce(
Object.values(labels),
(total, label) => {
return label.label_type === "builtin" &&
platformTitles.includes(label.name) &&
label.count
? total + label.count
: total;
},
0
);
const getLabel = (labelString: string, labels: ILabel[]) => {
return Object.values(labels).filter((label: ILabel) => {
return label.label_type === "builtin" && label.name === labelString;
});
};
const macCount = getCount(PLATFORM_STRINGS.macOS).toLocaleString("en-US");
const windowsCount = getCount(PLATFORM_STRINGS.windows).toLocaleString(
"en-US"
const { data: labels } = useQuery<ILabelsResponse, Error, ILabel[]>(
["labels"],
() => labelsAPI.loadAll(),
{
select: (data: ILabelsResponse) => data.labels,
}
);
useQuery<IHostCountResponse, Error, number>(
["mac host count", currentTeamId],
() => {
const macOsLabel = getLabel("macOS", labels || []);
return (
hostCountAPI.load({
selectedLabels: [`labels/${macOsLabel[0].id}`],
teamId: currentTeamId,
}) || { count: 0 }
);
},
{
select: (data: IHostCountResponse) => data.count,
enabled: !!labels,
onSuccess: (data: number) => setMacCount(data.toLocaleString("en-US")),
}
);
useQuery<IHostCountResponse, Error, number>(
["windows host count", currentTeamId],
() => {
const windowsLabel = getLabel("MS Windows", labels || []);
return (
hostCountAPI.load({
selectedLabels: [`labels/${windowsLabel[0].id}`],
teamId: currentTeamId,
}) || { count: 0 }
);
},
{
select: (data: IHostCountResponse) => data.count,
enabled: !!labels,
onSuccess: (data: number) =>
setWindowsCount(data.toLocaleString("en-US")),
}
);
useQuery<IHostCountResponse, Error, number>(
["linux host count", currentTeamId],
() => {
const linuxLabel = getLabel("All Linux", labels || []);
return (
hostCountAPI.load({
selectedLabels: [`labels/${linuxLabel[0].id}`],
teamId: currentTeamId,
}) || { count: 0 }
);
},
{
select: (data: IHostCountResponse) => data.count,
enabled: !!labels,
onSuccess: (data: number) => setLinuxCount(data.toLocaleString("en-US")),
}
);
const linuxCount = getCount(PLATFORM_STRINGS.linux).toLocaleString("en-US");
return (
<div className={baseClass}>

View file

@ -323,6 +323,10 @@ const ManageHostsPage = ({
),
};
if (queryParams.team_id) {
options.teamId = queryParams.team_id;
}
try {
const { hosts: returnedHosts, software } = await hostsAPI.loadAll(
options
@ -350,6 +354,10 @@ const ManageHostsPage = ({
),
};
if (queryParams.team_id) {
options.teamId = queryParams.team_id;
}
try {
const { count: returnedHostCount } = await hostCountAPI.load(options);
setFilteredHostCount(returnedHostCount);
@ -658,6 +666,10 @@ const ManageHostsPage = ({
newQueryParams.team_id = teamId;
}
if (queryParams.team_id) {
newQueryParams.team_id = queryParams.team_id;
}
if (policyId) {
newQueryParams.policy_id = policyId;
}