Skip to content

Commit 50a550c

Browse files
authored
feat: Add configure remodels form (#5592)
1 parent caf00ee commit 50a550c

18 files changed

Lines changed: 607 additions & 92 deletions

static/js/publisher/hooks/__tests__/useRemodels.test.tsx

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,12 @@ afterAll(() => {
7373

7474
describe("useRemodels", () => {
7575
test("returns remodels data", async () => {
76-
const { result } = renderHook(() => useRemodels("test-brand-id"), {
77-
wrapper: createWrapper(),
78-
});
76+
const { result } = renderHook(
77+
() => useRemodels("test-brand-id", "test-to-model"),
78+
{
79+
wrapper: createWrapper(),
80+
},
81+
);
7982

8083
await waitFor(() => {
8184
expect(result.current.isSuccess).toBe(true);
@@ -85,9 +88,12 @@ describe("useRemodels", () => {
8588
});
8689

8790
test("returns error if request fails", async () => {
88-
const { result } = renderHook(() => useRemodels("test-brand-id-fail"), {
89-
wrapper: createWrapper(),
90-
});
91+
const { result } = renderHook(
92+
() => useRemodels("test-brand-id-fail", "test-to-model"),
93+
{
94+
wrapper: createWrapper(),
95+
},
96+
);
9197

9298
await waitFor(() => {
9399
expect(result.current.isError).toBe(true);
@@ -97,9 +103,12 @@ describe("useRemodels", () => {
97103
});
98104

99105
test("returns error if network error", async () => {
100-
const { result } = renderHook(() => useRemodels("test-brand-id-error"), {
101-
wrapper: createWrapper(),
102-
});
106+
const { result } = renderHook(
107+
() => useRemodels("test-brand-id-error", "test-to-model"),
108+
{
109+
wrapper: createWrapper(),
110+
},
111+
);
103112

104113
await waitFor(() => {
105114
expect(result.current.isError).toBe(true);

static/js/publisher/hooks/useRemodels.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useQuery, UseQueryResult } from "react-query";
2-
import type { Remodel as RemodelType } from "../types/shared";
2+
import type { Remodel } from "../types/shared";
33

44
const useRemodels = (
55
brandId: string | undefined,
6-
): UseQueryResult<RemodelType[], Error> => {
7-
return useQuery<RemodelType[], Error>({
8-
queryKey: ["remodels", brandId],
6+
modelId: string | undefined,
7+
): UseQueryResult<Remodel[], Error> => {
8+
return useQuery<Remodel[], Error>({
9+
queryKey: ["remodels", brandId, modelId],
910
queryFn: async () => {
1011
const response = await fetch(
1112
`/api/store/${brandId}/models/remodel-allowlist`,
@@ -15,13 +16,31 @@ const useRemodels = (
1516
throw new Error("There was a problem fetching remodels");
1617
}
1718

18-
const remodelsData = await response.json();
19+
const data = await response.json();
1920

20-
if (!remodelsData.success) {
21-
throw new Error(remodelsData.message);
21+
if (!data.success) {
22+
throw new Error(data.message);
2223
}
2324

24-
return remodelsData.data.allowlist;
25+
const remodelsForCurrentModel = data.data.allowlist.filter(
26+
(remodel: Remodel) => {
27+
return (
28+
remodel["from-model"] === modelId || remodel["to-model"] === modelId
29+
);
30+
},
31+
);
32+
33+
return remodelsForCurrentModel.sort((a: Remodel, b: Remodel) => {
34+
if (a["created-at"] > b["created-at"]) {
35+
return -1;
36+
}
37+
38+
if (a["created-at"] < b["created-at"]) {
39+
return 1;
40+
}
41+
42+
return 0;
43+
});
2544
},
2645
enabled: !!brandId,
2746
});

static/js/publisher/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ root.render(
121121
<Route path="models">
122122
<Route index element={<Models />} />
123123
<Route path="create" element={<Models />} />
124-
<Route path=":model_id" element={<ModelDetailsPageLayout />}>
124+
<Route path=":modelId" element={<ModelDetailsPageLayout />}>
125125
<Route index element={<Model />} />
126126
<Route path="policies" element={<Policies />} />
127127
<Route path="policies/create" element={<Policies />} />
128128
<Route path="remodel" element={<Remodel />} />
129+
<Route path="remodel/configure" element={<Remodel />} />
129130
</Route>
130131
</Route>
131132
<Route path="*" element={<Navigate to="../snaps" replace />} />

static/js/publisher/layouts/ModelDetailsPageLayout/ModelBreadcrumb.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { Link, useParams } from "react-router-dom";
22

33
interface RouteParams {
44
id?: string;
5-
model_id?: string;
5+
modelId?: string;
66
}
77
function ModelBreadcrumb(): React.JSX.Element {
8-
const { id, model_id } = useParams() as RouteParams;
8+
const { id, modelId } = useParams() as RouteParams;
99

1010
return (
1111
<h1 className="p-heading--4">
1212
<Link to={`/admin/${id ?? ""}/models`}>&lsaquo;&nbsp;Models</Link> /{" "}
13-
{model_id ?? ""}
13+
{modelId ?? ""}
1414
</h1>
1515
);
1616
}

static/js/publisher/layouts/ModelDetailsPageLayout/ModelNav.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { Link, useParams } from "react-router-dom";
22

33
function ModelNav({ sectionName }: { sectionName: string }): React.JSX.Element {
4-
const { id, model_id } = useParams();
4+
const { id, modelId } = useParams();
55

66
return (
77
<nav className="p-tabs">
88
<ul className="p-tabs__list">
99
<li className="p-tabs__item">
1010
<Link
11-
to={`/admin/${id}/models/${model_id}`}
11+
to={`/admin/${id}/models/${modelId}`}
1212
className="p-tabs__link"
1313
aria-selected={sectionName === "overview"}
1414
role="tab"
@@ -18,7 +18,7 @@ function ModelNav({ sectionName }: { sectionName: string }): React.JSX.Element {
1818
</li>
1919
<li className="p-tabs__item">
2020
<Link
21-
to={`/admin/${id}/models/${model_id}/policies`}
21+
to={`/admin/${id}/models/${modelId}/policies`}
2222
className="p-tabs__link"
2323
aria-selected={sectionName === "policies"}
2424
role="tab"
@@ -28,7 +28,7 @@ function ModelNav({ sectionName }: { sectionName: string }): React.JSX.Element {
2828
</li>
2929
<li className="p-tabs__item">
3030
<Link
31-
to={`/admin/${id}/models/${model_id}/remodel`}
31+
to={`/admin/${id}/models/${modelId}/remodel`}
3232
className="p-tabs__link"
3333
aria-selected={sectionName === "remodel"}
3434
role="tab"

static/js/publisher/layouts/ModelDetailsPageLayout/ModelPageLayout.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import ModelNav from "./ModelNav";
44

55
function ModelDetailsPageLayout() {
66
const { pathname } = useLocation();
7-
const isPolicies = pathname.endsWith("policies");
8-
const isRemodel = pathname.endsWith("remodel");
7+
const isPolicies =
8+
pathname.endsWith("policies") || pathname.endsWith("policies/create");
9+
const isRemodel =
10+
pathname.endsWith("remodel") || pathname.endsWith("remodel/configure");
911

1012
const getSectionName = () => {
1113
if (isPolicies) {

static/js/publisher/pages/Model/CreatePolicyForm.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function CreatePolicyForm({
2424
setShowErrorNotification,
2525
refetchPolicies,
2626
}: Props): React.JSX.Element {
27-
const { id, model_id } = useParams();
27+
const { id, modelId } = useParams();
2828
const brandId = useAtomValue(brandIdState);
2929
const navigate = useNavigate();
3030
const location = useLocation();
@@ -37,7 +37,7 @@ function CreatePolicyForm({
3737

3838
const handleError = () => {
3939
setShowErrorNotification(true);
40-
navigate(`/admin/${id}/models/${model_id}/policies`);
40+
navigate(`/admin/${id}/models/${modelId}/policies`);
4141
setNewSigningKey({ name: "" });
4242
setIsSaving(false);
4343
setTimeout(() => {
@@ -56,7 +56,7 @@ function CreatePolicyForm({
5656

5757
setNewSigningKey({ name: "" });
5858

59-
return fetch(`/api/store/${brandId}/models/${model_id}/policies`, {
59+
return fetch(`/api/store/${brandId}/models/${modelId}/policies`, {
6060
method: "POST",
6161
body: formData,
6262
});
@@ -77,7 +77,7 @@ function CreatePolicyForm({
7777
setShowNotification(true);
7878
setIsSaving(false);
7979
refetchPolicies();
80-
navigate(`/admin/${id}/models/${model_id}/policies`);
80+
navigate(`/admin/${id}/models/${modelId}/policies`);
8181
setTimeout(() => {
8282
setShowNotification(false);
8383
}, 5000);
@@ -158,7 +158,7 @@ function CreatePolicyForm({
158158
<div className="u-align--right">
159159
<Link
160160
className="p-button u-no-margin--bottom"
161-
to={`/admin/${id}/models/${model_id}/policies`}
161+
to={`/admin/${id}/models/${modelId}/policies`}
162162
onClick={() => {
163163
setNewSigningKey({ name: "" });
164164
setShowErrorNotification(false);

static/js/publisher/pages/Model/Model.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type { Model as ModelType } from "../../types/shared";
2020
import { PortalEntrance } from "../Portals/Portals";
2121

2222
function Model() {
23-
const { id, model_id } = useParams();
23+
const { id, modelId } = useParams();
2424
const brandId = useAtomValue(brandIdState);
2525
const [apiKey, setApiKey] = useState("");
2626
const [showSuccessNotification, setShowSuccessNotificaton] = useState(false);
@@ -34,7 +34,7 @@ function Model() {
3434
formData.set("csrf_token", window.CSRF_TOKEN);
3535
formData.set("api_key", apiKey);
3636

37-
return fetch(`/api/store/${brandId}/models/${model_id}`, {
37+
return fetch(`/api/store/${brandId}/models/${modelId}`, {
3838
method: "PATCH",
3939
body: formData,
4040
});
@@ -84,7 +84,7 @@ function Model() {
8484
return;
8585
}
8686

87-
const current = models.find((model) => model.name === model_id);
87+
const current = models.find((model) => model.name === modelId);
8888

8989
if (!current) {
9090
return;
@@ -95,7 +95,7 @@ function Model() {
9595
}
9696

9797
return current;
98-
}, [models, model_id]);
98+
}, [models, modelId]);
9999

100100
currentModel && brandStore
101101
? setPageTitle(`${currentModel.name} in ${brandStore.name}`)

static/js/publisher/pages/Model/Policies.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ import { isClosedPanel, setPageTitle } from "../../utils";
2727
import { PortalEntrance } from "../Portals/Portals";
2828

2929
function Policies(): React.JSX.Element {
30-
const { id, model_id } = useParams();
30+
const { id, modelId } = useParams();
3131
const location = useLocation();
3232
const navigate = useNavigate();
3333
const { isLoading, isError, error, refetch, data }: UsePoliciesResponse =
34-
usePolicies(id, model_id);
34+
usePolicies(id, modelId);
3535
const signingKeys = useSigningKeys(id);
3636
const setPoliciesList = useSetAtom(policiesListState);
3737
const setFilter = useSetAtom(policiesListFilterState);
@@ -87,7 +87,7 @@ function Policies(): React.JSX.Element {
8787
<Col size={6} className="u-align--right">
8888
<Link
8989
className="p-button--positive"
90-
to={`/admin/${id}/models/${model_id}/policies/create`}
90+
to={`/admin/${id}/models/${modelId}/policies/create`}
9191
>
9292
Create policy
9393
</Link>
@@ -177,13 +177,13 @@ function Policies(): React.JSX.Element {
177177
isClosedPanel(location.pathname, "create") ? "u-hide" : ""
178178
}`}
179179
onClick={() => {
180-
navigate(`/admin/${id}/models/${model_id}/policies`);
180+
navigate(`/admin/${id}/models/${modelId}/policies`);
181181
setNewSigningKey({ name: "" });
182182
setShowErrorNotification(false);
183183
}}
184184
onKeyDown={(e) => {
185185
if (e.key === "Enter" || e.key === " ") {
186-
navigate(`/admin/${id}/models/${model_id}/policies`);
186+
navigate(`/admin/${id}/models/${modelId}/policies`);
187187
setNewSigningKey({ name: "" });
188188
setShowErrorNotification(false);
189189
}

static/js/publisher/pages/Model/PoliciesTable.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ function PoliciesTable({
2929
setShowDeletePolicyNotification,
3030
setShowDeletePolicyErrorNotification,
3131
}: Props): React.JSX.Element {
32-
const { id, model_id } = useParams();
32+
const { id, modelId } = useParams();
3333
const brandId = useAtomValue(brandIdState);
3434
const [policiesList, setPoliciesList] = useAtom(filteredPoliciesListState);
3535
const [showModal, setShowModal] = useState<boolean>(false);
3636
const [selectedPolicy, setSelectedPolicy] = useState<number | undefined>();
3737
const [isLoading, setIsLoading] = useState<boolean>(false);
38-
const { refetch } = usePolicies(id, model_id) as UsePoliciesResponse;
38+
const { refetch } = usePolicies(id, modelId) as UsePoliciesResponse;
3939

4040
const deletePolicy = async (policyRevision: number | undefined) => {
4141
if (policyRevision === undefined) {
@@ -52,7 +52,7 @@ function PoliciesTable({
5252
formData.set("csrf_token", window.CSRF_TOKEN);
5353

5454
const response = await fetch(
55-
`/api/store/${brandId}/models/${model_id}/policies/${policyRevision}`,
55+
`/api/store/${brandId}/models/${modelId}/policies/${policyRevision}`,
5656
{
5757
method: "DELETE",
5858
body: formData,

0 commit comments

Comments
 (0)