Skip to content

[UI] API Context #8851

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 7, 2025
2 changes: 1 addition & 1 deletion src/backend/InvenTree/part/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ class PartSerializer(
Used when displaying all details of a single component.
"""

import_exclude_fields = ['duplicate']
import_exclude_fields = ['duplicate', 'tags']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Is this meant to be in this PR?


class Meta:
"""Metaclass defining serializer fields."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query';
import { type ReactNode, useCallback } from 'react';
import { useNavigate } from 'react-router-dom';

import { api } from '../../../App';
import { useApi } from '../../../contexts/ApiContext';
import type { ModelType } from '../../../enums/ModelType';
import {
InvenTreeIcon,
Expand All @@ -31,6 +31,7 @@ function QueryCountWidget({
icon?: InvenTreeIconType;
params: any;
}>): ReactNode {
const api = useApi();
const user = useUserState();
const navigate = useNavigate();

Expand Down
5 changes: 4 additions & 1 deletion src/frontend/src/components/details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getValueAtPath } from 'mantine-datatable';
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import { formatDate } from '../../defaults/formatters';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
Expand Down Expand Up @@ -101,6 +101,8 @@ function NameBadge({
pk,
type
}: Readonly<{ pk: string | number; type: BadgeType }>) {
const api = useApi();

const { data } = useQuery({
queryKey: ['badge', type, pk],
queryFn: async () => {
Expand Down Expand Up @@ -217,6 +219,7 @@ function BooleanValue(props: Readonly<FieldProps>) {
}

function TableAnchorValue(props: Readonly<FieldProps>) {
const api = useApi();
const navigate = useNavigate();

const { data } = useQuery({
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/components/editors/NotesEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'easymde/dist/easymde.min.css';
import { useCallback, useEffect, useMemo, useState } from 'react';
import SimpleMDE from 'react-simplemde-editor';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
import { apiUrl } from '../../states/ApiState';
Expand All @@ -31,6 +31,7 @@ export default function NotesEditor({
modelId: number;
editable?: boolean;
}>) {
const api = useApi();
// In addition to the editable prop, we also need to check if the user has "enabled" editing
const [editing, setEditing] = useState<boolean>(false);

Expand Down
8 changes: 6 additions & 2 deletions src/frontend/src/components/forms/ApiForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '@mantine/core';
import { useId } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { useQuery } from '@tanstack/react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useCallback, useEffect, useMemo, useState } from 'react';
import {
type FieldValues,
Expand All @@ -23,7 +23,7 @@ import {
} from 'react-hook-form';
import { useNavigate } from 'react-router-dom';

import { api, queryClient } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import type { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
import {
Expand Down Expand Up @@ -110,6 +110,8 @@ export function OptionsApiForm({
props: ApiFormProps;
id?: string;
}>) {
const api = useApi();

const props = useMemo(
() => ({
..._props,
Expand Down Expand Up @@ -205,6 +207,8 @@ export function ApiForm({
props: ApiFormProps;
optionsLoading: boolean;
}>) {
const api = useApi();
const queryClient = useQueryClient();
const navigate = useNavigate();

const [fields, setFields] = useState<ApiFormFieldSet>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
useFormContext
} from 'react-hook-form';

import { api } from '../../../App';
import { useApi } from '../../../contexts/ApiContext';
import {
constructField,
extractAvailableFields
Expand All @@ -29,6 +29,7 @@ export function DependentField({
url?: string;
setFields?: React.Dispatch<React.SetStateAction<ApiFormFieldSet>>;
}>) {
const api = useApi();
const { watch, resetField } = useFormContext();

const mappedFieldNames = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from 'react-hook-form';
import Select from 'react-select';

import { api } from '../../../App';
import { useApi } from '../../../contexts/ApiContext';
import { vars } from '../../../theme';
import { RenderInstance } from '../../render/Instance';
import type { ApiFormFieldType } from './ApiFormField';
Expand All @@ -34,6 +34,7 @@ export function RelatedModelField({
fieldName: string;
limit?: number;
}>) {
const api = useApi();
const fieldId = useId();
const {
field,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '@tabler/icons-react';
import { type ReactNode, useCallback, useMemo, useState } from 'react';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { cancelEvent } from '../../functions/events';
import {
Expand Down Expand Up @@ -131,6 +131,7 @@ export default function ImporterDataSelector({
}: Readonly<{
session: ImportSessionState;
}>) {
const api = useApi();
const table = useTable('dataimporter');

const [selectedFieldNames, setSelectedFieldNames] = useState<string[]>([]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { IconCheck } from '@tabler/icons-react';
import { useCallback, useEffect, useMemo, useState } from 'react';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ImportSessionState } from '../../hooks/UseImportSession';
import { apiUrl } from '../../states/ApiState';
Expand All @@ -24,6 +24,8 @@ function ImporterColumn({
column,
options
}: Readonly<{ column: any; options: any[] }>) {
const api = useApi();

const [errorMessage, setErrorMessage] = useState<string>('');

const [selectedColumn, setSelectedColumn] = useState<string>(
Expand Down Expand Up @@ -78,6 +80,8 @@ function ImporterDefaultField({
fieldName: string;
session: ImportSessionState;
}) {
const api = useApi();

const onChange = useCallback(
(value: any) => {
// Update the default value for the field
Expand Down Expand Up @@ -162,6 +166,8 @@ export default function ImporterColumnSelector({
}: Readonly<{
session: ImportSessionState;
}>) {
const api = useApi();

const [errorMessage, setErrorMessage] = useState<string>('');

const acceptMapping = useCallback(() => {
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/components/nav/NavigationTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useQuery } from '@tanstack/react-query';
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import type { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
import { navigateToLink } from '../../functions/navigation';
Expand All @@ -48,6 +48,7 @@ export default function NavigationTree({
modelType: ModelType;
endpoint: ApiEndpoints;
}>) {
const api = useApi();
const navigate = useNavigate();
const treeState = useTree();

Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/components/render/Instance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Alert, Anchor, Group, Skeleton, Space, Text } from '@mantine/core';
import { useQuery } from '@tanstack/react-query';
import { type ReactNode, useCallback } from 'react';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import { ModelType } from '../../enums/ModelType';
import { navigateToLink } from '../../functions/navigation';
import { shortenString } from '../../functions/tables';
Expand Down Expand Up @@ -130,6 +130,8 @@ export function RenderRemoteInstance({
model: ModelType;
pk: number;
}>): ReactNode {
const api = useApi();

const { data, isLoading, isFetching } = useQuery({
queryKey: ['model', model, pk],
queryFn: async () => {
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/components/settings/SettingList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import React, {
} from 'react';
import { useStore } from 'zustand';

import { api } from '../../App';
import { useApi } from '../../contexts/ApiContext';
import type { ModelType } from '../../enums/ModelType';
import { useEditApiFormModal } from '../../hooks/UseForm';
import { apiUrl } from '../../states/ApiState';
Expand Down Expand Up @@ -40,6 +40,8 @@ export function SettingList({
settingsState.fetchSettings();
}, []);

const api = useApi();

const allKeys = useMemo(
() => settingsState?.settings?.map((s) => s.key) ?? [],
[settingsState?.settings]
Expand Down
31 changes: 31 additions & 0 deletions src/frontend/src/contexts/ApiContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { type QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { AxiosInstance } from 'axios';
import { createContext, useContext } from 'react';

const ApiContext = createContext<AxiosInstance | null>(null);

export const ApiProvider = ({
api,
client,
children
}: {
api: AxiosInstance;
client: QueryClient;
children: React.ReactNode;
}) => {
return (
<QueryClientProvider client={client}>
<ApiContext.Provider value={api}>{children}</ApiContext.Provider>
</QueryClientProvider>
);
};

export const useApi = () => {
const context = useContext(ApiContext);

if (!context) {
throw new Error('useApi must be used within an ApiProvider');
}

return context;
};
12 changes: 0 additions & 12 deletions src/frontend/src/contexts/BaseContext.tsx

This file was deleted.

4 changes: 3 additions & 1 deletion src/frontend/src/forms/PartForms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { t } from '@lingui/macro';
import { IconPackages } from '@tabler/icons-react';
import { useMemo, useState } from 'react';

import { api } from '../App';
import type { ApiFormFieldSet } from '../components/forms/fields/ApiFormField';
import { useApi } from '../contexts/ApiContext';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { apiUrl } from '../states/ApiState';
import { useGlobalSettingsState } from '../states/SettingsState';
Expand Down Expand Up @@ -179,6 +179,8 @@ export function usePartParameterFields({
}: {
editTemplate?: boolean;
}): ApiFormFieldSet {
const api = useApi();

// Valid field choices
const [choices, setChoices] = useState<any[]>([]);

Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/hooks/UseFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { useQuery } from '@tanstack/react-query';
import { useCallback, useMemo } from 'react';

import { api } from '../App';
import { useApi } from '../contexts/ApiContext';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { resolveItem } from '../functions/conversion';
import { apiUrl } from '../states/ApiState';
Expand All @@ -20,6 +20,8 @@ type UseFilterProps = {
};

export function useFilters(props: UseFilterProps) {
const api = useApi();

const query = useQuery({
enabled: true,
gcTime: 500,
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/hooks/UseInstance.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type QueryObserverResult, useQuery } from '@tanstack/react-query';
import { useCallback, useMemo, useState } from 'react';

import { api } from '../App';
import { useApi } from '../contexts/ApiContext';
import type { ApiEndpoints } from '../enums/ApiEndpoints';
import { type PathParams, apiUrl } from '../states/ApiState';

Expand Down Expand Up @@ -48,6 +48,8 @@ export function useInstance<T = any>({
throwError?: boolean;
updateInterval?: number;
}): UseInstanceResult {
const api = useApi();

const [instance, setInstance] = useState<T | undefined>(defaultValue);

const [requestStatus, setRequestStatus] = useState<number>(0);
Expand Down
3 changes: 0 additions & 3 deletions src/frontend/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import ReactDOM from 'react-dom/client';
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';

import { api } from './App';
import type { HostList } from './states/states';
import MainView from './views/MainView';

Expand All @@ -27,7 +26,6 @@ declare global {
sentry_dsn?: string;
environment?: string;
};
InvenTreeAPI: typeof api;
React: typeof React;
}
}
Expand Down Expand Up @@ -105,4 +103,3 @@ if (window.location.pathname === '/') {
}

window.React = React;
window.InvenTreeAPI = api;
3 changes: 2 additions & 1 deletion src/frontend/src/pages/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import {
} from '@tabler/icons-react';
import { useCallback, useMemo } from 'react';

import { api } from '../App';
import { ActionButton } from '../components/buttons/ActionButton';
import { PageDetail } from '../components/nav/PageDetail';
import { PanelGroup } from '../components/panels/PanelGroup';
import { useApi } from '../contexts/ApiContext';
import { ApiEndpoints } from '../enums/ApiEndpoints';
import { useTable } from '../hooks/UseTable';
import { apiUrl } from '../states/ApiState';
import { NotificationTable } from '../tables/notifications/NotificationTable';

export default function NotificationsPage() {
const api = useApi();
const unreadTable = useTable('unreadnotifications');
const readTable = useTable('readnotifications');

Expand Down
Loading
Loading