Skip to content

Commit 5097fc6

Browse files
committed
Merge branch 'main' into charmed-snapcraft-io
2 parents cdcb3c1 + ac90f4b commit 5097fc6

127 files changed

Lines changed: 1860 additions & 1556 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
"@babel/preset-typescript": "7.26.0",
3333
"@canonical/cookie-policy": "3.6.5",
3434
"@canonical/global-nav": "3.6.4",
35-
"@canonical/react-components": "2.2.4",
36-
"@canonical/store-components": "0.53.0",
35+
"@canonical/react-components": "2.7.9",
36+
"@canonical/store-components": "0.54.2",
3737
"@dnd-kit/core": "6.3.1",
3838
"@dnd-kit/sortable": "8.0.0",
3939
"@dnd-kit/utilities": "3.2.2",
@@ -70,6 +70,7 @@
7070
"downshift": "9.0.8",
7171
"expose-loader": "5.0.0",
7272
"fast-average-color": "9.4.0",
73+
"jotai": "2.12.5",
7374
"markdown-it": "14.1.0",
7475
"nanoid": "5.0.9",
7576
"polylabel": "2.0.1",
@@ -84,12 +85,11 @@
8485
"react-dnd-html5-backend": "16.0.1",
8586
"react-dom": "18.3.1",
8687
"react-hook-form": "7.54.2",
87-
"react-joyride": "2.9.3",
88+
"react-joyride": "3.0.0-7",
8889
"react-query": "3.39.3",
8990
"react-redux": "8.1.3",
9091
"react-router-dom": "7.1.1",
9192
"react-sortable-hoc": "2.0.0",
92-
"recoil": "0.7.7",
9393
"redux": "4.2.1",
9494
"redux-mock-store": "1.5.5",
9595
"redux-thunk": "2.4.2",
@@ -100,7 +100,7 @@
100100
"ts-loader": "9.5.1",
101101
"typescript": "5.3.3",
102102
"uuid": "11.0.4",
103-
"vanilla-framework": "4.23.2",
103+
"vanilla-framework": "4.26.0",
104104
"watch-cli": "0.2.3",
105105
"webpack": "5.97.1",
106106
"webpack-cli": "6.0.1",

redirects.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ docs/snapcraft-quickstart/?: https://documentation.ubuntu.com/snapcraft/stable/t
136136
docs/snapcraft-checklist/?: https://documentation.ubuntu.com/snapcraft/stable/tutorials/craft-a-snap/
137137
docs/adding-parts/?: https://documentation.ubuntu.com/snapcraft/stable/tutorials/craft-a-snap/
138138
docs/defining-a-command/?: https://documentation.ubuntu.com/snapcraft/stable/tutorials/craft-a-snap/
139+
docs/snapcraft-tutorials/?: https://documentation.ubuntu.com/snapcraft/stable/tutorials/
140+
docs/snapcraft-reference/?: https://documentation.ubuntu.com/snapcraft/stable/reference/
139141

140142
# Old URL redirects
141143
docs/build-snaps: /docs/snap-format

requirements.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# App dependencies
2-
canonicalwebteam.flask-base==2.5.0
2+
canonicalwebteam.flask-base==2.6.0
33
canonicalwebteam.candid==0.9.0
4-
canonicalwebteam.discourse==6.1.1
5-
canonicalwebteam.blog==6.4.4
6-
canonicalwebteam.search==2.1.1
7-
canonicalwebteam.image-template==1.5.0
8-
canonicalwebteam.store-api==6.4.0
4+
canonicalwebteam.discourse==6.3.0
5+
canonicalwebteam.blog==6.4.6
6+
canonicalwebteam.search==2.1.2
7+
canonicalwebteam.image-template==1.6.0
8+
canonicalwebteam.store-api==6.7.0
99
canonicalwebteam.launchpad==0.9.0
1010
django-openid-auth==0.17
1111
Flask-OpenID==1.3.0

static/js/global.d.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,8 @@ declare interface Window {
2424
setVolume: (level: number) => void;
2525
};
2626
};
27-
DNS_VERIFICATION_TOKEN: string;
2827
SENTRY_DSN: string;
2928
CSRF_TOKEN: string;
30-
SNAP_LISTING_DATA: {
31-
DNS_VERIFICATION_TOKEN: string;
32-
};
3329
API_URL: string;
3430
}
3531

static/js/publisher/brand-store.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { QueryClient, QueryClientProvider } from "react-query";
33
import * as Sentry from "@sentry/react";
44
import { BrowserTracing } from "@sentry/browser";
55
import BrandStoreRoot from "./routes/brand-store-root";
6-
import { RecoilRoot } from "recoil";
6+
import { Provider as JotaiProvider } from "jotai";
7+
78
Sentry.init({
89
dsn: window.SENTRY_DSN,
910
integrations: [new BrowserTracing()],
@@ -22,9 +23,9 @@ const queryClient = new QueryClient({
2223
});
2324

2425
root.render(
25-
<QueryClientProvider client={queryClient}>
26-
<RecoilRoot>
26+
<JotaiProvider>
27+
<QueryClientProvider client={queryClient}>
2728
<BrandStoreRoot />
28-
</RecoilRoot>
29-
</QueryClientProvider>,
29+
</QueryClientProvider>
30+
</JotaiProvider>,
3031
);

static/js/publisher/components/AppPagination/AppPagination.tsx

Lines changed: 0 additions & 132 deletions
This file was deleted.

static/js/publisher/components/AppPagination/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

static/js/publisher/components/Filter/Filter.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { useSearchParams } from "react-router-dom";
2-
import { useSetRecoilState } from "recoil";
2+
import { useSetAtom } from "jotai";
33
import { Button, Icon } from "@canonical/react-components";
44

5-
import type { RecoilState } from "recoil";
5+
import type { PrimitiveAtom } from "jotai";
66

77
type Props = {
8-
state: RecoilState<string>;
8+
state: PrimitiveAtom<string>;
99
label: string;
1010
placeholder: string;
1111
};
1212

1313
function Filter({ state, label, placeholder }: Props): React.JSX.Element {
1414
const [searchParams, setSearchParams] = useSearchParams();
15-
const setFilter = useSetRecoilState(state);
15+
const setFilter = useSetAtom(state);
1616

1717
return (
1818
<div className="p-search-box">
Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
1-
import { useEffect } from "react";
21
import { BrowserRouter } from "react-router-dom";
3-
import { RecoilRoot, RecoilValue, useRecoilValue, atom } from "recoil";
2+
import { atom as jotaiAtom } from "jotai";
43
import { QueryClient, QueryClientProvider } from "react-query";
5-
import { render, screen, fireEvent } from "@testing-library/react";
4+
import { render, screen } from "@testing-library/react";
65
import userEvent from "@testing-library/user-event";
76
import "@testing-library/jest-dom";
87

98
import Filter from "../Filter";
109

11-
const mockFilterState = atom({
12-
key: "mockFilter",
13-
default: "" as string,
14-
});
10+
import { JotaiTestProvider } from "../../../test-utils";
11+
12+
const mockFilterState = jotaiAtom("" as string);
1513

1614
const searchInputLabel = "Test filter label";
1715

18-
const queryClient = new QueryClient({
19-
defaultOptions: {
20-
queries: {
21-
refetchOnWindowFocus: false,
22-
refetchOnReconnect: false,
23-
},
24-
},
25-
});
16+
const queryClient = new QueryClient();
2617

2718
const mockFilterQuery = { filter: "" };
2819

@@ -31,36 +22,21 @@ jest.mock("react-router-dom", () => ({
3122
useSearchParams: () => [new URLSearchParams(mockFilterQuery), jest.fn()],
3223
}));
3324

34-
export const RecoilObserver = ({
35-
node,
36-
onChange,
37-
}: {
38-
node: RecoilValue<string>;
39-
onChange: (value: string) => void;
40-
}) => {
41-
const value = useRecoilValue(node);
42-
useEffect(() => onChange(value), [onChange, value]);
43-
return null;
44-
};
45-
46-
const onChange = jest.fn();
47-
4825
const renderComponent = (filterQuery?: string) => {
4926
mockFilterQuery.filter = filterQuery || "";
5027

5128
return render(
52-
<RecoilRoot>
29+
<QueryClientProvider client={queryClient}>
5330
<BrowserRouter>
54-
<QueryClientProvider client={queryClient}>
55-
<RecoilObserver node={mockFilterState} onChange={onChange} />
31+
<JotaiTestProvider initialValues={[[mockFilterState, ""]]}>
5632
<Filter
5733
state={mockFilterState}
5834
label="Test filter label"
5935
placeholder="Test filter placeholder"
6036
/>
61-
</QueryClientProvider>
37+
</JotaiTestProvider>
6238
</BrowserRouter>
63-
</RecoilRoot>,
39+
</QueryClientProvider>,
6440
);
6541
};
6642

@@ -80,21 +56,10 @@ describe("Filter", () => {
8056
expect(screen.getByLabelText(searchInputLabel)).toHaveValue("policy-name");
8157
});
8258

83-
it("calls `setFilter` when the search input changes", () => {
84-
renderComponent();
85-
fireEvent.change(screen.getByLabelText(searchInputLabel), {
86-
target: {
87-
value: "policy-name",
88-
},
89-
});
90-
expect(onChange).toHaveBeenCalledWith("policy-name");
91-
});
92-
9359
it("clears the filter when the reset button is clicked", async () => {
9460
const user = userEvent.setup();
9561
renderComponent();
9662
await user.click(screen.getByRole("button", { name: "Clear filter" }));
97-
expect(onChange).toHaveBeenCalledWith("");
9863
expect(screen.getByLabelText(searchInputLabel)).toHaveValue("");
9964
});
10065
});

static/js/publisher/components/Navigation/Navigation.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useState, useEffect } from "react";
2-
import { useRecoilState, useRecoilValue } from "recoil";
2+
import { useAtom, useAtomValue } from "jotai";
33
import { useParams, NavLink } from "react-router-dom";
44
import { Icon } from "@canonical/react-components";
55

@@ -17,15 +17,15 @@ function Navigation({
1717
}: {
1818
sectionName: string | null;
1919
}): React.JSX.Element {
20-
const brandStoresList = useRecoilValue(brandStoresState);
20+
const brandStoresList = useAtomValue(brandStoresState);
2121
const { id } = useParams();
2222
const { data: brand } = useBrand(id);
2323
const { data: publisherData } = usePublisher();
2424
const { data: validationSetsData } = useValidationSets();
2525
const [pinSideNavigation, setPinSideNavigation] = useState<boolean>(false);
2626
const [collapseNavigation, setCollapseNavigation] = useState<boolean>(false);
27-
const [publisher, setPublisher] = useRecoilState(publisherState);
28-
const [brandId, setBrandId] = useRecoilState(brandIdState);
27+
const [publisher, setPublisher] = useAtom(publisherState);
28+
const [brandId, setBrandId] = useAtom(brandIdState);
2929

3030
const currentStore = brandStoresList.find((store) => store.id === id);
3131

0 commit comments

Comments
 (0)