Implemented market places.
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
This commit is contained in:
parent
120fb89837
commit
8e393e229f
5
assets/icons/marketplaceicon.svg
Normal file
5
assets/icons/marketplaceicon.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
|
||||||
|
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" version="1.1" viewBox="0 0 72 69" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m20.601 66.402v-19.472h8.932v19.472h28.517c4.163 0 6.597-2.375 6.597-6.48v-23.76c3.033-1.711 5.043-4.945 5.043-8.699v-0.498c0-1.144-0.293-2.17-0.88-3.167l-7.77-13.283v-2.433c0-3.724-2.287-5.952-6.069-5.952h-37.912c-3.783 0-6.099 2.228-6.099 5.952v2.433l-7.77 13.283c-0.587 0.997-0.88 2.023-0.88 3.167v0.498c0 3.754 2.01 6.988 5.043 8.699v23.76c0 4.105 2.434 6.48 6.597 6.48h6.651zm39.325-28.945c-0.098 3e-3 -0.195 5e-3 -0.293 5e-3 -3.255 0-6.099-1.496-7.858-3.871-1.789 2.375-4.604 3.871-7.888 3.871s-6.128-1.496-7.887-3.871c-1.759 2.375-4.603 3.871-7.887 3.871-3.255 0-6.099-1.496-7.858-3.871-1.789 2.375-4.633 3.871-7.888 3.871-0.098 0-0.195-2e-3 -0.293-5e-3v21.262c0 1.906 1.026 2.962 2.903 2.962h1.759v-16.449c0-1.349 0.909-2.229 2.258-2.229h12.432c1.349 0 2.228 0.88 2.228 2.229v16.449h23.399c1.876 0 2.873-1.056 2.873-2.962v-21.262zm-37.443-8.088h11.289c-0.645 2.375-2.639 3.958-5.659 3.958-2.991 0-5.014-1.583-5.63-3.958zm31.52 0h11.289c-0.645 2.375-2.639 3.958-5.659 3.958-2.991 0-5.014-1.583-5.63-3.958zm-47.295 0h11.318c-0.645 2.375-2.639 3.958-5.659 3.958s-5.014-1.583-5.659-3.958zm31.52 0h11.318c-0.645 2.375-2.639 3.958-5.659 3.958s-5.013-1.583-5.659-3.958zm-30.846-4.134 6.363-11.201h44.275l6.539 11.201h-57.177zm8.005-15.629v-0.703c0-1.466 0.851-2.346 2.287-2.346h36.652c1.437 0 2.287 0.88 2.287 2.346v0.703h-41.226z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
107
src/components/Dashboard/Sales/Marketplaces.jsx
Normal file
107
src/components/Dashboard/Sales/Marketplaces.jsx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import { useState, useRef } from 'react'
|
||||||
|
import { Button, Flex, Space, Modal, Dropdown } from 'antd'
|
||||||
|
import NewMarketplace from './Marketplaces/NewMarketplace'
|
||||||
|
import ObjectTable from '../common/ObjectTable'
|
||||||
|
import PlusIcon from '../../Icons/PlusIcon'
|
||||||
|
import ReloadIcon from '../../Icons/ReloadIcon'
|
||||||
|
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||||
|
import ObjectTableViewButton from '../common/ObjectTableViewButton'
|
||||||
|
import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||||
|
import useViewMode from '../hooks/useViewMode'
|
||||||
|
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||||
|
import ColumnViewButton from '../common/ColumnViewButton'
|
||||||
|
import ExportListButton from '../common/ExportListButton'
|
||||||
|
|
||||||
|
const Marketplaces = () => {
|
||||||
|
const [newMarketplaceOpen, setNewMarketplaceOpen] = useState(false)
|
||||||
|
const tableRef = useRef()
|
||||||
|
|
||||||
|
const [viewMode, setViewMode] = useViewMode('marketplaces')
|
||||||
|
|
||||||
|
const [columnVisibility, setColumnVisibility] =
|
||||||
|
useColumnVisibility('marketplaces')
|
||||||
|
|
||||||
|
const [showFilterSidebar, setShowFilterSidebar] =
|
||||||
|
useFilterSidebarVisibility('Marketplaces')
|
||||||
|
|
||||||
|
const actionItems = {
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: 'New Marketplace',
|
||||||
|
key: 'newMarketplace',
|
||||||
|
icon: <PlusIcon />
|
||||||
|
},
|
||||||
|
{ type: 'divider' },
|
||||||
|
{
|
||||||
|
label: 'Reload List',
|
||||||
|
key: 'reloadList',
|
||||||
|
icon: <ReloadIcon />
|
||||||
|
}
|
||||||
|
],
|
||||||
|
onClick: ({ key }) => {
|
||||||
|
if (key === 'reloadList') {
|
||||||
|
tableRef.current?.reload()
|
||||||
|
} else if (key === 'newMarketplace') {
|
||||||
|
setNewMarketplaceOpen(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||||
|
<Flex justify={'space-between'}>
|
||||||
|
<Space size='small'>
|
||||||
|
<Dropdown menu={actionItems}>
|
||||||
|
<Button>Actions</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<ColumnViewButton
|
||||||
|
type='marketplace'
|
||||||
|
loading={false}
|
||||||
|
visibleState={columnVisibility}
|
||||||
|
updateVisibleState={setColumnVisibility}
|
||||||
|
/>
|
||||||
|
<ExportListButton objectType='marketplace' />
|
||||||
|
</Space>
|
||||||
|
<Space>
|
||||||
|
<FilterSidebarButton
|
||||||
|
active={showFilterSidebar}
|
||||||
|
onClick={() => setShowFilterSidebar(!showFilterSidebar)}
|
||||||
|
/>
|
||||||
|
<ObjectTableViewButton
|
||||||
|
viewMode={viewMode}
|
||||||
|
setViewMode={setViewMode}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
<ObjectTable
|
||||||
|
ref={tableRef}
|
||||||
|
visibleColumns={columnVisibility}
|
||||||
|
type='marketplace'
|
||||||
|
cards={viewMode === 'cards'}
|
||||||
|
showFilterSidebar={showFilterSidebar}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
<Modal
|
||||||
|
open={newMarketplaceOpen}
|
||||||
|
styles={{ content: { paddingBottom: '24px' } }}
|
||||||
|
footer={null}
|
||||||
|
width={800}
|
||||||
|
onCancel={() => {
|
||||||
|
setNewMarketplaceOpen(false)
|
||||||
|
}}
|
||||||
|
destroyOnHidden={true}
|
||||||
|
>
|
||||||
|
<NewMarketplace
|
||||||
|
onOk={() => {
|
||||||
|
setNewMarketplaceOpen(false)
|
||||||
|
tableRef.current?.reload()
|
||||||
|
}}
|
||||||
|
reset={newMarketplaceOpen}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Marketplaces
|
||||||
200
src/components/Dashboard/Sales/Marketplaces/MarketplaceInfo.jsx
Normal file
200
src/components/Dashboard/Sales/Marketplaces/MarketplaceInfo.jsx
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { useRef, useState } from 'react'
|
||||||
|
import { useLocation } from 'react-router-dom'
|
||||||
|
import { Space, Flex } from 'antd'
|
||||||
|
import loglevel from 'loglevel'
|
||||||
|
import config from '../../../../config'
|
||||||
|
import useCollapseState from '../../hooks/useCollapseState'
|
||||||
|
import NotesPanel from '../../common/NotesPanel'
|
||||||
|
import InfoCollapse from '../../common/InfoCollapse'
|
||||||
|
import ObjectInfo from '../../common/ObjectInfo'
|
||||||
|
import ViewButton from '../../common/ViewButton'
|
||||||
|
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
||||||
|
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||||
|
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
||||||
|
import ObjectForm from '../../common/ObjectForm'
|
||||||
|
import EditButtons from '../../common/EditButtons'
|
||||||
|
import LockIndicator from '../../common/LockIndicator.jsx'
|
||||||
|
import ActionHandler from '../../common/ActionHandler.jsx'
|
||||||
|
import ObjectActions from '../../common/ObjectActions.jsx'
|
||||||
|
import ObjectTable from '../../common/ObjectTable.jsx'
|
||||||
|
import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
|
||||||
|
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
|
||||||
|
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
|
||||||
|
import ScrollBox from '../../common/ScrollBox.jsx'
|
||||||
|
import { Card } from 'antd'
|
||||||
|
|
||||||
|
const log = loglevel.getLogger('MarketplaceInfo')
|
||||||
|
log.setLevel(config.logLevel)
|
||||||
|
|
||||||
|
const MarketplaceInfo = () => {
|
||||||
|
const location = useLocation()
|
||||||
|
const objectFormRef = useRef(null)
|
||||||
|
const actionHandlerRef = useRef(null)
|
||||||
|
const marketplaceId = new URLSearchParams(location.search).get('marketplaceId')
|
||||||
|
const [collapseState, updateCollapseState] = useCollapseState('MarketplaceInfo', {
|
||||||
|
info: true,
|
||||||
|
notes: true,
|
||||||
|
auditLogs: true
|
||||||
|
})
|
||||||
|
const [objectFormState, setEditFormState] = useState({
|
||||||
|
isEditing: false,
|
||||||
|
editLoading: false,
|
||||||
|
formValid: false,
|
||||||
|
lock: null,
|
||||||
|
loading: false,
|
||||||
|
objectData: {}
|
||||||
|
})
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
reload: () => {
|
||||||
|
objectFormRef?.current?.handleFetchObject?.()
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
edit: () => {
|
||||||
|
objectFormRef?.current?.startEditing?.()
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
cancelEdit: () => {
|
||||||
|
objectFormRef?.current?.cancelEditing?.()
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
finishEdit: () => {
|
||||||
|
objectFormRef?.current?.handleUpdate?.()
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
delete: () => {
|
||||||
|
objectFormRef?.current?.handleDelete?.()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Flex
|
||||||
|
gap='large'
|
||||||
|
vertical='true'
|
||||||
|
style={{ maxHeight: '100%', minHeight: 0 }}
|
||||||
|
>
|
||||||
|
<Flex justify={'space-between'}>
|
||||||
|
<Space size='middle'>
|
||||||
|
<Space size='small'>
|
||||||
|
<ObjectActions
|
||||||
|
type='marketplace'
|
||||||
|
id={marketplaceId}
|
||||||
|
disabled={objectFormState.loading}
|
||||||
|
objectData={objectFormState.objectData}
|
||||||
|
/>
|
||||||
|
<ViewButton
|
||||||
|
disabled={objectFormState.loading}
|
||||||
|
items={[
|
||||||
|
{ key: 'info', label: 'Marketplace Information' },
|
||||||
|
{ key: 'notes', label: 'Notes' },
|
||||||
|
{ key: 'auditLogs', label: 'Audit Logs' }
|
||||||
|
]}
|
||||||
|
visibleState={collapseState}
|
||||||
|
updateVisibleState={updateCollapseState}
|
||||||
|
/>
|
||||||
|
<UserNotifierToggle
|
||||||
|
type='marketplace'
|
||||||
|
objectData={objectFormState.objectData}
|
||||||
|
disabled={objectFormState.loading}
|
||||||
|
/>
|
||||||
|
<DocumentPrintButton
|
||||||
|
type='marketplace'
|
||||||
|
objectData={objectFormState.objectData}
|
||||||
|
disabled={objectFormState.loading}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
<LockIndicator lock={objectFormState.lock} />
|
||||||
|
</Space>
|
||||||
|
<Space>
|
||||||
|
<EditButtons
|
||||||
|
isEditing={objectFormState.isEditing}
|
||||||
|
handleUpdate={() => {
|
||||||
|
actionHandlerRef.current.callAction('finishEdit')
|
||||||
|
}}
|
||||||
|
cancelEditing={() => {
|
||||||
|
actionHandlerRef.current.callAction('cancelEdit')
|
||||||
|
}}
|
||||||
|
startEditing={() => {
|
||||||
|
actionHandlerRef.current.callAction('edit')
|
||||||
|
}}
|
||||||
|
editLoading={objectFormState.editLoading}
|
||||||
|
formValid={objectFormState.formValid}
|
||||||
|
disabled={objectFormState.lock?.locked || objectFormState.loading}
|
||||||
|
loading={objectFormState.editLoading}
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
</Flex>
|
||||||
|
<ScrollBox>
|
||||||
|
<Flex vertical gap={'large'}>
|
||||||
|
<ActionHandler
|
||||||
|
actions={actions}
|
||||||
|
loading={objectFormState.loading}
|
||||||
|
ref={actionHandlerRef}
|
||||||
|
>
|
||||||
|
<InfoCollapse
|
||||||
|
title='Marketplace Information'
|
||||||
|
icon={<InfoCircleIcon />}
|
||||||
|
active={collapseState.info}
|
||||||
|
onToggle={(expanded) => updateCollapseState('info', expanded)}
|
||||||
|
collapseKey='info'
|
||||||
|
>
|
||||||
|
<ObjectForm
|
||||||
|
id={marketplaceId}
|
||||||
|
type='marketplace'
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
ref={objectFormRef}
|
||||||
|
onStateChange={(state) => {
|
||||||
|
setEditFormState((prev) => ({ ...prev, ...state }))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ loading, isEditing, objectData }) => (
|
||||||
|
<ObjectInfo
|
||||||
|
loading={loading}
|
||||||
|
isEditing={isEditing}
|
||||||
|
type='marketplace'
|
||||||
|
objectData={objectData}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ObjectForm>
|
||||||
|
</InfoCollapse>
|
||||||
|
</ActionHandler>
|
||||||
|
<InfoCollapse
|
||||||
|
title='Notes'
|
||||||
|
icon={<NoteIcon />}
|
||||||
|
active={collapseState.notes}
|
||||||
|
onToggle={(expanded) => updateCollapseState('notes', expanded)}
|
||||||
|
collapseKey='notes'
|
||||||
|
>
|
||||||
|
<Card>
|
||||||
|
<NotesPanel _id={marketplaceId} type='marketplace' />
|
||||||
|
</Card>
|
||||||
|
</InfoCollapse>
|
||||||
|
<InfoCollapse
|
||||||
|
title='Audit Logs'
|
||||||
|
icon={<AuditLogIcon />}
|
||||||
|
active={collapseState.auditLogs}
|
||||||
|
onToggle={(expanded) =>
|
||||||
|
updateCollapseState('auditLogs', expanded)
|
||||||
|
}
|
||||||
|
collapseKey='auditLogs'
|
||||||
|
>
|
||||||
|
{objectFormState.loading ? (
|
||||||
|
<InfoCollapsePlaceholder />
|
||||||
|
) : (
|
||||||
|
<ObjectTable
|
||||||
|
type='auditLog'
|
||||||
|
masterFilter={{ 'parent._id': marketplaceId }}
|
||||||
|
visibleColumns={{ _id: false, 'parent._id': false }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</InfoCollapse>
|
||||||
|
</Flex>
|
||||||
|
</ScrollBox>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MarketplaceInfo
|
||||||
103
src/components/Dashboard/Sales/Marketplaces/NewMarketplace.jsx
Normal file
103
src/components/Dashboard/Sales/Marketplaces/NewMarketplace.jsx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ObjectInfo from '../../common/ObjectInfo'
|
||||||
|
import NewObjectForm from '../../common/NewObjectForm'
|
||||||
|
import WizardView from '../../common/WizardView'
|
||||||
|
|
||||||
|
const NewMarketplace = ({ onOk, defaultValues }) => {
|
||||||
|
return (
|
||||||
|
<NewObjectForm
|
||||||
|
type={'marketplace'}
|
||||||
|
defaultValues={{ active: true, ...defaultValues }}
|
||||||
|
>
|
||||||
|
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
title: 'Required',
|
||||||
|
key: 'required',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='marketplace'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
isEditing={true}
|
||||||
|
required={true}
|
||||||
|
objectData={objectData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'API Configuration',
|
||||||
|
key: 'config',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='marketplace'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
isEditing={true}
|
||||||
|
required={false}
|
||||||
|
objectData={objectData}
|
||||||
|
visibleProperties={{
|
||||||
|
_id: false,
|
||||||
|
_reference: false,
|
||||||
|
createdAt: false,
|
||||||
|
updatedAt: false,
|
||||||
|
name: false,
|
||||||
|
provider: false,
|
||||||
|
active: false
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Summary',
|
||||||
|
key: 'summary',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='marketplace'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
visibleProperties={{
|
||||||
|
_id: false,
|
||||||
|
createdAt: false,
|
||||||
|
updatedAt: false,
|
||||||
|
'config.appId': false,
|
||||||
|
'config.certId': false,
|
||||||
|
'config.devId': false,
|
||||||
|
'config.userToken': false,
|
||||||
|
'config.accessToken': false,
|
||||||
|
'config.refreshToken': false,
|
||||||
|
'config.appKey': false,
|
||||||
|
'config.appSecret': false
|
||||||
|
}}
|
||||||
|
isEditing={false}
|
||||||
|
objectData={objectData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<WizardView
|
||||||
|
steps={steps}
|
||||||
|
loading={submitLoading}
|
||||||
|
formValid={formValid}
|
||||||
|
title='New Marketplace'
|
||||||
|
onSubmit={async () => {
|
||||||
|
const result = await handleSubmit()
|
||||||
|
if (result) {
|
||||||
|
onOk()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</NewObjectForm>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
NewMarketplace.propTypes = {
|
||||||
|
onOk: PropTypes.func.isRequired,
|
||||||
|
reset: PropTypes.bool,
|
||||||
|
defaultValues: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewMarketplace
|
||||||
@ -2,8 +2,8 @@ import { useLocation } from 'react-router-dom'
|
|||||||
import DashboardSidebar from '../common/DashboardSidebar'
|
import DashboardSidebar from '../common/DashboardSidebar'
|
||||||
import ClientIcon from '../../Icons/ClientIcon'
|
import ClientIcon from '../../Icons/ClientIcon'
|
||||||
import SalesIcon from '../../Icons/SalesIcon'
|
import SalesIcon from '../../Icons/SalesIcon'
|
||||||
|
|
||||||
import SalesOrderIcon from '../../Icons/SalesOrderIcon'
|
import SalesOrderIcon from '../../Icons/SalesOrderIcon'
|
||||||
|
import MarketplaceIcon from '../../Icons/MarketplaceIcon'
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
@ -24,13 +24,20 @@ const items = [
|
|||||||
label: 'Sales Orders',
|
label: 'Sales Orders',
|
||||||
icon: <SalesOrderIcon />,
|
icon: <SalesOrderIcon />,
|
||||||
path: '/dashboard/sales/salesorders'
|
path: '/dashboard/sales/salesorders'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'marketplaces',
|
||||||
|
label: 'Marketplaces',
|
||||||
|
icon: <MarketplaceIcon />,
|
||||||
|
path: '/dashboard/sales/marketplaces'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const routeKeyMap = {
|
const routeKeyMap = {
|
||||||
'/dashboard/sales/overview': 'overview',
|
'/dashboard/sales/overview': 'overview',
|
||||||
'/dashboard/sales/clients': 'clients',
|
'/dashboard/sales/clients': 'clients',
|
||||||
'/dashboard/sales/salesorders': 'salesorders'
|
'/dashboard/sales/salesorders': 'salesorders',
|
||||||
|
'/dashboard/sales/marketplaces': 'marketplaces'
|
||||||
}
|
}
|
||||||
|
|
||||||
const SalesSidebar = (props) => {
|
const SalesSidebar = (props) => {
|
||||||
|
|||||||
@ -63,6 +63,11 @@ const ObjectInfo = ({
|
|||||||
|
|
||||||
items = items.filter((item) => {
|
items = items.filter((item) => {
|
||||||
const propertyName = item.name
|
const propertyName = item.name
|
||||||
|
// Support property.visible as a function (objectData) => boolean
|
||||||
|
if (typeof item.visible === 'function') {
|
||||||
|
const visible = item.visible(objectData || combinedObjectData || {})
|
||||||
|
if (!visible) return false
|
||||||
|
}
|
||||||
if (isWhitelistMode) {
|
if (isWhitelistMode) {
|
||||||
// Whitelist mode: only show properties that are explicitly set to true
|
// Whitelist mode: only show properties that are explicitly set to true
|
||||||
return visibleProperties[propertyName] === true
|
return visibleProperties[propertyName] === true
|
||||||
|
|||||||
6
src/components/Icons/MarketplaceIcon.jsx
Normal file
6
src/components/Icons/MarketplaceIcon.jsx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import Icon from '@ant-design/icons'
|
||||||
|
import CustomIconSvg from '../../../assets/icons/marketplaceicon.svg?react'
|
||||||
|
|
||||||
|
const MarketplaceIcon = (props) => <Icon component={CustomIconSvg} {...props} />
|
||||||
|
|
||||||
|
export default MarketplaceIcon
|
||||||
@ -39,6 +39,7 @@ import { Invoice } from './models/Invoice.js'
|
|||||||
import { Payment } from './models/Payment.js'
|
import { Payment } from './models/Payment.js'
|
||||||
import { Client } from './models/Client.js'
|
import { Client } from './models/Client.js'
|
||||||
import { SalesOrder } from './models/SalesOrder.js'
|
import { SalesOrder } from './models/SalesOrder.js'
|
||||||
|
import { Marketplace } from './models/Marketplace.js'
|
||||||
import QuestionCircleIcon from '../components/Icons/QuestionCircleIcon'
|
import QuestionCircleIcon from '../components/Icons/QuestionCircleIcon'
|
||||||
|
|
||||||
export const objectModels = [
|
export const objectModels = [
|
||||||
@ -82,7 +83,8 @@ export const objectModels = [
|
|||||||
Invoice,
|
Invoice,
|
||||||
Payment,
|
Payment,
|
||||||
Client,
|
Client,
|
||||||
SalesOrder
|
SalesOrder,
|
||||||
|
Marketplace
|
||||||
]
|
]
|
||||||
|
|
||||||
// Re-export individual models for direct access
|
// Re-export individual models for direct access
|
||||||
@ -127,7 +129,8 @@ export {
|
|||||||
Invoice,
|
Invoice,
|
||||||
Payment,
|
Payment,
|
||||||
Client,
|
Client,
|
||||||
SalesOrder
|
SalesOrder,
|
||||||
|
Marketplace
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getModelByName(name, ignoreCase = false) {
|
export function getModelByName(name, ignoreCase = false) {
|
||||||
|
|||||||
@ -84,6 +84,7 @@ export const Client = {
|
|||||||
'email',
|
'email',
|
||||||
'phone',
|
'phone',
|
||||||
'active',
|
'active',
|
||||||
|
'marketplace',
|
||||||
'createdAt',
|
'createdAt',
|
||||||
'updatedAt'
|
'updatedAt'
|
||||||
],
|
],
|
||||||
@ -186,6 +187,16 @@ export const Client = {
|
|||||||
readOnly: false,
|
readOnly: false,
|
||||||
required: false,
|
required: false,
|
||||||
columnWidth: 250
|
columnWidth: 250
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'marketplace',
|
||||||
|
label: 'Marketplace',
|
||||||
|
type: 'object',
|
||||||
|
objectType: 'marketplace',
|
||||||
|
showHyperlink: true,
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
244
src/database/models/Marketplace.js
Normal file
244
src/database/models/Marketplace.js
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
import MarketplaceIcon from '../../components/Icons/MarketplaceIcon'
|
||||||
|
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
|
||||||
|
import EditIcon from '../../components/Icons/EditIcon'
|
||||||
|
import CheckIcon from '../../components/Icons/CheckIcon'
|
||||||
|
import XMarkIcon from '../../components/Icons/XMarkIcon'
|
||||||
|
import ReloadIcon from '../../components/Icons/ReloadIcon'
|
||||||
|
import BinIcon from '../../components/Icons/BinIcon'
|
||||||
|
|
||||||
|
export const Marketplace = {
|
||||||
|
name: 'marketplace',
|
||||||
|
label: 'Marketplace',
|
||||||
|
prefix: 'MKT',
|
||||||
|
icon: MarketplaceIcon,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
name: 'info',
|
||||||
|
label: 'Info',
|
||||||
|
default: true,
|
||||||
|
row: true,
|
||||||
|
icon: InfoCircleIcon,
|
||||||
|
url: (_id) => `/dashboard/sales/marketplaces/info?marketplaceId=${_id}`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'reload',
|
||||||
|
label: 'Reload',
|
||||||
|
icon: ReloadIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=reload`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
label: 'Edit',
|
||||||
|
row: true,
|
||||||
|
icon: EditIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=edit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return !(objectData?._isEditing && objectData?._isEditing == true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'finishEdit',
|
||||||
|
label: 'Save Edits',
|
||||||
|
icon: CheckIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=finishEdit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return objectData?._isEditing && objectData?._isEditing == true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cancelEdit',
|
||||||
|
label: 'Cancel Edits',
|
||||||
|
icon: XMarkIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=cancelEdit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return objectData?._isEditing && objectData?._isEditing == true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'divider' },
|
||||||
|
{
|
||||||
|
name: 'delete',
|
||||||
|
label: 'Delete',
|
||||||
|
icon: BinIcon,
|
||||||
|
danger: true,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/sales/marketplaces/info?marketplaceId=${_id}&action=delete`
|
||||||
|
}
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
'_reference',
|
||||||
|
'name',
|
||||||
|
'provider',
|
||||||
|
'active',
|
||||||
|
'createdAt',
|
||||||
|
'updatedAt'
|
||||||
|
],
|
||||||
|
filters: ['name', '_id', 'provider', 'active', 'createdAt', 'updatedAt'],
|
||||||
|
sorters: ['name', 'provider', 'active', 'createdAt', 'updatedAt', '_id'],
|
||||||
|
group: ['provider'],
|
||||||
|
properties: [
|
||||||
|
{
|
||||||
|
name: '_id',
|
||||||
|
label: 'ID',
|
||||||
|
columnFixed: 'left',
|
||||||
|
type: 'id',
|
||||||
|
objectType: 'marketplace',
|
||||||
|
showCopy: true,
|
||||||
|
columnWidth: 140
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'createdAt',
|
||||||
|
label: 'Created At',
|
||||||
|
type: 'dateTime',
|
||||||
|
readOnly: true,
|
||||||
|
columnWidth: 175
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '_reference',
|
||||||
|
label: 'Reference',
|
||||||
|
type: 'reference',
|
||||||
|
columnFixed: 'left',
|
||||||
|
objectType: 'marketplace',
|
||||||
|
showCopy: true,
|
||||||
|
readOnly: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'updatedAt',
|
||||||
|
label: 'Updated At',
|
||||||
|
type: 'dateTime',
|
||||||
|
readOnly: true,
|
||||||
|
columnWidth: 175
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'name',
|
||||||
|
label: 'Name',
|
||||||
|
columnFixed: 'left',
|
||||||
|
required: true,
|
||||||
|
type: 'text',
|
||||||
|
columnWidth: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'active',
|
||||||
|
label: 'Active',
|
||||||
|
type: 'bool',
|
||||||
|
readOnly: false,
|
||||||
|
required: true,
|
||||||
|
columnWidth: 125
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'provider',
|
||||||
|
label: 'Provider',
|
||||||
|
type: 'select',
|
||||||
|
required: true,
|
||||||
|
options: [
|
||||||
|
{ value: 'ebay', label: 'eBay' },
|
||||||
|
{ value: 'etsy', label: 'Etsy' },
|
||||||
|
{ value: 'tiktokShop', label: 'TikTok Shop' }
|
||||||
|
],
|
||||||
|
columnWidth: 150
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'config.appId',
|
||||||
|
label: 'App ID',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'ebay'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.certId',
|
||||||
|
label: 'Cert ID',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'ebay'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.devId',
|
||||||
|
label: 'Dev ID',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'ebay'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.userToken',
|
||||||
|
label: 'User Token',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'ebay'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.siteId',
|
||||||
|
label: 'Site ID',
|
||||||
|
type: 'text',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 120,
|
||||||
|
visible: (objectData) => objectData?.provider === 'ebay'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.accessToken',
|
||||||
|
label: 'Access Token',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'etsy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.refreshToken',
|
||||||
|
label: 'Refresh Token',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'etsy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.shopId',
|
||||||
|
label: 'Shop ID',
|
||||||
|
type: 'text',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'etsy'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.appKey',
|
||||||
|
label: 'App Key',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'tiktokShop'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.appSecret',
|
||||||
|
label: 'App Secret',
|
||||||
|
type: 'secret',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'tiktokShop'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'config.shopCipher',
|
||||||
|
label: 'Shop Cipher',
|
||||||
|
type: 'text',
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200,
|
||||||
|
visible: (objectData) => objectData?.provider === 'tiktokShop'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -170,13 +170,14 @@ export const SalesOrder = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
group: ['client'],
|
group: ['client', 'marketplace'],
|
||||||
filters: ['client'],
|
filters: ['client', 'marketplace'],
|
||||||
sorters: ['createdAt', 'state', 'updatedAt'],
|
sorters: ['createdAt', 'state', 'updatedAt'],
|
||||||
columns: [
|
columns: [
|
||||||
'_reference',
|
'_reference',
|
||||||
'state',
|
'state',
|
||||||
'client',
|
'client',
|
||||||
|
'marketplace',
|
||||||
'totalAmount',
|
'totalAmount',
|
||||||
'totalAmountWithTax',
|
'totalAmountWithTax',
|
||||||
'totalTaxAmount',
|
'totalTaxAmount',
|
||||||
@ -245,6 +246,16 @@ export const SalesOrder = {
|
|||||||
showHyperlink: true,
|
showHyperlink: true,
|
||||||
columnWidth: 200
|
columnWidth: 200
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'marketplace',
|
||||||
|
label: 'Marketplace',
|
||||||
|
type: 'object',
|
||||||
|
objectType: 'marketplace',
|
||||||
|
showHyperlink: true,
|
||||||
|
readOnly: false,
|
||||||
|
required: false,
|
||||||
|
columnWidth: 200
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'confirmedAt',
|
name: 'confirmedAt',
|
||||||
label: 'Confirmed At',
|
label: 'Confirmed At',
|
||||||
|
|||||||
@ -16,6 +16,12 @@ const SalesOrderInfo = lazy(
|
|||||||
const SalesOverview = lazy(
|
const SalesOverview = lazy(
|
||||||
() => import('../components/Dashboard/Sales/SalesOverview.jsx')
|
() => import('../components/Dashboard/Sales/SalesOverview.jsx')
|
||||||
)
|
)
|
||||||
|
const Marketplaces = lazy(
|
||||||
|
() => import('../components/Dashboard/Sales/Marketplaces.jsx')
|
||||||
|
)
|
||||||
|
const MarketplaceInfo = lazy(
|
||||||
|
() => import('../components/Dashboard/Sales/Marketplaces/MarketplaceInfo.jsx')
|
||||||
|
)
|
||||||
|
|
||||||
const SalesRoutes = [
|
const SalesRoutes = [
|
||||||
<Route
|
<Route
|
||||||
@ -34,6 +40,12 @@ const SalesRoutes = [
|
|||||||
key='salesorders-info'
|
key='salesorders-info'
|
||||||
path='sales/salesorders/info'
|
path='sales/salesorders/info'
|
||||||
element={<SalesOrderInfo />}
|
element={<SalesOrderInfo />}
|
||||||
|
/>,
|
||||||
|
<Route key='marketplaces' path='sales/marketplaces' element={<Marketplaces />} />,
|
||||||
|
<Route
|
||||||
|
key='marketplaces-info'
|
||||||
|
path='sales/marketplaces/info'
|
||||||
|
element={<MarketplaceInfo />}
|
||||||
/>
|
/>
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user