Skip to content

Commit acfe24e

Browse files
committed
Update Products directory
1 parent 54daeee commit acfe24e

28 files changed

+233
-185
lines changed

src/components/ProductCatalog.tsx

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { useState, type ChangeEvent } from "react";
2+
import { getIconData, iconToSVG } from "@iconify/utils";
3+
// @ts-ignore virtual module
4+
import iconCollection from "virtual:astro-icon";
5+
import { type CollectionEntry } from "astro:content";
6+
7+
const ProductCatalog = ({
8+
products,
9+
}: {
10+
products: CollectionEntry<"products">[];
11+
}) => {
12+
const [filters, setFilters] = useState<{
13+
search: string;
14+
groups: string[];
15+
}>({
16+
search: "",
17+
groups: [],
18+
});
19+
20+
const groups = [...new Set(products.map((product) => product.groups).flat())];
21+
22+
const productList = products.filter((product) => {
23+
if (filters.groups.length > 0) {
24+
if (
25+
filters.groups.filter((val) => product.groups.includes(val)).length ===
26+
0
27+
) {
28+
return false;
29+
}
30+
}
31+
32+
if (filters.search) {
33+
if (
34+
!product.data.name.toLowerCase().includes(filters.search.toLowerCase())
35+
) {
36+
return false;
37+
}
38+
}
39+
40+
return true;
41+
});
42+
43+
return (
44+
<div className="md:flex">
45+
<div className="md:w-1/4 w-full mr-8">
46+
<input
47+
type="text"
48+
className="w-full mb-8 rounded-md bg-white dark:bg-black border-2 border-gray-200 dark:border-gray-700 px-2 py-2"
49+
placeholder="Search products"
50+
value={filters.search}
51+
onChange={(e) => setFilters({ ...filters, search: e.target.value })}
52+
/>
53+
54+
<div className="!mb-8 md:block hidden">
55+
<span className="uppercase text-gray-600 dark:text-gray-200 text-sm font-bold">
56+
Groups
57+
</span>
58+
59+
{groups.map((group) => (
60+
<label key={group} className="block !my-2">
61+
<input
62+
type="checkbox"
63+
className="mr-2"
64+
value={group}
65+
onChange={(e: ChangeEvent<HTMLInputElement>) => {
66+
if (e.target.checked) {
67+
setFilters({
68+
...filters,
69+
groups: [...filters.groups, e.target.value],
70+
});
71+
} else {
72+
setFilters({
73+
...filters,
74+
groups: filters.groups.filter(
75+
(f) => f !== e.target.value,
76+
),
77+
});
78+
}
79+
}}
80+
/>{" "}
81+
{group}
82+
</label>
83+
))}
84+
</div>
85+
</div>
86+
87+
<div className="grid lg:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-2 lg:gap-4 lg:w-3/4 w-full items-stretch self-start !mt-0">
88+
{productList.length === 0 && (
89+
<div className="border lg:col-span-3 md:col-span-2 bg-gray-50 dark:bg-gray-800 dark:border-gray-500 rounded-md w-full flex-col flex align-middle justify-center text-center py-6">
90+
<span className="text-lg !font-bold">No products found</span>
91+
<p>
92+
Try a different search term, or broaden your search by removing
93+
filters.
94+
</p>
95+
</div>
96+
)}
97+
{productList.map((product, idx) => {
98+
const iconData = getIconData(iconCollection.local, product.id);
99+
let icon = null;
100+
if (iconData) {
101+
icon = iconToSVG(iconData);
102+
}
103+
return (
104+
<a
105+
href={product.data.product.url}
106+
className="self-stretch p-3 border-gray-200 dark:border-gray-700 border-solid border rounded-md block !text-inherit no-underline hover:bg-gray-50 dark:hover:bg-black"
107+
>
108+
<div className="flex items-center">
109+
{icon && (
110+
<div className="rounded-full p-2 bg-orange-50 mr-2 text-orange-500">
111+
<svg
112+
{...icon.attributes}
113+
width={28}
114+
height={28}
115+
dangerouslySetInnerHTML={{ __html: icon.body }}
116+
/>
117+
</div>
118+
)}
119+
{!icon && (
120+
<div className="flex items-center justify-center leading-none rounded-full p-2 bg-orange-50 mr-2 text-[color:var(--orange-accent-200)] text-xl font-bold w-11 h-11">
121+
{product.data.name.substr(0, 1)}
122+
</div>
123+
)}
124+
<span className="font-semibold text-lg text-ellipsis overflow-hidden whitespace-nowrap">
125+
{product.data.name}
126+
</span>
127+
</div>
128+
{product.data.meta && (
129+
<p className="!mt-2 line-clamp-2 text-sm leading-6">
130+
{product.data.meta.description}
131+
</p>
132+
)}
133+
</a>
134+
);
135+
})}
136+
</div>
137+
</div>
138+
);
139+
};
140+
141+
export default ProductCatalog;

src/components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export { default as ResourcesBySelector } from "./ResourcesBySelector.astro";
4848
export { default as RuleID } from "./RuleID.astro";
4949
export { default as SpotlightAuthorDetails } from "./SpotlightAuthorDetails.astro";
5050
export { default as Stream } from "./Stream.astro";
51-
export { default as ThreeCardGrid } from "./ThreeCardGrid.astro";
5251
export { default as TroubleshootingList } from "./TroubleshootingList.astro";
5352
export { default as TunnelCalculator } from "./TunnelCalculator.astro";
5453
export { default as Type } from "./Type.astro";

src/content/products/access.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@ product:
44
title: Access
55
group: Cloudflare One
66
url: /cloudflare-one/policies/access/
7-
grid_placeholder: true
7+
8+
meta:
9+
title: Cloudflare Access
10+
description: Determine who can reach your application using policies.
11+
author: "@cloudflare"

src/content/products/account-billing.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Account and Billing
55
group: Cloudflare essentials
66
url: /fundamentals/subscriptions-and-billing/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Manage account billing and subscriptions.

src/content/products/browser-isolation.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Browser Isolation
55
group: Cloudflare One
66
url: /cloudflare-one/policies/browser-isolation/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cloudflare Browser Isolation executes active webpage content in a secure isolated browser.

src/content/products/cache-reserve.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Cache Reserve
55
group: Application performance
66
url: /cache/advanced-configuration/cache-reserve/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cache Reserve is a large, persistent data store implemented on top of R2.

src/content/products/casb.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: CASB
55
group: Cloudflare One
66
url: /cloudflare-one/applications/scan-apps/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Scan SaaS applications for misconfigurations, unauthorized user activity, shadow IT, and other data security issues that can occur after a user has successfully logged in.

src/content/products/cloudflare-for-saas.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@ product:
55
group: Application performance
66
additional_groups: [Application security]
77
url: /cloudflare-for-platforms/cloudflare-for-saas/
8-
grid_placeholder: true
8+
99
preview_tryout: true
1010

11+
meta:
12+
description: Cloudflare for SaaS allows you to extend the security and performance benefits of Cloudflare’s network to your customers via their own custom or vanity domains.
13+
1114
resources:
1215
dashboard_link: https://dash.cloudflare.com/?to=/:account/:zone/ssl-tls/custom-hostnames

src/content/products/cloudflare-tunnel.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ product:
44
title: Cloudflare Tunnel
55
group: Cloudflare One
66
url: /cloudflare-one/connections/connect-networks/
7-
grid_placeholder: true
7+
8+
meta:
9+
description: Cloudflare Tunnel provides you with a secure way to connect your resources to Cloudflare without a publicly routable IP address

src/content/products/dex.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,8 @@ product:
55
group: Cloudflare One
66
additional_groups: [Analytics]
77
url: /cloudflare-one/insights/dex/
8-
grid_placeholder: true
8+
99
wrap: true
10+
11+
meta:
12+
description: Digital Experience Monitoring provides visibility into device, network, and application performance across your Zero Trust organization.

0 commit comments

Comments
 (0)