Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 5 additions & 23 deletions static/js/publisher/pages/Remodel/Remodel.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import { useEffect, useState } from "react";
import { useAtomValue, useSetAtom } from "jotai";
import {
useParams,
useSearchParams,
Link,
useNavigate,
} from "react-router-dom";
import { useParams, Link, useNavigate, useLocation } from "react-router-dom";
import { Notification, Icon, Row, Col } from "@canonical/react-components";
Comment thread
steverydz marked this conversation as resolved.

import { useRemodels } from "../../hooks";
import {
remodelsListFilterState,
remodelsListState,
} from "../../state/remodelsState";
import { remodelsListState } from "../../state/remodelsState";
import { brandIdState, brandStoreState } from "../../state/brandStoreState";
import { setPageTitle, isClosedPanel } from "../../utils";
import { PortalEntrance } from "../Portals/Portals";

import Filter from "../../components/Filter";
import RemodelTable from "./RemodelTable";
import ConfigureRemodelForm from "./ConfigureRemodelForm";

Expand All @@ -26,6 +17,7 @@ import type { Remodel, RemodelResponse, ApiResponse } from "../../types/shared";

function Remodel(): React.JSX.Element {
const { id, modelId } = useParams();
const location = useLocation();
const brandId = useAtomValue(brandIdState);
const {
isLoading,
Expand All @@ -38,12 +30,10 @@ function Remodel(): React.JSX.Element {
modelId,
);
const setRemodels = useSetAtom(remodelsListState);
const setFilter = useSetAtom(remodelsListFilterState);
const [showNotification, setShowNotification] = useState(false);
const [showErrorNotification, setShowErrorNotification] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
const brandStore = useAtomValue(brandStoreState(id));
const [searchParams] = useSearchParams();
const navigate = useNavigate();

brandStore
Expand All @@ -53,9 +43,8 @@ function Remodel(): React.JSX.Element {
useEffect(() => {
if (!isLoading && !isError && data) {
setRemodels(data.data?.allowlist || []);
setFilter(searchParams.get("filter") || "");
}
}, [isLoading, error, data, brandId, id]);
}, [isLoading, isError, data, brandId, id]);

return (
<>
Expand All @@ -77,14 +66,7 @@ function Remodel(): React.JSX.Element {
) : (
<>
<Row>
<Col size={6}>
<Filter
state={remodelsListFilterState}
label="Search remodels"
placeholder="Search remodels"
/>
</Col>
<Col size={6} className="u-align--right">
<Col size={12} className="u-align--right">
<Link
className={`p-button--positive ${isError && !data ? "is-disabled" : ""}`}
to={`/admin/${id}/models/${modelId}/remodel/configure`}
Expand Down
25 changes: 8 additions & 17 deletions static/js/publisher/pages/Remodel/RemodelTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import { useAtomValue } from "jotai";
import { MainTable, TablePagination } from "@canonical/react-components";
import { format } from "date-fns";

import { filteredRemodelsListState } from "../../state/remodelsState";
import { useSortTableData } from "../../hooks";
import { remodelsListState } from "../../state/remodelsState";

import type { Remodel } from "../../types/shared";

function RemodelTable(): React.JSX.Element {
const remodels = useAtomValue(filteredRemodelsListState);
const remodels = useAtomValue(remodelsListState);

const headers = [
{ content: "Target model", sortKey: "to-model", style: { width: "250px" } },
{
content: "Target model",
style: { width: "250px" },
},
{
content: "Original model",
sortKey: "from-model",
style: { width: "250px" },
},
{ content: "Serial" },
{
content: "Created date",
className: "u-align--right",
sortKey: "created-at",
style: { width: "130px" },
},
{ content: "Note" },
Expand All @@ -42,28 +42,19 @@ function RemodelTable(): React.JSX.Element {
},
{ content: remodel["description"] },
],
sortData: {
"to-model": remodel["to-model"],
"from-model": remodel["from-model"],
"created-at": remodel["created-at"],
},
};
});

const { rows: sortedRows, updateSort } = useSortTableData({ rows });

return (
<TablePagination
data={sortedRows}
data={rows}
pageLimits={[25, 50, 100, 200]}
position="below"
>
<MainTable
data-testid="remodel-table"
sortable
emptyStateMsg="No remodels match this filter"
emptyStateMsg="No remodels found"
headers={headers}
onUpdateSort={updateSort}
/>
</TablePagination>
);
Expand Down
12 changes: 0 additions & 12 deletions static/js/publisher/pages/Remodel/__tests__/Remodel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,6 @@ describe("Remodel", () => {
).toBeInTheDocument();
});

it("doesn't display filter if user has no remodels access", () => {
mockUseRemodels.mockReturnValue(useRemodelsNoPermissions);
renderComponent();
expect(screen.queryByLabelText("Search remodels")).not.toBeInTheDocument();
});

it("doesn't display table if user has no remodels access", () => {
mockUseRemodels.mockReturnValue(useRemodelsNoPermissions);
renderComponent();
Expand All @@ -122,12 +116,6 @@ describe("Remodel", () => {
).not.toBeInTheDocument();
});

it("displays filter if user has remodels access", () => {
mockUseRemodels.mockReturnValue(useRemodelsPermissions);
renderComponent();
expect(screen.getByLabelText("Search remodels")).toBeInTheDocument();
});

it("displays table if user has remodels access", () => {
mockUseRemodels.mockReturnValue(useRemodelsPermissions);
renderComponent();
Expand Down
70 changes: 0 additions & 70 deletions static/js/publisher/pages/Remodel/__tests__/RemodelTable.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BrowserRouter } from "react-router-dom";
import { QueryClientProvider, QueryClient } from "react-query";
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom";

import RemodelTable from "../RemodelTable";
Expand Down Expand Up @@ -54,73 +53,4 @@ describe("RemodelTable", () => {
screen.getByRole("columnheader", { name: "Note" }),
).toBeInTheDocument();
});

it("sorts the 'Target model' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", {
name: "Target model",
});
const columnHeaderBtn = screen.getByRole("button", {
name: "Target model",
});

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});

it("sorts the 'Original model' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", {
name: "Original model",
});
const columnHeaderBtn = screen.getByRole("button", {
name: "Original model",
});

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});

it("sorts the 'Created date' column when clicking the column header", async () => {
renderComponent();

const user = userEvent.setup();
const columnHeader = screen.getByRole("columnheader", {
name: "Created date",
});
const columnHeaderBtn = screen.getByRole("button", {
name: "Created date",
});

expect(columnHeader.getAttribute("aria-sort")).toBe("none");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("ascending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("descending");

await user.click(columnHeaderBtn);
expect(columnHeader.getAttribute("aria-sort")).toBe("none");
});
});
35 changes: 1 addition & 34 deletions static/js/publisher/state/remodelsState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,4 @@ import type { Remodel } from "../types/shared";

const remodelsListState = atom([] as Remodel[]);

const remodelsListFilterState = atom("" as string);

function getFilteredRemodels(
remodels: Array<Remodel>,
filterQuery?: string | null,
) {
if (!filterQuery) {
return remodels;
}

return remodels.filter((remodel: Remodel) => {
if (
(remodel["from-model"] && remodel["from-model"].includes(filterQuery)) ||
(remodel["to-model"] && remodel["to-model"].includes(filterQuery))
) {
return true;
}

return false;
});
}

const filteredRemodelsListState = atom<Array<Remodel>>((get) => {
const filter = get(remodelsListFilterState);
const remodels = get(remodelsListState);

return getFilteredRemodels(remodels, filter);
});

export {
remodelsListState,
remodelsListFilterState,
filteredRemodelsListState,
};
export { remodelsListState };
Loading