Skip to content

Commit

Permalink
Create sentinel tutorials section from intro docs (#2508)
Browse files Browse the repository at this point in the history
Co-authored-by: Zach Shilton <[email protected]>
  • Loading branch information
im2nguyen and zchsh authored Sep 25, 2024
1 parent 3656197 commit 13ff652
Show file tree
Hide file tree
Showing 29 changed files with 260 additions and 129 deletions.
6 changes: 3 additions & 3 deletions scripts/warm-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from 'lib/learn-client/api/collection'
import { splitProductFromFilename } from 'views/tutorial-view/utils'
import config from '../config/base.json'
import { activeProductSlugs } from 'lib/products'
import { productSlugs } from 'lib/products'
import { ProductSlug } from 'types/products'

const DEV_PORTAL_URL = config.dev_dot.canonical_base_url
Expand All @@ -27,7 +27,7 @@ const fetch = createFetch(null, { timeout: 900 * 1000 })
async function warmDeveloperDocsCache() {
const url = new URL('/api/revalidate', DEV_PORTAL_URL)

for (const productSlug of activeProductSlugs) {
for (const productSlug of productSlugs) {
const body = JSON.stringify({ product: productSlug })

try {
Expand Down Expand Up @@ -93,7 +93,7 @@ async function getTutorialUrlsToCache(product: ProductSlug): Promise<string[]> {
try {
const tutorialUrls = (
await Promise.all(
activeProductSlugs.map((product: ProductSlug) =>
productSlugs.map((product: ProductSlug) =>
getTutorialUrlsToCache(product)
)
)
Expand Down
5 changes: 4 additions & 1 deletion src/components/branded-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import patternVault from './img/vault.png'
import patternWaypoint from './img/waypoint.png'
import s from './branded-card.module.css'

const PATTERN_IMG_MAP: Record<ProductSlug, StaticImageData> = {
const PATTERN_IMG_MAP: Record<
Exclude<ProductSlug, 'well-architected-framework'>,
StaticImageData
> = {
boundary: patternBoundary,
consul: patternConsul,
nomad: patternNomad,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ const generateBasicSuggestedPages = (productSlug: ProductSlug) => {

/**
* These are pages listed after the main pages for a product, and just before a
* link to the Ttorials Library.
* link to the Tutorials Library.
*/
const EXTRA_PAGES: Record<
Exclude<ProductSlug, 'sentinel'>,
Exclude<ProductSlug, 'sentinel' | 'well-architected-framework'>,
SuggestedPageProps[]
> = {
boundary: [
Expand Down
4 changes: 3 additions & 1 deletion src/components/icon-tile/icon-tile.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
/**
* Colors
*/
.color-neutral {
.color-neutral,
.color-sentinel,
.color-hcp {
--icon-color: var(--token-color-foreground-faint);
--border-color: var(--token-color-border-primary);
--background: var(--token-color-surface-faint);
Expand Down
7 changes: 2 additions & 5 deletions src/components/icon-tile/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,14 @@

import { ProductSlug } from 'types/products'

export type ProductBrandColor =
| 'neutral'
| 'neutral-dark'
| Exclude<ProductSlug, 'sentinel' | 'hcp'>
export type ProductBrandColor = 'neutral' | 'neutral-dark' | ProductSlug

export interface IconTileProps {
/** Pass a single child, which should be a Flight icon. For 'small' and 'medium' size, pass the 16px icon size; for other sizes pass the 24px icon size. Note that non-"color" icons will be colored using the "brandColor". */
children: React.ReactNode
/** Note: the "extra-large" option is not documented in the design system. It's being used for the IconTileLogo component, as used on the /{product} view pages. */
size?: 'small' | 'medium' | 'large' | 'extra-large'
/** Optional product slug to use for brand color theming. If not provided, defaults to "neutral". Note that "sentinel" and "hcp" are not supported. */
/** Optional product slug to use for brand color theming. If not provided, defaults to "neutral". Note that "sentinel" and "hcp" currently map to "neutral". */
brandColor?: ProductBrandColor
className?: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ export function getNavItems(currentProduct: ProductData): NavItem[] {
* Tutorials
*
* Note: we exclude Sentinel, as it does not have tutorials yet.
* Once Sentinel tutorials are published, we can remove this exclusion.
* PR to publish Sentinel tutorials:
* https://github.com/hashicorp/tutorials/pull/2169
*/
if (currentProduct.slug !== 'sentinel') {
items.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const generateProductLandingSidebarMenuItems = (
menuItems.push(introNavItem)
}

// Add a "Tutorials" link for all products except sentinel
// Add a "Tutorials" link for all products
if (product.slug !== 'sentinel') {
menuItems.push({
title: 'Tutorials',
Expand Down
23 changes: 12 additions & 11 deletions src/components/sidebar/helpers/generate-resources-nav-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ const DEFAULT_COMMUNITY_FORUM_LINK = 'https://discuss.hashicorp.com/'
const DEFAULT_GITHUB_LINK = 'https://github.com/hashicorp'
const DEFAULT_SUPPORT_LINK = 'https://www.hashicorp.com/customer-success'

const COMMUNITY_LINKS_BY_PRODUCT: { [key in ProductSlug]: string } = {
const COMMUNITY_LINKS_BY_PRODUCT: {
[key in Exclude<ProductSlug, 'well-architected-framework'>]: string
} = {
boundary: 'https://discuss.hashicorp.com/c/boundary/50',
consul: 'https://discuss.hashicorp.com/c/consul/29',
hcp: 'https://discuss.hashicorp.com/c/hcp/54',
Expand All @@ -43,7 +45,10 @@ const COMMUNITY_LINKS_BY_PRODUCT: { [key in ProductSlug]: string } = {
}

const GITHUB_LINKS_BY_PRODUCT_SLUG: {
[key in Exclude<ProductSlug, 'waypoint'>]: string
[key in Exclude<
ProductSlug,
'waypoint' | 'well-architected-framework'
>]: string
} = {
boundary: 'https://github.com/hashicorp/boundary',
consul: 'https://github.com/hashicorp/consul',
Expand Down Expand Up @@ -131,15 +136,11 @@ function generateResourcesNavItems(

return [
{ heading: 'Resources' },
...(productSlug !== 'sentinel'
? [
{
// Add a "Tutorials" link for all products except Sentinel
title: 'Tutorial Library',
href: getTutorialLibraryUrl(productSlug),
},
]
: []),
{
// Add a "Tutorials" link for all products except Sentinel
title: 'Tutorial Library',
href: getTutorialLibraryUrl(productSlug),
},
...getCertificationsLink(productSlug),
{
title: 'Community Forum',
Expand Down
2 changes: 1 addition & 1 deletion src/components/try-hcp-callout/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function hasHcpCalloutContent(s: string): s is ProductSlugWithContent {
}

export const tryHcpCalloutContent: Record<
ProductSlugWithContent,
Exclude<ProductSlugWithContent, 'well-architected-framework'>,
HcpCalloutContent
> = {
terraform: {
Expand Down
1 change: 1 addition & 0 deletions src/components/tutorial-card/helpers/build-aria-label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const PRODUCT_LABEL_MAP: Record<ProductOption, string> = {
vault: 'Vault',
vagrant: 'Vagrant',
waypoint: 'Waypoint',
sentinel: 'Sentinel',
}

export function getSpeakableDuration(duration: TutorialCardProps['duration']) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const PRODUCT_ICON_MAP: Record<ProductOption, JSX.Element> = {
vault: <ProductIcon productSlug="vault" />,
vagrant: <ProductIcon productSlug="vagrant" />,
waypoint: <ProductIcon productSlug="waypoint" />,
sentinel: <ProductIcon productSlug="hcp" />,
}
/**
* Map all card badge options to icons
Expand All @@ -46,6 +47,7 @@ const PRODUCT_LABEL_MAP: Record<ProductOption, string> = {
vault: 'Vault',
vagrant: 'Vagrant',
waypoint: 'Waypoint',
sentinel: 'Sentinel',
}
/**
* Map all card badge options to badge labels
Expand Down
48 changes: 48 additions & 0 deletions src/content/sentinel/docs-landing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"pageSubtitle": "Sentinel is a policy as code tool that lets you control what users of HashiCorp products are allowed to do. It enforces policies proactively, preventing end users from deploying changes that are not allowed.",
"marketingContentBlocks": [
{
"type": "card-grid",
"title": "Fundamentals",
"cards": [
{
"title": "Policy as Code",
"description": "Understand how policy-as-code can help your organization",
"url": "/sentinel/docs/concepts/policy-as-code"
},
{
"title": "Write Sentinel policy",
"description": "Learn the fundamentals to writing Sentinel policies",
"url": "/sentinel/docs/writing"
},
{
"description": "Test Sentinel policy",
"title": "Learn how to test your Sentinel policies",
"url": "/sentinel/docs/writing/testing"
}
]
},
{
"type": "card-grid",
"title": "Integrations",
"description": "Sentinel integrates with HashiCorp products.",
"cards": [
{
"title": "Terraform",
"description": "Enforce infrastructure compliance policies with Terraform",
"url": "/sentinel/docs/terraform"
},
{
"title": "Vault",
"description": "Implement advanced access control policies within Vault",
"url": "/sentinel/docs/terraform"
},
{
"title": "Consul",
"description": "Create service mesh governance rules within Consul",
"url": "/sentinel/docs/terraform"
}
]
}
]
}
5 changes: 0 additions & 5 deletions src/data/sentinel.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@
},
"version": "0.18.6",
"subnavItems": [
{
"url": "/sentinel/intro",
"text": "Intro",
"type": "inbound"
},
{
"url": "/sentinel",
"text": "Docs",
Expand Down
23 changes: 0 additions & 23 deletions src/lib/__tests__/products.test.ts

This file was deleted.

26 changes: 19 additions & 7 deletions src/lib/learn-client/api/collection/fetch-product-collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
uuid,
ProductOption,
AllCollectionsProductOptions,
ThemeOption,
} from 'lib/learn-client/types'
import { get, toError } from '../../index'

Expand All @@ -27,18 +28,29 @@ export const PRODUCT_COLLECTION_API_ROUTE = (
* includes filtering for theme
*/
export async function fetchAllCollectionsByProduct(
product: AllCollectionsProductOptions
product: AllCollectionsProductOptions,
/**
* All `ProductOption` values except `sentinel` can be used as "theme" options.
* Theme is mainly used to add a product logo to various UI elements, and
* since Sentinel doesn't have a logo, it's not a valid theme option.
*
* Note: an alternative here might be to implement a `theme` option for
* Sentinel, and for now, set it to render a HashiCorp logo. This might
* be a more future-proof approach. This would require updates to `learn-api`:
* https://github.com/hashicorp/learn-api/blob/main/src/models/collection.ts#L17
*/
theme?: Exclude<ProductOption, 'sentinel'> | ThemeOption
): Promise<Collection[]> {
const baseUrl = PRODUCT_COLLECTION_API_ROUTE(product.slug)
let route = baseUrl

if (product.sidebarSort) {
const params = new URLSearchParams([
['topLevelCategorySort', 'true'],
['theme', product.slug],
])

route = baseUrl + `?${params.toString()}`
const params = []
params.push(['topLevelCategorySort', 'true'])
if (theme) {
params.push(['theme', theme])
}
route = baseUrl + `?${new URLSearchParams(params).toString()}`
}

const getProductCollectionsRes = await get(route)
Expand Down
15 changes: 13 additions & 2 deletions src/lib/learn-client/api/collection/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,19 @@ export async function getAllCollections(

// check if the product option is valid, i.e. not 'cloud' or 'hashicorp'
if (options?.product && themeIsProduct(options.product.slug)) {
const allCollections = await fetchAllCollectionsByProduct(options.product)

/**
* Sentinel cannot use "theme", as the `learn-api` doesn't support a
* `sentinel` theme value. We expect authors to use `theme: hashicorp`
* on Sentinel collections. We could provide "hashicorp" here instead
* of `null`, but that might result in unexpected filtering out if
* authors use a different `theme` for any Sentinel collection.
*/
const theme =
options.product.slug === 'sentinel' ? null : options.product.slug
const allCollections = await fetchAllCollectionsByProduct(
options.product,
theme
)
collections = [...allCollections]
} else {
const limit = options?.limit?.toString()
Expand Down
1 change: 1 addition & 0 deletions src/lib/learn-client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ export enum ProductOption {
vagrant = 'vagrant',
vault = 'vault',
waypoint = 'waypoint',
sentinel = 'sentinel',
}

export enum SectionOption {
Expand Down
Loading

0 comments on commit 13ff652

Please sign in to comment.