diff --git a/frontend/components/queries/queryResults/QueryResultsHeading/QueryResultsHeading.tsx b/frontend/components/queries/queryResults/QueryResultsHeading/QueryResultsHeading.tsx
index d8668dc6eb..8e5567e7a5 100644
--- a/frontend/components/queries/queryResults/QueryResultsHeading/QueryResultsHeading.tsx
+++ b/frontend/components/queries/queryResults/QueryResultsHeading/QueryResultsHeading.tsx
@@ -1,11 +1,13 @@
import React from "react";
+import strUtils from "utilities/strings";
+
import Spinner from "components/Spinner";
import Button from "components/buttons/Button";
import TooltipWrapper from "components/TooltipWrapper";
const pluralizeHost = (count: number) => {
- return count > 1 ? "hosts" : "host";
+ return strUtils.pluralize(count, "host");
};
const baseClass = "query-results-heading";
diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileListItem/ProfileListItem.tsx b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileListItem/ProfileListItem.tsx
index 8fe3ce1323..15b7676701 100644
--- a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileListItem/ProfileListItem.tsx
+++ b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileListItem/ProfileListItem.tsx
@@ -10,7 +10,7 @@ import Button from "components/buttons/Button";
import Graphic from "components/Graphic";
import Icon from "components/Icon";
-import { pluralize } from "utilities/helpers";
+import strUtils from "utilities/strings";
const baseClass = "profile-list-item";
@@ -22,7 +22,7 @@ const LabelCount = ({
count: number;
}) => (
- {`${count} ${pluralize(count, "label", "s", "")}`}
+ {`${count} ${strUtils.pluralize(count, "label")}`}
);
diff --git a/frontend/pages/hosts/components/DeleteHostModal/DeleteHostModal.tsx b/frontend/pages/hosts/components/DeleteHostModal/DeleteHostModal.tsx
index 8524dee200..4b27ff3302 100644
--- a/frontend/pages/hosts/components/DeleteHostModal/DeleteHostModal.tsx
+++ b/frontend/pages/hosts/components/DeleteHostModal/DeleteHostModal.tsx
@@ -1,5 +1,7 @@
import React from "react";
+import strUtils from "utilities/strings";
+
import Modal from "components/Modal";
import Button from "components/buttons/Button";
import CustomLink from "components/CustomLink";
@@ -29,11 +31,18 @@ const DeleteHostModal = ({
hostName,
isUpdating,
}: IDeleteHostModalProps): JSX.Element => {
+ const pluralizeHost = () => {
+ if (!selectedHostIds) {
+ return "host";
+ }
+ return strUtils.pluralize(selectedHostIds.length, "host");
+ };
+
const hostText = () => {
if (selectedHostIds) {
return `${selectedHostIds.length}${
isAllMatchingHostsSelected ? "+" : ""
- } ${selectedHostIds.length === 1 ? "host" : "hosts"}`;
+ } ${pluralizeHost()}`;
}
return hostName;
};
@@ -58,17 +67,18 @@ const DeleteHostModal = ({
>
<>
- This action will delete {hostText()} from your Fleet instance.
- {largeVolumeText()}
+ This will remove the record of {hostText()}.{largeVolumeText()}
+
+
+ The {pluralizeHost()} will re-appear unless fleet's agent is
+ uninstalled.
- If the hosts come back online, they will automatically re-enroll.
- To prevent re-enrollment,{" "}
diff --git a/frontend/utilities/helpers.tsx b/frontend/utilities/helpers.tsx
index f433cc97e6..6d446468d2 100644
--- a/frontend/utilities/helpers.tsx
+++ b/frontend/utilities/helpers.tsx
@@ -53,31 +53,6 @@ import { IScheduledQueryStats } from "interfaces/scheduled_query_stats";
const ORG_INFO_ATTRS = ["org_name", "org_logo_url"];
const ADMIN_ATTRS = ["email", "name", "password", "password_confirmation"];
-/**
- *
- * @param count The number of items.
- * @param root The root of the word, omitting any suffixs.
- * @param pluralSuffix The suffix to add to the root if the count is not 1.
- * @param singularSuffix The suffix to add to the root if the count is 1.
- * @returns A string with the root and the appropriate suffix.
- *
- * @example
- * pluralize(1, "hero", "es", "") // "hero"
- * pluralize(0, "hero", "es", "") // "heroes"
- * pluralize(1, "fair", "ies", "y") // "fairy"
- * pluralize(2, "fair", "ies", "y") // "fairies"
- * pluralize(1, "dragon") // "dragon"
- * pluralize(2, "dragon") // "dragons"
- */
-export const pluralize = (
- count: number,
- root: string,
- pluralSuffix: string,
- singularSuffix: string
-) => {
- return `${root}${count !== 1 ? pluralSuffix : singularSuffix}`;
-};
-
export const addGravatarUrlToResource = (resource: any): any => {
const { email } = resource;
const gravatarAvailable =
@@ -887,7 +862,6 @@ export const getUniqueColumnNamesFromRows = (rows: any[]) =>
);
export default {
- pluralize,
addGravatarUrlToResource,
formatConfigDataForServer,
formatLabelResponse,
diff --git a/frontend/utilities/strings/stringUtils.tests.ts b/frontend/utilities/strings/stringUtils.tests.ts
index 9757456d84..25755873ff 100644
--- a/frontend/utilities/strings/stringUtils.tests.ts
+++ b/frontend/utilities/strings/stringUtils.tests.ts
@@ -1,23 +1,47 @@
-import { enforceFleetSentenceCasing } from "./stringUtils";
+import { enforceFleetSentenceCasing, pluralize } from "./stringUtils";
-describe("enforceFleetSentenceCasing utility", () => {
- it("fixes a Title Cased String with no ignore words", () => {
- expect(enforceFleetSentenceCasing("All Hosts")).toEqual("All hosts");
- expect(enforceFleetSentenceCasing("all Hosts")).toEqual("All hosts");
- expect(enforceFleetSentenceCasing("all hosts")).toEqual("All hosts");
- expect(enforceFleetSentenceCasing("All HosTs ")).toEqual("All hosts");
- });
+describe("string utilities", () => {
+ describe("enforceFleetSentenceCasing utility", () => {
+ it("fixes a Title Cased String with no ignore words", () => {
+ expect(enforceFleetSentenceCasing("All Hosts")).toEqual("All hosts");
+ expect(enforceFleetSentenceCasing("all Hosts")).toEqual("All hosts");
+ expect(enforceFleetSentenceCasing("all hosts")).toEqual("All hosts");
+ expect(enforceFleetSentenceCasing("All HosTs ")).toEqual("All hosts");
+ });
- it("fixes a title cased string while ignoring special words in various places ", () => {
- expect(enforceFleetSentenceCasing("macOS")).toEqual("macOS");
- expect(enforceFleetSentenceCasing("macOS Settings")).toEqual(
- "macOS settings"
+ it("fixes a title cased string while ignoring special words in various places ", () => {
+ expect(enforceFleetSentenceCasing("macOS")).toEqual("macOS");
+ expect(enforceFleetSentenceCasing("macOS Settings")).toEqual(
+ "macOS settings"
+ );
+ expect(
+ enforceFleetSentenceCasing("osquery shouldn't be Capitalized")
+ ).toEqual("osquery shouldn't be capitalized");
+ });
+ expect(enforceFleetSentenceCasing("fleet uses MySQL")).toEqual(
+ "Fleet uses MySQL"
);
- expect(
- enforceFleetSentenceCasing("osquery shouldn't be Capitalized")
- ).toEqual("osquery shouldn't be capitalized");
});
- expect(enforceFleetSentenceCasing("fleet uses MySQL")).toEqual(
- "Fleet uses MySQL"
- );
+
+ describe("pluralize utility", () => {
+ it("returns the singular form of a word when count is 1", () => {
+ expect(pluralize(1, "hero", "es", "")).toEqual("hero");
+ });
+
+ it("returns the plural form of a word when count is not 1", () => {
+ expect(pluralize(0, "hero", "es", "")).toEqual("heroes");
+ expect(pluralize(2, "hero", "es", "")).toEqual("heroes");
+ expect(pluralize(100, "hero", "es", "")).toEqual("heroes");
+ });
+
+ it("returns the singular form of a word when count is 1 and a no custom suffix are provided", () => {
+ expect(pluralize(1, "hero")).toEqual("hero");
+ });
+
+ it("returns the pluralized form of a word with 's' suffix when count is not 1 and no custom suffix are provided", () => {
+ expect(pluralize(0, "hero")).toEqual("heros");
+ expect(pluralize(2, "hero")).toEqual("heros");
+ expect(pluralize(100, "hero")).toEqual("heros");
+ });
+ });
});
diff --git a/frontend/utilities/strings/stringUtils.ts b/frontend/utilities/strings/stringUtils.ts
index edc0aea69a..e7e205d98e 100644
--- a/frontend/utilities/strings/stringUtils.ts
+++ b/frontend/utilities/strings/stringUtils.ts
@@ -45,7 +45,36 @@ export const enforceFleetSentenceCasing = (s: string) => {
return resArr.join(" ").trim();
};
+
+/**
+ * Pluralizes a word based on the entitiy count and the desired suffixes. If no
+ * suffixes are provided, the default suffix "s" is used.
+ *
+ * @param count The number of items.
+ * @param root The root of the word, omitting any suffixs.
+ * @param pluralSuffix The suffix to add to the root if the count is not 1.
+ * @param singularSuffix The suffix to add to the root if the count is 1.
+ * @returns A string with the root and the appropriate suffix.
+ *
+ * @example
+ * pluralize(1, "hero", "es", "") // "hero"
+ * pluralize(0, "hero", "es", "") // "heroes"
+ * pluralize(1, "fair", "ies", "y") // "fairy"
+ * pluralize(2, "fair", "ies", "y") // "fairies"
+ * pluralize(1, "dragon") // "dragon"
+ * pluralize(2, "dragon") // "dragons"
+ */
+export const pluralize = (
+ count: number,
+ root: string,
+ pluralSuffix = "s",
+ singularSuffix = ""
+) => {
+ return `${root}${count !== 1 ? pluralSuffix : singularSuffix}`;
+};
+
export default {
capitalize,
capitalizeRole,
+ pluralize,
};