From d69fb98d1acfbe57dff0830e572c6172b1ab3b80 Mon Sep 17 00:00:00 2001 From: osdodo Date: Tue, 12 Sep 2023 12:38:43 +0800 Subject: [PATCH 1/2] update LiveIcon --- src/components/IDE/EventLogs/index.tsx | 80 ++++---------------------- 1 file changed, 11 insertions(+), 69 deletions(-) diff --git a/src/components/IDE/EventLogs/index.tsx b/src/components/IDE/EventLogs/index.tsx index 348d7e20..09a78f41 100644 --- a/src/components/IDE/EventLogs/index.tsx +++ b/src/components/IDE/EventLogs/index.tsx @@ -11,78 +11,9 @@ import { VscDebugStart } from 'react-icons/vsc'; import { hooks } from '@/lib/hooks'; import { AiOutlineClear } from 'react-icons/ai'; import { ShowRequestTemplatesButton } from '../PublishEventRequestTemplates'; -import { motion, isValidMotionProp } from 'framer-motion'; import toast from 'react-hot-toast'; import { helper } from '@/lib/helper'; -const ChakraBox = chakra(motion.div, { - /** - * Allow motion props and non-Chakra props to be forwarded. - */ - shouldForwardProp: (prop) => isValidMotionProp(prop) || shouldForwardProp(prop) -}); - -const LiveIcon = () => { - return ( - - - - - ); -}; - type LocalStoreType = { loading: boolean; initialized: boolean; @@ -366,3 +297,14 @@ const EventLogs = observer(() => { }); export default EventLogs; + +const LiveIcon = () => { + return ( +
+ + + + +
+ ); +}; From c4553d118d7edc259df98f489e27b24f65e6a4d1 Mon Sep 17 00:00:00 2001 From: osdodo Date: Tue, 12 Sep 2023 13:59:56 +0800 Subject: [PATCH 2/2] add operator module --- .../IDE/UserSettings/Operators/index.tsx | 55 ++++++ src/components/IDE/UserSettings/index.tsx | 13 +- src/components/JSONTable/index.tsx | 52 +++--- src/store/lib/w3bstream/index.ts | 2 + src/store/lib/w3bstream/schema/operator.ts | 173 ++++++++++++++++++ 5 files changed, 266 insertions(+), 29 deletions(-) create mode 100644 src/components/IDE/UserSettings/Operators/index.tsx create mode 100644 src/store/lib/w3bstream/schema/operator.ts diff --git a/src/components/IDE/UserSettings/Operators/index.tsx b/src/components/IDE/UserSettings/Operators/index.tsx new file mode 100644 index 00000000..66c6b649 --- /dev/null +++ b/src/components/IDE/UserSettings/Operators/index.tsx @@ -0,0 +1,55 @@ +import { Flex, Button, Text, Spinner, Center } from '@chakra-ui/react'; +import { observer } from 'mobx-react-lite'; +import { useStore } from '@/store/index'; +import { defaultButtonStyle } from '@/lib/theme'; +import JSONTable from '@/components/JSONTable'; +import { hooks } from '@/lib/hooks'; + +export const Operators = observer(() => { + const { + w3s: { operator } + } = useStore(); + operator.useOperators(); + + return ( + <> + + + Operators + + + + + + Create your operators + + {operator.list.loading.value ? ( +
+ +
+ ) : ( + + )} + + ); +}); diff --git a/src/components/IDE/UserSettings/index.tsx b/src/components/IDE/UserSettings/index.tsx index 451aa916..f3e4b16f 100644 --- a/src/components/IDE/UserSettings/index.tsx +++ b/src/components/IDE/UserSettings/index.tsx @@ -1,19 +1,15 @@ import React, { useEffect } from 'react'; import { Box } from '@chakra-ui/react'; -import dynamic from 'next/dynamic'; import { observer } from 'mobx-react-lite'; import { useStore } from '@/store/index'; -import Header from '@/components/IDE/Header'; import { ApiKeys } from './ApiKeys'; +import { Operators } from './Operators'; const UserSettings = observer(() => { - const { - w3s, - base: { confirm } - } = useStore(); + const { w3s } = useStore(); useEffect(() => { - w3s.user.userSetting.call() + w3s.user.userSetting.call(); }, []); return ( @@ -21,6 +17,9 @@ const UserSettings = observer(() => { + + + ); }); diff --git a/src/components/JSONTable/index.tsx b/src/components/JSONTable/index.tsx index f04658e9..7ce27ea3 100644 --- a/src/components/JSONTable/index.tsx +++ b/src/components/JSONTable/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect } from 'react'; import { observer } from 'mobx-react-lite'; -import { Button, Center, Table as ChakraTable, TableContainer, Tbody, Td, Th, Thead, Tr, useDisclosure,Text } from '@chakra-ui/react'; +import { Button, Center, Table as ChakraTable, TableContainer, Tbody, Td, Th, Thead, Tr, useDisclosure, Text } from '@chakra-ui/react'; import SimplePagination from '../Common/SimplePagination'; import { ChevronDownIcon, ChevronRightIcon } from '@chakra-ui/icons'; import { ActionButtonType, Column, ExtendedTable, JSONSchemaTableState } from '@/store/standard/JSONSchemaState'; @@ -34,8 +34,10 @@ const JSONTable = observer((props: JSONTableProps) => { {needExtendedTable && } {columns.map((item) => ( - - {item.label} + + + {item.label} + ))} @@ -50,19 +52,25 @@ const JSONTable = observer((props: JSONTableProps) => { )} - {pagination.total == 0 &&
No Data
} + {pagination.total == 0 && ( +
+ No Data +
+ )} - {pagination.total > pagination.limit && { - pagination.setData({ - page: currentPage - }); - }} - />} + {pagination.total > pagination.limit && ( + { + pagination.setData({ + page: currentPage + }); + }} + /> + )} ); }); @@ -94,12 +102,12 @@ function Body({ item, columns }: { item: T; columns: Column[] }) { {columns.map((column) => { return ( - + {column.actions ? column.actions(item).map((btn, index) => ) : column.render - ? column.render(item) - : renderFieldValue(item[column.key])} + ? column.render(item) + : renderFieldValue(item[column.key])} ); })} @@ -131,8 +139,8 @@ function CollapseBody({ item, columns, extendedTables }: { item: T; columns: {column.actions ? column.actions(item).map((btn, index) => ) : column.render - ? column.render(item) - : renderFieldValue(item[column.key])} + ? column.render(item) + : renderFieldValue(item[column.key])} ); })} @@ -166,8 +174,8 @@ function CollapseBody({ item, columns, extendedTables }: { item: T; columns: {exC.actions ? exC.actions(exItem).map((btn, index) => ) : exC.render - ? exC.render(exItem) - : renderFieldValue(exItem[exC.key])} + ? exC.render(exItem) + : renderFieldValue(exItem[exC.key])} ); })} diff --git a/src/store/lib/w3bstream/index.ts b/src/store/lib/w3bstream/index.ts index e0db993d..c89f685b 100644 --- a/src/store/lib/w3bstream/index.ts +++ b/src/store/lib/w3bstream/index.ts @@ -23,6 +23,7 @@ import LabModule from './schema/lab'; import CronJobModule from './schema/cronJob'; import ENVModule from './schema/envs'; import ApiKeysModule from './schema/apiKeys'; +import OperatorModule from './schema/operator'; configure({ enforceActions: 'never' @@ -42,6 +43,7 @@ export class W3bStream { strategy = new StrategyModule(); contractLogs = new ContractLogModule(); apiKeys = new ApiKeysModule(); + operator = new OperatorModule(); chainTx = new ChainTxModule(); chainHeight = new ChainHeightModule(); dbTable = new DBTableModule(); diff --git a/src/store/lib/w3bstream/schema/operator.ts b/src/store/lib/w3bstream/schema/operator.ts new file mode 100644 index 00000000..4c27d688 --- /dev/null +++ b/src/store/lib/w3bstream/schema/operator.ts @@ -0,0 +1,173 @@ +import { JSONValue, JSONSchemaFormState, JSONSchemaTableState } from '@/store/standard/JSONSchemaState'; +import { FromSchema } from 'json-schema-to-ts'; +import { eventBus } from '@/lib/event'; +import { axios } from '@/lib/axios'; +import toast from 'react-hot-toast'; +import { defaultOutlineButtonStyle } from '@/lib/theme'; +import { PromiseState } from '@/store/standard/PromiseState'; +import { useEffect } from 'react'; +import { PaginationState } from '@/store/standard/PaginationState'; + +export const schema = { + definitions: { + types: { + type: 'number', + get enum() { + return [1, 2]; + }, + get enumNames() { + return ['ECDSA', 'ED25519']; + } + } + }, + type: 'object', + properties: { + name: { type: 'string', title: 'Name' }, + privateKey: { type: 'string', title: 'Private Key' }, + type: { $ref: '#/definitions/types', title: 'Type' }, + paymasterKey: { type: 'string', title: 'Paymaster Key', description: 'The paymaster key is optional and indicates whether or not the aa Payment in Lieu function is used, and the key issued by the Payment in Lieu service.'} + }, + required: ['name', 'privateKey', 'type'] +} as const; + +type SchemaType = FromSchema; + +export default class OperatorModule { + table = new JSONSchemaTableState<{ + operatorID: string; + type: 1 | 2; + address: string; + name: string; + accountID: string; + createdAt: string; + updatedAt: string; + }>({ + columns: [ + { + key: 'actions', + label: 'Actions', + actions: (item) => { + return [ + { + props: { + size: 'xs', + ...defaultOutlineButtonStyle, + onClick: () => { + globalThis.store.base.confirm.show({ + title: 'Warning', + description: 'Are you sure you want to delete it?', + onOk: async () => { + await axios.request({ + method: 'delete', + url: `/api/w3bapp/operator/data/${item.operatorID}` + }); + toast.success('Deleted successfully'); + this.list.call(); + } + }); + } + }, + text: 'Delete' + } + ]; + } + }, + { + key: 'operatorID', + label: 'Operator ID' + }, + { + key: 'name', + label: 'Name' + }, + { + key: 'type', + label: 'Type', + render: (item) => { + return item.type == 1 ? 'ECDSA' : 'ED25519'; + } + }, + { + key: 'address', + label: 'Address' + } + ], + pagination: new PaginationState({ + page: 1, + limit: 5, + onPageChange: (currentPage) => { + this.list.call(); + } + }), + isServerPaging: true, + rowKey: 'operatorID', + containerProps: { mt: '10px' } + }); + + form = new JSONSchemaFormState({ + //@ts-ignore + schema, + uiSchema: { + 'ui:submitButtonOptions': { + norender: false, + submitText: 'Submit' + }, + }, + afterSubmit: async (e) => { + eventBus.emit('base.formModal.afterSubmit', e.formData); + this.form.reset(); + }, + value: new JSONValue({ + default: { + name: '', + privateKey: '', + type: 1, + paymasterKey: '' + } + }) + }); + + createOperator = new PromiseState({ + function: async (formData: { name: string; privateKey: string; type: 1 | 2; paymasterKey?: string }) => { + const res = await axios.request({ + method: 'post', + url: `/api/w3bapp/operator`, + data: formData + }); + toast.success('Created successfully'); + this.list.call(); + return res; + } + }); + + list = new PromiseState({ + function: async () => { + const { page, limit } = this.table.pagination; + const offset = page * limit - limit; + const res = await axios.request({ + method: 'get', + url: `/api/w3bapp/operator/datalist`, + params: { + offset, + size: limit + } + }); + const data = res.data; + if (data?.data) { + this.table.set({ + dataSource: data.data + }); + this.table.pagination.setData({ + total: data.total + }); + } + return res; + } + }); + + useOperators() { + useEffect(() => { + this.list.call(); + }, []); + } +}