Refactor Dashboard Components to Integrate ListView Functionality
- Updated multiple dashboard components (Invoices, PaymentPolicies, Payments, TaxRecords, FilamentStocks, OrderItems, PartStocks, ProductStocks, PurchaseOrders, Shipments, StockAudits, StockEvents, StockLocations, StockTransfers, AppPasswords, AuditLogs) to incorporate ListViewTabs and ListViewEditButtons for enhanced user interaction. - Introduced ObjectListViewProvider to manage view state and filter/sort changes across components, improving maintainability and user experience. - Added state management for active views and filter/sort handling to streamline component functionality.
This commit is contained in:
parent
088ef79b11
commit
96b809b9d8
@ -22,7 +22,7 @@
|
||||
.ant-form-item-control-input,
|
||||
.ant-input,
|
||||
.ant-input-number .ant-input-number-input,
|
||||
.ant-segmented-item-label,
|
||||
.segmented-nav-item-label,
|
||||
.ant-badge-status-text,
|
||||
.ant-tree-title,
|
||||
.ant-select,
|
||||
@ -665,6 +665,11 @@ body {
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
.scrollbox-horizontal > [data-simplebar],
|
||||
.scrollbox-horizontal .simplebar-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.simplebar-scrollbar:before {
|
||||
background: #78787854 !important;
|
||||
}
|
||||
@ -2544,3 +2549,247 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.list-view-tabs {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs .ant-input-sm {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-spin {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-spin > .ant-spin-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-segmented-wrap {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-segmented-wrap .simplebar-track.simplebar-vertical {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.list-view-tabs-segmented-inner {
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.segmented-nav {
|
||||
display: inline-flex;
|
||||
width: max-content;
|
||||
flex-shrink: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.segmented-nav-group {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.segmented-nav-thumb {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
border-radius: 12px;
|
||||
background: var(--color-button-background);
|
||||
pointer-events: none;
|
||||
will-change: transform, width;
|
||||
transition:
|
||||
transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),
|
||||
width 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),
|
||||
height 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
.segmented-nav-item {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid var(--color-list-view-tabs-border);
|
||||
border-radius: 12px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
transition:
|
||||
background 0.2s ease,
|
||||
border 0.2s ease;
|
||||
}
|
||||
|
||||
.segmented-nav-item-label {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 30px;
|
||||
line-height: 30px;
|
||||
padding-inline: 12px;
|
||||
}
|
||||
|
||||
.segmented-nav-item-icon {
|
||||
padding-inline: 8px;
|
||||
}
|
||||
|
||||
.segmented-nav-item-icon-contents {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.segmented-nav-item:focus-visible {
|
||||
outline: 2px solid
|
||||
color-mix(in srgb, var(--color-primary, #1677ff) 45%, transparent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.segmented-nav-item-selected,
|
||||
.segmented-nav-item:not(.segmented-nav-item-disabled):hover {
|
||||
background: var(--color-button-background);
|
||||
border: 1px solid var(--color-button-border);
|
||||
}
|
||||
|
||||
.segmented-nav-item-disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.segmented-nav-disabled .segmented-nav-item {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.list-view-tabs-label {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.list-view-tabs-label-editing .ant-input {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.list-view-tabs-label-editing {
|
||||
margin: 0px -8px;
|
||||
max-width: none;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-label-editing .list-view-tabs-name-input-wrap {
|
||||
flex: 0 0 auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.list-view-tabs-name-input-wrap {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-name-input-sizer {
|
||||
visibility: hidden;
|
||||
white-space: pre;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
font-family: inherit;
|
||||
min-height: 1em;
|
||||
}
|
||||
|
||||
.list-view-tabs-label-editing .list-view-tabs-name-input {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding-inline: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-color-dot {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.list-view-tabs-editing
|
||||
.segmented-nav-item
|
||||
.ant-color-picker-trigger.ant-color-picker-sm {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.list-view-tabs-privacy-button,
|
||||
.list-view-tabs-options-button {
|
||||
padding-inline: 4px;
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
.list-view-tabs-options-dropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.list-view-tabs-options-dropdown-privacy {
|
||||
margin: 3px 12px 8px;
|
||||
}
|
||||
|
||||
.segmented-nav-drag-handle {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.segmented-nav-item-dragging {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.segmented-nav-item-drop-before::before,
|
||||
.segmented-nav-item-drop-after::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
width: 2px;
|
||||
border-radius: 1px;
|
||||
background: var(--color-primary, #1677ff);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.segmented-nav-item-drop-before::before {
|
||||
left: -5px;
|
||||
}
|
||||
|
||||
.segmented-nav-item-drop-after::after {
|
||||
right: -5px;
|
||||
}
|
||||
|
||||
.segmented-nav-reordering
|
||||
.segmented-nav-item:not(.segmented-nav-item-dragging) {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.list-view-tabs-add-button {
|
||||
padding-inline: 4px;
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
.state-tag-loading svg path {
|
||||
stroke: currentColor;
|
||||
stroke-width: 12px;
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Invoices = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('invoices')
|
||||
|
||||
@ -30,8 +38,13 @@ const Invoices = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='invoice'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='invoice'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const Invoices = () => {
|
||||
/>
|
||||
<ExportListButton objectType='invoice' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const Invoices = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const Invoices = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const PaymentPolicies = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('paymentPolicy')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('paymentPolicy')
|
||||
@ -24,8 +32,13 @@ const PaymentPolicies = () => {
|
||||
|
||||
return (
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='paymentPolicy'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='paymentPolicy'
|
||||
pageName='list'
|
||||
@ -39,7 +52,8 @@ const PaymentPolicies = () => {
|
||||
/>
|
||||
<ExportListButton objectType='paymentPolicy' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -51,10 +65,11 @@ const PaymentPolicies = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -71,6 +86,8 @@ const PaymentPolicies = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Payments = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('payments')
|
||||
|
||||
@ -30,8 +38,13 @@ const Payments = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='payment'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='payment'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const Payments = () => {
|
||||
/>
|
||||
<ExportListButton objectType='payment' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const Payments = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const Payments = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const TaxRecords = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('taxRecord')
|
||||
|
||||
@ -30,8 +38,13 @@ const TaxRecords = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='taxRecord'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='taxRecord'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const TaxRecords = () => {
|
||||
/>
|
||||
<ExportListButton objectType='taxRecord' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const TaxRecords = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const TaxRecords = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/filamentStocks.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -15,9 +15,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const FilamentStocks = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('filamentStocks')
|
||||
@ -35,8 +43,13 @@ const FilamentStocks = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='filamentStock'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='filamentStock'
|
||||
pageName='list'
|
||||
@ -50,7 +63,8 @@ const FilamentStocks = () => {
|
||||
/>
|
||||
<ExportListButton objectType='filamentStock' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -62,10 +76,11 @@ const FilamentStocks = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -83,6 +98,8 @@ const FilamentStocks = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const OrderItems = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('orderItems')
|
||||
|
||||
@ -30,8 +38,13 @@ const OrderItems = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='orderItem'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='orderItem'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const OrderItems = () => {
|
||||
/>
|
||||
<ExportListButton objectType='orderItem' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const OrderItems = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const OrderItems = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/partStocks.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -15,9 +15,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const PartStocks = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('partStocks')
|
||||
@ -35,8 +43,13 @@ const PartStocks = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='partStock'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='partStock'
|
||||
pageName='list'
|
||||
@ -50,7 +63,8 @@ const PartStocks = () => {
|
||||
/>
|
||||
<ExportListButton objectType='partStock' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -62,10 +76,11 @@ const PartStocks = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -83,6 +98,8 @@ const PartStocks = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// src/components/Dashboard/Inventory/ProductStocks.jsx
|
||||
// ProductStocks - tracks assembled products consisting of part stocks
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -16,9 +16,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const ProductStocks = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('productStocks')
|
||||
@ -36,8 +44,13 @@ const ProductStocks = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='productStock'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='productStock'
|
||||
pageName='list'
|
||||
@ -51,7 +64,8 @@ const ProductStocks = () => {
|
||||
/>
|
||||
<ExportListButton objectType='productStock' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -63,10 +77,11 @@ const ProductStocks = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -84,6 +99,8 @@ const ProductStocks = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const PurchaseOrders = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('purchaseOrders')
|
||||
|
||||
@ -30,8 +38,13 @@ const PurchaseOrders = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='purchaseOrder'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='purchaseOrder'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const PurchaseOrders = () => {
|
||||
/>
|
||||
<ExportListButton objectType='purchaseOrder' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const PurchaseOrders = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const PurchaseOrders = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Shipments = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('shipments')
|
||||
|
||||
@ -30,8 +38,13 @@ const Shipments = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='shipment'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='shipment'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const Shipments = () => {
|
||||
/>
|
||||
<ExportListButton objectType='shipment' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const Shipments = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const Shipments = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/stockAudits.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -15,9 +15,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const StockAudits = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('stockAudits')
|
||||
@ -35,8 +43,13 @@ const StockAudits = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='stockAudit'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='stockAudit'
|
||||
pageName='list'
|
||||
@ -50,7 +63,8 @@ const StockAudits = () => {
|
||||
/>
|
||||
<ExportListButton objectType='stockAudit' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -62,10 +76,11 @@ const StockAudits = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -83,6 +98,8 @@ const StockAudits = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const StockEvents = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('stockEvents')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
@ -29,8 +37,13 @@ const StockEvents = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='stockEvent'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='stockEvent'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const StockEvents = () => {
|
||||
/>
|
||||
<ExportListButton objectType='stockEvent' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const StockEvents = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -77,6 +92,8 @@ const StockEvents = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -13,9 +13,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const StockLocations = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('stockLocations')
|
||||
@ -33,8 +41,13 @@ const StockLocations = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='stockLocation'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='stockLocation'
|
||||
pageName='list'
|
||||
@ -48,7 +61,8 @@ const StockLocations = () => {
|
||||
/>
|
||||
<ExportListButton objectType='stockLocation' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -60,10 +74,11 @@ const StockLocations = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -81,6 +96,8 @@ const StockLocations = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -13,9 +13,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const StockTransfers = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('stockTransfers')
|
||||
@ -33,8 +41,13 @@ const StockTransfers = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='stockTransfer'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='stockTransfer'
|
||||
pageName='list'
|
||||
@ -48,7 +61,8 @@ const StockTransfers = () => {
|
||||
/>
|
||||
<ExportListButton objectType='stockTransfer' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -60,10 +74,11 @@ const StockTransfers = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -81,6 +96,8 @@ const StockTransfers = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
@ -11,9 +11,17 @@ import useViewMode from '../hooks/useViewMode'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const AppPasswords = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('appPassword')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
@ -29,8 +37,13 @@ const AppPasswords = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='appPassword'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='appPassword'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const AppPasswords = () => {
|
||||
/>
|
||||
<ExportListButton objectType='appPassword' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const AppPasswords = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -77,6 +92,8 @@ const AppPasswords = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
@ -10,9 +10,17 @@ import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||
import SortSidebarButton from '../common/SortSidebarButton'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const AuditLogs = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [columnVisibility, updateColumnVisibility] =
|
||||
useColumnVisibility('auditLog')
|
||||
@ -27,8 +35,13 @@ const AuditLogs = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='auditLog'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='auditLog'
|
||||
pageName='list'
|
||||
@ -42,7 +55,8 @@ const AuditLogs = () => {
|
||||
/>
|
||||
<ExportListButton objectType='auditLog' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -51,8 +65,10 @@ const AuditLogs = () => {
|
||||
active={showFilterSidebar}
|
||||
onClick={() => setShowFilterSidebar(!showFilterSidebar)}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -69,6 +85,8 @@ const AuditLogs = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const CourierServices = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('courierService')
|
||||
|
||||
@ -30,8 +38,13 @@ const CourierServices = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='courierService'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='courierService'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const CourierServices = () => {
|
||||
/>
|
||||
<ExportListButton objectType='courierService' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const CourierServices = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const CourierServices = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Couriers = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('courier')
|
||||
|
||||
@ -29,8 +37,13 @@ const Couriers = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='courier'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='courier'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const Couriers = () => {
|
||||
/>
|
||||
<ExportListButton objectType='courier' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const Couriers = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const Couriers = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const DocumentJobs = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentJob')
|
||||
|
||||
@ -30,8 +38,13 @@ const DocumentJobs = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='documentJob'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentJob'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const DocumentJobs = () => {
|
||||
/>
|
||||
<ExportListButton objectType='documentJob' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const DocumentJobs = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const DocumentJobs = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const DocumentPrinters = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentPrinter')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
@ -29,8 +37,13 @@ const DocumentPrinters = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='documentPrinter'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentPrinter'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const DocumentPrinters = () => {
|
||||
/>
|
||||
<ExportListButton objectType='documentPrinter' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const DocumentPrinters = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const DocumentPrinters = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const DocumentSizes = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentSize')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('documentSize')
|
||||
@ -28,8 +36,13 @@ const DocumentSizes = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='documentSize'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentSize'
|
||||
pageName='list'
|
||||
@ -43,7 +56,8 @@ const DocumentSizes = () => {
|
||||
/>
|
||||
<ExportListButton objectType='documentSize' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -55,10 +69,11 @@ const DocumentSizes = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -75,6 +90,8 @@ const DocumentSizes = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const DocumentTemplates = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('documentTemplate')
|
||||
|
||||
@ -30,8 +38,13 @@ const DocumentTemplates = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='documentTemplate'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='documentTemplate'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const DocumentTemplates = () => {
|
||||
/>
|
||||
<ExportListButton objectType='documentTemplate' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const DocumentTemplates = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const DocumentTemplates = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -13,9 +13,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const FilamentSkus = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('filamentSkus')
|
||||
@ -33,8 +41,13 @@ const FilamentSkus = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='filamentSku'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='filamentSku'
|
||||
pageName='list'
|
||||
@ -48,7 +61,8 @@ const FilamentSkus = () => {
|
||||
/>
|
||||
<ExportListButton objectType='filamentSku' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -60,10 +74,11 @@ const FilamentSkus = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -81,6 +96,8 @@ const FilamentSkus = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/filaments.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
|
||||
@ -13,11 +13,19 @@ import ObjectTableViewButton from '../common/ObjectTableViewButton'
|
||||
import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||
import SortSidebarButton from '../common/SortSidebarButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
|
||||
const Filaments = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
// View mode state (cards/list), persisted in sessionStorage via custom hook
|
||||
const [viewMode, setViewMode] = useViewMode('filament')
|
||||
@ -35,8 +43,13 @@ const Filaments = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='filament'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='filament'
|
||||
pageName='list'
|
||||
@ -50,7 +63,8 @@ const Filaments = () => {
|
||||
/>
|
||||
<ExportListButton objectType='filament' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -62,10 +76,11 @@ const Filaments = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -83,6 +98,8 @@ const Filaments = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Files = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('file')
|
||||
|
||||
@ -29,8 +37,13 @@ const Files = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='file'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='file'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const Files = () => {
|
||||
/>
|
||||
<ExportListButton objectType='file' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const Files = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const Files = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
// src/hosts.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
import useViewMode from '../hooks/useViewMode'
|
||||
@ -18,6 +21,11 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
|
||||
const Hosts = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
// View mode state (cards/list), persisted in sessionStorage via custom hook
|
||||
const [viewMode, setViewMode] = useViewMode('host')
|
||||
@ -34,8 +42,13 @@ const Hosts = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='host'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='host'
|
||||
pageName='list'
|
||||
@ -49,7 +62,8 @@ const Hosts = () => {
|
||||
/>
|
||||
<ExportListButton objectType='host' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -61,10 +75,11 @@ const Hosts = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -82,6 +97,8 @@ const Hosts = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
|
||||
@ -13,9 +13,17 @@ import useViewMode from '../hooks/useViewMode'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Materials = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('material')
|
||||
|
||||
@ -32,8 +40,13 @@ const Materials = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='material'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='material'
|
||||
pageName='list'
|
||||
@ -47,7 +60,8 @@ const Materials = () => {
|
||||
/>
|
||||
<ExportListButton objectType='material' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -59,10 +73,11 @@ const Materials = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -80,6 +95,8 @@ const Materials = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const NoteTypes = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('noteType')
|
||||
|
||||
@ -30,8 +38,13 @@ const NoteTypes = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='noteType'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='noteType'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const NoteTypes = () => {
|
||||
/>
|
||||
<ExportListButton objectType='noteType' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const NoteTypes = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const NoteTypes = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -13,9 +13,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const PartSkus = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('partSkus')
|
||||
@ -32,8 +40,13 @@ const PartSkus = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='partSku'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='partSku'
|
||||
pageName='list'
|
||||
@ -47,7 +60,8 @@ const PartSkus = () => {
|
||||
/>
|
||||
<ExportListButton objectType='partSku' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -59,10 +73,11 @@ const PartSkus = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -80,6 +95,8 @@ const PartSkus = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/gcodefiles.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
@ -18,9 +18,17 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Parts = (filter) => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('part')
|
||||
const [columnVisibility, setColumnVisibility] = useColumnVisibility('part')
|
||||
|
||||
@ -34,8 +42,13 @@ const Parts = (filter) => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='part'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='part'
|
||||
pageName='list'
|
||||
@ -49,7 +62,8 @@ const Parts = (filter) => {
|
||||
/>
|
||||
<ExportListButton objectType='part' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -61,10 +75,11 @@ const Parts = (filter) => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -82,6 +97,8 @@ const Parts = (filter) => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const PermissionSettingsList = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('permissionSetting')
|
||||
|
||||
@ -30,8 +38,13 @@ const PermissionSettingsList = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='permissionSetting'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='permissionSetting'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const PermissionSettingsList = () => {
|
||||
/>
|
||||
<ExportListButton objectType='permissionSetting' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const PermissionSettingsList = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const PermissionSettingsList = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
|
||||
@ -13,9 +13,17 @@ import useViewMode from '../hooks/useViewMode'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const ProductCategories = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('productCategory')
|
||||
|
||||
@ -32,8 +40,13 @@ const ProductCategories = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='productCategory'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='productCategory'
|
||||
pageName='list'
|
||||
@ -47,7 +60,8 @@ const ProductCategories = () => {
|
||||
/>
|
||||
<ExportListButton objectType='productCategory' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -59,10 +73,11 @@ const ProductCategories = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -80,6 +95,8 @@ const ProductCategories = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
|
||||
import { Flex, Space } from 'antd'
|
||||
|
||||
@ -13,9 +13,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const ProductSkus = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('productSkus')
|
||||
@ -33,8 +41,13 @@ const ProductSkus = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='productSku'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='productSku'
|
||||
pageName='list'
|
||||
@ -48,7 +61,8 @@ const ProductSkus = () => {
|
||||
/>
|
||||
<ExportListButton objectType='productSku' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -60,10 +74,11 @@ const ProductSkus = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -81,6 +96,8 @@ const ProductSkus = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/gcodefiles.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import {
|
||||
Button,
|
||||
@ -29,10 +29,18 @@ import useViewMode from '../hooks/useViewMode'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Products = () => {
|
||||
const navigate = useNavigate()
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('Products')
|
||||
|
||||
@ -304,8 +312,13 @@ const Products = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='product'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='product'
|
||||
pageName='list'
|
||||
@ -320,7 +333,8 @@ const Products = () => {
|
||||
<Button>View</Button>
|
||||
</Popover>
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -332,10 +346,11 @@ const Products = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
type={'product'}
|
||||
@ -351,6 +366,8 @@ const Products = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const StockAuditLevels = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('stockAuditLevel')
|
||||
|
||||
@ -28,8 +36,13 @@ const StockAuditLevels = () => {
|
||||
|
||||
return (
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='stockAuditLevel'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='stockAuditLevel'
|
||||
pageName='list'
|
||||
@ -43,7 +56,8 @@ const StockAuditLevels = () => {
|
||||
/>
|
||||
<ExportListButton objectType='stockAuditLevel' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -55,10 +69,11 @@ const StockAuditLevels = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -75,6 +90,8 @@ const StockAuditLevels = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const TaxRates = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('taxRate')
|
||||
|
||||
@ -29,8 +37,13 @@ const TaxRates = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='taxRate'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='taxRate'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const TaxRates = () => {
|
||||
/>
|
||||
<ExportListButton objectType='taxRate' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const TaxRates = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const TaxRates = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const UserGroups = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('userGroup')
|
||||
|
||||
@ -29,8 +37,13 @@ const UserGroups = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='userGroup'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='userGroup'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const UserGroups = () => {
|
||||
/>
|
||||
<ExportListButton objectType='userGroup' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const UserGroups = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const UserGroups = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Users = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('user')
|
||||
|
||||
@ -28,8 +36,13 @@ const Users = () => {
|
||||
|
||||
return (
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='user'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='user'
|
||||
pageName='list'
|
||||
@ -43,7 +56,8 @@ const Users = () => {
|
||||
/>
|
||||
<ExportListButton objectType='user' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,8 +70,10 @@ const Users = () => {
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
type={'user'}
|
||||
@ -74,6 +90,8 @@ const Users = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,16 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Vendors = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('vendor')
|
||||
|
||||
@ -25,41 +32,47 @@ const Vendors = () => {
|
||||
const [showSortSidebar, setShowSortSidebar] =
|
||||
useSortSidebarVisibility('Vendors')
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='vendor'
|
||||
pageName='list'
|
||||
onReload={() => tableRef.current?.reload()}
|
||||
/>
|
||||
<ColumnViewButton
|
||||
type='vendor'
|
||||
loading={false}
|
||||
visibleState={columnVisibility}
|
||||
updateVisibleState={setColumnVisibility}
|
||||
/>
|
||||
<ExportListButton objectType='vendor' />
|
||||
</Space>
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
/>
|
||||
<FilterSidebarButton
|
||||
active={showFilterSidebar}
|
||||
onClick={() => setShowFilterSidebar(!showFilterSidebar)}
|
||||
/>
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
</Space>
|
||||
</Flex>
|
||||
<ObjectListViewProvider
|
||||
objectType='vendor'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='vendor'
|
||||
pageName='list'
|
||||
onReload={() => tableRef.current?.reload()}
|
||||
/>
|
||||
<ColumnViewButton
|
||||
type='vendor'
|
||||
loading={false}
|
||||
visibleState={columnVisibility}
|
||||
updateVisibleState={setColumnVisibility}
|
||||
/>
|
||||
<ExportListButton objectType='vendor' />
|
||||
</Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
/>
|
||||
<FilterSidebarButton
|
||||
active={showFilterSidebar}
|
||||
onClick={() => setShowFilterSidebar(!showFilterSidebar)}
|
||||
/>
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +89,8 @@ const Vendors = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||
import SortSidebarButton from '../common/SortSidebarButton'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
@ -14,6 +17,11 @@ import useViewMode from '../hooks/useViewMode'
|
||||
|
||||
const FilamentProfiles = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('FilamentProfiles')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('filamentProfile')
|
||||
@ -27,8 +35,13 @@ const FilamentProfiles = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='filamentProfile'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='filamentProfile'
|
||||
pageName='list'
|
||||
@ -41,7 +54,8 @@ const FilamentProfiles = () => {
|
||||
/>
|
||||
<ExportListButton objectType='filamentProfile' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -53,10 +67,11 @@ const FilamentProfiles = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -74,6 +89,8 @@ const FilamentProfiles = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/gcodefiles.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
@ -14,9 +14,17 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const GCodeFiles = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('gcodeFile')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
@ -32,8 +40,13 @@ const GCodeFiles = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='gcodeFile'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='gcodeFile'
|
||||
pageName='list'
|
||||
@ -47,7 +60,8 @@ const GCodeFiles = () => {
|
||||
/>
|
||||
<ExportListButton objectType='gcodeFile' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -59,10 +73,11 @@ const GCodeFiles = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
type='gcodeFile'
|
||||
@ -79,6 +94,8 @@ const GCodeFiles = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/Jobs.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility.jsx'
|
||||
import ObjectTable from '../common/ObjectTable.jsx'
|
||||
@ -13,9 +13,17 @@ import ColumnViewButton from '../common/ColumnViewButton.jsx'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility.jsx'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton.jsx'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Jobs = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('job')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] = useColumnVisibility('job')
|
||||
@ -30,8 +38,13 @@ const Jobs = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='job'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='job'
|
||||
pageName='list'
|
||||
@ -45,8 +58,8 @@ const Jobs = () => {
|
||||
/>
|
||||
<ExportListButton objectType='job' />
|
||||
</Space>
|
||||
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -58,10 +71,11 @@ const Jobs = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -79,6 +93,8 @@ const Jobs = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||
import SortSidebarButton from '../common/SortSidebarButton'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
@ -13,6 +16,11 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import useViewMode from '../hooks/useViewMode'
|
||||
const PrinterProfiles = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('PrinterProfiles')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('printerProfile')
|
||||
@ -26,8 +34,13 @@ const PrinterProfiles = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='printerProfile'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='printerProfile'
|
||||
pageName='list'
|
||||
@ -40,7 +53,8 @@ const PrinterProfiles = () => {
|
||||
/>
|
||||
<ExportListButton objectType='printerProfile' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -52,10 +66,11 @@ const PrinterProfiles = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -73,6 +88,8 @@ const PrinterProfiles = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
// src/Printers.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Space, Flex } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
import ObjectTableViewButton from '../common/ObjectTableViewButton'
|
||||
import FilterSidebarButton from '../common/FilterSidebarButton'
|
||||
@ -17,6 +20,11 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
|
||||
const Printers = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
// View mode state (cards/list), persisted in sessionStorage via custom hook
|
||||
const [viewMode, setViewMode] = useViewMode('Printers')
|
||||
@ -35,8 +43,13 @@ const Printers = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space>
|
||||
<ObjectListViewProvider
|
||||
objectType='printer'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space>
|
||||
<ObjectActions
|
||||
type='printer'
|
||||
pageName='list'
|
||||
@ -50,7 +63,8 @@ const Printers = () => {
|
||||
/>
|
||||
<ExportListButton objectType='printer' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -62,10 +76,11 @@ const Printers = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -83,6 +98,8 @@ const Printers = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
|
||||
</Flex>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
// src/SubJobs.js
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import useColumnVisibility from '../hooks/useColumnVisibility.jsx'
|
||||
import ObjectTable from '../common/ObjectTable.jsx'
|
||||
@ -13,9 +13,17 @@ import ColumnViewButton from '../common/ColumnViewButton.jsx'
|
||||
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility.jsx'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ExportListButton from '../common/ExportListButton.jsx'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const SubJobs = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('subJob')
|
||||
|
||||
const [columnVisibility, setColumnVisibility] = useColumnVisibility('subJob')
|
||||
@ -30,8 +38,13 @@ const SubJobs = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='subJob'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='subJob'
|
||||
pageName='list'
|
||||
@ -45,8 +58,8 @@ const SubJobs = () => {
|
||||
/>
|
||||
<ExportListButton objectType='subJob' />
|
||||
</Space>
|
||||
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -58,10 +71,11 @@ const SubJobs = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
@ -79,6 +93,8 @@ const SubJobs = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Clients = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('client')
|
||||
|
||||
@ -29,8 +37,13 @@ const Clients = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='client'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='client'
|
||||
pageName='list'
|
||||
@ -44,7 +57,8 @@ const Clients = () => {
|
||||
/>
|
||||
<ExportListButton objectType='client' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -56,10 +70,11 @@ const Clients = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -76,6 +91,8 @@ const Clients = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const FulfillmentPolicies = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('fulfillmentPolicy')
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
useColumnVisibility('fulfillmentPolicy')
|
||||
@ -24,8 +32,13 @@ const FulfillmentPolicies = () => {
|
||||
|
||||
return (
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='fulfillmentPolicy'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='fulfillmentPolicy'
|
||||
pageName='list'
|
||||
@ -39,7 +52,8 @@ const FulfillmentPolicies = () => {
|
||||
/>
|
||||
<ExportListButton objectType='fulfillmentPolicy' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -51,10 +65,11 @@ const FulfillmentPolicies = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -71,6 +86,8 @@ const FulfillmentPolicies = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const ListingVarients = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('listingVarients')
|
||||
|
||||
@ -30,8 +38,13 @@ const ListingVarients = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='listingVarient'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='listingVarient'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const ListingVarients = () => {
|
||||
/>
|
||||
<ExportListButton objectType='listingVarient' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const ListingVarients = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const ListingVarients = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Listings = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('listings')
|
||||
|
||||
@ -30,8 +38,13 @@ const Listings = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='listing'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='listing'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const Listings = () => {
|
||||
/>
|
||||
<ExportListButton objectType='listing' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const Listings = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const Listings = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const Marketplaces = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('marketplaces')
|
||||
|
||||
@ -30,8 +38,13 @@ const Marketplaces = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='marketplace'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='marketplace'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const Marketplaces = () => {
|
||||
/>
|
||||
<ExportListButton objectType='marketplace' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const Marketplaces = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const Marketplaces = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const ReturnPolicies = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('returnPolicy')
|
||||
const [columnVisibility, setColumnVisibility] = useColumnVisibility('returnPolicy')
|
||||
const [showFilterSidebar, setShowFilterSidebar] =
|
||||
@ -23,8 +31,13 @@ const ReturnPolicies = () => {
|
||||
|
||||
return (
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='returnPolicy'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='returnPolicy'
|
||||
pageName='list'
|
||||
@ -38,7 +51,8 @@ const ReturnPolicies = () => {
|
||||
/>
|
||||
<ExportListButton objectType='returnPolicy' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -50,10 +64,11 @@ const ReturnPolicies = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -70,6 +85,8 @@ const ReturnPolicies = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Flex, Space } from 'antd'
|
||||
import ObjectTable from '../common/ObjectTable'
|
||||
import ObjectActions from '../common/ObjectActions'
|
||||
@ -11,9 +11,17 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
|
||||
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
|
||||
import ColumnViewButton from '../common/ColumnViewButton'
|
||||
import ExportListButton from '../common/ExportListButton'
|
||||
import ListViewTabs from '../common/ListViewTabs'
|
||||
import ListViewEditButtons from '../common/ListViewEditButtons'
|
||||
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
|
||||
|
||||
const SalesOrders = () => {
|
||||
const tableRef = useRef()
|
||||
const [viewState, setViewState] = useState({
|
||||
activeView: null,
|
||||
handleFilterSortChange: null
|
||||
})
|
||||
|
||||
|
||||
const [viewMode, setViewMode] = useViewMode('salesOrders')
|
||||
|
||||
@ -30,8 +38,13 @@ const SalesOrders = () => {
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={'true'} gap='large' className='h-100'>
|
||||
<Flex justify={'space-between'} style={{ minHeight: 0 }}>
|
||||
<Space size='small'>
|
||||
<ObjectListViewProvider
|
||||
objectType='salesOrder'
|
||||
tableRef={tableRef}
|
||||
onViewStateChange={setViewState}
|
||||
>
|
||||
<Flex justify='space-between' style={{ minHeight: 0 }} gap='small'>
|
||||
<Space size='small'>
|
||||
<ObjectActions
|
||||
type='salesOrder'
|
||||
pageName='list'
|
||||
@ -45,7 +58,8 @@ const SalesOrders = () => {
|
||||
/>
|
||||
<ExportListButton objectType='salesOrder' />
|
||||
</Space>
|
||||
<Space>
|
||||
<ListViewTabs />
|
||||
<Space>
|
||||
<SortSidebarButton
|
||||
active={showSortSidebar}
|
||||
onClick={() => setShowSortSidebar(!showSortSidebar)}
|
||||
@ -57,10 +71,11 @@ const SalesOrders = () => {
|
||||
<ObjectTableViewButton
|
||||
viewMode={viewMode}
|
||||
setViewMode={setViewMode}
|
||||
showEndingDivider={true}
|
||||
/>
|
||||
<ListViewEditButtons showStartingDivider={true} />
|
||||
</Space>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</ObjectListViewProvider>
|
||||
<ObjectTable
|
||||
ref={tableRef}
|
||||
visibleColumns={columnVisibility}
|
||||
@ -77,6 +92,8 @@ const SalesOrders = () => {
|
||||
saveSortInUrl={true}
|
||||
useSortInSession={true}
|
||||
useSortInUrl={true}
|
||||
activeObjectView={viewState.activeView}
|
||||
onObjectViewFilterSortChange={viewState.handleFilterSortChange}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
|
||||
@ -2,7 +2,16 @@ import { useState, useEffect } from 'react'
|
||||
import { ColorPicker, Checkbox, Flex, Row, Col, Divider } from 'antd'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
const ColorSelector = ({ value, onChange, disabled, required = false }) => {
|
||||
const ColorSelector = ({
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
required = false,
|
||||
size,
|
||||
showText = true,
|
||||
className,
|
||||
onClick
|
||||
}) => {
|
||||
// Determine initial enabled state based on value
|
||||
const [colorEnabled, setColorEnabled] = useState(!!value)
|
||||
|
||||
@ -97,18 +106,24 @@ const ColorSelector = ({ value, onChange, disabled, required = false }) => {
|
||||
]
|
||||
|
||||
return (
|
||||
<Flex gap={'middle'}>
|
||||
<Flex gap={showText ? 'middle' : 0} align='center'>
|
||||
<ColorPicker
|
||||
showText
|
||||
size={size}
|
||||
showText={showText}
|
||||
disabledAlpha
|
||||
style={{ width: '100%', justifyContent: 'start' }}
|
||||
style={
|
||||
showText
|
||||
? { width: '100%', justifyContent: 'start' }
|
||||
: undefined
|
||||
}
|
||||
disabled={(!colorEnabled && !required) || disabled}
|
||||
value={value || '#000000'}
|
||||
onChange={handleColorChange}
|
||||
onClick={onClick}
|
||||
presets={presets}
|
||||
panelRender={customPanelRender}
|
||||
arrow={false}
|
||||
className='ant-input-outlined'
|
||||
className={className ?? (showText ? 'ant-input-outlined' : undefined)}
|
||||
/>
|
||||
{!required && (
|
||||
<Checkbox
|
||||
@ -125,7 +140,11 @@ ColorSelector.propTypes = {
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
required: PropTypes.bool
|
||||
required: PropTypes.bool,
|
||||
size: PropTypes.string,
|
||||
showText: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
onClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default ColorSelector
|
||||
|
||||
@ -1027,7 +1027,7 @@ const FilterInput = ({
|
||||
}
|
||||
}, [])
|
||||
|
||||
const showPlaceholder = !internalValue && !focused
|
||||
const showPlaceholder = Boolean(placeholder) && !internalValue
|
||||
const showClear = allowClear && !!internalValue && !disabled
|
||||
const affixCls = `${prefixCls}-affix-wrapper`
|
||||
|
||||
@ -1076,6 +1076,7 @@ const FilterInput = ({
|
||||
className={classNames(prefixCls, 'filter-input-editor')}
|
||||
role='textbox'
|
||||
aria-multiline='false'
|
||||
aria-placeholder={showPlaceholder ? placeholder : undefined}
|
||||
aria-disabled={disabled || undefined}
|
||||
contentEditable={!disabled}
|
||||
suppressContentEditableWarning
|
||||
|
||||
38
src/components/Dashboard/common/ListViewEditButtons.jsx
Normal file
38
src/components/Dashboard/common/ListViewEditButtons.jsx
Normal file
@ -0,0 +1,38 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { Divider, Flex } from 'antd'
|
||||
import EditButtons from './EditButtons'
|
||||
import { useObjectListView } from '../context/ObjectListViewContext'
|
||||
|
||||
const ListViewEditButtons = ({ showStartingDivider = false }) => {
|
||||
const { isEditing, saving, saveEdits, cancelEdits, startEditing } =
|
||||
useObjectListView()
|
||||
|
||||
if (!isEditing) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex align='center' gap='small'>
|
||||
{showStartingDivider && (
|
||||
<Divider type='vertical' style={{ margin: '0 4px', height: '18px' }} />
|
||||
)}
|
||||
<EditButtons
|
||||
isEditing={isEditing}
|
||||
handleUpdate={async () => {
|
||||
await saveEdits()
|
||||
}}
|
||||
cancelEditing={cancelEdits}
|
||||
startEditing={startEditing}
|
||||
formValid={true}
|
||||
loading={saving}
|
||||
requirePermission={false}
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
ListViewEditButtons.propTypes = {
|
||||
showStartingDivider: PropTypes.bool
|
||||
}
|
||||
|
||||
export default ListViewEditButtons
|
||||
308
src/components/Dashboard/common/ListViewTabs.jsx
Normal file
308
src/components/Dashboard/common/ListViewTabs.jsx
Normal file
@ -0,0 +1,308 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { useMemo } from 'react'
|
||||
import {
|
||||
Input,
|
||||
Dropdown,
|
||||
Checkbox,
|
||||
Button,
|
||||
Flex,
|
||||
Typography,
|
||||
Spin,
|
||||
Divider,
|
||||
theme
|
||||
} from 'antd'
|
||||
const { useToken } = theme
|
||||
import SegmentedNav, { SegmentedNavDragHandle } from './SegmentedNav'
|
||||
import { CaretDownFilled, LoadingOutlined } from '@ant-design/icons'
|
||||
import { getModelByName } from '../../../database/ObjectModels'
|
||||
import { useObjectListView } from '../context/ObjectListViewContext'
|
||||
import classNames from 'classnames'
|
||||
import PlusIcon from '../../Icons/PlusIcon'
|
||||
import EditIcon from '../../Icons/EditIcon'
|
||||
import BinIcon from '../../Icons/BinIcon'
|
||||
import ScrollBox from './ScrollBox'
|
||||
import ColorSelector from './ColorSelector'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
const ViewColorDot = ({ color }) => (
|
||||
<span
|
||||
className='list-view-tabs-color-dot'
|
||||
style={{ backgroundColor: color || '#3498DB' }}
|
||||
/>
|
||||
)
|
||||
|
||||
ViewColorDot.propTypes = {
|
||||
color: PropTypes.string
|
||||
}
|
||||
|
||||
const ViewOptionsDropdown = ({ view, isEditing, onChange, onDelete }) => {
|
||||
const menu = {
|
||||
items: [
|
||||
{
|
||||
key: 'delete',
|
||||
label: 'Delete',
|
||||
icon: <BinIcon />,
|
||||
danger: true,
|
||||
onClick: ({ domEvent }) => {
|
||||
domEvent.stopPropagation()
|
||||
onDelete?.()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const menuStyle = {
|
||||
boxShadow: 'none'
|
||||
}
|
||||
|
||||
const { token } = useToken()
|
||||
const contentStyle = {
|
||||
backgroundColor: token.colorBgElevated,
|
||||
borderRadius: token.borderRadiusLG,
|
||||
boxShadow: token.boxShadowSecondary
|
||||
}
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
menu={menu}
|
||||
trigger={['hover']}
|
||||
placement='bottomLeft'
|
||||
popupRender={(menu) => (
|
||||
<div className='list-view-tabs-options-dropdown' style={contentStyle}>
|
||||
{React.cloneElement(menu, { style: menuStyle })}
|
||||
<Flex
|
||||
vertical
|
||||
gap='middle'
|
||||
className='list-view-tabs-options-dropdown-privacy'
|
||||
>
|
||||
<Checkbox
|
||||
checked={view.private !== false}
|
||||
disabled={!isEditing}
|
||||
onChange={(event) => onChange({ private: event.target.checked })}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
Private
|
||||
</Checkbox>
|
||||
</Flex>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
type='text'
|
||||
size='small'
|
||||
className='list-view-tabs-options-button'
|
||||
icon={<CaretDownFilled style={{ fontSize: 14, marginTop: 4 }} />}
|
||||
disabled={!isEditing}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
/>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
ViewOptionsDropdown.propTypes = {
|
||||
view: PropTypes.object.isRequired,
|
||||
isEditing: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onDelete: PropTypes.func
|
||||
}
|
||||
|
||||
const ViewTabNameInput = ({ value, onClick, onChange }) => (
|
||||
<span className='list-view-tabs-name-input-wrap'>
|
||||
<span aria-hidden className='list-view-tabs-name-input-sizer'>
|
||||
{value}
|
||||
</span>
|
||||
<Input
|
||||
size='small'
|
||||
variant='borderless'
|
||||
className='list-view-tabs-name-input'
|
||||
value={value}
|
||||
onClick={onClick}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
|
||||
ViewTabNameInput.propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
const ViewTabLabel = ({
|
||||
view,
|
||||
isEditing,
|
||||
onDraftChange,
|
||||
onRemove,
|
||||
onSelect
|
||||
}) => {
|
||||
if (!isEditing) {
|
||||
return (
|
||||
<Flex align='center' gap={8} className='list-view-tabs-label'>
|
||||
<ViewColorDot color={view.color} />
|
||||
<Text ellipsis style={{ maxWidth: 160 }}>
|
||||
{view.name}
|
||||
</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Flex
|
||||
align='center'
|
||||
gap={6}
|
||||
className='list-view-tabs-label list-view-tabs-label-editing'
|
||||
onFocusCapture={() => onSelect?.()}
|
||||
>
|
||||
<ColorSelector
|
||||
size='small'
|
||||
showText={false}
|
||||
required
|
||||
value={view.color || '#3498DB'}
|
||||
onChange={(color) => onDraftChange({ color })}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
/>
|
||||
<ViewTabNameInput
|
||||
value={view.name}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onChange={(event) => onDraftChange({ name: event.target.value })}
|
||||
/>
|
||||
<Flex align='center' gap={2}>
|
||||
<ViewOptionsDropdown
|
||||
view={view}
|
||||
isEditing={isEditing}
|
||||
onChange={onDraftChange}
|
||||
onDelete={onRemove}
|
||||
/>
|
||||
<SegmentedNavDragHandle value={String(view._id)} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
ViewTabLabel.propTypes = {
|
||||
view: PropTypes.object.isRequired,
|
||||
isEditing: PropTypes.bool.isRequired,
|
||||
onDraftChange: PropTypes.func.isRequired,
|
||||
onRemove: PropTypes.func,
|
||||
onSelect: PropTypes.func
|
||||
}
|
||||
|
||||
const ListViewTabs = () => {
|
||||
const {
|
||||
objectType,
|
||||
ALL_TAB_KEY,
|
||||
views,
|
||||
activeTabKey,
|
||||
initialLoading,
|
||||
isEditing,
|
||||
startEditing,
|
||||
selectTab,
|
||||
handleTabEdit,
|
||||
updateDraftView,
|
||||
reorderDraftViews,
|
||||
viewTabSignatures
|
||||
} = useObjectListView()
|
||||
|
||||
const model = getModelByName(objectType)
|
||||
|
||||
const options = useMemo(() => {
|
||||
const Icon = model?.icon
|
||||
const allOption = {
|
||||
value: ALL_TAB_KEY,
|
||||
icon: Icon ? <Icon style={{ fontSize: 14 }} /> : null
|
||||
}
|
||||
|
||||
const viewOptions = views.map((view) => ({
|
||||
value: String(view._id),
|
||||
reorderable: isEditing,
|
||||
label: (
|
||||
<ViewTabLabel
|
||||
view={view}
|
||||
isEditing={isEditing}
|
||||
onDraftChange={(changes) => updateDraftView(view._id, changes)}
|
||||
onRemove={
|
||||
isEditing
|
||||
? () => handleTabEdit(String(view._id), 'remove')
|
||||
: undefined
|
||||
}
|
||||
onSelect={() => {
|
||||
const tabKey = String(view._id)
|
||||
if (activeTabKey !== tabKey) {
|
||||
selectTab(tabKey)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}))
|
||||
|
||||
return [allOption, ...viewOptions]
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [
|
||||
ALL_TAB_KEY,
|
||||
activeTabKey,
|
||||
handleTabEdit,
|
||||
isEditing,
|
||||
model?.icon,
|
||||
selectTab,
|
||||
updateDraftView,
|
||||
viewTabSignatures
|
||||
])
|
||||
|
||||
return (
|
||||
<Flex
|
||||
align='center'
|
||||
gap='small'
|
||||
style={{ minHeight: 0, width: '100%', minWidth: 0 }}
|
||||
>
|
||||
<Divider type='vertical' style={{ margin: '0 4px', height: '18px' }} />
|
||||
<Spin
|
||||
spinning={initialLoading === true}
|
||||
wrapperClassName='list-view-tabs-spin'
|
||||
indicator={<LoadingOutlined spin />}
|
||||
>
|
||||
<Flex
|
||||
align='center'
|
||||
gap={4}
|
||||
className={classNames('list-view-tabs', {
|
||||
'list-view-tabs-editing': isEditing
|
||||
})}
|
||||
style={{ flex: 1, minWidth: 0 }}
|
||||
>
|
||||
<ScrollBox className='list-view-tabs-segmented-wrap' horizontal>
|
||||
<Flex
|
||||
align='center'
|
||||
gap={8}
|
||||
className='list-view-tabs-segmented-inner'
|
||||
>
|
||||
<SegmentedNav
|
||||
className='list-view-tabs-segmented'
|
||||
value={activeTabKey}
|
||||
options={options}
|
||||
onChange={selectTab}
|
||||
onReorder={isEditing ? reorderDraftViews : undefined}
|
||||
/>
|
||||
<Button
|
||||
type='text'
|
||||
size='small'
|
||||
className='list-view-tabs-add-button'
|
||||
onClick={
|
||||
isEditing ? () => handleTabEdit(null, 'add') : startEditing
|
||||
}
|
||||
icon={
|
||||
isEditing ? (
|
||||
<PlusIcon style={{ fontSize: 14, marginTop: 3 }} />
|
||||
) : (
|
||||
<EditIcon style={{ fontSize: 12, marginBottom: 5 }} />
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
</ScrollBox>
|
||||
</Flex>
|
||||
</Spin>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
export default ListViewTabs
|
||||
@ -255,6 +255,8 @@ const ObjectTable = forwardRef(
|
||||
saveSortInUrl = false,
|
||||
useSortInSession = false,
|
||||
useSortInUrl = false,
|
||||
activeObjectView = null,
|
||||
onObjectViewFilterSortChange,
|
||||
onRowAction
|
||||
},
|
||||
ref
|
||||
@ -317,6 +319,15 @@ const ObjectTable = forwardRef(
|
||||
const model = getModelByName(type)
|
||||
const activeFilterRef = useRef({})
|
||||
const tableSorterRef = useRef({})
|
||||
const activeObjectViewRef = useRef(activeObjectView)
|
||||
activeObjectViewRef.current = activeObjectView
|
||||
const onObjectViewFilterSortChangeRef = useRef(onObjectViewFilterSortChange)
|
||||
onObjectViewFilterSortChangeRef.current = onObjectViewFilterSortChange
|
||||
const listViewMastersRef = useRef({ masterFilter: {}, masterSort: {} })
|
||||
const [listViewMasters, setListViewMastersState] = useState({
|
||||
masterFilter: {},
|
||||
masterSort: {}
|
||||
})
|
||||
const [sidebarFilter, setSidebarFilter] = useState({})
|
||||
const [tableSorter, setTableSorter] = useState({})
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
@ -369,6 +380,33 @@ const ObjectTable = forwardRef(
|
||||
)
|
||||
const prevValuesRef = useRef({ type, masterFilter })
|
||||
|
||||
const effectiveMasterFilter = useMemo(
|
||||
() => ({
|
||||
...listViewMasters.masterFilter,
|
||||
...masterFilter
|
||||
}),
|
||||
[listViewMasters.masterFilter, masterFilter]
|
||||
)
|
||||
|
||||
const getEffectiveMasterFilter = useCallback(
|
||||
() => ({
|
||||
...listViewMastersRef.current.masterFilter,
|
||||
...masterFilter
|
||||
}),
|
||||
[masterFilter]
|
||||
)
|
||||
|
||||
const resolveSorter = useCallback((userSorter) => {
|
||||
if (userSorter?.field && userSorter?.order) {
|
||||
return { field: userSorter.field, order: userSorter.order }
|
||||
}
|
||||
const masterSort = listViewMastersRef.current.masterSort
|
||||
if (masterSort?.field && masterSort?.order) {
|
||||
return { field: masterSort.field, order: masterSort.order }
|
||||
}
|
||||
return {}
|
||||
}, [])
|
||||
|
||||
const rowActions =
|
||||
model.actions?.filter((action) => action.row == true) || []
|
||||
|
||||
@ -508,12 +546,19 @@ const ObjectTable = forwardRef(
|
||||
return fetchObjects(type, {
|
||||
page: pageNum,
|
||||
limit: pageSize,
|
||||
filter: { ...filter, ...masterFilter },
|
||||
sorter,
|
||||
filter: { ...getEffectiveMasterFilter(), ...filter },
|
||||
sorter: resolveSorter(sorter),
|
||||
onDataChange
|
||||
})
|
||||
},
|
||||
[type, masterFilter, pageSize, onDataChange, fetchObjects]
|
||||
[
|
||||
type,
|
||||
getEffectiveMasterFilter,
|
||||
pageSize,
|
||||
onDataChange,
|
||||
fetchObjects,
|
||||
resolveSorter
|
||||
]
|
||||
)
|
||||
|
||||
const skeletonsHeight = useMemo(() => {
|
||||
@ -871,15 +916,15 @@ const ObjectTable = forwardRef(
|
||||
Object.entries(sidebarFilter).forEach(([k, v]) => {
|
||||
if (v !== '' && v !== undefined) active[k] = v
|
||||
})
|
||||
return { ...active, ...masterFilter }
|
||||
}, [sidebarFilter, masterFilter])
|
||||
return { ...effectiveMasterFilter, ...active }
|
||||
}, [sidebarFilter, effectiveMasterFilter])
|
||||
|
||||
const tableFilterContextValue = useMemo(
|
||||
() => ({
|
||||
filter: getActiveFilterValues(sidebarFilter),
|
||||
masterFilter
|
||||
masterFilter: effectiveMasterFilter
|
||||
}),
|
||||
[sidebarFilter, masterFilter]
|
||||
[sidebarFilter, effectiveMasterFilter]
|
||||
)
|
||||
|
||||
newEventHandlerRef.current = newEventHandler
|
||||
@ -1043,20 +1088,89 @@ const ObjectTable = forwardRef(
|
||||
const filter = getPersistedFilter()
|
||||
const sorter = getPersistedSorter()
|
||||
const activeFilter = getActiveFilterValues(filter)
|
||||
const resolvedSorter = resolveSorter(sorter)
|
||||
|
||||
if (Object.keys(filter).length > 0) {
|
||||
setSidebarFilter(filter)
|
||||
}
|
||||
if (sorter.field) {
|
||||
if (sorter?.field) {
|
||||
tableSorterRef.current = sorter
|
||||
setTableSorter(sorter)
|
||||
}
|
||||
|
||||
loadPage(initialPage, activeFilter, sorter.field ? sorter : null)
|
||||
}, [getPersistedFilter, getPersistedSorter, initialPage, loadPage])
|
||||
loadPage(
|
||||
initialPage,
|
||||
activeFilter,
|
||||
resolvedSorter.field ? resolvedSorter : null
|
||||
)
|
||||
}, [
|
||||
getPersistedFilter,
|
||||
getPersistedSorter,
|
||||
initialPage,
|
||||
loadPage,
|
||||
resolveSorter
|
||||
])
|
||||
|
||||
const setListViewMasters = useCallback(
|
||||
({ masterFilter: nextMasterFilter = {}, masterSort: nextMasterSort = {} }) => {
|
||||
listViewMastersRef.current = {
|
||||
masterFilter: nextMasterFilter,
|
||||
masterSort: nextMasterSort
|
||||
}
|
||||
setListViewMastersState({
|
||||
masterFilter: nextMasterFilter,
|
||||
masterSort: nextMasterSort
|
||||
})
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
const applyViewState = useCallback(
|
||||
(filterState, sorterState) => {
|
||||
if (filterState == null && sorterState == null) {
|
||||
const filter = getPersistedFilter()
|
||||
const sorter = getPersistedSorter()
|
||||
const activeFilter = getActiveFilterValues(filter)
|
||||
const resolvedSorter = resolveSorter(sorter)
|
||||
setSidebarFilter(filter)
|
||||
tableSorterRef.current = sorter?.field ? sorter : {}
|
||||
setTableSorter(sorter?.field ? sorter : {})
|
||||
activeFilterRef.current = activeFilter
|
||||
loadPage(
|
||||
initialPage,
|
||||
activeFilter,
|
||||
resolvedSorter.field ? resolvedSorter : null
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const filter = filterState || {}
|
||||
const sorter = sorterState?.field ? sorterState : {}
|
||||
const activeFilter = getActiveFilterValues(filter)
|
||||
const resolvedSorter = resolveSorter(sorter)
|
||||
setSidebarFilter(filter)
|
||||
tableSorterRef.current = sorter
|
||||
setTableSorter(sorter)
|
||||
activeFilterRef.current = activeFilter
|
||||
loadPage(
|
||||
initialPage,
|
||||
activeFilter,
|
||||
resolvedSorter.field ? resolvedSorter : null
|
||||
)
|
||||
},
|
||||
[
|
||||
getPersistedFilter,
|
||||
getPersistedSorter,
|
||||
initialPage,
|
||||
loadPage,
|
||||
resolveSorter
|
||||
]
|
||||
)
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
reload,
|
||||
applyViewState,
|
||||
setListViewMasters,
|
||||
setData: (newData) => {
|
||||
setPages([{ pageNum: 1, items: newData }])
|
||||
},
|
||||
@ -1084,7 +1198,6 @@ const ObjectTable = forwardRef(
|
||||
useEffect(() => {
|
||||
const prevValues = prevValuesRef.current
|
||||
|
||||
// Deep comparison for objects, simple comparison for primitives
|
||||
const hasChanged =
|
||||
prevValues.type !== type ||
|
||||
JSON.stringify(prevValues.masterFilter) !== JSON.stringify(masterFilter)
|
||||
@ -1133,7 +1246,7 @@ const ObjectTable = forwardRef(
|
||||
propertyLabel={propertyLabel}
|
||||
modelType={type}
|
||||
filter={sidebarFilter}
|
||||
masterFilter={masterFilter}
|
||||
masterFilter={effectiveMasterFilter}
|
||||
/>
|
||||
)
|
||||
|
||||
@ -1158,21 +1271,29 @@ const ObjectTable = forwardRef(
|
||||
|
||||
setSidebarFilter(next)
|
||||
setTableSorter(nextSorter)
|
||||
persistTableState(next, nextSorter)
|
||||
loadPage(initialPage, getActiveFilterValues(next), nextSorter)
|
||||
if (activeObjectViewRef.current) {
|
||||
onObjectViewFilterSortChangeRef.current?.(next, nextSorter)
|
||||
} else {
|
||||
persistTableState(next, nextSorter)
|
||||
}
|
||||
loadPage(initialPage, getActiveFilterValues(next), resolveSorter(nextSorter))
|
||||
}
|
||||
|
||||
const handleSidebarFilterChange = useCallback(
|
||||
(newSidebarFilter) => {
|
||||
setSidebarFilter(newSidebarFilter)
|
||||
persistFilter(newSidebarFilter)
|
||||
if (activeObjectViewRef.current) {
|
||||
onObjectViewFilterSortChangeRef.current?.(newSidebarFilter, tableSorter)
|
||||
} else {
|
||||
persistFilter(newSidebarFilter)
|
||||
}
|
||||
loadPage(
|
||||
initialPage,
|
||||
getActiveFilterValues(newSidebarFilter),
|
||||
tableSorter.field ? tableSorter : null
|
||||
resolveSorter(tableSorter)
|
||||
)
|
||||
},
|
||||
[initialPage, loadPage, persistFilter, tableSorter]
|
||||
[initialPage, loadPage, persistFilter, resolveSorter, tableSorter]
|
||||
)
|
||||
|
||||
const handleSidebarSortChange = useCallback(
|
||||
@ -1183,17 +1304,21 @@ const ObjectTable = forwardRef(
|
||||
isInternalSortUpdateRef.current = true
|
||||
setTableSorter(nextSorter)
|
||||
tableSorterRef.current = nextSorter
|
||||
persistSort(nextSorter)
|
||||
if (activeObjectViewRef.current) {
|
||||
onObjectViewFilterSortChangeRef.current?.(sidebarFilter, nextSorter)
|
||||
} else {
|
||||
persistSort(nextSorter)
|
||||
}
|
||||
loadPage(
|
||||
initialPage,
|
||||
getActiveFilterValues(sidebarFilter),
|
||||
nextSorter.field ? nextSorter : null
|
||||
resolveSorter(nextSorter)
|
||||
)
|
||||
requestAnimationFrame(() => {
|
||||
isInternalSortUpdateRef.current = false
|
||||
})
|
||||
},
|
||||
[initialPage, loadPage, persistSort, sidebarFilter]
|
||||
[initialPage, loadPage, persistSort, resolveSorter, sidebarFilter]
|
||||
)
|
||||
|
||||
const modelProperties = getModelProperties(type)
|
||||
@ -1315,7 +1440,7 @@ const ObjectTable = forwardRef(
|
||||
}
|
||||
}
|
||||
|
||||
if (isFilterable && !Object.keys(masterFilter).includes(prop.name)) {
|
||||
if (isFilterable && !Object.keys(effectiveMasterFilter).includes(prop.name)) {
|
||||
columnConfig.filterDropdown = ({
|
||||
setSelectedKeys,
|
||||
selectedKeys,
|
||||
@ -1594,7 +1719,7 @@ const ObjectTable = forwardRef(
|
||||
type={type}
|
||||
filter={sidebarFilter}
|
||||
onFilterChange={handleSidebarFilterChange}
|
||||
masterFilter={masterFilter}
|
||||
masterFilter={effectiveMasterFilter}
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
@ -1639,6 +1764,8 @@ ObjectTable.propTypes = {
|
||||
saveSortInUrl: PropTypes.bool,
|
||||
useSortInSession: PropTypes.bool,
|
||||
useSortInUrl: PropTypes.bool,
|
||||
activeObjectView: PropTypes.object,
|
||||
onObjectViewFilterSortChange: PropTypes.func,
|
||||
onRowAction: PropTypes.func
|
||||
}
|
||||
|
||||
|
||||
@ -87,6 +87,7 @@ const PropertyChanges = ({ type, value }) => {
|
||||
longId={false}
|
||||
minimal={true}
|
||||
showPreview={false}
|
||||
showProgress={false}
|
||||
objectData={value?.old}
|
||||
maxWidth='200px'
|
||||
/>
|
||||
@ -102,6 +103,7 @@ const PropertyChanges = ({ type, value }) => {
|
||||
longId={false}
|
||||
minimal={true}
|
||||
showPreview={false}
|
||||
showProgress={false}
|
||||
objectData={value?.new}
|
||||
maxWidth='200px'
|
||||
/>
|
||||
|
||||
@ -8,21 +8,30 @@ const ScrollBox = ({
|
||||
horizontalBottomPadding = 16,
|
||||
verticalRightPadding = 16,
|
||||
inner = false,
|
||||
horizontal = false,
|
||||
smallPadding = false,
|
||||
className = '',
|
||||
...rest
|
||||
}) => {
|
||||
const outerStyle = {
|
||||
minHeight: '0',
|
||||
minWidth: horizontal ? 0 : undefined,
|
||||
'--scrollbox-vertical-right-padding': `${verticalRightPadding}px`,
|
||||
'--scrollbox-horizontal-bottom-padding': `${horizontalBottomPadding}px`,
|
||||
...(horizontal ? { width: '100%', height: 'auto' } : { height: '100%' })
|
||||
}
|
||||
|
||||
const simpleBarStyle = {
|
||||
...(horizontal ? { width: '100%', height: 'auto' } : { height: '100%' }),
|
||||
...style
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '100%',
|
||||
minHeight: '0',
|
||||
'--scrollbox-vertical-right-padding': `${verticalRightPadding}px`,
|
||||
'--scrollbox-horizontal-bottom-padding': `${horizontalBottomPadding}px`
|
||||
}}
|
||||
className={`${inner ? 'scrollbox-inner' : ''} ${smallPadding ? 'scrollbox-inner-small-padding' : ''} ${className}`}
|
||||
style={outerStyle}
|
||||
className={`${inner ? 'scrollbox-inner' : ''} ${smallPadding ? 'scrollbox-inner-small-padding' : ''} ${horizontal ? 'scrollbox-horizontal' : ''} ${className}`}
|
||||
>
|
||||
<SimpleBar style={{ height: '100%', ...style }} {...rest}>
|
||||
<SimpleBar style={simpleBarStyle} {...rest}>
|
||||
{children}
|
||||
</SimpleBar>
|
||||
</div>
|
||||
@ -35,6 +44,7 @@ ScrollBox.propTypes = {
|
||||
horizontalBottomPadding: PropTypes.number,
|
||||
verticalRightPadding: PropTypes.number,
|
||||
inner: PropTypes.bool,
|
||||
horizontal: PropTypes.bool,
|
||||
smallPadding: PropTypes.bool,
|
||||
className: PropTypes.string
|
||||
}
|
||||
|
||||
431
src/components/Dashboard/common/SegmentedNav.jsx
Normal file
431
src/components/Dashboard/common/SegmentedNav.jsx
Normal file
@ -0,0 +1,431 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useLayoutEffect,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react'
|
||||
import { HolderOutlined } from '@ant-design/icons'
|
||||
import classNames from 'classnames'
|
||||
|
||||
const SegmentedNavReorderContext = createContext(null)
|
||||
|
||||
const getEnabledOptions = (options, disabled) =>
|
||||
options.filter((option) => !disabled && !option.disabled)
|
||||
|
||||
const getItemMetrics = (element) => {
|
||||
if (!element) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
left: element.offsetLeft,
|
||||
top: element.offsetTop,
|
||||
width: element.offsetWidth,
|
||||
height: element.offsetHeight
|
||||
}
|
||||
}
|
||||
|
||||
export const SegmentedNavDragHandle = ({ value }) => {
|
||||
const reorder = useContext(SegmentedNavReorderContext)
|
||||
const dragProps = reorder?.getDragHandleProps?.(value)
|
||||
|
||||
if (!dragProps) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className='segmented-nav-drag-handle overview-drag-handle'
|
||||
draggable
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
onMouseDown={(event) => event.stopPropagation()}
|
||||
onDragStart={(event) => dragProps.onDragStart(event)}
|
||||
onDragEnd={dragProps.onDragEnd}
|
||||
>
|
||||
<HolderOutlined />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
SegmentedNavDragHandle.propTypes = {
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
|
||||
}
|
||||
|
||||
const SegmentedNav = ({
|
||||
value,
|
||||
options = [],
|
||||
onChange,
|
||||
onReorder,
|
||||
className,
|
||||
disabled = false
|
||||
}) => {
|
||||
const groupRef = useRef(null)
|
||||
const thumbRef = useRef(null)
|
||||
const itemRefs = useRef(new Map())
|
||||
const prevValueRef = useRef(value)
|
||||
const transitionGenRef = useRef(0)
|
||||
const finishGenRef = useRef(0)
|
||||
const [isAnimating, setIsAnimating] = useState(false)
|
||||
const [thumbRect, setThumbRect] = useState(null)
|
||||
const [draggedValue, setDraggedValue] = useState(null)
|
||||
const [dropTarget, setDropTarget] = useState(null)
|
||||
|
||||
const enabledOptions = getEnabledOptions(options, disabled)
|
||||
const isReordering = Boolean(onReorder && draggedValue != null)
|
||||
|
||||
const setItemRef = useCallback((optionValue, element) => {
|
||||
if (element) {
|
||||
itemRefs.current.set(optionValue, element)
|
||||
} else {
|
||||
itemRefs.current.delete(optionValue)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (prevValueRef.current === value) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const fromMetrics = getItemMetrics(
|
||||
itemRefs.current.get(prevValueRef.current)
|
||||
)
|
||||
const toMetrics = getItemMetrics(itemRefs.current.get(value))
|
||||
prevValueRef.current = value
|
||||
|
||||
if (!fromMetrics || !toMetrics) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const transitionGen = transitionGenRef.current + 1
|
||||
transitionGenRef.current = transitionGen
|
||||
|
||||
setIsAnimating(true)
|
||||
setThumbRect(fromMetrics)
|
||||
|
||||
let endFrame = 0
|
||||
const startFrame = requestAnimationFrame(() => {
|
||||
endFrame = requestAnimationFrame(() => {
|
||||
if (transitionGenRef.current === transitionGen) {
|
||||
finishGenRef.current = transitionGen
|
||||
setThumbRect(toMetrics)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return () => {
|
||||
cancelAnimationFrame(startFrame)
|
||||
cancelAnimationFrame(endFrame)
|
||||
}
|
||||
}, [value])
|
||||
|
||||
const finishAnimation = useCallback(() => {
|
||||
setIsAnimating(false)
|
||||
setThumbRect(null)
|
||||
}, [])
|
||||
|
||||
const handleThumbTransitionEnd = useCallback(
|
||||
(event) => {
|
||||
if (event.target !== thumbRef.current) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
(event.propertyName === 'transform' ||
|
||||
event.propertyName === 'width') &&
|
||||
finishGenRef.current === transitionGenRef.current
|
||||
) {
|
||||
finishAnimation()
|
||||
}
|
||||
},
|
||||
[finishAnimation]
|
||||
)
|
||||
|
||||
const clearDragState = useCallback(() => {
|
||||
setDraggedValue(null)
|
||||
setDropTarget(null)
|
||||
}, [])
|
||||
|
||||
const handleDragStart = useCallback(
|
||||
(event, optionValue) => {
|
||||
if (!onReorder) return
|
||||
|
||||
event.stopPropagation()
|
||||
const item = event.currentTarget.closest('.segmented-nav-item')
|
||||
if (item) {
|
||||
const rect = item.getBoundingClientRect()
|
||||
event.dataTransfer.setDragImage(
|
||||
item,
|
||||
event.clientX - rect.left,
|
||||
event.clientY - rect.top
|
||||
)
|
||||
}
|
||||
|
||||
setDraggedValue(optionValue)
|
||||
event.dataTransfer.effectAllowed = 'move'
|
||||
event.dataTransfer.setData('text/plain', String(optionValue))
|
||||
},
|
||||
[onReorder]
|
||||
)
|
||||
|
||||
const handleDragEnd = useCallback(() => {
|
||||
clearDragState()
|
||||
}, [clearDragState])
|
||||
|
||||
const handleItemDragOver = useCallback(
|
||||
(event, option) => {
|
||||
if (!onReorder || draggedValue == null || !option.reorderable) {
|
||||
return
|
||||
}
|
||||
if (String(option.value) === String(draggedValue)) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
event.dataTransfer.dropEffect = 'move'
|
||||
|
||||
const rect = event.currentTarget.getBoundingClientRect()
|
||||
setDropTarget({
|
||||
value: option.value,
|
||||
insertBefore: event.clientX < rect.left + rect.width / 2
|
||||
})
|
||||
},
|
||||
[draggedValue, onReorder]
|
||||
)
|
||||
|
||||
const handleItemDrop = useCallback(
|
||||
(event, option) => {
|
||||
if (!onReorder || draggedValue == null || !option.reorderable) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
const target = dropTarget || {
|
||||
value: option.value,
|
||||
insertBefore: true
|
||||
}
|
||||
|
||||
if (String(draggedValue) !== String(target.value)) {
|
||||
onReorder(draggedValue, target.value, target.insertBefore)
|
||||
}
|
||||
|
||||
clearDragState()
|
||||
},
|
||||
[clearDragState, draggedValue, dropTarget, onReorder]
|
||||
)
|
||||
|
||||
const handleGroupDragOver = useCallback(
|
||||
(event) => {
|
||||
if (!onReorder || draggedValue == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const reorderableOptions = options.filter((option) => option.reorderable)
|
||||
if (reorderableOptions.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
event.target instanceof Element &&
|
||||
event.target.closest('.segmented-nav-item')
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.dataTransfer.dropEffect = 'move'
|
||||
|
||||
const lastOption = reorderableOptions[reorderableOptions.length - 1]
|
||||
setDropTarget({
|
||||
value: lastOption.value,
|
||||
insertBefore: false
|
||||
})
|
||||
},
|
||||
[draggedValue, onReorder, options]
|
||||
)
|
||||
|
||||
const handleGroupDrop = useCallback(
|
||||
(event) => {
|
||||
if (!onReorder || draggedValue == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
event.target instanceof Element &&
|
||||
event.target.closest('.segmented-nav-item')
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
|
||||
const reorderableOptions = options.filter((option) => option.reorderable)
|
||||
const lastOption = reorderableOptions[reorderableOptions.length - 1]
|
||||
if (lastOption && String(draggedValue) !== String(lastOption.value)) {
|
||||
onReorder(draggedValue, lastOption.value, false)
|
||||
}
|
||||
|
||||
clearDragState()
|
||||
},
|
||||
[clearDragState, draggedValue, onReorder, options]
|
||||
)
|
||||
|
||||
const getDragHandleProps = useCallback(
|
||||
(optionValue) => {
|
||||
const option = options.find(
|
||||
(item) => String(item.value) === String(optionValue)
|
||||
)
|
||||
if (!onReorder || !option?.reorderable) {
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
onDragStart: (event) => handleDragStart(event, optionValue),
|
||||
onDragEnd: handleDragEnd
|
||||
}
|
||||
},
|
||||
[handleDragEnd, handleDragStart, onReorder, options]
|
||||
)
|
||||
|
||||
const handleKeyDown = (event, optionIndex) => {
|
||||
if (event.key !== 'ArrowRight' && event.key !== 'ArrowLeft') {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
|
||||
const direction = event.key === 'ArrowRight' ? 1 : -1
|
||||
const currentEnabledIndex = enabledOptions.findIndex(
|
||||
(option) => option.value === value
|
||||
)
|
||||
const startIndex =
|
||||
currentEnabledIndex === -1 ? optionIndex : currentEnabledIndex
|
||||
const nextIndex =
|
||||
(startIndex + direction + enabledOptions.length) % enabledOptions.length
|
||||
|
||||
onChange?.(enabledOptions[nextIndex].value)
|
||||
}
|
||||
|
||||
const reorderContextValue = onReorder ? { getDragHandleProps } : null
|
||||
|
||||
return (
|
||||
<SegmentedNavReorderContext.Provider value={reorderContextValue}>
|
||||
<div
|
||||
className={classNames('segmented-nav', className, {
|
||||
'segmented-nav-disabled': disabled,
|
||||
'segmented-nav-reordering': isReordering
|
||||
})}
|
||||
role='radiogroup'
|
||||
>
|
||||
<div
|
||||
className={classNames('segmented-nav-group', {
|
||||
'segmented-nav-animating': isAnimating
|
||||
})}
|
||||
ref={groupRef}
|
||||
onDragOver={handleGroupDragOver}
|
||||
onDrop={handleGroupDrop}
|
||||
>
|
||||
{isAnimating && thumbRect && (
|
||||
<div
|
||||
ref={thumbRef}
|
||||
className='segmented-nav-thumb'
|
||||
style={{
|
||||
width: thumbRect.width,
|
||||
height: thumbRect.height,
|
||||
transform: `translate3d(${thumbRect.left}px, ${thumbRect.top}px, 0)`
|
||||
}}
|
||||
onTransitionEnd={handleThumbTransitionEnd}
|
||||
aria-hidden='true'
|
||||
/>
|
||||
)}
|
||||
{options.map((option, index) => {
|
||||
const isSelected = value === option.value
|
||||
const isDisabled = disabled || option.disabled
|
||||
const isDragging =
|
||||
draggedValue != null &&
|
||||
String(draggedValue) === String(option.value)
|
||||
const isDropTarget =
|
||||
dropTarget != null &&
|
||||
String(dropTarget.value) === String(option.value) &&
|
||||
String(draggedValue) !== String(option.value)
|
||||
|
||||
return (
|
||||
<button
|
||||
key={option.value}
|
||||
ref={(element) => setItemRef(option.value, element)}
|
||||
type='button'
|
||||
role='radio'
|
||||
aria-checked={isSelected}
|
||||
disabled={isDisabled}
|
||||
tabIndex={isSelected ? 0 : -1}
|
||||
className={classNames('segmented-nav-item', option.className, {
|
||||
'segmented-nav-item-selected': isSelected,
|
||||
'segmented-nav-item-disabled': isDisabled,
|
||||
'segmented-nav-item-dragging': isDragging,
|
||||
'segmented-nav-item-drop-before':
|
||||
isDropTarget && dropTarget.insertBefore,
|
||||
'segmented-nav-item-drop-after':
|
||||
isDropTarget && !dropTarget.insertBefore,
|
||||
'segmented-nav-item-icon': option.icon
|
||||
})}
|
||||
onClick={() => {
|
||||
if (!isDisabled) {
|
||||
onChange?.(option.value)
|
||||
}
|
||||
}}
|
||||
onKeyDown={(event) => handleKeyDown(event, index)}
|
||||
onDragOver={
|
||||
option.reorderable
|
||||
? (event) => handleItemDragOver(event, option)
|
||||
: undefined
|
||||
}
|
||||
onDrop={
|
||||
option.reorderable
|
||||
? (event) => handleItemDrop(event, option)
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{option.icon && (
|
||||
<span className='segmented-nav-item-icon-contents'>
|
||||
{option.icon}
|
||||
</span>
|
||||
)}
|
||||
{option.label && (
|
||||
<span className='segmented-nav-item-label'>
|
||||
{option.label}
|
||||
</span>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</SegmentedNavReorderContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
SegmentedNav.propTypes = {
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
options: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
|
||||
.isRequired,
|
||||
label: PropTypes.node,
|
||||
disabled: PropTypes.bool,
|
||||
reorderable: PropTypes.bool,
|
||||
className: PropTypes.string
|
||||
})
|
||||
),
|
||||
onChange: PropTypes.func,
|
||||
onReorder: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool
|
||||
}
|
||||
|
||||
export default SegmentedNav
|
||||
@ -34,20 +34,27 @@ const StateDisplay = ({
|
||||
'syncing'
|
||||
]
|
||||
|
||||
const circularLoadingTypes = ['loading', 'processing', 'initializing']
|
||||
|
||||
const currentState = state || {
|
||||
type: 'unknown',
|
||||
progress: 0
|
||||
}
|
||||
const [showMessageModal, setShowMessageModal] = useState(false)
|
||||
const progressValue = Math.round(currentState.progress * 1000) / 10
|
||||
|
||||
const isCircularLoading = circularLoadingTypes.includes(currentState.type)
|
||||
const showCircularLoading = isCircularLoading && showProgress
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex gap='small' align={'center'}>
|
||||
{showState && (
|
||||
<Space>
|
||||
<StateTag state={currentState.type} />
|
||||
<StateTag state={currentState.type} loading={showCircularLoading} />
|
||||
</Space>
|
||||
)}
|
||||
|
||||
{showProgress &&
|
||||
loadingProgressTypes.includes(currentState.type) &&
|
||||
currentState?.progress &&
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
import PropTypes from 'prop-types'
|
||||
import { Badge, Flex, Tag } from 'antd'
|
||||
import { useMemo } from 'react'
|
||||
import LoadingIcon from '../../Icons/LoadingIcon'
|
||||
|
||||
const StateTag = ({ state, showBadge = true, showTag = true, style = {} }) => {
|
||||
const StateTag = ({
|
||||
state,
|
||||
showBadge = true,
|
||||
showTag = true,
|
||||
loading = false,
|
||||
style = {}
|
||||
}) => {
|
||||
const { badgeStatus, badgeText } = useMemo(() => {
|
||||
let status = 'default'
|
||||
let text = 'Unknown'
|
||||
@ -216,10 +223,17 @@ const StateTag = ({ state, showBadge = true, showTag = true, style = {} }) => {
|
||||
return <Badge {...badgeProps} style={{ ...style }} />
|
||||
}
|
||||
|
||||
const showLoading = loading && showBadge
|
||||
|
||||
const padding = showLoading ? '0 6px' : '0 8px'
|
||||
|
||||
return (
|
||||
<Tag color={badgeStatus} style={{ marginRight: 0, ...style }}>
|
||||
<Tag color={badgeStatus} style={{ marginRight: 0, ...style, padding }}>
|
||||
<Flex gap={6}>
|
||||
{showBadge && <Badge {...badgeProps} />}
|
||||
{showBadge && !loading && <Badge {...badgeProps} />}
|
||||
{showLoading && (
|
||||
<LoadingIcon style={{ fontSize: 8 }} className='state-tag-loading' />
|
||||
)}
|
||||
{badgeText}
|
||||
</Flex>
|
||||
</Tag>
|
||||
@ -230,7 +244,8 @@ StateTag.propTypes = {
|
||||
state: PropTypes.string,
|
||||
showBadge: PropTypes.bool,
|
||||
style: PropTypes.object,
|
||||
showTag: PropTypes.bool
|
||||
showTag: PropTypes.bool,
|
||||
loading: PropTypes.bool
|
||||
}
|
||||
|
||||
export default StateTag
|
||||
|
||||
@ -2532,6 +2532,51 @@ const ApiServerProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const fetchObjectViews = async (objectType) => {
|
||||
if (!objectType) return { data: [] }
|
||||
try {
|
||||
const result = await fetchObjects('objectView', {
|
||||
filter: { objectType },
|
||||
limit: 100
|
||||
})
|
||||
return result || { data: [] }
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => fetchObjectViews(objectType))
|
||||
return { data: [] }
|
||||
}
|
||||
}
|
||||
|
||||
const createObjectView = async (values) => {
|
||||
try {
|
||||
return await createObject('objectView', values)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => createObjectView(values))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const updateObjectView = async (objectViewId, updates) => {
|
||||
try {
|
||||
return await updateObject(objectViewId, 'objectView', updates)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => updateObjectView(objectViewId, updates))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const deleteObjectView = async (objectViewId) => {
|
||||
try {
|
||||
return await deleteObject(objectViewId, 'objectView')
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
showError(err, () => deleteObjectView(objectViewId))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const fetchNotificationsApi = useCallback(async () => {
|
||||
const response = await axios.get(`${config.backendUrl}/notifications`, {
|
||||
params: { limit: 100, sortProperty: 'createdAt', sortOrder: 'descend' },
|
||||
@ -2848,6 +2893,10 @@ const ApiServerProvider = ({ children }) => {
|
||||
fetchAllUserNotifiersForObject,
|
||||
toggleUserNotifier,
|
||||
editUserNotifier,
|
||||
fetchObjectViews,
|
||||
createObjectView,
|
||||
updateObjectView,
|
||||
deleteObjectView,
|
||||
fetchNotificationsApi,
|
||||
markNotificationAsReadApi,
|
||||
markAllNotificationsAsReadApi,
|
||||
|
||||
826
src/components/Dashboard/context/ObjectListViewContext.jsx
Normal file
826
src/components/Dashboard/context/ObjectListViewContext.jsx
Normal file
@ -0,0 +1,826 @@
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState
|
||||
} from 'react'
|
||||
import { message } from 'antd'
|
||||
import PropTypes from 'prop-types'
|
||||
import { ApiServerContext } from './ApiServerContext'
|
||||
import { AuthContext } from './AuthContext'
|
||||
import { useTableState } from './TableStateContext'
|
||||
|
||||
const ObjectListViewContext = createContext()
|
||||
|
||||
const ALL_TAB_KEY = 'all'
|
||||
|
||||
const getPreviousTabKey = (viewList, deletedKey) => {
|
||||
const index = viewList.findIndex(
|
||||
(view) => String(view._id) === String(deletedKey)
|
||||
)
|
||||
if (index <= 0) {
|
||||
return ALL_TAB_KEY
|
||||
}
|
||||
return String(viewList[index - 1]._id)
|
||||
}
|
||||
|
||||
const DEFAULT_VIEW = {
|
||||
name: 'New View',
|
||||
color: '#3498DB',
|
||||
private: true,
|
||||
filter: {},
|
||||
sort: {}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const getObjectViewKey = (view) =>
|
||||
view?._reference || view?._id || null
|
||||
|
||||
const resolveViewFromRef = (views, viewRef) => {
|
||||
if (!viewRef) return null
|
||||
return (
|
||||
views.find(
|
||||
(view) =>
|
||||
view._reference === viewRef || String(view._id) === String(viewRef)
|
||||
) || null
|
||||
)
|
||||
}
|
||||
|
||||
const cloneViews = (views) =>
|
||||
views.map((view) => ({
|
||||
...view,
|
||||
filter: view.filter ? { ...view.filter } : {},
|
||||
sort: view.sort ? { ...view.sort } : {}
|
||||
}))
|
||||
|
||||
const getViewTabSignature = (view) =>
|
||||
`${view._id}:${view.name}:${view.color}:${view.private}:${view._isDraft ? 1 : 0}`
|
||||
|
||||
const viewStateEqual = (left, right) =>
|
||||
JSON.stringify(left || {}) === JSON.stringify(right || {})
|
||||
|
||||
export const ObjectListViewProvider = ({
|
||||
children,
|
||||
objectType,
|
||||
tableRef,
|
||||
onViewStateChange
|
||||
}) => {
|
||||
const {
|
||||
fetchObjectViews,
|
||||
createObjectView,
|
||||
updateObjectView,
|
||||
deleteObjectView,
|
||||
connected,
|
||||
subscribeToObjectTypeUpdates,
|
||||
subscribeToObjectUpdates
|
||||
} = useContext(ApiServerContext)
|
||||
const { token, authInitialized } = useContext(AuthContext)
|
||||
const { getViewFromUrl, persistView } = useTableState()
|
||||
|
||||
const [views, setViews] = useState([])
|
||||
const [draftViews, setDraftViews] = useState([])
|
||||
const [initialLoading, setInitialLoading] = useState(true)
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [activeTabKey, setActiveTabKey] = useState(ALL_TAB_KEY)
|
||||
const [isEditing, setIsEditing] = useState(false)
|
||||
|
||||
const editSnapshotRef = useRef([])
|
||||
const wasEditingRef = useRef(false)
|
||||
const isEditingRef = useRef(isEditing)
|
||||
const activeViewRef = useRef(null)
|
||||
const viewsStateRef = useRef({ views, draftViews, isEditing })
|
||||
const urlSyncedRef = useRef(false)
|
||||
isEditingRef.current = isEditing
|
||||
const apiRef = useRef({
|
||||
fetchObjectViews,
|
||||
createObjectView,
|
||||
updateObjectView,
|
||||
deleteObjectView
|
||||
})
|
||||
apiRef.current = {
|
||||
fetchObjectViews,
|
||||
createObjectView,
|
||||
updateObjectView,
|
||||
deleteObjectView
|
||||
}
|
||||
|
||||
const subscribedIdsRef = useRef([])
|
||||
const unsubscribesRef = useRef([])
|
||||
const subscribeToObjectTypeUpdatesRef = useRef(null)
|
||||
const updateEventHandlerRef = useRef()
|
||||
|
||||
const authReady = Boolean(token && authInitialized)
|
||||
const displayedViews = isEditing ? draftViews : views
|
||||
|
||||
const activeView = useMemo(() => {
|
||||
if (activeTabKey === ALL_TAB_KEY) return null
|
||||
const view =
|
||||
displayedViews.find((item) => String(item._id) === String(activeTabKey)) ||
|
||||
null
|
||||
if (view?._isDraft) {
|
||||
return { ...view, filter: view.filter || {}, sort: view.sort || {} }
|
||||
}
|
||||
return view
|
||||
}, [activeTabKey, displayedViews])
|
||||
|
||||
viewsStateRef.current = { views, draftViews, isEditing }
|
||||
activeViewRef.current = activeView
|
||||
|
||||
const applyViewToTable = useCallback(
|
||||
(tabKey) => {
|
||||
if (!tableRef?.current?.applyViewState) return
|
||||
|
||||
const { views: savedViews, draftViews: drafts, isEditing: editing } =
|
||||
viewsStateRef.current
|
||||
const list = editing ? drafts : savedViews
|
||||
const view =
|
||||
tabKey === ALL_TAB_KEY
|
||||
? null
|
||||
: list.find((item) => String(item._id) === String(tabKey)) || null
|
||||
|
||||
if (tabKey !== ALL_TAB_KEY && !view) return
|
||||
|
||||
if (editing) {
|
||||
tableRef.current.setListViewMasters?.({
|
||||
masterFilter: {},
|
||||
masterSort: {}
|
||||
})
|
||||
tableRef.current.applyViewState(
|
||||
view?.filter || {},
|
||||
view?.sort?.field ? view.sort : {}
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
tableRef.current.setListViewMasters?.({
|
||||
masterFilter: view?.filter || {},
|
||||
masterSort: view?.sort?.field ? view.sort : {}
|
||||
})
|
||||
tableRef.current.applyViewState(null, null)
|
||||
},
|
||||
[tableRef]
|
||||
)
|
||||
|
||||
const loadViews = useCallback(
|
||||
async (silent = false) => {
|
||||
if (!authReady || !objectType) return
|
||||
if (!silent) setInitialLoading(true)
|
||||
try {
|
||||
const { data } = await apiRef.current.fetchObjectViews(objectType)
|
||||
const nextViews = data || []
|
||||
setViews(nextViews)
|
||||
if (!isEditingRef.current) {
|
||||
setDraftViews(cloneViews(nextViews))
|
||||
}
|
||||
return nextViews
|
||||
} catch (error) {
|
||||
console.error('Error fetching object views:', error)
|
||||
return []
|
||||
} finally {
|
||||
if (!silent) setInitialLoading(false)
|
||||
}
|
||||
},
|
||||
[authReady, objectType]
|
||||
)
|
||||
|
||||
const loadViewsRef = useRef(loadViews)
|
||||
loadViewsRef.current = loadViews
|
||||
|
||||
useEffect(() => {
|
||||
urlSyncedRef.current = false
|
||||
setActiveTabKey(ALL_TAB_KEY)
|
||||
}, [objectType])
|
||||
|
||||
useEffect(() => {
|
||||
loadViews()
|
||||
}, [loadViews])
|
||||
|
||||
useEffect(() => {
|
||||
if (initialLoading) return
|
||||
applyViewToTable(activeTabKey)
|
||||
}, [activeTabKey, applyViewToTable, initialLoading, isEditing])
|
||||
|
||||
useEffect(() => {
|
||||
if (initialLoading || urlSyncedRef.current) return
|
||||
|
||||
const viewRef = getViewFromUrl()
|
||||
if (!viewRef) {
|
||||
urlSyncedRef.current = true
|
||||
return
|
||||
}
|
||||
|
||||
const matched =
|
||||
resolveViewFromRef(views, viewRef) ||
|
||||
resolveViewFromRef(draftViews, viewRef)
|
||||
|
||||
if (matched) {
|
||||
setActiveTabKey(String(matched._id))
|
||||
urlSyncedRef.current = true
|
||||
return
|
||||
}
|
||||
|
||||
// Wait until views have loaded before deciding the URL reference is invalid
|
||||
if (views.length === 0) return
|
||||
|
||||
if (!isEditing) {
|
||||
persistView(null)
|
||||
}
|
||||
|
||||
urlSyncedRef.current = true
|
||||
}, [
|
||||
initialLoading,
|
||||
views,
|
||||
draftViews,
|
||||
isEditing,
|
||||
getViewFromUrl,
|
||||
persistView
|
||||
])
|
||||
|
||||
const selectTab = useCallback(
|
||||
(tabKey) => {
|
||||
if (String(tabKey) === String(activeTabKey)) return
|
||||
|
||||
setActiveTabKey(tabKey)
|
||||
|
||||
if (tabKey === ALL_TAB_KEY) {
|
||||
persistView(null)
|
||||
return
|
||||
}
|
||||
|
||||
const view = (isEditing ? draftViews : views).find(
|
||||
(item) => String(item._id) === String(tabKey)
|
||||
)
|
||||
if (!view || view._isDraft) return
|
||||
|
||||
persistView(getObjectViewKey(view))
|
||||
},
|
||||
[activeTabKey, draftViews, isEditing, persistView, views]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isEditing && !wasEditingRef.current) {
|
||||
const snapshot = cloneViews(views)
|
||||
editSnapshotRef.current = snapshot
|
||||
setDraftViews(snapshot)
|
||||
}
|
||||
wasEditingRef.current = isEditing
|
||||
}, [isEditing, views])
|
||||
|
||||
const startEditing = useCallback(() => {
|
||||
const snapshot = cloneViews(views)
|
||||
editSnapshotRef.current = snapshot
|
||||
setDraftViews(snapshot)
|
||||
setIsEditing(true)
|
||||
}, [views])
|
||||
|
||||
const cancelEdits = useCallback(async () => {
|
||||
const snapshot = cloneViews(editSnapshotRef.current)
|
||||
setDraftViews(snapshot)
|
||||
setViews(snapshot)
|
||||
setIsEditing(false)
|
||||
|
||||
if (activeTabKey !== ALL_TAB_KEY) {
|
||||
const stillExists = snapshot.some(
|
||||
(view) => String(view._id) === String(activeTabKey)
|
||||
)
|
||||
if (!stillExists) {
|
||||
setActiveTabKey(ALL_TAB_KEY)
|
||||
persistView(null)
|
||||
applyViewToTable(ALL_TAB_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
await loadViewsRef.current(true)
|
||||
}, [activeTabKey, applyViewToTable, persistView])
|
||||
|
||||
const saveEdits = useCallback(async () => {
|
||||
setSaving(true)
|
||||
try {
|
||||
const originalById = new Map(views.map((view) => [String(view._id), view]))
|
||||
const draftById = new Map(draftViews.map((view) => [String(view._id), view]))
|
||||
|
||||
let newActiveId = activeTabKey
|
||||
|
||||
for (const draft of draftViews) {
|
||||
if (draft._isDraft) {
|
||||
const created = await apiRef.current.createObjectView({
|
||||
objectType,
|
||||
name: draft.name,
|
||||
color: draft.color,
|
||||
private: draft.private !== false,
|
||||
filter: draft.filter || {},
|
||||
sort: draft.sort || {}
|
||||
})
|
||||
if (String(activeTabKey) === String(draft._id) && created?._id) {
|
||||
newActiveId = created._id
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
const original = originalById.get(String(draft._id))
|
||||
if (!original) continue
|
||||
|
||||
const updates = {}
|
||||
if (draft.name !== original.name) updates.name = draft.name
|
||||
if (draft.color !== original.color) updates.color = draft.color
|
||||
if (draft.private !== original.private) updates.private = draft.private
|
||||
if (!viewStateEqual(draft.filter, original.filter)) {
|
||||
updates.filter = draft.filter || {}
|
||||
}
|
||||
if (!viewStateEqual(draft.sort, original.sort)) {
|
||||
updates.sort = draft.sort || {}
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await apiRef.current.updateObjectView(draft._id, updates)
|
||||
}
|
||||
}
|
||||
|
||||
for (const original of views) {
|
||||
if (!draftById.has(String(original._id))) {
|
||||
await apiRef.current.deleteObjectView(original._id)
|
||||
}
|
||||
}
|
||||
|
||||
const refreshed = (await loadViewsRef.current(true)) || []
|
||||
setDraftViews(cloneViews(refreshed))
|
||||
setIsEditing(false)
|
||||
|
||||
let resolvedTabKey = String(activeTabKey)
|
||||
|
||||
if (
|
||||
String(activeTabKey).startsWith('draft-') &&
|
||||
newActiveId &&
|
||||
String(newActiveId) !== String(activeTabKey)
|
||||
) {
|
||||
resolvedTabKey = String(newActiveId)
|
||||
}
|
||||
|
||||
const savedView =
|
||||
refreshed.find((view) => String(view._id) === resolvedTabKey) ||
|
||||
draftViews.find((view) => String(view._id) === resolvedTabKey)
|
||||
|
||||
if (resolvedTabKey !== ALL_TAB_KEY && savedView && !savedView._isDraft) {
|
||||
setActiveTabKey(resolvedTabKey)
|
||||
persistView(getObjectViewKey(savedView))
|
||||
} else if (resolvedTabKey !== ALL_TAB_KEY && !savedView) {
|
||||
resolvedTabKey = ALL_TAB_KEY
|
||||
setActiveTabKey(ALL_TAB_KEY)
|
||||
persistView(null)
|
||||
}
|
||||
|
||||
message.success('Views saved')
|
||||
} catch (error) {
|
||||
console.error('Error saving object views:', error)
|
||||
message.error('Failed to save views')
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}, [
|
||||
activeTabKey,
|
||||
draftViews,
|
||||
objectType,
|
||||
persistView,
|
||||
views
|
||||
])
|
||||
|
||||
const handleTabEdit = useCallback(
|
||||
async (targetKeyOrEvent, action) => {
|
||||
if (action === 'add') {
|
||||
if (isEditing) {
|
||||
const tempView = {
|
||||
_id: `draft-${Date.now()}`,
|
||||
_isDraft: true,
|
||||
objectType,
|
||||
...DEFAULT_VIEW
|
||||
}
|
||||
setDraftViews((prev) => [...prev, tempView])
|
||||
const newKey = String(tempView._id)
|
||||
setActiveTabKey(newKey)
|
||||
applyViewToTable(newKey)
|
||||
return
|
||||
}
|
||||
|
||||
setSaving(true)
|
||||
try {
|
||||
const created = await apiRef.current.createObjectView({
|
||||
objectType,
|
||||
...DEFAULT_VIEW
|
||||
})
|
||||
if (created?._id) {
|
||||
const nextViews = [...views, created]
|
||||
setViews(nextViews)
|
||||
setDraftViews(cloneViews(nextViews))
|
||||
const newKey = String(created._id)
|
||||
setActiveTabKey(newKey)
|
||||
applyViewToTable(newKey)
|
||||
persistView(getObjectViewKey(created))
|
||||
} else {
|
||||
message.error('Failed to create view')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating object view:', error)
|
||||
message.error('Failed to create view')
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (!isEditing) return
|
||||
|
||||
const targetKey =
|
||||
typeof targetKeyOrEvent === 'string' ? targetKeyOrEvent : null
|
||||
if (action === 'remove' && targetKey && targetKey !== ALL_TAB_KEY) {
|
||||
const isActiveDeleted = String(activeTabKey) === String(targetKey)
|
||||
const previousKey = isActiveDeleted
|
||||
? getPreviousTabKey(draftViews, targetKey)
|
||||
: null
|
||||
|
||||
setDraftViews((prev) =>
|
||||
prev.filter((view) => String(view._id) !== String(targetKey))
|
||||
)
|
||||
|
||||
if (isActiveDeleted) {
|
||||
setActiveTabKey(previousKey)
|
||||
if (previousKey === ALL_TAB_KEY) {
|
||||
persistView(null)
|
||||
} else {
|
||||
const view = draftViews.find(
|
||||
(item) => String(item._id) === String(previousKey)
|
||||
)
|
||||
if (view && !view._isDraft) {
|
||||
persistView(getObjectViewKey(view))
|
||||
}
|
||||
}
|
||||
applyViewToTable(previousKey)
|
||||
}
|
||||
}
|
||||
},
|
||||
[
|
||||
activeTabKey,
|
||||
applyViewToTable,
|
||||
draftViews,
|
||||
isEditing,
|
||||
objectType,
|
||||
persistView,
|
||||
views
|
||||
]
|
||||
)
|
||||
|
||||
const updateDraftView = useCallback((viewId, changes) => {
|
||||
setDraftViews((prev) =>
|
||||
prev.map((view) =>
|
||||
String(view._id) === String(viewId) ? { ...view, ...changes } : view
|
||||
)
|
||||
)
|
||||
}, [])
|
||||
|
||||
const reorderDraftViews = useCallback((fromValue, toValue, insertBefore) => {
|
||||
if (!isEditing) return
|
||||
|
||||
setDraftViews((prev) => {
|
||||
const fromIndex = prev.findIndex(
|
||||
(view) => String(view._id) === String(fromValue)
|
||||
)
|
||||
const toIndex = prev.findIndex(
|
||||
(view) => String(view._id) === String(toValue)
|
||||
)
|
||||
if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) {
|
||||
return prev
|
||||
}
|
||||
|
||||
let targetIndex = insertBefore ? toIndex : toIndex + 1
|
||||
if (fromIndex < targetIndex) {
|
||||
targetIndex -= 1
|
||||
}
|
||||
if (fromIndex === targetIndex) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const next = [...prev]
|
||||
const [moved] = next.splice(fromIndex, 1)
|
||||
next.splice(targetIndex, 0, moved)
|
||||
return next
|
||||
})
|
||||
}, [isEditing])
|
||||
|
||||
const mergeViewUpdate = useCallback(
|
||||
(viewId, updatedData) => {
|
||||
const mergeOne = (prev) =>
|
||||
prev.map((view) =>
|
||||
String(view._id) === String(viewId) ? { ...view, ...updatedData } : view
|
||||
)
|
||||
|
||||
setViews(mergeOne)
|
||||
if (!isEditing) {
|
||||
setDraftViews(mergeOne)
|
||||
}
|
||||
},
|
||||
[isEditing]
|
||||
)
|
||||
|
||||
const removeView = useCallback(
|
||||
(viewId) => {
|
||||
const list = isEditing ? draftViews : views
|
||||
const isActiveDeleted = String(activeTabKey) === String(viewId)
|
||||
const previousKey = isActiveDeleted
|
||||
? getPreviousTabKey(list, viewId)
|
||||
: null
|
||||
|
||||
setViews((prev) => prev.filter((view) => String(view._id) !== String(viewId)))
|
||||
if (!isEditing) {
|
||||
setDraftViews((prev) =>
|
||||
prev.filter((view) => String(view._id) !== String(viewId))
|
||||
)
|
||||
}
|
||||
|
||||
if (isActiveDeleted) {
|
||||
setActiveTabKey(previousKey)
|
||||
if (previousKey === ALL_TAB_KEY) {
|
||||
persistView(null)
|
||||
} else {
|
||||
const view = list.find(
|
||||
(item) => String(item._id) === String(previousKey)
|
||||
)
|
||||
if (view && !view._isDraft) {
|
||||
persistView(getObjectViewKey(view))
|
||||
}
|
||||
}
|
||||
applyViewToTable(previousKey)
|
||||
}
|
||||
},
|
||||
[activeTabKey, applyViewToTable, draftViews, isEditing, persistView, views]
|
||||
)
|
||||
|
||||
const handleFilterSortChange = useCallback((filter, sorter) => {
|
||||
if (!isEditingRef.current) return
|
||||
|
||||
const view = activeViewRef.current
|
||||
if (!view) return
|
||||
|
||||
const nextFilter = filter || {}
|
||||
const nextSort = sorter || {}
|
||||
|
||||
const updateInList = (list) =>
|
||||
list.map((item) =>
|
||||
String(item._id) === String(view._id)
|
||||
? { ...item, filter: nextFilter, sort: nextSort }
|
||||
: item
|
||||
)
|
||||
|
||||
activeViewRef.current = {
|
||||
...view,
|
||||
filter: nextFilter,
|
||||
sort: nextSort
|
||||
}
|
||||
|
||||
setDraftViews((prev) => updateInList(prev))
|
||||
viewsStateRef.current = {
|
||||
...viewsStateRef.current,
|
||||
draftViews: updateInList(viewsStateRef.current.draftViews)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const viewMatchesType = useCallback(
|
||||
(view) => view?.objectType === objectType,
|
||||
[objectType]
|
||||
)
|
||||
|
||||
const updateEventHandler = useCallback(
|
||||
(id, updatedData) => {
|
||||
const merged = { _id: id, ...updatedData }
|
||||
if (!viewMatchesType(merged)) {
|
||||
removeView(id)
|
||||
return
|
||||
}
|
||||
mergeViewUpdate(id, updatedData)
|
||||
},
|
||||
[mergeViewUpdate, removeView, viewMatchesType]
|
||||
)
|
||||
|
||||
updateEventHandlerRef.current = updateEventHandler
|
||||
|
||||
const subscriptionFilter = useMemo(
|
||||
() => ({ objectType }),
|
||||
[objectType]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (connected !== true || !objectType || !authReady) return
|
||||
|
||||
const unsubscribe = subscribeToObjectTypeUpdates(
|
||||
'objectView',
|
||||
subscriptionFilter,
|
||||
() => {
|
||||
loadViewsRef.current(true)
|
||||
}
|
||||
)
|
||||
subscribeToObjectTypeUpdatesRef.current = unsubscribe
|
||||
|
||||
return () => {
|
||||
if (unsubscribe) unsubscribe()
|
||||
if (subscribeToObjectTypeUpdatesRef.current === unsubscribe) {
|
||||
subscribeToObjectTypeUpdatesRef.current = null
|
||||
}
|
||||
}
|
||||
}, [
|
||||
authReady,
|
||||
connected,
|
||||
objectType,
|
||||
subscribeToObjectTypeUpdates,
|
||||
subscriptionFilter
|
||||
])
|
||||
|
||||
const subscribedViewIds = useMemo(
|
||||
() => views.map((view) => view._id).filter(Boolean),
|
||||
[views]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (connected !== true) return
|
||||
|
||||
const newViewIds = subscribedViewIds.filter(
|
||||
(id) => !subscribedIdsRef.current.includes(id)
|
||||
)
|
||||
|
||||
newViewIds.forEach((itemId) => {
|
||||
const unsubscribe = subscribeToObjectUpdates(
|
||||
itemId?.toLowerCase(),
|
||||
'objectView',
|
||||
(updateData) => updateEventHandlerRef.current(itemId, updateData)
|
||||
)
|
||||
subscribedIdsRef.current.push(itemId)
|
||||
if (unsubscribe) {
|
||||
unsubscribesRef.current.push(unsubscribe)
|
||||
}
|
||||
})
|
||||
|
||||
const viewIdsToUnsubscribe = subscribedIdsRef.current.filter(
|
||||
(id) => !subscribedViewIds.includes(id)
|
||||
)
|
||||
|
||||
viewIdsToUnsubscribe.forEach((itemId) => {
|
||||
const index = subscribedIdsRef.current.indexOf(itemId)
|
||||
if (index > -1) {
|
||||
subscribedIdsRef.current.splice(index, 1)
|
||||
const unsubscribe = unsubscribesRef.current[index]
|
||||
if (unsubscribe) {
|
||||
unsubscribe()
|
||||
}
|
||||
unsubscribesRef.current.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}, [connected, subscribeToObjectUpdates, subscribedViewIds])
|
||||
|
||||
useEffect(
|
||||
() => () => {
|
||||
unsubscribesRef.current.forEach((unsubscribe) => {
|
||||
if (unsubscribe) unsubscribe()
|
||||
})
|
||||
unsubscribesRef.current = []
|
||||
subscribedIdsRef.current = []
|
||||
|
||||
if (subscribeToObjectTypeUpdatesRef.current) {
|
||||
subscribeToObjectTypeUpdatesRef.current()
|
||||
subscribeToObjectTypeUpdatesRef.current = null
|
||||
}
|
||||
},
|
||||
[]
|
||||
)
|
||||
|
||||
const handleFilterSortChangeRef = useRef(handleFilterSortChange)
|
||||
handleFilterSortChangeRef.current = handleFilterSortChange
|
||||
|
||||
const stableFilterSortHandlerRef = useRef((filter, sorter) => {
|
||||
handleFilterSortChangeRef.current?.(filter, sorter)
|
||||
})
|
||||
|
||||
const lastSyncedViewKeyRef = useRef(null)
|
||||
|
||||
const masterFilter = useMemo(() => {
|
||||
if (isEditing || !activeView) return {}
|
||||
return activeView.filter || {}
|
||||
}, [activeView, isEditing])
|
||||
|
||||
const masterSort = useMemo(() => {
|
||||
if (isEditing || !activeView?.sort?.field) return {}
|
||||
return activeView.sort
|
||||
}, [activeView, isEditing])
|
||||
|
||||
useEffect(() => {
|
||||
const viewKey = isEditing
|
||||
? `edit:${activeView?._id ?? activeTabKey}`
|
||||
: activeView?._id != null
|
||||
? String(activeView._id)
|
||||
: activeTabKey === ALL_TAB_KEY
|
||||
? 'all'
|
||||
: null
|
||||
|
||||
if (viewKey === lastSyncedViewKeyRef.current) return
|
||||
lastSyncedViewKeyRef.current = viewKey
|
||||
|
||||
onViewStateChange?.({
|
||||
activeView: isEditing ? activeViewRef.current : null,
|
||||
masterFilter,
|
||||
masterSort,
|
||||
isEditing,
|
||||
handleFilterSortChange: isEditing
|
||||
? stableFilterSortHandlerRef.current
|
||||
: null
|
||||
})
|
||||
}, [
|
||||
activeTabKey,
|
||||
activeView?._id,
|
||||
isEditing,
|
||||
masterFilter,
|
||||
masterSort,
|
||||
onViewStateChange
|
||||
])
|
||||
|
||||
const viewTabSignatures = useMemo(
|
||||
() => displayedViews.map(getViewTabSignature).join('|'),
|
||||
[displayedViews]
|
||||
)
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
objectType,
|
||||
ALL_TAB_KEY,
|
||||
views: displayedViews,
|
||||
activeView,
|
||||
activeTabKey,
|
||||
masterFilter,
|
||||
masterSort,
|
||||
initialLoading,
|
||||
saving,
|
||||
isEditing,
|
||||
selectTab,
|
||||
startEditing,
|
||||
saveEdits,
|
||||
cancelEdits,
|
||||
handleTabEdit,
|
||||
updateDraftView,
|
||||
reorderDraftViews,
|
||||
mergeViewUpdate,
|
||||
removeView,
|
||||
handleFilterSortChange,
|
||||
reloadViews: () => loadViewsRef.current(true),
|
||||
viewTabSignatures
|
||||
}),
|
||||
[
|
||||
objectType,
|
||||
displayedViews,
|
||||
activeView,
|
||||
activeTabKey,
|
||||
masterFilter,
|
||||
masterSort,
|
||||
initialLoading,
|
||||
saving,
|
||||
isEditing,
|
||||
selectTab,
|
||||
startEditing,
|
||||
saveEdits,
|
||||
cancelEdits,
|
||||
handleTabEdit,
|
||||
updateDraftView,
|
||||
reorderDraftViews,
|
||||
mergeViewUpdate,
|
||||
removeView,
|
||||
handleFilterSortChange,
|
||||
viewTabSignatures
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<ObjectListViewContext.Provider value={value}>
|
||||
{children}
|
||||
</ObjectListViewContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useObjectListView = () => {
|
||||
const context = useContext(ObjectListViewContext)
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useObjectListView must be used within an ObjectListViewProvider'
|
||||
)
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
ObjectListViewProvider.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
objectType: PropTypes.string.isRequired,
|
||||
tableRef: PropTypes.object,
|
||||
onViewStateChange: PropTypes.func
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export { ALL_TAB_KEY }
|
||||
|
||||
export default ObjectListViewContext
|
||||
@ -12,6 +12,7 @@ const TableStateContext = createContext()
|
||||
|
||||
export const FILTER_URL_PARAM = 'filter'
|
||||
export const SORT_URL_PARAM = 'sort'
|
||||
export const VIEW_URL_PARAM = 'view'
|
||||
|
||||
const getSessionFilterKey = (scope) => `tableState:${scope}:filter`
|
||||
const getSessionSortKey = (scope) => `tableState:${scope}:sort`
|
||||
@ -44,6 +45,8 @@ const readSortFromUrl = (searchParams) => {
|
||||
return { field: parsed.field, order: parsed.order }
|
||||
}
|
||||
|
||||
const readViewFromUrl = (searchParams) => searchParams.get(VIEW_URL_PARAM) || null
|
||||
|
||||
const readFilterFromSession = (scope) => {
|
||||
try {
|
||||
return parseJsonParam(sessionStorage.getItem(getSessionFilterKey(scope)))
|
||||
@ -128,6 +131,24 @@ export const TableStateProvider = ({ children }) => {
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
const getViewFromUrl = useCallback(
|
||||
() => readViewFromUrl(searchParams),
|
||||
[searchParams]
|
||||
)
|
||||
|
||||
const persistView = useCallback(
|
||||
(viewRef) => {
|
||||
const next = new URLSearchParams(searchParams)
|
||||
if (viewRef) {
|
||||
next.set(VIEW_URL_PARAM, viewRef)
|
||||
} else {
|
||||
next.delete(VIEW_URL_PARAM)
|
||||
}
|
||||
setSearchParams(next, { replace: true })
|
||||
},
|
||||
[searchParams, setSearchParams]
|
||||
)
|
||||
|
||||
const persistFilter = useCallback(
|
||||
(
|
||||
scope,
|
||||
@ -256,6 +277,8 @@ export const TableStateProvider = ({ children }) => {
|
||||
() => ({
|
||||
getPersistedFilter,
|
||||
getPersistedSorter,
|
||||
getViewFromUrl,
|
||||
persistView,
|
||||
persistFilter,
|
||||
persistSort,
|
||||
persistTableState,
|
||||
@ -269,6 +292,8 @@ export const TableStateProvider = ({ children }) => {
|
||||
[
|
||||
getPersistedFilter,
|
||||
getPersistedSorter,
|
||||
getViewFromUrl,
|
||||
persistView,
|
||||
persistFilter,
|
||||
persistSort,
|
||||
persistTableState,
|
||||
|
||||
@ -171,11 +171,27 @@ export const ThemeProvider = ({ children }) => {
|
||||
'--layout-modal-bg',
|
||||
isDarkMode ? '#1f1f1f' : '#ffffff'
|
||||
)
|
||||
root.style.setProperty(
|
||||
'--color-background',
|
||||
isDarkMode ? '#000000' : '#ffffff'
|
||||
)
|
||||
root.style.setProperty('--color-text', isDarkMode ? '#ffffff' : '#000000')
|
||||
root.style.setProperty(
|
||||
'--color-descriptions-border',
|
||||
isDarkMode ? 'rgba(253,253,253,0.12)' : 'rgba(5,5,5,0.06)'
|
||||
)
|
||||
root.style.setProperty(
|
||||
'--color-list-view-tabs-border',
|
||||
isDarkMode ? '#2a2a2a' : '#E7E7E7'
|
||||
)
|
||||
root.style.setProperty(
|
||||
'--color-button-background',
|
||||
isDarkMode ? '#141414' : '#FFFFFF'
|
||||
)
|
||||
root.style.setProperty(
|
||||
'--color-button-border',
|
||||
isDarkMode ? '#424242' : '#d9d9d9'
|
||||
)
|
||||
}, [isDarkMode, primaryColorOverride])
|
||||
|
||||
const themeConfig = {
|
||||
|
||||
@ -110,7 +110,7 @@ export const DocumentPrinter = {
|
||||
],
|
||||
sorters: [
|
||||
'name',
|
||||
'documentSize',
|
||||
'currentDocumentSize',
|
||||
'connectedAt',
|
||||
'connection.port',
|
||||
'updatedAt',
|
||||
@ -261,15 +261,47 @@ export const DocumentPrinter = {
|
||||
},
|
||||
columnWidth: 85
|
||||
},
|
||||
{
|
||||
name: 'connection.username',
|
||||
label: 'Username',
|
||||
type: 'text',
|
||||
required: false,
|
||||
visible: (objectData) => objectData?.connection?.interface === 'cups',
|
||||
columnWidth: 150
|
||||
},
|
||||
{
|
||||
name: 'connection.password',
|
||||
label: 'Password',
|
||||
type: 'secret',
|
||||
required: false,
|
||||
visible: (objectData) => objectData?.connection?.interface === 'cups',
|
||||
columnWidth: 150
|
||||
},
|
||||
{
|
||||
name: 'currentDocumentSize',
|
||||
label: 'Document Size',
|
||||
label: 'Current Document Size',
|
||||
required: false,
|
||||
type: 'object',
|
||||
objectType: 'documentSize',
|
||||
showHyperlink: true,
|
||||
columnWidth: 200
|
||||
},
|
||||
{
|
||||
name: 'rotateOrientation',
|
||||
label: 'Rotate Orientation',
|
||||
required: false,
|
||||
type: 'bool',
|
||||
columnWidth: 150
|
||||
},
|
||||
{
|
||||
name: 'supportedDocumentSizes',
|
||||
label: 'Supported Document Sizes',
|
||||
required: false,
|
||||
type: 'objectList',
|
||||
objectType: 'documentSize',
|
||||
showHyperlink: true,
|
||||
columnWidth: 260
|
||||
},
|
||||
{
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user