fleet/frontend/components/side_panels/HostSidePanel/HostSidePanel.tsx

138 lines
3.7 KiB
TypeScript

import React, { useState, useCallback } from "react";
import { filter } from "lodash";
import { ILabel } from "interfaces/label";
import { PLATFORM_LABEL_DISPLAY_ORDER } from "utilities/constants";
import Spinner from "components/Spinner";
import Button from "components/buttons/Button";
// @ts-ignore
import InputField from "components/forms/fields/InputField";
// @ts-ignore
import PanelGroup from "components/side_panels/HostSidePanel/PanelGroup";
// @ts-ignore
import SecondarySidePanelContainer from "components/side_panels/SecondarySidePanelContainer";
import PlusIcon from "../../../../assets/images/icon-plus-16x16@2x.png";
const baseClass = "host-side-panel";
interface IHostSidePanelProps {
labels?: ILabel[];
onAddLabelClick: (evt: React.MouseEvent<HTMLButtonElement>) => void;
onLabelClick: (
selectedLabel: ILabel
) => (evt: React.MouseEvent<HTMLButtonElement>) => void;
selectedFilter: string | undefined;
canAddNewLabel: boolean;
isLabelsLoading: boolean;
}
const HostSidePanel = ({
labels,
onAddLabelClick,
onLabelClick,
selectedFilter,
canAddNewLabel,
isLabelsLoading,
}: IHostSidePanelProps): JSX.Element => {
const [labelFilter, setLabelFilter] = useState<string>("");
const onFilterLabels = useCallback(
(filterString: string): void => {
setLabelFilter(filterString.toLowerCase());
},
[setLabelFilter]
);
if (isLabelsLoading || !labels) {
return (
<SecondarySidePanelContainer className={`${baseClass}`}>
<Spinner />
</SecondarySidePanelContainer>
);
}
const allHostLabels = filter(labels, { type: "all" });
const hostPlatformLabels = (() => {
const unorderedList: ILabel[] = labels.filter(
(label) => label.type === "platform"
);
const orderedList: ILabel[] = [];
PLATFORM_LABEL_DISPLAY_ORDER.forEach((name) => {
const label = unorderedList.find((el) => el.name === name);
label && orderedList.push(label);
});
return orderedList.filter(
(label) =>
["macOS", "MS Windows", "All Linux"].includes(label.name) ||
label.count !== 0
);
})();
const customLabels = filter(labels, (label) => {
const lowerDisplayText = label.display_text.toLowerCase();
return label.type === "custom" && lowerDisplayText.match(labelFilter);
});
return (
<SecondarySidePanelContainer className={`${baseClass}`}>
<PanelGroup
groupItems={allHostLabels}
onLabelClick={onLabelClick}
selectedFilter={selectedFilter}
type="all-hosts"
/>
<h3>Operating systems</h3>
<PanelGroup
groupItems={hostPlatformLabels}
onLabelClick={onLabelClick}
selectedFilter={selectedFilter}
type="platform"
/>
<div className="title">
<div>
<h3>Labels</h3>
</div>
<div>
{canAddNewLabel && (
<Button
variant="text-icon"
onClick={onAddLabelClick}
className={`${baseClass}__add-label-btn`}
>
<span>
Add label <img src={PlusIcon} alt="Add label icon" />
</span>
</Button>
)}
</div>
</div>
<div
className={`${baseClass}__panel-group-item ${baseClass}__panel-group-item--filter`}
>
<InputField
name="tags-filter"
onChange={onFilterLabels}
placeholder="Filter labels by name..."
value={labelFilter}
inputWrapperClass={`${baseClass}__filter-labels`}
/>
</div>
<PanelGroup
groupItems={customLabels}
onLabelClick={onLabelClick}
selectedFilter={selectedFilter}
type="label"
/>
</SecondarySidePanelContainer>
);
};
export default HostSidePanel;