-
-
Variants
-
size=small width=content
-
-
);
}
+
+const statuses = allTaskRunStatuses.map((status) => ({
+ title: runStatusTitle(status),
+ value: status,
+}));
+
+function Statuses() {
+ const navigate = useNavigate();
+ const location = useOptimisticLocation();
+ const search = new URLSearchParams(location.search);
+
+ const handleChange = useCallback((values: string[]) => {
+ search.delete("status");
+ for (const value of values) {
+ search.append("status", value);
+ }
+ navigate(`${location.pathname}?${search.toString()}`, { replace: true });
+ }, []);
+
+ return (
+
+ );
+}
+
+export const projects = [
+ {
+ type: "section" as const,
+ title: "Apple",
+ items: [
+ {
+ title: "iTunes",
+ value: "itunes",
+ },
+ {
+ title: "App Store",
+ value: "appstore",
+ },
+ ],
+ },
+ {
+ type: "section" as const,
+ title: "Google",
+ items: [
+ {
+ title: "Maps",
+ value: "maps",
+ },
+ {
+ title: "Gmail",
+ value: "gmail",
+ },
+ {
+ title: "Waymo",
+ value: "waymo",
+ },
+ {
+ title: "Android",
+ value: "android",
+ },
+ ],
+ },
+ {
+ type: "section" as const,
+ title: "Uber",
+ items: [
+ {
+ title: "Planner",
+ value: "planner",
+ },
+ ],
+ },
+];
+
+function ProjectSelector() {
+ const location = useOptimisticLocation();
+ const search = new URLSearchParams(location.search);
+
+ const selected = projects
+ .find((p) => p.items.some((i) => i.value === search.get("project")))
+ ?.items.find((i) => i.value === search.get("project"));
+
+ const searchParams = new URLSearchParams(location.search);
+ searchParams.delete("project");
+
+ return (
+
}
+ items={projects}
+ shortcut={{ key: "p", modifiers: ["alt"] }}
+ filter={(item, search, sectionTitle) =>
+ sectionTitle?.toLowerCase().includes(search.toLowerCase()) ||
+ item.title.toLowerCase().includes(search.toLowerCase())
+ }
+ >
+ {(matches, { shortcutsEnabled, section }) => (
+
+ {section && {section.title}}
+ {matches?.map((match, index) => (
+ }
+ key={match.value}
+ value={match.value}
+ to={`?${searchParams.toString()}&project=${match.value}`}
+ shortcut={shortcutFromIndex(index, { shortcutsEnabled, section })}
+ >
+ {match.title}
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/apps/webapp/app/routes/storybook/route.tsx b/apps/webapp/app/routes/storybook/route.tsx
index f8ed181ab6..ad8e61b0b4 100644
--- a/apps/webapp/app/routes/storybook/route.tsx
+++ b/apps/webapp/app/routes/storybook/route.tsx
@@ -134,6 +134,10 @@ const stories: Story[] = [
name: "Select",
slug: "select",
},
+ {
+ name: "Filter",
+ slug: "filter",
+ },
{
name: "Popover",
slug: "popover",
diff --git a/apps/webapp/package.json b/apps/webapp/package.json
index c9c2df2923..ab06ac89d2 100644
--- a/apps/webapp/package.json
+++ b/apps/webapp/package.json
@@ -30,6 +30,8 @@
"/public/build"
],
"dependencies": {
+ "@ariakit/react": "^0.4.6",
+ "@ariakit/react-core": "^0.4.6",
"@aws-sdk/client-sqs": "^3.445.0",
"@codemirror/autocomplete": "^6.3.1",
"@codemirror/commands": "^6.1.2",
@@ -124,11 +126,13 @@
"lodash.omit": "^4.5.0",
"lucide-react": "^0.229.0",
"marked": "^4.0.18",
+ "match-sorter": "^6.3.4",
"morgan": "^1.10.0",
"nanoid": "^3.3.4",
"non.geist": "^1.0.2",
"ohash": "^1.1.3",
"openai": "^4.33.1",
+ "parse-duration": "^1.1.0",
"posthog-js": "^1.93.3",
"posthog-node": "^3.1.3",
"prism-react-renderer": "^1.3.5",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7a78f649d0..25c73dba4e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -201,6 +201,12 @@ importers:
apps/webapp:
dependencies:
+ '@ariakit/react':
+ specifier: ^0.4.6
+ version: 0.4.6(react-dom@18.2.0)(react@18.2.0)
+ '@ariakit/react-core':
+ specifier: ^0.4.6
+ version: 0.4.6(react-dom@18.2.0)(react@18.2.0)
'@aws-sdk/client-sqs':
specifier: ^3.445.0
version: 3.454.0
@@ -483,6 +489,9 @@ importers:
marked:
specifier: ^4.0.18
version: 4.2.5
+ match-sorter:
+ specifier: ^6.3.4
+ version: 6.3.4
morgan:
specifier: ^1.10.0
version: 1.10.0
@@ -498,6 +507,9 @@ importers:
openai:
specifier: ^4.33.1
version: 4.33.1
+ parse-duration:
+ specifier: ^1.1.0
+ version: 1.1.0
posthog-js:
specifier: ^1.93.3
version: 1.93.3
@@ -3309,6 +3321,34 @@ packages:
- chokidar
dev: true
+ /@ariakit/core@0.4.6:
+ resolution: {integrity: sha512-L2WIZZlxDs611m3YLSv2xvJyQrkkVQJlxn8Y4DlI1G65VLTEH7hysw3RYUNdXsl0gP6S20id3zBMJCHT9BCRcg==}
+ dev: false
+
+ /@ariakit/react-core@0.4.6(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-2Ca327IzSOxQEd3gEr59JJj0y8fXDMLYd+948wyOzIsk2/yoTnA4+R7Vhs361w3KzOjBQM44KmnNL7ckBMtT0w==}
+ peerDependencies:
+ react: ^17.0.0 || ^18.0.0
+ react-dom: ^17.0.0 || ^18.0.0
+ dependencies:
+ '@ariakit/core': 0.4.6
+ '@floating-ui/dom': 1.6.5
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ use-sync-external-store: 1.2.2(react@18.2.0)
+ dev: false
+
+ /@ariakit/react@0.4.6(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-7lZQew9n+nxswgJ5aL87xo42I+t3A8gWzaxIIZY+c58SLCASh1IdDkGLhGPcyhmXWRIjs/8L1h6cMbRMEBrtJQ==}
+ peerDependencies:
+ react: ^17.0.0 || ^18.0.0
+ react-dom: ^17.0.0 || ^18.0.0
+ dependencies:
+ '@ariakit/react-core': 0.4.6(react-dom@18.2.0)(react@18.2.0)
+ react: 18.2.0
+ react-dom: 18.2.0(react@18.2.0)
+ dev: false
+
/@astrojs/compiler@2.1.0:
resolution: {integrity: sha512-Mp+qrNhly+27bL/Zq8lGeUY+YrdoU0eDfIlAeGIPrzt0PnI/jGpvPUdCaugv4zbCrDkOUScFfcbeEiYumrdJnw==}
@@ -5236,6 +5276,13 @@ packages:
dependencies:
regenerator-runtime: 0.13.11
+ /@babel/runtime@7.24.5:
+ resolution: {integrity: sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.1
+ dev: false
+
/@babel/template@7.22.15:
resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
engines: {node: '>=6.9.0'}
@@ -7535,12 +7582,25 @@ packages:
resolution: {integrity: sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==}
dev: false
+ /@floating-ui/core@1.6.1:
+ resolution: {integrity: sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==}
+ dependencies:
+ '@floating-ui/utils': 0.2.2
+ dev: false
+
/@floating-ui/dom@0.5.4:
resolution: {integrity: sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==}
dependencies:
'@floating-ui/core': 0.7.3
dev: false
+ /@floating-ui/dom@1.6.5:
+ resolution: {integrity: sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==}
+ dependencies:
+ '@floating-ui/core': 1.6.1
+ '@floating-ui/utils': 0.2.2
+ dev: false
+
/@floating-ui/react-dom@0.7.2(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg==}
peerDependencies:
@@ -7555,6 +7615,10 @@ packages:
- '@types/react'
dev: false
+ /@floating-ui/utils@0.2.2:
+ resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==}
+ dev: false
+
/@formatjs/ecma402-abstract@1.18.0:
resolution: {integrity: sha512-PEVLoa3zBevWSCZzPIM/lvPCi8P5l4G+NXQMc/CjEiaCWgyHieUoo0nM7Bs0n/NbuQ6JpXEolivQ9pKSBHaDlA==}
dependencies:
@@ -24693,11 +24757,11 @@ packages:
hasBin: true
dev: false
- /match-sorter@6.3.1:
- resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==}
+ /match-sorter@6.3.4:
+ resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==}
dependencies:
- '@babel/runtime': 7.22.5
- remove-accents: 0.4.2
+ '@babel/runtime': 7.24.5
+ remove-accents: 0.5.0
dev: false
/md-to-react-email@5.0.2(react@18.2.0):
@@ -27136,6 +27200,10 @@ packages:
dependencies:
callsites: 3.1.0
+ /parse-duration@1.1.0:
+ resolution: {integrity: sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ==}
+ dev: false
+
/parse-entities@4.0.0:
resolution: {integrity: sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ==}
dependencies:
@@ -28631,7 +28699,7 @@ packages:
dependencies:
'@babel/runtime': 7.22.5
broadcast-channel: 3.7.0
- match-sorter: 6.3.1
+ match-sorter: 6.3.4
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@@ -29046,6 +29114,10 @@ packages:
/regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+ /regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+ dev: false
+
/regenerator-transform@0.15.1:
resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==}
dependencies:
@@ -29350,8 +29422,8 @@ packages:
engines: {node: '>=8'}
dev: false
- /remove-accents@0.4.2:
- resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==}
+ /remove-accents@0.5.0:
+ resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==}
dev: false
/repeat-element@1.1.4:
@@ -32967,6 +33039,14 @@ packages:
tslib: 2.6.2
dev: false
+ /use-sync-external-store@1.2.2(react@18.2.0):
+ resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ dependencies:
+ react: 18.2.0
+ dev: false
+
/use@3.1.1:
resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==}
engines: {node: '>=0.10.0'}