= {
title: "components/Abbr",
component: Abbr,
@@ -34,9 +28,9 @@ export const InlinedShorthand: Story = {
The physical pain of getting bonked on the head with a cartoon mallet
lasts precisely 593{" "}
-
+
-
+
. The emotional turmoil and complete embarrassment lasts forever.
),
@@ -51,9 +45,9 @@ export const Acronym: Story = {
},
decorators: [
(Story) => (
-
+
-
+
),
],
};
@@ -66,9 +60,16 @@ export const Initialism: Story = {
},
decorators: [
(Story) => (
-
+
-
+
),
],
};
+
+const styles = {
+ // Just here to make the abbreviated part more obvious in the component library
+ underlined: {
+ textDecoration: "underline dotted",
+ },
+};
diff --git a/site/src/components/Dashboard/useUpdateCheck.test.tsx b/site/src/components/Dashboard/useUpdateCheck.test.tsx
index 6f5f8e5431b29..b689f39d4252e 100644
--- a/site/src/components/Dashboard/useUpdateCheck.test.tsx
+++ b/site/src/components/Dashboard/useUpdateCheck.test.tsx
@@ -14,7 +14,7 @@ const createWrapper = (): FC => {
};
beforeEach(() => {
- window.localStorage.clear();
+ localStorage.clear();
});
it("is dismissed when does not have permission to see it", () => {
@@ -57,7 +57,7 @@ it("is dismissed when it was dismissed previously", async () => {
);
}),
);
- window.localStorage.setItem("dismissedVersion", MockUpdateCheck.version);
+ localStorage.setItem("dismissedVersion", MockUpdateCheck.version);
const { result } = renderHook(() => useUpdateCheck(true), {
wrapper: createWrapper(),
});
diff --git a/site/src/components/Resources/VSCodeDesktopButton/VSCodeDesktopButton.tsx b/site/src/components/Resources/VSCodeDesktopButton/VSCodeDesktopButton.tsx
index 3e96b67f2e144..ceb03f016e459 100644
--- a/site/src/components/Resources/VSCodeDesktopButton/VSCodeDesktopButton.tsx
+++ b/site/src/components/Resources/VSCodeDesktopButton/VSCodeDesktopButton.tsx
@@ -1,14 +1,13 @@
-import { FC, PropsWithChildren, useState, useRef } from "react";
-import { getApiKey } from "api/api";
-import { VSCodeIcon } from "components/Icons/VSCodeIcon";
-import { VSCodeInsidersIcon } from "components/Icons/VSCodeInsidersIcon";
-import { AgentButton } from "components/Resources/AgentButton";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import ButtonGroup from "@mui/material/ButtonGroup";
-import { useLocalStorage } from "hooks";
import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
+import { type FC, useState, useRef } from "react";
+import { getApiKey } from "api/api";
import { DisplayApp } from "api/typesGenerated";
+import { VSCodeIcon } from "components/Icons/VSCodeIcon";
+import { VSCodeInsidersIcon } from "components/Icons/VSCodeInsidersIcon";
+import { AgentButton } from "components/Resources/AgentButton";
import { DisplayAppNameMap } from "../AppLink/AppLink";
export interface VSCodeDesktopButtonProps {
@@ -23,12 +22,9 @@ type VSCodeVariant = "vscode" | "vscode-insiders";
const VARIANT_KEY = "vscode-variant";
-export const VSCodeDesktopButton: FC<
- PropsWithChildren
-> = (props) => {
+export const VSCodeDesktopButton: FC = (props) => {
const [isVariantMenuOpen, setIsVariantMenuOpen] = useState(false);
- const localStorage = useLocalStorage();
- const previousVariant = localStorage.getLocal(VARIANT_KEY);
+ const previousVariant = localStorage.getItem(VARIANT_KEY);
const [variant, setVariant] = useState(() => {
if (!previousVariant) {
return "vscode";
@@ -38,7 +34,7 @@ export const VSCodeDesktopButton: FC<
const menuAnchorRef = useRef(null);
const selectVariant = (variant: VSCodeVariant) => {
- localStorage.saveLocal(VARIANT_KEY, variant);
+ localStorage.setItem(VARIANT_KEY, variant);
setVariant(variant);
setIsVariantMenuOpen(false);
};
@@ -109,12 +105,12 @@ export const VSCodeDesktopButton: FC<
);
};
-const VSCodeButton = ({
+const VSCodeButton: FC = ({
userName,
workspaceName,
agentName,
folderPath,
-}: VSCodeDesktopButtonProps) => {
+}) => {
const [loading, setLoading] = useState(false);
return (
@@ -153,12 +149,12 @@ const VSCodeButton = ({
);
};
-const VSCodeInsidersButton = ({
+const VSCodeInsidersButton: FC = ({
userName,
workspaceName,
agentName,
folderPath,
-}: VSCodeDesktopButtonProps) => {
+}) => {
const [loading, setLoading] = useState(false);
return (
diff --git a/site/src/contexts/ProxyContext.test.tsx b/site/src/contexts/ProxyContext.test.tsx
index d2642418bf17a..5b66c89b3fe61 100644
--- a/site/src/contexts/ProxyContext.test.tsx
+++ b/site/src/contexts/ProxyContext.test.tsx
@@ -19,7 +19,7 @@ import { screen } from "@testing-library/react";
import { server } from "testHelpers/server";
import { rest } from "msw";
import { Region } from "api/typesGenerated";
-import "testHelpers/localstorage";
+import "testHelpers/localStorage";
import userEvent from "@testing-library/user-event";
// Mock useProxyLatency to use a hard-coded latency. 'jest.mock' must be called
@@ -187,7 +187,7 @@ interface ProxyContextSelectionTest {
describe("ProxyContextSelection", () => {
beforeEach(() => {
- window.localStorage.clear();
+ localStorage.clear();
});
// A way to simulate a user clearing the proxy selection.
diff --git a/site/src/contexts/ProxyContext.tsx b/site/src/contexts/ProxyContext.tsx
index c661a1bc7c5db..d1b6b6057f4cd 100644
--- a/site/src/contexts/ProxyContext.tsx
+++ b/site/src/contexts/ProxyContext.tsx
@@ -310,11 +310,11 @@ const computeUsableURLS = (proxy?: Region): PreferredProxy => {
// Local storage functions
export const clearUserSelectedProxy = (): void => {
- window.localStorage.removeItem("user-selected-proxy");
+ localStorage.removeItem("user-selected-proxy");
};
export const saveUserSelectedProxy = (saved: Region): void => {
- window.localStorage.setItem("user-selected-proxy", JSON.stringify(saved));
+ localStorage.setItem("user-selected-proxy", JSON.stringify(saved));
};
export const loadUserSelectedProxy = (): Region | undefined => {
diff --git a/site/src/hooks/index.ts b/site/src/hooks/index.ts
index 16b46cd134713..7f0309dc3aefb 100644
--- a/site/src/hooks/index.ts
+++ b/site/src/hooks/index.ts
@@ -2,7 +2,6 @@ export * from "./useClickable";
export * from "./useClickableTableRow";
export * from "./useClipboard";
export * from "./useFeatureVisibility";
-export * from "./useLocalStorage";
export * from "./useMe";
export * from "./useOrganizationId";
export * from "./usePagination";
diff --git a/site/src/hooks/useLocalStorage.ts b/site/src/hooks/useLocalStorage.ts
deleted file mode 100644
index 10ae2889907ba..0000000000000
--- a/site/src/hooks/useLocalStorage.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-export const useLocalStorage = () => {
- return {
- saveLocal,
- getLocal,
- clearLocal,
- };
-};
-
-const saveLocal = (itemKey: string, itemValue: string): void => {
- window.localStorage.setItem(itemKey, itemValue);
-};
-
-const getLocal = (itemKey: string): string | undefined => {
- return localStorage.getItem(itemKey) ?? undefined;
-};
-
-const clearLocal = (itemKey: string): void => {
- localStorage.removeItem(itemKey);
-};
diff --git a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx
index 65a2b885719ee..ba76f413bda6b 100644
--- a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx
+++ b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx
@@ -3,13 +3,13 @@ import { updateTemplateMeta } from "api/api";
import { UpdateTemplateMeta } from "api/typesGenerated";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { displaySuccess } from "components/GlobalSnackbar/utils";
-import { FC } from "react";
+import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate, useParams } from "react-router-dom";
import { pageTitle } from "utils/page";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateSchedulePageView } from "./TemplateSchedulePageView";
-import { useLocalStorage, useOrganizationId } from "hooks";
+import { useOrganizationId } from "hooks";
import { templateByNameKey } from "api/queries/templates";
const TemplateSchedulePage: FC = () => {
@@ -21,7 +21,6 @@ const TemplateSchedulePage: FC = () => {
const { entitlements } = useDashboard();
const allowAdvancedScheduling =
entitlements.features["advanced_template_scheduling"].enabled;
- const { clearLocal } = useLocalStorage();
const {
mutate: updateTemplate,
@@ -36,8 +35,8 @@ const TemplateSchedulePage: FC = () => {
);
displaySuccess("Template updated successfully");
// clear browser storage of workspaces impending deletion
- clearLocal("dismissedWorkspaceList"); // workspaces page
- clearLocal("dismissedWorkspace"); // workspace page
+ localStorage.removeItem("dismissedWorkspaceList"); // workspaces page
+ localStorage.removeItem("dismissedWorkspace"); // workspace page
},
},
);
diff --git a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx
index db07c575db99e..995c4267ca586 100644
--- a/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx
+++ b/site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx
@@ -64,13 +64,13 @@ export interface TemplateVersionEditorProps {
defaultFileTree: FileTree;
buildLogs?: ProvisionerJobLog[];
resources?: WorkspaceResource[];
- disablePreview: boolean;
- disableUpdate: boolean;
+ disablePreview?: boolean;
+ disableUpdate?: boolean;
onPreview: (files: FileTree) => void;
onPublish: () => void;
onConfirmPublish: (data: PublishVersionData) => void;
onCancelPublish: () => void;
- publishingError: unknown;
+ publishingError?: unknown;
publishedVersion?: TemplateVersion;
onCreateWorkspace: () => void;
isAskingPublishParameters: boolean;
diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx
index 3dd0e8b478d4e..f613eaf028575 100644
--- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx
+++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx
@@ -317,7 +317,7 @@ describe("WorkspacePage", () => {
});
it("restart the workspace with one time parameters when having the confirmation dialog", async () => {
- window.localStorage.removeItem(`${MockUser.id}_ignoredWarnings`);
+ localStorage.removeItem(`${MockUser.id}_ignoredWarnings`);
jest.spyOn(api, "getWorkspaceParameters").mockResolvedValue({
templateVersionRichParameters: [
{
diff --git a/site/src/testHelpers/localStorage.ts b/site/src/testHelpers/localStorage.ts
new file mode 100644
index 0000000000000..428ae66b6dfce
--- /dev/null
+++ b/site/src/testHelpers/localStorage.ts
@@ -0,0 +1,37 @@
+export const localStorageMock = (): Storage => {
+ const store = new Map();
+
+ return {
+ getItem: (key) => {
+ return store.get(key) ?? null;
+ },
+ setItem: (key: string, value: string) => {
+ store.set(key, value);
+ },
+ clear: () => {
+ store.clear();
+ },
+ removeItem: (key: string) => {
+ store.delete(key);
+ },
+
+ get length() {
+ return store.size;
+ },
+
+ key: (index) => {
+ const values = store.values();
+ let value: IteratorResult = values.next();
+ for (let i = 1; i < index && !value.done; i++) {
+ value = values.next();
+ }
+
+ return value.value ?? null;
+ },
+ };
+};
+
+Object.defineProperty(globalThis, "localStorage", {
+ value: localStorageMock(),
+ writable: false,
+});
diff --git a/site/src/testHelpers/localstorage.ts b/site/src/testHelpers/localstorage.ts
deleted file mode 100644
index bff92d8f9f0b4..0000000000000
--- a/site/src/testHelpers/localstorage.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-export const localStorageMock = () => {
- const store = {} as Record;
-
- return {
- getItem: (key: string): string => {
- return store[key];
- },
- setItem: (key: string, value: string) => {
- store[key] = value;
- },
- clear: () => {
- Object.keys(store).forEach((key) => {
- delete store[key];
- });
- },
- removeItem: (key: string) => {
- delete store[key];
- },
- };
-};
-
-Object.defineProperty(window, "localStorage", { value: localStorageMock() });