diff --git a/packages/client/dashboard/src/App.tsx b/packages/client/dashboard/src/App.tsx index 6a31fca..10c7726 100644 --- a/packages/client/dashboard/src/App.tsx +++ b/packages/client/dashboard/src/App.tsx @@ -3,7 +3,7 @@ import { ProfileStateProvider } from '@us3r-network/profile' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import { useEffect, useState } from 'react' -import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components' +import { Radio, RadioGroup } from 'react-aria-components' import { NavLink, Outlet, @@ -21,12 +21,12 @@ import Nav from './components/nav/Nav' import { CERAMIC_TESTNET_HOST, WALLET_CONNECT_PROJECT_ID } from './constants' import CeramicNodes from './container/CeramicNodes' import Components from './container/Components' -import DappCreate from './container/DappCreate' import DappEditor from './container/DappEditor' import DappHome from './container/DappHome' import DappInfo from './container/DappInfo' import DappMetrics from './container/DappMetrics' import DappPlayground from './container/DappPlayground' +import DappCreate from './container/DappQuickStart' import DappSdk from './container/DappSdk' import ExploreComposite from './container/ExploreComposite' import ExploreModel from './container/ExploreModel' @@ -203,34 +203,26 @@ function BuildLayout () { setSelectComposite(data) }} selectComposite={selectComposite} - editable={pathname.includes('model-editor')} + editable={pathname.includes('editor')} />
- + + {PAGES.map(page => ( -
- - - -
+ + {page.label} + ))} -
- - {PAGES.map(page => ( - - - {page.label} - - - ))} - -
-
+
) @@ -238,8 +230,8 @@ function BuildLayout () { function ExploreLayout () { const { pathname } = useLocation() - const defaultExploreKey = pathname.split('/explore/')[1] - const EXPLORE_PAGES = [ + const defaultKey = pathname.split('/explore/')[1] + const PAGES = [ { id: 'model', label: 'Models' @@ -255,26 +247,18 @@ function ExploreLayout () { ] return ( - - {EXPLORE_PAGES.map(page => ( -
- - - -
+ + + {PAGES.map(page => ( + + {page.label} + ))} -
- - {EXPLORE_PAGES.map(page => ( - - - {page.label} - - - ))} - -
-
+
) } @@ -283,21 +267,70 @@ const LayoutContainer = styled.div` width: 100%; margin-top: 20px; margin-bottom: 20px; + position: relative; display: flex; + flex-direction: row; gap: 20px; - .tab-list { + .tabs { position: absolute; top: 0px; right: 0px; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + border: 1px solid white; + border-radius: 999px; } - .tab-panel { - position: absolute; - width: 100%; - top: 0; - margin: 0; - padding: 0; + + .tab { + --text-color-base: black; + --text-color-disabled: var(--text-color-base); + --highlight-background: white; + --border-color: transparent; + + padding: 10px 20px; + cursor: pointer; + outline: none; + position: relative; + color: white; + transition: color 200ms; + forced-color-adjust: none; + border-radius: 999px; + a { + color: var(--text-color); + } + + &[data-hovered], + &[data-focused] { + color: white; + } + + &[data-selected] { + background-color: var(--highlight-background); + color: var(--text-color-base); + a { + color: var(--text-color-base); + } + } + + &[data-disabled] { + color: var(--text-color-disabled); + &[data-selected] { + --border-color: var(--text-color-disabled); + } + } + + &[data-focus-visible]:after { + content: ''; + position: absolute; + inset: 4px; + border-radius: 4px; + border: 2px solid var(--focus-ring-color); + } } - .build-content{ + .build-content { flex-grow: 1; + width: 0; } ` diff --git a/packages/client/dashboard/src/components/icons/CircleIcon.tsx b/packages/client/dashboard/src/components/icons/CircleIcon.tsx index b429880..33aeb61 100644 --- a/packages/client/dashboard/src/components/icons/CircleIcon.tsx +++ b/packages/client/dashboard/src/components/icons/CircleIcon.tsx @@ -7,7 +7,7 @@ export default function CircleIcon ({ bgc = '#5BA85A' }: { bgc?: string }) { fill='none' xmlns='http://www.w3.org/2000/svg' > - + ) } diff --git a/packages/client/dashboard/src/components/icons/guideSteps/1.png b/packages/client/dashboard/src/components/icons/guideSteps/1.png new file mode 100644 index 0000000..5575091 Binary files /dev/null and b/packages/client/dashboard/src/components/icons/guideSteps/1.png differ diff --git a/packages/client/dashboard/src/components/icons/guideSteps/2.png b/packages/client/dashboard/src/components/icons/guideSteps/2.png new file mode 100644 index 0000000..86f18f8 Binary files /dev/null and b/packages/client/dashboard/src/components/icons/guideSteps/2.png differ diff --git a/packages/client/dashboard/src/components/icons/guideSteps/3.png b/packages/client/dashboard/src/components/icons/guideSteps/3.png new file mode 100644 index 0000000..41b4500 Binary files /dev/null and b/packages/client/dashboard/src/components/icons/guideSteps/3.png differ diff --git a/packages/client/dashboard/src/components/icons/guideSteps/4.png b/packages/client/dashboard/src/components/icons/guideSteps/4.png new file mode 100644 index 0000000..7de839c Binary files /dev/null and b/packages/client/dashboard/src/components/icons/guideSteps/4.png differ diff --git a/packages/client/dashboard/src/components/icons/guideSteps/5.png b/packages/client/dashboard/src/components/icons/guideSteps/5.png new file mode 100644 index 0000000..3f3cfe0 Binary files /dev/null and b/packages/client/dashboard/src/components/icons/guideSteps/5.png differ diff --git a/packages/client/dashboard/src/components/model/ExploreModelList.tsx b/packages/client/dashboard/src/components/model/ExploreModelList.tsx index 462e2e4..cb72a24 100644 --- a/packages/client/dashboard/src/components/model/ExploreModelList.tsx +++ b/packages/client/dashboard/src/components/model/ExploreModelList.tsx @@ -379,7 +379,7 @@ function Actions ({ const { s3ModelCollection } = useSelectedDapp() const [staring, setStaring] = useState(false) - const { loadDapps } = useAppCtx() + const { loadDapps, loadCurrDapp } = useAppCtx() const { selectedDapp } = useSelectedDapp() const [adding, setAdding] = useState(false) const addModelToDapp = useCallback( @@ -403,13 +403,14 @@ function Actions ({ ceramicNodeId ) await loadDapps() + await loadCurrDapp() } catch (err) { console.error(err) } finally { setAdding(false) } }, - [loadDapps, selectedDapp, session, setAdding, hasIndexed, ceramicNodeId] + [session, selectedDapp, ceramicNodeId, hasIndexed, loadDapps, loadCurrDapp] ) const collectModel = useCallback( diff --git a/packages/client/dashboard/src/components/model/ModelSDK.tsx b/packages/client/dashboard/src/components/model/ModelSDK.tsx index 00b0994..8e1b91e 100644 --- a/packages/client/dashboard/src/components/model/ModelSDK.tsx +++ b/packages/client/dashboard/src/components/model/ModelSDK.tsx @@ -8,20 +8,19 @@ import 'prismjs/plugins/line-numbers/prism-line-numbers.js' import { useCallback, useEffect, useState } from 'react' import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components' import styled from 'styled-components' -import { getModelSDK } from '../../api/model' -import useSelectedDapp from '../../hooks/useSelectedDapp' +import { getModelSDK, getModelsInfoByIds } from '../../api/model' import { GraphqlGenType, Network } from '../../types.d' import { sdkTemplate } from './sdkTemplate' -export default function ModelSDK({ +export default function ModelSDK ({ modelId, - modelName, + network, + modelName }: { modelId: string - modelName: string + network: Network + modelName?: string }) { - const { selectedDapp } = useSelectedDapp() - const [codes, setCodes] = useState< { id: number; title: string; content: string }[] >([]) @@ -35,25 +34,26 @@ export default function ModelSDK({ } const zip = new JSZip() - codes.forEach((item) => { + codes.forEach(item => { zip.file(item.title, item.content) }) zip .generateAsync({ type: 'blob' }) .then(function (content) { - FileSaver.saveAs(content, `${camelCase(modelName)}SDK.zip`) + FileSaver.saveAs(content, `${camelCase(modelName || '')}SDK.zip`) }) .catch(console.error) }, [codes, modelName]) const fetchModelSDK = useCallback(async () => { + if (!modelId || !network || !modelName) return try { setLoading(true) setErrMsg('') const resp = await getModelSDK({ - network: selectedDapp?.network as Network, + network: network, modelId: modelId, - type: genType, + type: genType }) if (resp.data.code !== 0) { throw new Error(resp.data.msg) @@ -66,7 +66,7 @@ export default function ModelSDK({ } const runtimeComposite = data.find( - (item) => item.filename === 'runtime-composite.ts' + item => item.filename === 'runtime-composite.ts' ) if (!runtimeComposite) { throw new Error('no runtime-composite') @@ -89,14 +89,14 @@ export const definition = ${JSON.stringify( [ { filename: `S3${modelName}Model.ts`, - content: sdkContent, + content: sdkContent }, runtimeComposite, - graphql, + graphql ].map((item, i) => ({ title: item.filename, content: item.content, - id: i, + id: i })) ) } catch (error) { @@ -105,12 +105,24 @@ export const definition = ${JSON.stringify( } finally { setLoading(false) } - }, [selectedDapp?.network, modelId, genType, modelName]) + }, [network, modelId, genType, modelName]) useEffect(() => { fetchModelSDK() }, [fetchModelSDK]) + // useEffect(() => { + // if (!modelId || !network) return + // if (!modelName) { + // getModelsInfoByIds({ + // network, + // ids: [modelId] + // }).then(resp => { + // modelName = resp.data.data[0].stream_content.name + // }) + // } + // }, [network, modelId, genType, modelName]) + return ( {/* */} {(errMsg && ( -
+

An Error Occurred Please Try Again Later.

-

{errMsg}

+

{errMsg}

)) || ( <> @@ -137,19 +149,26 @@ export const definition = ${JSON.stringify( - {(item) => {item.title}} + {item => ( + + {item.title} + + )} - {codes.map((item) => ( - - - - ))} + {codes.map(item => { + console.log('item', item) + return ( + + + + ) + })} )} @@ -159,7 +178,7 @@ export const definition = ${JSON.stringify( ) } -export function Code({ name, content }: { name: string; content: string }) { +export function Code ({ name, content }: { name: string; content: string }) { useEffect(() => { Prism.highlightAll() }, [content]) @@ -168,7 +187,7 @@ export function Code({ name, content }: { name: string; content: string }) { return (
diff --git a/packages/client/dashboard/src/components/nav/Nav.tsx b/packages/client/dashboard/src/components/nav/Nav.tsx index aca3359..81fe5df 100644 --- a/packages/client/dashboard/src/components/nav/Nav.tsx +++ b/packages/client/dashboard/src/components/nav/Nav.tsx @@ -3,7 +3,6 @@ import { Link, NavLink } from 'react-router-dom' import styled from 'styled-components' import { DOCS_URL } from '../../constants' import ChartIcon from '../icons/ChartIcon' -import ChevronRight from '../icons/ChevronRight' import ComponentIcon from '../icons/ComponentIcon' import DocIcon from '../icons/DocIcon' import ExploreIcon from '../icons/ExploreIcon' @@ -101,7 +100,7 @@ export default function Nav ({ appId }: { appId: string }) {
{navItems.map(item => ( - + ))}
@@ -162,7 +161,7 @@ function NavItemRenderer ({ {item.items && (
{item.items.map(item => ( - + ))}
)} diff --git a/packages/client/dashboard/src/components/node/CreateCeramicNodeModal.tsx b/packages/client/dashboard/src/components/node/CreateCeramicNodeModal.tsx index 9fbbab3..8d9afac 100644 --- a/packages/client/dashboard/src/components/node/CreateCeramicNodeModal.tsx +++ b/packages/client/dashboard/src/components/node/CreateCeramicNodeModal.tsx @@ -18,7 +18,7 @@ export default function CreateCeramicNodeModal ({ onSussess }: { fixedNetwork?: CeramicNetwork - closeModal: () => void + closeModal?: () => void onSussess: () => void }) { const [submitting, setSubmitting] = useState(false) @@ -55,8 +55,8 @@ export default function CreateCeramicNodeModal ({ if (resp.data.code !== 0) { throw new Error(resp.data.msg) } - onSussess() - closeModal() + onSussess?.() + closeModal?.() } catch (error) { console.error(error) } finally { @@ -77,9 +77,11 @@ export default function CreateCeramicNodeModal ({

Create Ceramic Node

- + {closeModal && ( + + )}
@@ -124,7 +126,11 @@ export default function CreateCeramicNodeModal ({ )) || ( - )} diff --git a/packages/client/dashboard/src/container/CeramicNodes.tsx b/packages/client/dashboard/src/container/CeramicNodes.tsx index 92bae35..7181deb 100644 --- a/packages/client/dashboard/src/container/CeramicNodes.tsx +++ b/packages/client/dashboard/src/container/CeramicNodes.tsx @@ -10,7 +10,13 @@ import { useSession } from '@us3r-network/auth-with-rainbowkit' import dayjs from 'dayjs' import { useEffect, useState } from 'react' -import { Button, Dialog, DialogTrigger, Modal, ModalOverlay } from 'react-aria-components' +import { + Button, + Dialog, + DialogTrigger, + Modal, + ModalOverlay +} from 'react-aria-components' import styled from 'styled-components' import PlusIcon from '../components/icons/PlusIcon' import TrashIcon from '../components/icons/TrashIcon' @@ -41,7 +47,7 @@ export default function CeramicNodes () { }, 5000) } } - return ()=>{ + return () => { if (timer) clearTimeout(timer) } }, [ceramicNodes, loadCeramicNodes]) @@ -86,9 +92,7 @@ export default function CeramicNodes () { const active = currCeramicNode?.id === item.id return (
-
+
{item.name}
{active && ( @@ -104,7 +108,7 @@ export default function CeramicNodes () { })} - {currCeramicNode && } + {currCeramicNode && } ) } @@ -159,7 +163,13 @@ function DeleteNodeButton ({ node }: { node: CeramicDto }) { ) } -function CeramicNodeInfo ({ node }: { node: CeramicDto }) { +export function CeramicNodeInfo ({ + node, + showTerminal +}: { + node: CeramicDto + showTerminal?: boolean +}) { const session = useSession() return ( @@ -171,7 +181,7 @@ function CeramicNodeInfo ({ node }: { node: CeramicDto }) {
- + {node.status === CeramicStatus.PREPARING ? (
{/* */} @@ -209,7 +219,7 @@ function CeramicNodeInfo ({ node }: { node: CeramicDto }) {
) : null} - {node?.id && + {showTerminal && node?.id && (node.status === CeramicStatus.STARTING || node.status === CeramicStatus.RUNNING) && session?.did && ( @@ -341,9 +351,11 @@ const NodesListBox = styled.div` } ` const NodeInfoContainer = styled.div` + width: 100%; height: 100%; display: flex; flex-direction: column; + /* justify-content: center; */ gap: 20px; flex-shrink: 1; flex-grow: 1; @@ -351,6 +363,7 @@ const NodeInfoContainer = styled.div` const NodeInfoBox = styled.div` width: 100%; padding: 20px; + box-sizing: border-box; border-radius: 20px; border: 1px solid #39424c; background: #1b1e23; diff --git a/packages/client/dashboard/src/container/DappCreate.tsx b/packages/client/dashboard/src/container/DappCreate.tsx deleted file mode 100644 index 21d20b0..0000000 --- a/packages/client/dashboard/src/container/DappCreate.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import { - useAuthentication, - useSession -} from '@us3r-network/auth-with-rainbowkit' -import { useCallback, useState } from 'react' -import { useNavigate } from 'react-router-dom' -import styled from 'styled-components' -import { createDapp } from '../api/dapp' -import EnumSelect from '../components/common/EnumSelect' -import { useAppCtx } from '../context/AppCtx' -import { Network } from '../types.d' - -export default function DappCreate () { - const navigate = useNavigate() - const [network, setNetwork] = useState(Network.TESTNET) - const { signIn } = useAuthentication() - const session = useSession() - const { loadDapps } = useAppCtx() - - const [appName, setAppName] = useState('') - const [creating, setCreating] = useState(false) - - const createAction = useCallback(async () => { - if (!session?.id) { - signIn() - return - } - - try { - setCreating(true) - const resp = await createDapp( - { name: appName, network }, - session.serialize() - ) - if (resp.data.code !== 0) { - throw new Error(resp.data.msg) - } - await loadDapps() - navigate(`/dapp/${resp.data.data.id}/index`) - } catch (error) { - console.error(error) - } finally { - setCreating(false) - } - }, [appName, navigate, network, session, signIn, loadDapps]) - - return ( - -
-

Create Application

-
-
- * App Name: - setAppName(e.target.value)} - /> -
- - - -
- - {creating ? ( - - ) : ( - - )} -
-
-
-
- ) -} - -const DappCreateContainer = styled.main` - > div { - display: flex; - flex-direction: column; - gap: 20px; - - h1 { - font-style: italic; - font-weight: 700; - font-size: 24px; - line-height: 28px; - margin: 0; - margin-top: 20px; - color: #ffffff; - } - - > div { - background: #1b1e23; - border-radius: 20px; - display: flex; - flex-direction: column; - justify-content: center; - padding: 40px; - gap: 40px; - - .app-name { - display: flex; - flex-direction: column; - - > span { - font-weight: 500; - font-size: 16px; - line-height: 24px; - margin-bottom: 8px; - } - - > input { - background: #1a1e23; - outline: none; - border: 1px solid #39424c; - border-radius: 12px; - height: 48px; - padding: 0px 16px; - color: #ffffff; - font-weight: 400; - font-size: 16px; - line-height: 24px; - } - } - - .btns { - display: flex; - align-items: center; - justify-content: end; - gap: 20px; - - button { - font-weight: 500; - font-size: 16px; - line-height: 24px; - - text-align: center; - - width: 120px; - background: none; - outline: none; - border: none; - cursor: pointer; - border: 1px solid #39424c; - border-radius: 24px; - height: 48px; - &.cancel { - background: #1b1e23; - - color: #ffffff; - } - - &.create { - color: #14171a; - background: #ffffff; - border-radius: 24px; - } - - > img { - height: 27px; - } - } - } - } - } -` diff --git a/packages/client/dashboard/src/container/DappQuickStart.tsx b/packages/client/dashboard/src/container/DappQuickStart.tsx new file mode 100644 index 0000000..467e8e0 --- /dev/null +++ b/packages/client/dashboard/src/container/DappQuickStart.tsx @@ -0,0 +1,495 @@ +import { + useAuthentication, + useSession +} from '@us3r-network/auth-with-rainbowkit' +import { useCallback, useEffect, useState } from 'react' +import { Button, Radio, RadioGroup } from 'react-aria-components' +import { useNavigate } from 'react-router-dom' +import styled from 'styled-components' +import { createDapp } from '../api/dapp' +import EnumSelect from '../components/common/EnumSelect' +import { useAppCtx } from '../context/AppCtx' +import { CeramicNetwork, CeramicStatus, Network } from '../types.d' + +import Step_1_Icon from '../components/icons/guideSteps/1.png' +import Step_2_Icon from '../components/icons/guideSteps/2.png' +import Step_3_Icon from '../components/icons/guideSteps/3.png' +import Step_4_Icon from '../components/icons/guideSteps/4.png' +// import Step_5_Icon from '../components/icons/guideSteps/5.png' +// import { CompositeList } from '../components/model/ExploreCompositeList' +import CreateCeramicNodeModal from '../components/node/CreateCeramicNodeModal' +import ModelSDK from '../components/model/ModelSDK' +import { useCeramicNodeCtx } from '../context/CeramicNodeCtx' +import { CeramicNodeInfo } from './CeramicNodes' +import { uniq } from 'lodash' +import ModelList from '../components/model/ExploreModelList' +import React from 'react' + +const CreateDapp = () => { + const [network, setNetwork] = useState(Network.TESTNET) + const { signIn } = useAuthentication() + const session = useSession() + const { loadDapps, currDapp, setCurrAppId } = useAppCtx() + + const [appName, setAppName] = useState('') + const [creating, setCreating] = useState(false) + + const createAction = useCallback(async () => { + if (!session?.id) { + signIn() + return + } + + try { + setCreating(true) + const resp = await createDapp( + { name: appName, network }, + session.serialize() + ) + if (resp.data.code !== 0) { + throw new Error(resp.data.msg) + } + setCurrAppId(String(resp.data.data.id)) + await loadDapps() + } catch (error) { + console.error(error) + } finally { + setCreating(false) + } + }, [session, signIn, appName, network, setCurrAppId, loadDapps]) + + return ( + + {currDapp ? ( +
+
+

App Name: {currDapp.name}

+

Network: {currDapp.network}

+

App ID: {currDapp.id}

+

Created At: {currDapp.createdAt}

+
+

+ Your dapp has been created; proceed to the next step to continue. +

+
+ ) : ( +
+
+
+ * App Name: + setAppName(e.target.value)} + /> +
+ + + +
+ {creating ? ( + + ) : ( + + )} +
+
+

+ Fill in the required information to create a dapp, and testnet + network is recommended during the development. +

+
+ )} +
+ ) +} + +const DeployNode = () => { + const { ceramicNodes, currCeramicNode, loadCeramicNodes } = + useCeramicNodeCtx() + useEffect(() => { + let timer: NodeJS.Timeout | undefined + // console.log('ceramicNodes changes: ', ceramicNodes) + if (ceramicNodes.length > 0) { + if (ceramicNodes[0].status !== CeramicStatus.RUNNING) { + timer = setTimeout(() => { + loadCeramicNodes() + }, 5000) + } + } + return () => { + if (timer) clearTimeout(timer) + } + }, [ceramicNodes, loadCeramicNodes]) + if (currCeramicNode) { + return ( + <> + +

+ Since you already have a Ceramic node set up, you can proceed to the + next step. +

+ + ) + } + return ( + <> + {' '} +

+ You must create a Ceramic node, as all data operations will be executed + on this node. +

+ + ) +} + +const Explore = () => { + return ( + <> + +

+ Browse through the current collection of models and choose a model that + you wish to incorporate into your dapp. +

+ + ) +} + +const StartBuilding = () => { + const { currDapp } = useAppCtx() + const firstModel = currDapp?.modelDetails?.[0] + if (firstModel) { + return ( + <> + {' '} + +

+ Using the automatically generated SDK, you can now directly perform + CRUD operations on data; let's begin coding. +

+ + ) + } else { + return
No Model in this Dapp!
+ } +} + +const STEPS = [ + { + id: 1, + title: 'Create Application', + icon: Step_1_Icon, + guideText: + 'Fill in some simple information to start developing your App or DApp.', + component: CreateDapp, + enable: true, + done: false + }, + { + id: 2, + title: 'Deploy Node', + icon: Step_2_Icon, + guideText: 'Before you start, you also need to deploy a node for your App.', + component: DeployNode, + enable: true, + done: false + }, + { + id: 3, + title: 'Explore Models, Composites and Components', + icon: Step_3_Icon, + guideText: + 'You can view the models, composites or components that others have created and add them to your App. Now try adding a model.', + component: Explore, + enable: false, + done: false + }, + { + id: 4, + title: 'Start Building', + icon: Step_4_Icon, + guideText: + 'You can check the components and SDKs for each model for future development.', + component: StartBuilding, + enable: false, + done: false + } +] + +export default function DappQuickStart () { + const navigate = useNavigate() + const [currentStep, setCurrentStep] = useState(1) + const [disabledSteps, setDisabledSteps] = useState(['3', '4']) + const [completedSteps, setCompletedSteps] = useState([]) + + const { currCeramicNode } = useCeramicNodeCtx() + const { currDapp } = useAppCtx() + + useEffect(() => { + if (currCeramicNode) { + setCompletedSteps(uniq([...completedSteps, 1])) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currCeramicNode]) + + useEffect(() => { + if (currDapp) { + setCompletedSteps(uniq([...completedSteps, 0])) + if (currDapp?.models?.length) { + setCompletedSteps(uniq([...completedSteps, 2])) + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currDapp]) + + useEffect(() => { + if (completedSteps.includes(0) && completedSteps.includes(1)) { + if (completedSteps.includes(2)) { + setDisabledSteps([]) + } else { + setDisabledSteps(['4']) + } + } else { + setDisabledSteps(['3', '4']) + } + }, [completedSteps]) + + const step = STEPS[currentStep - 1] + return ( + +
+ {} +
+ {currentStep < STEPS.length && + !disabledSteps.includes(String(currentStep + 1)) && ( + + )} + {currDapp && + completedSteps.includes(0) && + completedSteps.includes(1) && ( + + )} +
+
+
+ setCurrentStep(Number(value))} + > + {STEPS.map(item => ( + + {item.id} + + ))} + +
+ +

{STEPS[currentStep - 1]?.title}

+

{STEPS[currentStep - 1]?.guideText}

+
+
+
+ ) +} + +const Box = styled.main` + margin-top: 20px; + margin-bottom: 20px; + width: 100%; + height: 100%; + display: flex; + flex-direction: row; + align-items: start; + justify-content: center; + gap: 20px; + + .steps-container { + display: flex; + flex-direction: row; + /* align-items: center; */ + justify-content: center; + gap: 20px; + } + .step-info { + width: 300px; + margin-top: 100px; + /* height: 600px; */ + display: flex; + flex-direction: row; + /* align-items: center; */ + /* justify-content: end; */ + gap: 20px; + } + .step-tabs { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; + margin-bottom: 20px; + + .step { + display: flex; + align-items: center; + justify-content: center; + background: #1b1e23; + border: 2px solid transparent; + border-radius: 50%; + width: 40px; + height: 40px; + font-weight: 500; + font-size: 16px; + line-height: 24px; + color: #ffffff; + cursor: pointer; + + &[data-disabled] { + color: grey; + cursor: not-allowed; + } + &[data-hovered] { + border-color: white; + } + &[data-selected] { + background: #ffffff; + color: #14171a; + } + } + } + .step-action { + width: 800px; + height: 600px; + display: flex; + flex-direction: column; + align-items: center; + /* justify-content: center; */ + gap: 20px; + } +` + +const DappCreateContainer = styled.div` + width: 100%; + > div { + display: flex; + flex-direction: column; + gap: 20px; + + h1 { + font-style: italic; + font-weight: 700; + font-size: 24px; + line-height: 28px; + margin: 0; + margin-top: 20px; + color: #ffffff; + } + + > div { + background: #1b1e23; + border-radius: 20px; + display: flex; + flex-direction: column; + justify-content: center; + padding: 40px; + gap: 40px; + + .app-name { + display: flex; + flex-direction: column; + + > span { + font-weight: 500; + font-size: 16px; + line-height: 24px; + margin-bottom: 8px; + } + + > input { + background: #1a1e23; + outline: none; + border: 1px solid #39424c; + border-radius: 12px; + height: 48px; + padding: 0px 16px; + color: #ffffff; + font-weight: 400; + font-size: 16px; + line-height: 24px; + } + } + + .btns { + display: flex; + align-items: center; + justify-content: end; + gap: 20px; + + button { + font-weight: 500; + font-size: 16px; + line-height: 24px; + + text-align: center; + + width: 120px; + background: none; + outline: none; + border: none; + cursor: pointer; + border: 1px solid #39424c; + border-radius: 24px; + height: 48px; + &.cancel { + background: #1b1e23; + + color: #ffffff; + } + + &.create { + color: #14171a; + background: #ffffff; + border-radius: 24px; + } + + > img { + height: 27px; + } + } + } + } + } +` diff --git a/packages/client/dashboard/src/container/DappSdk.tsx b/packages/client/dashboard/src/container/DappSdk.tsx index 910095b..9c304b9 100644 --- a/packages/client/dashboard/src/container/DappSdk.tsx +++ b/packages/client/dashboard/src/container/DappSdk.tsx @@ -2,14 +2,16 @@ import { useOutletContext } from 'react-router-dom' import ModelSDK from '../components/model/ModelSDK' import { DappCompositeDto, ModelStream } from '../types' import { BuildContentBox } from './DappEditor' +import { useAppCtx } from '../context/AppCtx' export default function DappSdk () { + const { currDapp } = useAppCtx() const { selectModel } = useOutletContext<{ selectModel: ModelStream selectComposite: DappCompositeDto }>() - if (selectModel) { + if (selectModel && currDapp) { const name = selectModel.stream_content.name const modelId = selectModel.stream_id @@ -19,7 +21,7 @@ export default function DappSdk () { {name} SDK
- +
) diff --git a/packages/client/dashboard/src/container/MyDapps.tsx b/packages/client/dashboard/src/container/MyDapps.tsx index b7cca62..9f8cd10 100644 --- a/packages/client/dashboard/src/container/MyDapps.tsx +++ b/packages/client/dashboard/src/container/MyDapps.tsx @@ -10,9 +10,14 @@ import { useAppCtx } from '../context/AppCtx' import { ClientDApp } from '../types.d' import { createImageFromInitials } from '../utils/createImage' import { getRandomColor } from '../utils/randomColor' +import { useEffect } from 'react' export default function MyDapps() { - const { dapps } = useAppCtx() + const { dapps, setCurrAppId } = useAppCtx() + setCurrAppId('') + useEffect(() => { + setCurrAppId('') + }, [setCurrAppId]) return (
diff --git a/packages/client/dashboard/src/context/AppCtx.tsx b/packages/client/dashboard/src/context/AppCtx.tsx index efdad9e..e17ef00 100644 --- a/packages/client/dashboard/src/context/AppCtx.tsx +++ b/packages/client/dashboard/src/context/AppCtx.tsx @@ -4,7 +4,7 @@ import React, { useCallback, useContext, useEffect, - useState, + useState } from 'react' import { getDapp, getDappWithDid } from '../api/dapp' import { useGuideStepsState } from '../hooks/useGuideSteps' @@ -22,13 +22,14 @@ export interface AppContextData { currAppId: string setCurrAppId: React.Dispatch> loadDapps: () => Promise + loadCurrDapp: () => Promise guideSteps: ReturnType } const AppContext = createContext(null) -export default function AppProvider({ - children, +export default function AppProvider ({ + children }: { children: React.ReactNode }) { @@ -93,8 +94,9 @@ export default function AppProvider({ currAppId, setCurrAppId, loadDapps, + loadCurrDapp, loadingDApps: loadingDApps || loadingDApp, - guideSteps, + guideSteps }} > {children} @@ -102,12 +104,12 @@ export default function AppProvider({ ) } -export function useAppCtx() { +export function useAppCtx () { const context = useContext(AppContext) if (!context) { throw new Error('Missing connection context') } return { - ...context, + ...context } } diff --git a/packages/client/dashboard/src/hooks/useSelectedDapp.ts b/packages/client/dashboard/src/hooks/useSelectedDapp.ts index dbd2df4..338033d 100644 --- a/packages/client/dashboard/src/hooks/useSelectedDapp.ts +++ b/packages/client/dashboard/src/hooks/useSelectedDapp.ts @@ -6,7 +6,7 @@ import { useAppCtx } from '../context/AppCtx' import { Network } from '../types.d' export default function useSelectedDapp() { - const { dapps } = useAppCtx() + const { dapps, currAppId } = useAppCtx() const { appId } = useParams() const selectDapps = useMemo(() => { return ( @@ -19,8 +19,8 @@ export default function useSelectedDapp() { }, [dapps]) const selectedDapp = useMemo(() => { - return selectDapps?.find((item) => item.id === Number(appId)) - }, [selectDapps, appId]) + return selectDapps?.find((item) => item.id === Number(currAppId || appId)) + }, [selectDapps, currAppId, appId]) const s3ModelCollection = useMemo(() => { if (selectedDapp?.network === Network.MAINNET) { diff --git a/packages/client/dashboard/src/styles/react-aria/index.css b/packages/client/dashboard/src/styles/react-aria/index.css index 5b3fddc..58dea42 100644 --- a/packages/client/dashboard/src/styles/react-aria/index.css +++ b/packages/client/dashboard/src/styles/react-aria/index.css @@ -6,5 +6,4 @@ @import 'menu.css'; @import 'modal.css'; @import 'popover.css'; -@import 'tabs.css'; @import 'textfield.css'; diff --git a/packages/client/dashboard/src/styles/react-aria/tabs.css b/packages/client/dashboard/src/styles/react-aria/tabs.css deleted file mode 100644 index d8958d0..0000000 --- a/packages/client/dashboard/src/styles/react-aria/tabs.css +++ /dev/null @@ -1,66 +0,0 @@ -/* Tabs */ -.react-aria-Tabs { - position: relative; - --text-color-base:black; - --highlight-background: white; - width: 100%; -} - -.react-aria-TabList { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - - &[data-orientation=horizontal] { - border: 1px solid var(--border-color); - border-radius: 999px; - } -} - -.react-aria-Tab { - padding: 10px 20px; - cursor: default; - outline: none; - position: relative; - color: var(--text-color-base); - transition: color 200ms; - --border-color: transparent; - forced-color-adjust: none; - border-radius: 999px; - a { - color: var(--text-color); - } - - &[data-hovered], - &[data-focused] { - color: var(--text-color-hover); - } - - &[data-selected] { - background-color: var(--highlight-background); - color: var(--text-color-base); - a { - color: var(--text-color-base); - } - } - - &[data-disabled] { - color: var(--text-color-disabled); - &[data-selected] { - --border-color: var(--text-color-disabled); - } - } - - &[data-focus-visible]:after { - content: ''; - position: absolute; - inset: 4px; - border-radius: 4px; - border: 2px solid var(--focus-ring-color); - } -} - -.react-aria-TabPanel { - -} \ No newline at end of file diff --git a/packages/client/dashboard/src/types.d.ts b/packages/client/dashboard/src/types.d.ts index c979d92..eaa16dd 100644 --- a/packages/client/dashboard/src/types.d.ts +++ b/packages/client/dashboard/src/types.d.ts @@ -104,6 +104,7 @@ export type ClientDApp = { socialLinks?: { platform: string; url: string }[] tags?: string[] models?: string[] + modelDetails?: ModelStream[] composites?: DappCompositeDto[]; createdAt?: number lastModifiedAt?: number @@ -184,9 +185,9 @@ export type ModelStream = { stream_id: string controller_did: string tip: string - streamContent: { - name: string - } + // streamContent: { + // name: string + // } stream_content: { name: string description: string | null