chore: remove `useLocalStorage` hook (#11712)

This commit is contained in:
Kayla Washburn-Love 2024-01-19 16:04:19 -07:00 committed by GitHub
parent fa99f6a200
commit 80eac73ed1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 84 additions and 93 deletions

View File

@ -327,7 +327,7 @@ func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.ExternalAut
case http.StatusTooManyRequests:
return nil, xerrors.New("rate limit hit, unable to authorize device. please try again later")
default:
return nil, fmt.Errorf("status_code=%d: %w", resp.StatusCode, err)
return nil, xerrors.Errorf("status_code=%d: %w", resp.StatusCode, err)
}
}
if r.ErrorDescription != "" {

View File

@ -1626,7 +1626,7 @@ func TestWorkspaceAgentExternalAuthListen(t *testing.T) {
cancel()
// We expect only 1
// In a failed test, you will likely see 9, as the last one
// gets cancelled.
// gets canceled.
require.Equal(t, 1, validateCalls, "validate calls duplicated on same token")
})
}

View File

@ -276,9 +276,9 @@ func (p *ProxyHealth) runOnce(ctx context.Context, now time.Time) (map[uuid.UUID
case err == nil && resp.StatusCode == http.StatusOK:
err := json.NewDecoder(resp.Body).Decode(&status.Report)
if err != nil {
isCoderErr := fmt.Errorf("proxy url %q is not a coder proxy instance, verify the url is correct", reqURL)
isCoderErr := xerrors.Errorf("proxy url %q is not a coder proxy instance, verify the url is correct", reqURL)
if resp.Header.Get(codersdk.BuildVersionHeader) != "" {
isCoderErr = fmt.Errorf("proxy url %q is a coder instance, but unable to decode the response payload. Could this be a primary coderd and not a proxy?", reqURL)
isCoderErr = xerrors.Errorf("proxy url %q is a coder instance, but unable to decode the response payload. Could this be a primary coderd and not a proxy?", reqURL)
}
// If the response is not json, then the user likely input a bad url that returns status code 200.
@ -286,7 +286,7 @@ func (p *ProxyHealth) runOnce(ctx context.Context, now time.Time) (map[uuid.UUID
if notJSONErr := codersdk.ExpectJSONMime(resp); notJSONErr != nil {
err = errors.Join(
isCoderErr,
fmt.Errorf("attempted to query health at %q but got back the incorrect content type: %w", reqURL, notJSONErr),
xerrors.Errorf("attempted to query health at %q but got back the incorrect content type: %w", reqURL, notJSONErr),
)
status.Report.Errors = []string{
@ -300,7 +300,7 @@ func (p *ProxyHealth) runOnce(ctx context.Context, now time.Time) (map[uuid.UUID
status.Report.Errors = []string{
errors.Join(
isCoderErr,
fmt.Errorf("received a status code 200, but failed to decode health report body: %w", err),
xerrors.Errorf("received a status code 200, but failed to decode health report body: %w", err),
).Error(),
}
status.Status = Unhealthy

View File

@ -159,7 +159,7 @@ func New(ctx context.Context, opts *Options) (*Server, error) {
info, err := client.SDKClient.BuildInfo(ctx)
if err != nil {
return nil, fmt.Errorf("buildinfo: %w", errors.Join(
fmt.Errorf("unable to fetch build info from primary coderd. Are you sure %q is a coderd instance?", opts.DashboardURL),
xerrors.Errorf("unable to fetch build info from primary coderd. Are you sure %q is a coderd instance?", opts.DashboardURL),
err,
))
}

View File

@ -1,12 +1,6 @@
import { type PropsWithChildren } from "react";
import type { Meta, StoryObj } from "@storybook/react";
import { Abbr } from "./Abbr";
// Just here to make the abbreviated part more obvious in the component library
const Underline = ({ children }: PropsWithChildren) => (
<span css={{ textDecoration: "underline dotted" }}>{children}</span>
);
const meta: Meta<typeof Abbr> = {
title: "components/Abbr",
component: Abbr,
@ -34,9 +28,9 @@ export const InlinedShorthand: Story = {
<p css={{ maxWidth: "40em" }}>
The physical pain of getting bonked on the head with a cartoon mallet
lasts precisely 593{" "}
<Underline>
<span css={styles.underlined}>
<Story />
</Underline>
</span>
. The emotional turmoil and complete embarrassment lasts forever.
</p>
),
@ -51,9 +45,9 @@ export const Acronym: Story = {
},
decorators: [
(Story) => (
<Underline>
<span css={styles.underlined}>
<Story />
</Underline>
</span>
),
],
};
@ -66,9 +60,16 @@ export const Initialism: Story = {
},
decorators: [
(Story) => (
<Underline>
<span css={styles.underlined}>
<Story />
</Underline>
</span>
),
],
};
const styles = {
// Just here to make the abbreviated part more obvious in the component library
underlined: {
textDecoration: "underline dotted",
},
};

View File

@ -14,7 +14,7 @@ const createWrapper = (): FC<PropsWithChildren> => {
};
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(),
});

View File

@ -1,14 +1,13 @@
import { FC, PropsWithChildren, useState, useRef } from "react";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import ButtonGroup from "@mui/material/ButtonGroup";
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 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 { DisplayApp } from "api/typesGenerated";
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<VSCodeDesktopButtonProps>
> = (props) => {
export const VSCodeDesktopButton: FC<VSCodeDesktopButtonProps> = (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<VSCodeVariant>(() => {
if (!previousVariant) {
return "vscode";
@ -38,7 +34,7 @@ export const VSCodeDesktopButton: FC<
const menuAnchorRef = useRef<HTMLDivElement>(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<VSCodeDesktopButtonProps> = ({
userName,
workspaceName,
agentName,
folderPath,
}: VSCodeDesktopButtonProps) => {
}) => {
const [loading, setLoading] = useState(false);
return (
@ -153,12 +149,12 @@ const VSCodeButton = ({
);
};
const VSCodeInsidersButton = ({
const VSCodeInsidersButton: FC<VSCodeDesktopButtonProps> = ({
userName,
workspaceName,
agentName,
folderPath,
}: VSCodeDesktopButtonProps) => {
}) => {
const [loading, setLoading] = useState(false);
return (

View File

@ -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.

View File

@ -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 => {

View File

@ -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";

View File

@ -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);
};

View File

@ -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
},
},
);

View File

@ -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;

View File

@ -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: [
{

View File

@ -0,0 +1,37 @@
export const localStorageMock = (): Storage => {
const store = new Map<string, string>();
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<string, undefined> = 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,
});

View File

@ -1,22 +0,0 @@
export const localStorageMock = () => {
const store = {} as Record<string, string>;
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() });