mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 11:36:44 +00:00
Dynamic filters (#9290)
* Add attributes to TableFilter type def * Refactoring * Refactor ProjectCodeFilter * Provide simple string rendering of a dynamic filter * Refactor ResponsibleFilter * Further refactoring * More refactoring * Fix placeholder value
This commit is contained in:
parent
7a43c3a83e
commit
b25bf5e669
@ -6,9 +6,7 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { useApi } from '../contexts/ApiContext';
|
import { useApi } from '../contexts/ApiContext';
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
|
||||||
import { resolveItem } from '../functions/conversion';
|
import { resolveItem } from '../functions/conversion';
|
||||||
import { apiUrl } from '../states/ApiState';
|
|
||||||
import type { TableFilterChoice } from '../tables/Filter';
|
import type { TableFilterChoice } from '../tables/Filter';
|
||||||
|
|
||||||
type UseFilterProps = {
|
type UseFilterProps = {
|
||||||
@ -67,42 +65,3 @@ export function useFilters(props: UseFilterProps) {
|
|||||||
refresh
|
refresh
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provide list of project code filters
|
|
||||||
export function useProjectCodeFilters() {
|
|
||||||
return useFilters({
|
|
||||||
url: apiUrl(ApiEndpoints.project_code_list),
|
|
||||||
transform: (item) => ({
|
|
||||||
value: item.pk,
|
|
||||||
label: item.code
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provide list of user filters
|
|
||||||
export function useUserFilters() {
|
|
||||||
return useFilters({
|
|
||||||
url: apiUrl(ApiEndpoints.user_list),
|
|
||||||
params: {
|
|
||||||
is_active: true
|
|
||||||
},
|
|
||||||
transform: (item) => ({
|
|
||||||
value: item.pk,
|
|
||||||
label: item.username
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provide list of owner filters
|
|
||||||
export function useOwnerFilters() {
|
|
||||||
return useFilters({
|
|
||||||
url: apiUrl(ApiEndpoints.owner_list),
|
|
||||||
params: {
|
|
||||||
is_active: true
|
|
||||||
},
|
|
||||||
transform: (item) => ({
|
|
||||||
value: item.pk,
|
|
||||||
label: item.name
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,9 @@ import type {
|
|||||||
StatusCodeInterface,
|
StatusCodeInterface,
|
||||||
StatusCodeListInterface
|
StatusCodeListInterface
|
||||||
} from '../components/render/StatusRenderer';
|
} from '../components/render/StatusRenderer';
|
||||||
import type { ModelType } from '../enums/ModelType';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
|
import { ModelType } from '../enums/ModelType';
|
||||||
|
import { apiUrl } from '../states/ApiState';
|
||||||
import { useGlobalSettingsState } from '../states/SettingsState';
|
import { useGlobalSettingsState } from '../states/SettingsState';
|
||||||
import { type StatusLookup, useGlobalStatusState } from '../states/StatusState';
|
import { type StatusLookup, useGlobalStatusState } from '../states/StatusState';
|
||||||
|
|
||||||
@ -23,8 +25,9 @@ export type TableFilterChoice = {
|
|||||||
* choice: A filter which allows selection from a list of (supplied)
|
* choice: A filter which allows selection from a list of (supplied)
|
||||||
* date: A filter which allows selection from a date input
|
* date: A filter which allows selection from a date input
|
||||||
* text: A filter which allows raw text input
|
* text: A filter which allows raw text input
|
||||||
|
* api: A filter which fetches its options from an API endpoint
|
||||||
*/
|
*/
|
||||||
export type TableFilterType = 'boolean' | 'choice' | 'date' | 'text';
|
export type TableFilterType = 'boolean' | 'choice' | 'date' | 'text' | 'api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for the table filter type. Provides a number of options for selecting filter value:
|
* Interface for the table filter type. Provides a number of options for selecting filter value:
|
||||||
@ -39,6 +42,9 @@ export type TableFilterType = 'boolean' | 'choice' | 'date' | 'text';
|
|||||||
* value: The current value of the filter
|
* value: The current value of the filter
|
||||||
* displayValue: The current display value of the filter
|
* displayValue: The current display value of the filter
|
||||||
* active: Whether the filter is active (false = hidden, not used)
|
* active: Whether the filter is active (false = hidden, not used)
|
||||||
|
* apiUrl: The API URL to use for fetching dynamic filter options
|
||||||
|
* model: The model type to use for fetching dynamic filter options
|
||||||
|
* modelRenderer: A function to render a simple text version of the model type
|
||||||
*/
|
*/
|
||||||
export type TableFilter = {
|
export type TableFilter = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -51,6 +57,9 @@ export type TableFilter = {
|
|||||||
value?: any;
|
value?: any;
|
||||||
displayValue?: any;
|
displayValue?: any;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
apiUrl?: string;
|
||||||
|
model?: ModelType;
|
||||||
|
modelRenderer?: (instance: any) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,9 +256,7 @@ export function OrderStatusFilter({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProjectCodeFilter({
|
export function ProjectCodeFilter(): TableFilter {
|
||||||
choices
|
|
||||||
}: { choices: TableFilterChoice[] }): TableFilter {
|
|
||||||
const globalSettings = useGlobalSettingsState.getState();
|
const globalSettings = useGlobalSettingsState.getState();
|
||||||
const enabled = globalSettings.isSet('PROJECT_CODES_ENABLED', true);
|
const enabled = globalSettings.isSet('PROJECT_CODES_ENABLED', true);
|
||||||
|
|
||||||
@ -258,28 +265,73 @@ export function ProjectCodeFilter({
|
|||||||
label: t`Project Code`,
|
label: t`Project Code`,
|
||||||
description: t`Filter by project code`,
|
description: t`Filter by project code`,
|
||||||
active: enabled,
|
active: enabled,
|
||||||
choices: choices
|
type: 'api',
|
||||||
|
apiUrl: apiUrl(ApiEndpoints.project_code_list),
|
||||||
|
model: ModelType.projectcode,
|
||||||
|
modelRenderer: (instance) => instance.code
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ResponsibleFilter({
|
export function OwnerFilter({
|
||||||
choices
|
name,
|
||||||
}: { choices: TableFilterChoice[] }): TableFilter {
|
label,
|
||||||
|
description
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
description: string;
|
||||||
|
}): TableFilter {
|
||||||
return {
|
return {
|
||||||
|
name: name,
|
||||||
|
label: label,
|
||||||
|
description: description,
|
||||||
|
type: 'api',
|
||||||
|
apiUrl: apiUrl(ApiEndpoints.owner_list),
|
||||||
|
model: ModelType.owner,
|
||||||
|
modelRenderer: (instance: any) => instance.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResponsibleFilter(): TableFilter {
|
||||||
|
return OwnerFilter({
|
||||||
name: 'assigned_to',
|
name: 'assigned_to',
|
||||||
label: t`Responsible`,
|
label: t`Responsible`,
|
||||||
description: t`Filter by responsible owner`,
|
description: t`Filter by responsible owner`
|
||||||
choices: choices
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UserFilter({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
description
|
||||||
|
}: {
|
||||||
|
name?: string;
|
||||||
|
label?: string;
|
||||||
|
description?: string;
|
||||||
|
}): TableFilter {
|
||||||
|
return {
|
||||||
|
name: name ?? 'user',
|
||||||
|
label: label ?? t`User`,
|
||||||
|
description: description ?? t`Filter by user`,
|
||||||
|
type: 'api',
|
||||||
|
apiUrl: apiUrl(ApiEndpoints.user_list),
|
||||||
|
model: ModelType.user,
|
||||||
|
modelRenderer: (instance: any) => instance.username
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CreatedByFilter({
|
export function CreatedByFilter(): TableFilter {
|
||||||
choices
|
return UserFilter({
|
||||||
}: { choices: TableFilterChoice[] }): TableFilter {
|
|
||||||
return {
|
|
||||||
name: 'created_by',
|
name: 'created_by',
|
||||||
label: t`Created By`,
|
label: t`Created By`,
|
||||||
description: t`Filter by user who created the order`,
|
description: t`Filter by user who created the order`
|
||||||
choices: choices
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
|
export function IssuedByFilter(): TableFilter {
|
||||||
|
return UserFilter({
|
||||||
|
name: 'issued_by',
|
||||||
|
label: t`Issued By`,
|
||||||
|
description: t`Filter by user who issued the order`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import dayjs from 'dayjs';
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { IconCheck } from '@tabler/icons-react';
|
import { IconCheck } from '@tabler/icons-react';
|
||||||
|
import { StandaloneField } from '../components/forms/StandaloneField';
|
||||||
import { StylishText } from '../components/items/StylishText';
|
import { StylishText } from '../components/items/StylishText';
|
||||||
import type { TableState } from '../hooks/UseTable';
|
import type { TableState } from '../hooks/UseTable';
|
||||||
import {
|
import {
|
||||||
@ -64,13 +65,15 @@ function FilterItem({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function FilterElement({
|
function FilterElement({
|
||||||
filterType,
|
filterName,
|
||||||
|
filterProps,
|
||||||
valueOptions,
|
valueOptions,
|
||||||
onValueChange
|
onValueChange
|
||||||
}: {
|
}: {
|
||||||
filterType: TableFilterType;
|
filterName: string;
|
||||||
|
filterProps: TableFilter;
|
||||||
valueOptions: TableFilterChoice[];
|
valueOptions: TableFilterChoice[];
|
||||||
onValueChange: (value: string | null) => void;
|
onValueChange: (value: string | null, displayValue?: any) => void;
|
||||||
}) {
|
}) {
|
||||||
const setDateValue = useCallback(
|
const setDateValue = useCallback(
|
||||||
(value: DateValue) => {
|
(value: DateValue) => {
|
||||||
@ -86,7 +89,23 @@ function FilterElement({
|
|||||||
|
|
||||||
const [textValue, setTextValue] = useState<string>('');
|
const [textValue, setTextValue] = useState<string>('');
|
||||||
|
|
||||||
switch (filterType) {
|
switch (filterProps.type) {
|
||||||
|
case 'api':
|
||||||
|
return (
|
||||||
|
<StandaloneField
|
||||||
|
fieldName={`filter_value_${filterName}`}
|
||||||
|
fieldDefinition={{
|
||||||
|
field_type: 'related field',
|
||||||
|
api_url: filterProps.apiUrl,
|
||||||
|
placeholder: t`Select filter value`,
|
||||||
|
model: filterProps.model,
|
||||||
|
label: t`Select filter value`,
|
||||||
|
onValueChange: (value: any, instance: any) => {
|
||||||
|
onValueChange(value, filterProps.modelRenderer?.(instance));
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case 'text':
|
case 'text':
|
||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
@ -124,7 +143,7 @@ function FilterElement({
|
|||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
data={valueOptions}
|
data={valueOptions}
|
||||||
searchable={filterType != 'boolean'}
|
searchable={filterProps.type == 'choice'}
|
||||||
label={t`Value`}
|
label={t`Value`}
|
||||||
placeholder={t`Select filter value`}
|
placeholder={t`Select filter value`}
|
||||||
onChange={(value: string | null) => onValueChange(value)}
|
onChange={(value: string | null) => onValueChange(value)}
|
||||||
@ -177,23 +196,32 @@ function FilterAddGroup({
|
|||||||
return getTableFilterOptions(filter);
|
return getTableFilterOptions(filter);
|
||||||
}, [selectedFilter]);
|
}, [selectedFilter]);
|
||||||
|
|
||||||
// Determine the "type" of filter (default = boolean)
|
// Determine the filter "type" - if it is not supplied
|
||||||
const filterType: TableFilterType = useMemo(() => {
|
const getFilterType = (filter: TableFilter): TableFilterType => {
|
||||||
const filter = availableFilters?.find((flt) => flt.name === selectedFilter);
|
if (filter.type) {
|
||||||
|
|
||||||
if (filter?.type) {
|
|
||||||
return filter.type;
|
return filter.type;
|
||||||
} else if (filter?.choices) {
|
} else if (filter.apiUrl && filter.model) {
|
||||||
// If choices are provided, it is a choice filter
|
return 'api';
|
||||||
|
} else if (filter.choices || filter.choiceFunction) {
|
||||||
return 'choice';
|
return 'choice';
|
||||||
} else {
|
} else {
|
||||||
// Default fallback
|
|
||||||
return 'boolean';
|
return 'boolean';
|
||||||
}
|
}
|
||||||
}, [selectedFilter]);
|
};
|
||||||
|
|
||||||
|
// Extract filter definition
|
||||||
|
const filterProps: TableFilter | undefined = useMemo(() => {
|
||||||
|
const filter = availableFilters?.find((flt) => flt.name === selectedFilter);
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
filter.type = getFilterType(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}, [availableFilters, selectedFilter]);
|
||||||
|
|
||||||
const setSelectedValue = useCallback(
|
const setSelectedValue = useCallback(
|
||||||
(value: string | null) => {
|
(value: string | null, displayValue?: any) => {
|
||||||
// Find the matching filter
|
// Find the matching filter
|
||||||
const filter: TableFilter | undefined = availableFilters.find(
|
const filter: TableFilter | undefined = availableFilters.find(
|
||||||
(flt) => flt.name === selectedFilter
|
(flt) => flt.name === selectedFilter
|
||||||
@ -211,7 +239,8 @@ function FilterAddGroup({
|
|||||||
const newFilter: TableFilter = {
|
const newFilter: TableFilter = {
|
||||||
...filter,
|
...filter,
|
||||||
value: value,
|
value: value,
|
||||||
displayValue: valueOptions.find((v) => v.value === value)?.label
|
displayValue:
|
||||||
|
displayValue ?? valueOptions.find((v) => v.value === value)?.label
|
||||||
};
|
};
|
||||||
|
|
||||||
tableState.setActiveFilters([...filters, newFilter]);
|
tableState.setActiveFilters([...filters, newFilter]);
|
||||||
@ -233,9 +262,10 @@ function FilterAddGroup({
|
|||||||
onChange={(value: string | null) => setSelectedFilter(value)}
|
onChange={(value: string | null) => setSelectedFilter(value)}
|
||||||
maxDropdownHeight={800}
|
maxDropdownHeight={800}
|
||||||
/>
|
/>
|
||||||
{selectedFilter && (
|
{selectedFilter && filterProps && (
|
||||||
<FilterElement
|
<FilterElement
|
||||||
filterType={filterType}
|
filterName={selectedFilter}
|
||||||
|
filterProps={filterProps}
|
||||||
valueOptions={valueOptions}
|
valueOptions={valueOptions}
|
||||||
onValueChange={setSelectedValue}
|
onValueChange={setSelectedValue}
|
||||||
/>
|
/>
|
||||||
|
@ -8,13 +8,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useBuildOrderFields } from '../../forms/BuildForms';
|
import { useBuildOrderFields } from '../../forms/BuildForms';
|
||||||
import { shortenString } from '../../functions/tables';
|
|
||||||
import {
|
|
||||||
useFilters,
|
|
||||||
useOwnerFilters,
|
|
||||||
useProjectCodeFilters,
|
|
||||||
useUserFilters
|
|
||||||
} from '../../hooks/UseFilter';
|
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -37,6 +30,7 @@ import {
|
|||||||
CreatedAfterFilter,
|
CreatedAfterFilter,
|
||||||
CreatedBeforeFilter,
|
CreatedBeforeFilter,
|
||||||
HasProjectCodeFilter,
|
HasProjectCodeFilter,
|
||||||
|
IssuedByFilter,
|
||||||
MaxDateFilter,
|
MaxDateFilter,
|
||||||
MinDateFilter,
|
MinDateFilter,
|
||||||
OrderStatusFilter,
|
OrderStatusFilter,
|
||||||
@ -128,21 +122,6 @@ export function BuildOrderTable({
|
|||||||
];
|
];
|
||||||
}, [parentBuildId]);
|
}, [parentBuildId]);
|
||||||
|
|
||||||
const projectCodeFilters = useProjectCodeFilters();
|
|
||||||
const ownerFilters = useOwnerFilters();
|
|
||||||
const userFilters = useUserFilters();
|
|
||||||
|
|
||||||
const categoryFilters = useFilters({
|
|
||||||
url: apiUrl(ApiEndpoints.category_list),
|
|
||||||
transform: (item) => ({
|
|
||||||
value: item.pk,
|
|
||||||
label: shortenString({
|
|
||||||
str: item.pathstring,
|
|
||||||
len: 50
|
|
||||||
})
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
const filters: TableFilter[] = [
|
const filters: TableFilter[] = [
|
||||||
OutstandingFilter(),
|
OutstandingFilter(),
|
||||||
@ -171,20 +150,17 @@ export function BuildOrderTable({
|
|||||||
},
|
},
|
||||||
CompletedBeforeFilter(),
|
CompletedBeforeFilter(),
|
||||||
CompletedAfterFilter(),
|
CompletedAfterFilter(),
|
||||||
ProjectCodeFilter({ choices: projectCodeFilters.choices }),
|
ProjectCodeFilter(),
|
||||||
HasProjectCodeFilter(),
|
HasProjectCodeFilter(),
|
||||||
{
|
IssuedByFilter(),
|
||||||
name: 'issued_by',
|
ResponsibleFilter(),
|
||||||
label: t`Issued By`,
|
|
||||||
description: t`Filter by user who issued this order`,
|
|
||||||
choices: userFilters.choices
|
|
||||||
},
|
|
||||||
ResponsibleFilter({ choices: ownerFilters.choices }),
|
|
||||||
{
|
{
|
||||||
name: 'category',
|
name: 'category',
|
||||||
label: t`Category`,
|
label: t`Category`,
|
||||||
description: t`Filter by part category`,
|
description: t`Filter by part category`,
|
||||||
choices: categoryFilters.choices
|
apiUrl: apiUrl(ApiEndpoints.category_list),
|
||||||
|
model: ModelType.partcategory,
|
||||||
|
modelRenderer: (instance: any) => instance.name
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -199,13 +175,7 @@ export function BuildOrderTable({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}, [
|
}, [partId]);
|
||||||
partId,
|
|
||||||
categoryFilters.choices,
|
|
||||||
projectCodeFilters.choices,
|
|
||||||
ownerFilters.choices,
|
|
||||||
userFilters.choices
|
|
||||||
]);
|
|
||||||
|
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
|
@ -8,11 +8,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { usePurchaseOrderFields } from '../../forms/PurchaseOrderForms';
|
import { usePurchaseOrderFields } from '../../forms/PurchaseOrderForms';
|
||||||
import {
|
|
||||||
useOwnerFilters,
|
|
||||||
useProjectCodeFilters,
|
|
||||||
useUserFilters
|
|
||||||
} from '../../hooks/UseFilter';
|
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -66,10 +61,6 @@ export function PurchaseOrderTable({
|
|||||||
const table = useTable('purchase-order');
|
const table = useTable('purchase-order');
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const projectCodeFilters = useProjectCodeFilters();
|
|
||||||
const responsibleFilters = useOwnerFilters();
|
|
||||||
const createdByFilters = useUserFilters();
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
OrderStatusFilter({ model: ModelType.purchaseorder }),
|
OrderStatusFilter({ model: ModelType.purchaseorder }),
|
||||||
@ -98,16 +89,12 @@ export function PurchaseOrderTable({
|
|||||||
},
|
},
|
||||||
CompletedBeforeFilter(),
|
CompletedBeforeFilter(),
|
||||||
CompletedAfterFilter(),
|
CompletedAfterFilter(),
|
||||||
ProjectCodeFilter({ choices: projectCodeFilters.choices }),
|
ProjectCodeFilter(),
|
||||||
HasProjectCodeFilter(),
|
HasProjectCodeFilter(),
|
||||||
ResponsibleFilter({ choices: responsibleFilters.choices }),
|
ResponsibleFilter(),
|
||||||
CreatedByFilter({ choices: createdByFilters.choices })
|
CreatedByFilter()
|
||||||
];
|
];
|
||||||
}, [
|
}, []);
|
||||||
projectCodeFilters.choices,
|
|
||||||
responsibleFilters.choices,
|
|
||||||
createdByFilters.choices
|
|
||||||
]);
|
|
||||||
|
|
||||||
const tableColumns = useMemo(() => {
|
const tableColumns = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
@ -8,11 +8,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useReturnOrderFields } from '../../forms/ReturnOrderForms';
|
import { useReturnOrderFields } from '../../forms/ReturnOrderForms';
|
||||||
import {
|
|
||||||
useOwnerFilters,
|
|
||||||
useProjectCodeFilters,
|
|
||||||
useUserFilters
|
|
||||||
} from '../../hooks/UseFilter';
|
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -63,10 +58,6 @@ export function ReturnOrderTable({
|
|||||||
const table = useTable(!!partId ? 'returnorders-part' : 'returnorders-index');
|
const table = useTable(!!partId ? 'returnorders-part' : 'returnorders-index');
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const projectCodeFilters = useProjectCodeFilters();
|
|
||||||
const responsibleFilters = useOwnerFilters();
|
|
||||||
const createdByFilters = useUserFilters();
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
const filters: TableFilter[] = [
|
const filters: TableFilter[] = [
|
||||||
OrderStatusFilter({ model: ModelType.returnorder }),
|
OrderStatusFilter({ model: ModelType.returnorder }),
|
||||||
@ -96,9 +87,9 @@ export function ReturnOrderTable({
|
|||||||
CompletedBeforeFilter(),
|
CompletedBeforeFilter(),
|
||||||
CompletedAfterFilter(),
|
CompletedAfterFilter(),
|
||||||
HasProjectCodeFilter(),
|
HasProjectCodeFilter(),
|
||||||
ProjectCodeFilter({ choices: projectCodeFilters.choices }),
|
ProjectCodeFilter(),
|
||||||
ResponsibleFilter({ choices: responsibleFilters.choices }),
|
ResponsibleFilter(),
|
||||||
CreatedByFilter({ choices: createdByFilters.choices })
|
CreatedByFilter()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!!partId) {
|
if (!!partId) {
|
||||||
@ -111,12 +102,7 @@ export function ReturnOrderTable({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}, [
|
}, [partId]);
|
||||||
partId,
|
|
||||||
projectCodeFilters.choices,
|
|
||||||
responsibleFilters.choices,
|
|
||||||
createdByFilters.choices
|
|
||||||
]);
|
|
||||||
|
|
||||||
const tableColumns = useMemo(() => {
|
const tableColumns = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
@ -9,11 +9,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { useSalesOrderFields } from '../../forms/SalesOrderForms';
|
import { useSalesOrderFields } from '../../forms/SalesOrderForms';
|
||||||
import {
|
|
||||||
useOwnerFilters,
|
|
||||||
useProjectCodeFilters,
|
|
||||||
useUserFilters
|
|
||||||
} from '../../hooks/UseFilter';
|
|
||||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
@ -64,10 +59,6 @@ export function SalesOrderTable({
|
|||||||
const table = useTable(!!partId ? 'salesorder-part' : 'salesorder-index');
|
const table = useTable(!!partId ? 'salesorder-part' : 'salesorder-index');
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const projectCodeFilters = useProjectCodeFilters();
|
|
||||||
const responsibleFilters = useOwnerFilters();
|
|
||||||
const createdByFilters = useUserFilters();
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
const filters: TableFilter[] = [
|
const filters: TableFilter[] = [
|
||||||
OrderStatusFilter({ model: ModelType.salesorder }),
|
OrderStatusFilter({ model: ModelType.salesorder }),
|
||||||
@ -97,9 +88,9 @@ export function SalesOrderTable({
|
|||||||
CompletedBeforeFilter(),
|
CompletedBeforeFilter(),
|
||||||
CompletedAfterFilter(),
|
CompletedAfterFilter(),
|
||||||
HasProjectCodeFilter(),
|
HasProjectCodeFilter(),
|
||||||
ProjectCodeFilter({ choices: projectCodeFilters.choices }),
|
ProjectCodeFilter(),
|
||||||
ResponsibleFilter({ choices: responsibleFilters.choices }),
|
ResponsibleFilter(),
|
||||||
CreatedByFilter({ choices: createdByFilters.choices })
|
CreatedByFilter()
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!!partId) {
|
if (!!partId) {
|
||||||
@ -112,12 +103,7 @@ export function SalesOrderTable({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}, [
|
}, [partId]);
|
||||||
partId,
|
|
||||||
projectCodeFilters.choices,
|
|
||||||
responsibleFilters.choices,
|
|
||||||
createdByFilters.choices
|
|
||||||
]);
|
|
||||||
|
|
||||||
const salesOrderFields = useSalesOrderFields({});
|
const salesOrderFields = useSalesOrderFields({});
|
||||||
|
|
||||||
|
@ -21,14 +21,13 @@ import { RenderUser } from '../../components/render/User';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { shortenString } from '../../functions/tables';
|
import { shortenString } from '../../functions/tables';
|
||||||
import { useUserFilters } from '../../hooks/UseFilter';
|
|
||||||
import { useDeleteApiFormModal } from '../../hooks/UseForm';
|
import { useDeleteApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import { useGlobalSettingsState } from '../../states/SettingsState';
|
import { useGlobalSettingsState } from '../../states/SettingsState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import type { TableColumn } from '../Column';
|
import type { TableColumn } from '../Column';
|
||||||
import type { TableFilter } from '../Filter';
|
import { type TableFilter, UserFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import { RowDeleteAction } from '../RowActions';
|
import { RowDeleteAction } from '../RowActions';
|
||||||
|
|
||||||
@ -148,8 +147,6 @@ export default function BarcodeScanHistoryTable() {
|
|||||||
|
|
||||||
const globalSettings = useGlobalSettingsState();
|
const globalSettings = useGlobalSettingsState();
|
||||||
|
|
||||||
const userFilters = useUserFilters();
|
|
||||||
|
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
|
||||||
const tableColumns: TableColumn[] = useMemo(() => {
|
const tableColumns: TableColumn[] = useMemo(() => {
|
||||||
@ -204,19 +201,14 @@ export default function BarcodeScanHistoryTable() {
|
|||||||
|
|
||||||
const filters: TableFilter[] = useMemo(() => {
|
const filters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
UserFilter({}),
|
||||||
name: 'user',
|
|
||||||
label: t`User`,
|
|
||||||
choices: userFilters.choices,
|
|
||||||
description: t`Filter by user`
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'result',
|
name: 'result',
|
||||||
label: t`Result`,
|
label: t`Result`,
|
||||||
description: t`Filter by result`
|
description: t`Filter by result`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [userFilters]);
|
}, []);
|
||||||
|
|
||||||
const canDelete: boolean = useMemo(() => {
|
const canDelete: boolean = useMemo(() => {
|
||||||
return user.isStaff() && user.hasDeleteRole(UserRoles.admin);
|
return user.isStaff() && user.hasDeleteRole(UserRoles.admin);
|
||||||
|
@ -9,7 +9,7 @@ import { RenderUser } from '../../components/render/User';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { dataImporterSessionFields } from '../../forms/ImporterForms';
|
import { dataImporterSessionFields } from '../../forms/ImporterForms';
|
||||||
import { useFilters, useUserFilters } from '../../hooks/UseFilter';
|
import { useFilters } from '../../hooks/UseFilter';
|
||||||
import {
|
import {
|
||||||
useCreateApiFormModal,
|
useCreateApiFormModal,
|
||||||
useDeleteApiFormModal
|
useDeleteApiFormModal
|
||||||
@ -18,7 +18,7 @@ import { useTable } from '../../hooks/UseTable';
|
|||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import type { TableColumn } from '../Column';
|
import type { TableColumn } from '../Column';
|
||||||
import { DateColumn, StatusColumn } from '../ColumnRenderers';
|
import { DateColumn, StatusColumn } from '../ColumnRenderers';
|
||||||
import { StatusFilterOptions, type TableFilter } from '../Filter';
|
import { StatusFilterOptions, type TableFilter, UserFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import { type RowAction, RowDeleteAction } from '../RowActions';
|
import { type RowAction, RowDeleteAction } from '../RowActions';
|
||||||
|
|
||||||
@ -88,8 +88,6 @@ export default function ImportSesssionTable() {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const userFilter = useUserFilters();
|
|
||||||
|
|
||||||
const modelTypeFilters = useFilters({
|
const modelTypeFilters = useFilters({
|
||||||
url: apiUrl(ApiEndpoints.import_session_list),
|
url: apiUrl(ApiEndpoints.import_session_list),
|
||||||
method: 'OPTIONS',
|
method: 'OPTIONS',
|
||||||
@ -116,14 +114,9 @@ export default function ImportSesssionTable() {
|
|||||||
description: t`Filter by import session status`,
|
description: t`Filter by import session status`,
|
||||||
choiceFunction: StatusFilterOptions(ModelType.importsession)
|
choiceFunction: StatusFilterOptions(ModelType.importsession)
|
||||||
},
|
},
|
||||||
{
|
UserFilter({})
|
||||||
name: 'user',
|
|
||||||
label: t`User`,
|
|
||||||
description: t`Filter by user`,
|
|
||||||
choices: userFilter.choices
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
}, [modelTypeFilters.choices, userFilter.choices]);
|
}, [modelTypeFilters.choices]);
|
||||||
|
|
||||||
const tableActions = useMemo(() => {
|
const tableActions = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
@ -8,7 +8,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
|||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { UserRoles } from '../../enums/Roles';
|
import { UserRoles } from '../../enums/Roles';
|
||||||
import { stockLocationFields } from '../../forms/StockForms';
|
import { stockLocationFields } from '../../forms/StockForms';
|
||||||
import { useFilters } from '../../hooks/UseFilter';
|
|
||||||
import {
|
import {
|
||||||
useCreateApiFormModal,
|
useCreateApiFormModal,
|
||||||
useEditApiFormModal
|
useEditApiFormModal
|
||||||
@ -29,14 +28,6 @@ export function StockLocationTable({ parentId }: Readonly<{ parentId?: any }>) {
|
|||||||
const table = useTable('stocklocation');
|
const table = useTable('stocklocation');
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const locationTypeFilters = useFilters({
|
|
||||||
url: apiUrl(ApiEndpoints.stock_location_type_list),
|
|
||||||
transform: (item) => ({
|
|
||||||
value: item.pk,
|
|
||||||
label: item.name
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const tableFilters: TableFilter[] = useMemo(() => {
|
const tableFilters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -62,10 +53,12 @@ export function StockLocationTable({ parentId }: Readonly<{ parentId?: any }>) {
|
|||||||
name: 'location_type',
|
name: 'location_type',
|
||||||
label: t`Location Type`,
|
label: t`Location Type`,
|
||||||
description: t`Filter by location type`,
|
description: t`Filter by location type`,
|
||||||
choices: locationTypeFilters.choices
|
apiUrl: apiUrl(ApiEndpoints.stock_location_type_list),
|
||||||
|
model: ModelType.stocklocationtype,
|
||||||
|
modelRenderer: (instance: any) => instance.name
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [locationTypeFilters.choices]);
|
}, []);
|
||||||
|
|
||||||
const tableColumns: TableColumn[] = useMemo(() => {
|
const tableColumns: TableColumn[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
@ -19,12 +19,11 @@ import {
|
|||||||
import { RenderUser } from '../../components/render/User';
|
import { RenderUser } from '../../components/render/User';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { useUserFilters } from '../../hooks/UseFilter';
|
|
||||||
import { useTable } from '../../hooks/UseTable';
|
import { useTable } from '../../hooks/UseTable';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
import type { TableColumn } from '../Column';
|
import type { TableColumn } from '../Column';
|
||||||
import { DateColumn, DescriptionColumn } from '../ColumnRenderers';
|
import { DateColumn, DescriptionColumn } from '../ColumnRenderers';
|
||||||
import type { TableFilter } from '../Filter';
|
import { type TableFilter, UserFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
|
|
||||||
type StockTrackingEntry = {
|
type StockTrackingEntry = {
|
||||||
@ -37,8 +36,6 @@ export function StockTrackingTable({ itemId }: Readonly<{ itemId: number }>) {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const table = useTable('stock_tracking');
|
const table = useTable('stock_tracking');
|
||||||
|
|
||||||
const userFilters = useUserFilters();
|
|
||||||
|
|
||||||
// Render "details" for a stock tracking record
|
// Render "details" for a stock tracking record
|
||||||
const renderDetails = useCallback(
|
const renderDetails = useCallback(
|
||||||
(record: any) => {
|
(record: any) => {
|
||||||
@ -186,14 +183,13 @@ export function StockTrackingTable({ itemId }: Readonly<{ itemId: number }>) {
|
|||||||
|
|
||||||
const filters: TableFilter[] = useMemo(() => {
|
const filters: TableFilter[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
UserFilter({
|
||||||
name: 'user',
|
name: 'user',
|
||||||
label: t`User`,
|
label: t`User`,
|
||||||
choices: userFilters.choices,
|
|
||||||
description: t`Filter by user`
|
description: t`Filter by user`
|
||||||
}
|
})
|
||||||
];
|
];
|
||||||
}, [userFilters]);
|
}, []);
|
||||||
|
|
||||||
const tableColumns: TableColumn[] = useMemo(() => {
|
const tableColumns: TableColumn[] = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user