diff --git a/CHANGELOG.md b/CHANGELOG.md index fe165efe1c3..2ea93d260de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ### Added: - Resource links to empty state Volumes landing page #9065 - Resource links to empty state Firewalls landing page #9078 +- Resource links to empty state StackScripts landing page #9091 - Resource links to empty state Domains landing page #9092 - Ability download DNS zone file #9075 diff --git a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.styles.ts b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.styles.ts index 44da3ac4883..7710683e9ea 100644 --- a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.styles.ts +++ b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.styles.ts @@ -19,7 +19,6 @@ const styles = (theme: Theme) => }, emptyState: { color: theme.palette.text.primary, - textAlign: 'center', }, table: { backgroundColor: theme.bg.bgPaper, diff --git a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.tsx b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.tsx index 7b21b0817ed..d775a9b4557 100644 --- a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.tsx +++ b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptBase.tsx @@ -1,38 +1,38 @@ -import { Image } from '@linode/api-v4/lib/images'; -import { StackScript } from '@linode/api-v4/lib/stackscripts'; -import { APIError, Filter, ResourcePage } from '@linode/api-v4/lib/types'; -import classNames from 'classnames'; -import { pathOr } from 'ramda'; import * as React from 'react'; -import { RouteComponentProps, withRouter } from 'react-router-dom'; -import { Waypoint } from 'react-waypoint'; -import { compose } from 'recompose'; -import StackScriptsIcon from 'src/assets/icons/entityIcons/stackscript.svg'; +import { APIError, Filter, ResourcePage } from '@linode/api-v4/lib/types'; +import { + AcceptedFilters, + generateCatchAllFilter, + generateSpecificFilter, +} from '../stackScriptUtils'; import Button from 'src/components/Button'; +import classNames from 'classnames'; import { CircleProgress } from 'src/components/CircleProgress'; -import Typography from 'src/components/core/Typography'; +import { compose } from 'recompose'; import { DebouncedSearchTextField } from 'src/components/DebouncedSearchTextField'; import ErrorState from 'src/components/ErrorState'; +import { Image } from '@linode/api-v4/lib/images'; +import { pathOr } from 'ramda'; import { Notice } from 'src/components/Notice/Notice'; import Placeholder from 'src/components/Placeholder'; +import { RouteComponentProps, withRouter } from 'react-router-dom'; +import StackScriptsIcon from 'src/assets/icons/entityIcons/stackscript.svg'; +import StackScriptTableHead from '../Partials/StackScriptTableHead'; +import { StackScript } from '@linode/api-v4/lib/stackscripts'; +import { StackScriptsEmptyLandingState } from './StackScriptsEmptyLandingPage'; +import { StackScriptsRequest } from '../types'; import { Table } from 'src/components/Table'; -import { - withProfile, - WithProfileProps, -} from 'src/containers/profile.container'; -import { WithQueryClientProps } from 'src/containers/withQueryClient.container'; -import { isLinodeKubeImageId } from 'src/store/image/image.helpers'; import { getAPIErrorOrDefault } from 'src/utilities/errorUtils'; import { getDisplayName } from 'src/utilities/getDisplayName'; -import { handleUnauthorizedErrors } from 'src/utilities/handleUnauthorizedErrors'; import { getQueryParam } from 'src/utilities/queryParams'; -import StackScriptTableHead from '../Partials/StackScriptTableHead'; +import { handleUnauthorizedErrors } from 'src/utilities/handleUnauthorizedErrors'; +import { isLinodeKubeImageId } from 'src/store/image/image.helpers'; +import { Waypoint } from 'react-waypoint'; +import { WithQueryClientProps } from 'src/containers/withQueryClient.container'; import { - AcceptedFilters, - generateCatchAllFilter, - generateSpecificFilter, -} from '../stackScriptUtils'; -import { StackScriptsRequest } from '../types'; + withProfile, + WithProfileProps, +} from 'src/containers/profile.container'; import withStyles, { StyleProps } from './StackScriptBase.styles'; type CurrentFilter = 'label' | 'deploys' | 'revision'; @@ -493,44 +493,9 @@ const withStackScriptBase = (options: WithStackScriptBaseOptions) => ( You don’t have any StackScripts to select from. </Placeholder> ) : ( - <Placeholder - icon={StackScriptsIcon} - renderAsSecondary - isEntity - title="StackScripts" - buttonProps={[ - { - children: 'Create StackScript', - onClick: () => this.goToCreateStackScript(), - }, - ]} - className={classes.stackscriptPlaceholder} - > - <Typography variant="subtitle1"> - Automate Deployment with StackScripts! - </Typography> - <Typography variant="subtitle1"> - <a - href="https://linode.com/docs/platform/stackscripts-new-manager/" - target="_blank" - aria-describedby="external-site" - rel="noopener noreferrer" - className="h-u" - > - Learn more about getting started - </a> - or - <a - href="https://www.linode.com/docs/" - target="_blank" - aria-describedby="external-site" - rel="noopener noreferrer" - className="h-u" - > - visit our guides and tutorials. - </a> - </Typography> - </Placeholder> + <StackScriptsEmptyLandingState + goToCreateStackScript={this.goToCreateStackScript} + /> )} </div> ) : ( diff --git a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyLandingPage.tsx b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyLandingPage.tsx new file mode 100644 index 00000000000..51da185b8a5 --- /dev/null +++ b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyLandingPage.tsx @@ -0,0 +1,41 @@ +import * as React from 'react'; +import StackScriptsIcon from 'src/assets/icons/entityIcons/stackscript.svg'; +import { ResourcesSection } from 'src/components/EmptyLandingPageResources/ResourcesSection'; +import { sendEvent } from 'src/utilities/ga'; +import { + gettingStartedGuides, + headers, + linkGAEvent, + youtubeLinkData, +} from './StackScriptsEmptyResourcesData'; + +interface Props { + goToCreateStackScript: () => void; +} + +export const StackScriptsEmptyLandingState = (props: Props) => { + const { goToCreateStackScript } = props; + + return ( + <ResourcesSection + buttonProps={[ + { + onClick: () => { + sendEvent({ + category: linkGAEvent.category, + action: 'Click:button', + label: 'Create StackScript', + }); + goToCreateStackScript(); + }, + children: 'Create StackScript', + }, + ]} + gettingStartedGuidesData={gettingStartedGuides} + headers={headers} + icon={StackScriptsIcon} + linkGAEvent={linkGAEvent} + youtubeLinkData={youtubeLinkData} + /> + ); +}; diff --git a/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyResourcesData.ts b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyResourcesData.ts new file mode 100644 index 00000000000..42e969382b1 --- /dev/null +++ b/packages/manager/src/features/StackScripts/StackScriptBase/StackScriptsEmptyResourcesData.ts @@ -0,0 +1,72 @@ +import { + youtubeChannelLink, + youtubeMoreLinkText, +} from 'src/utilities/emptyStateLandingUtils'; +import type { + ResourcesHeaders, + ResourcesLinkSection, + ResourcesLinks, +} from 'src/components/EmptyLandingPageResources/ResourcesLinksTypes'; + +export const headers: ResourcesHeaders = { + description: + 'Run custom scripts to install and configure software when initializing Linode Compute Instances', + + subtitle: 'Automate deployment scripts', + title: 'StackScripts', +}; + +export const gettingStartedGuides: ResourcesLinkSection = { + links: [ + { + to: + 'https://www.linode.com/docs/products/tools/stackscripts/get-started/', + text: 'Getting Started with StackScripts', + }, + { + to: + 'https://www.linode.com/docs/products/tools/stackscripts/guides/create/', + text: 'Create a StackScript', + }, + { + to: + 'https://www.linode.com/docs/products/tools/stackscripts/guides/write-a-custom-script/', + text: 'Write a Custom Script for Use with StackScripts', + }, + ], + moreInfo: { + to: 'https://www.linode.com/docs/products/tools/stackscripts/ ', + text: 'View additional Object Storage documentation', + }, + title: 'Getting Started Guides', +}; + +export const youtubeLinkData: ResourcesLinkSection = { + links: [ + { + to: 'https://www.youtube.com/watch?v=nygChMc1hX4', + text: 'Automate Server Deployments Using Stackscripts', + external: true, + }, + { + to: 'https://www.youtube.com/watch?v=EbyA5rZwyRw', + text: 'Shell Scripts Explained', + external: true, + }, + { + to: 'https://www.youtube.com/watch?v=yM8v5i2Qjgg', + text: ' Linux for Programmers #7 | Environment Variables', + external: true, + }, + ], + moreInfo: { + to: youtubeChannelLink, + text: youtubeMoreLinkText, + }, + title: 'Video Playlist', +}; + +export const linkGAEvent: ResourcesLinks['linkGAEvent'] = { + action: 'Click:link', + category: 'StackScripts landing page empty', +};