2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-05-02 13:28:49 +00:00

[PUI] fix a few sonarcloud warnings (#8133)

* fix a few code issues

* fix common sonarcloud issues

* more small fixes
This commit is contained in:
Matthias Mair 2024-09-17 06:16:29 +02:00 committed by GitHub
parent 45aab46db3
commit 7c937fa283
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 211 additions and 229 deletions

View File

@ -4,7 +4,7 @@ import { ErrorBoundary, FallbackRender } from '@sentry/react';
import { IconExclamationCircle } from '@tabler/icons-react'; import { IconExclamationCircle } from '@tabler/icons-react';
import { ReactNode, useCallback } from 'react'; import { ReactNode, useCallback } from 'react';
function DefaultFallback({ title }: { title: String }): ReactNode { function DefaultFallback({ title }: Readonly<{ title: string }>): ReactNode {
return ( return (
<Alert <Alert
color="red" color="red"
@ -20,11 +20,11 @@ export function Boundary({
children, children,
label, label,
fallback fallback
}: { }: Readonly<{
children: ReactNode; children: ReactNode;
label: string; label: string;
fallback?: React.ReactElement | FallbackRender | undefined; fallback?: React.ReactElement | FallbackRender;
}): ReactNode { }>): ReactNode {
const onError = useCallback( const onError = useCallback(
(error: unknown, componentStack: string | undefined, eventId: string) => { (error: unknown, componentStack: string | undefined, eventId: string) => {
console.error(`Error rendering component: ${label}`); console.error(`Error rendering component: ${label}`);

View File

@ -22,7 +22,7 @@ export type AdminButtonProps = {
* - The user has "superuser" role * - The user has "superuser" role
* - The user has at least read rights for the selected item * - The user has at least read rights for the selected item
*/ */
export default function AdminButton(props: AdminButtonProps) { export default function AdminButton(props: Readonly<AdminButtonProps>) {
const user = useUserState(); const user = useUserState();
const enabled: boolean = useMemo(() => { const enabled: boolean = useMemo(() => {

View File

@ -12,14 +12,14 @@ export default function PrimaryActionButton({
color, color,
hidden, hidden,
onClick onClick
}: { }: Readonly<{
title: string; title: string;
tooltip?: string; tooltip?: string;
icon?: InvenTreeIconType; icon?: InvenTreeIconType;
color?: string; color?: string;
hidden?: boolean; hidden?: boolean;
onClick: () => void; onClick: () => void;
}) { }>) {
if (hidden) { if (hidden) {
return null; return null;
} }

View File

@ -6,10 +6,10 @@ import { ActionButton } from './ActionButton';
export default function RemoveRowButton({ export default function RemoveRowButton({
onClick, onClick,
tooltip = t`Remove this row` tooltip = t`Remove this row`
}: { }: Readonly<{
onClick: () => void; onClick: () => void;
tooltip?: string; tooltip?: string;
}) { }>) {
return ( return (
<ActionButton <ActionButton
onClick={onClick} onClick={onClick}

View File

@ -7,14 +7,14 @@ export function PassFailButton({
value, value,
passText, passText,
failText failText
}: { }: Readonly<{
value: any; value: any;
passText?: string; passText?: string;
failText?: string; failText?: string;
}) { }>) {
const v = isTrue(value); const v = isTrue(value);
const pass = passText || t`Pass`; const pass = passText ?? t`Pass`;
const fail = failText || t`Fail`; const fail = failText ?? t`Fail`;
return ( return (
<Badge <Badge
@ -29,11 +29,11 @@ export function PassFailButton({
); );
} }
export function YesNoButton({ value }: { value: any }) { export function YesNoButton({ value }: Readonly<{ value: any }>) {
return <PassFailButton value={value} passText={t`Yes`} failText={t`No`} />; return <PassFailButton value={value} passText={t`Yes`} failText={t`No`} />;
} }
export function YesNoUndefinedButton({ value }: { value?: boolean }) { export function YesNoUndefinedButton({ value }: Readonly<{ value?: boolean }>) {
if (value === undefined) { if (value === undefined) {
return <Skeleton height={15} width={32} />; return <Skeleton height={15} width={32} />;
} else { } else {

View File

@ -1,6 +1,4 @@
// import SimpleMDE from "react-simplemde-editor";
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { useMantineColorScheme } from '@mantine/core';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import EasyMDE, { default as SimpleMde } from 'easymde'; import EasyMDE, { default as SimpleMde } from 'easymde';
@ -60,13 +58,11 @@ export default function NotesEditor({
modelType, modelType,
modelId, modelId,
editable editable
}: { }: Readonly<{
modelType: ModelType; modelType: ModelType;
modelId: number; modelId: number;
editable?: boolean; editable?: boolean;
}) { }>) {
const { colorScheme } = useMantineColorScheme();
// In addition to the editable prop, we also need to check if the user has "enabled" editing // In addition to the editable prop, we also need to check if the user has "enabled" editing
const [editing, setEditing] = useState<boolean>(false); const [editing, setEditing] = useState<boolean>(false);

View File

@ -5,7 +5,7 @@ import NotAuthenticated from './NotAuthenticated';
import NotFound from './NotFound'; import NotFound from './NotFound';
import PermissionDenied from './PermissionDenied'; import PermissionDenied from './PermissionDenied';
export default function ClientError({ status }: { status?: number }) { export default function ClientError({ status }: Readonly<{ status?: number }>) {
switch (status) { switch (status) {
case 401: case 401:
return <NotAuthenticated />; return <NotAuthenticated />;

View File

@ -19,13 +19,13 @@ export default function ErrorPage({
title, title,
message, message,
status status
}: { }: Readonly<{
title: string; title: string;
message: string; message: string;
status?: number; status?: number;
redirectMessage?: string; redirectMessage?: string;
redirectTarget?: string; redirectTarget?: string;
}) { }>) {
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (

View File

@ -1,6 +1,6 @@
import { Select } from '@mantine/core'; import { Select } from '@mantine/core';
import { useId } from '@mantine/hooks'; import { useId } from '@mantine/hooks';
import { useCallback, useEffect, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { FieldValues, UseControllerReturn } from 'react-hook-form'; import { FieldValues, UseControllerReturn } from 'react-hook-form';
import { ApiFormFieldType } from './ApiFormField'; import { ApiFormFieldType } from './ApiFormField';
@ -12,11 +12,11 @@ export function ChoiceField({
controller, controller,
definition, definition,
fieldName fieldName
}: { }: Readonly<{
controller: UseControllerReturn<FieldValues, any>; controller: UseControllerReturn<FieldValues, any>;
definition: ApiFormFieldType; definition: ApiFormFieldType;
fieldName: string; fieldName: string;
}) { }>) {
const fieldId = useId(); const fieldId = useId();
const { const {

View File

@ -18,13 +18,13 @@ export function DependentField({
definition, definition,
url, url,
setFields setFields
}: { }: Readonly<{
control: Control<FieldValues, any>; control: Control<FieldValues, any>;
definition: ApiFormFieldType; definition: ApiFormFieldType;
fieldName: string; fieldName: string;
url?: string; url?: string;
setFields?: React.Dispatch<React.SetStateAction<ApiFormFieldSet>>; setFields?: React.Dispatch<React.SetStateAction<ApiFormFieldSet>>;
}) { }>) {
const { watch, resetField } = useFormContext(); const { watch, resetField } = useFormContext();
const mappedFieldNames = useMemo( const mappedFieldNames = useMemo(

View File

@ -20,16 +20,16 @@ export function TableField({
definition, definition,
fieldName, fieldName,
control control
}: { }: Readonly<{
definition: ApiFormFieldType; definition: ApiFormFieldType;
fieldName: string; fieldName: string;
control: UseControllerReturn<FieldValues, any>; control: UseControllerReturn<FieldValues, any>;
}) { }>) {
const { const {
field, field,
fieldState: { error } fieldState: { error }
} = control; } = control;
const { value, ref } = field; const { value } = field;
const onRowFieldChange = (idx: number, key: string, value: any) => { const onRowFieldChange = (idx: number, key: string, value: any) => {
const val = field.value; const val = field.value;

View File

@ -14,12 +14,12 @@ export default function TextField({
fieldName, fieldName,
definition, definition,
onChange onChange
}: { }: Readonly<{
controller: UseControllerReturn<FieldValues, any>; controller: UseControllerReturn<FieldValues, any>;
definition: any; definition: any;
fieldName: string; fieldName: string;
onChange: (value: any) => void; onChange: (value: any) => void;
}) { }>) {
const fieldId = useId(); const fieldId = useId();
const { const {
field, field,

View File

@ -1,5 +1,5 @@
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { Anchor, Group, Skeleton, Text } from '@mantine/core'; import { Anchor, Group } from '@mantine/core';
import { ReactNode, useMemo } from 'react'; import { ReactNode, useMemo } from 'react';
import { ApiImage } from './ApiImage'; import { ApiImage } from './ApiImage';
@ -14,14 +14,14 @@ export function Thumbnail({
link, link,
text, text,
align align
}: { }: Readonly<{
src?: string | undefined; src?: string;
alt?: string; alt?: string;
size?: number; size?: number;
text?: ReactNode; text?: ReactNode;
align?: string; align?: string;
link?: string; link?: string;
}) { }>) {
const backup_image = '/static/img/blank_image.png'; const backup_image = '/static/img/blank_image.png';
const inner = useMemo(() => { const inner = useMemo(() => {

View File

@ -38,12 +38,12 @@ function ImporterDataCell({
column, column,
row, row,
onEdit onEdit
}: { }: Readonly<{
session: ImportSessionState; session: ImportSessionState;
column: any; column: any;
row: any; row: any;
onEdit?: () => void; onEdit?: () => void;
}) { }>) {
const onRowEdit = useCallback( const onRowEdit = useCallback(
(event: any) => { (event: any) => {
cancelEvent(event); cancelEvent(event);
@ -128,9 +128,9 @@ function ImporterDataCell({
export default function ImporterDataSelector({ export default function ImporterDataSelector({
session session
}: { }: Readonly<{
session: ImportSessionState; session: ImportSessionState;
}) { }>) {
const table = useTable('dataimporter'); const table = useTable('dataimporter');
const [selectedFieldNames, setSelectedFieldNames] = useState<string[]>([]); const [selectedFieldNames, setSelectedFieldNames] = useState<string[]>([]);
@ -377,6 +377,7 @@ export default function ImporterDataSelector({
return [ return [
<ActionButton <ActionButton
key="import-selected-rows"
disabled={!canImport} disabled={!canImport}
icon={<IconArrowRight />} icon={<IconArrowRight />}
color="green" color="green"

View File

@ -20,7 +20,10 @@ import { apiUrl } from '../../states/ApiState';
import { StandaloneField } from '../forms/StandaloneField'; import { StandaloneField } from '../forms/StandaloneField';
import { ApiFormFieldType } from '../forms/fields/ApiFormField'; import { ApiFormFieldType } from '../forms/fields/ApiFormField';
function ImporterColumn({ column, options }: { column: any; options: any[] }) { function ImporterColumn({
column,
options
}: Readonly<{ column: any; options: any[] }>) {
const [errorMessage, setErrorMessage] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string>('');
const [selectedColumn, setSelectedColumn] = useState<string>( const [selectedColumn, setSelectedColumn] = useState<string>(
@ -122,11 +125,11 @@ function ImporterColumnTableRow({
session, session,
column, column,
options options
}: { }: Readonly<{
session: ImportSessionState; session: ImportSessionState;
column: any; column: any;
options: any; options: any;
}) { }>) {
return ( return (
<Table.Tr key={column.label ?? column.field}> <Table.Tr key={column.label ?? column.field}>
<Table.Td> <Table.Td>
@ -156,9 +159,9 @@ function ImporterColumnTableRow({
export default function ImporterColumnSelector({ export default function ImporterColumnSelector({
session session
}: { }: Readonly<{
session: ImportSessionState; session: ImportSessionState;
}) { }>) {
const [errorMessage, setErrorMessage] = useState<string>(''); const [errorMessage, setErrorMessage] = useState<string>('');
const acceptMapping = useCallback(() => { const acceptMapping = useCallback(() => {
@ -221,6 +224,7 @@ export default function ImporterColumnSelector({
{session.columnMappings.map((column: any) => { {session.columnMappings.map((column: any) => {
return ( return (
<ImporterColumnTableRow <ImporterColumnTableRow
key={`import-${column.field}}`}
session={session} session={session}
column={column} column={column}
options={columnOptions} options={columnOptions}

View File

@ -27,7 +27,9 @@ import ImporterImportProgress from './ImporterImportProgress';
/* /*
* Stepper component showing the current step of the data import process. * Stepper component showing the current step of the data import process.
*/ */
function ImportDrawerStepper({ currentStep }: { currentStep: number }) { function ImportDrawerStepper({
currentStep
}: Readonly<{ currentStep: number }>) {
/* TODO: Enhance this with: /* TODO: Enhance this with:
* - Custom icons * - Custom icons
* - Loading indicators for "background" states * - Loading indicators for "background" states
@ -54,11 +56,11 @@ export default function ImporterDrawer({
sessionId, sessionId,
opened, opened,
onClose onClose
}: { }: Readonly<{
sessionId: number; sessionId: number;
opened: boolean; opened: boolean;
onClose: () => void; onClose: () => void;
}) { }>) {
const session = useImportSession({ sessionId: sessionId }); const session = useImportSession({ sessionId: sessionId });
const importSessionStatus = useStatusCodes({ const importSessionStatus = useStatusCodes({

View File

@ -10,9 +10,9 @@ import { StylishText } from '../items/StylishText';
export default function ImporterImportProgress({ export default function ImporterImportProgress({
session session
}: { }: Readonly<{
session: ImportSessionState; session: ImportSessionState;
}) { }>) {
const importSessionStatus = useStatusCodes({ const importSessionStatus = useStatusCodes({
modelType: ModelType.importsession modelType: ModelType.importsession
}); });

View File

@ -127,11 +127,11 @@ export function OptionsActionDropdown({
actions = [], actions = [],
tooltip = t`Options`, tooltip = t`Options`,
hidden = false hidden = false
}: { }: Readonly<{
actions: ActionDropdownItem[]; actions: ActionDropdownItem[];
tooltip?: string; tooltip?: string;
hidden?: boolean; hidden?: boolean;
}) { }>) {
return ( return (
<ActionDropdown <ActionDropdown
icon={<IconDotsVertical />} icon={<IconDotsVertical />}

View File

@ -11,7 +11,6 @@ import {
Stack, Stack,
Text Text
} from '@mantine/core'; } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { modals } from '@mantine/modals'; import { modals } from '@mantine/modals';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import QR from 'qrcode'; import QR from 'qrcode';
@ -143,7 +142,6 @@ export const InvenTreeQRCode = ({
export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => { export const QRCodeLink = ({ mdl_prop }: { mdl_prop: QrCodeType }) => {
const [barcode, setBarcode] = useState(''); const [barcode, setBarcode] = useState('');
const [isScanning, toggleIsScanning] = useDisclosure(false);
function linkBarcode(value?: string) { function linkBarcode(value?: string) {
api api

View File

@ -8,11 +8,11 @@ export default function InstanceDetail({
status, status,
loading, loading,
children children
}: { }: Readonly<{
status: number; status: number;
loading: boolean; loading: boolean;
children: React.ReactNode; children: React.ReactNode;
}) { }>) {
const user = useUserState(); const user = useUserState();
if (loading || !user.isLoggedIn()) { if (loading || !user.isLoggedIn()) {

View File

@ -40,14 +40,14 @@ export default function NavigationTree({
selectedId, selectedId,
modelType, modelType,
endpoint endpoint
}: { }: Readonly<{
title: string; title: string;
opened: boolean; opened: boolean;
onClose: () => void; onClose: () => void;
selectedId?: number | null; selectedId?: number | null;
modelType: ModelType; modelType: ModelType;
endpoint: ApiEndpoints; endpoint: ApiEndpoints;
}) { }>) {
const navigate = useNavigate(); const navigate = useNavigate();
const treeState = useTree(); const treeState = useTree();

View File

@ -64,10 +64,10 @@ export async function isPluginPanelHidden({
export default function PluginPanelContent({ export default function PluginPanelContent({
pluginProps, pluginProps,
pluginContext pluginContext
}: { }: Readonly<{
pluginProps: PluginPanelProps; pluginProps: PluginPanelProps;
pluginContext: PluginContext; pluginContext: PluginContext;
}): ReactNode { }>): ReactNode {
const ref = useRef<HTMLDivElement>(); const ref = useRef<HTMLDivElement>();
const [error, setError] = useState<string | undefined>(undefined); const [error, setError] = useState<string | undefined>(undefined);

View File

@ -121,10 +121,10 @@ export function RenderInstance(props: RenderInstanceProps): ReactNode {
export function RenderRemoteInstance({ export function RenderRemoteInstance({
model, model,
pk pk
}: { }: Readonly<{
model: ModelType; model: ModelType;
pk: number; pk: number;
}): ReactNode { }>): ReactNode {
const { data, isLoading, isFetching } = useQuery({ const { data, isLoading, isFetching } = useQuery({
queryKey: ['model', model, pk], queryKey: ['model', model, pk],
queryFn: async () => { queryFn: async () => {
@ -166,7 +166,7 @@ export function RenderInlineModel({
navigate, navigate,
showSecondary = true, showSecondary = true,
tooltip tooltip
}: { }: Readonly<{
primary: string; primary: string;
secondary?: string; secondary?: string;
showSecondary?: boolean; showSecondary?: boolean;
@ -177,7 +177,7 @@ export function RenderInlineModel({
url?: string; url?: string;
navigate?: any; navigate?: any;
tooltip?: string; tooltip?: string;
}): ReactNode { }>): ReactNode {
// TODO: Handle labels // TODO: Handle labels
const onClick = useCallback( const onClick = useCallback(
@ -215,9 +215,9 @@ export function RenderInlineModel({
export function UnknownRenderer({ export function UnknownRenderer({
model model
}: { }: Readonly<{
model: ModelType | undefined; model: ModelType | undefined;
}): ReactNode { }>): ReactNode {
return ( return (
<Alert color="red" title={t`Unknown model: ${model}`}> <Alert color="red" title={t`Unknown model: ${model}`}>
<></> <></>

View File

@ -6,9 +6,9 @@ import { RenderInlineModel } from './Instance';
export function RenderPlugin({ export function RenderPlugin({
instance instance
}: { }: Readonly<{
instance: Readonly<any>; instance: Readonly<any>;
}): ReactNode { }>): ReactNode {
return ( return (
<RenderInlineModel <RenderInlineModel
primary={instance.name} primary={instance.name}

View File

@ -4,9 +4,9 @@ import { RenderInlineModel } from './Instance';
export function RenderReportTemplate({ export function RenderReportTemplate({
instance instance
}: { }: Readonly<{
instance: any; instance: any;
}): ReactNode { }>): ReactNode {
return ( return (
<RenderInlineModel <RenderInlineModel
primary={instance.name} primary={instance.name}
@ -17,9 +17,9 @@ export function RenderReportTemplate({
export function RenderLabelTemplate({ export function RenderLabelTemplate({
instance instance
}: { }: Readonly<{
instance: any; instance: any;
}): ReactNode { }>): ReactNode {
return ( return (
<RenderInlineModel <RenderInlineModel
primary={instance.name} primary={instance.name}

View File

@ -5,14 +5,18 @@ import { FactItem } from './FactItem';
export function FactCollection({ export function FactCollection({
items, items,
minItems = 3 minItems = 3
}: { }: Readonly<{
items: { title: string; value: any }[]; items: { title: string; value: any }[];
minItems?: number; minItems?: number;
}) { }>) {
return ( return (
<SimpleGrid cols={minItems} spacing="xs"> <SimpleGrid cols={minItems} spacing="xs">
{items.map((item, index) => ( {items.map((item, index) => (
<FactItem key={index} title={item.title} value={item.value} /> <FactItem
key={`${index}-${item.value}`}
title={item.title}
value={item.value}
/>
))} ))}
</SimpleGrid> </SimpleGrid>
); );

View File

@ -2,7 +2,10 @@ import { Paper, Stack, Text } from '@mantine/core';
import { StylishText } from '../items/StylishText'; import { StylishText } from '../items/StylishText';
export function FactItem({ title, value }: { title: string; value: number }) { export function FactItem({
title,
value
}: Readonly<{ title: string; value: number }>) {
return ( return (
<Paper p="md" shadow="xs"> <Paper p="md" shadow="xs">
<Stack gap="xs"> <Stack gap="xs">

View File

@ -11,7 +11,6 @@ import {
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { DataTable } from 'mantine-datatable'; import { DataTable } from 'mantine-datatable';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useFormContext } from 'react-hook-form';
import { api } from '../App'; import { api } from '../App';
import { ActionButton } from '../components/buttons/ActionButton'; import { ActionButton } from '../components/buttons/ActionButton';
@ -25,7 +24,6 @@ import { TableFieldRowProps } from '../components/forms/fields/TableField';
import { ProgressBar } from '../components/items/ProgressBar'; import { ProgressBar } from '../components/items/ProgressBar';
import { ApiEndpoints } from '../enums/ApiEndpoints'; import { ApiEndpoints } from '../enums/ApiEndpoints';
import { ModelType } from '../enums/ModelType'; import { ModelType } from '../enums/ModelType';
import { resolveItem } from '../functions/conversion';
import { InvenTreeIcon } from '../functions/icons'; import { InvenTreeIcon } from '../functions/icons';
import { useCreateApiFormModal } from '../hooks/UseForm'; import { useCreateApiFormModal } from '../hooks/UseForm';
import { useBatchCodeGenerator } from '../hooks/UseGenerator'; import { useBatchCodeGenerator } from '../hooks/UseGenerator';
@ -487,11 +485,11 @@ function BuildAllocateLineRow({
props, props,
record, record,
sourceLocation sourceLocation
}: { }: Readonly<{
props: TableFieldRowProps; props: TableFieldRowProps;
record: any; record: any;
sourceLocation: number | undefined; sourceLocation: number | undefined;
}) { }>) {
const stockField: ApiFormFieldType = useMemo(() => { const stockField: ApiFormFieldType = useMemo(() => {
return { return {
field_type: 'related field', field_type: 'related field',
@ -542,7 +540,6 @@ function BuildAllocateLineRow({
); );
return ( return (
<>
<Table.Tr key={`table-row-${record.pk}`}> <Table.Tr key={`table-row-${record.pk}`}>
<Table.Td>{partDetail}</Table.Td> <Table.Td>{partDetail}</Table.Td>
<Table.Td> <Table.Td>
@ -570,7 +567,6 @@ function BuildAllocateLineRow({
<RemoveRowButton onClick={() => props.removeFn(props.idx)} /> <RemoveRowButton onClick={() => props.removeFn(props.idx)} />
</Table.Td> </Table.Td>
</Table.Tr> </Table.Tr>
</>
); );
} }

View File

@ -197,11 +197,11 @@ function LineItemFormRow({
props, props,
record, record,
statuses statuses
}: { }: Readonly<{
props: TableFieldRowProps; props: TableFieldRowProps;
record: any; record: any;
statuses: any; statuses: any;
}) { }>) {
// Barcode Modal state // Barcode Modal state
const [opened, { open, close }] = useDisclosure(false, { const [opened, { open, close }] = useDisclosure(false, {
onClose: () => props.changeFn(props.idx, 'barcode', undefined) onClose: () => props.changeFn(props.idx, 'barcode', undefined)
@ -263,7 +263,7 @@ function LineItemFormRow({
// Barcode value // Barcode value
const [barcodeInput, setBarcodeInput] = useState<any>(''); const [barcodeInput, setBarcodeInput] = useState<any>('');
const [barcode, setBarcode] = useState<String | undefined>(undefined); const [barcode, setBarcode] = useState<string | undefined>(undefined);
// Change form value when state is altered // Change form value when state is altered
useEffect(() => { useEffect(() => {

View File

@ -6,11 +6,10 @@ import { useNavigate } from 'react-router-dom';
import { api } from '../App'; import { api } from '../App';
import { PanelType } from '../components/nav/Panel'; import { PanelType } from '../components/nav/Panel';
import { PluginContext } from '../components/plugins/PluginContext'; import { PluginContext } from '../components/plugins/PluginContext';
import { import PluginPanelContent, {
PluginPanelProps, PluginPanelProps,
isPluginPanelHidden isPluginPanelHidden
} from '../components/plugins/PluginPanel'; } from '../components/plugins/PluginPanel';
import PluginPanelContent from '../components/plugins/PluginPanel';
import { ApiEndpoints } from '../enums/ApiEndpoints'; import { ApiEndpoints } from '../enums/ApiEndpoints';
import { ModelType } from '../enums/ModelType'; import { ModelType } from '../enums/ModelType';
import { identifierString } from '../functions/conversion'; import { identifierString } from '../functions/conversion';

View File

@ -14,13 +14,12 @@ import {
Title, Title,
useMantineTheme useMantineTheme
} from '@mantine/core'; } from '@mantine/core';
import { IconReload, IconRestore } from '@tabler/icons-react'; import { IconRestore } from '@tabler/icons-react';
import { useState } from 'react'; import { useState } from 'react';
import { ColorToggle } from '../../../../components/items/ColorToggle'; import { ColorToggle } from '../../../../components/items/ColorToggle';
import { LanguageSelect } from '../../../../components/items/LanguageSelect'; import { LanguageSelect } from '../../../../components/items/LanguageSelect';
import { SizeMarks } from '../../../../defaults/defaults'; import { SizeMarks } from '../../../../defaults/defaults';
import { notYetImplemented } from '../../../../functions/notifications';
import { IS_DEV } from '../../../../main'; import { IS_DEV } from '../../../../main';
import { useLocalState } from '../../../../states/LocalState'; import { useLocalState } from '../../../../states/LocalState';
@ -32,7 +31,7 @@ const LOOKUP = Object.assign(
...Object.keys(DEFAULT_THEME.colors).map((clr) => getLkp(clr)) ...Object.keys(DEFAULT_THEME.colors).map((clr) => getLkp(clr))
); );
export function UserTheme({ height }: { height: number }) { export function UserTheme({ height }: Readonly<{ height: number }>) {
const theme = useMantineTheme(); const theme = useMantineTheme();
const [themeLoader, setThemeLoader] = useLocalState((state) => [ const [themeLoader, setThemeLoader] = useLocalState((state) => [

View File

@ -1,7 +1,6 @@
import { Trans, t } from '@lingui/macro'; import { Trans, t } from '@lingui/macro';
import { Accordion, Alert, Stack } from '@mantine/core'; import { Accordion, Alert, Stack } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons-react'; import { IconInfoCircle } from '@tabler/icons-react';
import { userInfo } from 'os';
import { lazy } from 'react'; import { lazy } from 'react';
import { StylishText } from '../../../../components/items/StylishText'; import { StylishText } from '../../../../components/items/StylishText';

View File

@ -11,7 +11,6 @@ import {
IconQrcode, IconQrcode,
IconServerCog, IconServerCog,
IconShoppingCart, IconShoppingCart,
IconSitemap,
IconTag, IconTag,
IconTools, IconTools,
IconTruckDelivery, IconTruckDelivery,

View File

@ -13,9 +13,9 @@ import { NoPricingData } from './PricingPanel';
export default function PurchaseHistoryPanel({ export default function PurchaseHistoryPanel({
part part
}: { }: Readonly<{
part: any; part: any;
}): ReactNode { }>): ReactNode {
const table = useTable('pricing-purchase-history'); const table = useTable('pricing-purchase-history');
const calculateUnitPrice = useCallback((record: any) => { const calculateUnitPrice = useCallback((record: any) => {
@ -86,13 +86,6 @@ export default function PurchaseHistoryPanel({
]; ];
}, []); }, []);
const currency: string = useMemo(() => {
if (table.records.length === 0) {
return '';
}
return table.records[0].purchase_price_currency;
}, [table.records]);
const purchaseHistoryData = useMemo(() => { const purchaseHistoryData = useMemo(() => {
return table.records.map((record: any) => { return table.records.map((record: any) => {
return { return {

View File

@ -12,7 +12,9 @@ import { DateColumn } from '../../../tables/ColumnRenderers';
import { InvenTreeTable } from '../../../tables/InvenTreeTable'; import { InvenTreeTable } from '../../../tables/InvenTreeTable';
import { NoPricingData } from './PricingPanel'; import { NoPricingData } from './PricingPanel';
export default function SaleHistoryPanel({ part }: { part: any }): ReactNode { export default function SaleHistoryPanel({
part
}: Readonly<{ part: any }>): ReactNode {
const table = useTable('pricing-sale-history'); const table = useTable('pricing-sale-history');
const columns: TableColumn[] = useMemo(() => { const columns: TableColumn[] = useMemo(() => {
@ -51,13 +53,6 @@ export default function SaleHistoryPanel({ part }: { part: any }): ReactNode {
]; ];
}, []); }, []);
const currency: string = useMemo(() => {
if (table.records.length === 0) {
return '';
}
return table.records[0].sale_price_currency;
}, [table.records]);
const saleHistoryData = useMemo(() => { const saleHistoryData = useMemo(() => {
return table.records.map((record: any) => { return table.records.map((record: any) => {
return { return {

View File

@ -34,7 +34,7 @@ export default function BuildAllocatedStockTable({
allowEdit, allowEdit,
modelTarget, modelTarget,
modelField modelField
}: { }: Readonly<{
buildId?: number; buildId?: number;
stockId?: number; stockId?: number;
partId?: number; partId?: number;
@ -43,7 +43,7 @@ export default function BuildAllocatedStockTable({
allowEdit?: boolean; allowEdit?: boolean;
modelTarget?: ModelType; modelTarget?: ModelType;
modelField?: string; modelField?: string;
}) { }>) {
const user = useUserState(); const user = useUserState();
const table = useTable('buildallocatedstock'); const table = useTable('buildallocatedstock');

View File

@ -5,7 +5,6 @@ import {
IconCircleMinus, IconCircleMinus,
IconShoppingCart, IconShoppingCart,
IconTool, IconTool,
IconTransferIn,
IconWand IconWand
} from '@tabler/icons-react'; } from '@tabler/icons-react';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
@ -37,12 +36,12 @@ export default function BuildLineTable({
build, build,
outputId, outputId,
params = {} params = {}
}: { }: Readonly<{
buildId: number; buildId: number;
build: any; build: any;
outputId?: number; outputId?: number;
params?: any; params?: any;
}) { }>) {
const table = useTable('buildline'); const table = useTable('buildline');
const user = useUserState(); const user = useUserState();
const buildStatus = useStatusCodes({ modelType: ModelType.build }); const buildStatus = useStatusCodes({ modelType: ModelType.build });
@ -441,6 +440,7 @@ export default function BuildLineTable({
const visible = production && canEdit; const visible = production && canEdit;
return [ return [
<ActionButton <ActionButton
key="auto-allocate"
icon={<IconWand />} icon={<IconWand />}
tooltip={t`Auto Allocate Stock`} tooltip={t`Auto Allocate Stock`}
hidden={!visible} hidden={!visible}
@ -450,6 +450,7 @@ export default function BuildLineTable({
}} }}
/>, />,
<ActionButton <ActionButton
key="allocate-stock"
icon={<IconArrowRight />} icon={<IconArrowRight />}
tooltip={t`Allocate Stock`} tooltip={t`Allocate Stock`}
hidden={!visible} hidden={!visible}
@ -468,6 +469,7 @@ export default function BuildLineTable({
}} }}
/>, />,
<ActionButton <ActionButton
key="deallocate-stock"
icon={<IconCircleMinus />} icon={<IconCircleMinus />}
tooltip={t`Deallocate Stock`} tooltip={t`Deallocate Stock`}
hidden={!visible} hidden={!visible}

View File

@ -28,10 +28,10 @@ import { TableHoverCard } from '../TableHoverCard';
export default function BuildOrderTestTable({ export default function BuildOrderTestTable({
buildId, buildId,
partId partId
}: { }: Readonly<{
buildId: number; buildId: number;
partId: number; partId: number;
}) { }>) {
const table = useTable('build-tests'); const table = useTable('build-tests');
const user = useUserState(); const user = useUserState();

View File

@ -34,7 +34,7 @@ type TestResultOverview = {
result: boolean; result: boolean;
}; };
export default function BuildOutputTable({ build }: { build: any }) { export default function BuildOutputTable({ build }: Readonly<{ build: any }>) {
const user = useUserState(); const user = useUserState();
const table = useTable('build-outputs'); const table = useTable('build-outputs');
@ -208,11 +208,13 @@ export default function BuildOutputTable({ build }: { build: any }) {
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="add-build-output"
tooltip={t`Add Build Output`} tooltip={t`Add Build Output`}
hidden={!user.hasAddRole(UserRoles.build)} hidden={!user.hasAddRole(UserRoles.build)}
onClick={addBuildOutput.open} onClick={addBuildOutput.open}
/>, />,
<ActionButton <ActionButton
key="complete-selected-outputs"
tooltip={t`Complete selected outputs`} tooltip={t`Complete selected outputs`}
icon={<InvenTreeIcon icon="success" />} icon={<InvenTreeIcon icon="success" />}
color="green" color="green"
@ -223,6 +225,7 @@ export default function BuildOutputTable({ build }: { build: any }) {
}} }}
/>, />,
<ActionButton <ActionButton
key="scrap-selected-outputs"
tooltip={t`Scrap selected outputs`} tooltip={t`Scrap selected outputs`}
icon={<InvenTreeIcon icon="delete" />} icon={<InvenTreeIcon icon="delete" />}
color="red" color="red"
@ -233,6 +236,7 @@ export default function BuildOutputTable({ build }: { build: any }) {
}} }}
/>, />,
<ActionButton <ActionButton
key="cancel-selected-outputs"
tooltip={t`Cancel selected outputs`} tooltip={t`Cancel selected outputs`}
icon={<InvenTreeIcon icon="cancel" />} icon={<InvenTreeIcon icon="cancel" />}
color="red" color="red"

View File

@ -29,12 +29,12 @@ export default function ExtraLineItemTable({
orderId, orderId,
currency, currency,
role role
}: { }: Readonly<{
endpoint: ApiEndpoints; endpoint: ApiEndpoints;
orderId: number; orderId: number;
currency: string; currency: string;
role: UserRoles; role: UserRoles;
}) { }>) {
const table = useTable('extra-line-item'); const table = useTable('extra-line-item');
const user = useUserState(); const user = useUserState();
@ -139,6 +139,7 @@ export default function ExtraLineItemTable({
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="add-line-item"
tooltip={t`Add Extra Line Item`} tooltip={t`Add Extra Line Item`}
hidden={!user.hasAddRole(role)} hidden={!user.hasAddRole(role)}
onClick={() => { onClick={() => {

View File

@ -30,10 +30,10 @@ import { TableHoverCard } from '../TableHoverCard';
export function PartParameterTable({ export function PartParameterTable({
partId, partId,
partLocked partLocked
}: { }: Readonly<{
partId: any; partId: any;
partLocked?: boolean; partLocked?: boolean;
}) { }>) {
const table = useTable('part-parameters'); const table = useTable('part-parameters');
const user = useUserState(); const user = useUserState();

View File

@ -8,7 +8,6 @@ import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column'; import { TableColumn } from '../Column';
import { DateColumn, ReferenceColumn, StatusColumn } from '../ColumnRenderers'; import { DateColumn, ReferenceColumn, StatusColumn } from '../ColumnRenderers';
import { StatusFilterOptions, TableFilter } from '../Filter'; import { StatusFilterOptions, TableFilter } from '../Filter';
@ -17,11 +16,10 @@ import { TableHoverCard } from '../TableHoverCard';
export default function PartPurchaseOrdersTable({ export default function PartPurchaseOrdersTable({
partId partId
}: { }: Readonly<{
partId: number; partId: number;
}) { }>) {
const table = useTable('partpurchaseorders'); const table = useTable('partpurchaseorders');
const user = useUserState();
const tableColumns: TableColumn[] = useMemo(() => { const tableColumns: TableColumn[] = useMemo(() => {
return [ return [
@ -130,7 +128,6 @@ export default function PartPurchaseOrdersTable({
}, []); }, []);
return ( return (
<>
<InvenTreeTable <InvenTreeTable
url={apiUrl(ApiEndpoints.purchase_order_line_list)} url={apiUrl(ApiEndpoints.purchase_order_line_list)}
tableState={table} tableState={table}
@ -147,6 +144,5 @@ export default function PartPurchaseOrdersTable({
tableFilters: tableFilters tableFilters: tableFilters
}} }}
/> />
</>
); );
} }

View File

@ -28,10 +28,10 @@ import { TableHoverCard } from '../TableHoverCard';
export default function PartTestTemplateTable({ export default function PartTestTemplateTable({
partId, partId,
partLocked partLocked
}: { }: Readonly<{
partId: number; partId: number;
partLocked?: boolean; partLocked?: boolean;
}) { }>) {
const table = useTable('part-test-template'); const table = useTable('part-test-template');
const user = useUserState(); const user = useUserState();
const navigate = useNavigate(); const navigate = useNavigate();
@ -234,6 +234,7 @@ export default function PartTestTemplateTable({
return [ return [
<AddItemButton <AddItemButton
key="add-test-template"
tooltip={t`Add Test Template`} tooltip={t`Add Test Template`}
onClick={() => newTestTemplate.open()} onClick={() => newTestTemplate.open()}
hidden={partLocked || !can_add} hidden={partLocked || !can_add}

View File

@ -73,7 +73,7 @@ export interface PluginI {
>; >;
} }
export function PluginDrawer({ pluginKey }: { pluginKey: Readonly<string> }) { export function PluginDrawer({ pluginKey }: Readonly<{ pluginKey: string }>) {
const { const {
instance: plugin, instance: plugin,
instanceQuery: { isFetching, error } instanceQuery: { isFetching, error }
@ -151,7 +151,7 @@ export function PluginDrawer({ pluginKey }: { pluginKey: Readonly<string> }) {
/> />
</Stack> </Stack>
) : ( ) : (
<Text color="red">{t`Plugin is not active`}</Text> <Text c="red">{t`Plugin is not active`}</Text>
)} )}
</Stack> </Stack>
</Card> </Card>
@ -207,7 +207,7 @@ export function PluginDrawer({ pluginKey }: { pluginKey: Readonly<string> }) {
/** /**
* Construct an indicator icon for a single plugin * Construct an indicator icon for a single plugin
*/ */
function PluginIcon({ plugin }: { plugin: PluginI }) { function PluginIcon({ plugin }: Readonly<{ plugin: PluginI }>) {
if (plugin?.is_installed) { if (plugin?.is_installed) {
if (plugin?.active) { if (plugin?.active) {
return ( return (
@ -514,12 +514,14 @@ export default function PluginListTable() {
return [ return [
<ActionButton <ActionButton
key="reload"
color="green" color="green"
icon={<IconRefresh />} icon={<IconRefresh />}
tooltip={t`Reload Plugins`} tooltip={t`Reload Plugins`}
onClick={reloadPlugins} onClick={reloadPlugins}
/>, />,
<ActionButton <ActionButton
key="install"
color="green" color="green"
icon={<IconPlaylistAdd />} icon={<IconPlaylistAdd />}
tooltip={t`Install Plugin`} tooltip={t`Install Plugin`}

View File

@ -34,11 +34,11 @@ export default function ReturnOrderLineItemTable({
orderId, orderId,
customerId, customerId,
currency currency
}: { }: Readonly<{
orderId: number; orderId: number;
customerId: number; customerId: number;
currency: string; currency: string;
}) { }>) {
const table = useTable('return-order-line-item'); const table = useTable('return-order-line-item');
const user = useUserState(); const user = useUserState();
@ -139,6 +139,7 @@ export default function ReturnOrderLineItemTable({
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="add-line-item"
tooltip={t`Add line item`} tooltip={t`Add line item`}
hidden={!user.hasAddRole(UserRoles.return_order)} hidden={!user.hasAddRole(UserRoles.return_order)}
onClick={() => { onClick={() => {

View File

@ -26,7 +26,7 @@ export default function SalesOrderAllocationTable({
allowEdit, allowEdit,
modelTarget, modelTarget,
modelField modelField
}: { }: Readonly<{
partId?: number; partId?: number;
stockId?: number; stockId?: number;
orderId?: number; orderId?: number;
@ -35,7 +35,7 @@ export default function SalesOrderAllocationTable({
allowEdit?: boolean; allowEdit?: boolean;
modelTarget?: ModelType; modelTarget?: ModelType;
modelField?: string; modelField?: string;
}) { }>) {
const user = useUserState(); const user = useUserState();
const table = useTable('salesorderallocations'); const table = useTable('salesorderallocations');
@ -110,7 +110,6 @@ export default function SalesOrderAllocationTable({
); );
return ( return (
<>
<InvenTreeTable <InvenTreeTable
url={apiUrl(ApiEndpoints.sales_order_allocation_list)} url={apiUrl(ApiEndpoints.sales_order_allocation_list)}
tableState={table} tableState={table}
@ -131,6 +130,5 @@ export default function SalesOrderAllocationTable({
modelType: modelTarget ?? ModelType.salesorder modelType: modelTarget ?? ModelType.salesorder
}} }}
/> />
</>
); );
} }

View File

@ -44,12 +44,12 @@ export default function SalesOrderLineItemTable({
currency, currency,
customerId, customerId,
editable editable
}: { }: Readonly<{
orderId: number; orderId: number;
currency: string; currency: string;
customerId: number; customerId: number;
editable: boolean; editable: boolean;
}) { }>) {
const user = useUserState(); const user = useUserState();
const table = useTable('sales-order-line-item'); const table = useTable('sales-order-line-item');
@ -149,7 +149,7 @@ export default function SalesOrderLineItemTable({
return ( return (
<TableHoverCard <TableHoverCard
value={<Text color={color}>{text}</Text>} value={<Text c={color}>{text}</Text>}
extra={extra} extra={extra}
title={t`Stock Information`} title={t`Stock Information`}
/> />
@ -254,6 +254,7 @@ export default function SalesOrderLineItemTable({
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="add-line-item"
tooltip={t`Add line item`} tooltip={t`Add line item`}
onClick={() => { onClick={() => {
setInitialData({ setInitialData({

View File

@ -23,9 +23,9 @@ import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
export default function SalesOrderShipmentTable({ export default function SalesOrderShipmentTable({
orderId orderId
}: { }: Readonly<{
orderId: number; orderId: number;
}) { }>) {
const user = useUserState(); const user = useUserState();
const table = useTable('sales-order-shipment'); const table = useTable('sales-order-shipment');
@ -130,6 +130,7 @@ export default function SalesOrderShipmentTable({
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="add-shipment"
tooltip={t`Add shipment`} tooltip={t`Add shipment`}
hidden={!user.hasAddRole(UserRoles.sales_order)} hidden={!user.hasAddRole(UserRoles.sales_order)}
onClick={() => { onClick={() => {

View File

@ -16,7 +16,6 @@ import {
} from '../../hooks/UseForm'; } from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column'; import { TableColumn } from '../Column';
import { DateColumn, StatusColumn } from '../ColumnRenderers'; import { DateColumn, StatusColumn } from '../ColumnRenderers';
import { StatusFilterOptions, TableFilter } from '../Filter'; import { StatusFilterOptions, TableFilter } from '../Filter';
@ -128,6 +127,7 @@ export default function ImportSesssionTable() {
const tableActions = useMemo(() => { const tableActions = useMemo(() => {
return [ return [
<AddItemButton <AddItemButton
key="create-import-session"
tooltip={t`Create Import Session`} tooltip={t`Create Import Session`}
onClick={() => newImportSession.open()} onClick={() => newImportSession.open()}
/> />

View File

@ -20,7 +20,6 @@ import {
} from '../../components/nav/DetailDrawer'; } from '../../components/nav/DetailDrawer';
import { ApiEndpoints } from '../../enums/ApiEndpoints'; import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType'; import { ModelType } from '../../enums/ModelType';
import { UserPermissions } from '../../enums/Roles';
import { import {
useCreateApiFormModal, useCreateApiFormModal,
useDeleteApiFormModal useDeleteApiFormModal
@ -51,10 +50,10 @@ export interface UserDetailI {
export function UserDrawer({ export function UserDrawer({
id, id,
refreshTable refreshTable
}: { }: Readonly<{
id: string; id: string;
refreshTable: () => void; refreshTable: () => void;
}) { }>) {
const { const {
instance: userDetail, instance: userDetail,
refreshInstance, refreshInstance,

View File

@ -31,7 +31,7 @@ type StockTrackingEntry = {
details: ReactNode; details: ReactNode;
}; };
export function StockTrackingTable({ itemId }: { itemId: number }) { export function StockTrackingTable({ itemId }: Readonly<{ itemId: number }>) {
const navigate = useNavigate(); const navigate = useNavigate();
const table = useTable('stock_tracking'); const table = useTable('stock_tracking');

View File

@ -1,26 +1,14 @@
import { t } from '@lingui/macro'; import { t } from '@lingui/macro';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { AddItemButton } from '../../components/buttons/AddItemButton';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { ModelType } from '../../enums/ModelType';
import { UserRoles } from '../../enums/Roles';
import { stockLocationFields } from '../../forms/StockForms';
import { getDetailUrl } from '../../functions/urls';
import {
useCreateApiFormModal,
useEditApiFormModal
} from '../../hooks/UseForm';
import { useTable } from '../../hooks/UseTable'; import { useTable } from '../../hooks/UseTable';
import { apiUrl } from '../../states/ApiState'; import { apiUrl } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
import { TableColumn } from '../Column'; import { TableColumn } from '../Column';
import { BooleanColumn, DescriptionColumn } from '../ColumnRenderers';
import { TableFilter } from '../Filter';
import { InvenTreeTable } from '../InvenTreeTable'; import { InvenTreeTable } from '../InvenTreeTable';
export function TestStatisticsTable({ params = {} }: { params?: any }) { export function TestStatisticsTable({
params = {}
}: Readonly<{ params?: any }>) {
const initialColumns: TableColumn[] = []; const initialColumns: TableColumn[] = [];
const [templateColumnList, setTemplateColumnList] = useState(initialColumns); const [templateColumnList, setTemplateColumnList] = useState(initialColumns);

View File

@ -1,4 +1,4 @@
import test, { Page, expect, request } from 'playwright/test'; import test, { expect } from 'playwright/test';
import { baseUrl } from './defaults.js'; import { baseUrl } from './defaults.js';
import { doQuickLogin } from './login.js'; import { doQuickLogin } from './login.js';