diff --git a/pages/about.tsx b/pages/about.tsx index 9c51a478..760b4348 100644 --- a/pages/about.tsx +++ b/pages/about.tsx @@ -302,10 +302,11 @@ export const getStaticProps: GetStaticProps = async ( } return propsWithGlobalSettings({ - metaTitle: 'About', + metaTitle: 'Our mission', + metaDescription: + 'We are building a flexible, scalable solution to application delivery.', teamMembers, footerVariant: FooterVariant.kitchenSink, - errors: [...(teamMembersError ? [teamMembersError] : [])], }) } diff --git a/pages/applications/[repo].tsx b/pages/applications/[repo].tsx index 4e629d13..17724e59 100644 --- a/pages/applications/[repo].tsx +++ b/pages/applications/[repo].tsx @@ -15,23 +15,26 @@ import { isEmpty } from 'lodash-es' import styled, { useTheme } from 'styled-components' import { type MergeDeep } from 'type-fest' -import { StandardPageSection } from '@pages/careers' -import { ProductValueSection } from '@pages/plural-stacks/[stack]' +// import { ProductValueSection } from '@pages/plural-stacks/ProductValueSection' import client, { directusClient } from '@src/apollo-client' import { mqs } from '@src/breakpoints' import Embed from '@src/components/Embed' import { FooterVariant } from '@src/components/FooterFull' import { Columns, EqualColumn } from '@src/components/layout/Columns' -import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' +import { + StandardPageSection, + StandardPageWidth, +} from '@src/components/layout/LayoutHelpers' import { TextLimiter } from '@src/components/layout/TextLimiter' import { BackButton } from '@src/components/Nav' import BuildStack, { getStackTabData, } from '@src/components/page-sections/BuildStackSection' import { - FeaturedArticleSection, - getFeaturedArticleApps, -} from '@src/components/page-sections/FeaturedArticleSection' + CaseStudySection, + getCaseStudyApps, +} from '@src/components/page-sections/CaseStudySection' +import { HPWMiniSectionAppStacks } from '@src/components/page-sections/HowPluralWorksMiniSection' import { StandardFAQSection } from '@src/components/page-sections/StandardFAQSection' import { TestimonialsSection } from '@src/components/QuoteCards' import RepoReadmeMd from '@src/components/RepoReadme/RepoReadmeMd' @@ -46,10 +49,11 @@ import { } from '@src/components/Typography' import { QUICKSTART_VIDEO_URL, getAppMeta, getProviderIcon } from '@src/consts' import { + type BasicRepo, type FullRepo, - type MinRepo, + type TinyRepo, getFullRepo, - getRepos, + getTinyRepos, } from '@src/data/getRepos' import { getStacks } from '@src/data/getStacks' import { @@ -62,6 +66,7 @@ import { FaqListDocument, type FaqListQuery, type FaqListQueryVariables, + type QuoteFragment, } from '@src/generated/graphqlDirectus' import { type Recipe, @@ -70,7 +75,11 @@ import { type RecipesQuery, type RecipesQueryVariables, } from '@src/generated/graphqlPlural' -import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { + type GlobalProps, + propsWithGlobalSettings, +} from '@src/utils/getGlobalProps' +import { normalizeM2mItems, normalizeQuotes } from '@src/utils/normalizeQuotes' import { CompanyLogosSection } from '../../src/components/CompanyLogos' import { GradientBG } from '../../src/components/layout/GradientBG' @@ -87,7 +96,7 @@ function isRecipe( } const AppPageTitle = styled( - ({ app, ...props }: { app: MinRepo } & ComponentProps<'div'>) => { + ({ app, ...props }: { app: BasicRepo } & ComponentProps<'div'>) => { const theme = useTheme() const iconProps = { url: @@ -141,11 +150,14 @@ export type ProviderProps = { export default function App({ repo, - appExtras, + heroVideo, + caseStudy, + quotes, recipes, buildStackTabs, caseStudyApps, faqs, + globalProps, }: InferGetStaticPropsType) { const router = useRouter() const tabs = @@ -204,7 +216,7 @@ export default function App({ @@ -215,7 +227,7 @@ export default function App({ 'flex-col', 'gap-large', 'py-xxxxlarge', - 'xl:py-[192px]' + 'xl:py-xxxxxxlarge' )} > @@ -276,31 +288,20 @@ export default function App({ )} - + {buildStackTabs && } - - + + - {/* - - - - - - - */} ) } @@ -309,15 +310,17 @@ export function CaseStudyFAQSection({ caseStudyProps, faqProps, }: { - caseStudyProps: ComponentProps + caseStudyProps?: ComponentProps faqProps: ComponentProps }) { return ( - - - + {caseStudyProps?.featuredArticle && ( + + + + )} @@ -332,7 +335,7 @@ export const getStaticPaths: GetStaticPaths = async () => { } } - const repos = (await getRepos()) || [] + const repos = (await getTinyRepos()) || [] return { paths: repos.map((repo) => ({ params: { repo: repo?.name } })), @@ -342,11 +345,20 @@ export const getStaticPaths: GetStaticPaths = async () => { export type AppPageProps = { repo?: FullRepo | null - appExtras?: AppExtrasFragment + quotes: QuoteFragment[] | null + heroVideo: Exclude< + ReturnType['heroVideo'], + undefined + > + caseStudy: Exclude< + ReturnType['case_study'], + undefined + > recipes?: Recipe[] buildStackTabs?: ReturnType - caseStudyApps: MinRepo[] + caseStudyApps: TinyRepo[] faqs: (FaqItemFragment | null)[] + globalProps: GlobalProps } const normalizeAppExtras = (extras: AppExtrasQuery) => @@ -358,7 +370,7 @@ const normalizeAppExtras = (extras: AppExtrasQuery) => export const getStaticProps: GetStaticProps = async (context) => { const repoName = context?.params?.repo - const { data: repos, error: reposError } = await until(() => getRepos()) + const { data: repos, error: reposError } = await until(() => getTinyRepos()) const { data: repo, error: repoError } = await until(() => getFullRepo(`${repoName}`) @@ -417,19 +429,21 @@ export const getStaticProps: GetStaticProps = async (context) => { ...thisRepo, } : null, - appExtras, + caseStudy: appExtras.case_study || null, + heroVideo: appExtras.heroVideo || null, + quotes: normalizeQuotes(appExtras.quotes), recipes, ...getAppMeta(thisRepo), - faqs: faqData.collapsible_lists?.[0]?.items || [], + faqs: normalizeM2mItems(faqData.collapsible_lists?.[0]) || [], buildStackTabs, - caseStudyApps: getFeaturedArticleApps( + caseStudyApps: getCaseStudyApps( repos, (appExtras.case_study?.stack_apps as string[]) || [] ), footerVariant: FooterVariant.kitchenSink, errors: [ ...(reposError ? [reposError] : []), - ...(stacksError ? [reposError] : []), + ...(stacksError ? [stacksError] : []), ...(repoError ? [repoError] : []), ...(appError ? [appError] : []), ...(faqError ? [faqError] : []), diff --git a/pages/careers/hire/[job].tsx b/pages/careers/hire/[job].tsx index 2ab7466e..bac39d05 100644 --- a/pages/careers/hire/[job].tsx +++ b/pages/careers/hire/[job].tsx @@ -111,9 +111,11 @@ export const getStaticProps: GetStaticProps = async (context) => { } return propsWithGlobalSettings({ - footerVariant: FooterVariant.kitchenSink, + metaTitle: `Careers – ${job?.job_title}`, + metaDescription: + 'We are a growing team working on interesting problems in the cloud with Kubernetes, Elixir, Go, and React. We’re always interested in hiring new talent!', showHeaderBG: true, - metaTitle: job?.job_title, + footerVariant: FooterVariant.kitchenSink, job, markdoc, errors: [...(jobError ? [jobError] : [])], diff --git a/pages/careers/index.tsx b/pages/careers/index.tsx index 1ad5b36f..e63576f8 100644 --- a/pages/careers/index.tsx +++ b/pages/careers/index.tsx @@ -5,15 +5,16 @@ import Head from 'next/head' import Script from 'next/script' import classNames from 'classnames' -import styled from 'styled-components' -import { mqs } from '@src/breakpoints' import { ResponsiveAspectRatioSC } from '@src/components/AspectRatio' import { BenefitCard } from '@src/components/BenefitCard' import { FooterVariant } from '@src/components/FooterFull' import { GradientBG } from '@src/components/layout/GradientBG' import { HeaderPad } from '@src/components/layout/HeaderPad' -import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' +import { + StandardPageSection, + StandardPageWidth, +} from '@src/components/layout/LayoutHelpers' import { JobListingsSection } from '@src/components/page-sections/JobListingsSection' import { BasicPageHero } from '@src/components/PageHeros' import { ScrollToLink } from '@src/components/ScrollToLink' @@ -24,19 +25,6 @@ import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' import { ValueCard } from '../../src/components/ValueCard' -export const StandardPageSection = styled.div(({ theme }) => ({ - paddingTop: theme.spacing.xxxxlarge, - paddingBottom: theme.spacing.xxxxlarge, - [mqs.md]: { - paddingTop: theme.spacing.xxxxxlarge, - paddingBottom: theme.spacing.xxxxxlarge, - }, - [mqs.xxl]: { - paddingTop: theme.spacing.xxxxxxlarge, - paddingBottom: theme.spacing.xxxxxxlarge, - }, -})) - function PhotosSection() { return (
@@ -299,6 +287,9 @@ export const getStaticProps = async () => { const { data: jobs, error: jobsError } = await getJobListings() return propsWithGlobalSettings({ + metaTitle: 'Careers', + metaDescription: + 'We are a growing team working on interesting problems in the cloud with Kubernetes, Elixir, Go, and React. We’re always interested in hiring new talent!', footerVariant: FooterVariant.kitchenSink, jobs: jobs || [], errors: [...(jobsError ? [jobsError] : [])], diff --git a/pages/community.tsx b/pages/community.tsx index 14f1cd07..516ce12f 100644 --- a/pages/community.tsx +++ b/pages/community.tsx @@ -166,7 +166,9 @@ export const getStaticProps: GetStaticProps = async ( const { data: events, error: eventsError } = await getEvents() return propsWithGlobalSettings({ - metaTitle: 'Community', + metaTitle: 'Join the community', + metaDescription: + 'The Plural community is built to support all Plural users through discussions, educational resources, and events.', contributors, featuredContributors, footerVariant: FooterVariant.kitchenSink, diff --git a/pages/contact-sales.tsx b/pages/contact-sales.tsx index 197d5363..95f85ea2 100644 --- a/pages/contact-sales.tsx +++ b/pages/contact-sales.tsx @@ -45,5 +45,8 @@ export default function Index() { export const getStaticProps = async () => propsWithGlobalSettings({ + metaTitle: 'Contact sales', + metaDescription: + 'Plural offers packages to teams of all sizes and flexible and transparent pricing for everyone.', footerVariant: FooterVariant.kitchenSink, }) diff --git a/pages/contact.tsx b/pages/contact.tsx index 03cd0277..1c49e11c 100644 --- a/pages/contact.tsx +++ b/pages/contact.tsx @@ -99,5 +99,8 @@ export default function Index() { export const getStaticProps = async () => propsWithGlobalSettings({ + metaTitle: 'Contact us', + metaDescription: + 'Plural offers support to teams of all sizes. We’re here to support our developers through our docs, Discord channel, or Twitter.', footerVariant: FooterVariant.kitchenSink, }) diff --git a/pages/index.tsx b/pages/index.tsx index 545fc34e..76caa58c 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,22 +1,492 @@ +import { + type ComponentProps, + type ReactElement, + type ReactNode, + cloneElement, +} from 'react' + +import { + Button, + CheckedShieldIcon, + CloudIcon, + ColorModeProvider, + LogsIcon, + PadlockLockedIcon, +} from '@pluralsh/design-system' +import { type InferGetStaticPropsType } from 'next' +import Link from 'next/link' + +import classNames from 'classnames' +import styled, { useTheme } from 'styled-components' + +import { directusClient } from '@src/apollo-client' +import { mqs } from '@src/breakpoints' +import { ArticleCardNoBorder } from '@src/components/ArticleCard' +import { CompanyLogosSection } from '@src/components/CompanyLogos' import { FooterVariant } from '@src/components/FooterFull' +import PersonCheck from '@src/components/icons/PersonCheck' +import { Columns, EqualColumn } from '@src/components/layout/Columns' +import { GradientBG } from '@src/components/layout/GradientBG' import { HeaderPad } from '@src/components/layout/HeaderPad' -import { Body1, Heading1 } from '@src/components/Typography' +import { HomePageHero } from '@src/components/PageHeros' +import { TestimonialsSection } from '@src/components/QuoteCards' +import { CenteredSectionHead } from '@src/components/SectionHeads' +import { ShadowedCard } from '@src/components/ShadowedCard' +import { Body2, ResponsiveText } from '@src/components/Typography' +import { + PageHomepageDocument, + type PageHomepageQuery, + type PageHomepageQueryVariables, +} from '@src/generated/graphqlDirectus' import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { normalizeQuotes } from '@src/utils/normalizeQuotes' + +import { + StandardPageSection, + StandardPageWidth, +} from '../src/components/layout/LayoutHelpers' + +const HeroImagesSC = styled.div(({ theme: _theme }) => { + const baseWidth = 1432 + const baseHeight = 683 -import { StandardPageWidth } from '../src/components/layout/LayoutHelpers' + return { + transformStyle: 'preserve-3d', + perspective: '1200px', + transformOrigin: 'center', + transform: 'rotateY(-00deg) rotateX(0deg) rotateZ(0deg)', -export default function Index() { + position: 'relative', + width: '100%', + aspectRatio: '2 / 1', + '& *': { + transformStyle: 'preserve-3d', + }, + '.heroImg': { + position: 'absolute', + + img: { + display: 'block', + width: '100%', + boxShadow: `0px 10px 20px 0px rgba(14, 16, 21, 0.30), 0px 3px 6px 0px rgba(14, 16, 21, 0.20)`, + }, + }, + '.heroImg1': { + width: `${(512 * 100) / baseWidth}%`, + left: `${(930 * 100) / baseWidth}%`, + top: `${(35 * 100) / baseHeight}%`, + img: { + transform: [ + 'rotateY(-10deg)', + // 'rotateX(0deg)', + // 'rotateZ(0deg)', + 'translateZ(-100px)', + 'translateX(7%)', + 'translateY(-10px)', + 'scale(1.1)', + ].join(' '), + }, + }, + '.heroImg2': { + width: `${(880.84 * 100) / baseWidth}%`, + left: `${(0 * 100) / baseWidth}%`, + top: `${(0 * 100) / baseHeight}%`, + img: { + transform: [ + 'rotateY(10deg)', + // 'rotateX(0deg)', + // 'rotateZ(0deg)', + // 'translateZ(100px)', + // 'scale(0.90)', + ].join(' '), + }, + }, + '.heroImg3': { + width: `${(840 * 100) / baseWidth}%`, + left: `${(563 * 100) / baseWidth}%`, + top: `${(226 * 100) / baseHeight}%`, + img: { + transform: [ + 'rotateY(-5deg)', + // // 'rotateX(0deg)', + // // 'rotateZ(0deg)', + 'translateZ(100px)', + 'translateX(-2%)', + 'translateY(-2%)', + 'scale(0.90)', + ].join(' '), + }, + }, + } +}) + +function HeroImages({ ...props }: ComponentProps) { return ( - -
- Home page - This is some body text + +
+ +
+
+
- +
+ +
+
+ ) +} + +const FeatureSC = styled(Columns)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + // flexDirection: 'column', + rowGap: theme.spacing.xxxlarge, + [mqs.columns]: { + '&:nth-child(2n+1)': { + flexDirection: 'row-reverse', + }, + }, +})) + +export function Feature({ + heading, + children, + imageUrl, +}: { + heading: ReactNode + children: ReactNode + imageUrl?: string +}) { + return ( + + + + {heading} + + {children} + + +
+ {imageUrl && } +
+
+
+ ) +} + +const BuildSecurelyCardSC = styled(ShadowedCard)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + gap: '', + textAlign: 'center', + ...theme.partials.text.body2Bold, + color: theme.colors['text-light'], + '& > *': { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + minHeight: 120, + paddingLeft: theme.spacing.medium, + paddingRight: theme.spacing.medium, + maxWidth: 240, + marginLeft: 'auto', + marginRight: 'auto', + '&:first-child': { + paddingTop: theme.spacing.xlarge, + }, + '&:last-child': { + paddingBottom: theme.spacing.xlarge, + }, + }, +})) + +function BuildSecurelyCard({ + icon, + heading, + ...props +}: { + icon: ReactElement + heading: ReactNode +} & ComponentProps) { + const theme = useTheme() + const iconClone = cloneElement(icon, { + size: 48, + color: theme.colors['icon-primary'], + }) + + return ( + +
{iconClone}
+
{heading}
+
+ ) +} + +const BuildSecurelyGridSC = styled.div(({ theme }) => ({ + display: 'grid', + gap: theme.spacing.medium, + gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', + textWrap: 'balance', + [mqs.xs]: { + gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', + '& > *': { + '&:nth-child(n + 5)': { + gridColumn: 'span 2', + }, + }, + }, + [mqs.md]: { + gridTemplateColumns: 'repeat(6, minmax(0, 1fr))', + '& > *': { + '&, &:nth-child(n)': { + gridColumn: 'span 2', + }, + '&:nth-child(n+4)': { + gridColumn: 'span 3', + }, + }, + }, + [mqs.lg]: { + gridTemplateColumns: 'repeat(5, minmax(0, 1fr))', + '& > *': { + '&, &:nth-child(n)': { + gridColumn: 'span 1', + }, + }, + }, +})) + +function BuildSecurely() { + return ( +
+ + We’re not a SaaS. You control everything. No need to share your + cloud account, keys or data. +
+ } + /> + + } + heading="Deployed on your cloud" + /> + } + heading="No need to share your cloud account keys" + /> + } + heading="Security scanned and hardened images" + /> + } + heading="Customize deployments to suit your setup" + /> + } + heading="User authentication enabled out of the box" + /> + +
+ ) +} + +function FeaturesSection() { + return ( + + + +
+ + +

+ Install Plural using our CLI or our cloud shell in minutes and + then choose from 90+ production-grade, open-source applications + to deploy in your environment. +

+
+ +

+ Plural is built for secure deployments, featuring + security-scanned and hardened images, seamless integration with + your SAML gateway, turnkey user authentication, centralized user + management, and granular RBAC. +

+
+ +

+ We know that everyone’s requirements are a little different. + That’s why everything is customizable in Plural. Want to change + the network setup? How about using a different storage layer? No + sweat. Better yet, all configuration is stored in Git, providing + a natural development workflow to rework and customize + applications. +

+
+ +

+ Never have the headache of manually upgrading applications + again. Plural’s built in dependency tree ensures all + dependencies are upgraded in the correct order, with no + downtime. Need to scale? That’s 1-click with our operational + runbooks. +

+
+ +

+ Harness Complete Performance Insights: Plural's Native + Integrations with Prometheus, Datadog, and More. Streamline + Testing and Rollouts with Effortless Multi-Cluster Deploys from + Dev to Prod. +

+
+
+
+
+
) } -export const getStaticProps = async () => - propsWithGlobalSettings({ +export default function Index({ + quotes, + globalProps, + articleCards, +}: InferGetStaticPropsType) { + return ( + <> + + + Build compliant, production-ready, infrastructure faster than + ever. +
+ } + ctas={ +
+ + +
+ } + /> +
+ + + +
+ + + + + + + + + + + + + + +
+ + +
+ {articleCards?.map((c, i) => { + const first = i === 0 + const last = i === articleCards.length - 1 + const medium = first || last + + return ( + + ) + })} +
+
{' '} +
+
+
+ + ) +} + +export const getStaticProps = async () => { + const { data, error } = await directusClient.query< + PageHomepageQuery, + PageHomepageQueryVariables + >({ + query: PageHomepageDocument, + }) + + const page = data.page_homepage + + return propsWithGlobalSettings({ + metaTitle: 'Secure, self-hosted applications in your cloud', + metaDescription: + 'Open-source application deployment, faster than ever without sacrificing compliance.', + articleCards: data.page_homepage?.article_cards || null, + quotes: normalizeQuotes(page?.quotes), + footerVariant: FooterVariant.kitchenSink, + errors: [...(error ? [`${error}`] : [])], }) +} diff --git a/pages/marketplace.tsx b/pages/marketplace.tsx index 2ffd5121..09440376 100644 --- a/pages/marketplace.tsx +++ b/pages/marketplace.tsx @@ -41,7 +41,7 @@ import { import StackHero from '@src/components/page-sections/MarketplaceStackHero' import { RepoCard, RepoCardList, StackCard } from '@src/components/RepoCardList' import { Body1, Heading1, Heading2, Subtitle } from '@src/components/Typography' -import { type MinRepo, getRepos, reposCache } from '@src/data/getRepos' +import { type BasicRepo, getRepos, reposCache } from '@src/data/getRepos' import { type Categories, type Tags, @@ -54,14 +54,15 @@ import { type FaqListQuery, type FaqListQueryVariables, } from '@src/generated/graphqlDirectus' -import { type MinRepoFragment } from '@src/generated/graphqlPlural' +import { type BasicRepoFragment } from '@src/generated/graphqlPlural' import { type GlobalProps, propsWithGlobalSettings, } from '@src/utils/getGlobalProps' +import { normalizeM2mItems } from '@src/utils/normalizeQuotes' type PageProps = { - repositories: MinRepo[] + repositories: BasicRepo[] stacks: MinStack[] categories: Categories tags: Tags @@ -83,7 +84,7 @@ export function getStackRepos(stack: MinStack) { return stack.collections?.[0]?.bundles ?.map((bundle) => bundle?.recipe?.repository) .filter( - (repo: MinRepoFragment | null | undefined): repo is MinRepoFragment => + (repo: BasicRepoFragment | null | undefined): repo is BasicRepoFragment => !!repo ) } @@ -602,12 +603,21 @@ export const getStaticProps: GetStaticProps = async () => { const { categories, tags } = await getSearchMetadata() + console.log('errors', [ + ...(reposError ? [reposError] : []), + ...(stacksError ? [reposError] : []), + ...(faqError ? [faqError] : []), + ]) + return propsWithGlobalSettings({ + metaTitle: 'Explore the open-source marketplace', + metaDescription: + 'Discover over 90 open-source applications ready to deploy in your cloud in minutes.', repositories: repos || reposCache.filtered, stacks: stacks || stacksCache.filtered, tags: tags || [], categories: categories || [], - faqs: faqData.collapsible_lists?.[0]?.items || [], + faqs: normalizeM2mItems(faqData.collapsible_lists?.[0]) || [], errors: [ ...(reposError ? [reposError] : []), ...(stacksError ? [reposError] : []), diff --git a/pages/plural-deployments-early-access.tsx b/pages/plural-deployments-early-access.tsx new file mode 100644 index 00000000..efa5c81c --- /dev/null +++ b/pages/plural-deployments-early-access.tsx @@ -0,0 +1,252 @@ +import { ColorModeProvider } from '@pluralsh/design-system' +import { type InferGetStaticPropsType } from 'next' + +import { ArticleCard } from '@src/components/ArticleCard' +import Embed from '@src/components/Embed' +import { FooterVariant } from '@src/components/FooterFull' +import { HubspotForm } from '@src/components/HubspotForm' +import { Columns, EqualColumn } from '@src/components/layout/Columns' +import { GradientBG } from '@src/components/layout/GradientBG' +import { + StandardPageSection, + StandardPageWidth, +} from '@src/components/layout/LayoutHelpers' +import { + CenteredSectionHead, + SubsectionHead, +} from '@src/components/SectionHeads' +import { BasicUl, Body1, Body2 } from '@src/components/Typography' +import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' + +import { HeaderPad } from '../src/components/layout/HeaderPad' + +import { Feature } from '.' + +function SignUpSection({ containerId }: { containerId: string }) { + return ( + + + + + + + + An end-to-end solution for managing Kubernetes clusters and + application deployment. Join our early access community today. + + + + + + + + + + ) +} + +export default function Legal( + _props: InferGetStaticPropsType +) { + return ( + <> + + {/* + An end-to-end solution for managing Kubernetes clusters and + application deployment. Join our early access community today. + + } + /> */} + + + + + + + +
+
+ +
+ +
+ + Deploy and manage your software with Plural Continuous + Deployment. An end-to-end solution for managing Kubernetes + clusters and application deployment on your cloud. + + } + /> +
+ +
+

Resource authoring with cdk8s

+
    +
  • Easily define K8s applications
  • +
  • Can be applied to any cluster
  • +
  • Unit testing
  • +
  • Package management
  • +
+

Point and click cluster creation

+
    +
  • Seamlessly spin up clusters in your cloud
  • +
  • Managed provisioner for consistent setup
  • +
  • Self-hosted for maximum security
  • +
  • Multi-cloud compatible
  • +
+

Continuous deployment

+
    +
  • Self-serviceably deploy your services
  • +
  • Secure secret iniection based on in-cluster vault
  • +
  • Easy UI for creating deployment pipelines
  • +
+
+
+
+ + + +
  • + Rapidly create new Kubernetes environments across any cloud + without ever having to write code +
  • +
  • + Managed, zero downtime upgrades with cluster api + reconciliation loops, don’t worry about sloppy and fragile + terraform rollouts +
  • +
  • + Dynamically add and remove nodes to your cluster node topology + as you like +
  • +
    +
    + + +
  • + Use scaffolds to create functional gitops deployments in a + flash +
  • +
  • + First class support for{' '} + + https://cdk8s.io + + to provide a robust Kubernetes authoring experience with unit + testability and package management +
  • +
  • Integrated secret management
  • +
    +
    + +
    +
    + + + Ferry code changes from development to production with + powerful integration tests and approval workflows. + +
    +
    + +
    +
    + +
    +
    + + + A single, scalable user interface where your org can deploy + and monitor everything fast. + +
    +
    + +
    +
    + {/*
    */} + + {/*
    */} +
    +
    +
    + + + + ) +} + +export const getStaticProps = async () => + propsWithGlobalSettings({ + metaTitle: 'Continuous deployment early access', + metaDescription: + 'An end-to-end solution for managing Kubernetes clusters and application deployment. Join our early access community today.', + footerVariant: FooterVariant.kitchenSink, + }) diff --git a/pages/plural-stacks/[stack].tsx b/pages/plural-stacks/[stack].tsx index 098ec805..48638ce1 100644 --- a/pages/plural-stacks/[stack].tsx +++ b/pages/plural-stacks/[stack].tsx @@ -19,7 +19,6 @@ import { type MergeDeep } from 'type-fest' import { CaseStudyFAQSection } from '@pages/applications/[repo]' import { directusClient } from '@src/apollo-client' import { AppCard } from '@src/components/AppOrStackCard' -import { Checklist, ChecklistItem } from '@src/components/Checklist' import Embed from '@src/components/Embed' import { FooterVariant } from '@src/components/FooterFull' import { GradientBG } from '@src/components/layout/GradientBG' @@ -28,28 +27,27 @@ import { BackButton } from '@src/components/Nav' import BuildStackSection, { getStackTabData, } from '@src/components/page-sections/BuildStackSection' -import { getFeaturedArticleApps } from '@src/components/page-sections/FeaturedArticleSection' +import { getCaseStudyApps } from '@src/components/page-sections/CaseStudySection' +import { HPWMiniSectionAppStacks } from '@src/components/page-sections/HowPluralWorksMiniSection' import { ProviderIcon } from '@src/components/ProviderIcon' import { TestimonialsSection } from '@src/components/QuoteCards' import { RepoSocials } from '@src/components/RepoSocials' import { AppTitle, Body1, - Body2, - Cta, Overline, ResponsiveText, - Title2, } from '@src/components/Typography' import { getProviderIcon, getStackMeta } from '@src/consts' import { appUrl } from '@src/consts/routes' -import { type MinRepo, getRepos, normalizeRepo } from '@src/data/getRepos' +import { type TinyRepo, getTinyRepos, normalizeRepo } from '@src/data/getRepos' import { type FullStack, getFullStack, getStacks } from '@src/data/getStacks' import { type FaqItemFragment, FaqListDocument, type FaqListQuery, type FaqListQueryVariables, + type QuoteFragment, type StackDefaultsFragment, StackExtrasDocument, type StackExtrasFragment, @@ -57,10 +55,14 @@ import { type StackExtrasQueryVariables, } from '@src/generated/graphqlDirectus' import { - type MinRepoFragment, + type BasicRepoFragment, type StackCollectionFragment, } from '@src/generated/graphqlPlural' -import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { + type GlobalProps, + propsWithGlobalSettings, +} from '@src/utils/getGlobalProps' +import { normalizeM2mItems, normalizeQuotes } from '@src/utils/normalizeQuotes' import { startsWithVowel } from '@src/utils/text' import { CompanyLogosSection } from '../../src/components/CompanyLogos' @@ -68,6 +70,8 @@ import { Columns, EqualColumn } from '../../src/components/layout/Columns' import { HeaderPad } from '../../src/components/layout/HeaderPad' import { TextLimiter } from '../../src/components/layout/TextLimiter' +// import { ProductValueSection } from './ProductValueSection' + const DEFAULT_HERO_VIDEO = 'https://www.youtube.com/watch?v=LOUshNTgPV0' function isCollection( @@ -88,10 +92,13 @@ const StackAppsTabPanel = styled(TabPanel)((_) => ({})) export default function Stack({ stack, - stackExtras, + quotes, + heroVideo, + caseStudy, faqs, buildStackTabs, caseStudyApps, + globalProps, }: InferGetStaticPropsType) { const router = useRouter() const providers = @@ -114,7 +121,7 @@ export default function Stack({ const apps = stack?.collections?.[0]?.bundles ?.map((bundle) => bundle?.recipe.repository) - .filter((repo): repo is MinRepoFragment => !!repo) + .filter((repo): repo is BasicRepoFragment => !!repo) .map((repo) => normalizeRepo(repo)) const appsTabStateRef = useRef() @@ -179,7 +186,7 @@ export default function Stack({ @@ -190,7 +197,7 @@ export default function Stack({ 'flex-col', // 'gap-large', 'py-xxxxlarge', - 'xl:py-[192px]' + 'xl:py-xxxxxxlarge' )} > @@ -269,17 +276,22 @@ export default function Stack({ - + {/* + /> */} {buildStackTabs && } - - + + @@ -304,11 +316,20 @@ export const getStaticPaths: GetStaticPaths = async () => { } export type StackPageProps = { - stack?: FullStack | null - stackExtras?: StackExtrasFragment + stack: FullStack | null + quotes: QuoteFragment[] | null + heroVideo: Exclude< + ReturnType['heroVideo'], + undefined + > + caseStudy: Exclude< + ReturnType['case_study'], + undefined + > buildStackTabs?: ReturnType - caseStudyApps: MinRepo[] + caseStudyApps: TinyRepo[] faqs: (FaqItemFragment | null)[] + globalProps: GlobalProps } const normalizeStackExtras = (extras: StackExtrasQuery) => @@ -325,11 +346,7 @@ export const getStaticProps: GetStaticProps = async ( if (!stackName || typeof stackName !== 'string') { return { notFound: true } } - const { data: repos, error: reposError } = await until(() => getRepos()) - - // const { data: repo, error: repoError } = await until(() => - // getFullRepo(`${repoName}`) - // ) + const { data: repos, error: reposError } = await until(() => getTinyRepos()) const { data: stacks, error: stacksError } = await until(() => getStacks()) const { data: stack, error: stackError } = await until(() => @@ -368,11 +385,13 @@ export const getStaticProps: GetStaticProps = async ( ...thisStack, } : null, - stackExtras, + heroVideo: stackExtras.heroVideo || null, + caseStudy: stackExtras.case_study || null, + quotes: normalizeQuotes(stackExtras.quotes), ...getStackMeta(thisStack), - faqs: faqData.collapsible_lists?.[0]?.items || [], + faqs: normalizeM2mItems(faqData.collapsible_lists?.[0]) || [], buildStackTabs, - caseStudyApps: getFeaturedArticleApps( + caseStudyApps: getCaseStudyApps( repos, (stackExtras.case_study?.stack_apps as string[]) || [] ), @@ -386,54 +405,3 @@ export const getStaticProps: GetStaticProps = async ( ], }) } - -export function ProductValueSection({ - name, - isStack, -}: { - name: string - isStack: boolean -}) { - const fullName = isStack ? `the ${name} Stack` : name - - return ( - -
    - - - - Open-source and free to use - - Plural automates the deployment and operation of {fullName} in - your cloud. Get up and running with your {fullName} instance in - minutes and let Plural deploy {fullName} and all its - dependencies into your cloud with all of the day-2 operations - handled out of the box. - - - Explore {fullName} on Plural in live demo environment - - - - - - Automated upgrades - - Transparent pricing and cost management - - Prebuilt dashboards, extendable - Prebuilt runbooks, extendable - Log management - - - -
    - Screenshots of the Plural Console app, showing dashboards for Applications, Nodes and cost -
    -
    -
    - ) -} diff --git a/pages/pricing.tsx b/pages/pricing.tsx index 9d8b8a04..b4f98e05 100644 --- a/pages/pricing.tsx +++ b/pages/pricing.tsx @@ -25,6 +25,7 @@ import { type FaqListQueryVariables, } from '@src/generated/graphqlDirectus' import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { normalizeM2mItems } from '@src/utils/normalizeQuotes' import { PlansFeaturesTable as PlanFeaturesTable } from '../src/components/page-sections/PlansFeaturesTables' @@ -245,8 +246,9 @@ export const getStaticProps: GetStaticProps = async ( return propsWithGlobalSettings({ metaTitle: 'Pricing', + metaDescription: 'Flexible plans for every stage of your business', ...pricing, - faqs: faqData.collapsible_lists?.[0]?.items || [], + faqs: normalizeM2mItems(faqData.collapsible_lists?.[0]) || [], footerVariant: FooterVariant.kitchenSink, errors: [ ...(pricingError ? [pricingError] : []), diff --git a/pages/product.tsx b/pages/product.tsx index 22f29c89..2aa7c52e 100644 --- a/pages/product.tsx +++ b/pages/product.tsx @@ -1,4 +1,5 @@ import { Button, ColorModeProvider } from '@pluralsh/design-system' +import { type InferGetStaticPropsType } from 'next' import Head from 'next/head' import Link from 'next/link' import Script from 'next/script' @@ -7,22 +8,27 @@ import classNames from 'classnames' import styled from 'styled-components' import { mqs } from '@src/breakpoints' +import { QuickstartDemoCard } from '@src/components/ArticleCard' +import { FeaturedQuote } from '@src/components/FeaturedQuote' import { FooterVariant } from '@src/components/FooterFull' import { Columns, EqualColumn } from '@src/components/layout/Columns' import { GradientBG } from '@src/components/layout/GradientBG' import { HeaderPad } from '@src/components/layout/HeaderPad' -import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' +import { + StandardPageSection, + StandardPageWidth, +} from '@src/components/layout/LayoutHelpers' import { TextLimiter } from '@src/components/layout/TextLimiter' -import { MassiveQuote } from '@src/components/MassiveQuote' -import { RepoFAQSection } from '@src/components/page-sections/RepoFAQSection' +import { HowPluralWorksSection } from '@src/components/page-sections/HowPluralWorksSection' +import { StandardFAQSection } from '@src/components/page-sections/StandardFAQSection' import { WhatIsPluralSection } from '@src/components/page-sections/WhatIsPluralSection' -import { QuickstartDemoCard } from '@src/components/QuickstartDemoCard' import { CenteredSectionHead } from '@src/components/SectionHeads' -import { Body2, InlineLink } from '@src/components/Typography' +import { getProductPageData } from '@src/data/getProductPageData' import { useAnimationPauser } from '@src/hooks/useAnimationPauser' import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { normalizeM2mItems } from '@src/utils/normalizeQuotes' -import { HowPluralWorksSection } from '../src/components/page-sections/HowPluralWorksSection' +import { TryPluralForFreeSection } from '../src/components/page-sections/TryPluralForFreeSection' import { HeroMainText } from '../src/components/PageHeros' export const ArchitectureContentSC = styled(TextLimiter)(({ theme }) => ({ @@ -39,19 +45,6 @@ export const ArchitectureContentSC = styled(TextLimiter)(({ theme }) => ({ }, })) -export const StandardPageSection = styled.div(({ theme }) => ({ - paddingTop: theme.spacing.xxxxlarge, - paddingBottom: theme.spacing.xxxxlarge, - [mqs.md]: { - paddingTop: theme.spacing.xxxxxlarge, - paddingBottom: theme.spacing.xxxxxlarge, - }, - [mqs.xxl]: { - paddingTop: theme.spacing.xxxxxxlarge, - paddingBottom: theme.spacing.xxxxxxlarge, - }, -})) - const AnimationWrapSC = styled.div((_) => ({ flex: 1, '& > div': { @@ -93,7 +86,10 @@ const HeroAnimationWrapSC = styled(AnimationWrapSC)((_) => ({ }, })) -export default function Index() { +export default function Index({ + featuredQuote, + faqs, +}: InferGetStaticPropsType) { useAnimationPauser() return ( @@ -185,15 +181,7 @@ export default function Index() { - - This is awesome. You saved me hours of further DevOps work for our - v1 release. Just to say, I really love Plural. - - } - attributions={['Ismael Goulani', 'Co-foundeer of MODEO']} - /> + {featuredQuote && } - -
    - -
    - - - -
    - - - Sign up with email - - -
    -
    - + + + {faqs && }
    - propsWithGlobalSettings({ +export const getStaticProps = async () => { + const { data: pageData, error: pageDataError } = await getProductPageData() + + return propsWithGlobalSettings({ + metaTitle: 'How Plural works', + metaDescription: + 'Plural is an open-source, unified, application deployment platform that stands up a Kubernetes cluster and selected applications in the cloud provider of your choice.', + featuredQuote: pageData?.featured_quote, + faqs: normalizeM2mItems(pageData?.faq), footerVariant: FooterVariant.kitchenSink, - pageTitle: 'How Plural works', + errors: [...(pageDataError ? [pageDataError] : [])], }) +} diff --git a/pages/solutions/[solution].tsx b/pages/solutions/[solution].tsx index c1b40050..ca60737a 100644 --- a/pages/solutions/[solution].tsx +++ b/pages/solutions/[solution].tsx @@ -1,4 +1,4 @@ -import { Button } from '@pluralsh/design-system' +import { Button, ColorModeProvider } from '@pluralsh/design-system' import { type GetStaticPaths, type GetStaticProps, @@ -6,15 +6,43 @@ import { } from 'next' import Link from 'next/link' +import { until } from '@open-draft/until' +import classNames from 'classnames' + +import { CaseStudyFAQSection } from '@pages/applications/[repo]' import { directusClient } from '@src/apollo-client' +import BasicMarkdown from '@src/components/BasicMarkdown' +import { Checklist2, Checklist2Item } from '@src/components/Checklist' +import { CompanyLogosSection } from '@src/components/CompanyLogos' +import { FeaturedQuote } from '@src/components/FeaturedQuote' import { FooterVariant } from '@src/components/FooterFull' +import { ColumnsMd, EqualColumn } from '@src/components/layout/Columns' +import { + StandardPageSection, + StandardPageWidth, +} from '@src/components/layout/LayoutHelpers' +import BuildStackSection, { + getStackTabData, +} from '@src/components/page-sections/BuildStackSection' +import { getCaseStudyApps } from '@src/components/page-sections/CaseStudySection' +import { HPWMiniSectionSolutions } from '@src/components/page-sections/HowPluralWorksMiniSection' import { BasicPageHero } from '@src/components/PageHeros' +import { + CenteredSectionHead, + SubsectionHead, +} from '@src/components/SectionHeads' +import { ShadowedCard } from '@src/components/ShadowedCard' +import { Body2, Cta } from '@src/components/Typography' import { getImageUrl } from '@src/consts/routes' +import { type TinyRepo, getTinyRepos } from '@src/data/getRepos' +import { getStacks } from '@src/data/getStacks' import { + type CaseStudyFragment, type FaqItemFragment, FaqListDocument, type FaqListQuery, type FaqListQueryVariables, + type QuoteFragment, type SolutionFragment, SolutionsDocument, type SolutionsQuery, @@ -23,7 +51,11 @@ import { type SolutionsSlugsQuery, type SolutionsSlugsQueryVariables, } from '@src/generated/graphqlDirectus' -import { propsWithGlobalSettings } from '@src/utils/getGlobalProps' +import { + type GlobalProps, + propsWithGlobalSettings, +} from '@src/utils/getGlobalProps' +import { normalizeM2mItems } from '@src/utils/normalizeQuotes' import { GradientBG } from '../../src/components/layout/GradientBG' import { HeaderPad } from '../../src/components/layout/HeaderPad' @@ -36,36 +68,102 @@ export type ProviderProps = { export default function Solution({ solution, + caseStudy, + caseStudyApps, + faqs, + featuredQuote, + buildStackTabs, + globalProps, }: InferGetStaticPropsType) { // const router = useRouter() + const imageUrl = getImageUrl(solution?.hero_image) return ( - - - + <> + + + +
    + ) : undefined + } + ctas={ +
    +
    - ) : undefined - } - ctas={ -
    - -
    - } + } + /> + + + + + + + + + + + {solution.bullet_points.map( + (bullet) => + bullet?.content && ( + {bullet.content} + ) + )} + + + Explore our live demo environment + + + + + + +
    +
    +
    + + - + + {buildStackTabs && } + ) } @@ -96,6 +194,11 @@ export const getStaticPaths: GetStaticPaths = async () => { export type AppPageProps = { solution: SolutionFragment faqs: (FaqItemFragment | null)[] + globalProps: GlobalProps + caseStudy: CaseStudyFragment | null + featuredQuote: QuoteFragment | null + caseStudyApps: TinyRepo[] + buildStackTabs?: ReturnType } export const getStaticProps: GetStaticProps = async (context) => { @@ -119,6 +222,9 @@ export const getStaticProps: GetStaticProps = async (context) => { return { notFound: true } } + const { data: repos, error: reposError } = await until(() => getTinyRepos()) + const { data: stacks, error: stacksError } = await until(() => getStacks()) + const { data: faqData, error: faqError } = await directusClient.query< FaqListQuery, FaqListQueryVariables @@ -126,16 +232,26 @@ export const getStaticProps: GetStaticProps = async (context) => { query: FaqListDocument, variables: { slug: 'generic' }, }) + const buildStackTabs = getStackTabData({ repos, stacks }) return propsWithGlobalSettings({ solution, - metaTitle: solution.title, - metaDescription: solution.description, - faqs: faqData.collapsible_lists?.[0]?.items || [], + metaTitle: `Solution${solution.title ? ` – ${solution.title}` : ''}`, + metaDescription: solution.description || null, + faqs: normalizeM2mItems(faqData.collapsible_lists?.[0]) || [], + caseStudy: solution.case_study || null, + caseStudyApps: getCaseStudyApps( + repos, + (solution.case_study?.stack_apps as string[]) || [] + ), + featuredQuote: solution.featured_quote || null, + buildStackTabs, footerVariant: FooterVariant.kitchenSink, errors: [ ...(solutionError ? [solutionError] : []), ...(faqError ? [faqError] : []), + ...(reposError ? [reposError] : []), + ...(stacksError ? [stacksError] : []), ], }) } diff --git a/public/assets/Flow Chart.jpg b/public/assets/Flow Chart.jpg deleted file mode 100644 index c7d4df71..00000000 Binary files a/public/assets/Flow Chart.jpg and /dev/null differ diff --git a/public/assets/Screen Shot 2021-07-23 at 12.02.37 AM.png b/public/assets/Screen Shot 2021-07-23 at 12.02.37 AM.png deleted file mode 100644 index 2f4050a9..00000000 Binary files a/public/assets/Screen Shot 2021-07-23 at 12.02.37 AM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-18 at 1.00.00 PM.png b/public/assets/Screen Shot 2021-08-18 at 1.00.00 PM.png deleted file mode 100644 index 5478b797..00000000 Binary files a/public/assets/Screen Shot 2021-08-18 at 1.00.00 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-18 at 12.35.31 PM.png b/public/assets/Screen Shot 2021-08-18 at 12.35.31 PM.png deleted file mode 100644 index 5bcf053c..00000000 Binary files a/public/assets/Screen Shot 2021-08-18 at 12.35.31 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-18 at 12.39.37 PM.png b/public/assets/Screen Shot 2021-08-18 at 12.39.37 PM.png deleted file mode 100644 index b99b545d..00000000 Binary files a/public/assets/Screen Shot 2021-08-18 at 12.39.37 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-19 at 3.54.54 PM.png b/public/assets/Screen Shot 2021-08-19 at 3.54.54 PM.png deleted file mode 100644 index 4d64cdfe..00000000 Binary files a/public/assets/Screen Shot 2021-08-19 at 3.54.54 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-30 at 12.37.04 PM.png b/public/assets/Screen Shot 2021-08-30 at 12.37.04 PM.png deleted file mode 100644 index 45c74aef..00000000 Binary files a/public/assets/Screen Shot 2021-08-30 at 12.37.04 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-30 at 12.37.24 PM.png b/public/assets/Screen Shot 2021-08-30 at 12.37.24 PM.png deleted file mode 100644 index 53bab901..00000000 Binary files a/public/assets/Screen Shot 2021-08-30 at 12.37.24 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-30 at 3.36.11 PM.png b/public/assets/Screen Shot 2021-08-30 at 3.36.11 PM.png deleted file mode 100644 index 184aa1ee..00000000 Binary files a/public/assets/Screen Shot 2021-08-30 at 3.36.11 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-08-30 at 3.36.34 PM.png b/public/assets/Screen Shot 2021-08-30 at 3.36.34 PM.png deleted file mode 100644 index 6083e22f..00000000 Binary files a/public/assets/Screen Shot 2021-08-30 at 3.36.34 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2021-11-11 at 7.55.50 PM.png b/public/assets/Screen Shot 2021-11-11 at 7.55.50 PM.png deleted file mode 100644 index da8d70b9..00000000 Binary files a/public/assets/Screen Shot 2021-11-11 at 7.55.50 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-01-07 at 11.47.57 PM.png b/public/assets/Screen Shot 2022-01-07 at 11.47.57 PM.png deleted file mode 100644 index 6e0cdea0..00000000 Binary files a/public/assets/Screen Shot 2022-01-07 at 11.47.57 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-01-07 at 11.48.06 PM.png b/public/assets/Screen Shot 2022-01-07 at 11.48.06 PM.png deleted file mode 100644 index 7aff544a..00000000 Binary files a/public/assets/Screen Shot 2022-01-07 at 11.48.06 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-01-07 at 11.50.03 PM.png b/public/assets/Screen Shot 2022-01-07 at 11.50.03 PM.png deleted file mode 100644 index 70960065..00000000 Binary files a/public/assets/Screen Shot 2022-01-07 at 11.50.03 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-02-18 at 1.01.22 PM.png b/public/assets/Screen Shot 2022-02-18 at 1.01.22 PM.png deleted file mode 100644 index 9dca2eb2..00000000 Binary files a/public/assets/Screen Shot 2022-02-18 at 1.01.22 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-02-22 at 2.53.09 PM.png b/public/assets/Screen Shot 2022-02-22 at 2.53.09 PM.png deleted file mode 100644 index 2ef2683a..00000000 Binary files a/public/assets/Screen Shot 2022-02-22 at 2.53.09 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-02-22 at 2.58.10 PM.png b/public/assets/Screen Shot 2022-02-22 at 2.58.10 PM.png deleted file mode 100644 index 667a73ff..00000000 Binary files a/public/assets/Screen Shot 2022-02-22 at 2.58.10 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-07-27 at 5.05.59 PM.png b/public/assets/Screen Shot 2022-07-27 at 5.05.59 PM.png deleted file mode 100644 index 584e1284..00000000 Binary files a/public/assets/Screen Shot 2022-07-27 at 5.05.59 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-07-27 at 5.06.40 PM.png b/public/assets/Screen Shot 2022-07-27 at 5.06.40 PM.png deleted file mode 100644 index 2ddd9749..00000000 Binary files a/public/assets/Screen Shot 2022-07-27 at 5.06.40 PM.png and /dev/null differ diff --git a/public/assets/Screen Shot 2022-07-27 at 5.11.01 PM (1).png b/public/assets/Screen Shot 2022-07-27 at 5.11.01 PM (1).png deleted file mode 100644 index 92fbee3f..00000000 Binary files a/public/assets/Screen Shot 2022-07-27 at 5.11.01 PM (1).png and /dev/null differ diff --git a/public/assets/advanced-topics/audit-logs.png b/public/assets/advanced-topics/audit-logs.png deleted file mode 100644 index 0e9d9ff2..00000000 Binary files a/public/assets/advanced-topics/audit-logs.png and /dev/null differ diff --git a/public/assets/advanced-topics/code-block.png b/public/assets/advanced-topics/code-block.png deleted file mode 100644 index 62a59e57..00000000 Binary files a/public/assets/advanced-topics/code-block.png and /dev/null differ diff --git a/public/assets/advanced-topics/installed-bundles.png b/public/assets/advanced-topics/installed-bundles.png deleted file mode 100644 index aca99bbe..00000000 Binary files a/public/assets/advanced-topics/installed-bundles.png and /dev/null differ diff --git a/public/assets/advanced-topics/rbac-basics.png b/public/assets/advanced-topics/rbac-basics.png deleted file mode 100644 index e26e4918..00000000 Binary files a/public/assets/advanced-topics/rbac-basics.png and /dev/null differ diff --git a/public/assets/advanced-topics/service-accounts.gif b/public/assets/advanced-topics/service-accounts.gif deleted file mode 100644 index d63a1c24..00000000 Binary files a/public/assets/advanced-topics/service-accounts.gif and /dev/null differ diff --git a/public/assets/basic-setup-and-deployment/application-runbook.png b/public/assets/basic-setup-and-deployment/application-runbook.png deleted file mode 100644 index d34c4a4b..00000000 Binary files a/public/assets/basic-setup-and-deployment/application-runbook.png and /dev/null differ diff --git a/public/assets/basic-setup-and-deployment/gitops-terminal.png b/public/assets/basic-setup-and-deployment/gitops-terminal.png deleted file mode 100644 index 4a897d04..00000000 Binary files a/public/assets/basic-setup-and-deployment/gitops-terminal.png and /dev/null differ diff --git a/public/assets/cli-quickstart/local-installer.png b/public/assets/cli-quickstart/local-installer.png deleted file mode 100644 index 350930f1..00000000 Binary files a/public/assets/cli-quickstart/local-installer.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/access-keys-aws.png b/public/assets/cloud-shell-quickstart/access-keys-aws.png deleted file mode 100644 index 2c967a3b..00000000 Binary files a/public/assets/cloud-shell-quickstart/access-keys-aws.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/add-key-gcp.png b/public/assets/cloud-shell-quickstart/add-key-gcp.png deleted file mode 100644 index cf08f328..00000000 Binary files a/public/assets/cloud-shell-quickstart/add-key-gcp.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/administrator-access-aws.png b/public/assets/cloud-shell-quickstart/administrator-access-aws.png deleted file mode 100644 index c6ead039..00000000 Binary files a/public/assets/cloud-shell-quickstart/administrator-access-aws.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/airflow-configuration.png b/public/assets/cloud-shell-quickstart/airflow-configuration.png deleted file mode 100644 index a2071c1b..00000000 Binary files a/public/assets/cloud-shell-quickstart/airflow-configuration.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/app-registrations-azure.png b/public/assets/cloud-shell-quickstart/app-registrations-azure.png deleted file mode 100644 index f5677460..00000000 Binary files a/public/assets/cloud-shell-quickstart/app-registrations-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/application-domains.png b/public/assets/cloud-shell-quickstart/application-domains.png deleted file mode 100644 index f434dc73..00000000 Binary files a/public/assets/cloud-shell-quickstart/application-domains.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/applications-install-confirm.png b/public/assets/cloud-shell-quickstart/applications-install-confirm.png deleted file mode 100644 index fba732b3..00000000 Binary files a/public/assets/cloud-shell-quickstart/applications-install-confirm.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/aws-plural-config.png b/public/assets/cloud-shell-quickstart/aws-plural-config.png deleted file mode 100644 index d542990f..00000000 Binary files a/public/assets/cloud-shell-quickstart/aws-plural-config.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/cloud-provider-info.png b/public/assets/cloud-shell-quickstart/cloud-provider-info.png deleted file mode 100644 index 6764b22a..00000000 Binary files a/public/assets/cloud-shell-quickstart/cloud-provider-info.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/cloud-shell-applications.png b/public/assets/cloud-shell-quickstart/cloud-shell-applications.png deleted file mode 100644 index fa799265..00000000 Binary files a/public/assets/cloud-shell-quickstart/cloud-shell-applications.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/cloud-shell-config.png b/public/assets/cloud-shell-quickstart/cloud-shell-config.png deleted file mode 100644 index 11e0e471..00000000 Binary files a/public/assets/cloud-shell-quickstart/cloud-shell-config.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/completed-role-assignments-azure.png b/public/assets/cloud-shell-quickstart/completed-role-assignments-azure.png deleted file mode 100644 index a8564e9d..00000000 Binary files a/public/assets/cloud-shell-quickstart/completed-role-assignments-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/console-example.png b/public/assets/cloud-shell-quickstart/console-example.png deleted file mode 100644 index db96572a..00000000 Binary files a/public/assets/cloud-shell-quickstart/console-example.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/create-keys-gcp.png b/public/assets/cloud-shell-quickstart/create-keys-gcp.png deleted file mode 100644 index 2ac03d40..00000000 Binary files a/public/assets/cloud-shell-quickstart/create-keys-gcp.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/create-user.png b/public/assets/cloud-shell-quickstart/create-user.png deleted file mode 100644 index 14fa43ee..00000000 Binary files a/public/assets/cloud-shell-quickstart/create-user.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/gcp-owner-service-account.png b/public/assets/cloud-shell-quickstart/gcp-owner-service-account.png deleted file mode 100644 index 999bcea2..00000000 Binary files a/public/assets/cloud-shell-quickstart/gcp-owner-service-account.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/gcp-plural-credentials.png b/public/assets/cloud-shell-quickstart/gcp-plural-credentials.png deleted file mode 100644 index e1505627..00000000 Binary files a/public/assets/cloud-shell-quickstart/gcp-plural-credentials.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/gcp-service-account-fields.png b/public/assets/cloud-shell-quickstart/gcp-service-account-fields.png deleted file mode 100644 index c489bfd3..00000000 Binary files a/public/assets/cloud-shell-quickstart/gcp-service-account-fields.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/github-config.png b/public/assets/cloud-shell-quickstart/github-config.png deleted file mode 100644 index de5cd21d..00000000 Binary files a/public/assets/cloud-shell-quickstart/github-config.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/iam-aws.png b/public/assets/cloud-shell-quickstart/iam-aws.png deleted file mode 100644 index f8a2626f..00000000 Binary files a/public/assets/cloud-shell-quickstart/iam-aws.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-1.png b/public/assets/cloud-shell-quickstart/image-1.png deleted file mode 100644 index eefeef05..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-1.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-2.png b/public/assets/cloud-shell-quickstart/image-2.png deleted file mode 100644 index 428ba384..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-2.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-3.png b/public/assets/cloud-shell-quickstart/image-3.png deleted file mode 100644 index 16de35f5..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-3.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-4.png b/public/assets/cloud-shell-quickstart/image-4.png deleted file mode 100644 index 6f0c385a..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-4.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-5.png b/public/assets/cloud-shell-quickstart/image-5.png deleted file mode 100644 index e80978b5..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-5.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-6.png b/public/assets/cloud-shell-quickstart/image-6.png deleted file mode 100644 index f8faa753..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-6.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/image-7.png b/public/assets/cloud-shell-quickstart/image-7.png deleted file mode 100644 index 71cc3aa7..00000000 Binary files a/public/assets/cloud-shell-quickstart/image-7.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/new-client-secret-azure.png b/public/assets/cloud-shell-quickstart/new-client-secret-azure.png deleted file mode 100644 index eb11bc0f..00000000 Binary files a/public/assets/cloud-shell-quickstart/new-client-secret-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/plural-azure-config.png b/public/assets/cloud-shell-quickstart/plural-azure-config.png deleted file mode 100644 index 1c517ef4..00000000 Binary files a/public/assets/cloud-shell-quickstart/plural-azure-config.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/ra-azure.png b/public/assets/cloud-shell-quickstart/ra-azure.png deleted file mode 100644 index c5039409..00000000 Binary files a/public/assets/cloud-shell-quickstart/ra-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/registration-details-azure.png b/public/assets/cloud-shell-quickstart/registration-details-azure.png deleted file mode 100644 index 46e23c7b..00000000 Binary files a/public/assets/cloud-shell-quickstart/registration-details-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/service-accounts-gcp.png b/public/assets/cloud-shell-quickstart/service-accounts-gcp.png deleted file mode 100644 index 08ad0dff..00000000 Binary files a/public/assets/cloud-shell-quickstart/service-accounts-gcp.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/setup-options.png b/public/assets/cloud-shell-quickstart/setup-options.png deleted file mode 100644 index 928c8e89..00000000 Binary files a/public/assets/cloud-shell-quickstart/setup-options.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/subscriptions-azure.png b/public/assets/cloud-shell-quickstart/subscriptions-azure.png deleted file mode 100644 index d2283128..00000000 Binary files a/public/assets/cloud-shell-quickstart/subscriptions-azure.png and /dev/null differ diff --git a/public/assets/cloud-shell-quickstart/terminal-output.png b/public/assets/cloud-shell-quickstart/terminal-output.png deleted file mode 100644 index 46081523..00000000 Binary files a/public/assets/cloud-shell-quickstart/terminal-output.png and /dev/null differ diff --git a/public/assets/frindle-service-account.gif b/public/assets/frindle-service-account.gif deleted file mode 100644 index 7b101d92..00000000 Binary files a/public/assets/frindle-service-account.gif and /dev/null differ diff --git a/public/assets/image (1).png b/public/assets/image (1).png deleted file mode 100644 index db9054ce..00000000 Binary files a/public/assets/image (1).png and /dev/null differ diff --git a/public/assets/image (2).png b/public/assets/image (2).png deleted file mode 100644 index 1234b339..00000000 Binary files a/public/assets/image (2).png and /dev/null differ diff --git a/public/assets/image (3).png b/public/assets/image (3).png deleted file mode 100644 index 4c0d64d1..00000000 Binary files a/public/assets/image (3).png and /dev/null differ diff --git a/public/assets/image.png b/public/assets/image.png deleted file mode 100644 index 4ab4d773..00000000 Binary files a/public/assets/image.png and /dev/null differ diff --git a/public/assets/introduction/introduction-marketplace.png b/public/assets/introduction/introduction-marketplace.png deleted file mode 100644 index 6139030d..00000000 Binary files a/public/assets/introduction/introduction-marketplace.png and /dev/null differ diff --git a/public/assets/operations/add-users-console.png b/public/assets/operations/add-users-console.png deleted file mode 100644 index 93b62169..00000000 Binary files a/public/assets/operations/add-users-console.png and /dev/null differ diff --git a/public/assets/operations/airflow-approval-policy.png b/public/assets/operations/airflow-approval-policy.png deleted file mode 100644 index 7f39faca..00000000 Binary files a/public/assets/operations/airflow-approval-policy.png and /dev/null differ diff --git a/public/assets/operations/marketplace-add-users.png b/public/assets/operations/marketplace-add-users.png deleted file mode 100644 index 3641ee8d..00000000 Binary files a/public/assets/operations/marketplace-add-users.png and /dev/null differ diff --git a/public/assets/operations/update-application.png b/public/assets/operations/update-application.png deleted file mode 100644 index d9bfce8f..00000000 Binary files a/public/assets/operations/update-application.png and /dev/null differ diff --git a/public/assets/operations/upgrade-policy.png b/public/assets/operations/upgrade-policy.png deleted file mode 100644 index 1dfd82e2..00000000 Binary files a/public/assets/operations/upgrade-policy.png and /dev/null differ diff --git a/public/assets/plural-service-account.gif b/public/assets/plural-service-account.gif deleted file mode 100644 index 2ba60f6a..00000000 Binary files a/public/assets/plural-service-account.gif and /dev/null differ diff --git a/public/assets/reference/architecture.png b/public/assets/reference/architecture.png deleted file mode 100644 index 27cf43cf..00000000 Binary files a/public/assets/reference/architecture.png and /dev/null differ diff --git a/public/assets/setup-oidc/image-1.png b/public/assets/setup-oidc/image-1.png deleted file mode 100644 index fc2a94b9..00000000 Binary files a/public/assets/setup-oidc/image-1.png and /dev/null differ diff --git a/public/assets/setup-oidc/image-2.png b/public/assets/setup-oidc/image-2.png deleted file mode 100644 index d17176ba..00000000 Binary files a/public/assets/setup-oidc/image-2.png and /dev/null differ diff --git a/public/downloads/Whitepaper - Accelerate Kubernetes Adoption with Plural Continuous Deployment.pdf b/public/downloads/Whitepaper - Accelerate Kubernetes Adoption with Plural Continuous Deployment.pdf new file mode 100644 index 00000000..619806d5 Binary files /dev/null and b/public/downloads/Whitepaper - Accelerate Kubernetes Adoption with Plural Continuous Deployment.pdf differ diff --git a/public/images/cont-deploy/create-cluster-m.png b/public/images/cont-deploy/create-cluster-m.png new file mode 100755 index 00000000..d36b5d3f Binary files /dev/null and b/public/images/cont-deploy/create-cluster-m.png differ diff --git a/public/images/cont-deploy/deploy-service.png b/public/images/cont-deploy/deploy-service.png new file mode 100644 index 00000000..9ba813a6 Binary files /dev/null and b/public/images/cont-deploy/deploy-service.png differ diff --git a/public/images/cont-deploy/deployments-clusters-update.png b/public/images/cont-deploy/deployments-clusters-update.png new file mode 100644 index 00000000..a38f48e8 Binary files /dev/null and b/public/images/cont-deploy/deployments-clusters-update.png differ diff --git a/public/images/cont-deploy/deployments-hero.png b/public/images/cont-deploy/deployments-hero.png new file mode 100644 index 00000000..25e6a5a4 Binary files /dev/null and b/public/images/cont-deploy/deployments-hero.png differ diff --git a/public/images/cont-deploy/diagram.png b/public/images/cont-deploy/diagram.png new file mode 100644 index 00000000..5c8bb2da Binary files /dev/null and b/public/images/cont-deploy/diagram.png differ diff --git a/public/images/cont-deploy/pipelines.png b/public/images/cont-deploy/pipelines.png new file mode 100644 index 00000000..0aaa0495 Binary files /dev/null and b/public/images/cont-deploy/pipelines.png differ diff --git a/public/images/cont-deploy/whitepaper.png b/public/images/cont-deploy/whitepaper.png new file mode 100644 index 00000000..8fee4106 Binary files /dev/null and b/public/images/cont-deploy/whitepaper.png differ diff --git a/public/images/homepage/features/customizable-1.png b/public/images/homepage/features/customizable-1.png new file mode 100644 index 00000000..d1a7e89c Binary files /dev/null and b/public/images/homepage/features/customizable-1.png differ diff --git a/public/images/homepage/features/easy-setup-1.png b/public/images/homepage/features/easy-setup-1.png new file mode 100644 index 00000000..3f971754 Binary files /dev/null and b/public/images/homepage/features/easy-setup-1.png differ diff --git a/public/images/homepage/features/easy-setup-2.png b/public/images/homepage/features/easy-setup-2.png new file mode 100644 index 00000000..21ef8e14 Binary files /dev/null and b/public/images/homepage/features/easy-setup-2.png differ diff --git a/public/images/homepage/features/production-1.png b/public/images/homepage/features/production-1.png new file mode 100644 index 00000000..fb356b29 Binary files /dev/null and b/public/images/homepage/features/production-1.png differ diff --git a/public/images/homepage/features/production-2.png b/public/images/homepage/features/production-2.png new file mode 100644 index 00000000..54989c26 Binary files /dev/null and b/public/images/homepage/features/production-2.png differ diff --git a/public/images/homepage/features/security-1.png b/public/images/homepage/features/security-1.png new file mode 100644 index 00000000..ed2fc279 Binary files /dev/null and b/public/images/homepage/features/security-1.png differ diff --git a/public/images/homepage/features/security-2.png b/public/images/homepage/features/security-2.png new file mode 100644 index 00000000..58fed86f Binary files /dev/null and b/public/images/homepage/features/security-2.png differ diff --git a/public/images/homepage/features/upgrades-1.png b/public/images/homepage/features/upgrades-1.png new file mode 100644 index 00000000..11ef3ef4 Binary files /dev/null and b/public/images/homepage/features/upgrades-1.png differ diff --git a/public/images/homepage/hero-apps-noshadow.svg b/public/images/homepage/hero-apps-noshadow.svg new file mode 100644 index 00000000..729b04b7 --- /dev/null +++ b/public/images/homepage/hero-apps-noshadow.svg @@ -0,0 +1,3526 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/homepage/hero-apps.png b/public/images/homepage/hero-apps.png new file mode 100644 index 00000000..ca622fef Binary files /dev/null and b/public/images/homepage/hero-apps.png differ diff --git a/public/images/homepage/hero-configuration-noshadow.svg b/public/images/homepage/hero-configuration-noshadow.svg new file mode 100644 index 00000000..57a39cd4 --- /dev/null +++ b/public/images/homepage/hero-configuration-noshadow.svg @@ -0,0 +1,1512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/homepage/hero-configuration.png b/public/images/homepage/hero-configuration.png new file mode 100644 index 00000000..a46434c0 Binary files /dev/null and b/public/images/homepage/hero-configuration.png differ diff --git a/public/images/homepage/hero-nodes-noshadow.svg b/public/images/homepage/hero-nodes-noshadow.svg new file mode 100644 index 00000000..73109357 --- /dev/null +++ b/public/images/homepage/hero-nodes-noshadow.svg @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/images/homepage/hero-nodes.png b/public/images/homepage/hero-nodes.png new file mode 100644 index 00000000..0d6ca11e Binary files /dev/null and b/public/images/homepage/hero-nodes.png differ diff --git a/public/images/how-plural-works/how-plural-works-screen.png b/public/images/how-plural-works/how-plural-works-screen.png new file mode 100644 index 00000000..0f33f20f Binary files /dev/null and b/public/images/how-plural-works/how-plural-works-screen.png differ diff --git a/public/images/search-icon.svg b/public/images/icons/search-icon.svg similarity index 100% rename from public/images/search-icon.svg rename to public/images/icons/search-icon.svg diff --git a/public/images/landing/hero-bg-lg.avif b/public/images/landing/hero-bg-lg.avif deleted file mode 100644 index 846c81ee..00000000 Binary files a/public/images/landing/hero-bg-lg.avif and /dev/null differ diff --git a/public/images/landing/hero-bg-lg.png b/public/images/landing/hero-bg-lg.png deleted file mode 100644 index ed728a87..00000000 Binary files a/public/images/landing/hero-bg-lg.png and /dev/null differ diff --git a/public/images/landing/hero-bg-sm.png b/public/images/landing/hero-bg-sm.png deleted file mode 100644 index b86a187b..00000000 Binary files a/public/images/landing/hero-bg-sm.png and /dev/null differ diff --git a/public/images/partner-logos/logo-aboitiz-dark.png b/public/images/partner-logos/logo-aboitiz-dark.png new file mode 100644 index 00000000..039c7b6c Binary files /dev/null and b/public/images/partner-logos/logo-aboitiz-dark.png differ diff --git a/public/images/partner-logos/logo-aboitiz-light.png b/public/images/partner-logos/logo-aboitiz-light.png new file mode 100644 index 00000000..ac59dc6e Binary files /dev/null and b/public/images/partner-logos/logo-aboitiz-light.png differ diff --git a/public/images/partner-logos/logo-aboitiz.png b/public/images/partner-logos/logo-aboitiz.png deleted file mode 100644 index 0c290f22..00000000 Binary files a/public/images/partner-logos/logo-aboitiz.png and /dev/null differ diff --git a/public/images/partner-logos/logo-apex-clean-energy-dark.png b/public/images/partner-logos/logo-apex-clean-energy-dark.png new file mode 100644 index 00000000..725f852c Binary files /dev/null and b/public/images/partner-logos/logo-apex-clean-energy-dark.png differ diff --git a/public/images/partner-logos/logo-apex-clean-energy-light.png b/public/images/partner-logos/logo-apex-clean-energy-light.png new file mode 100644 index 00000000..eaefeed4 Binary files /dev/null and b/public/images/partner-logos/logo-apex-clean-energy-light.png differ diff --git a/public/images/partner-logos/logo-apex-clean-energy.png b/public/images/partner-logos/logo-apex-clean-energy.png deleted file mode 100644 index af6c5614..00000000 Binary files a/public/images/partner-logos/logo-apex-clean-energy.png and /dev/null differ diff --git a/public/images/partner-logos/logo-cayena-dark.svg b/public/images/partner-logos/logo-cayena-dark.svg new file mode 100644 index 00000000..cbd6b732 --- /dev/null +++ b/public/images/partner-logos/logo-cayena-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-cayena-light.svg b/public/images/partner-logos/logo-cayena-light.svg new file mode 100644 index 00000000..3b5dc9c9 --- /dev/null +++ b/public/images/partner-logos/logo-cayena-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-coachhub-dark.svg b/public/images/partner-logos/logo-coachhub-dark.svg new file mode 100644 index 00000000..133297db --- /dev/null +++ b/public/images/partner-logos/logo-coachhub-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-coachhub-light.svg b/public/images/partner-logos/logo-coachhub-light.svg new file mode 100644 index 00000000..350570bd --- /dev/null +++ b/public/images/partner-logos/logo-coachhub-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-coachhub.png b/public/images/partner-logos/logo-coachhub.png deleted file mode 100644 index 257f00d2..00000000 Binary files a/public/images/partner-logos/logo-coachhub.png and /dev/null differ diff --git a/public/images/partner-logos/logo-digitas-dark.png b/public/images/partner-logos/logo-digitas-dark.png new file mode 100644 index 00000000..50c61e0c Binary files /dev/null and b/public/images/partner-logos/logo-digitas-dark.png differ diff --git a/public/images/partner-logos/logo-digitas-light.png b/public/images/partner-logos/logo-digitas-light.png new file mode 100644 index 00000000..47656aca Binary files /dev/null and b/public/images/partner-logos/logo-digitas-light.png differ diff --git a/public/images/partner-logos/logo-digitas.png b/public/images/partner-logos/logo-digitas.png deleted file mode 100644 index 46670a1c..00000000 Binary files a/public/images/partner-logos/logo-digitas.png and /dev/null differ diff --git a/public/images/partner-logos/logo-faros-dark.svg b/public/images/partner-logos/logo-faros-dark.svg new file mode 100644 index 00000000..f135f3b5 --- /dev/null +++ b/public/images/partner-logos/logo-faros-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-faros-light.svg b/public/images/partner-logos/logo-faros-light.svg new file mode 100644 index 00000000..82d1e6c3 --- /dev/null +++ b/public/images/partner-logos/logo-faros-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-fnatic-dark.svg b/public/images/partner-logos/logo-fnatic-dark.svg new file mode 100644 index 00000000..0d6a2cbc --- /dev/null +++ b/public/images/partner-logos/logo-fnatic-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-fnatic-light.svg b/public/images/partner-logos/logo-fnatic-light.svg new file mode 100644 index 00000000..fda5f8da --- /dev/null +++ b/public/images/partner-logos/logo-fnatic-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/partner-logos/logo-fsn-dark.png b/public/images/partner-logos/logo-fsn-dark.png new file mode 100644 index 00000000..852d42a7 Binary files /dev/null and b/public/images/partner-logos/logo-fsn-dark.png differ diff --git a/public/images/partner-logos/logo-fsn-light.png b/public/images/partner-logos/logo-fsn-light.png new file mode 100644 index 00000000..393dff62 Binary files /dev/null and b/public/images/partner-logos/logo-fsn-light.png differ diff --git a/public/images/partner-logos/logo-fsn.png b/public/images/partner-logos/logo-fsn.png deleted file mode 100644 index abd9b274..00000000 Binary files a/public/images/partner-logos/logo-fsn.png and /dev/null differ diff --git a/public/images/partner-logos/logo-justos-dark.png b/public/images/partner-logos/logo-justos-dark.png new file mode 100644 index 00000000..89e3bb8b Binary files /dev/null and b/public/images/partner-logos/logo-justos-dark.png differ diff --git a/public/images/partner-logos/logo-justos-light.png b/public/images/partner-logos/logo-justos-light.png new file mode 100644 index 00000000..3f6bffb2 Binary files /dev/null and b/public/images/partner-logos/logo-justos-light.png differ diff --git a/public/images/partner-logos/logo-justos.png b/public/images/partner-logos/logo-justos.png deleted file mode 100644 index 252f7b7f..00000000 Binary files a/public/images/partner-logos/logo-justos.png and /dev/null differ diff --git a/public/images/partner-logos/logo-poplar.svg b/public/images/partner-logos/logo-poplar-dark.svg similarity index 100% rename from public/images/partner-logos/logo-poplar.svg rename to public/images/partner-logos/logo-poplar-dark.svg diff --git a/public/images/partner-logos/logo-poplar-light.svg b/public/images/partner-logos/logo-poplar-light.svg new file mode 100644 index 00000000..97d92bf6 --- /dev/null +++ b/public/images/partner-logos/logo-poplar-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/images/plural-docs-logo.svg b/public/images/plural-docs-logo.svg deleted file mode 100644 index ad618150..00000000 --- a/public/images/plural-docs-logo.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/components/AppOrStackCard.tsx b/src/components/AppOrStackCard.tsx index 1cea97db..2c3a4a13 100644 --- a/src/components/AppOrStackCard.tsx +++ b/src/components/AppOrStackCard.tsx @@ -5,7 +5,7 @@ import { AppIcon, Chip, StackIcon } from '@pluralsh/design-system' import styled from 'styled-components' import { mqs } from '@src/breakpoints' -import { type MinRepo } from '@src/data/getRepos' +import { type TinyRepo } from '@src/data/getRepos' import { type MinStack } from '@src/data/getStacks' const AppOrStackCard = styled.div<{ @@ -108,11 +108,12 @@ export function StackCard({
    - {(stack.collections?.[0]?.bundles || []).map((b) => { + {(stack.collections?.[0]?.bundles || []).map((b, i) => { const repo = b?.recipe.repository return ( @@ -132,7 +133,7 @@ export const AppCard = forwardRef( ...props }: { active?: boolean - app: MinRepo + app: TinyRepo size?: ComponentProps['$size'] } & ComponentProps, ref diff --git a/src/components/ArticleCard.tsx b/src/components/ArticleCard.tsx new file mode 100644 index 00000000..5c7f018b --- /dev/null +++ b/src/components/ArticleCard.tsx @@ -0,0 +1,173 @@ +import { type ComponentProps } from 'react' + +import Link from 'next/link' +import { useRouter } from 'next/router' + +import styled from 'styled-components' +import { type Merge } from 'type-fest' + +import { mqs } from '@src/breakpoints' +import { QUICKSTART_VIDEO_URL } from '@src/consts' +import { getImageUrl } from '@src/consts/routes' +import { type ArticleCardFragment } from '@src/generated/graphqlDirectus' +import { isExternalUrl } from '@src/utils/text' + +import Embed from './Embed' +import { SubsectionHead } from './SectionHeads' +import { ShadowedCard } from './ShadowedCard' +import { Body1, Cta } from './Typography' + +const ArticleCardSC = styled(ShadowedCard)<{ + $size: 'medium' | 'small' + $reverse: boolean +}>(({ $size, $reverse = false, theme }) => ({ + overflow: 'hidden', + display: 'flex', + flexDirection: 'column', + gap: 0, + img: { + display: 'block', + margin: 0, + padding: 0, + opacity: 0, + }, + '.content': { + padding: theme.spacing.xlarge, + marginLeft: 'auto', + marginRight: 'auto', + maxWidth: 460, + display: 'flex', + flexDirection: 'column', + rowGap: theme.spacing.large, + }, + ...($size !== 'small' + ? { + [mqs.columns]: { + flexDirection: $reverse ? 'row-reverse' : 'row', + '& > *': { + width: '50%', + }, + '.content': { + marginLeft: 0, + }, + }, + } + : {}), +})) + +export function QuickstartDemoCard() { + return ( + + ) +} + +export function ArticleCard({ + ctas, + thumbnail, + heading, + description, + videoUrl, + url, + author, + date, + preHeading, + reverse = false, + size = 'medium', + ...props +}: Merge< + Merge< + ComponentProps, + ArticleCardFragment & { + size?: 'medium' | 'small' + preHeading?: string + reverse?: boolean + } + >, + { thumbnail?: ArticleCardFragment['thumbnail'] | string } +>) { + const thumbUrl = + typeof thumbnail === 'string' ? thumbnail : getImageUrl(thumbnail) + const locale = useRouter().locale || 'en-us' + + return ( + + {videoUrl ? ( + + ) : ( + thumbUrl && ( +
    + +
    + ) + )} +
    + + {[ + new Date(date).toLocaleDateString(locale, { + dateStyle: 'medium', + }), + author ? `By ${author}` : null, + ] + .filter((v) => !!v) + .join(' | ')} + + )) + } + heading={heading} + headingProps={{ textStyles: { '': 'mTitle1' } }} + /> + {description && {description}} + {ctas?.map((cta) => ( + + {cta.label} + + ))} +
    +
    + ) +} + +export const ArticleCardNoBorder = styled(ArticleCard)(() => ({ + border: 'none', +})) diff --git a/src/components/BasicMarkdown.tsx b/src/components/BasicMarkdown.tsx index 72d74b68..e0f6f7cd 100644 --- a/src/components/BasicMarkdown.tsx +++ b/src/components/BasicMarkdown.tsx @@ -1,6 +1,6 @@ import { memo } from 'react' -import { InlineCode } from '@pluralsh/design-system' +import { InlineCode, isExternalUrl } from '@pluralsh/design-system' import Link from 'next/link' import ReactMarkdown from 'react-markdown' @@ -21,6 +21,9 @@ export default memo(({ text }: { text?: string | null }) => { a: ({ node: _, ...props }) => ( ), diff --git a/src/components/Checklist.tsx b/src/components/Checklist.tsx index e6ebba6f..2271459f 100644 --- a/src/components/Checklist.tsx +++ b/src/components/Checklist.tsx @@ -2,6 +2,8 @@ import { CheckRoundedIcon } from '@pluralsh/design-system' import styled, { useTheme } from 'styled-components' +import { PlanFeatureCheck } from './page-sections/PlansFeaturesTables' + export const Checklist = styled.ul(({ theme }) => ({ display: 'flex', flexDirection: 'column', @@ -16,6 +18,7 @@ export const ChecklistItem = styled(({ children, ...props }) => { {children} @@ -26,4 +29,36 @@ export const ChecklistItem = styled(({ children, ...props }) => { gap: theme.spacing.small, ...theme.partials.marketingText.body1Bold, color: theme.colors.text, + textWrap: 'balance', + '.icon': { flexShrink: 0 }, +})) + +// Larger variant currently styled for light theme only +// Used on Solutions pages +export const Checklist2 = styled.ul(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing.large, })) + +const Checklist2ItemSC = styled.li(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing.medium, + ...theme.partials.marketingText.subtitle2, + color: theme.colors.text, + textWrap: 'balance', + '.icon': { + flexShrink: 0, + }, +})) + +export function Checklist2Item({ children, ...props }) { + return ( + + {/* @ts-expect-error */} + + {children} + + ) +} diff --git a/src/components/CompanyLogos.tsx b/src/components/CompanyLogos.tsx index 55165be4..0fe7097e 100644 --- a/src/components/CompanyLogos.tsx +++ b/src/components/CompanyLogos.tsx @@ -1,69 +1,88 @@ -import styled from 'styled-components' +import { type ComponentProps, type ReactNode } from 'react' + +import styled, { useTheme } from 'styled-components' +import { type Merge } from 'type-fest' import { TextLabel } from '@src/components/Typography' +import { getImageUrl } from '@src/consts/routes' +import { type LogoListFragment } from '@src/generated/graphqlDirectus' import { StandardPageWidth } from './layout/LayoutHelpers' -const partnerLogos = [ - { - logoUrl: 'logo-poplar.svg', - name: 'Poplar', - width: 53, - }, - { - logoUrl: 'logo-digitas.png', - name: 'Digitas', - width: 60, - }, - { - logoUrl: 'logo-justos.png', - name: 'Justos', - width: 70, - }, - { - logoUrl: 'logo-apex-clean-energy.png', - name: 'Apex Clean Energy', - width: 60, - }, - { - logoUrl: 'logo-fsn.png', - name: 'FSN Capital', - width: 50, - }, - { - logoUrl: 'logo-coachhub.png', - name: 'CoachHub', - width: 60, - }, - { - logoUrl: 'logo-aboitiz.png', - name: 'Aboitiz', - width: 65, - }, -] - -export const CompanyLogosSection = styled(({ ...props }) => ( - -
    - - Companies using Plural - -
      - {partnerLogos.map((logo) => ( -
      - {logo.name} -
      - ))} -
    -
    -
    -))(({ theme: _ }) => ({ +const CompanyLogosSectionSC = styled.div(({ theme: _ }) => ({ ul: {}, img: { width: 100, }, })) + +const LogoSC = styled.div(() => ({ + display: 'block', +})) + +export function CompanyLogosSection({ + logos, + heading, + ...props +}: Merge< + ComponentProps, + { + logos?: LogoListFragment['items'] + heading?: ReactNode + } +>) { + const theme = useTheme() + + return ( + + + + {heading || 'Used by fast-moving teams at'} + +
      + {logos?.map((logo) => { + if (!logo?.item) { + return null + } + const { + slug, + logo_dark: logoDark, + logo_light: logoLight, + name, + url, + width, + } = logo.item + const imgUrl = getImageUrl( + theme.mode === 'light' ? logoLight : logoDark + ) + + return ( + imgUrl && ( + + {name} + + ) + ) + })} +
    +
    +
    + ) +} diff --git a/src/components/DocSearchStyles.tsx b/src/components/DocSearchStyles.tsx index 6b533dc2..b3889739 100644 --- a/src/components/DocSearchStyles.tsx +++ b/src/components/DocSearchStyles.tsx @@ -144,7 +144,7 @@ const GlobalStyles = createGlobalStyle(({ theme }) => ({ display: 'block', width: 16, height: 16, - backgroundImage: 'url(/images/search-icon.svg)', + backgroundImage: 'url(/images/icons/search-icon.svg)', backgroundSize: 'contain', }, '.DocSearch-Search-Icon': { diff --git a/src/components/MassiveQuote.tsx b/src/components/FeaturedQuote.tsx similarity index 64% rename from src/components/MassiveQuote.tsx rename to src/components/FeaturedQuote.tsx index ffc35f4e..685d25d1 100644 --- a/src/components/MassiveQuote.tsx +++ b/src/components/FeaturedQuote.tsx @@ -1,14 +1,18 @@ -import { type ReactNode } from 'react' +import { type ComponentProps } from 'react' import styled from 'styled-components' +import { type QuoteFragment } from '@src/generated/graphqlDirectus' + import { StandardPageWidth } from './layout/LayoutHelpers' import { ResponsiveText } from './Typography' -const MassiveQuoteSC = styled.div(({ theme }) => ({ +const FeaturedQuoteSC = styled.div(({ theme }) => ({ paddingTop: theme.spacing.xxxxxxlarge, paddingBottom: theme.spacing.xxxxxxlarge, - backgroundColor: theme.colors['fill-two'], + // Used fill-two in Product page comp, but think that's a mistake + // backgroundColor: theme.colors['fill-two'], + backgroundColor: theme.colors['fill-zero'], '.contentArea': { display: 'flex', flexDirection: 'column', @@ -27,15 +31,16 @@ const IconStarSC = styled.img.attrs({ src: '/images/icons/star.svg' })((_) => ({ height: 20, })) -export function MassiveQuote({ - content, - attributions, -}: { - content: ReactNode - attributions: ReactNode[] -}) { +export function FeaturedQuote({ + quote, + ...props +}: ComponentProps & { quote?: QuoteFragment | null }) { + if (!quote) { + return null + } + return ( - +
    @@ -48,16 +53,16 @@ export function MassiveQuote({ - {content} + {quote.quote} - {attributions.join(' | ')} + {[quote.name, quote.title].filter((q) => !!q).join(' | ')}
    - + ) } diff --git a/src/components/HtmlHead.tsx b/src/components/HtmlHead.tsx index d97c5734..6f8917e1 100644 --- a/src/components/HtmlHead.tsx +++ b/src/components/HtmlHead.tsx @@ -32,25 +32,31 @@ function OpenGraph({ image, }: { title: string - description: string - image?: string + description?: string | null + image?: string | null }) { const router = useRouter() return ( - - - + {image && ( + + )} + {title && ( + + )} + {description && ( + + )} @@ -76,10 +82,12 @@ function HtmlHead({ name="title" content={title} /> - + {description && ( + + )} { const createForm = () => { diff --git a/src/components/PageHeros.tsx b/src/components/PageHeros.tsx index 207ec003..8f7ee214 100644 --- a/src/components/PageHeros.tsx +++ b/src/components/PageHeros.tsx @@ -1,6 +1,7 @@ -import { type ReactNode } from 'react' +import { type ComponentProps, type ReactNode } from 'react' import classNames from 'classnames' +import { type Merge } from 'type-fest' import { Columns, EqualColumn } from '@src/components/layout/Columns' import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' @@ -13,17 +14,24 @@ export function HeroMainText({ description, children, ctas, + className, ...props -}: { - preHeading?: ReactNode - heading: ReactNode - description?: ReactNode - ctas?: ReactNode - children?: ReactNode -}) { +}: Merge< + ComponentProps, + { + preHeading?: ReactNode + heading: ReactNode + description?: ReactNode + ctas?: ReactNode + children?: ReactNode + } +>) { return (
    @@ -109,3 +117,48 @@ export function BasicPageHero({ ) } + +export function HomePageHero({ + preHeading, + heading, + description, + // intro, + padTop = true, + padBottom = true, + ctas, + ...props +}: { + preHeading?: ReactNode + heading: ReactNode + description?: ReactNode + ctas?: ReactNode + padTop?: boolean + padBottom?: boolean + // intro?: ReactNode +}) { + return ( + +
    + {description}
    } + ctas={ctas} + className="mx-auto" + /> +
    + + ) +} diff --git a/src/components/ProductValueSection.tsx b/src/components/ProductValueSection.tsx new file mode 100644 index 00000000..e3a9bad4 --- /dev/null +++ b/src/components/ProductValueSection.tsx @@ -0,0 +1,57 @@ +/* Replaced by HowPluralWorksMiniSection */ +import { Checklist, ChecklistItem } from '@src/components/Checklist' +import { Columns, EqualColumn } from '@src/components/layout/Columns' +import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' +import { TextLimiter } from '@src/components/layout/TextLimiter' +import { Body2, Cta, Title2 } from '@src/components/Typography' + +export function ProductValueSection({ + name, + isStack, +}: { + name: string + isStack: boolean +}) { + const fullName = isStack ? `the ${name} Stack` : name + + return ( + +
    + + + + Open-source and free to use + + Plural automates the deployment and operation of {fullName} in + your cloud. Get up and running with your {fullName} instance in + minutes and let Plural deploy {fullName} and all its + dependencies into your cloud with all of the day-2 operations + handled out of the box. + + + Explore {fullName} on Plural in live demo environment + + + + + + Automated upgrades + + Transparent pricing and cost management + + Prebuilt dashboards, extendable + Prebuilt runbooks, extendable + Log management + + + +
    + Screenshots of the Plural Console app, showing dashboards for Applications, Nodes and cost +
    +
    +
    + ) +} diff --git a/src/components/QuickstartDemoCard.tsx b/src/components/QuickstartDemoCard.tsx deleted file mode 100644 index 5070c85d..00000000 --- a/src/components/QuickstartDemoCard.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import styled from 'styled-components' - -import { mqs } from '@src/breakpoints' -import { QUICKSTART_VIDEO_URL } from '@src/consts' - -import Embed from './Embed' -import { SubsectionHead } from './SectionHeads' -import { ShadowedCard } from './ShadowedCard' -import { Body1, Cta } from './Typography' - -const QuickstartDemoCardSC = styled(ShadowedCard)(({ theme }) => ({ - overflow: 'hidden', - display: 'flex', - flexDirection: 'column', - gap: 0, - '.content': { - padding: theme.spacing.xlarge, - marginLeft: 'auto', - marginRight: 'auto', - maxWidth: 460, - display: 'flex', - flexDirection: 'column', - rowGap: theme.spacing.large, - }, - [mqs.columns]: { - flexDirection: 'row', - '& > *': { - width: '50%', - }, - '.content': { - marginLeft: 0, - }, - }, -})) - -export function QuickstartDemoCard() { - return ( - - -
    - - - This guide goes over how to get started with Plural using our - in-browser Cloud Shell. - - - Browse all - -
    -
    - ) -} diff --git a/src/components/QuoteCards.tsx b/src/components/QuoteCards.tsx index b556e9ff..19093167 100644 --- a/src/components/QuoteCards.tsx +++ b/src/components/QuoteCards.tsx @@ -1,149 +1,56 @@ -import { type ComponentProps, type ReactNode, useEffect, useState } from 'react' +import { type ComponentProps, useEffect, useState } from 'react' import styled, { useTheme } from 'styled-components' import { Swiper, SwiperSlide } from 'swiper/react' import { type Swiper as SwiperT } from 'swiper/types' +import { type Merge } from 'type-fest' import 'swiper/css' import { mqs } from '@src/breakpoints' +import { getImageUrl } from '@src/consts/routes' +import { type QuoteFragment } from '@src/generated/graphqlDirectus' +import BasicMarkdown from './BasicMarkdown' import { CarouselDot, CarouselDots } from './CarouselDots' import useIndex from './hooks/useIndex' import { StandardPageWidth } from './layout/LayoutHelpers' import { Heading1 } from './Typography' -type Quote = { - quote?: ReactNode | string - company?: string - logoUrl?: string - name?: string - title?: string - portraitUrl?: string -} - -export const DEFAULT_QUOTES = [ - { - quote: ( - <> - “We no longer needed a dedicated DevOps team; instead, we actively - participated in the industrialization and deployment of our applications - through Plural. Additionally, it allowed us to quickly gain proficiency - in Terraform and Helm.” - - ), - company: 'Beamy', - logoUrl: 'logo-beamy.png', - name: 'Walid El Bouchikhi', - title: 'Data Engineer at Beamy', - portraitUrl: 'walid-el-bouchikhi.jpg', - }, - { - quote: ( - <> - “I have neither the patience nor the talent for DevOps/SysAdmin work, - and yet I've deployed four enterprise-caliber open-source apps on - Kubernetes... since 9am today. Bonkers.” - - ), - company: 'Justifi', - logoUrl: 'logo-justifi.png', - name: 'Sawyer Waugh', - title: 'Head of Engineering at Justifi', - portraitUrl: 'sawyer-waugh.jpg', - }, - { - quote: - '“This is awesome. You saved me hours of further DevOps work for our v1 release. Just to say, I really love Plural.”', - company: 'Modeo', - logoUrl: 'logo-modeo.png', - name: 'Ismael Goulani', - title: 'CTO | Data Engineer at Modeo', - portraitUrl: 'ismael-goulani.jpg', - }, - - { - quote: ( - <> - “Wow! First of all I want to say thank you for creating Plural! It - solves a lot of problems coming from a non-DevOps background. You guys - are amazing!” - - ), - company: 'Poplar Homes', - logoUrl: 'logo-poplar.png', - name: 'Joey Taleño', - title: 'Head of Data at Poplar Homes', - portraitUrl: 'joey-taleno.jpg', - }, - - { - quote: ( - <> - “We have been using Plural for complex Kubernetes deployments of - Kubeflow and are excited with the possibilities it provides in making - our workflows simpler and more efficient. ” - - ), - company: 'Alexander Thamm', - logoUrl: 'logo-alexander-thamm.png', - name: 'Jürgen Stary', - title: 'Engineering Manager @ Alexander Thamm', - portraitUrl: 'jurgen-stary.jpg', - }, - { - quote: ( - <> - “Plural has been awesome, it’s super fast and intuitive to get going and - there is zero-to-no overhead of the app management.” - - ), - company: 'Commandbar', - logoUrl: 'logo-commandbar.png', - name: 'Richard Freling', - title: 'CTA and Co-Founder at Commandbar', - portraitUrl: 'richard-freling.jpg', - }, -] as const satisfies readonly Quote[] - export const QuoteCard = styled( ({ quote, - logoUrl, - name, - portraitUrl, - title, - company, variant: _variant, ...props }: { - quote: ReactNode - logoUrl: string - name: string - portraitUrl: string - title: string - company: string + quote: QuoteFragment variant?: 'default' | 'active' } & ComponentProps<'div'>) => { - const dir = '/images/quotes' + const imgUrl = getImageUrl(quote.logo) return (
    -
    {quote}
    -
    - {company} +
    +
    + {imgUrl && ( +
    + {`${quote.company} +
    + )}
    -
    + {quote.portrait && ( +
    + )}
    -
    {name}
    -
    {title}
    + {quote.name &&
    {quote.name}
    } + {quote.title &&
    {quote.title}
    }
    @@ -212,84 +119,7 @@ export const QuoteCard = styled( : theme.colors['fill-three'], })) -export const QuotesCarousel = styled( - ({ - quotes = DEFAULT_QUOTES, - ...props - }: { quotes?: typeof DEFAULT_QUOTES } & ComponentProps<'div'>) => { - // const [activeIndex, setActiveIndex] = useState(0) - const theme = useTheme() - const [swiper, setSwiper] = useState(null) - const { - activeIndex: activeI, - setIndex, - goForward, - } = useIndex(quotes.length, 0, true) - - const activeIndex = activeI ?? 0 - - useEffect(() => { - if (activeIndex !== swiper?.realIndex) { - swiper?.slideToLoop(activeIndex) - } - }, [activeIndex, swiper]) - - useEffect(() => { - const timeout = setTimeout(() => { - goForward() - }, 6000) - - return () => { - clearTimeout(timeout) - } - }, [goForward]) - - const quotesInner = quotes - - return ( -
    -
    - { - setIndex(s.realIndex) - }} - onSwiper={setSwiper} - > - {quotesInner.map((quote, i) => ( - - { - setIndex(i) - }} - variant={i === activeIndex ? 'active' : undefined} - /> - - ))} - -
    - - {quotesInner.map((_, i) => ( - { - setIndex(i) - }} - /> - ))} - -
    - ) - } -)(({ theme }) => ({ +const QuotesCarouselFC = styled.div(({ theme }) => ({ display: 'flex', flexDirection: 'column', '.swiper': { @@ -320,14 +150,106 @@ export const QuotesCarousel = styled( }, })) -export function TestimonialsSection() { +export function QuotesCarousel({ + quotes, + ...props +}: Merge< + ComponentProps, + { + quotes?: (QuoteFragment | null | undefined)[] | null + } +>) { + const theme = useTheme() + const [swiper, setSwiper] = useState(null) + const { + activeIndex: activeI, + setIndex, + goForward, + } = useIndex(quotes?.length || 0, 0, true) + + const activeIndex = activeI ?? 0 + + useEffect(() => { + if (activeIndex !== swiper?.realIndex) { + swiper?.slideToLoop(activeIndex) + } + }, [activeIndex, swiper]) + + useEffect(() => { + const timeout = setTimeout(() => { + goForward() + }, 6000) + + return () => { + clearTimeout(timeout) + } + }, [goForward]) + + if (!quotes) return null + + const quotesInner = quotes + + return ( + +
    + { + setIndex(s.realIndex) + }} + onSwiper={setSwiper} + > + {quotesInner.map( + (quote, i) => + quote && ( + + { + setIndex(i) + }} + variant={i === activeIndex ? 'active' : undefined} + /> + + ) + )} + +
    + + {quotesInner.map((_, i) => ( + { + setIndex(i) + }} + /> + ))} + +
    + ) +} + +export function TestimonialsSection({ + quotes, + ...props +}: Merge< + Omit, 'children'>, + { quotes?: QuoteFragment[] | null } +>) { return ( - +
    What companies are saying about Plural - +
    ) diff --git a/src/components/RepoCardList.tsx b/src/components/RepoCardList.tsx index 7c718453..45e0b950 100644 --- a/src/components/RepoCardList.tsx +++ b/src/components/RepoCardList.tsx @@ -20,7 +20,7 @@ import { drop, isEmpty } from 'lodash-es' import { getStackRepos } from '@pages/marketplace' import { breakpointIsGreaterOrEqual } from '@src/breakpoints' import { appUrl, stackUrl } from '@src/consts/routes' -import { type MinRepo, fakeDisplayName } from '@src/data/getRepos' +import { type BasicRepo, fakeDisplayName } from '@src/data/getRepos' import { type MinStack } from '@src/data/getStacks' import { useBreakpoint } from './contexts/BreakpointProvider' @@ -105,7 +105,7 @@ export function RepoCard({ wideFeatures = true, ...props }: { - repository: MinRepo + repository: BasicRepo urlParams?: string wideFeatures: boolean }) { diff --git a/src/components/RepoSocials.tsx b/src/components/RepoSocials.tsx index 369bc972..6defc132 100644 --- a/src/components/RepoSocials.tsx +++ b/src/components/RepoSocials.tsx @@ -6,12 +6,12 @@ import { GitHubIcon, } from '@pluralsh/design-system' -import { type FullRepo, type MinRepo } from '@src/data/getRepos' +import { type BasicRepo, type FullRepo } from '@src/data/getRepos' export function RepoSocials({ repo, }: { - repo?: (MinRepo & Partial>) | null + repo?: (BasicRepo & Partial>) | null }) { if (!repo) { return null diff --git a/src/components/Typography.tsx b/src/components/Typography.tsx index e8e424e4..40cb4182 100644 --- a/src/components/Typography.tsx +++ b/src/components/Typography.tsx @@ -10,6 +10,7 @@ import { type styledTheme, useNavigationContext, } from '@pluralsh/design-system' +import Link from 'next/link' import { lowerFirst } from 'lodash-es' import styled, { type DefaultTheme } from 'styled-components' @@ -176,6 +177,15 @@ export const Overline = styled.p.withConfig(textPropFilter)( }) ) +export const ComponentLink = styled(Link).withConfig(textPropFilter)( + ({ theme, color }) => ({ + ...theme.partials.marketingText.componentLink, + ...(color + ? { color: theme.colors[color] || theme.colors['text-xlight'] } + : { color: theme.colors['text-xlight'] }), + }) +) + export const TextLabel = styled.h4.withConfig(textPropFilter)( ({ theme, color }) => ({ ...theme.partials.marketingText.label, diff --git a/src/components/icons/PersonCheck.tsx b/src/components/icons/PersonCheck.tsx new file mode 100644 index 00000000..20d1491e --- /dev/null +++ b/src/components/icons/PersonCheck.tsx @@ -0,0 +1,35 @@ +import createIcon from '@pluralsh/design-system/dist/components/icons/createIcon' + +export default createIcon(({ size, color }) => ( + + + + + + + + +)) diff --git a/src/components/layout/Columns.tsx b/src/components/layout/Columns.tsx index 56b974c0..764d9e3f 100644 --- a/src/components/layout/Columns.tsx +++ b/src/components/layout/Columns.tsx @@ -27,3 +27,20 @@ export function Columns({ className, ...props }: ComponentProps<'div'>) { /> ) } + +export function ColumnsMd({ className, ...props }: ComponentProps<'div'>) { + return ( +
    + ) +} diff --git a/src/components/layout/GradientBG.tsx b/src/components/layout/GradientBG.tsx index a2b6ce19..a8afef64 100644 --- a/src/components/layout/GradientBG.tsx +++ b/src/components/layout/GradientBG.tsx @@ -1,6 +1,7 @@ -import { type ReactNode } from 'react' +import { type ComponentProps, type ReactNode } from 'react' import styled from 'styled-components' +import { type Merge } from 'type-fest' const GradientBGSC = styled.div<{ $position?: string @@ -45,12 +46,15 @@ export function GradientBG({ image, size, ...props -}: { - children: ReactNode - position?: string - image?: string - size?: string -}) { +}: Merge< + ComponentProps, + { + children: ReactNode + position?: string + image?: string + size?: string + } +>) { return ( ) } + +const StandardPageSectionSC = styled.div<{ + $padTop?: boolean + $padBottom?: boolean +}>(({ $padTop: padTop = true, $padBottom: padBottom = true, theme }) => ({ + paddingTop: padTop ? theme.spacing.xxxxlarge : undefined, + paddingBottom: padBottom ? theme.spacing.xxxxlarge : undefined, + [mqs.md]: { + paddingTop: padTop ? theme.spacing.xxxxxlarge : undefined, + paddingBottom: padBottom ? theme.spacing.xxxxxlarge : undefined, + }, + [mqs.xxl]: { + paddingTop: padTop ? theme.spacing.xxxxxxlarge : undefined, + paddingBottom: padBottom ? theme.spacing.xxxxxxlarge : undefined, + }, +})) + +export function StandardPageSection({ + padTop = true, + padBottom = true, + ...props +}: { + padTop?: boolean + padBottom?: boolean +} & ComponentProps) { + return ( + + ) +} diff --git a/src/components/page-sections/BuildStackSection.tsx b/src/components/page-sections/BuildStackSection.tsx index 6ef31845..a54c969e 100644 --- a/src/components/page-sections/BuildStackSection.tsx +++ b/src/components/page-sections/BuildStackSection.tsx @@ -16,7 +16,7 @@ import styled from 'styled-components' import { mqs } from '@src/breakpoints' import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' import { appUrl, stackUrl } from '@src/consts/routes' -import { type getRepos } from '@src/data/getRepos' +import { type getTinyRepos } from '@src/data/getRepos' import { type getStacks } from '@src/data/getStacks' import { AppCard, StackCard } from '../AppOrStackCard' @@ -26,7 +26,7 @@ export const getStackTabData = ({ repos, stacks, }: { - repos?: Awaited> | null + repos?: Awaited> | null stacks?: Awaited> | null }) => [ { diff --git a/src/components/page-sections/FeaturedArticleSection.tsx b/src/components/page-sections/CaseStudySection.tsx similarity index 77% rename from src/components/page-sections/FeaturedArticleSection.tsx rename to src/components/page-sections/CaseStudySection.tsx index a7d78ff3..492d6f53 100644 --- a/src/components/page-sections/FeaturedArticleSection.tsx +++ b/src/components/page-sections/CaseStudySection.tsx @@ -1,9 +1,3 @@ -/* -https://www.plural.sh/blog/fnatic-deploys-data-stack-with-plural/ -https://www.plural.sh/blog/digitas-standardized-application-deployment-by-using-plural/ -https://www.plural.sh/blog/how-modeo-utilizes-plural-for-their-customers/ -*/ - import Link from 'next/link' import { isEmpty } from 'lodash-es' @@ -11,23 +5,24 @@ import { isEmpty } from 'lodash-es' import { Columns, EqualColumn } from '@src/components/layout/Columns' import { Body2, Cta, ResponsiveText } from '@src/components/Typography' import { appUrl, getImageUrl } from '@src/consts/routes' -import { type MinRepo } from '@src/data/getRepos' -import { type FeaturedArticleFragment } from '@src/generated/graphqlDirectus' +import { type TinyRepo } from '@src/data/getRepos' +import { type CaseStudyFragment } from '@src/generated/graphqlDirectus' import { AppCard } from '../AppOrStackCard' import BasicMarkdown from '../BasicMarkdown' import { SubsectionHead } from '../SectionHeads' -export function FeaturedArticleSection({ +export function CaseStudySection({ apps, featuredArticle, }: { - apps: MinRepo[] - featuredArticle?: FeaturedArticleFragment | null | undefined + apps: TinyRepo[] + featuredArticle?: CaseStudyFragment | null | undefined }) { if (!featuredArticle) { return null } + const heroUrl = getImageUrl(featuredArticle.hero_image) return ( @@ -59,9 +54,7 @@ export function FeaturedArticleSection({
    - {featuredArticle.hero_image && ( - - )} + {heroUrl && }
    {!isEmpty(apps) && (
    @@ -93,7 +86,7 @@ export function FeaturedArticleSection({ ) } -export const getFeaturedArticleApps = ( - repos: MinRepo[] | null, +export const getCaseStudyApps = ( + repos: TinyRepo[] | null | undefined, appList: string[] ) => repos?.filter((repo) => appList.includes(repo.name)) || [] diff --git a/src/components/page-sections/CommunityResourcesSection.tsx b/src/components/page-sections/CommunityResourcesSection.tsx index cd7c13b0..17f26c4f 100644 --- a/src/components/page-sections/CommunityResourcesSection.tsx +++ b/src/components/page-sections/CommunityResourcesSection.tsx @@ -115,7 +115,7 @@ function ResourceIconCard({ return ( diff --git a/src/components/page-sections/ContributorsSection.tsx b/src/components/page-sections/ContributorsSection.tsx index 14b10f77..9b2a3f5c 100644 --- a/src/components/page-sections/ContributorsSection.tsx +++ b/src/components/page-sections/ContributorsSection.tsx @@ -111,7 +111,7 @@ function ContributorCard({
    ({ + rowGap: theme.spacing.medium, + textWrap: 'balance', + '&, .text': { + display: 'flex', + flexDirection: 'column', + }, + '.icon': { + display: 'flex', + }, + '.text': { + rowGap: theme.spacing.xsmall, + }, + [mqs.md]: { + maxWidth: 300, + }, +})) + +function HowWorksInfo({ + icon, + heading, + children, + ...props +}: Merge< + ComponentProps, + { + icon: ReactElement + heading: ReactNode + children: ReactNode + } +>) { + const iconClone = cloneElement(icon, { size: 22 }) + + return ( + +
    + {iconClone} +
    +
    + + {heading} + + {children} +
    +
    + ) +} + +function HowPluralWorksMiniSection() { + return ( +
    + + + + + + + We make it easy to securely deploy and manage open-source + applications in your cloud. + + +
    + } + > + Get any stack you want running in minutes, and never think about + upgrades again. + + } + > + You control everything. No need to share your cloud account, + keys or data. + + } + > + Built on Kubernetes and using standard infrastructure as code + with Terraform and Helm. + + } + > + Interactive runbooks, dashboards, and Kubernetes api visualizers + give an easy-to-use toolset to manage application operations.{' '} + +
    + Learn more +
    + +
    +
    + + Screenshot of app installation in Plural app + +
    + ) +} + +const ImageAreaSC = styled.div(({ theme }) => ({ + paddingLeft: theme.spacing.large, + [mqs.columns]: { + position: 'absolute', + display: 'flex', + justifyContent: 'end', + alignItems: 'center', + width: '50%', + top: 0, + right: 0, + bottom: 0, + img: { + display: 'block', + width: '100%', + maxWidth: 1024, + }, + }, +})) + +const HPWMiniSectionSolutionsSC = styled.div(({ theme }) => ({ + backgroundColor: theme.colors['fill-zero'], + paddingTop: theme.spacing.xxxxlarge, + overflow: 'hidden', + [mqs.md]: { + paddingTop: theme.spacing.xxxxxlarge, + }, + [mqs.columns]: { + paddingBottom: theme.spacing.xxxxxlarge, + }, + [mqs.xxl]: { + paddingTop: theme.spacing.xxxxxxlarge, + paddingBottom: theme.spacing.xxxxxxlarge, + }, +})) + +export function HPWMiniSectionSolutions() { + return ( + + + + ) +} + +const HPWMiniSectionAppStacksSC = styled.div(({ theme }) => ({ + paddingTop: theme.spacing.xxlarge, + [mqs.md]: { + paddingTop: theme.spacing.xxxxlarge, + }, + [mqs.columns]: { + paddingBottom: theme.spacing.xxxxxlarge, + }, + [mqs.xxl]: { + paddingBottom: theme.spacing.xxxxxxlarge, + }, +})) + +export function HPWMiniSectionAppStacks() { + return ( + + + + ) +} diff --git a/src/components/page-sections/TryPluralForFreeSection.tsx b/src/components/page-sections/TryPluralForFreeSection.tsx new file mode 100644 index 00000000..c94cd852 --- /dev/null +++ b/src/components/page-sections/TryPluralForFreeSection.tsx @@ -0,0 +1,65 @@ +import { + Button, + GitHubLogoIcon, + GitLabLogoIcon, + GoogleLogoIcon, +} from '@pluralsh/design-system' + +import classNames from 'classnames' + +import { StandardPageWidth } from '@src/components/layout/LayoutHelpers' +import { CenteredSectionHead } from '@src/components/SectionHeads' +import { ComponentLink } from '@src/components/Typography' + +export function TryPluralForFreeSection() { + return ( + +
    + +
    +
    + + + +
    + + Sign up with email + +
    +
    +
    + ) +} diff --git a/src/consts.ts b/src/consts.ts index 4bc60c47..93c8104b 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -1,14 +1,14 @@ import { type GlobalPageProps } from '@pages/_app' -import { type MinRepo } from './data/getRepos' +import { type BasicRepo } from './data/getRepos' import { type MinStack } from './data/getStacks' export const ROOT_TITLE = - 'Plural | Deploy, maintain, and scale the open-source applications you love' + 'Plural | Open-source application deployment, faster than ever without sacrificing compliance.' export const PAGE_TITLE_PREFIX = 'Plural | ' export const PAGE_TITLE_SUFFIX = '' -export const getAppMeta = (repo: MinRepo): GlobalPageProps => { +export const getAppMeta = (repo: BasicRepo): GlobalPageProps => { const displayName = repo.displayName || repo.name if (!displayName) return {} @@ -25,8 +25,8 @@ export const getStackMeta = (stack: MinStack): GlobalPageProps => { if (!displayName) return {} return { - metaTitleFull: `Deploying ${displayName} stack on Kubernetes`, - metaDescription: `Use Plural to deploy and manage the ${displayName} stack on Kubernetes, in your cloud.`, + metaTitleFull: `Deploying the ${displayName} Stack on Kubernetes`, + metaDescription: `Use Plural to deploy and manage the ${displayName} Stack on Kubernetes, in your cloud.`, } } diff --git a/src/consts/routes.tsx b/src/consts/routes.tsx index ca984e4c..6e963736 100644 --- a/src/consts/routes.tsx +++ b/src/consts/routes.tsx @@ -24,11 +24,13 @@ export function jobUrl(jobSlug: string) { } export function getImageUrl( - image: Pick + image?: Pick | null ) { - return urlJoin( - FILE_BASE_URL, - image.filename_disk || '', - image.filename_download || '' - ) + return image + ? urlJoin( + FILE_BASE_URL, + image.filename_disk || '', + encodeURI(image.filename_download) || '' + ) + : null } diff --git a/src/contexts/ReposContext.tsx b/src/contexts/ReposContext.tsx index bf308158..d200e276 100644 --- a/src/contexts/ReposContext.tsx +++ b/src/contexts/ReposContext.tsx @@ -1,8 +1,8 @@ import { createContext, useContext } from 'react' -import type { MinRepo } from '../data/getRepos' +import type { BasicRepo } from '../data/getRepos' export type ReposContextT = any -export const ReposContext = createContext([]) +export const ReposContext = createContext([]) export const useRepos = () => useContext(ReposContext) export const ReposProvider = ReposContext.Provider diff --git a/src/data/getProductPageData.ts b/src/data/getProductPageData.ts new file mode 100644 index 00000000..8d7e6c25 --- /dev/null +++ b/src/data/getProductPageData.ts @@ -0,0 +1,28 @@ +import { directusClient as client } from '@src/apollo-client' +import { + type CalloutFragment, + PageProductDocument, + type PageProductQuery, + type PageProductQueryVariables, +} from '@src/generated/graphqlDirectus' + +let cache: PageProductQuery['page_product'] | null = null + +export type ProductPage = Awaited>['data'] + +export type Callouts = (CalloutFragment | null)[] | null | undefined + +export async function getProductPageData() { + const { data, error } = await client.query< + PageProductQuery, + PageProductQueryVariables + >({ + query: PageProductDocument, + }) + + if (data?.page_product) { + cache = data?.page_product + } + + return { data: data?.page_product || cache, error } +} diff --git a/src/data/getRepos.tsx b/src/data/getRepos.tsx index 60a171bc..d1d9611d 100644 --- a/src/data/getRepos.tsx +++ b/src/data/getRepos.tsx @@ -6,8 +6,8 @@ import { filterMapNodes } from '@src/utils/graphql' import client from '../apollo-client' import { + type BasicRepoFragment, type FullRepoFragment, - type MinRepoFragment, type RecipeFragment, type RecipeSectionFragment, RepoDocument, @@ -16,20 +16,32 @@ import { ReposDocument, type ReposQuery, type ReposQueryVariables, + type TinyRepoFragment, + TinyReposDocument, + type TinyReposQuery, + type TinyReposQueryVariables, } from '../generated/graphqlPlural' const REMOVE_LIST = ['bootstrap', 'test-harness', 'gcp-config-connector'] -export type MinRepo = ReturnType< - typeof normalizeRepo> +export type BasicRepo = ReturnType< + typeof normalizeRepo> > +export type TinyRepo = ReturnType + export type FullRepo = ReturnType< typeof normalizeRepo> > export const reposCache: { - filtered: MinRepo[] + filtered: BasicRepo[] +} = { + filtered: [], +} + +export const tinyReposCache: { + filtered: TinyRepo[] } = { filtered: [], } @@ -77,32 +89,47 @@ export function normalizeRepo< const { recipes, ...props } = repo const nRecipes = normalizeRecipes(recipes) - const community = props.community || ({} as typeof props.community) + const community: FullRepoFragment['community'] = { ...props.community } || {} + + if (!community?.gitUrl && props.gitUrl) { + community.gitUrl = props.gitUrl + } + if (!community?.homepage && props.homepage) { + community.homepage = props.homepage + } return { ...props, ...(nRecipes ? { recipes: nRecipes } : {}), - recipes, + ...(recipes ? { recipes } : {}), displayName: ((repo as any).displayName as string) || fakeDisplayName(repo?.name), community: { ...community, - ...(!community?.gitUrl && props.gitUrl // - ? { gitUrl: props.gitUrl } - : {}), - ...(!community?.homepage && props.homepage // - ? { homepage: props.homepage } - : {}), }, } } +export function normalizeTinyRepo(repo: TinyRepoFragment) { + return { + ...repo, + displayName: + ((repo as any).displayName as string) || fakeDisplayName(repo?.name), + } +} + function filterRepo< T extends { name?: string; recipes?: any[] | null } | null | undefined >(repo: T): boolean { return !!repo && !inRemoveList(repo?.name) && !isEmpty(repo?.recipes) } +function filterTinyRepo< + T extends { name?: string; recipes?: any[] | null } | null | undefined +>(repo: T): boolean { + return !!repo && !inRemoveList(repo?.name) +} + const normalizeRecipes = (recipes: FullRepoFragment['recipes']) => recipes ?.filter((recipe): recipe is RecipeFragment => !!recipe && !recipe.private) @@ -122,23 +149,58 @@ const normalizeRepos = memoizeOne((data: ReposQuery) => filterMapNodes(data?.repositories, filterRepo, normalizeRepo) ) -export async function getRepos(): Promise { +export const normalizeTinyRepos = (data: TinyReposQuery) => + filterMapNodes(data?.repositories, filterTinyRepo, normalizeTinyRepo) + +export async function getRepos(): Promise { const { data, error } = await client.query({ query: ReposDocument, }) + const filteredRepos: BasicRepo[] | undefined | null = normalizeRepos(data) + + if (filteredRepos && filteredRepos.length > 0) { + reposCache.filtered = filteredRepos + + return filteredRepos + } + if (!isEmpty(reposCache.filtered)) { + console.warn('getRepos(): No repos returned, using cached data') + + return reposCache.filtered + } if (error) { - throw new Error(`${error.name}: ${error.message}`) + throw new Error(`getRepos() – ${error.name}: ${error.message}`) } - const filteredRepos = normalizeRepos(data) as MinRepo[] + + throw new Error('getRepos() – No repos found') +} + +export async function getTinyRepos(): Promise { + const { data, error } = await client.query< + TinyReposQuery, + TinyReposQueryVariables + >({ + query: TinyReposDocument, + }) + + const filteredRepos: TinyRepo[] | undefined | null = normalizeTinyRepos(data) if (filteredRepos && filteredRepos.length > 0) { - reposCache.filtered = filteredRepos + tinyReposCache.filtered = filteredRepos - return filteredRepos || [] + return filteredRepos } + if (!isEmpty(tinyReposCache.filtered)) { + console.warn('getTinyRepos(): No repos returned, using cached data') - throw new Error('No repos found') + return tinyReposCache.filtered + } + + if (error) { + throw new Error(`getTinyRepos() – ${error.name}: ${error.message}`) + } + throw new Error('getTinyRepos() – No repos found') } const fullRepoCache: Record = {} @@ -156,7 +218,7 @@ export async function getFullRepo(repoName: string): Promise { ? normalizeRepo(data.repository) : fullRepoCache[repoName] || undefined - if (!filterRepo(repo)) throw new Error('No repo found') + if (!filterRepo(repo)) throw new Error('getFullRepo() – No repo found') fullRepoCache[repoName] = repo return repo diff --git a/src/generated/graphqlDirectus.ts b/src/generated/graphqlDirectus.ts index 28cb16de..6c301495 100644 --- a/src/generated/graphqlDirectus.ts +++ b/src/generated/graphqlDirectus.ts @@ -29,6 +29,9 @@ export type Query = { apps: Array; apps_aggregated: Array; apps_by_id?: Maybe; + article_cards: Array; + article_cards_aggregated: Array; + article_cards_by_id?: Maybe; callouts: Array; callouts_aggregated: Array; callouts_by_id?: Maybe; @@ -38,9 +41,18 @@ export type Query = { collapsible_lists: Array; collapsible_lists_aggregated: Array; collapsible_lists_by_id?: Maybe; + collapsible_lists_items: Array; + collapsible_lists_items_aggregated: Array; + collapsible_lists_items_by_id?: Maybe; collapsibles: Array; collapsibles_aggregated: Array; collapsibles_by_id?: Maybe; + company_logo_lists: Array; + company_logo_lists_aggregated: Array; + company_logo_lists_by_id?: Maybe; + company_logo_lists_items: Array; + company_logo_lists_items_aggregated: Array; + company_logo_lists_items_by_id?: Maybe; company_logos: Array; company_logos_aggregated: Array; company_logos_by_id?: Maybe; @@ -63,7 +75,18 @@ export type Query = { nav_list_aggregated: Array; nav_list_by_id?: Maybe; page_community?: Maybe; + page_homepage?: Maybe; page_legal?: Maybe; + page_product?: Maybe; + quote_lists: Array; + quote_lists_aggregated: Array; + quote_lists_by_id?: Maybe; + quote_lists_items: Array; + quote_lists_items_aggregated: Array; + quote_lists_items_by_id?: Maybe; + quotes: Array; + quotes_aggregated: Array; + quotes_by_id?: Maybe; site_settings?: Maybe; solutions_pages: Array; solutions_pages_aggregated: Array; @@ -104,6 +127,32 @@ export type QueryApps_By_IdArgs = { }; +export type QueryArticle_CardsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryArticle_Cards_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryArticle_Cards_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryCalloutsArgs = { filter?: InputMaybe; limit?: InputMaybe; @@ -182,6 +231,32 @@ export type QueryCollapsible_Lists_By_IdArgs = { }; +export type QueryCollapsible_Lists_ItemsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCollapsible_Lists_Items_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCollapsible_Lists_Items_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryCollapsiblesArgs = { filter?: InputMaybe; limit?: InputMaybe; @@ -208,6 +283,58 @@ export type QueryCollapsibles_By_IdArgs = { }; +export type QueryCompany_Logo_ListsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCompany_Logo_Lists_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCompany_Logo_Lists_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + +export type QueryCompany_Logo_Lists_ItemsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCompany_Logo_Lists_Items_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryCompany_Logo_Lists_Items_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + export type QueryCompany_LogosArgs = { filter?: InputMaybe; limit?: InputMaybe; @@ -390,6 +517,84 @@ export type QueryNav_List_By_IdArgs = { }; +export type QueryQuote_ListsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuote_Lists_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuote_Lists_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + +export type QueryQuote_Lists_ItemsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuote_Lists_Items_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuote_Lists_Items_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + +export type QueryQuotesArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuotes_AggregatedArgs = { + filter?: InputMaybe; + groupBy?: InputMaybe>>; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type QueryQuotes_By_IdArgs = { + id: Scalars['ID']['input']; +}; + + export type QuerySolutions_PagesArgs = { filter?: InputMaybe; limit?: InputMaybe; @@ -473,6 +678,7 @@ export type App_Defaults = { date_updated?: Maybe; date_updated_func?: Maybe; id: Scalars['ID']['output']; + quotes?: Maybe; user_updated?: Maybe; }; @@ -486,6 +692,16 @@ export type App_DefaultsCase_StudyArgs = { sort?: InputMaybe>>; }; + +export type App_DefaultsQuotesArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + export type Apps = { __typename?: 'apps'; case_study?: Maybe; @@ -551,6 +767,116 @@ export type Apps_Filter = { user_updated?: InputMaybe; }; +export type Article_Cards = { + __typename?: 'article_cards'; + article_card_id?: Maybe; + author?: Maybe; + ctas?: Maybe; + ctas_func?: Maybe; + date?: Maybe; + date_created?: Maybe; + date_created_func?: Maybe; + date_func?: Maybe; + date_updated?: Maybe; + date_updated_func?: Maybe; + description?: Maybe; + heading?: Maybe; + id: Scalars['ID']['output']; + sort?: Maybe; + status?: Maybe; + thumbnail?: Maybe; + url?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; + videoUrl?: Maybe; +}; + + +export type Article_CardsArticle_Card_IdArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type Article_CardsThumbnailArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Article_Cards_Aggregated = { + __typename?: 'article_cards_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Article_Cards_Aggregated_Count = { + __typename?: 'article_cards_aggregated_count'; + article_card_id?: Maybe; + author?: Maybe; + ctas?: Maybe; + date?: Maybe; + date_created?: Maybe; + date_updated?: Maybe; + description?: Maybe; + heading?: Maybe; + id?: Maybe; + sort?: Maybe; + status?: Maybe; + thumbnail?: Maybe; + url?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; + videoUrl?: Maybe; +}; + +export type Article_Cards_Aggregated_Fields = { + __typename?: 'article_cards_aggregated_fields'; + article_card_id?: Maybe; + id?: Maybe; + sort?: Maybe; +}; + +export type Article_Cards_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + article_card_id?: InputMaybe; + author?: InputMaybe; + ctas?: InputMaybe; + ctas_func?: InputMaybe; + date?: InputMaybe; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; + description?: InputMaybe; + heading?: InputMaybe; + id?: InputMaybe; + sort?: InputMaybe; + status?: InputMaybe; + thumbnail?: InputMaybe; + url?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; + videoUrl?: InputMaybe; +}; + export type Boolean_Filter_Operators = { _eq?: InputMaybe; _neq?: InputMaybe; @@ -708,7 +1034,7 @@ export type Collapsible_Lists = { date_updated?: Maybe; date_updated_func?: Maybe; id: Scalars['ID']['output']; - items?: Maybe>>; + items?: Maybe>>; items_func?: Maybe; slug: Scalars['String']['output']; status?: Maybe; @@ -718,7 +1044,7 @@ export type Collapsible_Lists = { export type Collapsible_ListsItemsArgs = { - filter?: InputMaybe; + filter?: InputMaybe; limit?: InputMaybe; offset?: InputMaybe; page?: InputMaybe; @@ -765,7 +1091,7 @@ export type Collapsible_Lists_Filter = { date_updated?: InputMaybe; date_updated_func?: InputMaybe; id?: InputMaybe; - items?: InputMaybe; + items?: InputMaybe; items_func?: InputMaybe; slug?: InputMaybe; status?: InputMaybe; @@ -773,6 +1099,67 @@ export type Collapsible_Lists_Filter = { user_updated?: InputMaybe; }; +export type Collapsible_Lists_Items = { + __typename?: 'collapsible_lists_items'; + collapsible_lists_id?: Maybe; + collection?: Maybe; + id: Scalars['ID']['output']; + item?: Maybe; + sort?: Maybe; +}; + + +export type Collapsible_Lists_ItemsCollapsible_Lists_IdArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Collapsible_Lists_Items_Aggregated = { + __typename?: 'collapsible_lists_items_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Collapsible_Lists_Items_Aggregated_Count = { + __typename?: 'collapsible_lists_items_aggregated_count'; + collapsible_lists_id?: Maybe; + collection?: Maybe; + id?: Maybe; + item?: Maybe; + sort?: Maybe; +}; + +export type Collapsible_Lists_Items_Aggregated_Fields = { + __typename?: 'collapsible_lists_items_aggregated_fields'; + collapsible_lists_id?: Maybe; + id?: Maybe; + sort?: Maybe; +}; + +export type Collapsible_Lists_Items_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + collapsible_lists_id?: InputMaybe; + collection?: InputMaybe; + id?: InputMaybe; + item__collapsibles?: InputMaybe; + sort?: InputMaybe; +}; + +export type Collapsible_Lists_Items_Item_Union = Collapsibles; + export type Collapsibles = { __typename?: 'collapsibles'; collapsible_id?: Maybe; @@ -854,20 +1241,168 @@ export type Collapsibles_Filter = { user_updated?: InputMaybe; }; -export type Company_Logos = { - __typename?: 'company_logos'; - date_updated?: Maybe; +export type Company_Logo_Lists = { + __typename?: 'company_logo_lists'; + date_created?: Maybe; + date_created_func?: Maybe; + date_updated?: Maybe; date_updated_func?: Maybe; id: Scalars['ID']['output']; - logo?: Maybe; - name: Scalars['String']['output']; + items?: Maybe>>; + items_func?: Maybe; slug?: Maybe; sort?: Maybe; + status?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + + +export type Company_Logo_ListsItemsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Company_Logo_Lists_Aggregated = { + __typename?: 'company_logo_lists_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Company_Logo_Lists_Aggregated_Count = { + __typename?: 'company_logo_lists_aggregated_count'; + date_created?: Maybe; + date_updated?: Maybe; + id?: Maybe; + items?: Maybe; + slug?: Maybe; + sort?: Maybe; + status?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + +export type Company_Logo_Lists_Aggregated_Fields = { + __typename?: 'company_logo_lists_aggregated_fields'; + id?: Maybe; + sort?: Maybe; +}; + +export type Company_Logo_Lists_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; + id?: InputMaybe; + items?: InputMaybe; + items_func?: InputMaybe; + slug?: InputMaybe; + sort?: InputMaybe; + status?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; +}; + +export type Company_Logo_Lists_Items = { + __typename?: 'company_logo_lists_items'; + collection?: Maybe; + company_logo_lists_id?: Maybe; + id: Scalars['ID']['output']; + item?: Maybe; + sort?: Maybe; +}; + + +export type Company_Logo_Lists_ItemsCompany_Logo_Lists_IdArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Company_Logo_Lists_Items_Aggregated = { + __typename?: 'company_logo_lists_items_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Company_Logo_Lists_Items_Aggregated_Count = { + __typename?: 'company_logo_lists_items_aggregated_count'; + collection?: Maybe; + company_logo_lists_id?: Maybe; + id?: Maybe; + item?: Maybe; + sort?: Maybe; +}; + +export type Company_Logo_Lists_Items_Aggregated_Fields = { + __typename?: 'company_logo_lists_items_aggregated_fields'; + company_logo_lists_id?: Maybe; + id?: Maybe; + sort?: Maybe; +}; + +export type Company_Logo_Lists_Items_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + collection?: InputMaybe; + company_logo_lists_id?: InputMaybe; + id?: InputMaybe; + item__company_logos?: InputMaybe; + sort?: InputMaybe; +}; + +export type Company_Logo_Lists_Items_Item_Union = Company_Logos; + +export type Company_Logos = { + __typename?: 'company_logos'; + date_updated?: Maybe; + date_updated_func?: Maybe; + id: Scalars['ID']['output']; + logo_dark?: Maybe; + logo_light?: Maybe; + name: Scalars['String']['output']; + slug?: Maybe; url?: Maybe; + width?: Maybe; +}; + + +export type Company_LogosLogo_DarkArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; }; -export type Company_LogosLogoArgs = { +export type Company_LogosLogo_LightArgs = { filter?: InputMaybe; limit?: InputMaybe; offset?: InputMaybe; @@ -894,17 +1429,18 @@ export type Company_Logos_Aggregated_Count = { __typename?: 'company_logos_aggregated_count'; date_updated?: Maybe; id?: Maybe; - logo?: Maybe; + logo_dark?: Maybe; + logo_light?: Maybe; name?: Maybe; slug?: Maybe; - sort?: Maybe; url?: Maybe; + width?: Maybe; }; export type Company_Logos_Aggregated_Fields = { __typename?: 'company_logos_aggregated_fields'; id?: Maybe; - sort?: Maybe; + width?: Maybe; }; export type Company_Logos_Filter = { @@ -913,11 +1449,12 @@ export type Company_Logos_Filter = { date_updated?: InputMaybe; date_updated_func?: InputMaybe; id?: InputMaybe; - logo?: InputMaybe; + logo_dark?: InputMaybe; + logo_light?: InputMaybe; name?: InputMaybe; slug?: InputMaybe; - sort?: InputMaybe; url?: InputMaybe; + width?: InputMaybe; }; export type Count_Function_Filter_Operators = { @@ -944,6 +1481,23 @@ export type Date_Filter_Operators = { _null?: InputMaybe; }; +export type Date_Function_Filter_Operators = { + day?: InputMaybe; + month?: InputMaybe; + week?: InputMaybe; + weekday?: InputMaybe; + year?: InputMaybe; +}; + +export type Date_Functions = { + __typename?: 'date_functions'; + day?: Maybe; + month?: Maybe; + week?: Maybe; + weekday?: Maybe; + year?: Maybe; +}; + export type Datetime_Function_Filter_Operators = { day?: InputMaybe; hour?: InputMaybe; @@ -990,7 +1544,6 @@ export type Directus_Files = { tags_func?: Maybe; title?: Maybe; type?: Maybe; - uploaded_by?: Maybe; uploaded_on?: Maybe; uploaded_on_func?: Maybe; width?: Maybe; @@ -1020,7 +1573,6 @@ export type Directus_Files_Filter = { tags_func?: InputMaybe; title?: InputMaybe; type?: InputMaybe; - uploaded_by?: InputMaybe; uploaded_on?: InputMaybe; uploaded_on_func?: InputMaybe; width?: InputMaybe; @@ -1396,64 +1948,335 @@ export type Nav_List_Aggregated_Count = { __typename?: 'nav_list_aggregated_count'; flatten?: Maybe; id?: Maybe; - link?: Maybe; - mobile_only?: Maybe; - parent_nav_list_id?: Maybe; - slug?: Maybe; + link?: Maybe; + mobile_only?: Maybe; + parent_nav_list_id?: Maybe; + slug?: Maybe; + sort?: Maybe; + subnav?: Maybe; +}; + +export type Nav_List_Aggregated_Fields = { + __typename?: 'nav_list_aggregated_fields'; + sort?: Maybe; +}; + +export type Nav_List_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + flatten?: InputMaybe; + id?: InputMaybe; + link?: InputMaybe; + mobile_only?: InputMaybe; + parent_nav_list_id?: InputMaybe; + slug?: InputMaybe; + sort?: InputMaybe; + subnav?: InputMaybe; + subnav_func?: InputMaybe; +}; + +export type Number_Filter_Operators = { + _between?: InputMaybe>>; + _eq?: InputMaybe; + _gt?: InputMaybe; + _gte?: InputMaybe; + _in?: InputMaybe>>; + _lt?: InputMaybe; + _lte?: InputMaybe; + _nbetween?: InputMaybe>>; + _neq?: InputMaybe; + _nin?: InputMaybe>>; + _nnull?: InputMaybe; + _null?: InputMaybe; +}; + +export type Page_Community = { + __typename?: 'page_community'; + callouts?: Maybe>>; + callouts_func?: Maybe; + date_created?: Maybe; + date_created_func?: Maybe; + date_updated?: Maybe; + date_updated_func?: Maybe; + id: Scalars['ID']['output']; + user_created?: Maybe; + user_updated?: Maybe; +}; + + +export type Page_CommunityCalloutsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Page_Community_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + callouts?: InputMaybe; + callouts_func?: InputMaybe; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; + id?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; +}; + +export type Page_Homepage = { + __typename?: 'page_homepage'; + article_cards?: Maybe>>; + article_cards_func?: Maybe; + date_created?: Maybe; + date_created_func?: Maybe; + date_updated?: Maybe; + date_updated_func?: Maybe; + id: Scalars['ID']['output']; + quotes?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + + +export type Page_HomepageArticle_CardsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type Page_HomepageQuotesArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Page_Homepage_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + article_cards?: InputMaybe; + article_cards_func?: InputMaybe; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; + id?: InputMaybe; + quotes?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; +}; + +export type Page_Legal = { + __typename?: 'page_legal'; + id: Scalars['ID']['output']; + pages?: Maybe>>; + pages_func?: Maybe; +}; + + +export type Page_LegalPagesArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Page_Legal_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + id?: InputMaybe; + pages?: InputMaybe; + pages_func?: InputMaybe; +}; + +export type Page_Product = { + __typename?: 'page_product'; + date_created?: Maybe; + date_created_func?: Maybe; + date_updated?: Maybe; + date_updated_func?: Maybe; + faq?: Maybe; + featured_quote?: Maybe; + id: Scalars['ID']['output']; + user_created?: Maybe; + user_updated?: Maybe; +}; + + +export type Page_ProductFaqArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + +export type Page_ProductFeatured_QuoteArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Quote_Lists = { + __typename?: 'quote_lists'; + date_created?: Maybe; + date_created_func?: Maybe; + date_updated?: Maybe; + date_updated_func?: Maybe; + id: Scalars['ID']['output']; + items?: Maybe>>; + items_func?: Maybe; + slug: Scalars['String']['output']; + status?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + + +export type Quote_ListsItemsArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Quote_Lists_Aggregated = { + __typename?: 'quote_lists_aggregated'; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; +}; + +export type Quote_Lists_Aggregated_Count = { + __typename?: 'quote_lists_aggregated_count'; + date_created?: Maybe; + date_updated?: Maybe; + id?: Maybe; + items?: Maybe; + slug?: Maybe; + status?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + +export type Quote_Lists_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; + id?: InputMaybe; + items?: InputMaybe; + items_func?: InputMaybe; + slug?: InputMaybe; + status?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; +}; + +export type Quote_Lists_Items = { + __typename?: 'quote_lists_items'; + collection?: Maybe; + id: Scalars['ID']['output']; + item?: Maybe; + quote_lists_id?: Maybe; + sort?: Maybe; +}; + + +export type Quote_Lists_ItemsQuote_Lists_IdArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type Quote_Lists_Items_Aggregated = { + __typename?: 'quote_lists_items_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Quote_Lists_Items_Aggregated_Count = { + __typename?: 'quote_lists_items_aggregated_count'; + collection?: Maybe; + id?: Maybe; + item?: Maybe; + quote_lists_id?: Maybe; sort?: Maybe; - subnav?: Maybe; }; -export type Nav_List_Aggregated_Fields = { - __typename?: 'nav_list_aggregated_fields'; +export type Quote_Lists_Items_Aggregated_Fields = { + __typename?: 'quote_lists_items_aggregated_fields'; + id?: Maybe; sort?: Maybe; }; -export type Nav_List_Filter = { - _and?: InputMaybe>>; - _or?: InputMaybe>>; - flatten?: InputMaybe; - id?: InputMaybe; - link?: InputMaybe; - mobile_only?: InputMaybe; - parent_nav_list_id?: InputMaybe; - slug?: InputMaybe; +export type Quote_Lists_Items_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + collection?: InputMaybe; + id?: InputMaybe; + item__quotes?: InputMaybe; + quote_lists_id?: InputMaybe; sort?: InputMaybe; - subnav?: InputMaybe; - subnav_func?: InputMaybe; }; -export type Number_Filter_Operators = { - _between?: InputMaybe>>; - _eq?: InputMaybe; - _gt?: InputMaybe; - _gte?: InputMaybe; - _in?: InputMaybe>>; - _lt?: InputMaybe; - _lte?: InputMaybe; - _nbetween?: InputMaybe>>; - _neq?: InputMaybe; - _nin?: InputMaybe>>; - _nnull?: InputMaybe; - _null?: InputMaybe; -}; +export type Quote_Lists_Items_Item_Union = Quotes; -export type Page_Community = { - __typename?: 'page_community'; - callouts?: Maybe>>; - callouts_func?: Maybe; +export type Quotes = { + __typename?: 'quotes'; + company?: Maybe; date_created?: Maybe; date_created_func?: Maybe; date_updated?: Maybe; date_updated_func?: Maybe; id: Scalars['ID']['output']; + logo?: Maybe; + name?: Maybe; + portrait?: Maybe; + quote?: Maybe; + quote_id?: Maybe; + status?: Maybe; + title?: Maybe; user_created?: Maybe; user_updated?: Maybe; }; -export type Page_CommunityCalloutsArgs = { - filter?: InputMaybe; +export type QuotesLogoArgs = { + filter?: InputMaybe; limit?: InputMaybe; offset?: InputMaybe; page?: InputMaybe; @@ -1461,30 +2284,19 @@ export type Page_CommunityCalloutsArgs = { sort?: InputMaybe>>; }; -export type Page_Community_Filter = { - _and?: InputMaybe>>; - _or?: InputMaybe>>; - callouts?: InputMaybe; - callouts_func?: InputMaybe; - date_created?: InputMaybe; - date_created_func?: InputMaybe; - date_updated?: InputMaybe; - date_updated_func?: InputMaybe; - id?: InputMaybe; - user_created?: InputMaybe; - user_updated?: InputMaybe; -}; -export type Page_Legal = { - __typename?: 'page_legal'; - id: Scalars['ID']['output']; - pages?: Maybe>>; - pages_func?: Maybe; +export type QuotesPortraitArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; }; -export type Page_LegalPagesArgs = { - filter?: InputMaybe; +export type QuotesQuote_IdArgs = { + filter?: InputMaybe; limit?: InputMaybe; offset?: InputMaybe; page?: InputMaybe; @@ -1492,12 +2304,60 @@ export type Page_LegalPagesArgs = { sort?: InputMaybe>>; }; -export type Page_Legal_Filter = { - _and?: InputMaybe>>; - _or?: InputMaybe>>; +export type Quotes_Aggregated = { + __typename?: 'quotes_aggregated'; + avg?: Maybe; + avgDistinct?: Maybe; + count?: Maybe; + countAll?: Maybe; + countDistinct?: Maybe; + group?: Maybe; + max?: Maybe; + min?: Maybe; + sum?: Maybe; + sumDistinct?: Maybe; +}; + +export type Quotes_Aggregated_Count = { + __typename?: 'quotes_aggregated_count'; + company?: Maybe; + date_created?: Maybe; + date_updated?: Maybe; + id?: Maybe; + logo?: Maybe; + name?: Maybe; + portrait?: Maybe; + quote?: Maybe; + quote_id?: Maybe; + status?: Maybe; + title?: Maybe; + user_created?: Maybe; + user_updated?: Maybe; +}; + +export type Quotes_Aggregated_Fields = { + __typename?: 'quotes_aggregated_fields'; + id?: Maybe; +}; + +export type Quotes_Filter = { + _and?: InputMaybe>>; + _or?: InputMaybe>>; + company?: InputMaybe; + date_created?: InputMaybe; + date_created_func?: InputMaybe; + date_updated?: InputMaybe; + date_updated_func?: InputMaybe; id?: InputMaybe; - pages?: InputMaybe; - pages_func?: InputMaybe; + logo?: InputMaybe; + name?: InputMaybe; + portrait?: InputMaybe; + quote?: InputMaybe; + quote_id?: InputMaybe; + status?: InputMaybe; + title?: InputMaybe; + user_created?: InputMaybe; + user_updated?: InputMaybe; }; export type Site_Settings = { @@ -1508,6 +2368,7 @@ export type Site_Settings = { main_nav?: Maybe; og_description?: Maybe; og_image?: Maybe; + partner_logos?: Maybe; user_updated?: Maybe; }; @@ -1531,6 +2392,16 @@ export type Site_SettingsOg_ImageArgs = { sort?: InputMaybe>>; }; + +export type Site_SettingsPartner_LogosArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + export type Solutions_Pages = { __typename?: 'solutions_pages'; bullet_points?: Maybe; @@ -1541,6 +2412,7 @@ export type Solutions_Pages = { date_updated?: Maybe; date_updated_func?: Maybe; description?: Maybe; + featured_quote?: Maybe; heading_1?: Maybe; heading_2?: Maybe; hero_image?: Maybe; @@ -1561,6 +2433,16 @@ export type Solutions_PagesCase_StudyArgs = { }; +export type Solutions_PagesFeatured_QuoteArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + + export type Solutions_PagesHero_ImageArgs = { filter?: InputMaybe; limit?: InputMaybe; @@ -1592,6 +2474,7 @@ export type Solutions_Pages_Aggregated_Count = { content_2?: Maybe; date_updated?: Maybe; description?: Maybe; + featured_quote?: Maybe; heading_1?: Maybe; heading_2?: Maybe; hero_image?: Maybe; @@ -1604,6 +2487,7 @@ export type Solutions_Pages_Aggregated_Count = { export type Solutions_Pages_Aggregated_Fields = { __typename?: 'solutions_pages_aggregated_fields'; case_study?: Maybe; + featured_quote?: Maybe; id?: Maybe; sort?: Maybe; }; @@ -1619,6 +2503,7 @@ export type Solutions_Pages_Filter = { date_updated?: InputMaybe; date_updated_func?: InputMaybe; description?: InputMaybe; + featured_quote?: InputMaybe; heading_1?: InputMaybe; heading_2?: InputMaybe; hero_image?: InputMaybe; @@ -1634,6 +2519,7 @@ export type Stack_Defaults = { date_updated?: Maybe; date_updated_func?: Maybe; id: Scalars['ID']['output']; + quotes?: Maybe; user_updated?: Maybe; }; @@ -1647,6 +2533,16 @@ export type Stack_DefaultsCase_StudyArgs = { sort?: InputMaybe>>; }; + +export type Stack_DefaultsQuotesArgs = { + filter?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + page?: InputMaybe; + search?: InputMaybe; + sort?: InputMaybe>>; +}; + export type Stacks = { __typename?: 'stacks'; case_study?: Maybe; @@ -1812,36 +2708,40 @@ export type NavListFragment = { __typename?: 'nav_list', id: string, flatten?: b export type NavListDepth3Fragment = { __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null }; -export type SiteSettingsFragment = { __typename?: 'site_settings', og_description?: string | null, main_nav?: { __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null, og_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; +export type CompanyLogoFragment = { __typename?: 'company_logos', slug?: string | null, name: string, url?: string | null, width?: number | null, logo_light?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo_dark?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; + +export type LogoListFragment = { __typename?: 'company_logo_lists', slug?: string | null, items?: Array<{ __typename?: 'company_logo_lists_items', item?: { __typename?: 'company_logos', slug?: string | null, name: string, url?: string | null, width?: number | null, logo_light?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo_dark?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null }; + +export type SiteSettingsFragment = { __typename?: 'site_settings', og_description?: string | null, main_nav?: { __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null, og_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, partner_logos?: { __typename?: 'company_logo_lists', slug?: string | null, items?: Array<{ __typename?: 'company_logo_lists_items', item?: { __typename?: 'company_logos', slug?: string | null, name: string, url?: string | null, width?: number | null, logo_light?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo_dark?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null }; export type SiteSettingsQueryVariables = Exact<{ [key: string]: never; }>; -export type SiteSettingsQuery = { __typename?: 'Query', site_settings?: { __typename?: 'site_settings', og_description?: string | null, main_nav?: { __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null, og_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; +export type SiteSettingsQuery = { __typename?: 'Query', site_settings?: { __typename?: 'site_settings', og_description?: string | null, main_nav?: { __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, subnav?: Array<{ __typename?: 'nav_list', id: string, flatten?: boolean | null, mobile_only?: boolean | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null> | null, link?: { __typename?: 'nav_link', id: string, title?: string | null, url?: string | null } | null } | null, og_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, partner_logos?: { __typename?: 'company_logo_lists', slug?: string | null, items?: Array<{ __typename?: 'company_logo_lists_items', item?: { __typename?: 'company_logos', slug?: string | null, name: string, url?: string | null, width?: number | null, logo_light?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo_dark?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null } | null }; -export type FeaturedArticleFragment = { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; +export type CaseStudyFragment = { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; export type AppExtrasFragment = { __typename?: 'apps', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; -export type AppDefaultsFragment = { __typename?: 'app_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; +export type AppDefaultsFragment = { __typename?: 'app_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null }; export type AppExtrasQueryVariables = Exact<{ name?: InputMaybe; }>; -export type AppExtrasQuery = { __typename?: 'Query', apps: Array<{ __typename?: 'apps', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }>, app_defaults?: { __typename?: 'app_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null }; +export type AppExtrasQuery = { __typename?: 'Query', apps: Array<{ __typename?: 'apps', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }>, app_defaults?: { __typename?: 'app_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null } | null }; export type StackExtrasFragment = { __typename?: 'stacks', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; -export type StackDefaultsFragment = { __typename?: 'stack_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; +export type StackDefaultsFragment = { __typename?: 'stack_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null }; export type StackExtrasQueryVariables = Exact<{ name?: InputMaybe; }>; -export type StackExtrasQuery = { __typename?: 'Query', stacks: Array<{ __typename?: 'stacks', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }>, stack_defaults?: { __typename?: 'stack_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null }; +export type StackExtrasQuery = { __typename?: 'Query', stacks: Array<{ __typename?: 'stacks', name?: string | null, heroVideo?: string | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }>, stack_defaults?: { __typename?: 'stack_defaults', case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null } | null }; export type ImageFileFragment = { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null }; @@ -1861,16 +2761,16 @@ export type FeaturedContributorsQuery = { __typename?: 'Query', featured_contrib export type FaqItemFragment = { __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null }; -export type FaqListFragment = { __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null> | null }; +export type FaqListFragment = { __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsible_lists_items', item?: { __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null } | null> | null }; export type FaqListQueryVariables = Exact<{ slug?: InputMaybe; }>; -export type FaqListQuery = { __typename?: 'Query', collapsible_lists: Array<{ __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null> | null }> }; +export type FaqListQuery = { __typename?: 'Query', collapsible_lists: Array<{ __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsible_lists_items', item?: { __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null } | null> | null }> }; -export type SolutionFragment = { __typename?: 'solutions_pages', id: string, slug: string, title?: string | null, description?: string | null, heading_1?: string | null, content_1?: string | null, heading_2?: string | null, content_2?: string | null, bullet_points?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; +export type SolutionFragment = { __typename?: 'solutions_pages', id: string, slug: string, title?: string | null, description?: string | null, heading_1?: string | null, content_1?: string | null, heading_2?: string | null, content_2?: string | null, bullet_points?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, featured_quote?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }; export type SolutionsSlugsQueryVariables = Exact<{ [key: string]: never; }>; @@ -1882,7 +2782,7 @@ export type SolutionsQueryVariables = Exact<{ }>; -export type SolutionsQuery = { __typename?: 'Query', solutions_pages: Array<{ __typename?: 'solutions_pages', id: string, slug: string, title?: string | null, description?: string | null, heading_1?: string | null, content_1?: string | null, heading_2?: string | null, content_2?: string | null, bullet_points?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }> }; +export type SolutionsQuery = { __typename?: 'Query', solutions_pages: Array<{ __typename?: 'solutions_pages', id: string, slug: string, title?: string | null, description?: string | null, heading_1?: string | null, content_1?: string | null, heading_2?: string | null, content_2?: string | null, bullet_points?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, case_study?: { __typename?: 'case_studies', id: string, slug?: string | null, label?: string | null, title?: string | null, content?: string | null, ctas?: any | null, stack_label?: string | null, stack_apps?: any | null, hero_image?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, featured_quote?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null }> }; export type MinJobListingFragment = { __typename?: 'job_listings', id: string, slug: string, job_title?: string | null, department?: string | null, tags?: any | null, location?: string | null }; @@ -1914,6 +2814,13 @@ export type PageCommunityQueryVariables = Exact<{ [key: string]: never; }>; export type PageCommunityQuery = { __typename?: 'Query', page_community?: { __typename?: 'page_community', callouts?: Array<{ __typename?: 'callouts', id: string, sort?: number | null, category?: string | null, title?: string | null, content?: string | null, ctas?: any | null } | null> | null } | null }; +export type PageProductFragment = { __typename?: 'page_product', featured_quote?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, faq?: { __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsible_lists_items', item?: { __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null } | null> | null } | null }; + +export type PageProductQueryVariables = Exact<{ [key: string]: never; }>; + + +export type PageProductQuery = { __typename?: 'Query', page_product?: { __typename?: 'page_product', featured_quote?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null, faq?: { __typename?: 'collapsible_lists', items?: Array<{ __typename?: 'collapsible_lists_items', item?: { __typename?: 'collapsibles', id: string, label?: string | null, content?: string | null } | null } | null> | null } | null } | null }; + export type MarkdownPageFragment = { __typename?: 'markdown_pages', id: string, slug?: string | null, title?: string | null, subtitle?: string | null, content?: string | null }; export type PageLegalFragment = { __typename?: 'page_legal', pages?: Array<{ __typename?: 'markdown_pages', id: string, slug?: string | null, title?: string | null, subtitle?: string | null, content?: string | null } | null> | null }; @@ -1928,6 +2835,19 @@ export type LegalPageSlugsQueryVariables = Exact<{ [key: string]: never; }>; export type LegalPageSlugsQuery = { __typename?: 'Query', page_legal?: { __typename?: 'page_legal', pages?: Array<{ __typename?: 'markdown_pages', slug?: string | null } | null> | null } | null }; +export type ArticleCardFragment = { __typename?: 'article_cards', heading?: string | null, description?: string | null, videoUrl?: string | null, date?: any | null, author?: string | null, ctas?: any | null, url?: string | null, thumbnail?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; + +export type PageHomepageFragment = { __typename?: 'page_homepage', quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null, article_cards?: Array<{ __typename?: 'article_cards', heading?: string | null, description?: string | null, videoUrl?: string | null, date?: any | null, author?: string | null, ctas?: any | null, url?: string | null, thumbnail?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null> | null }; + +export type PageHomepageQueryVariables = Exact<{ [key: string]: never; }>; + + +export type PageHomepageQuery = { __typename?: 'Query', page_homepage?: { __typename?: 'page_homepage', quotes?: { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null } | null, article_cards?: Array<{ __typename?: 'article_cards', heading?: string | null, description?: string | null, videoUrl?: string | null, date?: any | null, author?: string | null, ctas?: any | null, url?: string | null, thumbnail?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null> | null } | null }; + +export type QuoteFragment = { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null }; + +export type QuoteListFragment = { __typename?: 'quote_lists', slug: string, items?: Array<{ __typename?: 'quote_lists_items', item?: { __typename?: 'quotes', id: string, quote?: string | null, name?: string | null, title?: string | null, company?: string | null, portrait?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null, logo?: { __typename?: 'directus_files', id: string, title?: string | null, description?: string | null, tags?: any | null, filename_disk?: string | null, filename_download: string, metadata?: any | null, type?: string | null, filesize?: any | null } | null } | null } | null> | null }; + export const EventFragmentDoc = gql` fragment Event on events { id @@ -1983,6 +2903,30 @@ export const ImageFileFragmentDoc = gql` filesize } `; +export const CompanyLogoFragmentDoc = gql` + fragment CompanyLogo on company_logos { + slug + name + logo_light { + ...ImageFile + } + logo_dark { + ...ImageFile + } + url + width +} + ${ImageFileFragmentDoc}`; +export const LogoListFragmentDoc = gql` + fragment LogoList on company_logo_lists { + slug + items { + item { + ...CompanyLogo + } + } +} + ${CompanyLogoFragmentDoc}`; export const SiteSettingsFragmentDoc = gql` fragment SiteSettings on site_settings { main_nav(sort: ["sort"]) { @@ -1992,11 +2936,15 @@ export const SiteSettingsFragmentDoc = gql` og_image { ...ImageFile } + partner_logos { + ...LogoList + } } ${NavListDepth3FragmentDoc} -${ImageFileFragmentDoc}`; -export const FeaturedArticleFragmentDoc = gql` - fragment FeaturedArticle on case_studies { +${ImageFileFragmentDoc} +${LogoListFragmentDoc}`; +export const CaseStudyFragmentDoc = gql` + fragment CaseStudy on case_studies { id slug label @@ -2015,33 +2963,66 @@ export const AppExtrasFragmentDoc = gql` name heroVideo case_study { - ...FeaturedArticle + ...CaseStudy + } +} + ${CaseStudyFragmentDoc}`; +export const QuoteFragmentDoc = gql` + fragment Quote on quotes { + id + quote + name + title + company + portrait { + ...ImageFile + } + logo { + ...ImageFile + } +} + ${ImageFileFragmentDoc}`; +export const QuoteListFragmentDoc = gql` + fragment QuoteList on quote_lists { + slug + items { + item { + ...Quote + } } } - ${FeaturedArticleFragmentDoc}`; + ${QuoteFragmentDoc}`; export const AppDefaultsFragmentDoc = gql` fragment AppDefaults on app_defaults { case_study { - ...FeaturedArticle + ...CaseStudy + } + quotes { + ...QuoteList } } - ${FeaturedArticleFragmentDoc}`; + ${CaseStudyFragmentDoc} +${QuoteListFragmentDoc}`; export const StackExtrasFragmentDoc = gql` fragment StackExtras on stacks { name heroVideo case_study { - ...FeaturedArticle + ...CaseStudy } } - ${FeaturedArticleFragmentDoc}`; + ${CaseStudyFragmentDoc}`; export const StackDefaultsFragmentDoc = gql` fragment StackDefaults on stack_defaults { case_study { - ...FeaturedArticle + ...CaseStudy + } + quotes { + ...QuoteList } } - ${FeaturedArticleFragmentDoc}`; + ${CaseStudyFragmentDoc} +${QuoteListFragmentDoc}`; export const TeamMemberFragmentDoc = gql` fragment TeamMember on team_members { id @@ -2069,20 +3050,6 @@ export const FeaturedContributorFragmentDoc = gql` ctas } ${ImageFileFragmentDoc}`; -export const FaqItemFragmentDoc = gql` - fragment FaqItem on collapsibles { - id - label - content -} - `; -export const FaqListFragmentDoc = gql` - fragment FaqList on collapsible_lists { - items { - ...FaqItem - } -} - ${FaqItemFragmentDoc}`; export const SolutionFragmentDoc = gql` fragment Solution on solutions_pages { id @@ -2097,12 +3064,16 @@ export const SolutionFragmentDoc = gql` ...ImageFile } case_study { - ...FeaturedArticle + ...CaseStudy } bullet_points + featured_quote { + ...Quote + } } ${ImageFileFragmentDoc} -${FeaturedArticleFragmentDoc}`; +${CaseStudyFragmentDoc} +${QuoteFragmentDoc}`; export const MinJobListingFragmentDoc = gql` fragment MinJobListing on job_listings { id @@ -2136,6 +3107,33 @@ export const PageCommunityFragmentDoc = gql` } } ${CalloutFragmentDoc}`; +export const FaqItemFragmentDoc = gql` + fragment FaqItem on collapsibles { + id + label + content +} + `; +export const FaqListFragmentDoc = gql` + fragment FaqList on collapsible_lists { + items { + item { + ...FaqItem + } + } +} + ${FaqItemFragmentDoc}`; +export const PageProductFragmentDoc = gql` + fragment PageProduct on page_product { + featured_quote { + ...Quote + } + faq { + ...FaqList + } +} + ${QuoteFragmentDoc} +${FaqListFragmentDoc}`; export const MarkdownPageFragmentDoc = gql` fragment MarkdownPage on markdown_pages { id @@ -2152,6 +3150,31 @@ export const PageLegalFragmentDoc = gql` } } ${MarkdownPageFragmentDoc}`; +export const ArticleCardFragmentDoc = gql` + fragment ArticleCard on article_cards { + heading + description + thumbnail { + ...ImageFile + } + videoUrl + date + author + ctas + url +} + ${ImageFileFragmentDoc}`; +export const PageHomepageFragmentDoc = gql` + fragment PageHomepage on page_homepage { + quotes { + ...QuoteList + } + article_cards { + ...ArticleCard + } +} + ${QuoteListFragmentDoc} +${ArticleCardFragmentDoc}`; export const EventsDocument = gql` query Events { events { @@ -2607,6 +3630,40 @@ export function usePageCommunityLazyQuery(baseOptions?: Apollo.LazyQueryHookOpti export type PageCommunityQueryHookResult = ReturnType; export type PageCommunityLazyQueryHookResult = ReturnType; export type PageCommunityQueryResult = Apollo.QueryResult; +export const PageProductDocument = gql` + query PageProduct { + page_product { + ...PageProduct + } +} + ${PageProductFragmentDoc}`; + +/** + * __usePageProductQuery__ + * + * To run a query within a React component, call `usePageProductQuery` and pass it any options that fit your needs. + * When your component renders, `usePageProductQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = usePageProductQuery({ + * variables: { + * }, + * }); + */ +export function usePageProductQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PageProductDocument, options); + } +export function usePageProductLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PageProductDocument, options); + } +export type PageProductQueryHookResult = ReturnType; +export type PageProductLazyQueryHookResult = ReturnType; +export type PageProductQueryResult = Apollo.QueryResult; export const PageLegalDocument = gql` query PageLegal { page_legal { @@ -2676,4 +3733,38 @@ export function useLegalPageSlugsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt } export type LegalPageSlugsQueryHookResult = ReturnType; export type LegalPageSlugsLazyQueryHookResult = ReturnType; -export type LegalPageSlugsQueryResult = Apollo.QueryResult; \ No newline at end of file +export type LegalPageSlugsQueryResult = Apollo.QueryResult; +export const PageHomepageDocument = gql` + query PageHomepage { + page_homepage { + ...PageHomepage + } +} + ${PageHomepageFragmentDoc}`; + +/** + * __usePageHomepageQuery__ + * + * To run a query within a React component, call `usePageHomepageQuery` and pass it any options that fit your needs. + * When your component renders, `usePageHomepageQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = usePageHomepageQuery({ + * variables: { + * }, + * }); + */ +export function usePageHomepageQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(PageHomepageDocument, options); + } +export function usePageHomepageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(PageHomepageDocument, options); + } +export type PageHomepageQueryHookResult = ReturnType; +export type PageHomepageLazyQueryHookResult = ReturnType; +export type PageHomepageQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/src/generated/graphqlDirectusSystem.ts b/src/generated/graphqlDirectusSystem.ts index 0e5477bd..988a35e8 100644 --- a/src/generated/graphqlDirectusSystem.ts +++ b/src/generated/graphqlDirectusSystem.ts @@ -314,7 +314,6 @@ export type Directus_Files = { tags_func?: Maybe; title?: Maybe; type?: Maybe; - uploaded_by?: Maybe; uploaded_on?: Maybe; uploaded_on_func?: Maybe; width?: Maybe; @@ -354,7 +353,6 @@ export type Directus_Files_Aggregated_Count = { tags?: Maybe; title?: Maybe; type?: Maybe; - uploaded_by?: Maybe; uploaded_on?: Maybe; width?: Maybe; }; @@ -391,7 +389,6 @@ export type Directus_Files_Filter = { tags_func?: InputMaybe; title?: InputMaybe; type?: InputMaybe; - uploaded_by?: InputMaybe; uploaded_on?: InputMaybe; uploaded_on_func?: InputMaybe; width?: InputMaybe; diff --git a/src/generated/graphqlPlural.ts b/src/generated/graphqlPlural.ts index 21907eac..c4a364a0 100644 --- a/src/generated/graphqlPlural.ts +++ b/src/generated/graphqlPlural.ts @@ -1365,6 +1365,7 @@ export type IntegrationWebhookEdge = { export type Invite = { __typename?: 'Invite'; account?: Maybe; + admin?: Maybe; email?: Maybe; existing: Scalars['Boolean']['output']; expiresAt?: Maybe; @@ -1377,6 +1378,7 @@ export type Invite = { }; export type InviteAttributes = { + admin?: InputMaybe; email?: InputMaybe; inviteGroups?: InputMaybe>>; }; @@ -1623,7 +1625,8 @@ export enum NotificationType { IncidentUpdate = 'INCIDENT_UPDATE', Locked = 'LOCKED', Mention = 'MENTION', - Message = 'MESSAGE' + Message = 'MESSAGE', + Pending = 'PENDING' } export type OauthAttributes = { @@ -5029,7 +5032,9 @@ export type RecipesQuery = { __typename?: 'RootQueryType', recipes?: { __typenam export type PublisherFragment = { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null }; -export type MinRepoFragment = { __typename?: 'Repository', category?: Category | null, darkIcon?: string | null, description?: string | null, icon?: string | null, id: string, name: string, private?: boolean | null, releaseStatus?: ReleaseStatus | null, trending?: boolean | null, verified?: boolean | null, homepage?: string | null, gitUrl?: string | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null } | null, tags?: Array<{ __typename?: 'Tag', tag: string } | null> | null, recipes?: Array<{ __typename?: 'Recipe', name: string, private?: boolean | null } | null> | null, community?: { __typename?: 'Community', discord?: string | null, slack?: string | null, homepage?: string | null, gitUrl?: string | null, twitter?: string | null } | null, license?: { __typename?: 'License', name?: string | null, url?: string | null } | null }; +export type TinyRepoFragment = { __typename?: 'Repository', id: string, name: string, category?: Category | null, darkIcon?: string | null, icon?: string | null }; + +export type BasicRepoFragment = { __typename?: 'Repository', category?: Category | null, darkIcon?: string | null, description?: string | null, icon?: string | null, id: string, name: string, private?: boolean | null, releaseStatus?: ReleaseStatus | null, trending?: boolean | null, verified?: boolean | null, homepage?: string | null, gitUrl?: string | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null } | null, tags?: Array<{ __typename?: 'Tag', tag: string } | null> | null, recipes?: Array<{ __typename?: 'Recipe', name: string, private?: boolean | null } | null> | null, community?: { __typename?: 'Community', discord?: string | null, slack?: string | null, homepage?: string | null, gitUrl?: string | null, twitter?: string | null } | null, license?: { __typename?: 'License', name?: string | null, url?: string | null } | null }; export type FullRepoFragment = { __typename?: 'Repository', readme?: string | null, mainBranch?: string | null, category?: Category | null, darkIcon?: string | null, description?: string | null, icon?: string | null, id: string, name: string, private?: boolean | null, releaseStatus?: ReleaseStatus | null, trending?: boolean | null, verified?: boolean | null, homepage?: string | null, gitUrl?: string | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null } | null, tags?: Array<{ __typename?: 'Tag', tag: string } | null> | null, recipes?: Array<{ __typename?: 'Recipe', name: string, private?: boolean | null } | null> | null, community?: { __typename?: 'Community', discord?: string | null, slack?: string | null, homepage?: string | null, gitUrl?: string | null, twitter?: string | null } | null, license?: { __typename?: 'License', name?: string | null, url?: string | null } | null }; @@ -5038,6 +5043,11 @@ export type ReposQueryVariables = Exact<{ [key: string]: never; }>; export type ReposQuery = { __typename?: 'RootQueryType', repositories?: { __typename?: 'RepositoryConnection', edges?: Array<{ __typename?: 'RepositoryEdge', node?: { __typename?: 'Repository', category?: Category | null, darkIcon?: string | null, description?: string | null, icon?: string | null, id: string, name: string, private?: boolean | null, releaseStatus?: ReleaseStatus | null, trending?: boolean | null, verified?: boolean | null, homepage?: string | null, gitUrl?: string | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null } | null, tags?: Array<{ __typename?: 'Tag', tag: string } | null> | null, recipes?: Array<{ __typename?: 'Recipe', name: string, private?: boolean | null } | null> | null, community?: { __typename?: 'Community', discord?: string | null, slack?: string | null, homepage?: string | null, gitUrl?: string | null, twitter?: string | null } | null, license?: { __typename?: 'License', name?: string | null, url?: string | null } | null } | null } | null> | null } | null }; +export type TinyReposQueryVariables = Exact<{ [key: string]: never; }>; + + +export type TinyReposQuery = { __typename?: 'RootQueryType', repositories?: { __typename?: 'RepositoryConnection', edges?: Array<{ __typename?: 'RepositoryEdge', node?: { __typename?: 'Repository', id: string, name: string, category?: Category | null, darkIcon?: string | null, icon?: string | null } | null } | null> | null } | null }; + export type RepoQueryVariables = Exact<{ name?: InputMaybe; }>; @@ -5141,6 +5151,15 @@ export const RecipeFragmentDoc = gql` } } ${RecipeSectionFragmentDoc}`; +export const TinyRepoFragmentDoc = gql` + fragment TinyRepo on Repository { + id + name + category + darkIcon + icon +} + `; export const PublisherFragmentDoc = gql` fragment Publisher on Publisher { id @@ -5157,8 +5176,8 @@ export const MinRecipeFragmentDoc = gql` private } `; -export const MinRepoFragmentDoc = gql` - fragment MinRepo on Repository { +export const BasicRepoFragmentDoc = gql` + fragment BasicRepo on Repository { category darkIcon description @@ -5196,11 +5215,11 @@ export const MinRepoFragmentDoc = gql` ${MinRecipeFragmentDoc}`; export const FullRepoFragmentDoc = gql` fragment FullRepo on Repository { - ...MinRepo + ...BasicRepo readme mainBranch } - ${MinRepoFragmentDoc}`; + ${BasicRepoFragmentDoc}`; export const CategoryFragmentDoc = gql` fragment Category on CategoryInfo { category @@ -5226,7 +5245,7 @@ export const StackCollectionFragmentDoc = gql` bundles { recipe { repository { - ...MinRepo + ...BasicRepo tags { tag } @@ -5234,7 +5253,7 @@ export const StackCollectionFragmentDoc = gql` } } } - ${MinRepoFragmentDoc}`; + ${BasicRepoFragmentDoc}`; export const MinStackFragmentDoc = gql` fragment MinStack on Stack { id @@ -5371,12 +5390,12 @@ export const ReposDocument = gql` repositories(first: 5000) { edges { node { - ...MinRepo + ...BasicRepo } } } } - ${MinRepoFragmentDoc}`; + ${BasicRepoFragmentDoc}`; /** * __useReposQuery__ @@ -5404,6 +5423,44 @@ export function useReposLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions; export type ReposLazyQueryHookResult = ReturnType; export type ReposQueryResult = Apollo.QueryResult; +export const TinyReposDocument = gql` + query TinyRepos { + repositories(first: 5000) { + edges { + node { + ...TinyRepo + } + } + } +} + ${TinyRepoFragmentDoc}`; + +/** + * __useTinyReposQuery__ + * + * To run a query within a React component, call `useTinyReposQuery` and pass it any options that fit your needs. + * When your component renders, `useTinyReposQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useTinyReposQuery({ + * variables: { + * }, + * }); + */ +export function useTinyReposQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(TinyReposDocument, options); + } +export function useTinyReposLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(TinyReposDocument, options); + } +export type TinyReposQueryHookResult = ReturnType; +export type TinyReposLazyQueryHookResult = ReturnType; +export type TinyReposQueryResult = Apollo.QueryResult; export const RepoDocument = gql` query Repo($name: String) { repository(name: $name) { diff --git a/src/generated/pages.json b/src/generated/pages.json index 0cb893aa..41c0acfc 100644 --- a/src/generated/pages.json +++ b/src/generated/pages.json @@ -23,6 +23,9 @@ { "path": "/marketplace" }, + { + "path": "/plural-deployments-early-access" + }, { "path": "/pricing" }, diff --git a/src/graph/directus/cms.graphql b/src/graph/directus/cms.graphql index 2d1993d2..50ebfc71 100644 --- a/src/graph/directus/cms.graphql +++ b/src/graph/directus/cms.graphql @@ -43,6 +43,28 @@ fragment NavListDepth3 on nav_list { } } +fragment CompanyLogo on company_logos { + slug + name + logo_light { + ...ImageFile + } + logo_dark { + ...ImageFile + } + url + width +} + +fragment LogoList on company_logo_lists { + slug + items { + item { + ...CompanyLogo + } + } +} + fragment SiteSettings on site_settings { main_nav(sort: ["sort"]) { ...NavListDepth3 @@ -51,6 +73,9 @@ fragment SiteSettings on site_settings { og_image { ...ImageFile } + partner_logos { + ...LogoList + } } query SiteSettings { @@ -59,7 +84,7 @@ query SiteSettings { } } -fragment FeaturedArticle on case_studies { +fragment CaseStudy on case_studies { id slug label @@ -77,12 +102,15 @@ fragment AppExtras on apps { name heroVideo case_study { - ...FeaturedArticle + ...CaseStudy } } fragment AppDefaults on app_defaults { case_study { - ...FeaturedArticle + ...CaseStudy + } + quotes { + ...QuoteList } } @@ -99,12 +127,15 @@ fragment StackExtras on stacks { name heroVideo case_study { - ...FeaturedArticle + ...CaseStudy } } fragment StackDefaults on stack_defaults { case_study { - ...FeaturedArticle + ...CaseStudy + } + quotes { + ...QuoteList } } @@ -174,7 +205,9 @@ fragment FaqItem on collapsibles { fragment FaqList on collapsible_lists { items { - ...FaqItem + item { + ...FaqItem + } } } @@ -197,9 +230,12 @@ fragment Solution on solutions_pages { ...ImageFile } case_study { - ...FeaturedArticle + ...CaseStudy } bullet_points + featured_quote { + ...Quote + } } query SolutionsSlugs { diff --git a/src/graph/directus/pages.graphql b/src/graph/directus/pages.graphql index 50498b6f..eb1df64f 100644 --- a/src/graph/directus/pages.graphql +++ b/src/graph/directus/pages.graphql @@ -19,6 +19,21 @@ query PageCommunity { } } +fragment PageProduct on page_product { + featured_quote { + ...Quote + } + faq { + ...FaqList + } +} + +query PageProduct { + page_product { + ...PageProduct + } +} + fragment MarkdownPage on markdown_pages { id slug @@ -46,3 +61,31 @@ query LegalPageSlugs { } } } + +fragment ArticleCard on article_cards { + heading + description + thumbnail { + ...ImageFile + } + videoUrl + date + author + ctas + url +} + +fragment PageHomepage on page_homepage { + quotes { + ...QuoteList + } + article_cards { + ...ArticleCard + } +} + +query PageHomepage { + page_homepage { + ...PageHomepage + } +} diff --git a/src/graph/directus/quotes.graphql b/src/graph/directus/quotes.graphql new file mode 100644 index 00000000..ca13a685 --- /dev/null +++ b/src/graph/directus/quotes.graphql @@ -0,0 +1,22 @@ +fragment Quote on quotes { + id + quote + name + title + company + portrait { + ...ImageFile + } + logo { + ...ImageFile + } +} + +fragment QuoteList on quote_lists { + slug + items { + item { + ...Quote + } + } +} diff --git a/src/graph/plural/repos.graphql b/src/graph/plural/repos.graphql index 19e93feb..d982b4cd 100644 --- a/src/graph/plural/repos.graphql +++ b/src/graph/plural/repos.graphql @@ -7,7 +7,15 @@ fragment Publisher on Publisher { backgroundColor } -fragment MinRepo on Repository { +fragment TinyRepo on Repository { + id + name + category + darkIcon + icon +} + +fragment BasicRepo on Repository { category darkIcon description @@ -40,13 +48,10 @@ fragment MinRepo on Repository { name url } - # Remove later when repositories q is public - # readme - # mainBranch } fragment FullRepo on Repository { - ...MinRepo + ...BasicRepo readme mainBranch } @@ -55,7 +60,7 @@ query Repos { repositories(first: 5000) { edges { node { - ...MinRepo + ...BasicRepo } } } @@ -65,7 +70,17 @@ query Repos { repositories(first: 5000) { edges { node { - ...MinRepo + ...BasicRepo + } + } + } +} + +query TinyRepos { + repositories(first: 5000) { + edges { + node { + ...TinyRepo } } } diff --git a/src/graph/plural/stacks.graphql b/src/graph/plural/stacks.graphql index 74afbe67..b0957504 100644 --- a/src/graph/plural/stacks.graphql +++ b/src/graph/plural/stacks.graphql @@ -4,7 +4,7 @@ fragment StackCollection on StackCollection { bundles { recipe { repository { - ...MinRepo + ...BasicRepo tags { tag } diff --git a/src/utils/normalizeQuotes.ts b/src/utils/normalizeQuotes.ts new file mode 100644 index 00000000..4d517777 --- /dev/null +++ b/src/utils/normalizeQuotes.ts @@ -0,0 +1,19 @@ +import { type Maybe } from 'graphql/jsutils/Maybe' + +import { type QuoteListFragment } from '@src/generated/graphqlDirectus' + +import { notNil } from './typescript' + +export type M2mList = Maybe<{ + items?: Maybe }>[]> +}> + +export function normalizeM2mItems(itemList: M2mList): I[] | null { + return itemList?.items?.map((i) => i?.item).filter(notNil) || null +} + +export function normalizeQuotes( + quotes: T | null | undefined +) { + return normalizeM2mItems(quotes) +} diff --git a/src/utils/ts-notNil.ts b/src/utils/ts-notNil.ts deleted file mode 100644 index 3a9ac6a8..00000000 --- a/src/utils/ts-notNil.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { isNil } from 'lodash-es' - -// Functions to use in Array.filter() that will inform the type checker that -// null and undefined values are guaranteed filtered out - -export function notNil(value: T | null | undefined): value is T { - return !isNil(value) -} - -export function notNilAnd(filterFunc: (value: T) => boolean) { - return function combinedFilter(value: T | null | undefined): value is T { - return notNil(value) && filterFunc(value) - } -} diff --git a/src/utils/typescript.ts b/src/utils/typescript.ts index 52a3a06e..2c2fcf7b 100644 --- a/src/utils/typescript.ts +++ b/src/utils/typescript.ts @@ -20,7 +20,7 @@ export type PartialBy = Omit & Partial> // Functions to use in Array.filter() that will inform the type checker that // null and undefined values are guaranteed filtered out -export function notNil(value: T | null | undefined): value is T { +export function notNil(value: T): value is NonNullable { return !isNil(value) } @@ -32,4 +32,4 @@ export function notNilAnd(filterFunc: (value: T) => boolean) { export type Omit$Props< T extends keyof JSX.IntrinsicElements | JSXElementConstructor -> = ConditionalExcept, `${string}`> +> = ConditionalExcept, `$${string}`>