From 4eb49cf5c5f1334805a5cdc82689ab37323c596e Mon Sep 17 00:00:00 2001 From: Freda Lai <42527625+fredalai@users.noreply.github.com> Date: Tue, 2 Apr 2024 18:35:25 +0800 Subject: [PATCH] feat(wren-ui): Support sample data UI (#53) * feat(wren-ui): Support sample data UI * feat(wren-ui): Use SampleDatasetName enum instead of * fixup! feat(wren-ui): Support sample data UI --- .../client/graphql/dataSource.generated.ts | 38 ++++++++++++ .../src/apollo/client/graphql/dataSource.ts | 6 ++ .../src/components/pages/setup/Starter.tsx | 62 ++++++++++++++++--- wren-ui/src/components/pages/setup/utils.tsx | 27 +++++--- wren-ui/src/hooks/useSetupConnection.tsx | 33 ++++++++-- wren-ui/src/utils/enum/setup.ts | 5 -- 6 files changed, 144 insertions(+), 27 deletions(-) diff --git a/wren-ui/src/apollo/client/graphql/dataSource.generated.ts b/wren-ui/src/apollo/client/graphql/dataSource.generated.ts index de1ccdb38..68e4a21ff 100644 --- a/wren-ui/src/apollo/client/graphql/dataSource.generated.ts +++ b/wren-ui/src/apollo/client/graphql/dataSource.generated.ts @@ -3,6 +3,13 @@ import * as Types from './__types__'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; +export type StartSampleDatasetMutationVariables = Types.Exact<{ + data: Types.SampleDatasetInput; +}>; + + +export type StartSampleDatasetMutation = { __typename?: 'Mutation', startSampleDataset: any }; + export type ListDataSourceTablesQueryVariables = Types.Exact<{ [key: string]: never; }>; @@ -35,6 +42,37 @@ export type SaveRelationsMutationVariables = Types.Exact<{ export type SaveRelationsMutation = { __typename?: 'Mutation', saveRelations: any }; +export const StartSampleDatasetDocument = gql` + mutation StartSampleDataset($data: SampleDatasetInput!) { + startSampleDataset(data: $data) +} + `; +export type StartSampleDatasetMutationFn = Apollo.MutationFunction; + +/** + * __useStartSampleDatasetMutation__ + * + * To run a mutation, you first call `useStartSampleDatasetMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useStartSampleDatasetMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [startSampleDatasetMutation, { data, loading, error }] = useStartSampleDatasetMutation({ + * variables: { + * data: // value for 'data' + * }, + * }); + */ +export function useStartSampleDatasetMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(StartSampleDatasetDocument, options); + } +export type StartSampleDatasetMutationHookResult = ReturnType; +export type StartSampleDatasetMutationResult = Apollo.MutationResult; +export type StartSampleDatasetMutationOptions = Apollo.BaseMutationOptions; export const ListDataSourceTablesDocument = gql` query ListDataSourceTables { listDataSourceTables { diff --git a/wren-ui/src/apollo/client/graphql/dataSource.ts b/wren-ui/src/apollo/client/graphql/dataSource.ts index 104bc8191..69e80055c 100644 --- a/wren-ui/src/apollo/client/graphql/dataSource.ts +++ b/wren-ui/src/apollo/client/graphql/dataSource.ts @@ -1,5 +1,11 @@ import { gql } from '@apollo/client'; +export const SET_SAMPLE_DATASETS = gql` + mutation StartSampleDataset($data: SampleDatasetInput!) { + startSampleDataset(data: $data) + } +`; + export const LIST_DATA_SOURCE_TABLES = gql` query ListDataSourceTables { listDataSourceTables { diff --git a/wren-ui/src/components/pages/setup/Starter.tsx b/wren-ui/src/components/pages/setup/Starter.tsx index 526527046..ef49fe95e 100644 --- a/wren-ui/src/components/pages/setup/Starter.tsx +++ b/wren-ui/src/components/pages/setup/Starter.tsx @@ -1,10 +1,15 @@ import Link from 'next/link'; import Image from 'next/image'; +import { useState } from 'react'; import { Button, Typography, Row, Col } from 'antd'; +import Icon from '@ant-design/icons'; import styled from 'styled-components'; import { ButtonOption, getDataSources, getTemplates } from './utils'; import { makeIterable, IterableComponent } from '@/utils/iteration'; -import { DataSourceName } from '@/apollo/client/graphql/__types__'; +import { + DataSourceName, + SampleDatasetName, +} from '@/apollo/client/graphql/__types__'; const ButtonItem = styled(Button)` border: 1px var(--gray-4) solid; @@ -15,6 +20,11 @@ const ButtonItem = styled(Button)` &:disabled { opacity: 0.5; } + + // loading of button + .ant-btn-loading-icon .anticon { + font-size: 24px; + } `; const PlainImage = styled.div` @@ -37,15 +47,32 @@ const CommingSoon = styled.div` const ButtonTemplate = ( props: IterableComponent< - ButtonOption & { value: string; onSelect: (value: string) => void } + ButtonOption & { + value: string; + onSelect: (value: string) => void; + selectedTemplate?: string; + } >, ) => { - const { value, disabled, logo, label, onSelect } = props; + const { + value, + disabled, + submitting, + logo, + IconComponent, + label, + onSelect, + selectedTemplate, + } = props; + + const loading = selectedTemplate === value; + return ( onSelect(value)} >
@@ -57,6 +84,12 @@ const ButtonTemplate = ( width="40" height="40" /> + ) : IconComponent ? ( + ) : ( )} @@ -72,7 +105,10 @@ const DataSourceIterator = makeIterable(ButtonTemplate); const TemplatesIterator = makeIterable(ButtonTemplate); export default function Starter(props) { - const { onNext } = props; + const { onNext, submitting } = props; + + const [template, setTemplate] = useState(); + const dataSources = getDataSources(); const templates = getTemplates(); @@ -81,6 +117,7 @@ export default function Starter(props) { }; const onSelectTemplate = (value: string) => { + setTemplate(value as SampleDatasetName); onNext && onNext({ template: value }); }; @@ -101,7 +138,11 @@ export default function Starter(props) { . - +
@@ -110,7 +151,12 @@ export default function Starter(props) { Play around with sample data - +
diff --git a/wren-ui/src/components/pages/setup/utils.tsx b/wren-ui/src/components/pages/setup/utils.tsx index 0a218b458..b5f05df59 100644 --- a/wren-ui/src/components/pages/setup/utils.tsx +++ b/wren-ui/src/components/pages/setup/utils.tsx @@ -1,11 +1,16 @@ import { merge } from 'lodash'; +import IconComponentProps from '@ant-design/icons'; +import CustomerServiceOutlined from '@ant-design/icons/CustomerServiceOutlined'; +import ShoppingCartOutlined from '@ant-design/icons/ShoppingCartOutlined'; +import TrophyOutlined from '@ant-design/icons/TrophyOutlined'; +import { SETUP, DATA_SOURCES } from '@/utils/enum'; import Starter from './Starter'; import ConnectDataSource from './ConnectDataSource'; import SelectModels from './SelectModels'; import DefineRelations from './DefineRelations'; -import { SETUP, DATA_SOURCES, DEMO_TEMPLATES } from '@/utils/enum'; import BigQueryProperties from './dataSources/BigQueryProperties'; import DuckDBProperties from './dataSources/DuckDBProperties'; +import { SampleDatasetName } from '@/apollo/client/graphql/__types__'; type SetupStep = { step: number; @@ -21,8 +26,10 @@ type SetupStep = { export type ButtonOption = { label: string; logo: string; + IconComponent?: typeof IconComponentProps; guide: string; disabled: boolean; + submitting?: boolean; }; export const SETUP_STEPS = { @@ -73,13 +80,17 @@ export const DATA_SOURCE_FORM = { }; export const TEMPLATE_OPTIONS = { - [DEMO_TEMPLATES.CRM]: { - label: 'CRM', - logo: '', - }, - [DEMO_TEMPLATES.ECORMERCE]: { + [SampleDatasetName.ECOMMERCE]: { label: 'E-commerce', - logo: '', + IconComponent: ShoppingCartOutlined, + }, + [SampleDatasetName.MUSIC]: { + label: 'Music Store', + IconComponent: CustomerServiceOutlined, + }, + [SampleDatasetName.NBA]: { + label: 'NBA', + IconComponent: TrophyOutlined, }, }; @@ -111,6 +122,6 @@ export const getTemplates = () => { ...TEMPLATE_OPTIONS[key], value: key, })) as (Omit & { - value: DEMO_TEMPLATES; + value: SampleDatasetName; })[]; }; diff --git a/wren-ui/src/hooks/useSetupConnection.tsx b/wren-ui/src/hooks/useSetupConnection.tsx index d2f165c27..3a07ca36a 100644 --- a/wren-ui/src/hooks/useSetupConnection.tsx +++ b/wren-ui/src/hooks/useSetupConnection.tsx @@ -1,8 +1,14 @@ import { useState, useEffect } from 'react'; -import { SETUP } from '@/utils/enum'; +import { Path, SETUP } from '@/utils/enum'; import { useRouter } from 'next/router'; -import { useSaveDataSourceMutation } from '@/apollo/client/graphql/dataSource.generated'; -import { DataSourceName } from '@/apollo/client/graphql/__types__'; +import { + useSaveDataSourceMutation, + useStartSampleDatasetMutation, +} from '@/apollo/client/graphql/dataSource.generated'; +import { + DataSourceName, + SampleDatasetName, +} from '@/apollo/client/graphql/__types__'; const transformProperties = ( properties: Record, @@ -42,7 +48,13 @@ export default function useSetupConnection() { const [saveDataSourceMutation, { loading, error }] = useSaveDataSourceMutation({ onError: (error) => console.error(error), - onCompleted: () => router.push('/setup/models'), + onCompleted: () => router.push(Path.OnboardingModels), + }); + + const [startSampleDatasetMutation, { loading: startSampleDatasetLoading }] = + useStartSampleDatasetMutation({ + onError: (error) => console.error(error), + onCompleted: () => router.push(Path.Home), }); useEffect(() => { @@ -60,6 +72,14 @@ export default function useSetupConnection() { }); }; + const submitTemplate = async (template: SampleDatasetName) => { + await startSampleDatasetMutation({ + variables: { + data: { name: template }, + }, + }); + }; + const onBack = () => { if (stepKey === SETUP.CREATE_DATA_SOURCE) { setStepKey(SETUP.STARTER); @@ -68,6 +88,7 @@ export default function useSetupConnection() { const onNext = (data?: { dataSource?: DataSourceName; + template?: SampleDatasetName; properties?: JSON; }) => { if (stepKey === SETUP.STARTER) { @@ -75,7 +96,7 @@ export default function useSetupConnection() { setDataSource(data?.dataSource); setStepKey(SETUP.CREATE_DATA_SOURCE); } else { - // TODO: implement template chosen + submitTemplate(data.template); } } else if (stepKey === SETUP.CREATE_DATA_SOURCE) { submitDataSource(data.properties); @@ -87,7 +108,7 @@ export default function useSetupConnection() { dataSource, onBack, onNext, - submitting: loading, + submitting: loading || startSampleDatasetLoading, connectErrorMessage, }; } diff --git a/wren-ui/src/utils/enum/setup.ts b/wren-ui/src/utils/enum/setup.ts index b1effe9bd..14332c03a 100644 --- a/wren-ui/src/utils/enum/setup.ts +++ b/wren-ui/src/utils/enum/setup.ts @@ -5,8 +5,3 @@ export enum SETUP { RECOMMEND_RELATIONS = 'recommendRelations', DEFINE_RELATIONS = 'defineRelations', } - -export enum DEMO_TEMPLATES { - CRM = 'CRM', - ECORMERCE = 'Ecommerce', -}