Add InfoActionButtons to Various Dashboard Components
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

- Integrated InfoActionButtons into multiple components across the Finance and Inventory sections, enhancing user interaction and providing contextual actions for invoices, payment policies, payments, tax records, and various inventory items.
- Updated the respective components to include the new buttons with appropriate object types and list mode settings, improving the overall functionality and user experience in the dashboard.
This commit is contained in:
Tom Butcher 2026-09-14 23:33:03 +01:00
parent 8adf2d7847
commit eea7e1f724
67 changed files with 434 additions and 73 deletions

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const Invoices = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='invoice' />
<InfoActionButtons type='invoice' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const PaymentPolicies = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='paymentPolicy' />
<InfoActionButtons type='paymentPolicy' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const Payments = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='payment' />
<InfoActionButtons type='payment' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const TaxRecords = () => {
updateCollapseState={setColumnVisibility}
/>
<ExportListButton objectType='taxRecord' />
<InfoActionButtons type='taxRecord' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -15,6 +15,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -56,6 +57,7 @@ const FilamentStocks = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='filamentStock' />
<InfoActionButtons type='filamentStock' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const OrderItems = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='orderItem' />
<InfoActionButtons type='orderItem' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -15,6 +15,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -56,6 +57,7 @@ const PartStocks = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='partStock' />
<InfoActionButtons type='partStock' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -16,6 +16,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -57,6 +58,7 @@ const ProductStocks = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='productStock' />
<InfoActionButtons type='productStock' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const PurchaseOrders = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='purchaseOrder' />
<InfoActionButtons type='purchaseOrder' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const Shipments = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='shipment' />
<InfoActionButtons type='shipment' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -15,6 +15,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -56,6 +57,7 @@ const StockAudits = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='stockAudit' />
<InfoActionButtons type='stockAudit' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const StockEvents = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='stockEvent' />
<InfoActionButtons type='stockEvent' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const StockLocations = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='stockLocation' />
<InfoActionButtons type='stockLocation' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const StockTransfers = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='stockTransfer' />
<InfoActionButtons type='stockTransfer' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import SortSidebarButton from '../common/SortSidebarButton'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const AppPasswords = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='appPassword' />
<InfoActionButtons type='appPassword' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import FilterSidebarButton from '../common/FilterSidebarButton'
import SortSidebarButton from '../common/SortSidebarButton'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import ObjectTableViewButton from '../common/ObjectTableViewButton'
@ -49,6 +50,7 @@ const AuditLogs = () => {
updateVisibleState={updateColumnVisibility}
/>
<ExportListButton objectType='auditLog' />
<InfoActionButtons type='auditLog' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const CourierServices = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='courierService' />
<InfoActionButtons type='courierService' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const Couriers = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='courier' />
<InfoActionButtons type='courier' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const DocumentJobs = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='documentJob' />
<InfoActionButtons type='documentJob' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -8,6 +8,7 @@ import { ApiServerContext } from '../../context/ApiServerContext'
import { useCallback, useContext, useEffect, useRef, useState } from 'react'
import { Modal } from 'antd'
import dayjs from 'dayjs'
import { toTemplateObjectData } from '../../utils/templateObjectData'
const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
const {
@ -125,7 +126,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
}}
>
<TemplatePreview
objectData={objectData?.object}
objectData={toTemplateObjectData(objectData?.objects)}
documentTemplate={objectData?.documentTemplate}
/>
</div>
@ -158,7 +159,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
downloadTemplate(
objectData.documentTemplate._id,
objectData.documentTemplate.content,
objectData.object,
toTemplateObjectData(objectData.objects),
fileName,
'pdf',
() => {
@ -175,7 +176,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
downloadTemplate(
objectData.documentTemplate._id,
objectData.documentTemplate.content,
objectData.object,
toTemplateObjectData(objectData.objects),
fileName,
'png',
() => {
@ -192,7 +193,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
downloadTemplate(
objectData.documentTemplate._id,
objectData.documentTemplate.content,
objectData.object,
toTemplateObjectData(objectData.objects),
fileName,
'jpeg',
() => {
@ -209,7 +210,7 @@ const NewDocumentJob = ({ onOk, defaultValues = {} }) => {
downloadTemplate(
objectData.documentTemplate._id,
objectData.documentTemplate.content,
objectData.object,
toTemplateObjectData(objectData.objects),
fileName,
'svg',
() => {

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const DocumentPrinters = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='documentPrinter' />
<InfoActionButtons type='documentPrinter' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const DocumentSizes = () => {
updateCollapseState={setColumnVisibility}
/>
<ExportListButton objectType='documentSize' />
<InfoActionButtons type='documentSize' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const DocumentTemplates = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='documentTemplate' />
<InfoActionButtons type='documentTemplate' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const EmailAccounts = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='emailAccount' />
<InfoActionButtons type='emailAccount' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const EmailMessages = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='emailMessage' />
<InfoActionButtons type='emailMessage' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -14,7 +14,8 @@ import WizardView from '../../common/WizardView'
import TemplatePreview from '../../common/TemplatePreview'
import ProgressDisplay from '../../common/ProgressDisplay'
import { ApiServerContext } from '../../context/ApiServerContext'
import { resolveEmailRecipients } from '../../utils/emailRecipients'
import { resolveEmailRecipientsForObjects } from '../../utils/emailRecipients'
import { toTemplateObjectData } from '../../utils/templateObjectData'
const progressByState = {
queued: 10,
@ -46,9 +47,13 @@ const EmailWizardContent = ({
return
}
let cancelled = false
resolveEmailRecipients({
resolveEmailRecipientsForObjects({
type: objectData?.objectType,
objectData: objectData?.object,
objects: Array.isArray(objectData?.objects)
? objectData.objects
: objectData?.object
? [objectData.object]
: [],
fetchObject
}).then((result) => {
if (!cancelled) setCandidates(result)
@ -60,6 +65,7 @@ const EmailWizardContent = ({
defaultCandidates,
fetchObject,
objectData?.object,
objectData?.objects,
objectData?.objectType
])
@ -110,7 +116,7 @@ const EmailWizardContent = ({
visibleProperties={{
name: true,
objectType: true,
object: true,
objects: true,
emailTemplate: true,
emailAccount: true,
recipientEmail: true,
@ -142,7 +148,7 @@ const EmailWizardContent = ({
}}
>
<TemplatePreview
objectData={objectData?.object}
objectData={toTemplateObjectData(objectData?.objects)}
template={objectData?.emailTemplate}
templateType='emailTemplate'
capabilities={{

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const EmailTemplates = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='emailTemplate' />
<InfoActionButtons type='emailTemplate' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const FilamentSkus = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='filamentSku' />
<InfoActionButtons type='filamentSku' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import ObjectTableViewButton from '../common/ObjectTableViewButton'
import FilterSidebarButton from '../common/FilterSidebarButton'
import SortSidebarButton from '../common/SortSidebarButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -58,6 +59,7 @@ const Filaments = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='filament' />
<InfoActionButtons type='filament' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -50,6 +51,7 @@ const Files = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='file' />
<InfoActionButtons type='file' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -7,6 +7,7 @@ import { Flex, Space } from 'antd'
import useColumnVisibility from '../hooks/useColumnVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -57,6 +58,7 @@ const Hosts = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='host' />
<InfoActionButtons type='host' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import SortSidebarButton from '../common/SortSidebarButton'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const Materials = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='material' />
<InfoActionButtons type='material' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const NoteTypes = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='noteType' />
<InfoActionButtons type='noteType' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -53,6 +54,7 @@ const PartSkus = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='partSku' />
<InfoActionButtons type='partSku' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -18,6 +18,7 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -57,6 +58,7 @@ const Parts = (filter) => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='part' />
<InfoActionButtons type='part' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const PermissionSettingsList = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='permissionSetting' />
<InfoActionButtons type='permissionSetting' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import SortSidebarButton from '../common/SortSidebarButton'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const ProductCategories = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='productCategory' />
<InfoActionButtons type='productCategory' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -54,6 +55,7 @@ const ProductSkus = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='productSku' />
<InfoActionButtons type='productSku' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -29,6 +29,7 @@ import SortSidebarButton from '../common/SortSidebarButton'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -320,6 +321,7 @@ const Products = () => {
onReload={() => tableRef.current?.reload()}
/>
<ExportListButton objectType='product' />
<InfoActionButtons type='product' listMode={true} />
<Popover
content={getViewDropdownItems()}
placement='bottomLeft'

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const StockAuditLevels = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='stockAuditLevel' />
<InfoActionButtons type='stockAuditLevel' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const TaxRates = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='taxRate' />
<InfoActionButtons type='taxRate' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const UserGroups = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='userGroup' />
<InfoActionButtons type='userGroup' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const Users = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='user' />
<InfoActionButtons type='user' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -50,6 +51,7 @@ const Vendors = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='vendor' />
<InfoActionButtons type='vendor' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -2,6 +2,7 @@ import { useRef } from 'react'
import { Flex, Space } from 'antd'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -49,6 +50,7 @@ const FilamentProfiles = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='filamentProfile' />
<InfoActionButtons type='filamentProfile' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -14,6 +14,7 @@ import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -55,6 +56,7 @@ const GCodeFiles = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='gcodeFile' />
<InfoActionButtons type='gcodeFile' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import ColumnViewButton from '../common/ColumnViewButton.jsx'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility.jsx'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton.jsx'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -53,6 +54,7 @@ const Jobs = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='job' />
<InfoActionButtons type='job' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -2,6 +2,7 @@ import { useRef } from 'react'
import { Flex, Space } from 'antd'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const PrinterProfiles = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='printerProfile' />
<InfoActionButtons type='printerProfile' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -7,6 +7,7 @@ import ObjectActions from '../common/ObjectActions'
import BulkObjectActions from '../common/BulkObjectActions'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -58,6 +59,7 @@ const Printers = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='printer' />
<InfoActionButtons type='printer' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -13,6 +13,7 @@ import ColumnViewButton from '../common/ColumnViewButton.jsx'
import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility.jsx'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ExportListButton from '../common/ExportListButton.jsx'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -53,6 +54,7 @@ const SubJobs = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='subJob' />
<InfoActionButtons type='subJob' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -51,6 +52,7 @@ const Clients = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='client' />
<InfoActionButtons type='client' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -48,6 +49,7 @@ const FulfillmentPolicies = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='fulfillmentPolicy' />
<InfoActionButtons type='fulfillmentPolicy' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const ListingVarients = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='listingVarient' />
<InfoActionButtons type='listingVarient' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const Listings = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='listing' />
<InfoActionButtons type='listing' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const Marketplaces = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='marketplace' />
<InfoActionButtons type='marketplace' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -47,6 +48,7 @@ const ReturnPolicies = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='returnPolicy' />
<InfoActionButtons type='returnPolicy' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -11,6 +11,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useSortSidebarVisibility from '../hooks/useSortSidebarVisibility'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import InfoActionButtons from '../common/InfoActionButtons'
import ListViewTabs from '../common/ListViewTabs'
import ListViewEditButtons from '../common/ListViewEditButtons'
import { ObjectListViewProvider } from '../context/ObjectListViewContext'
@ -52,6 +53,7 @@ const SalesOrders = () => {
updateVisibleState={setColumnVisibility}
/>
<ExportListButton objectType='salesOrder' />
<InfoActionButtons type='salesOrder' listMode={true} />
</Space>
<ListViewTabs />
<Space>

View File

@ -7,33 +7,39 @@ import {
useMemo,
useRef
} from 'react'
// import { getModelByName } from '../../../database/ObjectModels'
import DocumentPrinterIcon from '../../Icons/DocumentPrinterIcon'
import { Button, Dropdown, Modal } from 'antd'
import { Button, Dropdown, Modal, message } from 'antd'
import { ApiServerContext } from '../context/ApiServerContext'
import { TableStateContext } from '../context/TableStateContext'
import DocumentTemplateIcon from '../../Icons/DocumentTemplateIcon'
import NewDocumentJob from '../Management/DocumentJobs/NewDocumentJob'
import { AuthContext } from '../context/AuthContext'
import LoadingPleaseWaitModal from './LoadingPleaseWaitModal'
import { fetchAllObjectPages } from '../utils/fetchAllObjectPages'
import { resolveObjectsList } from '../utils/templateObjectData'
const DocumentPrintButton = ({
type,
objectData,
objects,
listMode = false,
disabled = false,
...buttonProps
}) => {
const {
fetchObjects,
connected,
subscribeToObjectUpdates,
subscribeToObjectTypeUpdates
} = useContext(ApiServerContext)
const { fetchObjects, connected, subscribeToObjectUpdates, subscribeToObjectTypeUpdates } =
useContext(ApiServerContext)
const tableState = useContext(TableStateContext)
const fetchObjectsRef = useRef(fetchObjects)
fetchObjectsRef.current = fetchObjects
const [documentTemplates, setDocumentTemplates] = useState([])
const [currentDocumentTemplate, setCurrentDocumentTemplate] = useState(null)
const [loading, setLoading] = useState(false)
const [listLoading, setListLoading] = useState(false)
const [newDocumentJobOpen, setNewDocumentJobOpen] = useState(false)
const [selectedObjects, setSelectedObjects] = useState(() =>
resolveObjectsList(objects, objectData)
)
const subscribedIdsRef = useRef([])
const unsubscribesRef = useRef([])
@ -42,6 +48,11 @@ const DocumentPrintButton = ({
const { token } = useContext(AuthContext)
const resolvedObjects = useMemo(
() => resolveObjectsList(objects, objectData),
[objects, objectData]
)
const subscriptionFilter = useMemo(
() => ({
objectType: type,
@ -69,7 +80,7 @@ const DocumentPrintButton = ({
try {
const result = await fetchObjectsRef.current('documentTemplate', {
filter: subscriptionFilter,
limit: 100 // Get more templates to show in dropdown
limit: 100
})
if (result && result.data) {
@ -89,13 +100,13 @@ const DocumentPrintButton = ({
const loadDocumentTemplatesRef = useRef(loadDocumentTemplates)
loadDocumentTemplatesRef.current = loadDocumentTemplates
// Stable key from objectData._id (excludes _isEditing so toggling edit mode doesn't trigger template reload)
const objectKey = useMemo(() => {
if (!objectData) return null
return objectData._id ?? objectData.id ?? null
}, [objectData])
if (listMode) return 'list'
const first = resolvedObjects[0]
if (!first) return null
return first._id ?? first.id ?? null
}, [listMode, resolvedObjects])
// Fetch document templates when component mounts or objectData, type or token changes
useEffect(() => {
loadDocumentTemplates()
}, [objectKey, token, type, loadDocumentTemplates])
@ -147,7 +158,9 @@ const DocumentPrintButton = ({
useEffect(() => {
if (connected !== true) return
const templateIds = documentTemplates.map((template) => template._id).filter(Boolean)
const templateIds = documentTemplates
.map((template) => template._id)
.filter(Boolean)
const newTemplateIds = templateIds.filter(
(id) => !subscribedIdsRef.current.includes(id)
@ -197,15 +210,40 @@ const DocumentPrintButton = ({
}
}, [])
// Handle template selection
const handleTemplateSelect = (template) => {
setCurrentDocumentTemplate(template)
setNewDocumentJobOpen(true)
// TODO: Implement the actual printing logic here
// This could open a print dialog, navigate to a print page, etc.
}
const handleTemplateSelect = useCallback(
async (template) => {
setCurrentDocumentTemplate(template)
if (listMode) {
setListLoading(true)
try {
const list = await fetchAllObjectPages({
fetchObjects: fetchObjectsRef.current,
type,
filter: tableState?.getObjectListFilter?.(type) || {},
sorter: tableState?.getObjectListSorter?.(type) || {}
})
if (!list.length) {
message.warning('No objects in this list to print')
return
}
setSelectedObjects(list)
setNewDocumentJobOpen(true)
} catch (error) {
console.error('Error fetching objects for document job:', error)
message.error('Failed to load objects for printing')
} finally {
setListLoading(false)
}
return
}
setSelectedObjects(resolvedObjects)
setNewDocumentJobOpen(true)
},
[listMode, resolvedObjects, tableState, type]
)
// Group templates by tag for nested dropdown menu; untagged templates at root
const menuItems = useMemo(() => {
const templatesByTag = new Map()
const untaggedTemplates = []
@ -228,9 +266,9 @@ const DocumentPrintButton = ({
}
for (const tag of templateTags) {
const templates = templatesByTag.get(tag) ?? []
templates.push(template)
templatesByTag.set(tag, templates)
const tagged = templatesByTag.get(tag) ?? []
tagged.push(template)
templatesByTag.set(tag, tagged)
}
}
@ -252,9 +290,14 @@ const DocumentPrintButton = ({
.map(toTemplateMenuItem)
return [...rootUntaggedItems, ...taggedMenuItems]
}, [documentTemplates])
}, [documentTemplates, handleTemplateSelect])
const unavailable =
disabled ||
loading ||
listLoading ||
(!listMode && resolvedObjects.length === 0)
// If no templates available, show disabled state
if (documentTemplates.length === 0 && !loading) {
return (
<Button
@ -274,16 +317,17 @@ const DocumentPrintButton = ({
loading: loading
}}
trigger={['hover']}
disabled={disabled || loading}
disabled={unavailable}
>
<Button
{...buttonProps}
icon={<DocumentPrinterIcon />}
disabled={disabled || loading}
loading={loading}
disabled={unavailable}
loading={loading || listLoading}
title={loading ? 'Loading templates...' : 'Print document'}
/>
</Dropdown>
<LoadingPleaseWaitModal open={listLoading} />
<Modal
open={newDocumentJobOpen}
onCancel={() => setNewDocumentJobOpen(false)}
@ -305,7 +349,7 @@ const DocumentPrintButton = ({
reset={!newDocumentJobOpen}
defaultValues={{
objectType: type,
object: objectData,
objects: selectedObjects,
documentTemplate: currentDocumentTemplate
}}
/>
@ -317,7 +361,9 @@ const DocumentPrintButton = ({
DocumentPrintButton.propTypes = {
type: PropTypes.string.isRequired,
disabled: PropTypes.bool,
objectData: PropTypes.object.isRequired
objectData: PropTypes.object,
objects: PropTypes.array,
listMode: PropTypes.bool
}
export default DocumentPrintButton

View File

@ -7,18 +7,30 @@ import {
useRef,
useState
} from 'react'
import { Button, Dropdown, Modal } from 'antd'
import { Button, Dropdown, Modal, message } from 'antd'
import { ApiServerContext } from '../context/ApiServerContext'
import { AuthContext } from '../context/AuthContext'
import { TableStateContext } from '../context/TableStateContext'
import MailIcon from '../../Icons/MailIcon'
import EmailTemplateIcon from '../../Icons/EmailTemplateIcon'
import NewEmailMessage from '../Management/EmailMessages/NewEmailMessage'
import {
getDefaultEmailRecipient,
resolveEmailRecipients
resolveEmailRecipients,
resolveEmailRecipientsForObjects
} from '../utils/emailRecipients'
import LoadingPleaseWaitModal from './LoadingPleaseWaitModal'
import { fetchAllObjectPages } from '../utils/fetchAllObjectPages'
import { resolveObjectsList } from '../utils/templateObjectData'
const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps }) => {
const EmailSendButton = ({
type,
objectData,
objects,
listMode = false,
disabled = false,
...buttonProps
}) => {
const {
fetchObject,
fetchObjects,
@ -27,16 +39,26 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
subscribeToObjectTypeUpdates
} = useContext(ApiServerContext)
const { token } = useContext(AuthContext)
const tableState = useContext(TableStateContext)
const [templates, setTemplates] = useState([])
const [recipients, setRecipients] = useState([])
const [selectedTemplate, setSelectedTemplate] = useState(null)
const [selectedObjects, setSelectedObjects] = useState(() =>
resolveObjectsList(objects, objectData)
)
const [open, setOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [listLoading, setListLoading] = useState(false)
const fetchObjectsRef = useRef(fetchObjects)
const fetchObjectRef = useRef(fetchObject)
fetchObjectsRef.current = fetchObjects
fetchObjectRef.current = fetchObject
const resolvedObjects = useMemo(
() => resolveObjectsList(objects, objectData),
[objects, objectData]
)
const filter = useMemo(
() => ({ objectType: type, global: false, active: true }),
[type]
@ -71,11 +93,15 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
}, [loadTemplates])
useEffect(() => {
if (listMode) {
setRecipients([])
return undefined
}
let cancelled = false
setRecipients([])
resolveEmailRecipients({
type,
objectData,
objectData: resolvedObjects[0],
fetchObject: (...args) => fetchObjectRef.current(...args)
}).then((result) => {
if (!cancelled) setRecipients(result)
@ -83,19 +109,14 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
return () => {
cancelled = true
}
}, [objectData, type])
}, [listMode, resolvedObjects, type])
useEffect(() => {
if (!connected) return undefined
return subscribeToObjectTypeUpdates('emailTemplate', filter, () =>
loadTemplates(true)
)
}, [
connected,
filter,
loadTemplates,
subscribeToObjectTypeUpdates
])
}, [connected, filter, loadTemplates, subscribeToObjectTypeUpdates])
useEffect(() => {
if (!connected) return undefined
@ -121,6 +142,50 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
return () => unsubscribes.forEach((unsubscribe) => unsubscribe?.())
}, [connected, matches, subscribeToObjectUpdates, templates])
const handleTemplateSelect = useCallback(
async (template) => {
setSelectedTemplate(template)
if (listMode) {
setListLoading(true)
try {
const list = await fetchAllObjectPages({
fetchObjects: fetchObjectsRef.current,
type,
filter: tableState?.getObjectListFilter?.(type) || {},
sorter: tableState?.getObjectListSorter?.(type) || {}
})
if (!list.length) {
message.warning('No objects in this list to email')
return
}
const nextRecipients = await resolveEmailRecipientsForObjects({
type,
objects: list,
fetchObject: (...args) => fetchObjectRef.current(...args)
})
if (!nextRecipients.length) {
message.warning('No email recipients available for these objects')
return
}
setSelectedObjects(list)
setRecipients(nextRecipients)
setOpen(true)
} catch (error) {
console.error('Error fetching objects for email:', error)
message.error('Failed to load objects for email')
} finally {
setListLoading(false)
}
return
}
setSelectedObjects(resolvedObjects)
setOpen(true)
},
[listMode, resolvedObjects, tableState, type]
)
const menuItems = useMemo(() => {
const byTag = new Map()
const untagged = []
@ -129,8 +194,7 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
label: template.name,
icon: <EmailTemplateIcon />,
onClick: () => {
setSelectedTemplate(template)
setOpen(true)
handleTemplateSelect(template)
}
})
@ -159,19 +223,28 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
.map(makeItem)
}))
]
}, [templates])
}, [handleTemplateSelect, templates])
const defaultRecipient = useMemo(
() => getDefaultEmailRecipient(recipients),
[recipients]
)
const unavailable = disabled || loading || !templates.length || !recipients.length
const title = !recipients.length
? 'No email recipients available for this object'
: !templates.length
const unavailable =
disabled ||
loading ||
listLoading ||
!templates.length ||
(!listMode && (!resolvedObjects.length || !recipients.length))
const title = listMode
? !templates.length
? 'No email templates available for this object type'
: 'Send email'
: !recipients.length
? 'No email recipients available for this object'
: !templates.length
? 'No email templates available for this object type'
: 'Send email'
return (
<>
@ -180,10 +253,11 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
{...buttonProps}
icon={<MailIcon />}
disabled={unavailable}
loading={loading}
loading={loading || listLoading}
title={title}
/>
</Dropdown>
<LoadingPleaseWaitModal open={listLoading} />
<Modal
open={open}
onCancel={() => setOpen(false)}
@ -195,7 +269,7 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
onOk={() => setOpen(false)}
defaultValues={{
objectType: type,
object: objectData,
objects: selectedObjects,
emailTemplate: selectedTemplate,
...defaultRecipient
}}
@ -208,7 +282,9 @@ const EmailSendButton = ({ type, objectData, disabled = false, ...buttonProps })
EmailSendButton.propTypes = {
type: PropTypes.string.isRequired,
objectData: PropTypes.object.isRequired,
objectData: PropTypes.object,
objects: PropTypes.array,
listMode: PropTypes.bool,
disabled: PropTypes.bool
}

View File

@ -25,7 +25,9 @@ const InfoActionButtons = (props) => {
InfoActionButtons.propTypes = {
type: PropTypes.string.isRequired,
disabled: PropTypes.bool,
objectData: PropTypes.object.isRequired
objectData: PropTypes.object,
objects: PropTypes.array,
listMode: PropTypes.bool
}
export default InfoActionButtons

View File

@ -0,0 +1,30 @@
import PropTypes from 'prop-types'
import { Modal, Space, Typography } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
const { Text } = Typography
const LoadingPleaseWaitModal = ({ open = false }) => (
<Modal
open={open}
className='loading-modal'
title={false}
height={20}
style={{ maxWidth: 220, top: '50%', transform: 'translateY(-50%)' }}
closable={false}
maskClosable={false}
footer={false}
zIndex={2000}
>
<Space size={'middle'}>
<LoadingOutlined />
<Text style={{ margin: 0 }}>Loading, please wait...</Text>
</Space>
</Modal>
)
LoadingPleaseWaitModal.propTypes = {
open: PropTypes.bool
}
export default LoadingPleaseWaitModal

View File

@ -10,7 +10,10 @@ import {
import { useSearchParams } from 'react-router-dom'
import PropTypes from 'prop-types'
const TableStateContext = createContext()
const TableStateContext = createContext(null)
// eslint-disable-next-line react-refresh/only-export-components
export { TableStateContext }
export const FILTER_URL_PARAM = 'filter'
export const SORT_URL_PARAM = 'sort'

View File

@ -79,6 +79,26 @@ export const resolveEmailRecipients = async ({
return candidates
}
export const resolveEmailRecipientsForObjects = async ({
type,
objects,
fetchObject
}) => {
const list = Array.isArray(objects) ? objects.filter(Boolean) : []
const merged = []
for (const objectData of list) {
const result = await resolveEmailRecipients({
type,
objectData,
fetchObject
})
for (const candidate of result) {
addCandidate(merged, candidate)
}
}
return merged
}
/** Prefer a client/vendor ref; otherwise use a plain email candidate. */
export const getDefaultEmailRecipient = (candidates = []) => {
if (!Array.isArray(candidates) || !candidates.length) return null

View File

@ -0,0 +1,41 @@
export async function fetchAllObjectPages({
fetchObjects,
type,
filter = {},
sorter = {},
limit = 25
}) {
if (!type || typeof fetchObjects !== 'function') return []
const all = []
let page = 1
let totalPages = 1
do {
const result = await fetchObjects(type, {
page,
limit,
filter,
sorter
})
if (!result || Array.isArray(result)) {
break
}
const data = Array.isArray(result.data) ? result.data : []
all.push(...data)
if (Number.isFinite(result.totalPages) && result.totalPages > 0) {
totalPages = result.totalPages
} else if (result.hasMore) {
totalPages = page + 1
} else {
totalPages = page
}
page += 1
} while (page <= totalPages)
return all
}

View File

@ -0,0 +1,21 @@
export function resolveObjectsList(objects, objectData) {
if (Array.isArray(objects) && objects.length) {
return objects.filter(Boolean)
}
if (objectData) {
return [objectData]
}
return []
}
export function toTemplateObjectData(objects) {
const list = Array.isArray(objects) ? objects.filter(Boolean) : []
if (!list.length) return {}
if (list.length === 1) {
const first = list[0]
if (first && typeof first === 'object' && !Array.isArray(first)) {
return first
}
}
return { objects: list }
}

View File

@ -166,7 +166,12 @@ export const DocumentJob = {
columnFixed: 'left',
value: (objectData) => {
if (objectData?.createdAt == undefined) {
return `${objectData?.documentTemplate?.name || 'No template'} ${dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')} (${objectData?.object?.name || objectData?.object?._id})`
const list = Array.isArray(objectData?.objects)
? objectData.objects
: []
const first = list[0]
const extra = list.length > 1 ? ` +${list.length - 1}` : ''
return `${objectData?.documentTemplate?.name || 'No template'} ${dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss')} (${first?.name || first?._id || 'no object'}${extra})`
}
}
},
@ -188,11 +193,11 @@ export const DocumentJob = {
type: 'objectType'
},
{
name: 'object',
label: 'Object',
name: 'objects',
label: 'Objects',
required: true,
columnWidth: 150,
type: 'object',
type: 'objectList',
objectType: (objectData) => {
return objectData?.objectType
},

View File

@ -220,9 +220,9 @@ export const EmailMessage = {
columnWidth: 180
},
{
name: 'object',
label: 'Object',
type: 'object',
name: 'objects',
label: 'Objects',
type: 'objectList',
objectType: (data) => data?.objectType,
required: true,
readOnly: readOnlyAfterCreate,