Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand Templates #10994

Merged
merged 15 commits into from
Sep 9, 2024
Binary file added app/dashboard/src/assets/ReadAndFilter.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/aggregate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/blankProject.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/book.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/cleansing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/covid.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions app/dashboard/src/assets/enso_logo_large.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/joining.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/kmeans.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/monthSales.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/nasdaq.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/dashboard/src/assets/weather.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
147 changes: 87 additions & 60 deletions app/dashboard/src/layouts/Samples.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
/** @file Renders the list of templates from which a project can be created. */
import * as React from 'react'

import Logo from '#/assets/enso_logo.svg'
import GeoImage from '#/assets/geo.svg'
import HeartIcon from '#/assets/heart.svg'
import OpenCountIcon from '#/assets/open_count.svg'
import ReadAndFilterImage from '#/assets/ReadAndFilter.png'
import CleansingImage from '#/assets/cleansing.png'
import AggregatingImage from '#/assets/aggregate.png'
import JoinImage from '#/assets/joining.png'
import SpreadsheetsImage from '#/assets/spreadsheets.svg'
import BlankImage from '#/assets/blankProject.png'
import VisualizeImage from '#/assets/visualize.png'

import * as textProvider from '#/providers/TextProvider'
import MonthSalesImage from '#/assets/monthSales.png'
import CovidImage from '#/assets/covid.png'
import WeatherImage from '#/assets/weather.png'
import GeoImage from '#/assets/geo.svg'
import NasdaqImage from '#/assets/nasdaq.png'
import KMeansImage from '#/assets/kmeans.png'

import * as aria from '#/components/aria'
import FocusArea from '#/components/styled/FocusArea'
import FocusRing from '#/components/styled/FocusRing'
import SvgMask from '#/components/SvgMask'

import * as tailwindMerge from '#/utilities/tailwindMerge'

// =================
// === Constants ===
// =================

/** A placeholder author for a sample, for use until the backend implements an endpoint. */
const DUMMY_AUTHOR = 'Enso Team'
/** A placeholder number of times a sample has been opened, for use until the backend implements
* an endpoint. */
const DUMMY_OPEN_COUNT = 10
/** A placeholder number of likes for a sample, for use until the backend implements an endpoint. */
const DUMMY_LIKE_COUNT = 10

// =========================
// === List of templates ===
// =========================
Expand All @@ -41,42 +33,101 @@ export interface Sample {
readonly description: string
readonly id: string
readonly background?: string
readonly group?: string
}

/** The full list of templates. */
export const SAMPLES: Sample[] = [
{
title: 'Colorado COVID',
id: 'Colorado_COVID',
description: 'Learn to glue multiple spreadsheets to analyses all your data at once.',
title: 'Blank Project',
id: 'Default',
description: "Start with a blank workflow.",
background: `url("${BlankImage}") center / cover`,
group: 'Getting Started'
},
{
title: 'KMeans',
id: 'KMeans',
description: 'Learn where to open a coffee shop to maximize your income.',
title: 'Reading and Filterng Data',
id: 'Getting_Started_Reading',
description: "Learn how to bring data into Enso.",
background: `url("${ReadAndFilterImage}") center / cover`,
group: 'Getting Started'
},
{
title: 'Aggregating and Pivoting',
id: 'Getting_Started_Aggregating',
description: "Learn how to group and aggregate data, and pivot.",
background: `url("${AggregatingImage}") center / cover`,
group: 'Getting Started'
},
{
title: 'Cleaning and Parsing Data',
id: 'Getting_Started_Cleansing',
description: "Learn how to cleanse and parse text values.",
background: `url("${CleansingImage}") center / cover`,
group: 'Getting Started'
},
{
title: 'Selecting Columns and Joining Tables',
id: 'Getting_Started_Selecting',
description: "Learn how to choose columns and join tables.",
background: `url("${JoinImage}") center / cover`,
group: 'Getting Started'
},
{
title: 'Analyze GitHub stars',
id: 'Stargazers',
description: "Find out which of Enso's repositories are most popular over time.",
background: `url("${VisualizeImage}") center / cover`,
group: 'Advanced'
},
{
title: 'NASDAQ Returns',
id: 'NASDAQReturns',
description: 'Learn how to clean your data to prepare it for advanced analysis.',
background: `url("${NasdaqImage}") center / cover`,
group: 'Advanced'
},
{
title: 'KMeans',
id: 'KMeans',
description: 'Learn where to open a coffee shop to maximize your income.',
background: `url("${KMeansImage}") center / cover`,
group: 'Advanced'
},
{
title: 'Combine spreadsheets',
id: 'Orders',
description: 'Glue multiple spreadsheets together to analyse all your data at once.',
background: `url('${SpreadsheetsImage}') center / 50% no-repeat, rgba(255, 255, 255, 0.30)`,
background: `url("${SpreadsheetsImage}") center / 50% no-repeat, rgba(255, 255, 255, 0.30)`,
group: 'Examples'
},
{
title: 'Month on Month Sales',
id: 'Monthly_Sales',
description: 'Learn how to compare with previous month sales.',
background: `url("${MonthSalesImage}") center / cover`,
group: 'Examples'
},
{
title: 'Colorado COVID',
id: 'Colorado_COVID',
description: 'Learn to glue multiple spreadsheets to analyses all your data at once.',
background: `url('${CovidImage}') center / 100% no-repeat, rgba(255, 255, 255, 0.30)`,
group: 'Examples'
},
{
title: 'Web API analysis',
id: 'Bank_Holiday_Rain',
description: 'Learn whether it rains on UK Bank Holidays via REST APIs.',
background: `url('${WeatherImage}') center / 100% no-repeat, rgba(255, 255, 255, 0.30)`,
group: 'Examples'
},
{
title: 'Geospatial analysis',
id: 'Restaurants',
description: 'Learn where to open a coffee shop to maximize your income.',
background: `url('${GeoImage}') 50% 20% / 100% no-repeat`,
},
{
title: 'Analyze GitHub stars',
id: 'Stargazers',
description: "Find out which of Enso's repositories are most popular over time.",
background: `url("${VisualizeImage}") center / cover`,
group: 'Examples'
},
]

Expand All @@ -93,11 +144,7 @@ interface InternalProjectTileProps {
/** A button that, when clicked, creates and opens a new project based on a template. */
function ProjectTile(props: InternalProjectTileProps) {
const { sample, createProject } = props
const { getText } = textProvider.useText()
const { id, title, description, background } = sample
const author = DUMMY_AUTHOR
const opens = DUMMY_OPEN_COUNT
const likes = DUMMY_LIKE_COUNT

return (
<div className="flex flex-col gap-sample">
Expand Down Expand Up @@ -127,26 +174,6 @@ function ProjectTile(props: InternalProjectTileProps) {
</FocusRing>
)}
</FocusArea>
{/* Although this component is instantiated multiple times, it has a unique role and hence
* its own opacity. */}
{/* eslint-disable-next-line no-restricted-syntax */}
<div className="flex h-sample-info justify-between px-sample-description-x text-primary opacity-70">
<div className="flex gap-samples-icon-with-text">
<SvgMask src={Logo} className="size-4 self-end" />
<aria.Text className="self-start font-bold leading-snug">{author}</aria.Text>
</div>
{/* Normally `flex` */}
<div className="hidden gap-icons">
<div title={getText('views')} className="flex gap-samples-icon-with-text">
<SvgMask alt={getText('views')} src={OpenCountIcon} className="size-4 self-end" />
<aria.Text className="self-start font-bold leading-snug">{opens}</aria.Text>
</div>
<div title={getText('likes')} className="flex gap-samples-icon-with-text">
<SvgMask alt={getText('likes')} src={HeartIcon} className="size-4 self-end" />
<aria.Text className="self-start font-bold leading-snug">{likes}</aria.Text>
</div>
</div>
</div>
</div>
)
}
Expand All @@ -157,22 +184,22 @@ function ProjectTile(props: InternalProjectTileProps) {

/** Props for a {@link Samples}. */
export interface SamplesProps {
readonly groupName: string
readonly createProject: (templateId?: string | null, templateName?: string | null) => void
}

/** A list of sample projects. */
export default function Samples(props: SamplesProps) {
const { createProject } = props
const { getText } = textProvider.useText()
const { groupName, createProject } = props

return (
<div data-testid="samples" className="flex flex-col gap-subheading px-[5px]">
<aria.Heading level={2} className="text-subheading font-normal">
{getText('sampleAndCommunityProjects')}
{groupName}
</aria.Heading>

<div className="grid grid-cols-fill-samples gap-samples">
{SAMPLES.map((sample) => (
{SAMPLES.filter(s => s.group === groupName).map((sample) => (
<ProjectTile key={sample.id} sample={sample} createProject={createProject} />
))}
</div>
Expand Down
27 changes: 18 additions & 9 deletions app/dashboard/src/layouts/StartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,32 @@ export default function StartModal(props: StartModalProps) {
<ariaComponents.Dialog type="fullscreen" title={getText('selectTemplate')}>
{(opts) => (
<div className="mb-4 flex flex-1 flex-col gap-home text-xs text-primary">
<ariaComponents.Text
elementType="p"
variant="custom"
balance
className="mx-10 my-12 max-w-[45rem] self-center text-center text-3xl font-light leading-snug"
>
{getText('welcomeSubtitle')}
</ariaComponents.Text>

<WhatsNew />

<Samples
groupName="Getting Started"
createProject={(templateId, templateName) => {
createProject(templateId, templateName)
opts.close()
}}
/>

<Samples
groupName="Examples"
createProject={(templateId, templateName) => {
createProject(templateId, templateName)
opts.close()
}}
/>

<Samples
groupName="Advanced"
createProject={(templateId, templateName) => {
createProject(templateId, templateName)
opts.close()
}}
/>

</div>
)}
</ariaComponents.Dialog>
Expand Down
47 changes: 37 additions & 10 deletions app/dashboard/src/layouts/WhatsNew.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/** @file Community updates for the app. */
import * as React from 'react'

import DiscordIcon from '#/assets/discord.svg'
import Logo from '#/assets/enso_logo_large.svg'
import BookImage from '#/assets/book.png'
import IntegrationsImage from '#/assets/integrations.png'
import YoutubeIcon from '#/assets/youtube.svg'

Expand Down Expand Up @@ -29,19 +30,22 @@ export default function WhatsNew() {
{(innerProps) => (
<FocusRing>
<a
className="focus-child relative col-span-1 h-news-item rounded-default bg-v3 text-tag-text col-span-2-news-item sm:col-span-2"
className="focus-child relative h-news-item rounded-default bg-green text-tag-text"
rel="noreferrer"
target="_blank"
href="https://enso.org/"
style={{ background: `url(${IntegrationsImage}) top -85px right -390px / 1055px` }}
href="https://help.enso.org/"
{...innerProps}
>
<img
className="absolute left-1/2 top-7 mx-auto -translate-x-1/2"
src={BookImage}
/>
<div className="absolute bottom flex w-full flex-col p-news-item-description">
<aria.Text className="text-subheading font-bold">
{getText('newsItem3Beta')}
{getText('newsItemHelpServer')}
</aria.Text>
<aria.Text className="py-news-item-subtitle-y text-sm leading-snug">
{getText('newsItem3BetaDescription')}
{getText('newsItemHelpServerDescription')}
</aria.Text>
</div>
</a>
Expand All @@ -55,7 +59,7 @@ export default function WhatsNew() {
className="focus-child relative h-news-item rounded-default bg-youtube text-tag-text"
rel="noreferrer"
target="_blank"
href="https://www.youtube.com/c/Enso_org"
href="https://www.youtube.com/@Enso_Analytics/videos"
{...innerProps}
>
<img
Expand All @@ -78,15 +82,15 @@ export default function WhatsNew() {
{(innerProps) => (
<FocusRing>
<a
className="focus-child relative h-news-item rounded-default bg-discord text-tag-text"
className="focus-child relative h-news-item rounded-default bg-green text-tag-text"
rel="noreferrer"
target="_blank"
href="https://discord.gg/enso"
href="https://community.ensoanalytics.com/"
{...innerProps}
>
<img
className="absolute left-1/2 top-7 mx-auto -translate-x-1/2"
src={DiscordIcon}
src={Logo}
/>
<div className="absolute bottom flex w-full flex-col p-news-item-description">
<aria.Text className="text-subheading font-bold">
Expand All @@ -100,6 +104,29 @@ export default function WhatsNew() {
</FocusRing>
)}
</FocusArea>
<FocusArea direction="horizontal">
{(innerProps) => (
<FocusRing>
<a
className="focus-child relative col-span-1 h-news-item rounded-default bg-v3 text-tag-text"
rel="noreferrer"
target="_blank"
href="https://community.ensoanalytics.com/c/what-is-new-in-enso/"
style={{ background: `url(${IntegrationsImage}) top -85px right -390px / 1055px` }}
{...innerProps}
>
<div className="absolute bottom flex w-full flex-col p-news-item-description">
<aria.Text className="text-subheading font-bold">
{getText('newsItem3Beta')}
</aria.Text>
<aria.Text className="py-news-item-subtitle-y text-sm leading-snug">
{getText('newsItem3BetaDescription')}
</aria.Text>
</div>
</a>
</FocusRing>
)}
</FocusArea>
</div>
</div>
)
Expand Down
Loading
Loading