diff --git a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx
index 881a6bdeba..454225c5b5 100644
--- a/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx
+++ b/src/frontend/src/pages/Index/Settings/AdminCenter/Index.tsx
@@ -16,6 +16,7 @@ import {
IconListDetails,
IconMail,
IconPackages,
+ IconPhoto,
IconPlugConnected,
IconQrcode,
IconReport,
@@ -107,6 +108,10 @@ const SnippetTable = Loadable(
lazy(() => import('../../../../tables/settings/SnippetTable'))
);
+const AssetTable = Loadable(
+ lazy(() => import('../../../../tables/settings/AssetTable'))
+);
+
export default function AdminCenter() {
const user = useUserState();
@@ -231,6 +236,12 @@ export default function AdminCenter() {
icon: ,
content:
},
+ {
+ name: 'assets',
+ label: t`Report Assets`,
+ icon: ,
+ content:
+ },
{
name: 'location-types',
label: t`Location Types`,
@@ -283,7 +294,7 @@ export default function AdminCenter() {
{
id: 'reporting',
label: t`Reporting`,
- panelIDs: ['labels', 'reports', 'snippets']
+ panelIDs: ['labels', 'reports', 'snippets', 'assets']
},
{
id: 'plm',
diff --git a/src/frontend/src/tables/settings/AssetTable.tsx b/src/frontend/src/tables/settings/AssetTable.tsx
new file mode 100644
index 0000000000..a04ac10af0
--- /dev/null
+++ b/src/frontend/src/tables/settings/AssetTable.tsx
@@ -0,0 +1,124 @@
+import { AddItemButton } from '@lib/components/AddItemButton';
+import { type RowAction, RowDeleteAction } from '@lib/components/RowActions';
+import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
+import { apiUrl } from '@lib/functions/Api';
+import useTable from '@lib/hooks/UseTable';
+import type { ApiFormFieldSet } from '@lib/types/Forms';
+import type { TableColumn } from '@lib/types/Tables';
+import { t } from '@lingui/core/macro';
+import { Alert, Text } from '@mantine/core';
+import { IconInfoCircle } from '@tabler/icons-react';
+import { type ReactNode, useCallback, useMemo, useState } from 'react';
+import { AttachmentLink } from '../../components/items/AttachmentLink';
+import {
+ useCreateApiFormModal,
+ useDeleteApiFormModal
+} from '../../hooks/UseForm';
+import { useUserState } from '../../states/UserState';
+import { DescriptionColumn } from '../ColumnRenderers';
+import { InvenTreeTable } from '../InvenTreeTable';
+
+export type AssetI = {
+ pk: number;
+ asset: string;
+ description: string;
+};
+
+export default function AssetTable() {
+ const table = useTable('report-asset');
+ const user = useUserState();
+
+ const columns: TableColumn[] = useMemo(() => {
+ return [
+ {
+ accessor: 'asset',
+ title: t`Asset`,
+ sortable: false,
+ switchable: false,
+ render: (record: AssetI) => {
+ if (!record.asset) {
+ return '-';
+ }
+
+ return ;
+ },
+ noContext: true
+ },
+ DescriptionColumn({
+ accessor: 'description',
+ sortable: false,
+ switchable: false
+ })
+ ];
+ }, []);
+
+ const [selectedAsset, setSelectedAsset] = useState(-1);
+
+ const rowActions = useCallback(
+ (record: AssetI): RowAction[] => {
+ return [
+ RowDeleteAction({
+ hidden: !user.isStaff(),
+ onClick: () => {
+ setSelectedAsset(record.pk);
+ deleteAsset.open();
+ }
+ })
+ ];
+ },
+ [user]
+ );
+
+ const newAssetFields: ApiFormFieldSet = useMemo(() => {
+ return {
+ asset: {},
+ description: {}
+ };
+ }, []);
+
+ const deleteAsset = useDeleteApiFormModal({
+ url: ApiEndpoints.report_asset,
+ pk: selectedAsset,
+ title: t`Delete Asset`,
+ table: table
+ });
+
+ const newAsset = useCreateApiFormModal({
+ url: ApiEndpoints.report_asset,
+ title: t`Add Asset`,
+ fields: newAssetFields,
+ table: table
+ });
+
+ const tableActions: ReactNode[] = useMemo(() => {
+ return [
+ newAsset.open()}
+ tooltip={t`Add asset`}
+ hidden={!user.isStaff()}
+ />
+ ];
+ }, [user]);
+
+ return (
+ <>
+ {newAsset.modal}
+ {deleteAsset.modal}
+ } title={t`Assets`}>
+ {t`Assets are files (such as images) which can be used when rendering reports and labels.`}
+
+
+ >
+ );
+}