From ebcf959e85be86f57895a5e1b9d97c9cbea6d129 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sun, 13 Sep 2026 17:12:50 +0100 Subject: [PATCH] Add Bulk Object Actions to Management and Dashboard Components - Integrated BulkObjectActions component across various management and dashboard components for improved batch processing capabilities. - Updated components including Invoices, PaymentPolicies, Payments, TaxRecords, and multiple Inventory and Management sections to include bulk action functionality. - Enhanced user experience by allowing users to perform actions on multiple items simultaneously, streamlining workflows and improving efficiency. --- assets/icons/duplicateicon.svg | 11 + assets/stylesheets/App.css | 41 ++++ src/components/Dashboard/Finance/Invoices.jsx | 5 + .../Dashboard/Finance/PaymentPolicies.jsx | 5 + src/components/Dashboard/Finance/Payments.jsx | 5 + .../Dashboard/Finance/TaxRecords.jsx | 5 + .../Dashboard/Inventory/FilamentStocks.jsx | 5 + .../Dashboard/Inventory/OrderItems.jsx | 5 + .../Dashboard/Inventory/PartStocks.jsx | 5 + .../Dashboard/Inventory/ProductStocks.jsx | 5 + .../Dashboard/Inventory/PurchaseOrders.jsx | 5 + .../Dashboard/Inventory/Shipments.jsx | 5 + .../Dashboard/Inventory/StockAudits.jsx | 5 + .../Dashboard/Inventory/StockEvents.jsx | 5 + .../Dashboard/Inventory/StockLocations.jsx | 5 + .../Dashboard/Inventory/StockTransfers.jsx | 5 + .../Dashboard/Management/AppPasswords.jsx | 5 + .../Dashboard/Management/AuditLogs.jsx | 5 + .../Dashboard/Management/CourierServices.jsx | 5 + .../Dashboard/Management/Couriers.jsx | 5 + .../Dashboard/Management/DocumentJobs.jsx | 5 + .../Dashboard/Management/DocumentPrinters.jsx | 5 + .../Dashboard/Management/DocumentSizes.jsx | 5 + .../Management/DocumentTemplates.jsx | 5 + .../Dashboard/Management/EmailAccounts.jsx | 5 + .../Dashboard/Management/EmailMessages.jsx | 5 + .../Dashboard/Management/EmailTemplates.jsx | 5 + .../Dashboard/Management/FilamentSkus.jsx | 5 + .../Dashboard/Management/Filaments.jsx | 5 + src/components/Dashboard/Management/Files.jsx | 5 + src/components/Dashboard/Management/Hosts.jsx | 5 + .../Dashboard/Management/Materials.jsx | 5 + .../Dashboard/Management/NoteTypes.jsx | 5 + .../Dashboard/Management/PartSkus.jsx | 5 + src/components/Dashboard/Management/Parts.jsx | 5 + .../Management/PermissionSettings.jsx | 5 + .../Management/ProductCategories.jsx | 5 + .../Dashboard/Management/ProductSkus.jsx | 5 + .../Dashboard/Management/Products.jsx | 5 + .../Dashboard/Management/StockAuditLevels.jsx | 5 + .../Dashboard/Management/TaxRates.jsx | 5 + .../Dashboard/Management/UserGroups.jsx | 5 + src/components/Dashboard/Management/Users.jsx | 5 + .../Dashboard/Management/Vendors.jsx | 5 + .../Dashboard/Production/FilamentProfiles.jsx | 5 + .../Dashboard/Production/GCodeFiles.jsx | 5 + src/components/Dashboard/Production/Jobs.jsx | 5 + .../Dashboard/Production/PrinterProfiles.jsx | 5 + .../Dashboard/Production/Printers.jsx | 5 + .../Dashboard/Production/SubJobs.jsx | 5 + src/components/Dashboard/Sales/Clients.jsx | 5 + .../Dashboard/Sales/FulfillmentPolicies.jsx | 5 + .../Dashboard/Sales/ListingVarients.jsx | 5 + src/components/Dashboard/Sales/Listings.jsx | 5 + .../Dashboard/Sales/Marketplaces.jsx | 5 + .../Dashboard/Sales/ReturnPolicies.jsx | 5 + .../Dashboard/Sales/SalesOrders.jsx | 5 + .../Dashboard/common/BulkObjectActions.jsx | 196 ++++++++++++++++++ .../Dashboard/common/ObjectActions.jsx | 7 +- .../Dashboard/common/ObjectTable.jsx | 157 +++++++++++++- .../Dashboard/context/ApiServerContext.jsx | 32 +++ .../context/ObjectListViewContext.jsx | 13 +- src/components/Icons/DuplicateIcon.jsx | 6 + src/database/models/AppPassword.js | 29 +++ src/database/models/Client.js | 12 ++ src/database/models/Courier.js | 12 ++ src/database/models/CourierService.js | 12 ++ src/database/models/DocumentJob.js | 11 + src/database/models/DocumentPrinter.js | 29 +++ src/database/models/DocumentSize.js | 29 +++ src/database/models/DocumentTemplate.js | 29 +++ src/database/models/EmailAccount.js | 29 +++ src/database/models/EmailMessage.js | 11 + src/database/models/EmailTemplate.js | 29 +++ src/database/models/Filament.js | 12 ++ src/database/models/FilamentProfile.js | 12 ++ src/database/models/FilamentSku.js | 12 ++ src/database/models/FilamentStock.js | 12 ++ src/database/models/File.js | 1 + src/database/models/FulfillmentPolicy.js | 12 ++ src/database/models/GCodeFile.js | 29 +++ src/database/models/Host.js | 12 ++ src/database/models/Invoice.js | 12 ++ src/database/models/Job.js | 12 ++ src/database/models/Listing.js | 12 ++ src/database/models/ListingVarient.js | 12 ++ src/database/models/Marketplace.js | 12 ++ src/database/models/Material.js | 12 ++ src/database/models/NoteType.js | 29 +++ src/database/models/OrderItem.js | 12 ++ src/database/models/Part.js | 29 +++ src/database/models/PartSku.js | 12 ++ src/database/models/PartStock.js | 12 ++ src/database/models/Payment.js | 12 ++ src/database/models/PaymentPolicy.js | 12 ++ src/database/models/PermissionSetting.js | 12 ++ src/database/models/Printer.js | 29 +++ src/database/models/PrinterProfile.js | 12 ++ src/database/models/Product.js | 29 +++ src/database/models/ProductCategory.js | 12 ++ src/database/models/ProductSku.js | 12 ++ src/database/models/ProductStock.js | 12 ++ src/database/models/PurchaseOrder.js | 12 ++ src/database/models/ReturnPolicy.js | 12 ++ src/database/models/SalesOrder.js | 12 ++ src/database/models/Shipment.js | 12 ++ src/database/models/StockAudit.js | 12 ++ src/database/models/StockAuditLevel.js | 12 ++ src/database/models/StockLocation.js | 29 +++ src/database/models/StockTransfer.js | 12 ++ src/database/models/TaxRate.js | 12 ++ src/database/models/TaxRecord.js | 12 ++ src/database/models/UserGroup.js | 12 ++ src/database/models/Vendor.js | 12 ++ 114 files changed, 1534 insertions(+), 7 deletions(-) create mode 100644 assets/icons/duplicateicon.svg create mode 100644 src/components/Dashboard/common/BulkObjectActions.jsx create mode 100644 src/components/Icons/DuplicateIcon.jsx diff --git a/assets/icons/duplicateicon.svg b/assets/icons/duplicateicon.svg new file mode 100644 index 00000000..6eac6aa3 --- /dev/null +++ b/assets/icons/duplicateicon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/stylesheets/App.css b/assets/stylesheets/App.css index d92b0d38..a0d62271 100644 --- a/assets/stylesheets/App.css +++ b/assets/stylesheets/App.css @@ -1439,6 +1439,47 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton { flex-direction: column; } +.object-table-select-cell { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; +} + +.object-table-select-cell .object-table-row-checkbox, +.object-table-select-cell .object-table-row-icon { + position: absolute; + inset: 0; +} + +.object-table-select-cell .object-table-row-checkbox { + opacity: 0; + pointer-events: none; + transition: opacity 0.2s; +} + +.dashboard-table + .ant-table-row:hover + .object-table-select-cell + .object-table-row-checkbox, +.object-table-select-cell.object-table-select-cell-selected + .object-table-row-checkbox { + opacity: 1; + pointer-events: auto; +} + +.dashboard-table + .ant-table-row:hover + .object-table-select-cell + .object-table-row-icon, +.object-table-select-cell.object-table-select-cell-selected + .object-table-row-icon { + transition: opacity 0.2s; + opacity: 0; +} + .objectKanbanContainerWrapper { position: relative; width: 100%; diff --git a/src/components/Dashboard/Finance/Invoices.jsx b/src/components/Dashboard/Finance/Invoices.jsx index fb716014..2cc85d33 100644 --- a/src/components/Dashboard/Finance/Invoices.jsx +++ b/src/components/Dashboard/Finance/Invoices.jsx @@ -2,6 +2,7 @@ import { useRef } from 'react' import { Flex, Space } from 'antd' import ObjectTable from '../common/ObjectTable' import ObjectActions from '../common/ObjectActions' +import BulkObjectActions from '../common/BulkObjectActions' import useColumnVisibility from '../hooks/useColumnVisibility' import ObjectTableViewButton from '../common/ObjectTableViewButton' import FilterSidebarButton from '../common/FilterSidebarButton' @@ -31,6 +32,10 @@ const Invoices = () => { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + tableRef.current?.reload()} + /> { + const model = getModelByName(type) + const { userProfile } = useContext(AuthContext) + const { deleteObjects, fetchObjects } = useContext(ApiServerContext) + const { showSuccess, showError } = useMessageContext() + const { bulkSelection, clearBulkSelection } = useObjectListView() + const [activeAction, setActiveAction] = useState(null) + const [actionLoading, setActionLoading] = useState(false) + const [selectedObjects, setSelectedObjects] = useState([]) + const [selectionLoading, setSelectionLoading] = useState(false) + const fetchObjectsRef = useRef(fetchObjects) + fetchObjectsRef.current = fetchObjects + + const selectionKey = useMemo( + () => + JSON.stringify({ + filter: bulkSelection?.filter || {}, + masterFilter: bulkSelection?.masterFilter || {} + }), + [bulkSelection?.filter, bulkSelection?.masterFilter] + ) + + useEffect(() => { + if (!bulkSelection) { + setSelectedObjects([]) + setSelectionLoading(false) + return + } + + let cancelled = false + + const loadSelectedObjects = async () => { + setSelectionLoading(true) + try { + if (Array.isArray(bulkSelection.selectedObjects)) { + setSelectedObjects(bulkSelection.selectedObjects) + return + } + + const objects = [] + const filter = { + ...(bulkSelection.masterFilter || {}), + ...(bulkSelection.filter || {}) + } + let page = 1 + + while (!cancelled) { + const result = await fetchObjectsRef.current(type, { + page, + limit: 100, + filter + }) + objects.push(...(result?.data || [])) + if (!result?.hasMore) break + page += 1 + } + + if (!cancelled) setSelectedObjects(objects) + } catch (error) { + console.error(`Error loading selected ${model.labelPlural}:`, error) + if (!cancelled) setSelectedObjects([]) + } finally { + if (!cancelled) setSelectionLoading(false) + } + } + + loadSelectedObjects() + return () => { + cancelled = true + } + // selectionKey intentionally represents both selection filters. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectionKey, type]) + + const actions = useMemo( + () => + (model.actions || []).filter( + (action) => + action.bulk === true && + hasActionPermission(userProfile, model, action.name) + ), + [model, userProfile] + ) + + if (!bulkSelection || actions.length === 0) return null + + const isActionDisabled = (action) => { + if (selectionLoading || selectedObjects.length === 0) return true + if (typeof action.disabled === 'function') { + return selectedObjects + .map((objectData) => + action.disabled({ ...objectData, _user: userProfile }) + ) + .every(Boolean) + } + return action.disabled === true + } + + const menu = { + items: actions.map((action) => ({ + key: action.name, + label: action.label, + danger: action.danger === true, + icon: action.icon ? createElement(action.icon) : undefined, + disabled: isActionDisabled(action) + })), + onClick: ({ key }) => { + const action = actions.find((item) => item.name === key) + if (action) setActiveAction(action) + } + } + + const closeModal = () => { + if (!actionLoading) setActiveAction(null) + } + + const runBulkDelete = async () => { + setActionLoading(true) + try { + const result = await deleteObjects(type, { + filter: bulkSelection.filter || {}, + masterFilter: bulkSelection.masterFilter || {} + }) + const deletedCount = result?.deletedCount || 0 + const failedCount = result?.failedCount || 0 + + showSuccess( + `${deletedCount} ${deletedCount === 1 ? model.label.toLowerCase() : model.labelPlural.toLowerCase()} deleted successfully!` + ) + if (failedCount > 0) { + showError( + `${failedCount} ${failedCount === 1 ? model.label.toLowerCase() : model.labelPlural.toLowerCase()} could not be deleted.` + ) + } + setActiveAction(null) + clearBulkSelection() + onReload?.() + } catch (error) { + console.error(`Error deleting ${model.labelPlural.toLowerCase()}:`, error) + showError(`Failed to delete selected ${model.labelPlural.toLowerCase()}.`) + } finally { + setActionLoading(false) + } + } + + return ( + <> + + + + + + + + {activeAction?.name === 'delete' && ( + } + title={`Are you sure you want to delete the selected ${model.labelPlural.toLowerCase()}?`} + description='This will permanently delete every object matching the selection.' + onOk={runBulkDelete} + okText='Delete' + okLoading={actionLoading} + danger + /> + )} + + + ) +} + +BulkObjectActions.propTypes = { + type: PropTypes.string.isRequired, + onReload: PropTypes.func +} + +export default BulkObjectActions diff --git a/src/components/Dashboard/common/ObjectActions.jsx b/src/components/Dashboard/common/ObjectActions.jsx index 4155b121..fe7da762 100644 --- a/src/components/Dashboard/common/ObjectActions.jsx +++ b/src/components/Dashboard/common/ObjectActions.jsx @@ -185,7 +185,7 @@ const ObjectActions = ({ const navigate = useNavigate() const location = useLocation() const { showActionsModal } = useActionsModal() - const { setOnModalOk } = useActions() + const { setOnModalOk, setCurrentObject, setCurrentObjectType } = useActions() const { userProfile } = useContext(AuthContext) const onReloadRef = useRef(onReload) onReloadRef.current = onReload @@ -227,8 +227,11 @@ const ObjectActions = ({ const currentUrlWithActions = location.pathname + location.search - const openActionsModal = () => + const openActionsModal = () => { + setCurrentObject(objectData) + setCurrentObjectType(type) showActionsModal(id, type, objectData, pageName) + } const menu = { items: mapActionsToMenuItems( diff --git a/src/components/Dashboard/common/ObjectTable.jsx b/src/components/Dashboard/common/ObjectTable.jsx index 30f8d537..d80fa09e 100644 --- a/src/components/Dashboard/common/ObjectTable.jsx +++ b/src/components/Dashboard/common/ObjectTable.jsx @@ -19,7 +19,8 @@ import { Space, Form, Splitter, - Card + Card, + Checkbox } from 'antd' import { LoadingOutlined } from '@ant-design/icons' import PropTypes from 'prop-types' @@ -403,6 +404,13 @@ const ObjectTable = forwardRef( } const tableRef = useRef(null) const model = getModelByName(type) + const bulkActions = + model.actions?.filter( + (action) => + action.bulk === true && + hasActionPermission(userProfile, model, action.name) + ) || [] + const canBulkSelect = bulkActions.length > 0 && objectListView != null const activeFilterRef = useRef({}) const tableSorterRef = useRef({}) const listViewIdRef = useRef(listViewId) @@ -1123,6 +1131,100 @@ const ObjectTable = forwardRef( [effectiveFilter, resolvedMasterFilter] ) + const bulkSelection = objectListView?.bulkSelection + const selectedRowIds = useMemo( + () => bulkSelection?.selectedIds || [], + [bulkSelection?.selectedIds] + ) + const selectedRowIdSet = useMemo( + () => new Set(selectedRowIds.map((id) => String(id))), + [selectedRowIds] + ) + const selectionScopeKey = useMemo( + () => + JSON.stringify({ + type, + viewMode: viewMode.type, + filter: subscriptionFilter + }), + [subscriptionFilter, type, viewMode.type] + ) + const previousSelectionScopeKeyRef = useRef(selectionScopeKey) + + useEffect(() => { + if (previousSelectionScopeKeyRef.current === selectionScopeKey) return + previousSelectionScopeKeyRef.current = selectionScopeKey + objectListView?.clearBulkSelection?.() + }, [objectListView, selectionScopeKey]) + + const setExplicitSelection = useCallback( + (ids) => { + const uniqueIds = [...new Set(ids.map((id) => String(id)))] + if (uniqueIds.length === 0) { + objectListView?.clearBulkSelection?.() + return + } + objectListView?.setBulkSelection?.({ + allMatching: false, + selectedIds: uniqueIds, + selectedObjects: uniqueIds + .map((id) => + tableData.find((item) => String(item?._id) === String(id)) + ) + .filter(Boolean), + filter: { _id: uniqueIds.join('|') }, + masterFilter: {} + }) + }, + [objectListView, tableData] + ) + + const toggleRowSelection = useCallback( + (record, checked) => { + if (!record?._id || record.isSkeleton) return + const id = String(record._id) + if (bulkSelection?.allMatching) { + const loadedIds = tableData + .filter((item) => !item?.isSkeleton && item?._id != null) + .map((item) => String(item._id)) + setExplicitSelection( + checked ? loadedIds : loadedIds.filter((itemId) => itemId !== id) + ) + return + } + + const nextIds = checked + ? [...selectedRowIds, id] + : selectedRowIds.filter((itemId) => String(itemId) !== id) + setExplicitSelection(nextIds) + }, + [ + bulkSelection?.allMatching, + selectedRowIds, + setExplicitSelection, + tableData + ] + ) + + const toggleSelectAll = useCallback( + (checked) => { + if (!checked) { + objectListView?.clearBulkSelection?.() + return + } + objectListView?.setBulkSelection?.({ + allMatching: true, + selectedIds: [], + selectedObjects: tableData.filter( + (item) => !item?.isSkeleton && item?._id != null + ), + filter: effectiveFilter, + masterFilter: resolvedMasterFilter + }) + }, + [effectiveFilter, objectListView, resolvedMasterFilter, tableData] + ) + const tableFilterContextValue = useMemo( () => ({ filter: effectiveFilter, @@ -1760,12 +1862,59 @@ const ObjectTable = forwardRef( // Table columns from model properties const columnsWithSkeleton = [ { - title: lazyLoading ? : isCards ? model.icon : null, + title: + loading || lazyLoading ? ( +
+ +
+ ) : canBulkSelect ? ( +
+ 0 + } + onChange={(event) => toggleSelectAll(event.target.checked)} + aria-label={`Select all ${model.labelPlural || model.label}`} + /> +
+ ) : isCards ? ( + model.icon + ) : null, key: 'icon', width: 45, fixed: 'left', - render: () => { - return {createElement(model.icon)} + render: (_, record) => { + const selected = + bulkSelection?.allMatching === true || + selectedRowIdSet.has(String(record?._id)) + + if (!canBulkSelect || record?.isSkeleton) { + return {createElement(model.icon)} + } + + return ( + +
+ event.stopPropagation()} + onChange={(event) => + toggleRowSelection(record, event.target.checked) + } + className='object-table-row-checkbox' + aria-label={`Select ${record?.name || record?._reference || record?._id}`} + /> +
+ {createElement(model.icon)} +
+
+
+ ) } } ] diff --git a/src/components/Dashboard/context/ApiServerContext.jsx b/src/components/Dashboard/context/ApiServerContext.jsx index 9796ae4f..970c4f11 100644 --- a/src/components/Dashboard/context/ApiServerContext.jsx +++ b/src/components/Dashboard/context/ApiServerContext.jsx @@ -1641,6 +1641,37 @@ const ApiServerProvider = ({ children }) => { } } + const deleteObjects = async ( + type, + { filter = {}, masterFilter = {} } = {} + ) => { + const deleteUrl = `${config.backendUrl}/${getObjectEndpoint(type)}/delete` + logger.debug('Deleting objects by filter:', type, { + filter, + masterFilter + }) + try { + const response = await axios.delete(deleteUrl, { + params: { + filter: JSON.stringify(filter), + masterFilter: JSON.stringify(masterFilter) + }, + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } + }) + logger.debug('Objects deleted successfully') + return response.data + } catch (err) { + console.error(err) + showError(err, () => { + deleteObjects(type, { filter, masterFilter }) + }) + throw err + } + } + // Update filament information const createObject = async (type, value) => { const createUrl = `${config.backendUrl}/${getObjectEndpoint(type)}` @@ -2910,6 +2941,7 @@ const ApiServerProvider = ({ children }) => { getObjectFunction, sendObjectFunction, deleteObject, + deleteObjects, subscribeToObjectUpdates, subscribeToAllObjectUpdates, subscribeToObjectEvent, diff --git a/src/components/Dashboard/context/ObjectListViewContext.jsx b/src/components/Dashboard/context/ObjectListViewContext.jsx index c8836b22..4d41e3f5 100644 --- a/src/components/Dashboard/context/ObjectListViewContext.jsx +++ b/src/components/Dashboard/context/ObjectListViewContext.jsx @@ -144,6 +144,11 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => { const [isEditing, setIsEditing] = useState(false) const [viewSyncReady, setViewSyncReady] = useState(false) const [userViewModeOverride, setUserViewModeOverride] = useState(null) + const [bulkSelection, setBulkSelection] = useState(null) + + const clearBulkSelection = useCallback(() => { + setBulkSelection(null) + }, []) const editSnapshotRef = useRef([]) const wasEditingRef = useRef(false) @@ -295,6 +300,7 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => { setViewSyncReady(false) setViewsFetched(false) setActiveTabKey(ALL_TAB_KEY) + clearBulkSelection() const cached = readCachedViews(objectType) if (cached) { @@ -308,7 +314,7 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => { setDraftViews([]) setInitialLoading(true) } - }, [objectType]) + }, [objectType, clearBulkSelection]) useEffect(() => { loadViews() @@ -984,6 +990,9 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => { handleFilterSortChange, handleViewModeChange, userOverridesRef, + bulkSelection, + setBulkSelection, + clearBulkSelection, reloadViews: () => loadViewsRef.current(true), viewTabSignatures }), @@ -1013,6 +1022,8 @@ export const ObjectListViewProvider = ({ children, objectType, tableRef }) => { removeView, handleFilterSortChange, handleViewModeChange, + bulkSelection, + clearBulkSelection, viewTabSignatures ] ) diff --git a/src/components/Icons/DuplicateIcon.jsx b/src/components/Icons/DuplicateIcon.jsx new file mode 100644 index 00000000..37f5e275 --- /dev/null +++ b/src/components/Icons/DuplicateIcon.jsx @@ -0,0 +1,6 @@ +import Icon from '@ant-design/icons' +import CustomIconSvg from '../../../assets/icons/duplicateicon.svg?react' + +const DuplicateIcon = (props) => + +export default DuplicateIcon diff --git a/src/database/models/AppPassword.js b/src/database/models/AppPassword.js index fd120952..a91216d2 100644 --- a/src/database/models/AppPassword.js +++ b/src/database/models/AppPassword.js @@ -12,6 +12,9 @@ const RegenerateAppPasswordSecret = lazy( () => import('../../components/Dashboard/Management/AppPasswords/RegenerateAppPasswordSecret') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import AppPasswordIcon from '../../components/Icons/AppPasswordIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' @@ -20,6 +23,8 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import LockIcon from '../../components/Icons/LockIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const AppPassword = { name: 'appPassword', @@ -44,6 +49,16 @@ export const AppPassword = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'appPassword', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -111,6 +126,20 @@ export const AppPassword = { onOk }) } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/Client.js b/src/database/models/Client.js index b811ffa4..e1a9e82b 100644 --- a/src/database/models/Client.js +++ b/src/database/models/Client.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Client = { name: 'client', @@ -41,6 +42,16 @@ export const Client = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'client', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const Client = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Courier.js b/src/database/models/Courier.js index 44adc925..b3723280 100644 --- a/src/database/models/Courier.js +++ b/src/database/models/Courier.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Courier = { name: 'courier', @@ -41,6 +42,16 @@ export const Courier = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'courier', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const Courier = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/CourierService.js b/src/database/models/CourierService.js index 19f62746..bda1a57e 100644 --- a/src/database/models/CourierService.js +++ b/src/database/models/CourierService.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const CourierService = { name: 'courierService', @@ -43,6 +44,16 @@ export const CourierService = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'courierService', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const CourierService = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/DocumentJob.js b/src/database/models/DocumentJob.js index 3e904c54..6fdef4a3 100644 --- a/src/database/models/DocumentJob.js +++ b/src/database/models/DocumentJob.js @@ -16,6 +16,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import DocumentJobIcon from '../../components/Icons/DocumentJobIcon' import dayjs from 'dayjs' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const DocumentJob = { name: 'documentJob', @@ -40,6 +41,16 @@ export const DocumentJob = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'documentJob', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', diff --git a/src/database/models/DocumentPrinter.js b/src/database/models/DocumentPrinter.js index b0349299..01aa6554 100644 --- a/src/database/models/DocumentPrinter.js +++ b/src/database/models/DocumentPrinter.js @@ -8,6 +8,9 @@ const NewDocumentPrinter = lazy( () => import('../../components/Dashboard/Management/DocumentPrinters/NewDocumentPrinter') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -15,6 +18,8 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import DocumentPrinterIcon from '../../components/Icons/DocumentPrinterIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const DocumentPrinter = { name: 'documentPrinter', @@ -39,6 +44,16 @@ export const DocumentPrinter = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'documentPrinter', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -85,6 +100,20 @@ export const DocumentPrinter = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/DocumentSize.js b/src/database/models/DocumentSize.js index 80cfb4bc..0c4ae0e7 100644 --- a/src/database/models/DocumentSize.js +++ b/src/database/models/DocumentSize.js @@ -8,6 +8,9 @@ const NewDocumentSize = lazy( () => import('../../components/Dashboard/Management/DocumentSizes/NewDocumentSize') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -15,6 +18,8 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import DocumentSizeIcon from '../../components/Icons/DocumentSizeIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const DocumentSize = { name: 'documentSize', @@ -39,6 +44,16 @@ export const DocumentSize = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'documentSize', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -85,6 +100,20 @@ export const DocumentSize = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/DocumentTemplate.js b/src/database/models/DocumentTemplate.js index a75e5392..d4c8d085 100644 --- a/src/database/models/DocumentTemplate.js +++ b/src/database/models/DocumentTemplate.js @@ -8,6 +8,9 @@ const NewDocumentTemplate = lazy( () => import('../../components/Dashboard/Management/DocumentTemplates/NewDocumentTemplate') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -16,6 +19,8 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import DesignIcon from '../../components/Icons/DesignIcon' import DocumentTemplateIcon from '../../components/Icons/DocumentTemplateIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const DocumentTemplate = { name: 'documentTemplate', @@ -40,6 +45,16 @@ export const DocumentTemplate = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'documentTemplate', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -94,6 +109,20 @@ export const DocumentTemplate = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/EmailAccount.js b/src/database/models/EmailAccount.js index afd66b3a..6dc6cfe5 100644 --- a/src/database/models/EmailAccount.js +++ b/src/database/models/EmailAccount.js @@ -8,6 +8,9 @@ const NewEmailAccount = lazy( () => import('../../components/Dashboard/Management/EmailAccounts/NewEmailAccount') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -15,6 +18,8 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import ListIcon from '../../components/Icons/ListIcon' import EmailAccountIcon from '../../components/Icons/EmailAccountIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const EmailAccount = { name: 'emailAccount', @@ -40,6 +45,16 @@ export const EmailAccount = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'emailAccount', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -86,6 +101,20 @@ export const EmailAccount = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/EmailMessage.js b/src/database/models/EmailMessage.js index c66b58cc..5230a34a 100644 --- a/src/database/models/EmailMessage.js +++ b/src/database/models/EmailMessage.js @@ -4,6 +4,7 @@ import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import ListIcon from '../../components/Icons/ListIcon' import EmailMessageIcon from '../../components/Icons/EmailMessageIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' const EmailMessageInfo = lazy( () => @@ -36,6 +37,16 @@ export const EmailMessage = { content: (objectData, { onOk } = {}) => createElement(NewEmailMessage, { defaultValues: objectData, onOk }) }, + { + name: 'duplicate', + type: 'alias', + objectType: 'emailMessage', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', diff --git a/src/database/models/EmailTemplate.js b/src/database/models/EmailTemplate.js index 37a056a3..5125ea57 100644 --- a/src/database/models/EmailTemplate.js +++ b/src/database/models/EmailTemplate.js @@ -8,6 +8,9 @@ const NewEmailTemplate = lazy( () => import('../../components/Dashboard/Management/EmailTemplates/NewEmailTemplate') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -16,6 +19,8 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import DesignIcon from '../../components/Icons/DesignIcon' import ListIcon from '../../components/Icons/ListIcon' import EmailTemplateIcon from '../../components/Icons/EmailTemplateIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const EmailTemplate = { name: 'emailTemplate', @@ -41,6 +46,16 @@ export const EmailTemplate = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'emailTemplate', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -95,6 +110,20 @@ export const EmailTemplate = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/Filament.js b/src/database/models/Filament.js index cb264847..d9014001 100644 --- a/src/database/models/Filament.js +++ b/src/database/models/Filament.js @@ -17,6 +17,7 @@ import FilamentIcon from '../../components/Icons/FilamentIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Filament = { name: 'filament', @@ -41,6 +42,16 @@ export const Filament = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'filament', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -102,6 +113,7 @@ export const Filament = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/FilamentProfile.js b/src/database/models/FilamentProfile.js index 9899afbd..c848844e 100644 --- a/src/database/models/FilamentProfile.js +++ b/src/database/models/FilamentProfile.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const FilamentProfile = { name: 'filamentProfile', @@ -43,6 +44,16 @@ export const FilamentProfile = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'filamentProfile', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const FilamentProfile = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/FilamentSku.js b/src/database/models/FilamentSku.js index 5ec2e3e2..da42f00b 100644 --- a/src/database/models/FilamentSku.js +++ b/src/database/models/FilamentSku.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const FilamentSku = { name: 'filamentSku', @@ -43,6 +44,16 @@ export const FilamentSku = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'filamentSku', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const FilamentSku = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/FilamentStock.js b/src/database/models/FilamentStock.js index f94380b5..cbd14804 100644 --- a/src/database/models/FilamentStock.js +++ b/src/database/models/FilamentStock.js @@ -23,6 +23,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const FilamentStock = { name: 'filamentStock', @@ -47,6 +48,16 @@ export const FilamentStock = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'filamentStock', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -99,6 +110,7 @@ export const FilamentStock = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/File.js b/src/database/models/File.js index 7e777db7..131056c6 100644 --- a/src/database/models/File.js +++ b/src/database/models/File.js @@ -90,6 +90,7 @@ export const File = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/FulfillmentPolicy.js b/src/database/models/FulfillmentPolicy.js index eadcc22b..c0a04d43 100644 --- a/src/database/models/FulfillmentPolicy.js +++ b/src/database/models/FulfillmentPolicy.js @@ -20,6 +20,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' import { marketplaceSyncMappingsProperty } from './marketplaceMappings' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const FulfillmentPolicy = { name: 'fulfillmentPolicy', @@ -45,6 +46,16 @@ export const FulfillmentPolicy = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'fulfillmentPolicy', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -95,6 +106,7 @@ export const FulfillmentPolicy = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/GCodeFile.js b/src/database/models/GCodeFile.js index baa53733..9a7f0052 100644 --- a/src/database/models/GCodeFile.js +++ b/src/database/models/GCodeFile.js @@ -6,6 +6,9 @@ const GCodeFileInfo = lazy( const NewGCodeFile = lazy( () => import('../../components/Dashboard/Production/GCodeFiles/NewGCodeFile') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import DownloadIcon from '../../components/Icons/DownloadIcon' import PlusIcon from '../../components/Icons/PlusIcon' import EditIcon from '../../components/Icons/EditIcon' @@ -15,6 +18,8 @@ import GCodeFileIcon from '../../components/Icons/GCodeFileIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import EyeIcon from '../../components/Icons/EyeIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const GCodeFile = { name: 'gcodeFile', @@ -35,6 +40,16 @@ export const GCodeFile = { return createElement(NewGCodeFile, { defaultValues: objectData, onOk, reset: true }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'gcodeFile', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -97,6 +112,20 @@ export const GCodeFile = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/Host.js b/src/database/models/Host.js index 054acd13..c2a68a70 100644 --- a/src/database/models/Host.js +++ b/src/database/models/Host.js @@ -21,6 +21,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import OTPIcon from '../../components/Icons/OTPIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Host = { name: 'host', @@ -45,6 +46,16 @@ export const Host = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'host', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -107,6 +118,7 @@ export const Host = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Invoice.js b/src/database/models/Invoice.js index c7bfa130..04ce79f7 100644 --- a/src/database/models/Invoice.js +++ b/src/database/models/Invoice.js @@ -23,6 +23,7 @@ import EditIcon from '../../components/Icons/EditIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Invoice = { name: 'invoice', @@ -47,6 +48,16 @@ export const Invoice = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'invoice', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -99,6 +110,7 @@ export const Invoice = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Job.js b/src/database/models/Job.js index af852575..960feb30 100644 --- a/src/database/models/Job.js +++ b/src/database/models/Job.js @@ -21,6 +21,7 @@ import EditIcon from '../../components/Icons/EditIcon' import BinIcon from '../../components/Icons/BinIcon' import dayjs from 'dayjs' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Job = { name: 'job', @@ -45,6 +46,16 @@ export const Job = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'job', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -97,6 +108,7 @@ export const Job = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Listing.js b/src/database/models/Listing.js index 272df1f8..6972cf8f 100644 --- a/src/database/models/Listing.js +++ b/src/database/models/Listing.js @@ -23,6 +23,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Listing = { name: 'listing', @@ -47,6 +48,16 @@ export const Listing = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'listing', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -139,6 +150,7 @@ export const Listing = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/ListingVarient.js b/src/database/models/ListingVarient.js index bfbb7aee..2a4b1a43 100644 --- a/src/database/models/ListingVarient.js +++ b/src/database/models/ListingVarient.js @@ -27,6 +27,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const ListingVarient = { name: 'listingVarient', @@ -51,6 +52,16 @@ export const ListingVarient = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'listingVarient', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -135,6 +146,7 @@ export const ListingVarient = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Marketplace.js b/src/database/models/Marketplace.js index 6d07f810..04a73c78 100644 --- a/src/database/models/Marketplace.js +++ b/src/database/models/Marketplace.js @@ -47,6 +47,7 @@ import ReloadIcon from '../../components/Icons/ReloadIcon' import LinkIcon from '../../components/Icons/LinkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Marketplace = { name: 'marketplace', @@ -71,6 +72,16 @@ export const Marketplace = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'marketplace', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -271,6 +282,7 @@ export const Marketplace = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Material.js b/src/database/models/Material.js index cc4e069c..b91da3c4 100644 --- a/src/database/models/Material.js +++ b/src/database/models/Material.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Material = { name: 'material', @@ -41,6 +42,16 @@ export const Material = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'material', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const Material = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/NoteType.js b/src/database/models/NoteType.js index adb52e48..a1b0506f 100644 --- a/src/database/models/NoteType.js +++ b/src/database/models/NoteType.js @@ -6,6 +6,9 @@ const NoteTypeInfo = lazy( const NewNoteType = lazy( () => import('../../components/Dashboard/Management/NoteTypes/NewNoteType') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import NoteTypeIcon from '../../components/Icons/NoteTypeIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' @@ -13,6 +16,8 @@ import EditIcon from '../../components/Icons/EditIcon' import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const NoteType = { name: 'noteType', @@ -37,6 +42,16 @@ export const NoteType = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'noteType', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -83,6 +98,20 @@ export const NoteType = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/OrderItem.js b/src/database/models/OrderItem.js index ff5206dc..baa9ccc2 100644 --- a/src/database/models/OrderItem.js +++ b/src/database/models/OrderItem.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const OrderItem = { name: 'orderItem', @@ -41,6 +42,16 @@ export const OrderItem = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'orderItem', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const OrderItem = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Part.js b/src/database/models/Part.js index 20bf48da..be9f9c18 100644 --- a/src/database/models/Part.js +++ b/src/database/models/Part.js @@ -6,6 +6,9 @@ const PartInfo = lazy( const NewPart = lazy( () => import('../../components/Dashboard/Management/Parts/NewPart') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import EditIcon from '../../components/Icons/EditIcon' import PlusIcon from '../../components/Icons/PlusIcon' import CheckIcon from '../../components/Icons/CheckIcon' @@ -13,6 +16,8 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import PartIcon from '../../components/Icons/PartIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const Part = { name: 'part', @@ -37,6 +42,16 @@ export const Part = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'part', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -94,6 +109,20 @@ export const Part = { return !(objectData?._isEditing && objectData?._isEditing == true) }, objectData: (objectData) => ({ part: objectData }) + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/PartSku.js b/src/database/models/PartSku.js index 7a7273e1..563529c0 100644 --- a/src/database/models/PartSku.js +++ b/src/database/models/PartSku.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const PartSku = { name: 'partSku', @@ -41,6 +42,16 @@ export const PartSku = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'partSku', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const PartSku = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/PartStock.js b/src/database/models/PartStock.js index 7dc6278f..cb510a34 100644 --- a/src/database/models/PartStock.js +++ b/src/database/models/PartStock.js @@ -21,6 +21,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const PartStock = { name: 'partStock', @@ -45,6 +46,16 @@ export const PartStock = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'partStock', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -97,6 +108,7 @@ export const PartStock = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Payment.js b/src/database/models/Payment.js index 572fdec7..623372ab 100644 --- a/src/database/models/Payment.js +++ b/src/database/models/Payment.js @@ -29,6 +29,7 @@ import EditIcon from '../../components/Icons/EditIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Payment = { name: 'payment', @@ -53,6 +54,16 @@ export const Payment = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'payment', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -105,6 +116,7 @@ export const Payment = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/PaymentPolicy.js b/src/database/models/PaymentPolicy.js index 1c1f5510..59bcf224 100644 --- a/src/database/models/PaymentPolicy.js +++ b/src/database/models/PaymentPolicy.js @@ -20,6 +20,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' import { marketplaceSyncMappingsProperty } from './marketplaceMappings' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const PaymentPolicy = { name: 'paymentPolicy', @@ -45,6 +46,16 @@ export const PaymentPolicy = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'paymentPolicy', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -95,6 +106,7 @@ export const PaymentPolicy = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/PermissionSetting.js b/src/database/models/PermissionSetting.js index b1a30861..2ba3b7ad 100644 --- a/src/database/models/PermissionSetting.js +++ b/src/database/models/PermissionSetting.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const PermissionSetting = { name: 'permissionSetting', @@ -44,6 +45,16 @@ export const PermissionSetting = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'permissionSetting', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -94,6 +105,7 @@ export const PermissionSetting = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Printer.js b/src/database/models/Printer.js index d3e3869b..5309226a 100644 --- a/src/database/models/Printer.js +++ b/src/database/models/Printer.js @@ -25,6 +25,9 @@ const RestartMoonraker = lazy( () => import('../../components/Dashboard/Production/Printers/RestartMoonraker') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import PrinterIcon from '../../components/Icons/PrinterIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' @@ -39,6 +42,8 @@ import FilamentStockIcon from '../../components/Icons/FilamentStockIcon' import ControlIcon from '../../components/Icons/ControlIcon' import JobIcon from '../../components/Icons/JobIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const Printer = { name: 'printer', @@ -63,6 +68,16 @@ export const Printer = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'printer', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -292,6 +307,20 @@ export const Printer = { } } ] + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/PrinterProfile.js b/src/database/models/PrinterProfile.js index adef0ab8..f73b487a 100644 --- a/src/database/models/PrinterProfile.js +++ b/src/database/models/PrinterProfile.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' const THUMBNAIL_PROPERTIES = [ { @@ -308,6 +309,16 @@ export const PrinterProfile = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'printerProfile', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -358,6 +369,7 @@ export const PrinterProfile = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Product.js b/src/database/models/Product.js index caf49d6a..37defad9 100644 --- a/src/database/models/Product.js +++ b/src/database/models/Product.js @@ -6,6 +6,9 @@ const ProductInfo = lazy( const NewProduct = lazy( () => import('../../components/Dashboard/Management/Products/NewProduct') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import ProductIcon from '../../components/Icons/ProductIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' @@ -13,6 +16,8 @@ import EditIcon from '../../components/Icons/EditIcon' import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const Product = { name: 'product', @@ -37,6 +42,16 @@ export const Product = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'product', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -96,6 +111,20 @@ export const Product = { return !(objectData?._isEditing && objectData?._isEditing == true) }, objectData: (objectData) => ({ product: objectData }) + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/ProductCategory.js b/src/database/models/ProductCategory.js index b62b06f4..2cd14a8a 100644 --- a/src/database/models/ProductCategory.js +++ b/src/database/models/ProductCategory.js @@ -20,6 +20,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const ProductCategory = { name: 'productCategory', @@ -45,6 +46,16 @@ export const ProductCategory = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'productCategory', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -95,6 +106,7 @@ export const ProductCategory = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/ProductSku.js b/src/database/models/ProductSku.js index 234376a8..b4a50f85 100644 --- a/src/database/models/ProductSku.js +++ b/src/database/models/ProductSku.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const ProductSku = { name: 'productSku', @@ -43,6 +44,16 @@ export const ProductSku = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'productSku', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const ProductSku = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/ProductStock.js b/src/database/models/ProductStock.js index 7d1745a6..e0928961 100644 --- a/src/database/models/ProductStock.js +++ b/src/database/models/ProductStock.js @@ -23,6 +23,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const ProductStock = { name: 'productStock', @@ -47,6 +48,16 @@ export const ProductStock = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'productStock', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -99,6 +110,7 @@ export const ProductStock = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/PurchaseOrder.js b/src/database/models/PurchaseOrder.js index 5029608b..3ca6d383 100644 --- a/src/database/models/PurchaseOrder.js +++ b/src/database/models/PurchaseOrder.js @@ -31,6 +31,7 @@ import EditIcon from '../../components/Icons/EditIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const PurchaseOrder = { name: 'purchaseOrder', @@ -55,6 +56,16 @@ export const PurchaseOrder = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'purchaseOrder', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -107,6 +118,7 @@ export const PurchaseOrder = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/ReturnPolicy.js b/src/database/models/ReturnPolicy.js index 62ac568f..a0f3cae3 100644 --- a/src/database/models/ReturnPolicy.js +++ b/src/database/models/ReturnPolicy.js @@ -20,6 +20,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' import { marketplaceSyncMappingsProperty } from './marketplaceMappings' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const ReturnPolicy = { name: 'returnPolicy', @@ -45,6 +46,16 @@ export const ReturnPolicy = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'returnPolicy', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -95,6 +106,7 @@ export const ReturnPolicy = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/SalesOrder.js b/src/database/models/SalesOrder.js index f6e61885..3c2709f0 100644 --- a/src/database/models/SalesOrder.js +++ b/src/database/models/SalesOrder.js @@ -26,6 +26,7 @@ import EditIcon from '../../components/Icons/EditIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const SalesOrder = { name: 'salesOrder', @@ -50,6 +51,16 @@ export const SalesOrder = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'salesOrder', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -102,6 +113,7 @@ export const SalesOrder = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Shipment.js b/src/database/models/Shipment.js index 4b158579..08ee9635 100644 --- a/src/database/models/Shipment.js +++ b/src/database/models/Shipment.js @@ -26,6 +26,7 @@ import BinIcon from '../../components/Icons/BinIcon' import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Shipment = { name: 'shipment', @@ -50,6 +51,16 @@ export const Shipment = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'shipment', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -102,6 +113,7 @@ export const Shipment = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/StockAudit.js b/src/database/models/StockAudit.js index 9419ddcc..f7865e1c 100644 --- a/src/database/models/StockAudit.js +++ b/src/database/models/StockAudit.js @@ -22,6 +22,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const StockAudit = { name: 'stockAudit', @@ -46,6 +47,16 @@ export const StockAudit = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'stockAudit', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -99,6 +110,7 @@ export const StockAudit = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/StockAuditLevel.js b/src/database/models/StockAuditLevel.js index 585ea417..0962ea22 100644 --- a/src/database/models/StockAuditLevel.js +++ b/src/database/models/StockAuditLevel.js @@ -19,6 +19,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const StockAuditLevel = { name: 'stockAuditLevel', @@ -43,6 +44,16 @@ export const StockAuditLevel = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'stockAuditLevel', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -93,6 +104,7 @@ export const StockAuditLevel = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/StockLocation.js b/src/database/models/StockLocation.js index 7e2c7257..0c7b4f2b 100644 --- a/src/database/models/StockLocation.js +++ b/src/database/models/StockLocation.js @@ -8,6 +8,9 @@ const NewStockLocation = lazy( () => import('../../components/Dashboard/Inventory/StockLocations/NewStockLocation') ) +const DeleteObject = lazy( + () => import('../../components/Dashboard/common/DeleteObject') +) import StockLocationIcon from '../../components/Icons/StockLocationIcon' import PlusIcon from '../../components/Icons/PlusIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' @@ -15,6 +18,8 @@ import EditIcon from '../../components/Icons/EditIcon' import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' +import BinIcon from '../../components/Icons/BinIcon' export const StockLocation = { name: 'stockLocation', @@ -39,6 +44,16 @@ export const StockLocation = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'stockLocation', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -85,6 +100,20 @@ export const StockLocation = { visible: (objectData) => { return objectData?._isEditing && objectData?._isEditing == true } + }, + { type: 'divider' }, + { + name: 'delete', + bulk: true, + type: 'modal', + modalWidth: 520, + modalCentered: true, + label: 'Delete', + icon: BinIcon, + danger: true, + content: (objectData, { onOk } = {}) => { + return createElement(DeleteObject, { objectData, onOk }) + } } ], pages: [ diff --git a/src/database/models/StockTransfer.js b/src/database/models/StockTransfer.js index c07efff2..6c058f44 100644 --- a/src/database/models/StockTransfer.js +++ b/src/database/models/StockTransfer.js @@ -23,6 +23,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const StockTransfer = { name: 'stockTransfer', @@ -47,6 +48,16 @@ export const StockTransfer = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'stockTransfer', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -99,6 +110,7 @@ export const StockTransfer = { }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/TaxRate.js b/src/database/models/TaxRate.js index 89c71ba0..4b7c45e9 100644 --- a/src/database/models/TaxRate.js +++ b/src/database/models/TaxRate.js @@ -18,6 +18,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' import { marketplaceSyncMappingsProperty } from './marketplaceMappings' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const TaxRate = { name: 'taxRate', @@ -42,6 +43,16 @@ export const TaxRate = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'taxRate', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -92,6 +103,7 @@ export const TaxRate = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/TaxRecord.js b/src/database/models/TaxRecord.js index a632547f..96e7c805 100644 --- a/src/database/models/TaxRecord.js +++ b/src/database/models/TaxRecord.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const TaxRecord = { name: 'taxRecord', @@ -41,6 +42,16 @@ export const TaxRecord = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'taxRecord', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const TaxRecord = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/UserGroup.js b/src/database/models/UserGroup.js index 44f3992a..158a5c4a 100644 --- a/src/database/models/UserGroup.js +++ b/src/database/models/UserGroup.js @@ -18,6 +18,7 @@ import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import { calculateUserGroupPermissions } from '../permissions.js' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const UserGroup = { name: 'userGroup', @@ -42,6 +43,16 @@ export const UserGroup = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'userGroup', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -92,6 +103,7 @@ export const UserGroup = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true, diff --git a/src/database/models/Vendor.js b/src/database/models/Vendor.js index 780f116b..a165b617 100644 --- a/src/database/models/Vendor.js +++ b/src/database/models/Vendor.js @@ -17,6 +17,7 @@ import CheckIcon from '../../components/Icons/CheckIcon' import XMarkIcon from '../../components/Icons/XMarkIcon' import BinIcon from '../../components/Icons/BinIcon' import ListIcon from '../../components/Icons/ListIcon' +import DuplicateIcon from '../../components/Icons/DuplicateIcon' export const Vendor = { name: 'vendor', @@ -41,6 +42,16 @@ export const Vendor = { }) } }, + { + name: 'duplicate', + type: 'alias', + objectType: 'vendor', + aliasAction: 'new', + pageName: 'info', + label: 'Duplicate', + icon: DuplicateIcon, + objectData: (objectData) => objectData + }, { name: 'list', type: 'page', @@ -91,6 +102,7 @@ export const Vendor = { { type: 'divider' }, { name: 'delete', + bulk: true, type: 'modal', modalWidth: 520, modalCentered: true,