2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-08-07 04:12:11 +00:00

Enhancements for "custom state" form

- More intuitive form actions
This commit is contained in:
Oliver Walters
2024-11-05 23:56:22 +00:00
parent 245803b0d4
commit cf2dae00af
5 changed files with 78 additions and 23 deletions

View File

@@ -3406,17 +3406,20 @@ class InvenTreeCustomUserStateModel(models.Model):
"""Custom model to extends any registered state with extra custom, user defined states."""
key = models.IntegerField(
verbose_name=_('Key'),
help_text=_('Value that will be saved in the models database'),
verbose_name=_('Value'),
help_text=_('Numerical value that will be saved in the models database'),
)
name = models.CharField(
max_length=250, verbose_name=_('Name'), help_text=_('Name of the state')
)
label = models.CharField(
max_length=250,
verbose_name=_('Label'),
help_text=_('Label that will be displayed in the frontend'),
)
color = models.CharField(
max_length=10,
choices=state_color_mappings(),
@@ -3424,12 +3427,14 @@ class InvenTreeCustomUserStateModel(models.Model):
verbose_name=_('Color'),
help_text=_('Color that will be displayed in the frontend'),
)
logical_key = models.IntegerField(
verbose_name=_('Logical Key'),
help_text=_(
'State logical key that is equal to this custom state in business logic'
),
)
model = models.ForeignKey(
ContentType,
on_delete=models.SET_NULL,
@@ -3438,6 +3443,7 @@ class InvenTreeCustomUserStateModel(models.Model):
verbose_name=_('Model'),
help_text=_('Model this state is associated with'),
)
reference_status = models.CharField(
max_length=250,
verbose_name=_('Reference Status Set'),

View File

@@ -5,7 +5,7 @@ import { ModelType } from '../../enums/ModelType';
import { resolveItem } from '../../functions/conversion';
import { useGlobalStatusState } from '../../states/StatusState';
interface StatusCodeInterface {
export interface StatusCodeInterface {
key: string;
label: string;
name: string;
@@ -13,7 +13,10 @@ interface StatusCodeInterface {
}
export interface StatusCodeListInterface {
[key: string]: StatusCodeInterface;
statusClass: string;
values: {
[key: string]: StatusCodeInterface;
};
}
interface RenderStatusLabelOptionsInterface {
@@ -33,10 +36,10 @@ function renderStatusLabel(
let color = null;
// Find the entry which matches the provided key
for (let name in codes) {
let entry = codes[name];
for (let name in codes.values) {
let entry: StatusCodeInterface = codes.values[name];
if (entry.key == key) {
if (entry?.key == key) {
text = entry.label;
color = entry.color;
break;
@@ -97,7 +100,7 @@ export function getStatusCodeName(
}
for (let name in statusCodes) {
let entry = statusCodes[name];
let entry: StatusCodeInterface = statusCodes.values[name];
if (entry.key == key) {
return entry.name;

View File

@@ -1,6 +1,12 @@
import { IconUsers } from '@tabler/icons-react';
import { useMemo, useState } from 'react';
import { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
import {
StatusCodeInterface,
StatusCodeListInterface
} from '../components/render/StatusRenderer';
import { useGlobalStatusState } from '../states/StatusState';
export function projectCodeFields(): ApiFormFieldSet {
return {
@@ -12,16 +18,51 @@ export function projectCodeFields(): ApiFormFieldSet {
};
}
export function customStateFields(): ApiFormFieldSet {
return {
key: {},
name: {},
label: {},
color: {},
logical_key: {},
model: {},
reference_status: {}
};
export function useCustomStateFields(): ApiFormFieldSet {
// Status codes
const statusCodes = useGlobalStatusState();
// Selected base status class
const [statusClass, setStatusClass] = useState<string>('');
// Construct a list of status options based on the selected status class
const statusOptions: any[] = useMemo(() => {
let options: any[] = [];
const valuesList = Object.values(statusCodes.status ?? {}).find(
(value: StatusCodeListInterface) => value.statusClass === statusClass
);
Object.values(valuesList?.values ?? {}).forEach(
(value: StatusCodeInterface) => {
options.push({
value: value.key,
display_name: value.label
});
}
);
return options;
}, [statusCodes, statusClass]);
return useMemo(() => {
return {
reference_status: {
onValueChange(value) {
setStatusClass(value);
}
},
logical_key: {
field_type: 'choice',
choices: statusOptions
},
key: {},
name: {},
label: {},
color: {},
model: {}
};
}, [statusOptions]);
}
export function customUnitsFields(): ApiFormFieldSet {

View File

@@ -35,8 +35,10 @@ export const useGlobalStatusState = create<ServerStateProps>()(
.then((response) => {
const newStatusLookup: StatusLookup = {} as StatusLookup;
for (const key in response.data) {
newStatusLookup[statusCodeList[key] || key] =
response.data[key].values;
newStatusLookup[statusCodeList[key] || key] = {
statusClass: key,
values: response.data[key].values
};
}
set({ status: newStatusLookup });
})

View File

@@ -4,7 +4,7 @@ import { useCallback, useMemo, useState } from 'react';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { UserRoles } from '../../enums/Roles';
import { customStateFields } from '../../forms/CommonForms';
import { useCustomStateFields } from '../../forms/CommonForms';
import {
useCreateApiFormModal,
useDeleteApiFormModal,
@@ -60,10 +60,13 @@ export default function CustomStateTable() {
];
}, []);
const newCustomStateFields = useCustomStateFields();
const editCustomStateFields = useCustomStateFields();
const newCustomState = useCreateApiFormModal({
url: ApiEndpoints.custom_state_list,
title: t`Add State`,
fields: customStateFields(),
fields: newCustomStateFields,
table: table
});
@@ -75,7 +78,7 @@ export default function CustomStateTable() {
url: ApiEndpoints.custom_state_list,
pk: selectedCustomState,
title: t`Edit State`,
fields: customStateFields(),
fields: editCustomStateFields,
table: table
});