From 5c6e2129207feda00bae216445cd3c4f17e8d2b0 Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 18:04:05 +0800 Subject: [PATCH 1/8] rename dapp models and composites component --- packages/client/dashboard/src/App.tsx | 4 +- .../src/components/model/ModelList.tsx | 653 ------------------ 2 files changed, 2 insertions(+), 655 deletions(-) delete mode 100644 packages/client/dashboard/src/components/model/ModelList.tsx diff --git a/packages/client/dashboard/src/App.tsx b/packages/client/dashboard/src/App.tsx index 9f0e641..d4cf6f9 100644 --- a/packages/client/dashboard/src/App.tsx +++ b/packages/client/dashboard/src/App.tsx @@ -36,7 +36,7 @@ import NoMatch from './container/NoMatch' import Header from './components/nav/Header' import Nav from './components/nav/Nav' -import ModelList from './components/model/ModelList' +import DappModelAndComposites from './components/model/DappModelAndComposites' import ExploreComposite from './container/ExploreComposite' dayjs.extend(relativeTime) @@ -182,7 +182,7 @@ function ModelEditorLayout () { return ( - { setSelectModel(data) diff --git a/packages/client/dashboard/src/components/model/ModelList.tsx b/packages/client/dashboard/src/components/model/ModelList.tsx deleted file mode 100644 index 51920b3..0000000 --- a/packages/client/dashboard/src/components/model/ModelList.tsx +++ /dev/null @@ -1,653 +0,0 @@ -import { useSession } from '@us3r-network/auth-with-rainbowkit' -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { - Button, - Dialog, - DialogTrigger, - Menu, - MenuItem, - MenuTrigger, - Modal, - ModalOverlay, - Popover -} from 'react-aria-components' -import { useLocation, useNavigate } from 'react-router-dom' -import styled from 'styled-components' -import { deleteDappComposites, getDappComposites } from '../../api/composite' -import { updateDapp } from '../../api/dapp' -import { getDappModels, getModelsInfoByIds } from '../../api/model' -import { useAppCtx } from '../../context/AppCtx' -import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' -import useIsOwner from '../../hooks/useIsOwner' -import useSelectedDapp from '../../hooks/useSelectedDapp' -import { - CeramicStatus, - DappCompositeDto, - ModelStream, - Network -} from '../../types.d' -import { shortPubKey } from '../../utils/shortPubKey' -import CopyTint from '../common/CopyTint' -import MergeIcon from '../icons/MergeIcon' -import PlusIcon from '../icons/PlusIcon' -import TrashIcon from '../icons/TrashIcon' -import NoCeramicNodeModal from '../node/NoCeramicNodeModal' -import CreateCompositeModal from './CreateCompositeModal' -import CreateNewModel from './CreateNewModel' -import FavoriteModel from './FavoriteModal' -import MergeModal from './MergeModal' -import { getCompositeDefaultSchema } from '../../utils/composedb-types/schemas' - -enum OPEN_MODAL { - NONE, - CREATE_NEW_MODEL, - ADD_FROM_ALL_MODELS, - ADD_FROM_FAVORITE_MODELS, - CREATE_NEW_COMPOSITE, - ADD_FROM_ALL_COMPOSITES, - ADD_FROM_FAVORITE_COMPOSITES -} - -export default function ModelList ({ - editable, - selectComposite, - setSelectComposite, - selectModel, - setSelectModel -}: { - selectModel: ModelStream | undefined - setSelectModel: (m: ModelStream | undefined) => void - selectComposite: DappCompositeDto | undefined - setSelectComposite: (composite: DappCompositeDto | undefined) => void - - editable?: boolean -}) { - const session = useSession() - const { loadDapps, currDapp } = useAppCtx() - const { appId, selectedDapp } = useSelectedDapp() - const { currCeramicNode } = useCeramicNodeCtx() - const navigate = useNavigate() - const [loading, setLoading] = useState(false) - const [dappModels, setDappModels] = useState() - const [dappComposites, setDappComposites] = useState([]) - const location = useLocation() - - const dapp = useMemo(() => { - return selectedDapp || currDapp - }, [selectedDapp, currDapp]) - - const { isOwner } = useIsOwner() - - const loadModelsInfo = useCallback(async () => { - if (dapp?.models?.length === 0 || !dapp) { - setDappModels([]) - return - } - - try { - const resp = await getModelsInfoByIds({ - network: dapp.network as Network, - ids: dapp.models || [] - }) - - const list = resp.data.data - setDappModels(list) - if (list.length > 0) { - setSelectModel(list[0]) - } - } catch (error) { - console.error(error) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dapp]) - - // const loadDappModels = useCallback(async () => { - // if (!dapp) return - // try { - // const resp = await getDappModels({ - // dapp - // }) - // if (resp.data.code !== 0) throw new Error(resp.data.msg) - // setDappModels(resp.data.data) - // } catch (error) { - // console.error(error) - // } - // }, [dapp]) - - const loadDappComposites = useCallback(async () => { - if (!dapp) return - try { - const resp = await getDappComposites({ - dapp - }) - if (resp.data.code !== 0) throw new Error(resp.data.msg) - setDappComposites(resp.data.data) - } catch (error) { - console.error(error) - } - }, [dapp]) - - const removeModelFromDapp = useCallback( - async (modelId: string) => { - if (!session) return - if (!selectedDapp) return - - try { - const newModels = - selectedDapp?.models?.filter(id => id !== modelId) || [] - - await updateDapp( - { ...selectedDapp, models: newModels }, - session.serialize() - ) - await loadDapps() - setSelectModel(undefined) - } catch (error) { - console.error(error) - } - }, - [loadDapps, selectedDapp, session, setSelectModel] - ) - - const delDappComposite = useCallback( - async (id: number) => { - if (!session) return - if (!selectedDapp) return - try { - await deleteDappComposites({ - compositeId: id, - did: session.serialize(), - dapp: selectedDapp - }) - await loadDappComposites() - setSelectComposite(undefined) - } catch (error) { - console.error(error) - } - }, - [session, selectedDapp, loadDappComposites, setSelectComposite] - ) - - const isFirstRenderRef = useRef(true) - const [mounted, setMounted] = useState(false) - - useEffect(() => { - setMounted(true) - }, []) - - useEffect(() => { - if (!mounted) return - if (isFirstRenderRef.current) { - isFirstRenderRef.current = false - setLoading(true) - } - - Promise.all([loadDappComposites(), loadModelsInfo()]).finally(() => - setLoading(false) - ) - }, [loadModelsInfo, loadDappComposites, mounted]) - - useEffect(() => { - setSelectModel(undefined) - setDappModels(undefined) - setSelectComposite(undefined) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [appId]) - - const isMetrics = location.pathname.endsWith('statistic') - const isSdk = location.pathname.endsWith('sdk') - - const [openModal, setOpenModal] = useState(OPEN_MODAL.NONE) - if (loading) { - return ( - -
- -
-
- ) - } - - return ( - -
-

Models

- {editable && - isOwner && - (!currCeramicNode || - currCeramicNode.status !== CeramicStatus.RUNNING ? ( - - - - - - {({ close }) => } - - - - - ) : ( - - - - { - if (id === 'explore') { - navigate(`/dapp/${appId}/explore/model`) - return - } - if (id === 'favorite') { - setOpenModal(OPEN_MODAL.ADD_FROM_FAVORITE_MODELS) - return - } - if (id === 'create') { - setOpenModal(OPEN_MODAL.CREATE_NEW_MODEL) - return - } - }} - > - Explore Models - Add From Favorite - Create New Model - - - - ))} -
- - { - setSelectModel(model) - }} - removeModelAction={async (id: string) => { - await removeModelFromDapp(id) - if (id === selectModel?.stream_id) { - setSelectModel(undefined) - setDappModels(undefined) - setSelectModel(undefined) - } - }} - /> - - {!(isMetrics || isSdk) && ( - <> -
-

Composites

- {editable && - isOwner && - (!currCeramicNode || - currCeramicNode.status !== CeramicStatus.RUNNING ? ( - - - - - - {({ close }) => ( - - )} - - - - - ) : ( - - - - { - if (id === 'explore') { - navigate(`/dapp/${appId}/explore/composite`) - return - } - if (id === 'create') { - setOpenModal(OPEN_MODAL.CREATE_NEW_COMPOSITE) - return - } - }} - > - Explore Composites - Create New Composites - - - - ))} -
- - - - )} - setOpenModal(OPEN_MODAL.NONE)} - > - {({ close }) => } - - setOpenModal(OPEN_MODAL.NONE)} - > - - {({ close }) => ( - - )} - - - setOpenModal(OPEN_MODAL.NONE)} - > - {({ close }) => } - - {editable && isOwner && ( - - - - - - - {({ close }) => ( - - )} - - - - - - )} -
- ) -} - -function DappCompositeList ({ - composites, - removeAction, - editable, - selectComposite, - setSelectedComposite -}: { - composites: DappCompositeDto[] - selectComposite: DappCompositeDto | undefined - setSelectedComposite: (composite: DappCompositeDto) => void - removeAction: (id: number) => Promise - editable?: boolean -}) { - if (composites.length === 0) { - return ( - -

This Dapp has no composites available yet.

-
- ) - } - return ( - - {composites?.map(item => { - const active = selectComposite?.id === item.id - return ( -
-
{ - setSelectedComposite(item) - }} - > -
{item.name}
- {editable && ( - { - await removeAction(item.id) - }} - id={item.id + ''} - /> - )} -
-
- ) - })} -
- ) -} - -function DappModelList ({ - selected, - setSelected, - dappModels, - selectAction, - removeModelAction, - editable -}: { - selected?: ModelStream - setSelected: (ms: ModelStream) => void - dappModels: ModelStream[] - selectAction: (model: ModelStream) => void - removeModelAction: (modelId: string) => Promise - editable?: boolean -}) { - if (dappModels.length === 0) { - return ( - -

There is no model in this dapp.

-
- ) - } - return ( - - {dappModels?.map(item => { - const active = selected?.stream_id === item.stream_id - return ( -
-
{ - selectAction(item) - setSelected(item) - }} - > -
{item.stream_content.name}
- {editable && ( - - )} -
- {active && ( - <> -
-
-

ID: {shortPubKey(selected.stream_id, { len: 7 })}

-
- -
-
-

{selected.stream_content.description}

-

- Streams: {selected.useCount} -

- - )} -
- ) - })} -
- ) -} - -function RemoveButton ({ - id, - removeAction -}: { - id: string - removeAction: (id: string) => Promise -}) { - const [removing, setRemoving] = useState(false) - if (removing) { - return ( -
- {' '} -
- ) - } - return ( - - ) -} - -const ListBox = styled.div` - background: #1b1e23; - border: 1px solid #39424c; - border-radius: 20px; - padding: 20px; - display: flex; - flex-direction: column; - align-items: flex-start; - padding: 20px; - gap: 20px; - width: 261px; - min-width: 261px; - box-sizing: border-box; - height: fit-content; - > div { - width: 100%; - } - .title { - height: 42px; - display: flex; - align-items: center; - justify-content: space-between; - > h3 { - font-style: italic; - font-weight: 700; - font-size: 20px; - line-height: 24px; - margin: 0; - color: #ffffff; - } - } - .loading { - width: 100%; - text-align: center; - } -` - -const DappModelsListBox = styled.div` - display: flex; - flex-direction: column; - gap: 20px; - overflow: scroll; - > div { - padding: 10px 16px; - box-sizing: border-box; - border: 1px solid #39424c; - border-radius: 12px; - cursor: pointer; - } - - div.title { - > div { - cursor: pointer; - max-width: 80%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - } - - div.active { - background: rgba(113, 128, 150, 0.3); - border: 1px solid #718096; - border-radius: 12px; - - .id-copy { - display: flex; - align-items: center; - justify-content: space-between; - - > p { - margin: 0; - } - } - } - - hr { - border-color: rgba(255, 255, 255, 0.2); - margin-top: 10px; - } - - p { - color: #718096; - > span { - color: #ffffff; - font-size: 16px; - font-family: Rubik; - font-style: normal; - font-weight: 500; - line-height: normal; - } - } - - .removing { - > img { - width: 20px; - } - } -` - -const MergeBox = styled.div` - .merge-btn { - width: 100%; - background: #718096; - color: #ffffff; - padding: 12px 24px; - border-radius: 12px; - font-weight: 700; - font-size: 16px; - - display: flex; - align-items: center; - justify-content: center; - gap: 10px; - } -` From a4ba42042bed1b9ba88d247267d20a10ab8c9bf9 Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 18:04:17 +0800 Subject: [PATCH 2/8] rename dapp models and composites component --- .../model/DappModelAndComposites.tsx | 653 ++++++++++++++++++ 1 file changed, 653 insertions(+) create mode 100644 packages/client/dashboard/src/components/model/DappModelAndComposites.tsx diff --git a/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx new file mode 100644 index 0000000..b5d4b8e --- /dev/null +++ b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx @@ -0,0 +1,653 @@ +import { useSession } from '@us3r-network/auth-with-rainbowkit' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { + Button, + Dialog, + DialogTrigger, + Menu, + MenuItem, + MenuTrigger, + Modal, + ModalOverlay, + Popover +} from 'react-aria-components' +import { useLocation, useNavigate } from 'react-router-dom' +import styled from 'styled-components' +import { deleteDappComposites, getDappComposites } from '../../api/composite' +import { updateDapp } from '../../api/dapp' +import { getModelsInfoByIds } from '../../api/model' +import { useAppCtx } from '../../context/AppCtx' +import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' +import useIsOwner from '../../hooks/useIsOwner' +import useSelectedDapp from '../../hooks/useSelectedDapp' +import { + CeramicStatus, + DappCompositeDto, + ModelStream, + Network +} from '../../types' +import { getCompositeDefaultSchema } from '../../utils/composedb-types/schemas' +import { shortPubKey } from '../../utils/shortPubKey' +import CopyTint from '../common/CopyTint' +import MergeIcon from '../icons/MergeIcon' +import PlusIcon from '../icons/PlusIcon' +import TrashIcon from '../icons/TrashIcon' +import NoCeramicNodeModal from '../node/NoCeramicNodeModal' +import CreateCompositeModal from './CreateCompositeModal' +import CreateNewModel from './CreateNewModel' +import FavoriteModel from './FavoriteModal' +import MergeModal from './MergeModal' + +enum OPEN_MODAL { + NONE, + CREATE_NEW_MODEL, + ADD_FROM_ALL_MODELS, + ADD_FROM_FAVORITE_MODELS, + CREATE_NEW_COMPOSITE, + ADD_FROM_ALL_COMPOSITES, + ADD_FROM_FAVORITE_COMPOSITES +} + +export default function DappModelAndComposites ({ + editable, + selectComposite, + setSelectComposite, + selectModel, + setSelectModel +}: { + selectModel: ModelStream | undefined + setSelectModel: (m: ModelStream | undefined) => void + selectComposite: DappCompositeDto | undefined + setSelectComposite: (composite: DappCompositeDto | undefined) => void + + editable?: boolean +}) { + const session = useSession() + const { loadDapps, currDapp } = useAppCtx() + const { appId, selectedDapp } = useSelectedDapp() + const { currCeramicNode } = useCeramicNodeCtx() + const navigate = useNavigate() + const [loading, setLoading] = useState(false) + const [dappModels, setDappModels] = useState() + const [dappComposites, setDappComposites] = useState([]) + const location = useLocation() + + const dapp = useMemo(() => { + return selectedDapp || currDapp + }, [selectedDapp, currDapp]) + + const { isOwner } = useIsOwner() + + const loadModelsInfo = useCallback(async () => { + if (dapp?.models?.length === 0 || !dapp) { + setDappModels([]) + return + } + + try { + const resp = await getModelsInfoByIds({ + network: dapp.network as Network, + ids: dapp.models || [] + }) + + const list = resp.data.data + setDappModels(list) + if (list.length > 0) { + setSelectModel(list[0]) + } + } catch (error) { + console.error(error) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [dapp]) + + // const loadDappModels = useCallback(async () => { + // if (!dapp) return + // try { + // const resp = await getDappModels({ + // dapp + // }) + // if (resp.data.code !== 0) throw new Error(resp.data.msg) + // setDappModels(resp.data.data) + // } catch (error) { + // console.error(error) + // } + // }, [dapp]) + + const loadDappComposites = useCallback(async () => { + if (!dapp) return + try { + const resp = await getDappComposites({ + dapp + }) + if (resp.data.code !== 0) throw new Error(resp.data.msg) + setDappComposites(resp.data.data) + } catch (error) { + console.error(error) + } + }, [dapp]) + + const removeModelFromDapp = useCallback( + async (modelId: string) => { + if (!session) return + if (!selectedDapp) return + + try { + const newModels = + selectedDapp?.models?.filter(id => id !== modelId) || [] + + await updateDapp( + { ...selectedDapp, models: newModels }, + session.serialize() + ) + await loadDapps() + setSelectModel(undefined) + } catch (error) { + console.error(error) + } + }, + [loadDapps, selectedDapp, session, setSelectModel] + ) + + const delDappComposite = useCallback( + async (id: number) => { + if (!session) return + if (!selectedDapp) return + try { + await deleteDappComposites({ + compositeId: id, + did: session.serialize(), + dapp: selectedDapp + }) + await loadDappComposites() + setSelectComposite(undefined) + } catch (error) { + console.error(error) + } + }, + [session, selectedDapp, loadDappComposites, setSelectComposite] + ) + + const isFirstRenderRef = useRef(true) + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + }, []) + + useEffect(() => { + if (!mounted) return + if (isFirstRenderRef.current) { + isFirstRenderRef.current = false + setLoading(true) + } + + Promise.all([loadDappComposites(), loadModelsInfo()]).finally(() => + setLoading(false) + ) + }, [loadModelsInfo, loadDappComposites, mounted]) + + useEffect(() => { + setSelectModel(undefined) + setDappModels(undefined) + setSelectComposite(undefined) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [appId]) + + const isMetrics = location.pathname.endsWith('statistic') + const isSdk = location.pathname.endsWith('sdk') + + const [openModal, setOpenModal] = useState(OPEN_MODAL.NONE) + if (loading) { + return ( + +
+ +
+
+ ) + } + + return ( + +
+

Models

+ {editable && + isOwner && + (!currCeramicNode || + currCeramicNode.status !== CeramicStatus.RUNNING ? ( + + + + + + {({ close }) => } + + + + + ) : ( + + + + { + if (id === 'explore') { + navigate(`/dapp/${appId}/explore/model`) + return + } + if (id === 'favorite') { + setOpenModal(OPEN_MODAL.ADD_FROM_FAVORITE_MODELS) + return + } + if (id === 'create') { + setOpenModal(OPEN_MODAL.CREATE_NEW_MODEL) + return + } + }} + > + Explore Models + Add From Favorite + Create New Model + + + + ))} +
+ + { + setSelectModel(model) + }} + removeModelAction={async (id: string) => { + await removeModelFromDapp(id) + if (id === selectModel?.stream_id) { + setSelectModel(undefined) + setDappModels(undefined) + setSelectModel(undefined) + } + }} + /> + + {!(isMetrics || isSdk) && ( + <> +
+

Composites

+ {editable && + isOwner && + (!currCeramicNode || + currCeramicNode.status !== CeramicStatus.RUNNING ? ( + + + + + + {({ close }) => ( + + )} + + + + + ) : ( + + + + { + if (id === 'explore') { + navigate(`/dapp/${appId}/explore/composite`) + return + } + if (id === 'create') { + setOpenModal(OPEN_MODAL.CREATE_NEW_COMPOSITE) + return + } + }} + > + Explore Composites + Create New Composites + + + + ))} +
+ + + + )} + setOpenModal(OPEN_MODAL.NONE)} + > + {({ close }) => } + + setOpenModal(OPEN_MODAL.NONE)} + > + + {({ close }) => ( + + )} + + + setOpenModal(OPEN_MODAL.NONE)} + > + {({ close }) => } + + {editable && isOwner && ( + + + + + + + {({ close }) => ( + + )} + + + + + + )} +
+ ) +} + +function DappCompositeList ({ + composites, + removeAction, + editable, + selectComposite, + setSelectedComposite +}: { + composites: DappCompositeDto[] + selectComposite: DappCompositeDto | undefined + setSelectedComposite: (composite: DappCompositeDto) => void + removeAction: (id: number) => Promise + editable?: boolean +}) { + if (composites.length === 0) { + return ( + +

This Dapp has no composites available yet.

+
+ ) + } + return ( + + {composites?.map(item => { + const active = selectComposite?.id === item.id + return ( +
+
{ + setSelectedComposite(item) + }} + > +
{item.name}
+ {editable && ( + { + await removeAction(item.id) + }} + id={item.id + ''} + /> + )} +
+
+ ) + })} +
+ ) +} + +function DappModelList ({ + selected, + setSelected, + dappModels, + selectAction, + removeModelAction, + editable +}: { + selected?: ModelStream + setSelected: (ms: ModelStream) => void + dappModels: ModelStream[] + selectAction: (model: ModelStream) => void + removeModelAction: (modelId: string) => Promise + editable?: boolean +}) { + if (dappModels.length === 0) { + return ( + +

There is no model in this dapp.

+
+ ) + } + return ( + + {dappModels?.map(item => { + const active = selected?.stream_id === item.stream_id + return ( +
+
{ + selectAction(item) + setSelected(item) + }} + > +
{item.stream_content.name}
+ {editable && ( + + )} +
+ {active && ( + <> +
+
+

ID: {shortPubKey(selected.stream_id, { len: 7 })}

+
+ +
+
+

{selected.stream_content.description}

+

+ Streams: {selected.useCount} +

+ + )} +
+ ) + })} +
+ ) +} + +function RemoveButton ({ + id, + removeAction +}: { + id: string + removeAction: (id: string) => Promise +}) { + const [removing, setRemoving] = useState(false) + if (removing) { + return ( +
+ {' '} +
+ ) + } + return ( + + ) +} + +const Box = styled.div` + background: #1b1e23; + border: 1px solid #39424c; + border-radius: 20px; + padding: 20px; + display: flex; + flex-direction: column; + align-items: flex-start; + padding: 20px; + gap: 20px; + width: 261px; + min-width: 261px; + box-sizing: border-box; + height: fit-content; + > div { + width: 100%; + } + .title { + height: 42px; + display: flex; + align-items: center; + justify-content: space-between; + > h3 { + font-style: italic; + font-weight: 700; + font-size: 20px; + line-height: 24px; + margin: 0; + color: #ffffff; + } + } + .loading { + width: 100%; + text-align: center; + } +` + +const DappModelsListBox = styled.div` + display: flex; + flex-direction: column; + gap: 20px; + overflow: scroll; + > div { + padding: 10px 16px; + box-sizing: border-box; + border: 1px solid #39424c; + border-radius: 12px; + cursor: pointer; + } + + div.title { + > div { + cursor: pointer; + max-width: 80%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + } + + div.active { + background: rgba(113, 128, 150, 0.3); + border: 1px solid #718096; + border-radius: 12px; + + .id-copy { + display: flex; + align-items: center; + justify-content: space-between; + + > p { + margin: 0; + } + } + } + + hr { + border-color: rgba(255, 255, 255, 0.2); + margin-top: 10px; + } + + p { + color: #718096; + > span { + color: #ffffff; + font-size: 16px; + font-family: Rubik; + font-style: normal; + font-weight: 500; + line-height: normal; + } + } + + .removing { + > img { + width: 20px; + } + } +` + +const MergeBox = styled.div` + .merge-btn { + width: 100%; + background: #718096; + color: #ffffff; + padding: 12px 24px; + border-radius: 12px; + font-weight: 700; + font-size: 16px; + + display: flex; + align-items: center; + justify-content: center; + gap: 10px; + } +` From 85b3db7590b15ce0c6d53c75e95eb4bbd0c8f3da Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 18:41:52 +0800 Subject: [PATCH 3/8] extract explore model list component --- .../model/DappModelAndComposites.tsx | 2 +- .../src/components/model/ExploreModelList.tsx | 523 +++++++++++++++++ .../src/components/model/FavoriteModal.tsx | 260 +-------- .../dashboard/src/components/nav/Nav.tsx | 2 +- .../src/container/ExploreComposite.tsx | 2 +- .../dashboard/src/container/ExploreModel.tsx | 526 +----------------- 6 files changed, 537 insertions(+), 778 deletions(-) create mode 100644 packages/client/dashboard/src/components/model/ExploreModelList.tsx diff --git a/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx index b5d4b8e..208f115 100644 --- a/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx +++ b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx @@ -25,7 +25,7 @@ import { DappCompositeDto, ModelStream, Network -} from '../../types' +} from '../../types.d' import { getCompositeDefaultSchema } from '../../utils/composedb-types/schemas' import { shortPubKey } from '../../utils/shortPubKey' import CopyTint from '../common/CopyTint' diff --git a/packages/client/dashboard/src/components/model/ExploreModelList.tsx b/packages/client/dashboard/src/components/model/ExploreModelList.tsx new file mode 100644 index 0000000..a5ad9fe --- /dev/null +++ b/packages/client/dashboard/src/components/model/ExploreModelList.tsx @@ -0,0 +1,523 @@ +import { useSession } from '@us3r-network/auth-with-rainbowkit' +import dayjs from 'dayjs' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' +import { + Button, + Dialog, + DialogTrigger, + Modal, + ModalOverlay +} from 'react-aria-components' +import InfiniteScroll from 'react-infinite-scroll-component' +import styled from 'styled-components' +import { updateDapp } from '../../api/dapp' +import { PAGE_SIZE } from '../../constants' +import { + getModelStreamList, + getModelsInfoByIds, + startIndexModel +} from '../../api/model' +import { ImgOrName } from '../../components/common/ImgOrName' +import { TableBox, TableContainer } from '../../components/common/TableBox' +import CheckCircleIcon from '../../components/icons/CheckCircleIcon' +import PlusCircleIcon from '../../components/icons/PlusCircleIcon' +import StarGoldIcon from '../../components/icons/StarGoldIcon' +import StarIcon from '../../components/icons/StarIcon' +import NoCeramicNodeModal from '../../components/node/NoCeramicNodeModal' +import { S3_SCAN_URL } from '../../constants' +import { PersonalCollection, useAppCtx } from '../../context/AppCtx' +import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' +import useSelectedDapp from '../../hooks/useSelectedDapp' +import { CeramicStatus, ClientDApp, ModelStream, Network } from '../../types.d' +import { shortPubKey } from '../../utils/shortPubKey' + +export default function ModelList ({ + searchText, + filterStar +}: { + searchText?: string + filterStar?: boolean +}) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { s3ModelCollection, selectedDapp } = useSelectedDapp() + const { currCeramicNode } = useCeramicNodeCtx() + const session = useSession() + const [models, setModels] = useState>([]) + const [starModels, setStarModels] = useState>([]) + const [hasMore, setHasMore] = useState(true) + const pageNum = useRef(1) + const [personalCollections, setPersonalCollections] = useState< + PersonalCollection[] + >([]) + const fetchPersonalCollections = useCallback(async () => { + if (!session) return + s3ModelCollection.authComposeClient(session) + try { + const personal = await s3ModelCollection.queryPersonalCollections({ + first: 500 + }) + if (personal.errors) throw new Error(personal.errors[0].message) + const collected = personal.data?.viewer.modelCollectionList + + if (collected) { + setPersonalCollections( + collected?.edges + .filter(item => item.node && item.node.revoke === false) + .map(item => { + return { + modelId: item.node.modelID, + id: item.node.id!, + revoke: !!item.node.revoke + } + }) + ) + } + } catch (error) { + console.error('error -----', error) + } + }, [s3ModelCollection, session]) + + const fetchStarModels = useCallback(async () => { + const ids = personalCollections + .filter(item => item.revoke === false) + .map(item => { + return item.modelId + }) + if (ids.length === 0) { + setStarModels([]) + return + } + + try { + const resp = await getModelsInfoByIds({ + network: (selectedDapp?.network as Network) || Network.TESTNET, + ids + }) + if (resp.data.code !== 0) { + throw new Error(resp.data.msg) + } + + const list = resp.data.data + setStarModels([...list]) + } catch (error) { + console.error(error) + } + }, [personalCollections, selectedDapp?.network]) + + const fetchModel = useCallback(async () => { + setModels([]) + setHasMore(true) + const resp = await getModelStreamList({ + name: searchText, + network: (selectedDapp?.network as Network) || Network.TESTNET + }) + const list = resp.data.data + setModels(list) + setHasMore(list.length >= PAGE_SIZE) + pageNum.current = 1 + }, [selectedDapp?.network]) + + const fetchMoreModel = useCallback( + async (pageNumber: number) => { + const resp = await getModelStreamList({ + pageNumber + }) + const list = resp.data.data + setHasMore(list.length >= PAGE_SIZE) + setModels([...models, ...list]) + }, + [models] + ) + + useEffect(() => { + fetchModel() + fetchPersonalCollections() + }, [fetchModel, fetchPersonalCollections]) + + useEffect(() => { + fetchStarModels().catch(err => { + setStarModels([]) + console.error(err) + }) + }, [fetchStarModels]) + + const lists = useMemo(() => { + if (!filterStar) return models + return starModels + }, [filterStar, models, starModels]) + + return ( + <> + { + pageNum.current += 1 + fetchMoreModel(pageNum.current) + console.log('fetch more') + }} + hasMore={filterStar ? false : hasMore} + loader={Loading...} + > + + + + + Model Name + Description + ID + Usage Count + 7 Days Usage + Release Date + Dapps + + + + + + {lists.map((item, idx) => { + const hasStarItem = personalCollections.find( + starItem => starItem.modelId === item.stream_id + ) + return ( + + + + + +
{item.stream_content.description}
+ + + + + + + + {item.recentlyUseCount || '-'} + +
+ {(item.last_anchored_at && + dayjs(item.created_at).format( + 'YYYY-MM-DD HH:mm:ss' + )) || + '-'} +
+ + + + + + {/* */} + + + + ) + })} + +
+
+
+ {!filterStar && !hasMore && no more data} + + ) +} + +export function Dapps ({ dapps }: { dapps: ClientDApp[] }) { + const apps = useMemo(() => { + const data = [...dapps] + if (data.length > 3) + return { data: data.slice(0, 3), left: data.length - 3 } + return { data, left: 0 } + }, [dapps]) + + return ( + + {apps.data.length > 0 + ? apps.data.map((item, idx) => { + return ( + + + + ) + }) + : 'None'} + {apps.left > 0 && {apps.left}+} + + ) +} + +const DappBox = styled.div` + display: flex; + gap: 5px; + overflow: hidden; + color: #fff; + font-family: Rubik; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; + a { + > span { + color: #fff; + width: 36px; + height: 36px; + border-radius: 10px; + border: 1px solid #718096; + display: inline-flex; + align-items: center; + justify-content: center; + overflow: hidden; + &.name { + font-size: 20px; + font-weight: 500; + } + &.left { + border: none; + color: #fff; + justify-content: start; + font-family: Rubik; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; + } + > img { + width: 100%; + height: 100%; + object-fit: cover; + flex-shrink: 0; + } + } + } +` + +function Actions ({ + hasStarItem, + fetchPersonal, + stream_id, + hasIndexed, + ceramicNodeId +}: { + hasIndexed: boolean + stream_id: string + hasStarItem: + | { + modelId: string + id: string + revoke: boolean + } + | undefined + fetchPersonal: () => void + ceramicNodeId?: number +}) { + const session = useSession() + const { s3ModelCollection } = useSelectedDapp() + const [staring, setStaring] = useState(false) + + const { loadDapps } = useAppCtx() + const { selectedDapp } = useSelectedDapp() + const [adding, setAdding] = useState(false) + const addModelToDapp = useCallback( + async (modelId: string) => { + if (!session || !selectedDapp) return + if (!ceramicNodeId) return + if (!hasIndexed) { + startIndexModel({ + modelId, + network: selectedDapp.network as Network, + didSession: session.serialize() + }).catch(console.error) + } + try { + setAdding(true) + const models = selectedDapp.models || [] + models.push(modelId) + await updateDapp( + { ...selectedDapp, models }, + session.serialize(), + ceramicNodeId + ) + await loadDapps() + } catch (err) { + console.error(err) + } finally { + setAdding(false) + } + }, + [loadDapps, selectedDapp, session, setAdding, hasIndexed, ceramicNodeId] + ) + + const collectModel = useCallback( + async (modelId: string, id?: string, revoke?: boolean) => { + if (staring) return + try { + if (!session) return + s3ModelCollection.authComposeClient(session) + setStaring(true) + if (id) { + const resp = await s3ModelCollection.updateCollection(id, { + revoke: !revoke + }) + if (resp.errors) { + throw new Error(resp.errors[0].message) + } + } else { + const resp = await s3ModelCollection.createCollection({ + modelID: modelId, + revoke: false + }) + if (resp.errors) { + throw new Error(resp.errors[0].message) + } + } + await fetchPersonal() + } catch (error) { + console.error(error) + } finally { + setStaring(false) + } + }, + [session, s3ModelCollection, fetchPersonal, staring] + ) + + const modelId = stream_id + + return ( + + {(staring && ( + + )) || ( + + )} + + {adding ? ( + + ) : ( + <> + {selectedDapp?.models?.includes(modelId) ? ( + + ) : ceramicNodeId ? ( + + ) : ( + + + + + + {({ close }) => } + + + + + )} + + )} + + ) +} + +const OpsBox = styled.div` + display: flex; + align-items: center; + gap: 5px; + + img { + width: 17px; + } +` +const Loading = styled.div` + padding: 20px; + text-align: center; + color: gray; +` diff --git a/packages/client/dashboard/src/components/model/FavoriteModal.tsx b/packages/client/dashboard/src/components/model/FavoriteModal.tsx index 90d92ff..c5cb9b7 100644 --- a/packages/client/dashboard/src/components/model/FavoriteModal.tsx +++ b/packages/client/dashboard/src/components/model/FavoriteModal.tsx @@ -1,20 +1,6 @@ -import { useSession } from '@us3r-network/auth-with-rainbowkit' -import dayjs from 'dayjs' -import { useCallback, useEffect, useState } from 'react' import styled from 'styled-components' -import { updateDapp } from '../../api/dapp' -import { getModelsInfoByIds, startIndexModel } from '../../api/model' -import { S3_SCAN_URL } from '../../constants' -import { PersonalCollection, useAppCtx } from '../../context/AppCtx' -import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' -import useSelectedDapp from '../../hooks/useSelectedDapp' -import { CeramicStatus, ModelStream, Network } from '../../types.d' -import { shortPubKey } from '../../utils/shortPubKey' -import { TableBox, TableContainer } from '../common/TableBox' -import CheckCircleIcon from '../icons/CheckCircleIcon' import CloseIcon from '../icons/CloseIcon' -import PlusCircleIcon from '../icons/PlusCircleIcon' -import StarGoldIcon from '../icons/StarGoldIcon' +import ModelList from './ExploreModelList' export default function FavoriteModal({ closeModal, @@ -30,243 +16,12 @@ export default function FavoriteModal({
- +
) } -function ModelList() { - const { s3ModelCollection, selectedDapp } = useSelectedDapp() - const session = useSession() - const { currCeramicNode } = useCeramicNodeCtx() - const [starModels, setStarModels] = useState>([]) - const [personalCollections, setPersonalCollections] = useState< - PersonalCollection[] - >([]) - const fetchPersonalCollections = useCallback(async () => { - if (!session) return - s3ModelCollection.authComposeClient(session) - try { - const personal = await s3ModelCollection.queryPersonalCollections({ - first: 500, - }) - if (personal.errors) throw new Error(personal.errors[0].message) - const collected = personal.data?.viewer.modelCollectionList - - if (collected) { - setPersonalCollections( - collected?.edges - .filter((item) => item.node && item.node.revoke === false) - .map((item) => { - return { - modelId: item.node.modelID, - id: item.node.id!, - revoke: !!item.node.revoke, - } - }) - ) - } - } catch (error) { - console.error(error) - } - }, [s3ModelCollection, session]) - - const fetchStarModels = useCallback(async () => { - const ids = personalCollections - .filter((item) => item.revoke === false) - .map((item) => { - return item.modelId - }) - if (ids.length === 0) { - setStarModels([]) - return - } - - try { - const resp = await getModelsInfoByIds({ - network: (selectedDapp?.network as Network) || Network.TESTNET, - ids, - }) - if (resp.data.code !== 0) { - throw new Error(resp.data.msg) - } - - const list = resp.data.data - setStarModels([...list]) - } catch (error) { - console.error(error) - } - }, [personalCollections, selectedDapp?.network]) - - useEffect(() => { - fetchPersonalCollections() - }, [fetchPersonalCollections]) - - useEffect(() => { - fetchStarModels().catch(console.error) - }, [fetchStarModels]) - - return ( - - - - - - Model Name - Description - ID - Usage Count - Release Date - - - - - {starModels.map((item, idx) => { - return ( - - - - - -
- {item.stream_content.description} -
- - - - - - - - -
- {(item.last_anchored_at && - dayjs(item.created_at).format('YYYY-MM-DD HH:mm:ss')) || - '-'} -
- - - - - - - ) - })} - -
-
-
- ) -} - -export function OpsBtns({ - modelId, - hasIndexed, - ceramicNodeId, -}: { - modelId: string - hasIndexed: boolean - ceramicNodeId?: number -}) { - const { loadDapps } = useAppCtx() - const session = useSession() - const { selectedDapp } = useSelectedDapp() - const [adding, setAdding] = useState(false) - const addToModelList = useCallback( - async (modelId: string) => { - if (!session || !selectedDapp) return - if (!hasIndexed) { - startIndexModel({ - modelId, - network: selectedDapp.network as Network, - didSession: session.serialize(), - }).catch(console.error) - } - if (!ceramicNodeId) return - try { - setAdding(true) - const models = selectedDapp.models || [] - models.push(modelId) - await updateDapp({ ...selectedDapp, models }, session.serialize(),ceramicNodeId) - await loadDapps() - } catch (err) { - console.error(err) - } finally { - setAdding(false) - } - }, - [ceramicNodeId, hasIndexed, loadDapps, selectedDapp, session] - ) - return ( -
- - {adding ? ( - - ) : ( - <> - {selectedDapp?.models?.includes(modelId) ? ( - - ) : ( - - )} - - )} -
- ) -} - const FavoriteBox = styled.div` display: flex; flex-direction: column; @@ -295,14 +50,3 @@ const FavoriteBox = styled.div` } } ` - -const ListBox = styled.div` - .btns { - display: flex; - align-items: center; - - .loading { - width: 20px; - } - } -` diff --git a/packages/client/dashboard/src/components/nav/Nav.tsx b/packages/client/dashboard/src/components/nav/Nav.tsx index 1b2e2bf..33a8f7c 100644 --- a/packages/client/dashboard/src/components/nav/Nav.tsx +++ b/packages/client/dashboard/src/components/nav/Nav.tsx @@ -93,7 +93,7 @@ export default function Nav({ appId }: { appId: string }) { )} - +
{(filterStar && ) || } Favorite diff --git a/packages/client/dashboard/src/container/ExploreComposite.tsx b/packages/client/dashboard/src/container/ExploreComposite.tsx index 768100b..c5968f9 100644 --- a/packages/client/dashboard/src/container/ExploreComposite.tsx +++ b/packages/client/dashboard/src/container/ExploreComposite.tsx @@ -26,7 +26,7 @@ import useSelectedDapp from '../hooks/useSelectedDapp' import { CeramicStatus, DappCompositeDto, Network } from '../types.d' import { shortPubKey } from '../utils/shortPubKey' import { bindingDappComposites, getComposites } from '../api/composite' -import { Dapps } from './ExploreModel' +import { Dapps } from '../components/model/ExploreModelList' import CreateCompositeModal from '../components/model/CreateCompositeModal' import LayoutIcon from '../components/icons/LayoutIcon' import { startIndexModels } from '../api/model' diff --git a/packages/client/dashboard/src/container/ExploreModel.tsx b/packages/client/dashboard/src/container/ExploreModel.tsx index 9f9fd10..0179e6a 100644 --- a/packages/client/dashboard/src/container/ExploreModel.tsx +++ b/packages/client/dashboard/src/container/ExploreModel.tsx @@ -1,153 +1,17 @@ -import { useSession } from '@us3r-network/auth-with-rainbowkit' -import dayjs from 'dayjs' -import { useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { - Button, - Dialog, - DialogTrigger, - Modal, - ModalOverlay -} from 'react-aria-components' -import InfiniteScroll from 'react-infinite-scroll-component' +import { useMemo, useState } from 'react' import { useSearchParams } from 'react-router-dom' import styled from 'styled-components' -import { updateDapp } from '../api/dapp' -import { PAGE_SIZE } from '../constants' -import { - getModelStreamList, - getModelsInfoByIds, - startIndexModel -} from '../api/model' -import { ImgOrName } from '../components/common/ImgOrName' import Search from '../components/common/Search' -import { TableBox, TableContainer } from '../components/common/TableBox' -import CheckCircleIcon from '../components/icons/CheckCircleIcon' -import PlusCircleIcon from '../components/icons/PlusCircleIcon' -import StarGoldIcon from '../components/icons/StarGoldIcon' -import StarIcon from '../components/icons/StarIcon' -import NoCeramicNodeModal from '../components/node/NoCeramicNodeModal' -import { S3_SCAN_URL } from '../constants' -import { PersonalCollection, useAppCtx } from '../context/AppCtx' -import { useCeramicNodeCtx } from '../context/CeramicNodeCtx' -import useSelectedDapp from '../hooks/useSelectedDapp' -import { CeramicStatus, ClientDApp, ModelStream, Network } from '../types.d' -import { shortPubKey } from '../utils/shortPubKey' +import ModelList from '../components/model/ExploreModelList' export default function ExploreModel () { - // eslint-disable-next-line @typescript-eslint/no-unused-vars const [searchParams, setSearchParams] = useSearchParams() - const { s3ModelCollection, selectedDapp } = useSelectedDapp() - const { currCeramicNode } = useCeramicNodeCtx() - const session = useSession() - const [models, setModels] = useState>([]) - const [starModels, setStarModels] = useState>([]) - const [hasMore, setHasMore] = useState(true) - const searchText = useRef('') - const pageNum = useRef(1) - const [personalCollections, setPersonalCollections] = useState< - PersonalCollection[] - >([]) - const fetchPersonalCollections = useCallback(async () => { - if (!session) return - s3ModelCollection.authComposeClient(session) - try { - const personal = await s3ModelCollection.queryPersonalCollections({ - first: 500 - }) - if (personal.errors) throw new Error(personal.errors[0].message) - const collected = personal.data?.viewer.modelCollectionList - - if (collected) { - setPersonalCollections( - collected?.edges - .filter(item => item.node && item.node.revoke === false) - .map(item => { - return { - modelId: item.node.modelID, - id: item.node.id!, - revoke: !!item.node.revoke - } - }) - ) - } - } catch (error) { - console.error('error -----', error) - } - }, [s3ModelCollection, session]) - - const fetchStarModels = useCallback(async () => { - const ids = personalCollections - .filter(item => item.revoke === false) - .map(item => { - return item.modelId - }) - if (ids.length === 0) { - setStarModels([]) - return - } - - try { - const resp = await getModelsInfoByIds({ - network: (selectedDapp?.network as Network) || Network.TESTNET, - ids - }) - if (resp.data.code !== 0) { - throw new Error(resp.data.msg) - } - - const list = resp.data.data - setStarModels([...list]) - } catch (error) { - console.error(error) - } - }, [personalCollections, selectedDapp?.network]) - - const fetchModel = useCallback(async () => { - setModels([]) - setHasMore(true) - const resp = await getModelStreamList({ - name: searchText.current, - network: (selectedDapp?.network as Network) || Network.TESTNET - }) - const list = resp.data.data - setModels(list) - setHasMore(list.length >= PAGE_SIZE) - pageNum.current = 1 - }, [selectedDapp?.network]) - - const fetchMoreModel = useCallback( - async (pageNumber: number) => { - const resp = await getModelStreamList({ - pageNumber - }) - const list = resp.data.data - setHasMore(list.length >= PAGE_SIZE) - setModels([...models, ...list]) - }, - [models] - ) - - useEffect(() => { - fetchModel() - fetchPersonalCollections() - }, [fetchModel, fetchPersonalCollections]) - - useEffect(() => { - fetchStarModels().catch(err => { - setStarModels([]) - console.error(err) - }) - }, [fetchStarModels]) - const filterStar = useMemo(() => { - return searchParams.get('filterStar') || '' + return searchParams.get('filterStar') === 'true' }, [searchParams]) - - const lists = useMemo(() => { - if (!filterStar) return models - return starModels - }, [filterStar, models, starModels]) - + const [searchText, setSearchText] = useState( + searchParams.get('searchText') || '' + ) return (
@@ -155,385 +19,19 @@ export default function ExploreModel () {
{ - searchText.current = text - setModels([]) - fetchModel() + setSearchText(text) }} placeholder={'Search by model name'} />
- { - pageNum.current += 1 - fetchMoreModel(pageNum.current) - console.log('fetch more') - }} - hasMore={filterStar ? false : hasMore} - loader={Loading...} - > - - - - - Model Name - Description - ID - Usage Count - 7 Days Usage - Release Date - Dapps - - - - - - {lists.map((item, idx) => { - const hasStarItem = personalCollections.find( - starItem => starItem.modelId === item.stream_id - ) - return ( - - - - - -
{item.stream_content.description}
- - - - - - - - {item.recentlyUseCount || '-'} - -
- {(item.last_anchored_at && - dayjs(item.created_at).format( - 'YYYY-MM-DD HH:mm:ss' - )) || - '-'} -
- - - - - - {/* */} - - - - ) - })} - -
-
-
- {!filterStar && !hasMore && no more data} +
) } -export function Dapps ({ dapps }: { dapps: ClientDApp[] }) { - const apps = useMemo(() => { - const data = [...dapps] - if (data.length > 3) - return { data: data.slice(0, 3), left: data.length - 3 } - return { data, left: 0 } - }, [dapps]) - - return ( - - {apps.data.length > 0 - ? apps.data.map((item, idx) => { - return ( - - - - ) - }) - : 'None'} - {apps.left > 0 && {apps.left}+} - - ) -} - -const DappBox = styled.div` - display: flex; - gap: 5px; - overflow: hidden; - color: #fff; - font-family: Rubik; - font-size: 12px; - font-style: normal; - font-weight: 400; - line-height: normal; - a { - > span { - color: #fff; - width: 36px; - height: 36px; - border-radius: 10px; - border: 1px solid #718096; - display: inline-flex; - align-items: center; - justify-content: center; - overflow: hidden; - &.name { - font-size: 20px; - font-weight: 500; - } - &.left { - border: none; - color: #fff; - justify-content: start; - font-family: Rubik; - font-size: 12px; - font-style: normal; - font-weight: 400; - line-height: normal; - } - > img { - width: 100%; - height: 100%; - object-fit: cover; - flex-shrink: 0; - } - } - } -` - -function ModelStarItem ({ - hasStarItem, - fetchPersonal, - stream_id, - hasIndexed, - ceramicNodeId -}: { - hasIndexed: boolean - stream_id: string - hasStarItem: - | { - modelId: string - id: string - revoke: boolean - } - | undefined - fetchPersonal: () => void - ceramicNodeId?: number -}) { - const session = useSession() - const { s3ModelCollection } = useSelectedDapp() - const [staring, setStaring] = useState(false) - - const { loadDapps } = useAppCtx() - const { selectedDapp } = useSelectedDapp() - const [adding, setAdding] = useState(false) - const addToModelList = useCallback( - async (modelId: string) => { - if (!session || !selectedDapp) return - if (!ceramicNodeId) return - if (!hasIndexed) { - startIndexModel({ - modelId, - network: selectedDapp.network as Network, - didSession: session.serialize() - }).catch(console.error) - } - try { - setAdding(true) - const models = selectedDapp.models || [] - models.push(modelId) - await updateDapp( - { ...selectedDapp, models }, - session.serialize(), - ceramicNodeId - ) - await loadDapps() - } catch (err) { - console.error(err) - } finally { - setAdding(false) - } - }, - [loadDapps, selectedDapp, session, setAdding, hasIndexed, ceramicNodeId] - ) - - const starModelAction = useCallback( - async (modelId: string, id?: string, revoke?: boolean) => { - if (staring) return - try { - if (!session) return - s3ModelCollection.authComposeClient(session) - setStaring(true) - if (id) { - const resp = await s3ModelCollection.updateCollection(id, { - revoke: !revoke - }) - if (resp.errors) { - throw new Error(resp.errors[0].message) - } - } else { - const resp = await s3ModelCollection.createCollection({ - modelID: modelId, - revoke: false - }) - if (resp.errors) { - throw new Error(resp.errors[0].message) - } - } - await fetchPersonal() - } catch (error) { - console.error(error) - } finally { - setStaring(false) - } - }, - [session, s3ModelCollection, fetchPersonal, staring] - ) - - const modelId = stream_id - - return ( - - {(staring && ( - - )) || ( - - )} - - {adding ? ( - - ) : ( - <> - {selectedDapp?.models?.includes(modelId) ? ( - - ) : ceramicNodeId ? ( - - ) : ( - - - - - - {({ close }) => } - - - - - )} - - )} - - ) -} - -const OpsBox = styled.div` - display: flex; - align-items: center; - gap: 5px; - - img { - width: 17px; - } -` - const ExploreModelContainer = styled.div` margin-top: 25px; margin-bottom: 25px; @@ -619,9 +117,3 @@ const ExploreModelContainer = styled.div` font-size: 18px; } ` - -const Loading = styled.div` - padding: 20px; - text-align: center; - color: gray; -` From 8f52468c88d805fc851ab6e35613162d3e6bdca7 Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 18:46:29 +0800 Subject: [PATCH 4/8] extract explore model list component --- .../dashboard/src/components/model/ExploreModelList.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/client/dashboard/src/components/model/ExploreModelList.tsx b/packages/client/dashboard/src/components/model/ExploreModelList.tsx index a5ad9fe..98ca3ec 100644 --- a/packages/client/dashboard/src/components/model/ExploreModelList.tsx +++ b/packages/client/dashboard/src/components/model/ExploreModelList.tsx @@ -108,25 +108,27 @@ export default function ModelList ({ setModels([]) setHasMore(true) const resp = await getModelStreamList({ - name: searchText, + name: searchText || '', network: (selectedDapp?.network as Network) || Network.TESTNET }) const list = resp.data.data setModels(list) setHasMore(list.length >= PAGE_SIZE) pageNum.current = 1 - }, [selectedDapp?.network]) + }, [searchText, selectedDapp?.network]) const fetchMoreModel = useCallback( async (pageNumber: number) => { const resp = await getModelStreamList({ + name: searchText || '', + network: (selectedDapp?.network as Network) || Network.TESTNET, pageNumber }) const list = resp.data.data setHasMore(list.length >= PAGE_SIZE) setModels([...models, ...list]) }, - [models] + [models, searchText, selectedDapp?.network] ) useEffect(() => { From 67fe66edd760ec941ff0f9cf0769b4d4b6891a47 Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 19:00:09 +0800 Subject: [PATCH 5/8] extract explore composite list component --- .../src/components/model/ExploreModelList.tsx | 14 +- .../src/container/ExploreComposite.tsx | 379 +----------------- .../dashboard/src/container/ExploreModel.tsx | 2 +- 3 files changed, 17 insertions(+), 378 deletions(-) diff --git a/packages/client/dashboard/src/components/model/ExploreModelList.tsx b/packages/client/dashboard/src/components/model/ExploreModelList.tsx index 98ca3ec..0d3ece9 100644 --- a/packages/client/dashboard/src/components/model/ExploreModelList.tsx +++ b/packages/client/dashboard/src/components/model/ExploreModelList.tsx @@ -17,13 +17,13 @@ import { getModelsInfoByIds, startIndexModel } from '../../api/model' -import { ImgOrName } from '../../components/common/ImgOrName' -import { TableBox, TableContainer } from '../../components/common/TableBox' -import CheckCircleIcon from '../../components/icons/CheckCircleIcon' -import PlusCircleIcon from '../../components/icons/PlusCircleIcon' -import StarGoldIcon from '../../components/icons/StarGoldIcon' -import StarIcon from '../../components/icons/StarIcon' -import NoCeramicNodeModal from '../../components/node/NoCeramicNodeModal' +import { ImgOrName } from '../common/ImgOrName' +import { TableBox, TableContainer } from '../common/TableBox' +import CheckCircleIcon from '../icons/CheckCircleIcon' +import PlusCircleIcon from '../icons/PlusCircleIcon' +import StarGoldIcon from '../icons/StarGoldIcon' +import StarIcon from '../icons/StarIcon' +import NoCeramicNodeModal from '../node/NoCeramicNodeModal' import { S3_SCAN_URL } from '../../constants' import { PersonalCollection, useAppCtx } from '../../context/AppCtx' import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' diff --git a/packages/client/dashboard/src/container/ExploreComposite.tsx b/packages/client/dashboard/src/container/ExploreComposite.tsx index c5968f9..19632cb 100644 --- a/packages/client/dashboard/src/container/ExploreComposite.tsx +++ b/packages/client/dashboard/src/container/ExploreComposite.tsx @@ -1,153 +1,14 @@ -import { useSession } from '@us3r-network/auth-with-rainbowkit' -import dayjs from 'dayjs' -import { useCallback, useEffect, useRef, useState } from 'react' -import { - Button, - Dialog, - DialogTrigger, - Modal, - ModalOverlay -} from 'react-aria-components' -import InfiniteScroll from 'react-infinite-scroll-component' +import { useState } from 'react' import { useSearchParams } from 'react-router-dom' import styled from 'styled-components' -import { updateDapp } from '../api/dapp' -import { PAGE_SIZE } from '../constants' -import { ImgOrName } from '../components/common/ImgOrName' import Search from '../components/common/Search' -import { TableBox, TableContainer } from '../components/common/TableBox' -import CheckCircleIcon from '../components/icons/CheckCircleIcon' -import PlusCircleIcon from '../components/icons/PlusCircleIcon' -import NoCeramicNodeModal from '../components/node/NoCeramicNodeModal' -import { S3_SCAN_URL } from '../constants' -import { useAppCtx } from '../context/AppCtx' -import { useCeramicNodeCtx } from '../context/CeramicNodeCtx' -import useSelectedDapp from '../hooks/useSelectedDapp' -import { CeramicStatus, DappCompositeDto, Network } from '../types.d' -import { shortPubKey } from '../utils/shortPubKey' -import { bindingDappComposites, getComposites } from '../api/composite' -import { Dapps } from '../components/model/ExploreModelList' -import CreateCompositeModal from '../components/model/CreateCompositeModal' -import LayoutIcon from '../components/icons/LayoutIcon' -import { startIndexModels } from '../api/model' +import { CompositeList } from '../components/model/ExploreCompositeList' export default function ExploreComposite () { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [searchParams, setSearchParams] = useSearchParams() - const { s3ModelCollection, selectedDapp } = useSelectedDapp() - const { currCeramicNode } = useCeramicNodeCtx() - const session = useSession() - const [composites, setComposites] = useState>([]) - // const [starModels, setStarModels] = useState>([]) - const [hasMore, setHasMore] = useState(true) - const searchText = useRef('') - const pageNum = useRef(1) - // const [personalCollections, setPersonalCollections] = useState< - // PersonalCollection[] - // >([]) - // const fetchPersonalCollections = useCallback(async () => { - // if (!session) return - // s3ModelCollection.authComposeClient(session) - // try { - // const personal = await s3ModelCollection.queryPersonalCollections({ - // first: 500 - // }) - // if (personal.errors) throw new Error(personal.errors[0].message) - // const collected = personal.data?.viewer.modelCollectionList - - // if (collected) { - // setPersonalCollections( - // collected?.edges - // .filter(item => item.node && item.node.revoke === false) - // .map(item => { - // return { - // modelId: item.node.modelID, - // id: item.node.id!, - // revoke: !!item.node.revoke - // } - // }) - // ) - // } - // } catch (error) { - // console.error('error -----', error) - // } - // }, [s3ModelCollection, session]) - - // const fetchStarModels = useCallback(async () => { - // const ids = personalCollections - // .filter(item => item.revoke === false) - // .map(item => { - // return item.modelId - // }) - // if (ids.length === 0) { - // setStarModels([]) - // return - // } - - // try { - // const resp = await getModelsInfoByIds({ - // network: (selectedDapp?.network as Network) || Network.TESTNET, - // ids - // }) - // if (resp.data.code !== 0) { - // throw new Error(resp.data.msg) - // } - - // const list = resp.data.data - // setStarModels([...list]) - // } catch (error) { - // console.error(error) - // } - // }, [personalCollections, selectedDapp?.network]) - - const fetchComposites = useCallback(async () => { - setComposites([]) - setHasMore(true) - const resp = await getComposites({ - name: searchText.current, - network: (selectedDapp?.network as Network) || Network.TESTNET - }) - const list = resp.data.data - setComposites(list) - setHasMore(list.length >= PAGE_SIZE) - pageNum.current = 1 - }, [selectedDapp?.network]) - - const fetchMoreComposites = useCallback( - async (pageNumber: number) => { - const resp = await getComposites({ - name: searchText.current, - pageNumber, - network: (selectedDapp?.network as Network) || Network.TESTNET - }) - const list = resp.data.data - setHasMore(list.length >= PAGE_SIZE) - setComposites([...composites, ...list]) - }, - [composites, selectedDapp?.network] + const [searchParams] = useSearchParams() + const [searchText, setSearchText] = useState( + searchParams.get('searchText') || '' ) - - useEffect(() => { - fetchComposites() - // fetchPersonalCollections() - }, [fetchComposites]) - - // useEffect(() => { - // fetchStarModels().catch(err => { - // setStarModels([]) - // console.error(err) - // }) - // }, [fetchStarModels]) - - // const filterStar = useMemo(() => { - // return searchParams.get('filterStar') || '' - // }, [searchParams]) - - // const lists = useMemo(() => { - // if (!filterStar) return models - // return starModels - // }, [filterStar, models, starModels]) - const lists = composites return (
@@ -155,235 +16,19 @@ export default function ExploreComposite () {
{ - searchText.current = text - setComposites([]) - fetchComposites() + setSearchText(text) }} - placeholder={'Search by model name'} + placeholder={'Search by name'} />
- { - pageNum.current += 1 - fetchMoreComposites(pageNum.current) - console.log('fetch more') - }} - hasMore={hasMore} - loader={Loading...} - > - - - - - Composite Name - Stream ID - Release Date - Dapps - - - - - - {lists.map((item, idx) => { - return ( - - -
{item.name}
- - -
- {item.streamId ? ( - - {shortPubKey(item.streamId, { - len: 8, - split: '-' - })} - - ) : ( - '-' - )} -
- - -
- {dayjs(item.createdAt).format('YYYY-MM-DD HH:mm:ss') || - '-'} -
- - - - - - {/* */} - dapp.id === selectedDapp?.id - ) !== -1 - } - ceramicNodeId={ - currCeramicNode && - currCeramicNode.status === CeramicStatus.RUNNING - ? currCeramicNode?.id - : undefined - } - /> - - - ) - })} - -
-
-
- {!hasMore && no more data} +
) } -function Actions ({ - composite, - hasIndexed, - ceramicNodeId -}: { - composite: DappCompositeDto - hasIndexed: boolean - ceramicNodeId?: number -}) { - const session = useSession() - - const { loadDapps } = useAppCtx() - const { selectedDapp } = useSelectedDapp() - const [adding, setAdding] = useState(false) - - const bindComposite = useCallback(async () => { - if (!session || !selectedDapp) return - if (!ceramicNodeId) return - if (!hasIndexed) { - bindingDappComposites({ - compositeId: composite.id, - dapp: selectedDapp, - did: session.serialize() - }) - .then( - () => { - const models = JSON.parse(composite.composite).models - console.log(Object.keys(models)) - const modelIds = Object.keys(models) - startIndexModels({ - modelIds, - network: selectedDapp.network, - didSession: session.serialize() - }).catch(console.error) - }, - err => { - console.error(err) - } - ) - .catch(console.error) - } - try { - setAdding(true) - const composites = selectedDapp.composites || [] - composites.push(composite) - await updateDapp( - { ...selectedDapp, composites }, - session.serialize(), - ceramicNodeId - ) - await loadDapps() - } catch (err) { - console.error(err) - } finally { - setAdding(false) - } - }, [session, selectedDapp, ceramicNodeId, hasIndexed, composite, loadDapps]) - return ( - - - - - - - {({ close }) => ( - - )} - - - - - {adding ? ( - - ) : ( - <> - {hasIndexed ? ( - - ) : ceramicNodeId ? ( - - ) : ( - - - - - - {({ close }) => } - - - - - )} - - )} - - ) -} - -const OpsBox = styled.div` - display: flex; - align-items: center; - gap: -5px; - img { - width: 17px; - } -` - const ExploreModelContainer = styled.div` margin-top: 25px; margin-bottom: 25px; @@ -469,9 +114,3 @@ const ExploreModelContainer = styled.div` font-size: 18px; } ` - -const Loading = styled.div` - padding: 20px; - text-align: center; - color: gray; -` diff --git a/packages/client/dashboard/src/container/ExploreModel.tsx b/packages/client/dashboard/src/container/ExploreModel.tsx index 0179e6a..4738932 100644 --- a/packages/client/dashboard/src/container/ExploreModel.tsx +++ b/packages/client/dashboard/src/container/ExploreModel.tsx @@ -5,7 +5,7 @@ import Search from '../components/common/Search' import ModelList from '../components/model/ExploreModelList' export default function ExploreModel () { - const [searchParams, setSearchParams] = useSearchParams() + const [searchParams] = useSearchParams() const filterStar = useMemo(() => { return searchParams.get('filterStar') === 'true' }, [searchParams]) From 54d631caef963a2fafeb47baebc81f9f3092a99c Mon Sep 17 00:00:00 2001 From: bufan Date: Mon, 29 Jan 2024 19:00:18 +0800 Subject: [PATCH 6/8] extract explore composite list component --- .../components/model/ExploreCompositeList.tsx | 297 ++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 packages/client/dashboard/src/components/model/ExploreCompositeList.tsx diff --git a/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx b/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx new file mode 100644 index 0000000..8a9dc0a --- /dev/null +++ b/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx @@ -0,0 +1,297 @@ +import { useSession } from '@us3r-network/auth-with-rainbowkit' +import dayjs from 'dayjs' +import { useCallback, useEffect, useRef, useState } from 'react' +import { + Button, + Dialog, + DialogTrigger, + Modal, + ModalOverlay +} from 'react-aria-components' +import InfiniteScroll from 'react-infinite-scroll-component' +import styled from 'styled-components' +import { bindingDappComposites, getComposites } from '../../api/composite' +import { updateDapp } from '../../api/dapp' +import { startIndexModels } from '../../api/model' +import { PAGE_SIZE, S3_SCAN_URL } from '../../constants' +import { useAppCtx } from '../../context/AppCtx' +import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' +import useSelectedDapp from '../../hooks/useSelectedDapp' +import { CeramicStatus, DappCompositeDto, Network } from '../../types.d' +import { shortPubKey } from '../../utils/shortPubKey' +import { TableBox, TableContainer } from '../common/TableBox' +import CheckCircleIcon from '../icons/CheckCircleIcon' +import LayoutIcon from '../icons/LayoutIcon' +import PlusCircleIcon from '../icons/PlusCircleIcon' +import CreateCompositeModal from '../model/CreateCompositeModal' +import { Dapps } from '../model/ExploreModelList' +import NoCeramicNodeModal from '../node/NoCeramicNodeModal' + +export function CompositeList ({ + searchText +}: { + searchText?: string +}) { + const { selectedDapp } = useSelectedDapp() + const { currCeramicNode } = useCeramicNodeCtx() + const [composites, setComposites] = useState>([]) + const [hasMore, setHasMore] = useState(true) + const pageNum = useRef(1) + const fetchComposites = useCallback(async () => { + setComposites([]) + setHasMore(true) + const resp = await getComposites({ + name: searchText, + network: (selectedDapp?.network as Network) || Network.TESTNET + }) + const list = resp.data.data + setComposites(list) + setHasMore(list.length >= PAGE_SIZE) + pageNum.current = 1 + }, [searchText, selectedDapp?.network]) + + const fetchMoreComposites = useCallback( + async (pageNumber: number) => { + const resp = await getComposites({ + name: searchText, + pageNumber, + network: (selectedDapp?.network as Network) || Network.TESTNET + }) + const list = resp.data.data + setHasMore(list.length >= PAGE_SIZE) + setComposites([...composites, ...list]) + }, + [composites, searchText, selectedDapp?.network] + ) + + useEffect(() => { + fetchComposites() + }, [fetchComposites]) + + const lists = composites + return ( + <> + { + pageNum.current += 1 + fetchMoreComposites(pageNum.current) + console.log('fetch more') + }} + hasMore={hasMore} + loader={Loading...} + > + + + + + Composite Name + Stream ID + Release Date + Dapps + + + + + + {lists.map((item, idx) => { + return ( + + +
{item.name}
+ + +
+ {item.streamId ? ( + + {shortPubKey(item.streamId, { + len: 8, + split: '-' + })} + + ) : ( + '-' + )} +
+ + +
+ {dayjs(item.createdAt).format('YYYY-MM-DD HH:mm:ss') || + '-'} +
+ + + + + + {/* */} + dapp.id === selectedDapp?.id + ) !== -1 + } + ceramicNodeId={ + currCeramicNode && + currCeramicNode.status === CeramicStatus.RUNNING + ? currCeramicNode?.id + : undefined + } + /> + + + ) + })} + +
+
+
+ {!hasMore && no more data} + + ) +} + +function Actions ({ + composite, + hasIndexed, + ceramicNodeId +}: { + composite: DappCompositeDto + hasIndexed: boolean + ceramicNodeId?: number +}) { + const session = useSession() + + const { loadDapps } = useAppCtx() + const { selectedDapp } = useSelectedDapp() + const [adding, setAdding] = useState(false) + + const bindComposite = useCallback(async () => { + if (!session || !selectedDapp) return + if (!ceramicNodeId) return + if (!hasIndexed) { + bindingDappComposites({ + compositeId: composite.id, + dapp: selectedDapp, + did: session.serialize() + }) + .then( + () => { + const models = JSON.parse(composite.composite).models + console.log(Object.keys(models)) + const modelIds = Object.keys(models) + startIndexModels({ + modelIds, + network: selectedDapp.network, + didSession: session.serialize() + }).catch(console.error) + }, + err => { + console.error(err) + } + ) + .catch(console.error) + } + try { + setAdding(true) + const composites = selectedDapp.composites || [] + composites.push(composite) + await updateDapp( + { ...selectedDapp, composites }, + session.serialize(), + ceramicNodeId + ) + await loadDapps() + } catch (err) { + console.error(err) + } finally { + setAdding(false) + } + }, [session, selectedDapp, ceramicNodeId, hasIndexed, composite, loadDapps]) + return ( + + + + + + + {({ close }) => ( + + )} + + + + + {adding ? ( + + ) : ( + <> + {hasIndexed ? ( + + ) : ceramicNodeId ? ( + + ) : ( + + + + + + {({ close }) => } + + + + + )} + + )} + + ) +} + +const OpsBox = styled.div` + display: flex; + align-items: center; + gap: -5px; + img { + width: 17px; + } +` + +const Loading = styled.div` + padding: 20px; + text-align: center; + color: gray; +` From 83d0b3eb945981a19698e3dc54966b36ed7c3ded Mon Sep 17 00:00:00 2001 From: bufan Date: Tue, 30 Jan 2024 13:02:03 +0800 Subject: [PATCH 7/8] open explore models in modal --- ...positeModal.tsx => CreateNewComposite.tsx} | 2 +- .../model/DappModelAndComposites.tsx | 119 ++++++++++++++++-- .../components/model/ExploreCompositeList.tsx | 2 +- .../src/components/model/ExploreModelList.tsx | 10 +- .../src/components/model/FavoriteModal.tsx | 52 -------- 5 files changed, 117 insertions(+), 68 deletions(-) rename packages/client/dashboard/src/components/model/{CreateCompositeModal.tsx => CreateNewComposite.tsx} (99%) delete mode 100644 packages/client/dashboard/src/components/model/FavoriteModal.tsx diff --git a/packages/client/dashboard/src/components/model/CreateCompositeModal.tsx b/packages/client/dashboard/src/components/model/CreateNewComposite.tsx similarity index 99% rename from packages/client/dashboard/src/components/model/CreateCompositeModal.tsx rename to packages/client/dashboard/src/components/model/CreateNewComposite.tsx index cb03568..d739c97 100644 --- a/packages/client/dashboard/src/components/model/CreateCompositeModal.tsx +++ b/packages/client/dashboard/src/components/model/CreateNewComposite.tsx @@ -11,7 +11,7 @@ import { createCompositeFromBrowser } from '../../utils/composeDBUtils' import { useCeramicNodeCtx } from '../../context/CeramicNodeCtx' import { startIndexModels } from '../../api/model' -export default function CreateCompositeModal ({ +export default function CreateNewComposite ({ closeModal, loadDappComposites, defaultName, diff --git a/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx index 208f115..9bb7f70 100644 --- a/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx +++ b/packages/client/dashboard/src/components/model/DappModelAndComposites.tsx @@ -11,7 +11,7 @@ import { ModalOverlay, Popover } from 'react-aria-components' -import { useLocation, useNavigate } from 'react-router-dom' +import { useLocation } from 'react-router-dom' import styled from 'styled-components' import { deleteDappComposites, getDappComposites } from '../../api/composite' import { updateDapp } from '../../api/dapp' @@ -33,10 +33,12 @@ import MergeIcon from '../icons/MergeIcon' import PlusIcon from '../icons/PlusIcon' import TrashIcon from '../icons/TrashIcon' import NoCeramicNodeModal from '../node/NoCeramicNodeModal' -import CreateCompositeModal from './CreateCompositeModal' +import CreateNewComposite from './CreateNewComposite' import CreateNewModel from './CreateNewModel' -import FavoriteModel from './FavoriteModal' import MergeModal from './MergeModal' +import CloseIcon from '../icons/CloseIcon' +import ModelList from './ExploreModelList' +import { CompositeList } from './ExploreCompositeList' enum OPEN_MODAL { NONE, @@ -44,8 +46,8 @@ enum OPEN_MODAL { ADD_FROM_ALL_MODELS, ADD_FROM_FAVORITE_MODELS, CREATE_NEW_COMPOSITE, - ADD_FROM_ALL_COMPOSITES, - ADD_FROM_FAVORITE_COMPOSITES + ADD_FROM_ALL_COMPOSITES + // ADD_FROM_FAVORITE_COMPOSITES } export default function DappModelAndComposites ({ @@ -66,7 +68,6 @@ export default function DappModelAndComposites ({ const { loadDapps, currDapp } = useAppCtx() const { appId, selectedDapp } = useSelectedDapp() const { currCeramicNode } = useCeramicNodeCtx() - const navigate = useNavigate() const [loading, setLoading] = useState(false) const [dappModels, setDappModels] = useState() const [dappComposites, setDappComposites] = useState([]) @@ -237,7 +238,7 @@ export default function DappModelAndComposites ({ { if (id === 'explore') { - navigate(`/dapp/${appId}/explore/model`) + setOpenModal(OPEN_MODAL.ADD_FROM_ALL_MODELS) return } if (id === 'favorite') { @@ -250,7 +251,7 @@ export default function DappModelAndComposites ({ } }} > - Explore Models + Add From Popular Models Add From Favorite Create New Model @@ -308,7 +309,7 @@ export default function DappModelAndComposites ({ { if (id === 'explore') { - navigate(`/dapp/${appId}/explore/composite`) + setOpenModal(OPEN_MODAL.ADD_FROM_ALL_COMPOSITES) return } if (id === 'create') { @@ -317,7 +318,9 @@ export default function DappModelAndComposites ({ } }} > - Explore Composites + + Add From Popular Composites + Create New Composites @@ -334,19 +337,21 @@ export default function DappModelAndComposites ({ /> )} + {/* CREATE_NEW_MODEL modal */} setOpenModal(OPEN_MODAL.NONE)} > {({ close }) => } + {/* CREATE_NEW_COMPOSITE modal */} setOpenModal(OPEN_MODAL.NONE)} > {({ close }) => ( - + {/* ADD_FROM_FAVORITE_MODELS modal */} setOpenModal(OPEN_MODAL.NONE)} > - {({ close }) => } + + {({ close }) => ( + +
+

My Favorite Models

+ +
+
+ +
+
+ )} +
+
+ {/* ADD_FROM_ALL_MODELS modal */} + setOpenModal(OPEN_MODAL.NONE)} + > + + {({ close }) => ( + +
+

Popular Models

+ +
+
+ +
+
+ )} +
+
+ {/* ADD_FROM_ALL_COMPOSITES modal */} + setOpenModal(OPEN_MODAL.NONE)} + > + + {({ close }) => ( + +
+

Popular Composites

+ +
+
+ +
+
+ )} +
{editable && isOwner && ( @@ -651,3 +713,36 @@ const MergeBox = styled.div` gap: 10px; } ` +const DialogBox = styled.div` + display: flex; + flex-direction: column; + padding: 20px; + gap: 20px; + height: calc(100vh - 100px); + position: relative; + width: 1240px; + margin: 0 auto; + + background: #1b1e23; + border-radius: 20px; + + > div.title { + flex: 0 0 42px; + display: flex; + align-items: center; + justify-content: space-between; + + color: #ffffff; + > h1 { + margin: 0; + font-style: italic; + font-weight: 700; + font-size: 24px; + line-height: 28px; + } + } + > div.content { + height: 0; + flex: 1; + } +` diff --git a/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx b/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx index 8a9dc0a..367a3d7 100644 --- a/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx +++ b/packages/client/dashboard/src/components/model/ExploreCompositeList.tsx @@ -23,7 +23,7 @@ import { TableBox, TableContainer } from '../common/TableBox' import CheckCircleIcon from '../icons/CheckCircleIcon' import LayoutIcon from '../icons/LayoutIcon' import PlusCircleIcon from '../icons/PlusCircleIcon' -import CreateCompositeModal from '../model/CreateCompositeModal' +import CreateCompositeModal from './CreateNewComposite' import { Dapps } from '../model/ExploreModelList' import NoCeramicNodeModal from '../node/NoCeramicNodeModal' diff --git a/packages/client/dashboard/src/components/model/ExploreModelList.tsx b/packages/client/dashboard/src/components/model/ExploreModelList.tsx index 0d3ece9..462e2e4 100644 --- a/packages/client/dashboard/src/components/model/ExploreModelList.tsx +++ b/packages/client/dashboard/src/components/model/ExploreModelList.tsx @@ -149,7 +149,7 @@ export default function ModelList ({ }, [filterStar, models, starModels]) return ( - <> + { @@ -272,7 +272,7 @@ export default function ModelList ({ {!filterStar && !hasMore && no more data} - + ) } @@ -305,6 +305,12 @@ export function Dapps ({ dapps }: { dapps: ClientDApp[] }) { ) } +const Box = styled.div` + height: 100%; + overflow: auto; + position: relative; +` + const DappBox = styled.div` display: flex; gap: 5px; diff --git a/packages/client/dashboard/src/components/model/FavoriteModal.tsx b/packages/client/dashboard/src/components/model/FavoriteModal.tsx deleted file mode 100644 index c5cb9b7..0000000 --- a/packages/client/dashboard/src/components/model/FavoriteModal.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import styled from 'styled-components' -import CloseIcon from '../icons/CloseIcon' -import ModelList from './ExploreModelList' - -export default function FavoriteModal({ - closeModal, -}: { - closeModal: () => void -}) { - return ( - -
-

My Favorite Models

- -
-
- -
-
- ) -} - -const FavoriteBox = styled.div` - display: flex; - flex-direction: column; - padding: 20px; - gap: 20px; - min-height: calc(100vh - 300px); - position: relative; - width: 1240px; - margin: 0 auto; - - background: #1b1e23; - border-radius: 20px; - - > div.title { - display: flex; - align-items: center; - justify-content: space-between; - - color: #ffffff; - > h1 { - margin: 0; - font-style: italic; - font-weight: 700; - font-size: 24px; - line-height: 28px; - } - } -` From 58ff7a38ef829666da7e30fad0d8f1ee719fc454 Mon Sep 17 00:00:00 2001 From: bufan Date: Tue, 30 Jan 2024 17:45:25 +0800 Subject: [PATCH 8/8] adjust nav --- .../{CheckronDown.tsx => ChevronDown.tsx} | 0 .../src/components/model/CodeDownload.tsx | 2 +- .../dashboard/src/components/nav/Nav.tsx | 288 +++++++++++------- .../dashboard/src/container/DappHome.tsx | 2 +- 4 files changed, 178 insertions(+), 114 deletions(-) rename packages/client/dashboard/src/components/icons/{CheckronDown.tsx => ChevronDown.tsx} (100%) diff --git a/packages/client/dashboard/src/components/icons/CheckronDown.tsx b/packages/client/dashboard/src/components/icons/ChevronDown.tsx similarity index 100% rename from packages/client/dashboard/src/components/icons/CheckronDown.tsx rename to packages/client/dashboard/src/components/icons/ChevronDown.tsx diff --git a/packages/client/dashboard/src/components/model/CodeDownload.tsx b/packages/client/dashboard/src/components/model/CodeDownload.tsx index 51e3dd7..9b33fae 100644 --- a/packages/client/dashboard/src/components/model/CodeDownload.tsx +++ b/packages/client/dashboard/src/components/model/CodeDownload.tsx @@ -1,7 +1,7 @@ import FileSaver from 'file-saver' import { useState } from 'react' import styled from 'styled-components' -import ChevronDown from '../icons/CheckronDown' +import ChevronDown from '../icons/ChevronDown' import DownloadIcon from '../icons/DownloadIcon' import { Code } from './ModelSDK' diff --git a/packages/client/dashboard/src/components/nav/Nav.tsx b/packages/client/dashboard/src/components/nav/Nav.tsx index 33a8f7c..aa217a5 100644 --- a/packages/client/dashboard/src/components/nav/Nav.tsx +++ b/packages/client/dashboard/src/components/nav/Nav.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useState } from 'react' -import { Link, NavLink, useSearchParams } from 'react-router-dom' +import { Link, NavLink } from 'react-router-dom' import styled from 'styled-components' import { DOCS_URL } from '../../constants' import ChartIcon from '../icons/ChartIcon' @@ -12,113 +12,167 @@ import InfoIcon from '../icons/InfoIcon' import LayoutIcon from '../icons/LayoutIcon' import NodeIcon from '../icons/NodeIcon' import SdkIcon from '../icons/SdkIcon' -import StarGoldIcon from '../icons/StarGoldIcon' -import StarIcon from '../icons/StarIcon' import TerminalIcon from '../icons/TerminalIcon' +import ChevronDown from '../icons/ChevronDown' -export default function Nav({ appId }: { appId: string }) { - const [open, setOpen] = useState(true) - const [searchParams] = useSearchParams() +type NavItem = { + path?: string + name: string + icon: any + items?: NavItem[] +} - const filterStar = useMemo(() => { - return searchParams.get('filterStar') || '' - }, [searchParams]) +export default function Nav ({ appId }: { appId: string }) { + const [open, setOpen] = useState(true) + const navItems = useMemo(() => { + return [ + { + path: `/dapp/${appId}/index`, + name: 'Home', + icon: HomeIcon + }, + { + // path: `/dapp/${appId}/explore`, + name: 'Explore', + icon: ExploreIcon, + items: [ + { + path: `/dapp/${appId}/explore/model`, + name: 'Models', + icon: ExploreIcon + }, + { + path: `/dapp/${appId}/explore/composite`, + name: 'Composites', + icon: ExploreIcon + }, + { + path: `/dapp/${appId}/components`, + name: 'Components', + icon: ComponentIcon + } + ] + }, + { + // path: `/dapp/${appId}/build`, + name: 'Build', + icon: InfoIcon, + items: [ + { + path: `/dapp/${appId}/model-editor`, + name: 'Compose', + icon: LayoutIcon + }, + { + path: `/dapp/${appId}/model-playground`, + name: 'Playground', + icon: TerminalIcon + }, + { + path: `/dapp/${appId}/model-sdk`, + name: 'SDK', + icon: SdkIcon + }, + { + path: `/dapp/${appId}/statistic`, + name: 'Metrics', + icon: ChartIcon + } + ] + }, + { + path: `/dapp/${appId}/node`, + name: 'Node', + icon: NodeIcon + }, + { + path: `/dapp/${appId}/info`, + name: 'Info', + icon: InfoIcon + } + ] + }, [appId]) return (
-
-
- {[ - { - path: `/dapp/${appId}/index`, - name: 'Home', - icon: HomeIcon, - }, - { - path: `/dapp/${appId}/node`, - name: 'Node Deployment', - icon: NodeIcon, - }, - { - path: `/dapp/${appId}/model-editor`, - name: 'Model Editor', - icon: LayoutIcon, - }, - { - path: `/dapp/${appId}/model-playground`, - name: 'Model Playground', - icon: TerminalIcon, - }, - { - path: `/dapp/${appId}/model-sdk`, - name: 'Model SDK', - icon: SdkIcon, - }, - { - path: `/dapp/${appId}/statistic`, - name: 'Model Metrics', - icon: ChartIcon, - }, - { - path: `/dapp/${appId}/components`, - name: 'S3 Components', - icon: ComponentIcon, - }, - { - path: `/dapp/${appId}/info`, - name: 'Info', - icon: InfoIcon, - }, - ].map((item) => { - return ( - - {({ isActive }) => ( -
- {React.createElement(item.icon, { isActive })} - {item.name} -
- )} -
- ) - })} +
+
+ {navItems.map(item => ( + + ))}
-
- - {({ isActive }) => ( -
- - Explore -
- )} -
- - -
- {(filterStar && ) || } - Favorite +
+ +
+ + S3 Scan
- - -
+ + +
Document
-
setOpen(!open)}> + {/*
setOpen(!open)}> -
+
*/}
) } + +function NavItemRenderer ({ + item, + level = 0, +}: { + item: NavItem + level?: number +}) { + return ( + +
+ {item.path ? ( + + {({ isActive }) => ( +
+ {React.createElement(item.icon, { isActive })} + {item.name} +
+ )} +
+ ) : ( +
+ {React.createElement(item.icon)} + {item.name} +
+ )} + {item.items && ( +
+ +
+ )} +
+ {item.items && ( +
+ {item.items.map(item => ( + + ))} +
+ )} +
+ ) +} + + const NavContainer = styled.nav<{ open?: boolean }>` > div { height: calc(100vh - 60px); - width: ${(props) => (props.open ? '200px' : '57px')}; + width: ${props => (props.open ? '200px' : '57px')}; top: 60px; bottom: 0; @@ -134,44 +188,46 @@ const NavContainer = styled.nav<{ open?: boolean }>` align-items: center; justify-content: space-between; - .active .item { - background: #14171a; - color: #fff; - } - .item { - padding: 10px; - border-radius: 10px; - color: #718096; - position: relative; + .item-container { display: flex; + flex-direction: row; + justify-content: space-between; align-items: center; - gap: 10px; - margin-top: 20px; - overflow: hidden; - > span { - opacity: ${(props) => (props.open ? 1 : 0)}; - position: absolute; - left: 37px; - width: 150px; - transition: opacity 0.09s ease-in-out; - } + gap: 1px; + } + .item { + flex: 1; + padding: 10px; + border-radius: 10px; + color: #718096; + position: relative; + display: flex; + align-items: center; + gap: 10px; + overflow: hidden; + > span { + opacity: ${props => (props.open ? 1 : 0)}; + transition: opacity 0.09s ease-in-out; + } - &.active { - background: #14171a; - color: #fff; + &.active { + background: #14171a; + color: #fff; + } } - } .top { width: 100%; padding: 10px; box-sizing: border-box; - display: block; + display: flex; + flex-direction: column; + gap: 20px; } .bottom { width: 100%; - margin-bottom: 20px; + margin-bottom: 10px; padding: 10px; box-sizing: border-box; display: block; @@ -194,14 +250,22 @@ const NavContainer = styled.nav<{ open?: boolean }>` justify-content: center; cursor: pointer; transition: transform 0.1s ease-in-out; - transform: ${(props) => + transform: ${props => props.open ? `rotate(180deg)` : `rotate(0deg)`}; } } } } +` - .star { - cursor: pointer; +const NavItemBox = styled.div` + display: flex; + flex-direction: column; + gap: 6px; + .sub { + margin-left: 24px; + display: flex; + flex-direction: column; + gap: 6px; } ` diff --git a/packages/client/dashboard/src/container/DappHome.tsx b/packages/client/dashboard/src/container/DappHome.tsx index 85b9bab..ba6a076 100644 --- a/packages/client/dashboard/src/container/DappHome.tsx +++ b/packages/client/dashboard/src/container/DappHome.tsx @@ -6,7 +6,7 @@ import styled from 'styled-components' import Dashboard from '../components/dapp/home/Dashboard' import Header from '../components/dapp/home/Header' import CheckCircleIcon from '../components/icons/CheckCircleIcon' -import ChevronDown from '../components/icons/CheckronDown' +import ChevronDown from '../components/icons/ChevronDown' import { ChevronRightDoubleWhite } from '../components/icons/ChevronRightDouble' import DisabledIcon from '../components/icons/DisabledIcon' import LightbulbIcon from '../components/icons/LightbulbIcon'