mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 03:56:43 +00:00
Fix URL generation error (#8630)
- Implement better helper function for handling URL generation - Handle errors in said function
This commit is contained in:
parent
9f120ef76f
commit
82bce192e6
@ -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) => {
|
||||
|
@ -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.');
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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};`);
|
||||
|
Loading…
x
Reference in New Issue
Block a user