Refine manage hosts page to better handle timing and loading issues (#3402)

This commit is contained in:
Luke Heath 2021-12-17 15:40:57 -06:00 committed by GitHub
parent 040b8eddc3
commit 5b64985ece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 54 additions and 18 deletions

View File

@ -0,0 +1 @@
* Refine manage hosts page to better handle timing and loading issues.

View File

@ -1,4 +1,5 @@
import React, { useContext, useMemo } from "react";
import classnames from "classnames";
import { AppContext } from "context/app";
import { ITeam } from "interfaces/team";
@ -34,6 +35,7 @@ interface ITeamsDropdownProps {
currentUserTeams: ITeam[];
selectedTeamId: number;
includeAll?: boolean;
isDisabled?: boolean;
onChange: (newSelectedValue: number) => void;
onOpen?: () => void;
onClose?: () => void;
@ -45,6 +47,7 @@ const TeamsDropdown = ({
currentUserTeams,
selectedTeamId,
includeAll,
isDisabled,
onChange,
onOpen,
onClose,
@ -63,8 +66,12 @@ const TeamsDropdown = ({
? selectedTeamId
: teamOptions[0]?.value;
const dropdownWrapperClasses = classnames(`${baseClass}-wrapper`, {
disabled: isDisabled || undefined,
});
return (
<div>
<div className={dropdownWrapperClasses}>
{teamOptions.length && (
<Dropdown
value={selectedValue}
@ -72,6 +79,7 @@ const TeamsDropdown = ({
className={baseClass}
options={teamOptions}
searchable={false}
disabled={isDisabled || false}
onChange={onChange}
onOpen={onOpen}
onClose={onClose}

View File

@ -1,3 +1,10 @@
.component__team-dropdown-wrapper {
&.disabled {
cursor: auto;
opacity: 0.75;
}
}
.component__team-dropdown {
border: 0 !important;
position: relative;

View File

@ -22,7 +22,7 @@ const FormField = ({
label,
name,
type,
}: IFormFieldProps) => {
}: IFormFieldProps): JSX.Element => {
const renderLabel = () => {
const labelWrapperClasses = classnames(`${baseClass}__label`, {
[`${baseClass}__label--error`]: !isEmpty(error),

View File

@ -253,6 +253,7 @@ const TeamDetailsWrapper = ({
<TeamsDropdown
selectedTeamId={toNumber(routeParams.team_id)}
currentUserTeams={adminTeams || []}
isDisabled={isLoadingTeams}
onChange={(newSelectedValue: number) =>
handleTeamSelect(newSelectedValue)
}

View File

@ -52,6 +52,7 @@ import TableContainer from "components/TableContainer";
import TableDataError from "components/TableDataError";
import { IActionButtonProps } from "components/TableContainer/DataTable/ActionButton";
import TeamsDropdown from "components/TeamsDropdown";
import Spinner from "components/Spinner";
import { getValidatedTeamId } from "fleet/helpers";
import {
@ -1078,6 +1079,7 @@ const ManageHostsPage = ({
selectedTeamId={
(policyId && policy?.team_id) || (currentTeam?.id as number)
}
isDisabled={isHostsLoading || isHostCountLoading}
onChange={(newSelectedValue: number) =>
handleTeamSelect(newSelectedValue)
}
@ -1461,7 +1463,7 @@ const ManageHostsPage = ({
);
};
const renderTable = (selectedTeam: number) => {
const renderTable = () => {
if (
!config ||
!currentUser ||
@ -1481,7 +1483,8 @@ const ManageHostsPage = ({
(getStatusSelected() === ALL_HOSTS_LABEL && selectedLabel.count === 0) ||
(getStatusSelected() === ALL_HOSTS_LABEL &&
filteredHostCount === 0 &&
searchQuery === "")
searchQuery === "" &&
!isHostsLoading)
) {
return (
<NoHosts
@ -1491,6 +1494,11 @@ const ManageHostsPage = ({
);
}
// Hosts not ready to render
if (isHostsLoading && filteredHostCount === 0) {
return <Spinner />;
}
const secondarySelectActions: IActionButtonProps[] = [
{
name: "transfer",
@ -1544,8 +1552,6 @@ const ManageHostsPage = ({
);
};
const selectedTeam = currentTeam?.id || 0;
const renderNoEnrollSecretBanner = () => {
const noTeamEnrollSecrets =
currentTeam &&
@ -1624,7 +1630,7 @@ const ManageHostsPage = ({
{renderSoftwareVulnerabilities()}
</div>
))}
{config && (!isPremiumTier || teams) && renderTable(selectedTeam)}
{config && (!isPremiumTier || teams) ? renderTable() : <Spinner />}
</div>
)}
{!isLabelsLoading && renderSidePanel()}

View File

@ -1,5 +1,5 @@
import React, { useState, useCallback, useContext } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { useQuery } from "react-query";
import { IPack } from "interfaces/pack";
@ -12,10 +12,10 @@ import { renderFlash } from "redux/nodes/notifications/actions";
import PATHS from "router/paths";
// @ts-ignore
import deepDifference from "utilities/deep_difference";
import Button from "components/buttons/Button";
import TableDataError from "components/TableDataError";
import Spinner from "components/Spinner";
import PacksListWrapper from "./components/PacksListWrapper";
import RemovePackModal from "./components/RemovePackModal";
@ -196,7 +196,7 @@ const ManagePacksPage = ({ router }: IManagePacksPageProps): JSX.Element => {
)}
</div>
<div>
{!isLoadingPacks &&
{!isLoadingPacks ? (
renderTable(
onRemovePackClick,
onEnablePackClick,
@ -205,7 +205,10 @@ const ManagePacksPage = ({ router }: IManagePacksPageProps): JSX.Element => {
packs,
packsError,
isLoadingPacks
)}
)
) : (
<Spinner />
)}
</div>
{showRemovePackModal && (
<RemovePackModal

View File

@ -20,11 +20,11 @@ import fleetQueriesAPI from "services/entities/queries";
import teamsAPI from "services/entities/teams";
// @ts-ignore
import { renderFlash } from "redux/nodes/notifications/actions";
import sortUtils from "utilities/sort";
import sortUtils from "utilities/sort";
import paths from "router/paths";
import Button from "components/buttons/Button";
// @ts-ignore
import Spinner from "components/Spinner";
import TeamsDropdown from "components/TeamsDropdown";
import IconToolTip from "components/IconToolTip";
import TableDataError from "components/TableDataError";
@ -153,13 +153,13 @@ const ManageSchedulePage = ({
() => teamsAPI.loadAll({}),
{
enabled: !!isPremiumTier,
refetchOnMount: false,
refetchOnWindowFocus: false,
select: (data) => {
return currentUser?.teams
? filterAndSortTeamOptions(data.teams, currentUser.teams)
: data.teams;
},
refetchOnMount: false,
refetchOnWindowFocus: false,
}
);
@ -167,9 +167,9 @@ const ManageSchedulePage = ({
["fleetQueries"],
() => fleetQueriesAPI.loadAll(),
{
select: (data) => data.queries,
refetchOnMount: false,
refetchOnWindowFocus: false,
select: (data) => data.queries,
}
);
@ -450,7 +450,7 @@ const ManageSchedulePage = ({
)}
</div>
<div>
{!isLoadingTeams &&
{!isLoadingTeams ? (
renderTable(
onRemoveScheduledQueryClick,
onEditScheduledQueryClick,
@ -459,7 +459,10 @@ const ManageSchedulePage = ({
toggleScheduleEditorModal,
isOnGlobalTeam || false,
selectedTeamData
)}
)
) : (
<Spinner />
)}
</div>
{/* must use ternary for NaN */}
{selectedTeamId && allTeamsScheduledQueriesList.length > 0 ? (

View File

@ -4,3 +4,10 @@
opacity: 1;
}
}
#app {
.Select.is-disabled > .Select-control {
background: transparent;
pointer-events: none;
}
}