diff --git a/package.json b/package.json
index d08767b3cf..61237633c0 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
"@canonical/cookie-policy": "3.6.3",
"@canonical/global-nav": "3.6.4",
"@canonical/latest-news": "1.5.0",
- "@canonical/react-components": "0.59.1",
+ "@canonical/react-components": "0.60.0",
"@canonical/store-components": "0.50.1",
"@dnd-kit/core": "6.1.0",
"@dnd-kit/sortable": "8.0.0",
diff --git a/static/js/validation-sets/index.tsx b/static/js/validation-sets/index.tsx
new file mode 100644
index 0000000000..dbe5f08162
--- /dev/null
+++ b/static/js/validation-sets/index.tsx
@@ -0,0 +1,28 @@
+import { createRoot } from "react-dom/client";
+import { createBrowserRouter, RouterProvider } from "react-router-dom";
+
+import Root from "./routes/root";
+import ValidationSets from "./pages/ValidationSets";
+import ValidationSet from "./pages/ValidationSet";
+
+const router = createBrowserRouter([
+ {
+ path: "/",
+ element: ,
+ children: [
+ {
+ path: "/validation-sets",
+ element: ,
+ },
+ {
+ path: "/validation-sets/:validationSetId",
+ element: ,
+ },
+ ],
+ },
+]);
+
+const rootEl = document.getElementById("root") as HTMLElement;
+const root = createRoot(rootEl);
+
+root.render();
diff --git a/static/js/validation-sets/pages/ValidationSet/ValidationSet.tsx b/static/js/validation-sets/pages/ValidationSet/ValidationSet.tsx
new file mode 100644
index 0000000000..600af53dbd
--- /dev/null
+++ b/static/js/validation-sets/pages/ValidationSet/ValidationSet.tsx
@@ -0,0 +1,9 @@
+function ValidationSet(): JSX.Element {
+ return (
+ <>
+
Validation set page
+ >
+ );
+}
+
+export default ValidationSet;
diff --git a/static/js/validation-sets/pages/ValidationSet/index.ts b/static/js/validation-sets/pages/ValidationSet/index.ts
new file mode 100644
index 0000000000..609f4f2b42
--- /dev/null
+++ b/static/js/validation-sets/pages/ValidationSet/index.ts
@@ -0,0 +1 @@
+export { default } from "./ValidationSet";
diff --git a/static/js/validation-sets/pages/ValidationSets/ValidationSets.tsx b/static/js/validation-sets/pages/ValidationSets/ValidationSets.tsx
new file mode 100644
index 0000000000..cf21ef75c6
--- /dev/null
+++ b/static/js/validation-sets/pages/ValidationSets/ValidationSets.tsx
@@ -0,0 +1,9 @@
+function ValidationSets(): JSX.Element {
+ return (
+ <>
+ Validation sets page
+ >
+ );
+}
+
+export default ValidationSets;
diff --git a/static/js/validation-sets/pages/ValidationSets/index.ts b/static/js/validation-sets/pages/ValidationSets/index.ts
new file mode 100644
index 0000000000..a1d62d5bde
--- /dev/null
+++ b/static/js/validation-sets/pages/ValidationSets/index.ts
@@ -0,0 +1 @@
+export { default } from "./ValidationSets";
diff --git a/static/js/validation-sets/routes/root.tsx b/static/js/validation-sets/routes/root.tsx
new file mode 100644
index 0000000000..1b28ff857f
--- /dev/null
+++ b/static/js/validation-sets/routes/root.tsx
@@ -0,0 +1,74 @@
+import { useState } from "react";
+import { Outlet } from "react-router-dom";
+
+import {
+ ApplicationLayout,
+ Panel,
+ Row,
+ Col,
+} from "@canonical/react-components";
+
+function Root(): JSX.Element {
+ const [menuPinned, setMenuPinned] = useState(false);
+ const [menuCollapsed, setMenuCollapsed] = useState(false);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Root;
diff --git a/templates/store/validation-sets.html b/templates/store/validation-sets.html
new file mode 100644
index 0000000000..bc21b17ca1
--- /dev/null
+++ b/templates/store/validation-sets.html
@@ -0,0 +1,7 @@
+{% set show_header = False %}
+{% extends "_base-layout.html" %}
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/webapp/store/views.py b/webapp/store/views.py
index c8b61c7aa6..9ef365c910 100644
--- a/webapp/store/views.py
+++ b/webapp/store/views.py
@@ -100,6 +100,12 @@ def get_validation_set(validation_set_id):
return response
+ @store.route("/validation-sets", defaults={"path": ""})
+ @store.route("/validation-sets/")
+ @login_required
+ def validation_sets(path):
+ return flask.render_template("store/validation-sets.html")
+
@store.route("/discover")
def discover():
return flask.redirect(flask.url_for(".homepage"))
diff --git a/webpack.config.entry.js b/webpack.config.entry.js
index b9150cbbc9..c4f6eac7cd 100644
--- a/webpack.config.entry.js
+++ b/webpack.config.entry.js
@@ -21,4 +21,5 @@ module.exports = {
"publisher-settings": "./static/js/publisher/settings/index.tsx",
"about-listing": "./static/js/public/about/listing.ts",
store: "./static/js/store/index.tsx",
+ "validation-sets": "./static/js/validation-sets/index.tsx",
};
diff --git a/yarn.lock b/yarn.lock
index bd0f239921..b0aa56c53c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1109,10 +1109,10 @@
react-table "7.8.0"
react-useportal "1.0.19"
-"@canonical/react-components@0.59.1":
- version "0.59.1"
- resolved "https://registry.yarnpkg.com/@canonical/react-components/-/react-components-0.59.1.tgz#bcc4cc6ec7b309a179fca2aaffd58f03a75df4e1"
- integrity sha512-vHd287WhZxJpojGCYW312Z/BcorO1ybQ7CEE/MRERXl7XUYZlvx9i8AortoesAxFZK/BgujQgafx/zesL/9uUQ==
+"@canonical/react-components@0.60.0":
+ version "0.60.0"
+ resolved "https://registry.yarnpkg.com/@canonical/react-components/-/react-components-0.60.0.tgz#526adf54acf4bd74244ec600c72ef50f6e3ff5ae"
+ integrity sha512-i90GBNVKFHXctRpN/dId6WmanFUdeAUSS0lS/V2JapAhaQDU6MoxyPh4DVGzsc1s6BqBFwBM6yqvlWLcQi4DEg==
dependencies:
"@types/jest" "29.5.12"
"@types/node" "20.12.11"