Skip to content

Commit

Permalink
Merge branch 'main' of github.com:canonical/charmhub.io into WD-17915-…
Browse files Browse the repository at this point in the history
…upgrade-mermaid-version
  • Loading branch information
codeEmpress1 committed Dec 18, 2024
2 parents 92dea0b + 313c91f commit a07f45f
Show file tree
Hide file tree
Showing 23 changed files with 627 additions and 9,838 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
"@babel/preset-env": "7.23.9",
"@babel/preset-react": "7.23.3",
"@babel/preset-typescript": "7.23.3",
"@canonical/cookie-policy": "3.6.4",
"@canonical/cookie-policy": "3.6.5",
"@canonical/global-nav": "3.6.4",
"@canonical/react-components": "1.7.1",
"@canonical/store-components": "0.51.0",
"@canonical/react-components": "1.7.2",
"@canonical/store-components": "0.52.0",
"@sentry/react": "7.113.0",
"@testing-library/dom": "10.4.0",
"@testing-library/jest-dom": "6.4.2",
Expand Down Expand Up @@ -61,7 +61,7 @@
"style-loader": "3.3.4",
"ts-loader": "9.5.1",
"typescript": "5.3.3",
"vanilla-framework": "4.18.2",
"vanilla-framework": "4.18.4",
"watch-cli": "0.2.3",
"webpack": "5.94.0",
"webpack-cli": "5.1.4"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import { useState } from "react";

type Props = {
hasDeveloperDocumentation: boolean;
};

function InterfaceDetailsNav({ hasDeveloperDocumentation }: Props) {
const [activeLink, setActiveLink] = useState("charms");
return (
<div className="p-side-navigation">
<ul className="p-side-navigation__list">
<li className="p-side-navigation__item">
<a href="#charms" className="p-side-navigation__link is-active">
<a
href="#charms"
className={`p-side-navigation__link ${
activeLink === "charms" ? "is-active" : ""
}`}
onClick={() => setActiveLink("charms")}
>
Charms
</a>
</li>
{hasDeveloperDocumentation && (
<li className="p-side-navigation__item">
<a
href="#developer-documentation"
className="p-side-navigation__link"
className={`p-side-navigation__link ${
activeLink === "developer-documentation" ? "is-active" : ""
}`}
onClick={() => setActiveLink("developer-documentation")}
>
Developer documentation
</a>
Expand Down
2 changes: 1 addition & 1 deletion static/js/src/store/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { QueryClient, QueryClientProvider } from "react-query";

import Packages from "../Packages";
import Packages from "../../pages/Packages";

function App() {
const queryClient = new QueryClient({
Expand Down
2 changes: 1 addition & 1 deletion static/js/src/store/components/App/__tests__/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { render, screen } from "@testing-library/react";
import App from "../App";
import "@testing-library/jest-dom";

jest.mock("../../Packages", () => () => <div>Packages Component</div>);
jest.mock("../../../pages/Packages", () => () => <div>Packages Component</div>);

describe("App Component", () => {
test("should render the App component with the Packages route", () => {
Expand Down
52 changes: 3 additions & 49 deletions static/js/src/store/components/Banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,18 @@
import { RefObject } from "react";
import { useSearchParams } from "react-router-dom";
import { Strip, Row, Col } from "@canonical/react-components";
import { SearchInput } from "../SearchInput";

type Props = {
searchRef: RefObject<HTMLInputElement>;
searchSummaryRef: RefObject<HTMLDivElement>;
};

function Banner({ searchRef, searchSummaryRef }: Props) {
const [searchParams, setSearchParams] = useSearchParams();

function Banner({ searchRef }: Props) {
return (
<Strip type="dark">
<Row>
<Col size={6} className="col-start-large-4">
<h1 className="p-heading--2">The Charm Collection</h1>
<form
className="p-search-box"
onSubmit={(e) => {
e.preventDefault();

if (searchRef.current && searchRef.current.value) {
searchParams.delete("page");
searchParams.set("q", searchRef.current.value);
setSearchParams(searchParams);
}

if (searchSummaryRef && searchSummaryRef.current) {
searchSummaryRef.current.scrollIntoView({
behavior: "smooth",
});
}
}}
>
<label className="u-off-screen" htmlFor="search">
Search Charmhub
</label>
<input
type="search"
id="search"
className="p-search-box__input"
name="q"
placeholder="Search Charmhub"
defaultValue={searchParams.get("q") || ""}
ref={searchRef}
/>
<button
type="reset"
className="p-search-box__reset"
onClick={() => {
searchParams.delete("q");
setSearchParams(searchParams);
}}
>
<i className="p-icon--close">Close</i>
</button>
<button type="submit" className="p-search-box__button">
<i className="p-icon--search">Search</i>
</button>
</form>
<SearchInput searchRef={searchRef} />
</Col>
</Row>
</Strip>
Expand Down
63 changes: 5 additions & 58 deletions static/js/src/store/components/Banner/__tests__/Banner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ window.HTMLElement.prototype.scrollIntoView = jest.fn();
describe("Banner Component", () => {
let mockSetSearchParams: jest.Mock;
let mockSearchRef: React.RefObject<HTMLInputElement>;
let mockSearchSummaryRef: React.RefObject<HTMLDivElement>;

beforeEach(() => {
mockSetSearchParams = jest.fn();
Expand All @@ -25,19 +24,10 @@ describe("Banner Component", () => {
mockSearchRef = {
current: document.createElement("input"),
};

mockSearchSummaryRef = {
current: document.createElement("div"),
};
});

test("should render the Banner component", () => {
render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);
render(<Banner searchRef={mockSearchRef} />);

expect(
screen.getByRole("heading", { name: /The Charm Collection/i })
Expand All @@ -50,12 +40,7 @@ describe("Banner Component", () => {
});

test("should update search params and scroll on form submission", () => {
render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);
render(<Banner searchRef={mockSearchRef} />);

if (mockSearchRef.current) {
mockSearchRef.current.value = "kubernetes";
Expand All @@ -66,32 +51,18 @@ describe("Banner Component", () => {
expect(mockSetSearchParams).toHaveBeenCalledWith(
new URLSearchParams({ q: "kubernetes" })
);

expect(mockSearchSummaryRef.current?.scrollIntoView).toHaveBeenCalledWith({
behavior: "smooth",
});
});

test("should clear search params on reset button click", () => {
render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);
render(<Banner searchRef={mockSearchRef} />);

fireEvent.click(screen.getByRole("button", { name: /Close/i }));

expect(mockSetSearchParams).toHaveBeenCalledWith(new URLSearchParams());
});

test("should not update search params when input is empty", () => {
render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);
render(<Banner searchRef={mockSearchRef} />);

if (mockSearchRef.current) {
mockSearchRef.current.value = "";
Expand All @@ -109,35 +80,11 @@ describe("Banner Component", () => {
mockSetSearchParams,
]);

render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);
render(<Banner searchRef={mockSearchRef} />);

const searchInput = screen.getByPlaceholderText(
"Search Charmhub"
) as HTMLInputElement;
expect(searchInput.value).toBe("test");
});

test("should call scrollIntoView on form submission", () => {
render(
<Banner
searchRef={mockSearchRef}
searchSummaryRef={mockSearchSummaryRef}
/>
);

if (mockSearchSummaryRef.current) {
mockSearchSummaryRef.current.scrollIntoView = jest.fn();
}

fireEvent.submit(screen.getByRole("button", { name: /Search/i }));

expect(mockSearchSummaryRef.current?.scrollIntoView).toHaveBeenCalledWith({
behavior: "smooth",
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { Col, Link, List, Row, Strip } from "@canonical/react-components";
import { SearchInput } from "../SearchInput";
import { PackageFilter } from "../PackageFilter";
import { useRef } from "react";
import { Store } from "../../types";

export const EmptyResultSection = ({
searchTerm,
data,
isFetching,
}: {
searchTerm: string | null;
data?: Store;
isFetching: boolean;
}) => {
const searchRef = useRef<HTMLInputElement | null>(null);

return (
<Strip>
<Row>
<Col size={3}>
<PackageFilter data={data} disabled={isFetching} />
</Col>

<Col size={9}>
<Row>
<Col size={9}>
<h1 className="p-heading--2">
Search results for "{searchTerm}"
</h1>
<SearchInput searchRef={searchRef} />
</Col>
</Row>
<Row>
<Col size={4}>
<h2 className="p-heading--4">
Why not trying widening your search?
</h2>
<p className="p-heading--4">You can do this by:</p>
</Col>
<Col size={4}>
<List
items={[
"Adding alternative words or phrases",
"Using individual words instead of phrases",
"Trying a different spelling",
]}
ticked
/>
</Col>
</Row>

<Row>
<Col size={9}>
<div className="u-fixed-width u-hide--small u-hide--medium">
<hr className="p-rule" />
</div>
</Col>
</Row>

<Row>
<Col size={4}>
<h2 className="p-heading--4">Still no luck?</h2>
</Col>
<Col size={4} className="snap-packages__empty-more-options">
<List
items={[
<Link
href="/"
key={"explore-store"}
className={"snap-packages__list-item"}
>
Explore the store
</Link>,
<Link
href="https://canonical.com/contact-us"
key={"contact-us"}
className={"snap-packages__list-item"}
>
Contact us
</Link>,
]}
/>
</Col>
</Row>
</Col>
</Row>
</Strip>
);
};
1 change: 1 addition & 0 deletions static/js/src/store/components/EmptyResultSection/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { EmptyResultSection } from "./EmptyResultSection";
Loading

0 comments on commit a07f45f

Please sign in to comment.