mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-11-03 22:55:43 +00:00 
			
		
		
		
	fix various sonarlint warnings (#8479)
Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
		@@ -30,14 +30,14 @@ export default function DashboardMenu({
 | 
			
		||||
  onStartEdit,
 | 
			
		||||
  onStartRemove,
 | 
			
		||||
  onAcceptLayout
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  editing: boolean;
 | 
			
		||||
  removing: boolean;
 | 
			
		||||
  onAddWidget: () => void;
 | 
			
		||||
  onStartEdit: () => void;
 | 
			
		||||
  onStartRemove: () => void;
 | 
			
		||||
  onAcceptLayout: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const instanceName = useInstanceName();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,12 @@ export default function DashboardWidget({
 | 
			
		||||
  editing,
 | 
			
		||||
  removing,
 | 
			
		||||
  onRemove
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  item: DashboardWidgetProps;
 | 
			
		||||
  editing: boolean;
 | 
			
		||||
  removing: boolean;
 | 
			
		||||
  onRemove: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  // TODO: Implement visibility check
 | 
			
		||||
  //     if (!props?.visible?.() == false) {
 | 
			
		||||
  //     return null;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,12 +26,12 @@ export default function DashboardWidgetDrawer({
 | 
			
		||||
  onClose,
 | 
			
		||||
  onAddWidget,
 | 
			
		||||
  currentWidgets
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  opened: boolean;
 | 
			
		||||
  onClose: () => void;
 | 
			
		||||
  onAddWidget: (widget: string) => void;
 | 
			
		||||
  currentWidgets: string[];
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  // Load available widgets
 | 
			
		||||
  const availableWidgets = useDashboardItems();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ import { StylishText } from '../../items/StylishText';
 | 
			
		||||
/**
 | 
			
		||||
 * Render a link to an external news item
 | 
			
		||||
 */
 | 
			
		||||
function NewsLink({ item }: { item: any }) {
 | 
			
		||||
function NewsLink({ item }: Readonly<{ item: any }>) {
 | 
			
		||||
  let link: string = item.link;
 | 
			
		||||
 | 
			
		||||
  if (link?.startsWith('/')) {
 | 
			
		||||
@@ -45,10 +45,10 @@ function NewsLink({ item }: { item: any }) {
 | 
			
		||||
function NewsItem({
 | 
			
		||||
  item,
 | 
			
		||||
  onMarkRead
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  item: any;
 | 
			
		||||
  onMarkRead: (id: number) => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const date: string = item.published?.split(' ')[0] ?? '';
 | 
			
		||||
  return (
 | 
			
		||||
    <Table.Tr>
 | 
			
		||||
 
 | 
			
		||||
@@ -25,12 +25,12 @@ function QueryCountWidget({
 | 
			
		||||
  title,
 | 
			
		||||
  icon,
 | 
			
		||||
  params
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  modelType: ModelType;
 | 
			
		||||
  title: string;
 | 
			
		||||
  icon?: InvenTreeIconType;
 | 
			
		||||
  params: any;
 | 
			
		||||
}): ReactNode {
 | 
			
		||||
}>): ReactNode {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,10 @@ import { LanguageToggle } from '../items/LanguageToggle';
 | 
			
		||||
export function AuthFormOptions({
 | 
			
		||||
  hostname,
 | 
			
		||||
  toggleHostEdit
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  hostname: string;
 | 
			
		||||
  toggleHostEdit: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const [server] = useServerApiState((state) => [state.server]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ function TableFieldRow({
 | 
			
		||||
  control,
 | 
			
		||||
  changeFn,
 | 
			
		||||
  removeFn
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  item: any;
 | 
			
		||||
  idx: number;
 | 
			
		||||
  errors: any;
 | 
			
		||||
@@ -34,7 +34,7 @@ function TableFieldRow({
 | 
			
		||||
  control: UseControllerReturn<FieldValues, any>;
 | 
			
		||||
  changeFn: (idx: number, key: string, value: any) => void;
 | 
			
		||||
  removeFn: (idx: number) => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  // Table fields require render function
 | 
			
		||||
  if (!definition.modelRenderer) {
 | 
			
		||||
    return (
 | 
			
		||||
@@ -62,11 +62,11 @@ export function TableFieldErrorWrapper({
 | 
			
		||||
  props,
 | 
			
		||||
  errorKey,
 | 
			
		||||
  children
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  props: TableFieldRowProps;
 | 
			
		||||
  errorKey: string;
 | 
			
		||||
  children: ReactNode;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const msg = props?.rowErrors?.[errorKey];
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ import * as classes from './GettingStartedCarousel.css';
 | 
			
		||||
import type { MenuLinkItem } from './MenuLinks';
 | 
			
		||||
import { StylishText } from './StylishText';
 | 
			
		||||
 | 
			
		||||
function StartedCard({ title, description, link }: MenuLinkItem) {
 | 
			
		||||
function StartedCard({ title, description, link }: Readonly<MenuLinkItem>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <Paper shadow='md' p='xl' radius='md' className={classes.card}>
 | 
			
		||||
      <div>
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ import { api } from '../../App';
 | 
			
		||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
 | 
			
		||||
import { apiUrl } from '../../states/ApiState';
 | 
			
		||||
 | 
			
		||||
export function LicenceView(entries: any[]) {
 | 
			
		||||
export function LicenceView(entries: Readonly<any[]>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <Stack gap='xs'>
 | 
			
		||||
      <Divider />
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,7 @@ export function NavigationDrawer({
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function DrawerContent({ closeFunc }: { closeFunc?: () => void }) {
 | 
			
		||||
function DrawerContent({ closeFunc }: Readonly<{ closeFunc?: () => void }>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
 | 
			
		||||
  const globalSettings = useGlobalSettingsState();
 | 
			
		||||
@@ -186,13 +186,11 @@ function DrawerContent({ closeFunc }: { closeFunc?: () => void }) {
 | 
			
		||||
          />
 | 
			
		||||
          <Space h='md' />
 | 
			
		||||
          {plugins.length > 0 ? (
 | 
			
		||||
            <>
 | 
			
		||||
              <MenuLinks
 | 
			
		||||
                title={t`Plugins`}
 | 
			
		||||
                links={plugins}
 | 
			
		||||
                beforeClick={closeFunc}
 | 
			
		||||
              />
 | 
			
		||||
            </>
 | 
			
		||||
            <MenuLinks
 | 
			
		||||
              title={t`Plugins`}
 | 
			
		||||
              links={plugins}
 | 
			
		||||
              beforeClick={closeFunc}
 | 
			
		||||
            />
 | 
			
		||||
          ) : (
 | 
			
		||||
            <></>
 | 
			
		||||
          )}
 | 
			
		||||
 
 | 
			
		||||
@@ -36,10 +36,10 @@ import { ModelInformationDict } from '../render/ModelType';
 | 
			
		||||
function NotificationEntry({
 | 
			
		||||
  notification,
 | 
			
		||||
  onRead
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  notification: any;
 | 
			
		||||
  onRead: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
  let link = notification.target?.link;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,10 @@ import { useGlobalSettingsState } from '../../states/SettingsState';
 | 
			
		||||
export default function PageTitle({
 | 
			
		||||
  title,
 | 
			
		||||
  subtitle
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  title?: string;
 | 
			
		||||
  subtitle?: string;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const globalSettings = useGlobalSettingsState();
 | 
			
		||||
 | 
			
		||||
  const pageTitle = useMemo(() => {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,10 @@ import type { PluginInterface } from './PluginInterface';
 | 
			
		||||
export default function LocateItemButton({
 | 
			
		||||
  stockId,
 | 
			
		||||
  locationId
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  stockId?: number;
 | 
			
		||||
  locationId?: number;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const locatePlugins = usePluginsWithMixin('locate');
 | 
			
		||||
 | 
			
		||||
  const [selectedPlugin, setSelectedPlugin] = useState<string | undefined>(
 | 
			
		||||
 
 | 
			
		||||
@@ -18,10 +18,10 @@ import PluginSettingsPanel from './PluginSettingsPanel';
 | 
			
		||||
export default function PluginDrawer({
 | 
			
		||||
  pluginKey,
 | 
			
		||||
  pluginInstance
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  pluginKey?: string;
 | 
			
		||||
  pluginInstance: PluginInterface;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const { id } = useParams();
 | 
			
		||||
 | 
			
		||||
  const pluginPrimaryKey: string = useMemo(() => {
 | 
			
		||||
@@ -53,106 +53,104 @@ export default function PluginDrawer({
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Accordion defaultValue={['plugin-details', 'plugin-settings']} multiple>
 | 
			
		||||
        <Accordion.Item value='plugin-details'>
 | 
			
		||||
    <Accordion defaultValue={['plugin-details', 'plugin-settings']} multiple>
 | 
			
		||||
      <Accordion.Item value='plugin-details'>
 | 
			
		||||
        <Accordion.Control>
 | 
			
		||||
          <StylishText size='lg'>{t`Plugin Information`}</StylishText>
 | 
			
		||||
        </Accordion.Control>
 | 
			
		||||
        <Accordion.Panel>
 | 
			
		||||
          <Stack gap='xs'>
 | 
			
		||||
            <Card withBorder>
 | 
			
		||||
              <Stack gap='md'>
 | 
			
		||||
                <Stack pos='relative' gap='xs'>
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Name`}
 | 
			
		||||
                    value={pluginInstance?.name}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Description`}
 | 
			
		||||
                    value={pluginInstance?.meta.description}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Author`}
 | 
			
		||||
                    value={pluginInstance?.meta.author}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Date`}
 | 
			
		||||
                    value={pluginInstance?.meta.pub_date}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Version`}
 | 
			
		||||
                    value={pluginInstance?.meta.version}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='boolean'
 | 
			
		||||
                    name={t`Active`}
 | 
			
		||||
                    value={pluginInstance?.active}
 | 
			
		||||
                  />
 | 
			
		||||
                </Stack>
 | 
			
		||||
              </Stack>
 | 
			
		||||
            </Card>
 | 
			
		||||
            <Card withBorder>
 | 
			
		||||
              <Stack gap='md'>
 | 
			
		||||
                <Stack pos='relative' gap='xs'>
 | 
			
		||||
                  {pluginInstance?.is_package && (
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Package Name`}
 | 
			
		||||
                      value={pluginInstance?.package_name}
 | 
			
		||||
                    />
 | 
			
		||||
                  )}
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='text'
 | 
			
		||||
                    name={t`Installation Path`}
 | 
			
		||||
                    value={pluginInstance?.meta.package_path}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='boolean'
 | 
			
		||||
                    name={t`Builtin`}
 | 
			
		||||
                    value={pluginInstance?.is_builtin}
 | 
			
		||||
                  />
 | 
			
		||||
                  <InfoItem
 | 
			
		||||
                    type='boolean'
 | 
			
		||||
                    name={t`Package`}
 | 
			
		||||
                    value={pluginInstance?.is_package}
 | 
			
		||||
                  />
 | 
			
		||||
                </Stack>
 | 
			
		||||
              </Stack>
 | 
			
		||||
            </Card>
 | 
			
		||||
          </Stack>
 | 
			
		||||
        </Accordion.Panel>
 | 
			
		||||
      </Accordion.Item>
 | 
			
		||||
      {hasSettings && (
 | 
			
		||||
        <Accordion.Item value='plugin-settings'>
 | 
			
		||||
          <Accordion.Control>
 | 
			
		||||
            <StylishText size='lg'>{t`Plugin Information`}</StylishText>
 | 
			
		||||
            <StylishText size='lg'>{t`Plugin Settings`}</StylishText>
 | 
			
		||||
          </Accordion.Control>
 | 
			
		||||
          <Accordion.Panel>
 | 
			
		||||
            <Stack gap='xs'>
 | 
			
		||||
              <Card withBorder>
 | 
			
		||||
                <Stack gap='md'>
 | 
			
		||||
                  <Stack pos='relative' gap='xs'>
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Name`}
 | 
			
		||||
                      value={pluginInstance?.name}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Description`}
 | 
			
		||||
                      value={pluginInstance?.meta.description}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Author`}
 | 
			
		||||
                      value={pluginInstance?.meta.author}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Date`}
 | 
			
		||||
                      value={pluginInstance?.meta.pub_date}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Version`}
 | 
			
		||||
                      value={pluginInstance?.meta.version}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='boolean'
 | 
			
		||||
                      name={t`Active`}
 | 
			
		||||
                      value={pluginInstance?.active}
 | 
			
		||||
                    />
 | 
			
		||||
                  </Stack>
 | 
			
		||||
                </Stack>
 | 
			
		||||
              </Card>
 | 
			
		||||
              <Card withBorder>
 | 
			
		||||
                <Stack gap='md'>
 | 
			
		||||
                  <Stack pos='relative' gap='xs'>
 | 
			
		||||
                    {pluginInstance?.is_package && (
 | 
			
		||||
                      <InfoItem
 | 
			
		||||
                        type='text'
 | 
			
		||||
                        name={t`Package Name`}
 | 
			
		||||
                        value={pluginInstance?.package_name}
 | 
			
		||||
                      />
 | 
			
		||||
                    )}
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='text'
 | 
			
		||||
                      name={t`Installation Path`}
 | 
			
		||||
                      value={pluginInstance?.meta.package_path}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='boolean'
 | 
			
		||||
                      name={t`Builtin`}
 | 
			
		||||
                      value={pluginInstance?.is_builtin}
 | 
			
		||||
                    />
 | 
			
		||||
                    <InfoItem
 | 
			
		||||
                      type='boolean'
 | 
			
		||||
                      name={t`Package`}
 | 
			
		||||
                      value={pluginInstance?.is_package}
 | 
			
		||||
                    />
 | 
			
		||||
                  </Stack>
 | 
			
		||||
                </Stack>
 | 
			
		||||
              </Card>
 | 
			
		||||
            </Stack>
 | 
			
		||||
            <Card withBorder>
 | 
			
		||||
              <PluginSettingList pluginKey={pluginPrimaryKey} />
 | 
			
		||||
            </Card>
 | 
			
		||||
          </Accordion.Panel>
 | 
			
		||||
        </Accordion.Item>
 | 
			
		||||
        {hasSettings && (
 | 
			
		||||
          <Accordion.Item value='plugin-settings'>
 | 
			
		||||
            <Accordion.Control>
 | 
			
		||||
              <StylishText size='lg'>{t`Plugin Settings`}</StylishText>
 | 
			
		||||
            </Accordion.Control>
 | 
			
		||||
            <Accordion.Panel>
 | 
			
		||||
              <Card withBorder>
 | 
			
		||||
                <PluginSettingList pluginKey={pluginPrimaryKey} />
 | 
			
		||||
              </Card>
 | 
			
		||||
            </Accordion.Panel>
 | 
			
		||||
          </Accordion.Item>
 | 
			
		||||
        )}
 | 
			
		||||
        {pluginAdmin?.source && (
 | 
			
		||||
          <Accordion.Item value='plugin-custom'>
 | 
			
		||||
            <Accordion.Control>
 | 
			
		||||
              <StylishText size='lg'>{t`Plugin Configuration`}</StylishText>
 | 
			
		||||
            </Accordion.Control>
 | 
			
		||||
            <Accordion.Panel>
 | 
			
		||||
              <Card withBorder>
 | 
			
		||||
                <PluginSettingsPanel pluginAdmin={pluginAdmin} />
 | 
			
		||||
              </Card>
 | 
			
		||||
            </Accordion.Panel>
 | 
			
		||||
          </Accordion.Item>
 | 
			
		||||
        )}
 | 
			
		||||
      </Accordion>
 | 
			
		||||
    </>
 | 
			
		||||
      )}
 | 
			
		||||
      {pluginAdmin?.source && (
 | 
			
		||||
        <Accordion.Item value='plugin-custom'>
 | 
			
		||||
          <Accordion.Control>
 | 
			
		||||
            <StylishText size='lg'>{t`Plugin Configuration`}</StylishText>
 | 
			
		||||
          </Accordion.Control>
 | 
			
		||||
          <Accordion.Panel>
 | 
			
		||||
            <Card withBorder>
 | 
			
		||||
              <PluginSettingsPanel pluginAdmin={pluginAdmin} />
 | 
			
		||||
            </Card>
 | 
			
		||||
          </Accordion.Panel>
 | 
			
		||||
        </Accordion.Item>
 | 
			
		||||
      )}
 | 
			
		||||
    </Accordion>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,9 @@ export interface PluginAdminInterface {
 | 
			
		||||
 */
 | 
			
		||||
export default function PluginSettingsPanel({
 | 
			
		||||
  pluginAdmin
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  pluginAdmin: PluginAdminInterface;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const pluginContext = useInvenTreeContext();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
 
 | 
			
		||||
@@ -21,11 +21,11 @@ export default function RemoteComponent({
 | 
			
		||||
  source,
 | 
			
		||||
  defaultFunctionName,
 | 
			
		||||
  context
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  source: string;
 | 
			
		||||
  defaultFunctionName: string;
 | 
			
		||||
  context: InvenTreeContext;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const componentRef = useRef<HTMLDivElement>();
 | 
			
		||||
 | 
			
		||||
  const [renderingError, setRenderingError] = useState<string | undefined>(
 | 
			
		||||
@@ -78,28 +78,23 @@ export default function RemoteComponent({
 | 
			
		||||
  }, [sourceFile, functionName, context]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Boundary
 | 
			
		||||
        label={identifierString(
 | 
			
		||||
          `RemoteComponent-${sourceFile}-${functionName}`
 | 
			
		||||
    <Boundary
 | 
			
		||||
      label={identifierString(`RemoteComponent-${sourceFile}-${functionName}`)}
 | 
			
		||||
    >
 | 
			
		||||
      <Stack gap='xs'>
 | 
			
		||||
        {renderingError && (
 | 
			
		||||
          <Alert
 | 
			
		||||
            color='red'
 | 
			
		||||
            title={t`Error Loading Content`}
 | 
			
		||||
            icon={<IconExclamationCircle />}
 | 
			
		||||
          >
 | 
			
		||||
            <Text>
 | 
			
		||||
              {t`Error occurred while loading plugin content`}: {renderingError}
 | 
			
		||||
            </Text>
 | 
			
		||||
          </Alert>
 | 
			
		||||
        )}
 | 
			
		||||
      >
 | 
			
		||||
        <Stack gap='xs'>
 | 
			
		||||
          {renderingError && (
 | 
			
		||||
            <Alert
 | 
			
		||||
              color='red'
 | 
			
		||||
              title={t`Error Loading Content`}
 | 
			
		||||
              icon={<IconExclamationCircle />}
 | 
			
		||||
            >
 | 
			
		||||
              <Text>
 | 
			
		||||
                {t`Error occurred while loading plugin content`}:{' '}
 | 
			
		||||
                {renderingError}
 | 
			
		||||
              </Text>
 | 
			
		||||
            </Alert>
 | 
			
		||||
          )}
 | 
			
		||||
          <div ref={componentRef as any} />
 | 
			
		||||
        </Stack>
 | 
			
		||||
      </Boundary>
 | 
			
		||||
    </>
 | 
			
		||||
        <div ref={componentRef as any} />
 | 
			
		||||
      </Stack>
 | 
			
		||||
    </Boundary>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -121,11 +121,11 @@ function SalesOrderAllocateLineRow({
 | 
			
		||||
  props,
 | 
			
		||||
  record,
 | 
			
		||||
  sourceLocation
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  props: TableFieldRowProps;
 | 
			
		||||
  record: any;
 | 
			
		||||
  sourceLocation?: number | null;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  // Statically defined field for selecting the stock item
 | 
			
		||||
  const stockItemField: ApiFormFieldType = useMemo(() => {
 | 
			
		||||
    return {
 | 
			
		||||
@@ -360,7 +360,7 @@ export function useSalesOrderAllocationFields({
 | 
			
		||||
  shipment
 | 
			
		||||
}: {
 | 
			
		||||
  orderId?: number;
 | 
			
		||||
  shipment: any | null;
 | 
			
		||||
  shipment: any;
 | 
			
		||||
}): ApiFormFieldSet {
 | 
			
		||||
  return useMemo(() => {
 | 
			
		||||
    return {
 | 
			
		||||
 
 | 
			
		||||
@@ -7,36 +7,34 @@ import { useUserState } from '../../states/UserState';
 | 
			
		||||
import PartBuildAllocationsTable from '../../tables/part/PartBuildAllocationsTable';
 | 
			
		||||
import PartSalesAllocationsTable from '../../tables/part/PartSalesAllocationsTable';
 | 
			
		||||
 | 
			
		||||
export default function PartAllocationPanel({ part }: { part: any }) {
 | 
			
		||||
export default function PartAllocationPanel({ part }: Readonly<{ part: any }>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Accordion
 | 
			
		||||
        multiple={true}
 | 
			
		||||
        defaultValue={['buildallocations', 'salesallocations']}
 | 
			
		||||
      >
 | 
			
		||||
        {part.component && user.hasViewRole(UserRoles.build) && (
 | 
			
		||||
          <Accordion.Item value='buildallocations' key='buildallocations'>
 | 
			
		||||
            <Accordion.Control>
 | 
			
		||||
              <StylishText size='lg'>{t`Build Order Allocations`}</StylishText>
 | 
			
		||||
            </Accordion.Control>
 | 
			
		||||
            <Accordion.Panel>
 | 
			
		||||
              <PartBuildAllocationsTable partId={part.pk} />
 | 
			
		||||
            </Accordion.Panel>
 | 
			
		||||
          </Accordion.Item>
 | 
			
		||||
        )}
 | 
			
		||||
        {part.salable && user.hasViewRole(UserRoles.sales_order) && (
 | 
			
		||||
          <Accordion.Item value='salesallocations' key='salesallocations'>
 | 
			
		||||
            <Accordion.Control>
 | 
			
		||||
              <StylishText size='lg'>{t`Sales Order Allocations`}</StylishText>
 | 
			
		||||
            </Accordion.Control>
 | 
			
		||||
            <Accordion.Panel>
 | 
			
		||||
              <PartSalesAllocationsTable partId={part.pk} />
 | 
			
		||||
            </Accordion.Panel>
 | 
			
		||||
          </Accordion.Item>
 | 
			
		||||
        )}
 | 
			
		||||
      </Accordion>
 | 
			
		||||
    </>
 | 
			
		||||
    <Accordion
 | 
			
		||||
      multiple={true}
 | 
			
		||||
      defaultValue={['buildallocations', 'salesallocations']}
 | 
			
		||||
    >
 | 
			
		||||
      {part.component && user.hasViewRole(UserRoles.build) && (
 | 
			
		||||
        <Accordion.Item value='buildallocations' key='buildallocations'>
 | 
			
		||||
          <Accordion.Control>
 | 
			
		||||
            <StylishText size='lg'>{t`Build Order Allocations`}</StylishText>
 | 
			
		||||
          </Accordion.Control>
 | 
			
		||||
          <Accordion.Panel>
 | 
			
		||||
            <PartBuildAllocationsTable partId={part.pk} />
 | 
			
		||||
          </Accordion.Panel>
 | 
			
		||||
        </Accordion.Item>
 | 
			
		||||
      )}
 | 
			
		||||
      {part.salable && user.hasViewRole(UserRoles.sales_order) && (
 | 
			
		||||
        <Accordion.Item value='salesallocations' key='salesallocations'>
 | 
			
		||||
          <Accordion.Control>
 | 
			
		||||
            <StylishText size='lg'>{t`Sales Order Allocations`}</StylishText>
 | 
			
		||||
          </Accordion.Control>
 | 
			
		||||
          <Accordion.Panel>
 | 
			
		||||
            <PartSalesAllocationsTable partId={part.pk} />
 | 
			
		||||
          </Accordion.Panel>
 | 
			
		||||
        </Accordion.Item>
 | 
			
		||||
      )}
 | 
			
		||||
    </Accordion>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ import { TableHoverCard } from '../../tables/TableHoverCard';
 | 
			
		||||
/*
 | 
			
		||||
 * Render a tooltip for the chart, with correct date information
 | 
			
		||||
 */
 | 
			
		||||
function ChartTooltip({ label, payload }: ChartTooltipProps) {
 | 
			
		||||
function ChartTooltip({ label, payload }: Readonly<ChartTooltipProps>) {
 | 
			
		||||
  if (!payload) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
@@ -56,7 +56,9 @@ function ChartTooltip({ label, payload }: ChartTooltipProps) {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function PartSchedulingDetail({ part }: { part: any }) {
 | 
			
		||||
export default function PartSchedulingDetail({
 | 
			
		||||
  part
 | 
			
		||||
}: Readonly<{ part: any }>) {
 | 
			
		||||
  const table = useTable('part-scheduling');
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ import { RowDeleteAction, RowEditAction } from '../../tables/RowActions';
 | 
			
		||||
/*
 | 
			
		||||
 * Render a tooltip for the chart, with correct date information
 | 
			
		||||
 */
 | 
			
		||||
function ChartTooltip({ label, payload }: ChartTooltipProps) {
 | 
			
		||||
function ChartTooltip({ label, payload }: Readonly<ChartTooltipProps>) {
 | 
			
		||||
  const formattedLabel: string = useMemo(() => {
 | 
			
		||||
    if (label && typeof label === 'number') {
 | 
			
		||||
      return formatDate(new Date(label).toISOString()) ?? label;
 | 
			
		||||
@@ -66,7 +66,9 @@ function ChartTooltip({ label, payload }: ChartTooltipProps) {
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function PartStocktakeDetail({ partId }: { partId: number }) {
 | 
			
		||||
export default function PartStocktakeDetail({
 | 
			
		||||
  partId
 | 
			
		||||
}: Readonly<{ partId: number }>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const table = useTable('part-stocktake');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,9 @@ import { StylishText } from '../../components/items/StylishText';
 | 
			
		||||
import { ManufacturerPartTable } from '../../tables/purchasing/ManufacturerPartTable';
 | 
			
		||||
import { SupplierPartTable } from '../../tables/purchasing/SupplierPartTable';
 | 
			
		||||
 | 
			
		||||
export default function PartSupplierDetail({ partId }: { partId: number }) {
 | 
			
		||||
export default function PartSupplierDetail({
 | 
			
		||||
  partId
 | 
			
		||||
}: Readonly<{ partId: number }>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <Accordion multiple defaultValue={['part-suppliers', 'part-manufacturers']}>
 | 
			
		||||
      <Accordion.Item value='part-suppliers'>
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ export default function InvenTreeTableHeader({
 | 
			
		||||
  columns,
 | 
			
		||||
  filters,
 | 
			
		||||
  toggleColumn
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  tableUrl: string;
 | 
			
		||||
  tableState: TableState;
 | 
			
		||||
  tableProps: InvenTreeTableProps<any>;
 | 
			
		||||
@@ -49,7 +49,7 @@ export default function InvenTreeTableHeader({
 | 
			
		||||
  columns: any;
 | 
			
		||||
  filters: TableFilter[];
 | 
			
		||||
  toggleColumn: (column: string) => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  // Filter list visibility
 | 
			
		||||
  const [filtersVisible, setFiltersVisible] = useState<boolean>(false);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,10 +4,10 @@ import { IconChevronDown, IconChevronRight } from '@tabler/icons-react';
 | 
			
		||||
export default function RowExpansionIcon({
 | 
			
		||||
  enabled,
 | 
			
		||||
  expanded
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  enabled: boolean;
 | 
			
		||||
  expanded: boolean;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <ActionIcon size='sm' variant='transparent' disabled={!enabled}>
 | 
			
		||||
      {expanded ? <IconChevronDown /> : <IconChevronRight />}
 | 
			
		||||
 
 | 
			
		||||
@@ -56,11 +56,11 @@ export function BuildLineSubTable({
 | 
			
		||||
  lineItem,
 | 
			
		||||
  onEditAllocation,
 | 
			
		||||
  onDeleteAllocation
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  lineItem: any;
 | 
			
		||||
  onEditAllocation?: (pk: number) => void;
 | 
			
		||||
  onDeleteAllocation?: (pk: number) => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -61,61 +61,59 @@ function OutputAllocationDrawer({
 | 
			
		||||
  output,
 | 
			
		||||
  opened,
 | 
			
		||||
  close
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  build: any;
 | 
			
		||||
  output: any;
 | 
			
		||||
  opened: boolean;
 | 
			
		||||
  close: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Drawer
 | 
			
		||||
        position='bottom'
 | 
			
		||||
        size='lg'
 | 
			
		||||
        title={
 | 
			
		||||
          <Group p='md' wrap='nowrap' justify='space-apart'>
 | 
			
		||||
            <StylishText size='lg'>{t`Build Output Stock Allocation`}</StylishText>
 | 
			
		||||
            <Space h='lg' />
 | 
			
		||||
            <PartColumn part={build.part_detail} />
 | 
			
		||||
            {output?.serial && (
 | 
			
		||||
              <Text size='sm'>
 | 
			
		||||
                {t`Serial Number`}: {output.serial}
 | 
			
		||||
              </Text>
 | 
			
		||||
            )}
 | 
			
		||||
            {output?.batch && (
 | 
			
		||||
              <Text size='sm'>
 | 
			
		||||
                {t`Batch Code`}: {output.batch}
 | 
			
		||||
              </Text>
 | 
			
		||||
            )}
 | 
			
		||||
            <Space h='lg' />
 | 
			
		||||
          </Group>
 | 
			
		||||
    <Drawer
 | 
			
		||||
      position='bottom'
 | 
			
		||||
      size='lg'
 | 
			
		||||
      title={
 | 
			
		||||
        <Group p='md' wrap='nowrap' justify='space-apart'>
 | 
			
		||||
          <StylishText size='lg'>{t`Build Output Stock Allocation`}</StylishText>
 | 
			
		||||
          <Space h='lg' />
 | 
			
		||||
          <PartColumn part={build.part_detail} />
 | 
			
		||||
          {output?.serial && (
 | 
			
		||||
            <Text size='sm'>
 | 
			
		||||
              {t`Serial Number`}: {output.serial}
 | 
			
		||||
            </Text>
 | 
			
		||||
          )}
 | 
			
		||||
          {output?.batch && (
 | 
			
		||||
            <Text size='sm'>
 | 
			
		||||
              {t`Batch Code`}: {output.batch}
 | 
			
		||||
            </Text>
 | 
			
		||||
          )}
 | 
			
		||||
          <Space h='lg' />
 | 
			
		||||
        </Group>
 | 
			
		||||
      }
 | 
			
		||||
      opened={opened}
 | 
			
		||||
      onClose={close}
 | 
			
		||||
      withCloseButton
 | 
			
		||||
      closeOnEscape
 | 
			
		||||
      closeOnClickOutside
 | 
			
		||||
      styles={{
 | 
			
		||||
        header: {
 | 
			
		||||
          width: '100%'
 | 
			
		||||
        },
 | 
			
		||||
        title: {
 | 
			
		||||
          width: '100%'
 | 
			
		||||
        }
 | 
			
		||||
        opened={opened}
 | 
			
		||||
        onClose={close}
 | 
			
		||||
        withCloseButton
 | 
			
		||||
        closeOnEscape
 | 
			
		||||
        closeOnClickOutside
 | 
			
		||||
        styles={{
 | 
			
		||||
          header: {
 | 
			
		||||
            width: '100%'
 | 
			
		||||
          },
 | 
			
		||||
          title: {
 | 
			
		||||
            width: '100%'
 | 
			
		||||
          }
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <Divider />
 | 
			
		||||
        <Paper p='md'>
 | 
			
		||||
          <BuildLineTable
 | 
			
		||||
            build={build}
 | 
			
		||||
            output={output}
 | 
			
		||||
            params={{
 | 
			
		||||
              tracked: true
 | 
			
		||||
            }}
 | 
			
		||||
          />
 | 
			
		||||
        </Paper>
 | 
			
		||||
      </Drawer>
 | 
			
		||||
    </>
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      <Divider />
 | 
			
		||||
      <Paper p='md'>
 | 
			
		||||
        <BuildLineTable
 | 
			
		||||
          build={build}
 | 
			
		||||
          output={output}
 | 
			
		||||
          params={{
 | 
			
		||||
            tracked: true
 | 
			
		||||
          }}
 | 
			
		||||
        />
 | 
			
		||||
      </Paper>
 | 
			
		||||
    </Drawer>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,9 +27,9 @@ import { BuildLineSubTable } from '../build/BuildLineTable';
 | 
			
		||||
 */
 | 
			
		||||
export default function PartBuildAllocationsTable({
 | 
			
		||||
  partId
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  partId: number;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
  const table = useTable('part-build-allocations');
 | 
			
		||||
@@ -106,25 +106,23 @@ export default function PartBuildAllocationsTable({
 | 
			
		||||
  }, [table.isRowExpanded]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <InvenTreeTable
 | 
			
		||||
        url={apiUrl(ApiEndpoints.build_line_list)}
 | 
			
		||||
        tableState={table}
 | 
			
		||||
        columns={tableColumns}
 | 
			
		||||
        props={{
 | 
			
		||||
          minHeight: 200,
 | 
			
		||||
          params: {
 | 
			
		||||
            part: partId,
 | 
			
		||||
            consumable: false,
 | 
			
		||||
            build_detail: true,
 | 
			
		||||
            order_outstanding: true
 | 
			
		||||
          },
 | 
			
		||||
          enableColumnSwitching: false,
 | 
			
		||||
          enableSearch: false,
 | 
			
		||||
          rowActions: rowActions,
 | 
			
		||||
          rowExpansion: rowExpansion
 | 
			
		||||
        }}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
    <InvenTreeTable
 | 
			
		||||
      url={apiUrl(ApiEndpoints.build_line_list)}
 | 
			
		||||
      tableState={table}
 | 
			
		||||
      columns={tableColumns}
 | 
			
		||||
      props={{
 | 
			
		||||
        minHeight: 200,
 | 
			
		||||
        params: {
 | 
			
		||||
          part: partId,
 | 
			
		||||
          consumable: false,
 | 
			
		||||
          build_detail: true,
 | 
			
		||||
          order_outstanding: true
 | 
			
		||||
        },
 | 
			
		||||
        enableColumnSwitching: false,
 | 
			
		||||
        enableSearch: false,
 | 
			
		||||
        rowActions: rowActions,
 | 
			
		||||
        rowExpansion: rowExpansion
 | 
			
		||||
      }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,9 @@ import SalesOrderAllocationTable from '../sales/SalesOrderAllocationTable';
 | 
			
		||||
 | 
			
		||||
export default function PartSalesAllocationsTable({
 | 
			
		||||
  partId
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  partId: number;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
  const navigate = useNavigate();
 | 
			
		||||
  const table = useTable('part-sales-allocations');
 | 
			
		||||
@@ -109,24 +109,22 @@ export default function PartSalesAllocationsTable({
 | 
			
		||||
  }, [table.isRowExpanded]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <InvenTreeTable
 | 
			
		||||
        url={apiUrl(ApiEndpoints.sales_order_line_list)}
 | 
			
		||||
        tableState={table}
 | 
			
		||||
        columns={tableColumns}
 | 
			
		||||
        props={{
 | 
			
		||||
          minHeight: 200,
 | 
			
		||||
          params: {
 | 
			
		||||
            part: partId,
 | 
			
		||||
            order_detail: true,
 | 
			
		||||
            order_outstanding: true
 | 
			
		||||
          },
 | 
			
		||||
          enableSearch: false,
 | 
			
		||||
          enableColumnSwitching: false,
 | 
			
		||||
          rowExpansion: rowExpansion,
 | 
			
		||||
          rowActions: rowActions
 | 
			
		||||
        }}
 | 
			
		||||
      />
 | 
			
		||||
    </>
 | 
			
		||||
    <InvenTreeTable
 | 
			
		||||
      url={apiUrl(ApiEndpoints.sales_order_line_list)}
 | 
			
		||||
      tableState={table}
 | 
			
		||||
      columns={tableColumns}
 | 
			
		||||
      props={{
 | 
			
		||||
        minHeight: 200,
 | 
			
		||||
        params: {
 | 
			
		||||
          part: partId,
 | 
			
		||||
          order_detail: true,
 | 
			
		||||
          order_outstanding: true
 | 
			
		||||
        },
 | 
			
		||||
        enableSearch: false,
 | 
			
		||||
        enableColumnSwitching: false,
 | 
			
		||||
        rowExpansion: rowExpansion,
 | 
			
		||||
        rowActions: rowActions
 | 
			
		||||
      }}
 | 
			
		||||
    />
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ import { RowDeleteAction } from '../RowActions';
 | 
			
		||||
/*
 | 
			
		||||
 * Render detail information for a particular barcode scan result.
 | 
			
		||||
 */
 | 
			
		||||
function BarcodeScanDetail({ scan }: { scan: any }) {
 | 
			
		||||
function BarcodeScanDetail({ scan }: Readonly<{ scan: any }>) {
 | 
			
		||||
  const dataStyle: MantineStyleProp = {
 | 
			
		||||
    textWrap: 'wrap',
 | 
			
		||||
    lineBreak: 'auto',
 | 
			
		||||
@@ -51,93 +51,91 @@ function BarcodeScanDetail({ scan }: { scan: any }) {
 | 
			
		||||
  }, [scan.context]);
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <Stack gap='xs'>
 | 
			
		||||
        <Divider />
 | 
			
		||||
        <Table>
 | 
			
		||||
          <Table.Tbody>
 | 
			
		||||
    <Stack gap='xs'>
 | 
			
		||||
      <Divider />
 | 
			
		||||
      <Table>
 | 
			
		||||
        <Table.Tbody>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Td colSpan={2}>
 | 
			
		||||
              <StylishText size='sm'>{t`Barcode Information`}</StylishText>
 | 
			
		||||
            </Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Th>{t`Barcode`}</Table.Th>
 | 
			
		||||
            <Table.Td>
 | 
			
		||||
              <Text size='sm' style={dataStyle}>
 | 
			
		||||
                {scan.data}
 | 
			
		||||
              </Text>
 | 
			
		||||
            </Table.Td>
 | 
			
		||||
            <Table.Td>
 | 
			
		||||
              <CopyButton value={scan.data} size='xs' />
 | 
			
		||||
            </Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Th>{t`Timestamp`}</Table.Th>
 | 
			
		||||
            <Table.Td>{scan.timestamp}</Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Th>{t`User`}</Table.Th>
 | 
			
		||||
            <Table.Td>
 | 
			
		||||
              <RenderUser instance={scan.user_detail} />
 | 
			
		||||
            </Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Th>{t`Endpoint`}</Table.Th>
 | 
			
		||||
            <Table.Td>{scan.endpoint}</Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          <Table.Tr>
 | 
			
		||||
            <Table.Th>{t`Result`}</Table.Th>
 | 
			
		||||
            <Table.Td>
 | 
			
		||||
              <PassFailButton value={scan.result} />
 | 
			
		||||
            </Table.Td>
 | 
			
		||||
          </Table.Tr>
 | 
			
		||||
          {hasContextData && (
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Td colSpan={2}>
 | 
			
		||||
                <StylishText size='sm'>{t`Barcode Information`}</StylishText>
 | 
			
		||||
                <StylishText size='sm'>{t`Context`}</StylishText>
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th>{t`Barcode`}</Table.Th>
 | 
			
		||||
              <Table.Td>
 | 
			
		||||
                <Text size='sm' style={dataStyle}>
 | 
			
		||||
                  {scan.data}
 | 
			
		||||
                </Text>
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
              <Table.Td>
 | 
			
		||||
                <CopyButton value={scan.data} size='xs' />
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th>{t`Timestamp`}</Table.Th>
 | 
			
		||||
              <Table.Td>{scan.timestamp}</Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th>{t`User`}</Table.Th>
 | 
			
		||||
              <Table.Td>
 | 
			
		||||
                <RenderUser instance={scan.user_detail} />
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th>{t`Endpoint`}</Table.Th>
 | 
			
		||||
              <Table.Td>{scan.endpoint}</Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Th>{t`Result`}</Table.Th>
 | 
			
		||||
              <Table.Td>
 | 
			
		||||
                <PassFailButton value={scan.result} />
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
            {hasContextData && (
 | 
			
		||||
              <Table.Tr>
 | 
			
		||||
                <Table.Td colSpan={2}>
 | 
			
		||||
                  <StylishText size='sm'>{t`Context`}</StylishText>
 | 
			
		||||
          )}
 | 
			
		||||
          {hasContextData &&
 | 
			
		||||
            Object.keys(scan.context).map((key) => (
 | 
			
		||||
              <Table.Tr key={key}>
 | 
			
		||||
                <Table.Th>{key}</Table.Th>
 | 
			
		||||
                <Table.Td>
 | 
			
		||||
                  <Text size='sm' style={dataStyle}>
 | 
			
		||||
                    {scan.context[key]}
 | 
			
		||||
                  </Text>
 | 
			
		||||
                </Table.Td>
 | 
			
		||||
                <Table.Td>
 | 
			
		||||
                  <CopyButton value={scan.context[key]} size='xs' />
 | 
			
		||||
                </Table.Td>
 | 
			
		||||
              </Table.Tr>
 | 
			
		||||
            )}
 | 
			
		||||
            {hasContextData &&
 | 
			
		||||
              Object.keys(scan.context).map((key) => (
 | 
			
		||||
                <Table.Tr key={key}>
 | 
			
		||||
                  <Table.Th>{key}</Table.Th>
 | 
			
		||||
                  <Table.Td>
 | 
			
		||||
                    <Text size='sm' style={dataStyle}>
 | 
			
		||||
                      {scan.context[key]}
 | 
			
		||||
                    </Text>
 | 
			
		||||
                  </Table.Td>
 | 
			
		||||
                  <Table.Td>
 | 
			
		||||
                    <CopyButton value={scan.context[key]} size='xs' />
 | 
			
		||||
                  </Table.Td>
 | 
			
		||||
                </Table.Tr>
 | 
			
		||||
              ))}
 | 
			
		||||
            {hasResponseData && (
 | 
			
		||||
              <Table.Tr>
 | 
			
		||||
                <Table.Td colSpan={2}>
 | 
			
		||||
                  <StylishText size='sm'>{t`Response`}</StylishText>
 | 
			
		||||
            ))}
 | 
			
		||||
          {hasResponseData && (
 | 
			
		||||
            <Table.Tr>
 | 
			
		||||
              <Table.Td colSpan={2}>
 | 
			
		||||
                <StylishText size='sm'>{t`Response`}</StylishText>
 | 
			
		||||
              </Table.Td>
 | 
			
		||||
            </Table.Tr>
 | 
			
		||||
          )}
 | 
			
		||||
          {hasResponseData &&
 | 
			
		||||
            Object.keys(scan.response).map((key) => (
 | 
			
		||||
              <Table.Tr key={key}>
 | 
			
		||||
                <Table.Th>{key}</Table.Th>
 | 
			
		||||
                <Table.Td>
 | 
			
		||||
                  <Text size='sm' style={dataStyle}>
 | 
			
		||||
                    {scan.response[key]}
 | 
			
		||||
                  </Text>
 | 
			
		||||
                </Table.Td>
 | 
			
		||||
                <Table.Td>
 | 
			
		||||
                  <CopyButton value={scan.response[key]} size='xs' />
 | 
			
		||||
                </Table.Td>
 | 
			
		||||
              </Table.Tr>
 | 
			
		||||
            )}
 | 
			
		||||
            {hasResponseData &&
 | 
			
		||||
              Object.keys(scan.response).map((key) => (
 | 
			
		||||
                <Table.Tr key={key}>
 | 
			
		||||
                  <Table.Th>{key}</Table.Th>
 | 
			
		||||
                  <Table.Td>
 | 
			
		||||
                    <Text size='sm' style={dataStyle}>
 | 
			
		||||
                      {scan.response[key]}
 | 
			
		||||
                    </Text>
 | 
			
		||||
                  </Table.Td>
 | 
			
		||||
                  <Table.Td>
 | 
			
		||||
                    <CopyButton value={scan.response[key]} size='xs' />
 | 
			
		||||
                  </Table.Td>
 | 
			
		||||
                </Table.Tr>
 | 
			
		||||
              ))}
 | 
			
		||||
          </Table.Tbody>
 | 
			
		||||
        </Table>
 | 
			
		||||
      </Stack>
 | 
			
		||||
    </>
 | 
			
		||||
            ))}
 | 
			
		||||
        </Table.Tbody>
 | 
			
		||||
      </Table>
 | 
			
		||||
    </Stack>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import type { TableColumn } from '../Column';
 | 
			
		||||
import { InvenTreeTable } from '../InvenTreeTable';
 | 
			
		||||
import { type RowAction, RowDeleteAction } from '../RowActions';
 | 
			
		||||
 | 
			
		||||
function ErrorDetail({ errorId }: { errorId?: number }) {
 | 
			
		||||
function ErrorDetail({ errorId }: Readonly<{ errorId?: number }>) {
 | 
			
		||||
  const { id } = useParams();
 | 
			
		||||
 | 
			
		||||
  const errorPrimaryKey = useMemo(() => {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,9 @@ import { InvenTreeTable } from '../InvenTreeTable';
 | 
			
		||||
 | 
			
		||||
export default function FailedTasksTable({
 | 
			
		||||
  onRecordsUpdated
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  onRecordsUpdated: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const table = useTable('tasks-failed');
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,9 +10,9 @@ import { InvenTreeTable } from '../InvenTreeTable';
 | 
			
		||||
 | 
			
		||||
export default function PendingTasksTable({
 | 
			
		||||
  onRecordsUpdated
 | 
			
		||||
}: {
 | 
			
		||||
}: Readonly<{
 | 
			
		||||
  onRecordsUpdated: () => void;
 | 
			
		||||
}) {
 | 
			
		||||
}>) {
 | 
			
		||||
  const table = useTable('tasks-pending');
 | 
			
		||||
  const user = useUserState();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user