mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Render status labels (#5759)
* added deepsource coverage settings * Ignore missing coverage * trigger full CI run * typo * Added general status lookup endpoint * Bumped API version * cleaned up branch * Fixed PlaygroundArea accordion behaviour * Added dummy area for status labels * Added StatusRenderer skeleton * Fetch data from server * Made server api state session persistant * cleanup * Added StatusLabel lookups based on ModelType * Made use of translated status fields * Added new ModelTypes * Used new StatusRenderer * Simplified renderer * style fixes * revert style change * Squashed commit of the following: commit 5e8ea099068475fd257d8c172348dc6f3edf9bcf Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 09:22:38 2023 +0200 Update ui_plattform.spec.ts commit 49da3312beff7fd6837ea741e621df221c445d19 Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 07:56:25 2023 +0200 more logging commit 5337be4c3990051b805a6fce2e79ca4030b4afe5 Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 07:56:11 2023 +0200 added filter method for undefined settings that overwrite defaults commit 5df8a0b3e77cd5dcf04c39ad7638ac845df75e4c Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 03:05:06 2023 +0200 you do not need to string a string commit 0650d3b3a0132889c2a76de38db38224e974d205 Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 03:04:34 2023 +0200 fix things that were borken for no good reason commit a40dbfd1364cf01465037350184f59d2a2a8afab Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 02:39:34 2023 +0200 reduce unneeded blocking timeouts commit bf9046a5361ae919e70662e717d6156434b6fe43 Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 02:34:10 2023 +0200 catch server fetching errors commit aa01e67e8c8e789fdf755ac4481e730fe5ea4183 Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 02:33:29 2023 +0200 move init as things are now plugged together different commit 290c33bd3125d50779497d6fc5981d5813b58f5d Author: Matthias Mair <code@mjmair.com> Date: Tue Oct 24 01:49:32 2023 +0200 do not log a failed automatic login try - why would you?
This commit is contained in:
parent
2ff2c0801a
commit
53c16510a1
@ -2,11 +2,14 @@
|
||||
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 141
|
||||
INVENTREE_API_VERSION = 142
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v142 -> 2023-10-20: https://github.com/inventree/InvenTree/pull/5759
|
||||
- Adds generic API endpoints for looking up status models
|
||||
|
||||
v141 -> 2023-10-23 : https://github.com/inventree/InvenTree/pull/5774
|
||||
- Changed 'part.responsible' from User to Owner
|
||||
|
||||
|
@ -18,6 +18,7 @@ from rest_framework.views import APIView
|
||||
|
||||
import common.models
|
||||
import common.serializers
|
||||
from generic.states.api import AllStatusViews, StatusView
|
||||
from InvenTree.api import BulkDeleteMixin, MetadataView
|
||||
from InvenTree.config import CONFIG_LOOKUPS
|
||||
from InvenTree.filters import ORDER_FILTER, SEARCH_ORDER_FILTER
|
||||
@ -617,6 +618,14 @@ common_api_urls = [
|
||||
path('<str:key>/', FlagDetail.as_view(), name='api-flag-detail'),
|
||||
re_path(r'^.*$', FlagList.as_view(), name='api-flag-list'),
|
||||
])),
|
||||
|
||||
# Status
|
||||
path('generic/status/', include([
|
||||
path(f'<str:{StatusView.MODEL_REF}>/', include([
|
||||
path('', StatusView.as_view(), name='api-status'),
|
||||
])),
|
||||
path('', AllStatusViews.as_view(), name='api-status-all'),
|
||||
])),
|
||||
]
|
||||
|
||||
admin_api_urls = [
|
||||
|
@ -26,7 +26,7 @@ class StatusView(APIView):
|
||||
MODEL_REF = 'statusmodel'
|
||||
|
||||
def get_status_model(self, *args, **kwargs):
|
||||
"""Return the StatusCode moedl based on extra parameters passed to the view"""
|
||||
"""Return the StatusCode model based on extra parameters passed to the view"""
|
||||
status_model = self.kwargs.get(self.MODEL_REF, None)
|
||||
|
||||
if status_model is None:
|
||||
@ -50,3 +50,23 @@ class StatusView(APIView):
|
||||
}
|
||||
|
||||
return Response(data)
|
||||
|
||||
|
||||
class AllStatusViews(StatusView):
|
||||
"""Endpoint for listing all defined status models."""
|
||||
|
||||
permission_classes = [
|
||||
permissions.IsAuthenticated,
|
||||
]
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""Perform a GET request to learn information about status codes"""
|
||||
data = {}
|
||||
|
||||
for status_class in StatusCode.__subclasses__():
|
||||
data[status_class.__name__] = {
|
||||
'class': status_class.__name__,
|
||||
'values': status_class.dict(),
|
||||
}
|
||||
|
||||
return Response(data)
|
||||
|
@ -324,9 +324,9 @@ export function SearchDrawer({
|
||||
// Callback when one of the search results is clicked
|
||||
function onResultClick(query: ModelType, pk: number) {
|
||||
closeDrawer();
|
||||
navigate(
|
||||
ModelInformationDict[query].url_detail.replace(':pk', pk.toString())
|
||||
);
|
||||
const targetModel = ModelInformationDict[query];
|
||||
if (targetModel.url_detail == undefined) return;
|
||||
navigate(targetModel.url_detail.replace(':pk', pk.toString()));
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -46,11 +46,13 @@ const RendererLookup: EnumDictionary<
|
||||
[ModelType.partcategory]: RenderPartCategory,
|
||||
[ModelType.partparametertemplate]: RenderPartParameterTemplate,
|
||||
[ModelType.purchaseorder]: RenderPurchaseOrder,
|
||||
[ModelType.purchaseorderline]: RenderPurchaseOrder,
|
||||
[ModelType.returnorder]: RenderReturnOrder,
|
||||
[ModelType.salesorder]: RenderSalesOrder,
|
||||
[ModelType.salesordershipment]: RenderSalesOrderShipment,
|
||||
[ModelType.stocklocation]: RenderStockLocation,
|
||||
[ModelType.stockitem]: RenderStockItem,
|
||||
[ModelType.stockhistory]: RenderStockItem,
|
||||
[ModelType.supplierpart]: RenderSupplierPart,
|
||||
[ModelType.user]: RenderUser,
|
||||
[ModelType.manufacturerpart]: RenderPart
|
||||
|
@ -8,9 +8,11 @@ export enum ModelType {
|
||||
partparametertemplate = 'partparametertemplate',
|
||||
stockitem = 'stockitem',
|
||||
stocklocation = 'stocklocation',
|
||||
stockhistory = 'stockhistory',
|
||||
build = 'build',
|
||||
company = 'company',
|
||||
purchaseorder = 'purchaseorder',
|
||||
purchaseorderline = 'purchaseorderline',
|
||||
salesorder = 'salesorder',
|
||||
salesordershipment = 'salesordershipment',
|
||||
returnorder = 'returnorder',
|
||||
@ -23,8 +25,8 @@ export enum ModelType {
|
||||
interface ModelInformatonInterface {
|
||||
label: string;
|
||||
label_multiple: string;
|
||||
url_overview: string;
|
||||
url_detail: string;
|
||||
url_overview?: string;
|
||||
url_detail?: string;
|
||||
}
|
||||
|
||||
type ModelDictory = {
|
||||
@ -74,6 +76,10 @@ export const ModelInformationDict: ModelDictory = {
|
||||
url_overview: '/stocklocation',
|
||||
url_detail: '/stocklocation/:pk/'
|
||||
},
|
||||
stockhistory: {
|
||||
label: t`Stock History`,
|
||||
label_multiple: t`Stock Histories`
|
||||
},
|
||||
build: {
|
||||
label: t`Build`,
|
||||
label_multiple: t`Builds`,
|
||||
@ -92,6 +98,10 @@ export const ModelInformationDict: ModelDictory = {
|
||||
url_overview: '/purchaseorder',
|
||||
url_detail: '/purchaseorder/:pk/'
|
||||
},
|
||||
purchaseorderline: {
|
||||
label: t`Purchase Order Line`,
|
||||
label_multiple: t`Purchase Order Lines`
|
||||
},
|
||||
salesorder: {
|
||||
label: t`Sales Order`,
|
||||
label_multiple: t`Sales Orders`,
|
||||
|
96
src/frontend/src/components/renderers/StatusRenderer.tsx
Normal file
96
src/frontend/src/components/renderers/StatusRenderer.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import { Badge, MantineSize } from '@mantine/core';
|
||||
|
||||
import { colorMap } from '../../defaults/backendMappings';
|
||||
import { useServerApiState } from '../../states/ApiState';
|
||||
import { ModelType } from '../render/ModelType';
|
||||
|
||||
interface StatusCodeInterface {
|
||||
key: string;
|
||||
label: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface StatusCodeListInterface {
|
||||
[key: string]: StatusCodeInterface;
|
||||
}
|
||||
|
||||
interface renderStatusLabelOptionsInterface {
|
||||
size?: MantineSize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic function to render a status label
|
||||
*/
|
||||
function renderStatusLabel(
|
||||
key: string,
|
||||
codes: StatusCodeListInterface,
|
||||
options: renderStatusLabelOptionsInterface = {}
|
||||
) {
|
||||
let text = null;
|
||||
let color = null;
|
||||
|
||||
// Find the entry which matches the provided key
|
||||
for (let name in codes) {
|
||||
let entry = codes[name];
|
||||
|
||||
if (entry.key == key) {
|
||||
text = entry.label;
|
||||
color = entry.color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!text) {
|
||||
console.error(`renderStatusLabel could not find match for code ${key}`);
|
||||
}
|
||||
|
||||
// Fallbacks
|
||||
if (color == null) color = 'default';
|
||||
color = colorMap[color] || colorMap['default'];
|
||||
const size = options.size || 'xs';
|
||||
|
||||
if (!text) {
|
||||
text = key;
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge color={color} variant="filled" size={size}>
|
||||
{text}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
/*
|
||||
* Render the status for a object.
|
||||
* Uses the values specified in "status_codes.py"
|
||||
*/
|
||||
export const StatusRenderer = ({
|
||||
status,
|
||||
type,
|
||||
options
|
||||
}: {
|
||||
status: string;
|
||||
type: ModelType;
|
||||
options?: renderStatusLabelOptionsInterface;
|
||||
}) => {
|
||||
const [statusCodeList] = useServerApiState((state) => [state.status]);
|
||||
if (statusCodeList === undefined) {
|
||||
console.log('StatusRenderer: statusCodeList is undefined');
|
||||
return null;
|
||||
}
|
||||
const statusCodes = statusCodeList[type];
|
||||
if (statusCodes === undefined) {
|
||||
console.log('StatusRenderer: statusCodes is undefined');
|
||||
return null;
|
||||
}
|
||||
|
||||
return renderStatusLabel(status, statusCodes, options);
|
||||
};
|
||||
|
||||
/*
|
||||
* Render the status badge in a table
|
||||
*/
|
||||
export function TableStatusRenderer(
|
||||
type: ModelType
|
||||
): ((record: any) => any) | undefined {
|
||||
return (record: any) => StatusRenderer({ status: record.status, type: type });
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Progress, Text } from '@mantine/core';
|
||||
import { Progress } from '@mantine/core';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useTableRefresh } from '../../../hooks/TableRefresh';
|
||||
import { ApiPaths, apiUrl } from '../../../states/ApiState';
|
||||
import { ThumbnailHoverCard } from '../../images/Thumbnail';
|
||||
import { ModelType } from '../../render/ModelType';
|
||||
import { TableStatusRenderer } from '../../renderers/StatusRenderer';
|
||||
import { TableColumn } from '../Column';
|
||||
import { TableFilter } from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
@ -82,8 +84,8 @@ function buildOrderTableColumns(): TableColumn[] {
|
||||
accessor: 'status',
|
||||
sortable: true,
|
||||
title: t`Status`,
|
||||
switchable: true
|
||||
// TODO: Custom render function here (status label)
|
||||
switchable: true,
|
||||
render: TableStatusRenderer(ModelType.build)
|
||||
},
|
||||
{
|
||||
accessor: 'priority',
|
||||
|
@ -5,6 +5,8 @@ import { useMemo } from 'react';
|
||||
import { useTableRefresh } from '../../../hooks/TableRefresh';
|
||||
import { ApiPaths, apiUrl } from '../../../states/ApiState';
|
||||
import { Thumbnail } from '../../images/Thumbnail';
|
||||
import { ModelType } from '../../render/ModelType';
|
||||
import { StatusRenderer } from '../../renderers/StatusRenderer';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export function PurchaseOrderTable({ params }: { params?: any }) {
|
||||
@ -59,8 +61,12 @@ export function PurchaseOrderTable({ params }: { params?: any }) {
|
||||
accessor: 'status',
|
||||
title: t`Status`,
|
||||
sortable: true,
|
||||
switchable: true
|
||||
// TODO: Custom formatter
|
||||
switchable: true,
|
||||
render: (record: any) =>
|
||||
StatusRenderer({
|
||||
status: record.status,
|
||||
type: ModelType.purchaseorder
|
||||
})
|
||||
},
|
||||
{
|
||||
accessor: 'creation_date',
|
||||
|
@ -5,6 +5,8 @@ import { useMemo } from 'react';
|
||||
import { useTableRefresh } from '../../../hooks/TableRefresh';
|
||||
import { ApiPaths, apiUrl } from '../../../states/ApiState';
|
||||
import { Thumbnail } from '../../images/Thumbnail';
|
||||
import { ModelType } from '../../render/ModelType';
|
||||
import { TableStatusRenderer } from '../../renderers/StatusRenderer';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export function ReturnOrderTable({ params }: { params?: any }) {
|
||||
@ -58,8 +60,8 @@ export function ReturnOrderTable({ params }: { params?: any }) {
|
||||
accessor: 'status',
|
||||
title: t`Status`,
|
||||
sortable: true,
|
||||
switchable: true
|
||||
// TODO: Custom formatter
|
||||
switchable: true,
|
||||
render: TableStatusRenderer(ModelType.returnorder)
|
||||
}
|
||||
// TODO: Creation date
|
||||
// TODO: Target date
|
||||
|
@ -5,6 +5,8 @@ import { useMemo } from 'react';
|
||||
import { useTableRefresh } from '../../../hooks/TableRefresh';
|
||||
import { ApiPaths, apiUrl } from '../../../states/ApiState';
|
||||
import { Thumbnail } from '../../images/Thumbnail';
|
||||
import { ModelType } from '../../render/ModelType';
|
||||
import { TableStatusRenderer } from '../../renderers/StatusRenderer';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
export function SalesOrderTable({ params }: { params?: any }) {
|
||||
@ -59,8 +61,8 @@ export function SalesOrderTable({ params }: { params?: any }) {
|
||||
accessor: 'status',
|
||||
title: t`Status`,
|
||||
sortable: true,
|
||||
switchable: true
|
||||
// TODO: Custom formatter
|
||||
switchable: true,
|
||||
render: TableStatusRenderer(ModelType.salesorder)
|
||||
}
|
||||
|
||||
// TODO: Creation date
|
||||
|
@ -7,6 +7,8 @@ import { notYetImplemented } from '../../../functions/notifications';
|
||||
import { useTableRefresh } from '../../../hooks/TableRefresh';
|
||||
import { ApiPaths, apiUrl } from '../../../states/ApiState';
|
||||
import { Thumbnail } from '../../images/Thumbnail';
|
||||
import { ModelType } from '../../render/ModelType';
|
||||
import { TableStatusRenderer } from '../../renderers/StatusRenderer';
|
||||
import { TableColumn } from '../Column';
|
||||
import { TableFilter } from '../Filter';
|
||||
import { RowAction } from '../RowActions';
|
||||
@ -52,8 +54,8 @@ function stockItemTableColumns(): TableColumn[] {
|
||||
sortable: true,
|
||||
switchable: true,
|
||||
filter: true,
|
||||
title: t`Status`
|
||||
// TODO: Custom renderer for stock status label
|
||||
title: t`Status`,
|
||||
render: TableStatusRenderer(ModelType.stockitem)
|
||||
},
|
||||
{
|
||||
accessor: 'batch',
|
||||
|
29
src/frontend/src/defaults/backendMappings.tsx
Normal file
29
src/frontend/src/defaults/backendMappings.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { ModelType } from '../components/render/ModelType';
|
||||
|
||||
/* Lookup tables for mapping backend responses to internal types */
|
||||
|
||||
/**
|
||||
* List of status codes which are used in the backend
|
||||
* and the model type they are associated with
|
||||
*/
|
||||
export const statusCodeList: Record<string, ModelType> = {
|
||||
BuildStatus: ModelType.build,
|
||||
PurchaseOrderStatus: ModelType.purchaseorder,
|
||||
ReturnOrderLineStatus: ModelType.purchaseorderline,
|
||||
ReturnOrderStatus: ModelType.returnorder,
|
||||
SalesOrderStatus: ModelType.salesorder,
|
||||
StockHistoryCode: ModelType.stockhistory,
|
||||
StockStatus: ModelType.stockitem
|
||||
};
|
||||
|
||||
/*
|
||||
* Map the colors used in the backend to the colors used in the frontend
|
||||
*/
|
||||
export const colorMap: { [key: string]: string } = {
|
||||
dark: 'dark',
|
||||
warning: 'yellow',
|
||||
success: 'green',
|
||||
info: 'cyan',
|
||||
danger: 'red',
|
||||
default: 'gray'
|
||||
};
|
@ -1,13 +1,15 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Button } from '@mantine/core';
|
||||
import { Button, TextInput } from '@mantine/core';
|
||||
import { Group, Text } from '@mantine/core';
|
||||
import { Accordion } from '@mantine/core';
|
||||
import { ReactNode } from 'react';
|
||||
import { ReactNode, useState } from 'react';
|
||||
|
||||
import { ApiFormProps } from '../../components/forms/ApiForm';
|
||||
import { ApiFormChangeCallback } from '../../components/forms/fields/ApiFormField';
|
||||
import { PlaceholderPill } from '../../components/items/Placeholder';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import { ModelType } from '../../components/render/ModelType';
|
||||
import { StatusRenderer } from '../../components/renderers/StatusRenderer';
|
||||
import { openCreateApiForm, openEditApiForm } from '../../functions/forms';
|
||||
import {
|
||||
createPart,
|
||||
@ -60,6 +62,23 @@ function ApiFormsPlayground() {
|
||||
);
|
||||
}
|
||||
|
||||
// Show some example status labels
|
||||
function StatusLabelPlayground() {
|
||||
const [status, setStatus] = useState<string>('10');
|
||||
return (
|
||||
<>
|
||||
<Group>
|
||||
<Text>Stock Status</Text>
|
||||
<TextInput
|
||||
value={status}
|
||||
onChange={(event) => setStatus(event.currentTarget.value)}
|
||||
/>
|
||||
<StatusRenderer type={ModelType.stockitem} status={status} />
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
/** Construct a simple accordion group with title and content */
|
||||
function PlaygroundArea({
|
||||
title,
|
||||
@ -95,10 +114,11 @@ export default function Playground() {
|
||||
</Trans>
|
||||
</Text>
|
||||
<Accordion defaultValue="">
|
||||
<PlaygroundArea title="API Forms" content={<ApiFormsPlayground />} />
|
||||
<PlaygroundArea
|
||||
title="API Forms"
|
||||
content={<ApiFormsPlayground />}
|
||||
></PlaygroundArea>
|
||||
title="Status labels"
|
||||
content={<StatusLabelPlayground />}
|
||||
/>
|
||||
</Accordion>
|
||||
</>
|
||||
);
|
||||
|
@ -1,28 +1,52 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
import { api } from '../App';
|
||||
import { ModelType } from '../components/render/ModelType';
|
||||
import { StatusCodeListInterface } from '../components/renderers/StatusRenderer';
|
||||
import { statusCodeList } from '../defaults/backendMappings';
|
||||
import { emptyServerAPI } from '../defaults/defaults';
|
||||
import { ServerAPIProps, UserProps } from './states';
|
||||
|
||||
type StatusLookup = Record<ModelType, StatusCodeListInterface>;
|
||||
|
||||
interface ServerApiStateProps {
|
||||
server: ServerAPIProps;
|
||||
setServer: (newServer: ServerAPIProps) => void;
|
||||
fetchServerApiState: () => void;
|
||||
status: StatusLookup | undefined;
|
||||
}
|
||||
|
||||
export const useServerApiState = create<ServerApiStateProps>((set, get) => ({
|
||||
server: emptyServerAPI,
|
||||
setServer: (newServer: ServerAPIProps) => set({ server: newServer }),
|
||||
fetchServerApiState: async () => {
|
||||
// Fetch server data
|
||||
await api
|
||||
.get(apiUrl(ApiPaths.api_server_info))
|
||||
.then((response) => {
|
||||
set({ server: response.data });
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
}));
|
||||
export const useServerApiState = create<ServerApiStateProps>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
server: emptyServerAPI,
|
||||
setServer: (newServer: ServerAPIProps) => set({ server: newServer }),
|
||||
fetchServerApiState: async () => {
|
||||
// Fetch server data
|
||||
await api
|
||||
.get(apiUrl(ApiPaths.api_server_info))
|
||||
.then((response) => {
|
||||
set({ server: response.data });
|
||||
})
|
||||
.catch(() => {});
|
||||
// Fetch status data for rendering labels
|
||||
await api.get(apiUrl(ApiPaths.global_status)).then((response) => {
|
||||
const newStatusLookup: StatusLookup = {} as StatusLookup;
|
||||
for (const key in response.data) {
|
||||
newStatusLookup[statusCodeList[key]] = response.data[key].values;
|
||||
}
|
||||
set({ status: newStatusLookup });
|
||||
});
|
||||
},
|
||||
status: undefined
|
||||
}),
|
||||
{
|
||||
name: 'server-api-state',
|
||||
getStorage: () => sessionStorage
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
export enum ApiPaths {
|
||||
api_server_info = 'api-server-info',
|
||||
@ -43,6 +67,7 @@ export enum ApiPaths {
|
||||
|
||||
barcode = 'api-barcode',
|
||||
news = 'news',
|
||||
global_status = 'api-global-status',
|
||||
|
||||
// Build order URLs
|
||||
build_order_list = 'api-build-list',
|
||||
@ -123,6 +148,8 @@ export function apiEndpoint(path: ApiPaths): string {
|
||||
return 'barcode/';
|
||||
case ApiPaths.news:
|
||||
return 'news/';
|
||||
case ApiPaths.global_status:
|
||||
return 'generic/status/';
|
||||
case ApiPaths.build_order_list:
|
||||
return 'build/';
|
||||
case ApiPaths.build_order_attachment_list:
|
||||
|
Loading…
Reference in New Issue
Block a user