2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-07-06 07:00:39 +00:00

Merge branch 'master' into ci-add-zimor

This commit is contained in:
Matthias Mair
2024-12-09 19:12:00 +01:00
committed by GitHub
92 changed files with 29459 additions and 27967 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2138,7 +2138,7 @@ class StockItem(
self.add_tracking_entry(tracking_code, user, notes=notes, deltas=tracking_info)
self.save()
self.save(add_note=False)
# Trigger event for the plugin system
trigger_event(
+3 -3
View File
@@ -297,9 +297,9 @@ distlib==0.3.9 \
--hash=sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87 \
--hash=sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403
# via virtualenv
django==4.2.16 \
--hash=sha256:1ddc333a16fc139fd253035a1606bb24261951bbc3a6ca256717fa06cc41a898 \
--hash=sha256:6f1616c2786c408ce86ab7e10f792b8f15742f7b7b7460243929cb371e7f1dad
django==4.2.17 \
--hash=sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0 \
--hash=sha256:6b56d834cc94c8b21a8f4e775064896be3b4a4ca387f2612d4406a5927cd2fdc
# via
# -c src/backend/requirements.txt
# django-admin-shell
+3 -3
View File
@@ -401,9 +401,9 @@ diff-match-patch==20241021 \
dj-rest-auth==7.0.0 \
--hash=sha256:08dbc03a35223872da9f59bc2d7a71bec2e721aa69f7cdc84c7a329aeae1f86e
# via -r src/backend/requirements.in
django==4.2.16 \
--hash=sha256:1ddc333a16fc139fd253035a1606bb24261951bbc3a6ca256717fa06cc41a898 \
--hash=sha256:6f1616c2786c408ce86ab7e10f792b8f15742f7b7b7460243929cb371e7f1dad
django==4.2.17 \
--hash=sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0 \
--hash=sha256:6b56d834cc94c8b21a8f4e775064896be3b4a4ca387f2612d4406a5927cd2fdc
# via
# -r src/backend/requirements.in
# dj-rest-auth
@@ -3,8 +3,8 @@ import { IconUserStar } from '@tabler/icons-react';
import { useCallback, useMemo } from 'react';
import type { ModelType } from '../../enums/ModelType';
import { generateUrl } from '../../functions/urls';
import { useServerApiState } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState';
import { useUserState } from '../../states/UserState';
import { ModelInformationDict } from '../render/ModelType';
import { ActionButton } from './ActionButton';
@@ -56,16 +56,14 @@ export default function AdminButton(props: Readonly<AdminButtonProps>) {
const openAdmin = useCallback(
(event: any) => {
const modelDef = ModelInformationDict[props.model];
const host = useLocalState.getState().host;
if (!modelDef.admin_url) {
return;
}
// Generate the URL for the admin interface
const url = new URL(
`${server.server.django_admin}${modelDef.admin_url}${props.id}/`,
host
const url = generateUrl(
`${server.server.django_admin}${modelDef.admin_url}${props.id}/`
);
if (event?.ctrlKey || event?.shiftKey) {
@@ -8,9 +8,9 @@ import { api } from '../../App';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
import { extractAvailableFields } from '../../functions/forms';
import { generateUrl } from '../../functions/urls';
import { useCreateApiFormModal } from '../../hooks/UseForm';
import { apiUrl } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState';
import { useUserSettingsState } from '../../states/SettingsState';
import type { ApiFormFieldSet } from '../forms/fields/ApiFormField';
import { ActionDropdown } from '../items/ActionDropdown';
@@ -28,8 +28,6 @@ export function PrintingActions({
enableReports?: boolean;
modelType?: ModelType;
}) {
const { host } = useLocalState.getState();
const userSettings = useUserSettingsState();
const enabled = useMemo(() => items.length > 0, [items]);
@@ -116,7 +114,7 @@ export function PrintingActions({
if (response.output) {
// An output file was generated
const url = new URL(response.output, host);
const url = generateUrl(response.output);
window.open(url.toString(), '_blank');
}
}
@@ -154,7 +152,7 @@ export function PrintingActions({
if (response.output) {
// An output file was generated
const url = new URL(response.output, host);
const url = generateUrl(response.output);
window.open(url.toString(), '_blank');
}
}
@@ -6,6 +6,7 @@
import { Image, type ImageProps, Skeleton, Stack } from '@mantine/core';
import { useMemo } from 'react';
import { generateUrl } from '../../functions/urls';
import { useLocalState } from '../../states/LocalState';
interface ApiImageProps extends ImageProps {
@@ -19,7 +20,7 @@ export function ApiImage(props: Readonly<ApiImageProps>) {
const { host } = useLocalState.getState();
const imageUrl = useMemo(() => {
return new URL(props.src, host).toString();
return generateUrl(props.src, host);
}, [host, props.src]);
return (
@@ -10,8 +10,7 @@ import {
IconPhoto
} from '@tabler/icons-react';
import { type ReactNode, useMemo } from 'react';
import { useLocalState } from '../../states/LocalState';
import { generateUrl } from '../../functions/urls';
/**
* Return an icon based on the provided filename
@@ -61,16 +60,13 @@ export function AttachmentLink({
}>): ReactNode {
const text = external ? attachment : attachment.split('/').pop();
const host = useLocalState((s) => s.host);
const url = useMemo(() => {
if (external) {
return attachment;
}
const u = new URL(attachment, host);
return u.toString();
}, [host, attachment, external]);
return generateUrl(attachment);
}, [attachment, external]);
return (
<Group justify='left' gap='sm' wrap='nowrap'>
@@ -15,8 +15,8 @@ import { useQuery } from '@tanstack/react-query';
import { api } from '../../App';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { generateUrl } from '../../functions/urls';
import { apiUrl, useServerApiState } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState';
import { useUserState } from '../../states/UserState';
import { CopyButton } from '../buttons/CopyButton';
import { StylishText } from '../items/StylishText';
@@ -35,7 +35,6 @@ export function AboutInvenTreeModal({
modalBody: string;
}>) {
const [user] = useUserState((state) => [state.user]);
const { host } = useLocalState.getState();
const [server] = useServerApiState((state) => [state.server]);
if (user?.is_staff != true)
@@ -137,7 +136,7 @@ export function AboutInvenTreeModal({
{
ref: 'api',
title: <Trans>API Version</Trans>,
link: new URL('/api-doc/', host).toString(),
link: generateUrl('/api-doc/'),
copy: true
},
{
@@ -1,11 +1,9 @@
import { useLocalState } from '../../states/LocalState';
import { generateUrl } from '../../functions/urls';
/*
* Load an external plugin source from a URL.
*/
export async function loadExternalPluginSource(source: string) {
const host = useLocalState.getState().host;
source = source.trim();
// If no source is provided, clear the plugin content
@@ -13,7 +11,7 @@ export async function loadExternalPluginSource(source: string) {
return null;
}
const url = new URL(source, host).toString();
const url = generateUrl(source);
const module = await import(/* @vite-ignore */ url)
.catch((error) => {
+1 -3
View File
@@ -126,6 +126,7 @@ const icons = {
units: IconRulerMeasure,
keywords: IconTag,
status: IconInfoCircle,
status_custom_key: IconInfoCircle,
edit: IconEdit,
info: IconInfoCircle,
exclamation: IconExclamationCircle,
@@ -291,6 +292,3 @@ export function InvenTreeIcon(props: Readonly<InvenTreeIconProps>) {
return <Icon {...props.iconProps} />;
}
function IconShapes(props: TablerIconProps): Element {
throw new Error('Function not implemented.');
}
+24
View File
@@ -1,6 +1,7 @@
import { ModelInformationDict } from '../components/render/ModelType';
import type { ModelType } from '../enums/ModelType';
import { base_url } from '../main';
import { useLocalState } from '../states/LocalState';
/**
* Returns the detail view URL for a given model type
@@ -30,3 +31,26 @@ export function getDetailUrl(
console.error(`No detail URL found for model ${model} <${pk}>`);
return '';
}
/**
* Returns the edit view URL for a given model type
*/
export function generateUrl(url: string | URL, base?: string): string {
const { host } = useLocalState.getState();
let newUrl: string | URL = url;
try {
if (base) {
newUrl = new URL(url, base).toString();
} else if (host) {
newUrl = new URL(url, host).toString();
} else {
newUrl = url.toString();
}
} catch (e: any) {
console.error(`ERR: generateURL failed. url='${url}', base='${base}'`);
}
return newUrl.toString();
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -18,7 +18,7 @@ import { PanelGroup } from '../components/panels/PanelGroup';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { useTable } from '../hooks/UseTable';
import { apiUrl } from '../states/ApiState';
import { NotificationTable } from '../tables/notifications/NotificationsTable';
import { NotificationTable } from '../tables/notifications/NotificationTable';
export default function NotificationsPage() {
const unreadTable = useTable('unreadnotifications');
+2 -5
View File
@@ -2,8 +2,8 @@ import { create } from 'zustand';
import { api } from '../App';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { generateUrl } from '../functions/urls';
import { apiUrl } from './ApiState';
import { useLocalState } from './LocalState';
type IconPackage = {
name: string;
@@ -34,8 +34,6 @@ export const useIconState = create<IconState>()((set, get) => ({
fetchIcons: async () => {
if (get().hasLoaded) return;
const host = useLocalState.getState().host;
const packs = await api.get(apiUrl(ApiEndpoints.icons));
await Promise.all(
@@ -43,8 +41,7 @@ export const useIconState = create<IconState>()((set, get) => ({
const fontName = `inventree-icon-font-${pack.prefix}`;
const src = Object.entries(pack.fonts as Record<string, string>)
.map(
([format, url]) =>
`url(${new URL(url, host).toString()}) format("${format}")`
([format, url]) => `url(${generateUrl(url)}) format("${format}")`
)
.join(',\n');
const font = new FontFace(fontName, `${src};`);
@@ -24,7 +24,8 @@ export function NotificationTable({
{
accessor: 'age_human',
title: t`Age`,
sortable: true
sortable: true,
ordering: 'creation'
},
{
accessor: 'category',