mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge remote-tracking branch 'upstream/master' into barcode-generation
This commit is contained in:
commit
aebf7ab147
@ -14,8 +14,10 @@ env:
|
|||||||
- INVENTREE_BACKUP_DIR=/opt/inventree/backup
|
- INVENTREE_BACKUP_DIR=/opt/inventree/backup
|
||||||
- INVENTREE_PLUGIN_FILE=/opt/inventree/plugins.txt
|
- INVENTREE_PLUGIN_FILE=/opt/inventree/plugins.txt
|
||||||
- INVENTREE_CONFIG_FILE=/opt/inventree/config.yaml
|
- INVENTREE_CONFIG_FILE=/opt/inventree/config.yaml
|
||||||
|
- APP_REPO=inventree/InvenTree
|
||||||
before_install: contrib/packager.io/preinstall.sh
|
before_install: contrib/packager.io/preinstall.sh
|
||||||
after_install: contrib/packager.io/postinstall.sh
|
after_install: contrib/packager.io/postinstall.sh
|
||||||
|
before_remove: contrib/packager.io/preinstall.sh
|
||||||
before:
|
before:
|
||||||
- contrib/packager.io/before.sh
|
- contrib/packager.io/before.sh
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
# The sha is the second element in APP_PKG_ITERATION
|
# The sha is the second element in APP_PKG_ITERATION
|
||||||
REPO="inventree/InvenTree"
|
|
||||||
VERSION="$APP_PKG_VERSION-$APP_PKG_ITERATION"
|
VERSION="$APP_PKG_VERSION-$APP_PKG_ITERATION"
|
||||||
SHA=$(echo $APP_PKG_ITERATION | cut -d'.' -f2)
|
SHA=$(echo $APP_PKG_ITERATION | cut -d'.' -f2)
|
||||||
|
|
||||||
@ -15,17 +14,17 @@ echo "INFO collection | Getting info from github for commit $SHA"
|
|||||||
curl -L -s -f \
|
curl -L -s -f \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
https://api.github.com/repos/$REPO/commits/$SHA > commit.json
|
https://api.github.com/repos/$APP_REPO/commits/$SHA > commit.json
|
||||||
echo "INFO collection | Got commit.json with size $(wc -c commit.json)"
|
echo "INFO collection | Got commit.json with size $(wc -c commit.json)"
|
||||||
curl -L -s -f \
|
curl -L -s -f \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
https://api.github.com/repos/$REPO/commits/$SHA/branches-where-head > branches.json
|
https://api.github.com/repos/$APP_REPO/commits/$SHA/branches-where-head > branches.json
|
||||||
echo "INFO collection | Got branches.json with size $(wc -c branches.json)"
|
echo "INFO collection | Got branches.json with size $(wc -c branches.json)"
|
||||||
curl -L -s -f \
|
curl -L -s -f \
|
||||||
-H "Accept: application/vnd.github+json" \
|
-H "Accept: application/vnd.github+json" \
|
||||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||||
https://api.github.com/repos/$REPO/commits/$APP_PKG_VERSION > tag.json
|
https://api.github.com/repos/$APP_REPO/commits/$APP_PKG_VERSION > tag.json
|
||||||
echo "INFO collection | Got tag.json with size $(wc -c tag.json)"
|
echo "INFO collection | Got tag.json with size $(wc -c tag.json)"
|
||||||
|
|
||||||
# Extract info
|
# Extract info
|
||||||
@ -60,7 +59,7 @@ if [ "$TAG_SHA" != "$FULL_SHA" ]; then
|
|||||||
echo "INFO frontend | Tag sha '$TAG_SHA' is not the same as commit sha $FULL_SHA, can not download frontend"
|
echo "INFO frontend | Tag sha '$TAG_SHA' is not the same as commit sha $FULL_SHA, can not download frontend"
|
||||||
else
|
else
|
||||||
echo "INFO frontend | Getting frontend from github via tag"
|
echo "INFO frontend | Getting frontend from github via tag"
|
||||||
curl https://github.com/$REPO/releases/download/$APP_PKG_VERSION/frontend-build.zip -L -O -f
|
curl https://github.com/$APP_REPO/releases/download/$APP_PKG_VERSION/frontend-build.zip -L -O -f
|
||||||
mkdir -p src/backend/InvenTree/web/static
|
mkdir -p src/backend/InvenTree/web/static
|
||||||
echo "INFO frontend | Unzipping frontend"
|
echo "INFO frontend | Unzipping frontend"
|
||||||
unzip -qq frontend-build.zip -d src/backend/InvenTree/web/static/web
|
unzip -qq frontend-build.zip -d src/backend/InvenTree/web/static/web
|
||||||
|
@ -60,7 +60,7 @@ function detect_python() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Try to detect a python between 3.9 and 3.12 in reverse order
|
# Try to detect a python between 3.9 and 3.12 in reverse order
|
||||||
if [ -z "${SETUP_PYTHON}" ]; then
|
if [ -z "$(which ${SETUP_PYTHON})" ]; then
|
||||||
echo "# Trying to detecting python3.${PYTHON_FROM} to python3.${PYTHON_TO} - using newest version"
|
echo "# Trying to detecting python3.${PYTHON_FROM} to python3.${PYTHON_TO} - using newest version"
|
||||||
for i in $(seq $PYTHON_TO -1 $PYTHON_FROM); do
|
for i in $(seq $PYTHON_TO -1 $PYTHON_FROM); do
|
||||||
echo "# Checking for python3.${i}"
|
echo "# Checking for python3.${i}"
|
||||||
@ -318,17 +318,17 @@ function set_env() {
|
|||||||
sed -i s=debug:\ True=debug:\ False=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=debug:\ True=debug:\ False=g ${INVENTREE_CONFIG_FILE}
|
||||||
|
|
||||||
# Database engine
|
# Database engine
|
||||||
sed -i s=#ENGINE:\ sampleengine=ENGINE:\ ${INVENTREE_DB_ENGINE}=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ ENGINE:\ Database\ engine.\ Selection\ from:=ENGINE:\ ${INVENTREE_DB_ENGINE}=g ${INVENTREE_CONFIG_FILE}
|
||||||
# Database name
|
# Database name
|
||||||
sed -i s=#NAME:\ \'/path/to/database\'=NAME:\ \'${INVENTREE_DB_NAME}\'=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ NAME:\ Database\ name=NAME:\ \'${INVENTREE_DB_NAME}\'=g ${INVENTREE_CONFIG_FILE}
|
||||||
# Database user
|
# Database user
|
||||||
sed -i s=#USER:\ sampleuser=USER:\ ${INVENTREE_DB_USER}=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ USER:\ Database\ username\ \(if\ required\)=USER:\ ${INVENTREE_DB_USER}=g ${INVENTREE_CONFIG_FILE}
|
||||||
# Database password
|
# Database password
|
||||||
sed -i s=#PASSWORD:\ samplepassword=PASSWORD:\ ${INVENTREE_DB_PASSWORD}=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ PASSWORD:\ Database\ password\ \(if\ required\)=PASSWORD:\ ${INVENTREE_DB_PASSWORD}=g ${INVENTREE_CONFIG_FILE}
|
||||||
# Database host
|
# Database host
|
||||||
sed -i s=#HOST:\ samplehost=HOST:\ ${INVENTREE_DB_HOST}=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ HOST:\ Database\ host\ address\ \(if\ required\)=HOST:\ ${INVENTREE_DB_HOST}=g ${INVENTREE_CONFIG_FILE}
|
||||||
# Database port
|
# Database port
|
||||||
sed -i s=#PORT:\ 123456=PORT:\ ${INVENTREE_DB_PORT}=g ${INVENTREE_CONFIG_FILE}
|
sed -i s=#\ PORT:\ Database\ host\ port\ \(if\ required\)=PORT:\ ${INVENTREE_DB_PORT}=g ${INVENTREE_CONFIG_FILE}
|
||||||
|
|
||||||
# Fixing the permissions
|
# Fixing the permissions
|
||||||
chown ${APP_USER}:${APP_GROUP} ${DATA_DIR} ${INVENTREE_CONFIG_FILE}
|
chown ${APP_USER}:${APP_GROUP} ${DATA_DIR} ${INVENTREE_CONFIG_FILE}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# packager.io preinstall script
|
# packager.io preinstall/preremove script
|
||||||
#
|
#
|
||||||
PATH=${APP_HOME}/env/bin:${APP_HOME}/:/sbin:/bin:/usr/sbin:/usr/bin:
|
PATH=${APP_HOME}/env/bin:${APP_HOME}/:/sbin:/bin:/usr/sbin:/usr/bin:
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
# Note: Database configuration options can also be specified from environmental variables,
|
# Note: Database configuration options can also be specified from environmental variables,
|
||||||
# with the prefix INVENTREE_DB_
|
# with the prefix INVENTREE_DB_
|
||||||
# e.g INVENTREE_DB_NAME / INVENTREE_DB_USER / INVENTREE_DB_PASSWORD
|
# e.g INVENTREE_DB_NAME / INVENTREE_DB_USER / INVENTREE_DB_PASSWORD
|
||||||
|
# Do not change this section if you are using the package - use `inventree config` instead
|
||||||
|
# TO MAINTAINERS: Do not change database strings
|
||||||
database:
|
database:
|
||||||
# --- Available options: ---
|
# --- Available options: ---
|
||||||
# ENGINE: Database engine. Selection from:
|
# ENGINE: Database engine. Selection from:
|
||||||
|
@ -398,9 +398,9 @@ pyyaml==6.0.1 \
|
|||||||
# via
|
# via
|
||||||
# -c src/backend/requirements.txt
|
# -c src/backend/requirements.txt
|
||||||
# pre-commit
|
# pre-commit
|
||||||
setuptools==70.3.0 \
|
setuptools==71.0.3 \
|
||||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
--hash=sha256:3d8531791a27056f4a38cd3e54084d8b1c4228ff9cf3f2d7dd075ec99f9fd70d \
|
||||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
--hash=sha256:f501b6e6db709818dc76882582d9c516bf3b67b948864c5fa1d1624c09a49207
|
||||||
# via
|
# via
|
||||||
# -c src/backend/requirements.txt
|
# -c src/backend/requirements.txt
|
||||||
# -r src/backend/requirements-dev.in
|
# -r src/backend/requirements-dev.in
|
||||||
|
@ -1543,15 +1543,15 @@ rpds-py==0.18.1 \
|
|||||||
# via
|
# via
|
||||||
# jsonschema
|
# jsonschema
|
||||||
# referencing
|
# referencing
|
||||||
sentry-sdk==2.7.0 \
|
sentry-sdk==2.8.0 \
|
||||||
--hash=sha256:d846a211d4a0378b289ced3c434480945f110d0ede00450ba631fc2852e7a0d4 \
|
--hash=sha256:6051562d2cfa8087bb8b4b8b79dc44690f8a054762a29c07e22588b1f619bfb5 \
|
||||||
--hash=sha256:db9594c27a4d21c1ebad09908b1f0dc808ef65c2b89c1c8e7e455143262e37c1
|
--hash=sha256:aa4314f877d9cd9add5a0c9ba18e3f27f99f7de835ce36bd150e48a41c7c646f
|
||||||
# via
|
# via
|
||||||
# -r src/backend/requirements.in
|
# -r src/backend/requirements.in
|
||||||
# django-q-sentry
|
# django-q-sentry
|
||||||
setuptools==70.3.0 \
|
setuptools==71.0.3 \
|
||||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
--hash=sha256:3d8531791a27056f4a38cd3e54084d8b1c4228ff9cf3f2d7dd075ec99f9fd70d \
|
||||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
--hash=sha256:f501b6e6db709818dc76882582d9c516bf3b67b948864c5fa1d1624c09a49207
|
||||||
# via
|
# via
|
||||||
# -r src/backend/requirements.in
|
# -r src/backend/requirements.in
|
||||||
# django-money
|
# django-money
|
||||||
|
@ -31,7 +31,7 @@ export function DashboardItemProxy({
|
|||||||
queryFn: fetchData,
|
queryFn: fetchData,
|
||||||
refetchOnWindowFocus: autoupdate
|
refetchOnWindowFocus: autoupdate
|
||||||
});
|
});
|
||||||
const [dashdata, setDashData] = useState({ title: t`Title`, value: '000' });
|
const [dashData, setDashData] = useState({ title: t`Title`, value: '000' });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (data) {
|
||||||
@ -44,7 +44,7 @@ export function DashboardItemProxy({
|
|||||||
<div key={id}>
|
<div key={id}>
|
||||||
<StatisticItem
|
<StatisticItem
|
||||||
id={id}
|
id={id}
|
||||||
data={dashdata}
|
data={dashData}
|
||||||
isLoading={isLoading || isFetching}
|
isLoading={isLoading || isFetching}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { IconUserStar } from '@tabler/icons-react';
|
import { IconUserStar } from '@tabler/icons-react';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { ModelType } from '../../enums/ModelType';
|
import { ModelType } from '../../enums/ModelType';
|
||||||
import { navigateToLink } from '../../functions/navigation';
|
|
||||||
import { base_url } from '../../main';
|
|
||||||
import { useLocalState } from '../../states/LocalState';
|
import { useLocalState } from '../../states/LocalState';
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { ModelInformationDict } from '../render/ModelType';
|
import { ModelInformationDict } from '../render/ModelType';
|
||||||
|
@ -2,7 +2,7 @@ import { t } from '@lingui/macro';
|
|||||||
import { notifications } from '@mantine/notifications';
|
import { notifications } from '@mantine/notifications';
|
||||||
import { IconPrinter, IconReport, IconTags } from '@tabler/icons-react';
|
import { IconPrinter, IconReport, IconTags } from '@tabler/icons-react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
|
@ -85,7 +85,7 @@ function UploadModal({
|
|||||||
apiPath: string;
|
apiPath: string;
|
||||||
setImage: (image: string) => void;
|
setImage: (image: string) => void;
|
||||||
}) {
|
}) {
|
||||||
const [file1, setFile] = useState<FileWithPath | null>(null);
|
const [currentFile, setCurrentFile] = useState<FileWithPath | null>(null);
|
||||||
let uploading = false;
|
let uploading = false;
|
||||||
|
|
||||||
// Components to show in the Dropzone when no file is selected
|
// Components to show in the Dropzone when no file is selected
|
||||||
@ -168,7 +168,7 @@ function UploadModal({
|
|||||||
return (
|
return (
|
||||||
<Paper style={{ height: '220px' }}>
|
<Paper style={{ height: '220px' }}>
|
||||||
<Dropzone
|
<Dropzone
|
||||||
onDrop={(files) => setFile(files[0])}
|
onDrop={(files) => setCurrentFile(files[0])}
|
||||||
maxFiles={1}
|
maxFiles={1}
|
||||||
accept={IMAGE_MIME_TYPE}
|
accept={IMAGE_MIME_TYPE}
|
||||||
loading={uploading}
|
loading={uploading}
|
||||||
@ -198,7 +198,9 @@ function UploadModal({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Dropzone.Reject>
|
</Dropzone.Reject>
|
||||||
<Dropzone.Idle>{file1 ? fileInfo(file1) : noFileIdle}</Dropzone.Idle>
|
<Dropzone.Idle>
|
||||||
|
{currentFile ? fileInfo(currentFile) : noFileIdle}
|
||||||
|
</Dropzone.Idle>
|
||||||
</Group>
|
</Group>
|
||||||
</Dropzone>
|
</Dropzone>
|
||||||
<Paper
|
<Paper
|
||||||
@ -218,12 +220,15 @@ function UploadModal({
|
|||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
disabled={!file1}
|
disabled={!currentFile}
|
||||||
onClick={() => setFile(null)}
|
onClick={() => setCurrentFile(null)}
|
||||||
>
|
>
|
||||||
<Trans>Clear</Trans>
|
<Trans>Clear</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
<Button disabled={!file1} onClick={() => uploadImage(file1)}>
|
<Button
|
||||||
|
disabled={!currentFile}
|
||||||
|
onClick={() => uploadImage(currentFile)}
|
||||||
|
>
|
||||||
<Trans>Submit</Trans>
|
<Trans>Submit</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
</Paper>
|
</Paper>
|
||||||
@ -354,31 +359,27 @@ export function DetailsImage(props: Readonly<DetailImageProps>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<AspectRatio ref={ref} maw={IMAGE_DIMENSION} ratio={1} pos="relative">
|
||||||
<AspectRatio ref={ref} maw={IMAGE_DIMENSION} ratio={1} pos="relative">
|
<>
|
||||||
<>
|
<ApiImage
|
||||||
<ApiImage
|
src={img}
|
||||||
src={img}
|
mah={IMAGE_DIMENSION}
|
||||||
mah={IMAGE_DIMENSION}
|
maw={IMAGE_DIMENSION}
|
||||||
maw={IMAGE_DIMENSION}
|
onClick={expandImage}
|
||||||
onClick={expandImage}
|
/>
|
||||||
/>
|
{permissions.hasChangeRole(props.appRole) && hasOverlay && hovered && (
|
||||||
{permissions.hasChangeRole(props.appRole) &&
|
<Overlay color="black" opacity={0.8} onClick={expandImage}>
|
||||||
hasOverlay &&
|
<ImageActionButtons
|
||||||
hovered && (
|
visible={hovered}
|
||||||
<Overlay color="black" opacity={0.8} onClick={expandImage}>
|
actions={props.imageActions}
|
||||||
<ImageActionButtons
|
apiPath={props.apiPath}
|
||||||
visible={hovered}
|
hasImage={props.src ? true : false}
|
||||||
actions={props.imageActions}
|
pk={props.pk}
|
||||||
apiPath={props.apiPath}
|
setImage={setAndRefresh}
|
||||||
hasImage={props.src ? true : false}
|
/>
|
||||||
pk={props.pk}
|
</Overlay>
|
||||||
setImage={setAndRefresh}
|
)}
|
||||||
/>
|
</>
|
||||||
</Overlay>
|
</AspectRatio>
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</AspectRatio>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Trans } from '@lingui/macro';
|
import { Trans } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Alert,
|
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Center,
|
Center,
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import { Alert, FileInput, NumberInput, Stack, Switch } from '@mantine/core';
|
||||||
Alert,
|
|
||||||
FileInput,
|
|
||||||
NumberInput,
|
|
||||||
Stack,
|
|
||||||
Switch,
|
|
||||||
TextInput
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { UseFormReturnType } from '@mantine/form';
|
import { UseFormReturnType } from '@mantine/form';
|
||||||
import { useId } from '@mantine/hooks';
|
import { useId } from '@mantine/hooks';
|
||||||
import { IconX } from '@tabler/icons-react';
|
|
||||||
import { ReactNode, useCallback, useEffect, useMemo } from 'react';
|
import { ReactNode, useCallback, useEffect, useMemo } from 'react';
|
||||||
import { Control, FieldValues, useController } from 'react-hook-form';
|
import { Control, FieldValues, useController } from 'react-hook-form';
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Trans, t } from '@lingui/macro';
|
import { Trans, t } from '@lingui/macro';
|
||||||
import { Container, Flex, Group, Table } from '@mantine/core';
|
import { Container, Group, Table } from '@mantine/core';
|
||||||
import { useEffect, useMemo } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
import { FieldValues, UseControllerReturn } from 'react-hook-form';
|
import { FieldValues, UseControllerReturn } from 'react-hook-form';
|
||||||
|
|
||||||
|
@ -29,18 +29,16 @@ export default function ImporterImportProgress({
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Center>
|
||||||
<Center>
|
<Container>
|
||||||
<Container>
|
<Stack gap="xs">
|
||||||
<Stack gap="xs">
|
<StylishText size="lg">{t`Importing Records`}</StylishText>
|
||||||
<StylishText size="lg">{t`Importing Records`}</StylishText>
|
<Loader />
|
||||||
<Loader />
|
<Text size="lg">
|
||||||
<Text size="lg">
|
{t`Imported rows`}: {session.sessionData.row_count}
|
||||||
{t`Imported rows`}: {session.sessionData.row_count}
|
</Text>
|
||||||
</Text>
|
</Stack>
|
||||||
</Stack>
|
</Container>
|
||||||
</Container>
|
</Center>
|
||||||
</Center>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Trans } from '@lingui/macro';
|
import { Trans } from '@lingui/macro';
|
||||||
import { Carousel } from '@mantine/carousel';
|
import { Carousel } from '@mantine/carousel';
|
||||||
import { Anchor, Button, Paper, Text, Title, rem } from '@mantine/core';
|
import { Anchor, Button, Paper, Text, Title } from '@mantine/core';
|
||||||
|
|
||||||
import { DocumentationLinkItem } from './DocumentationLinks';
|
import { DocumentationLinkItem } from './DocumentationLinks';
|
||||||
import * as classes from './GettingStartedCarousel.css';
|
import * as classes from './GettingStartedCarousel.css';
|
||||||
|
@ -35,7 +35,7 @@ export function QrCodeModal({
|
|||||||
key: 'camId',
|
key: 'camId',
|
||||||
defaultValue: null
|
defaultValue: null
|
||||||
});
|
});
|
||||||
const [ScanningEnabled, setIsScanning] = useState<boolean>(false);
|
const [scanningEnabled, setScanningEnabled] = useState<boolean>(false);
|
||||||
const [wasAutoPaused, setWasAutoPaused] = useState<boolean>(false);
|
const [wasAutoPaused, setWasAutoPaused] = useState<boolean>(false);
|
||||||
const documentState = useDocumentVisibility();
|
const documentState = useDocumentVisibility();
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ export function QrCodeModal({
|
|||||||
|
|
||||||
// Stop/star when leaving or reentering page
|
// Stop/star when leaving or reentering page
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ScanningEnabled && documentState === 'hidden') {
|
if (scanningEnabled && documentState === 'hidden') {
|
||||||
stopScanning();
|
stopScanning();
|
||||||
setWasAutoPaused(true);
|
setWasAutoPaused(true);
|
||||||
} else if (wasAutoPaused && documentState === 'visible') {
|
} else if (wasAutoPaused && documentState === 'visible') {
|
||||||
@ -128,12 +128,12 @@ export function QrCodeModal({
|
|||||||
icon: <IconX />
|
icon: <IconX />
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setIsScanning(true);
|
setScanningEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopScanning() {
|
function stopScanning() {
|
||||||
if (qrCodeScanner && ScanningEnabled) {
|
if (qrCodeScanner && scanningEnabled) {
|
||||||
qrCodeScanner.stop().catch((err: string) => {
|
qrCodeScanner.stop().catch((err: string) => {
|
||||||
showNotification({
|
showNotification({
|
||||||
title: t`Error while stopping`,
|
title: t`Error while stopping`,
|
||||||
@ -142,7 +142,7 @@ export function QrCodeModal({
|
|||||||
icon: <IconX />
|
icon: <IconX />
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setIsScanning(false);
|
setScanningEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ export function QrCodeModal({
|
|||||||
<Group>
|
<Group>
|
||||||
<Text size="sm">{camId?.label}</Text>
|
<Text size="sm">{camId?.label}</Text>
|
||||||
<Space style={{ flex: 1 }} />
|
<Space style={{ flex: 1 }} />
|
||||||
<Badge>{ScanningEnabled ? t`Scanning` : t`Not scanning`}</Badge>
|
<Badge>{scanningEnabled ? t`Scanning` : t`Not scanning`}</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
<Container px={0} id="reader" w={'100%'} mih="300px" />
|
<Container px={0} id="reader" w={'100%'} mih="300px" />
|
||||||
{!camId ? (
|
{!camId ? (
|
||||||
@ -164,14 +164,14 @@ export function QrCodeModal({
|
|||||||
<Button
|
<Button
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
onClick={() => startScanning()}
|
onClick={() => startScanning()}
|
||||||
disabled={camId != undefined && ScanningEnabled}
|
disabled={camId != undefined && scanningEnabled}
|
||||||
>
|
>
|
||||||
<Trans>Start scanning</Trans>
|
<Trans>Start scanning</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
onClick={() => stopScanning()}
|
onClick={() => stopScanning()}
|
||||||
disabled={!ScanningEnabled}
|
disabled={!scanningEnabled}
|
||||||
>
|
>
|
||||||
<Trans>Stop scanning</Trans>
|
<Trans>Stop scanning</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -2,7 +2,7 @@ import { ActionIcon, Container, Group, Indicator, Tabs } from '@mantine/core';
|
|||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import { IconBell, IconSearch } from '@tabler/icons-react';
|
import { IconBell, IconSearch } from '@tabler/icons-react';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useEffect, useState } from 'react';
|
import { ReactNode, useEffect, useMemo, useState } from 'react';
|
||||||
import { useMatch, useNavigate } from 'react-router-dom';
|
import { useMatch, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
@ -132,10 +132,35 @@ export function Header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NavTabs() {
|
function NavTabs() {
|
||||||
|
const user = useUserState();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const match = useMatch(':tabName/*');
|
const match = useMatch(':tabName/*');
|
||||||
const tabValue = match?.params.tabName;
|
const tabValue = match?.params.tabName;
|
||||||
|
|
||||||
|
const tabs: ReactNode[] = useMemo(() => {
|
||||||
|
let _tabs: ReactNode[] = [];
|
||||||
|
|
||||||
|
mainNavTabs.forEach((tab) => {
|
||||||
|
if (tab.role && !user.hasViewRole(tab.role)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabs.push(
|
||||||
|
<Tabs.Tab
|
||||||
|
value={tab.name}
|
||||||
|
key={tab.name}
|
||||||
|
onClick={(event: any) =>
|
||||||
|
navigateToLink(`/${tab.name}`, navigate, event)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{tab.text}
|
||||||
|
</Tabs.Tab>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return _tabs;
|
||||||
|
}, [mainNavTabs, user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue="home"
|
defaultValue="home"
|
||||||
@ -146,19 +171,7 @@ function NavTabs() {
|
|||||||
}}
|
}}
|
||||||
value={tabValue}
|
value={tabValue}
|
||||||
>
|
>
|
||||||
<Tabs.List>
|
<Tabs.List>{tabs.map((tab) => tab)}</Tabs.List>
|
||||||
{mainNavTabs.map((tab) => (
|
|
||||||
<Tabs.Tab
|
|
||||||
value={tab.name}
|
|
||||||
key={tab.name}
|
|
||||||
onClick={(event: any) =>
|
|
||||||
navigateToLink(`/${tab.name}`, navigate, event)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{tab.text}
|
|
||||||
</Tabs.Tab>
|
|
||||||
))}
|
|
||||||
</Tabs.List>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import {
|
|||||||
Drawer,
|
Drawer,
|
||||||
Group,
|
Group,
|
||||||
Loader,
|
Loader,
|
||||||
LoadingOverlay,
|
|
||||||
Space,
|
Space,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Alert, Anchor, Group, Skeleton, Space, Text } from '@mantine/core';
|
import { Alert, Anchor, Group, Skeleton, Space, Text } from '@mantine/core';
|
||||||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { ReactNode, useCallback } from 'react';
|
import { ReactNode, useCallback } from 'react';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
|
@ -15,7 +15,7 @@ export function RenderPart(
|
|||||||
const { instance } = props;
|
const { instance } = props;
|
||||||
|
|
||||||
let badgeText = '';
|
let badgeText = '';
|
||||||
let badgeColor = 'green';
|
let badgeColor = '';
|
||||||
|
|
||||||
let stock = instance.total_in_stock;
|
let stock = instance.total_in_stock;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ import { openContextModal } from '@mantine/modals';
|
|||||||
|
|
||||||
import { DocumentationLinkItem } from '../components/items/DocumentationLinks';
|
import { DocumentationLinkItem } from '../components/items/DocumentationLinks';
|
||||||
import { StylishText } from '../components/items/StylishText';
|
import { StylishText } from '../components/items/StylishText';
|
||||||
|
import { UserRoles } from '../enums/Roles';
|
||||||
import { IS_DEV_OR_DEMO } from '../main';
|
import { IS_DEV_OR_DEMO } from '../main';
|
||||||
|
|
||||||
export const footerLinks = [
|
export const footerLinks = [
|
||||||
@ -25,12 +26,17 @@ export const footerLinks = [
|
|||||||
export const navTabs = [
|
export const navTabs = [
|
||||||
{ text: <Trans>Home</Trans>, name: 'home' },
|
{ text: <Trans>Home</Trans>, name: 'home' },
|
||||||
{ text: <Trans>Dashboard</Trans>, name: 'dashboard' },
|
{ text: <Trans>Dashboard</Trans>, name: 'dashboard' },
|
||||||
{ text: <Trans>Parts</Trans>, name: 'part' },
|
{ text: <Trans>Parts</Trans>, name: 'part', role: UserRoles.part },
|
||||||
{ text: <Trans>Stock</Trans>, name: 'stock' },
|
{ text: <Trans>Stock</Trans>, name: 'stock', role: UserRoles.stock },
|
||||||
{ text: <Trans>Build</Trans>, name: 'build' },
|
{ text: <Trans>Build</Trans>, name: 'build', role: UserRoles.build },
|
||||||
{ text: <Trans>Purchasing</Trans>, name: 'purchasing' },
|
{
|
||||||
{ text: <Trans>Sales</Trans>, name: 'sales' }
|
text: <Trans>Purchasing</Trans>,
|
||||||
|
name: 'purchasing',
|
||||||
|
role: UserRoles.purchase_order
|
||||||
|
},
|
||||||
|
{ text: <Trans>Sales</Trans>, name: 'sales', role: UserRoles.sales_order }
|
||||||
];
|
];
|
||||||
|
|
||||||
if (IS_DEV_OR_DEMO) {
|
if (IS_DEV_OR_DEMO) {
|
||||||
navTabs.push({ text: <Trans>Playground</Trans>, name: 'playground' });
|
navTabs.push({ text: <Trans>Playground</Trans>, name: 'playground' });
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { ActionIcon, Alert, Stack, Text } from '@mantine/core';
|
import { Alert, Stack, Text } from '@mantine/core';
|
||||||
import {
|
import {
|
||||||
IconCalendar,
|
IconCalendar,
|
||||||
IconLink,
|
IconLink,
|
||||||
|
@ -33,10 +33,7 @@ import {
|
|||||||
ApiFormAdjustFilterType,
|
ApiFormAdjustFilterType,
|
||||||
ApiFormFieldSet
|
ApiFormFieldSet
|
||||||
} from '../components/forms/fields/ApiFormField';
|
} from '../components/forms/fields/ApiFormField';
|
||||||
import {
|
import { TableFieldExtraRow } from '../components/forms/fields/TableField';
|
||||||
TableField,
|
|
||||||
TableFieldExtraRow
|
|
||||||
} from '../components/forms/fields/TableField';
|
|
||||||
import { Thumbnail } from '../components/images/Thumbnail';
|
import { Thumbnail } from '../components/images/Thumbnail';
|
||||||
import { ProgressBar } from '../components/items/ProgressBar';
|
import { ProgressBar } from '../components/items/ProgressBar';
|
||||||
import { StylishText } from '../components/items/StylishText';
|
import { StylishText } from '../components/items/StylishText';
|
||||||
|
@ -7,13 +7,10 @@ import { Suspense, useCallback, useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
import { ActionButton } from '../components/buttons/ActionButton';
|
import { ActionButton } from '../components/buttons/ActionButton';
|
||||||
import { StandaloneField } from '../components/forms/StandaloneField';
|
|
||||||
import {
|
import {
|
||||||
ApiFormAdjustFilterType,
|
ApiFormAdjustFilterType,
|
||||||
ApiFormField,
|
|
||||||
ApiFormFieldSet
|
ApiFormFieldSet
|
||||||
} from '../components/forms/fields/ApiFormField';
|
} from '../components/forms/fields/ApiFormField';
|
||||||
import { ChoiceField } from '../components/forms/fields/ChoiceField';
|
|
||||||
import { TableFieldExtraRow } from '../components/forms/fields/TableField';
|
import { TableFieldExtraRow } from '../components/forms/fields/TableField';
|
||||||
import { Thumbnail } from '../components/images/Thumbnail';
|
import { Thumbnail } from '../components/images/Thumbnail';
|
||||||
import { StylishText } from '../components/items/StylishText';
|
import { StylishText } from '../components/items/StylishText';
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { api } from '../App';
|
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
import { apiUrl } from '../states/ApiState';
|
|
||||||
import { useInstance } from './UseInstance';
|
import { useInstance } from './UseInstance';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../enums/ApiEndpoints';
|
||||||
|
@ -14,21 +14,19 @@ export default function Logged_In() {
|
|||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Container>
|
||||||
<Container>
|
<Stack align="center">
|
||||||
<Stack align="center">
|
<Card shadow="sm" padding="lg" radius="md">
|
||||||
<Card shadow="sm" padding="lg" radius="md">
|
<Stack>
|
||||||
<Stack>
|
<Text size="lg">
|
||||||
<Text size="lg">
|
<Trans>Checking if you are already logged in</Trans>
|
||||||
<Trans>Checking if you are already logged in</Trans>
|
</Text>
|
||||||
</Text>
|
<Group justify="center">
|
||||||
<Group justify="center">
|
<Loader />
|
||||||
<Loader />
|
</Group>
|
||||||
</Group>
|
</Stack>
|
||||||
</Stack>
|
</Card>
|
||||||
</Card>
|
</Stack>
|
||||||
</Stack>
|
</Container>
|
||||||
</Container>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,21 +14,19 @@ export default function Logout() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Container>
|
||||||
<Container>
|
<Stack align="center">
|
||||||
<Stack align="center">
|
<Card shadow="sm" padding="lg" radius="md">
|
||||||
<Card shadow="sm" padding="lg" radius="md">
|
<Stack>
|
||||||
<Stack>
|
<Text size="lg">
|
||||||
<Text size="lg">
|
<Trans>Logging out</Trans>
|
||||||
<Trans>Logging out</Trans>
|
</Text>
|
||||||
</Text>
|
<Group justify="center">
|
||||||
<Group justify="center">
|
<Loader />
|
||||||
<Loader />
|
</Group>
|
||||||
</Group>
|
</Stack>
|
||||||
</Stack>
|
</Card>
|
||||||
</Card>
|
</Stack>
|
||||||
</Stack>
|
</Container>
|
||||||
</Container>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -146,16 +146,14 @@ function ApiFormsPlayground() {
|
|||||||
function StatusLabelPlayground() {
|
function StatusLabelPlayground() {
|
||||||
const [status, setStatus] = useState<string>('10');
|
const [status, setStatus] = useState<string>('10');
|
||||||
return (
|
return (
|
||||||
<>
|
<Group>
|
||||||
<Group>
|
<Text>Stock Status</Text>
|
||||||
<Text>Stock Status</Text>
|
<TextInput
|
||||||
<TextInput
|
value={status}
|
||||||
value={status}
|
onChange={(event) => setStatus(event.currentTarget.value)}
|
||||||
onChange={(event) => setStatus(event.currentTarget.value)}
|
/>
|
||||||
/>
|
<StatusRenderer type={ModelType.stockitem} status={status} />
|
||||||
<StatusRenderer type={ModelType.stockitem} status={status} />
|
</Group>
|
||||||
</Group>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,14 +200,12 @@ function PlaygroundArea({
|
|||||||
content: ReactNode;
|
content: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<>
|
<Accordion.Item value={`accordion-playground-${title}`}>
|
||||||
<Accordion.Item value={`accordion-playground-${title}`}>
|
<Accordion.Control>
|
||||||
<Accordion.Control>
|
<Text>{title}</Text>
|
||||||
<Text>{title}</Text>
|
</Accordion.Control>
|
||||||
</Accordion.Control>
|
<Accordion.Panel>{content}</Accordion.Panel>
|
||||||
<Accordion.Panel>{content}</Accordion.Panel>
|
</Accordion.Item>
|
||||||
</Accordion.Item>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ import {
|
|||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { Html5Qrcode } from 'html5-qrcode';
|
import { Html5Qrcode } from 'html5-qrcode';
|
||||||
import { CameraDevice } from 'html5-qrcode/camera/core';
|
import { CameraDevice } from 'html5-qrcode/camera/core';
|
||||||
import { ReactNode, useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { DocInfo } from '../../components/items/DocInfo';
|
import { DocInfo } from '../../components/items/DocInfo';
|
||||||
@ -553,7 +553,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
});
|
});
|
||||||
const [cameras, setCameras] = useState<any[]>([]);
|
const [cameras, setCameras] = useState<any[]>([]);
|
||||||
const [cameraValue, setCameraValue] = useState<string | null>(null);
|
const [cameraValue, setCameraValue] = useState<string | null>(null);
|
||||||
const [ScanningEnabled, setIsScanning] = useState<boolean>(false);
|
const [scanningEnabled, setScanningEnabled] = useState<boolean>(false);
|
||||||
const [wasAutoPaused, setWasAutoPaused] = useState<boolean>(false);
|
const [wasAutoPaused, setWasAutoPaused] = useState<boolean>(false);
|
||||||
const documentState = useDocumentVisibility();
|
const documentState = useDocumentVisibility();
|
||||||
|
|
||||||
@ -580,7 +580,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
|
|
||||||
// Stop/start when leaving or reentering page
|
// Stop/start when leaving or reentering page
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ScanningEnabled && documentState === 'hidden') {
|
if (scanningEnabled && documentState === 'hidden') {
|
||||||
btnStopScanning();
|
btnStopScanning();
|
||||||
setWasAutoPaused(true);
|
setWasAutoPaused(true);
|
||||||
} else if (wasAutoPaused && documentState === 'visible') {
|
} else if (wasAutoPaused && documentState === 'visible') {
|
||||||
@ -642,7 +642,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function btnStartScanning() {
|
function btnStartScanning() {
|
||||||
if (camId && qrCodeScanner && !ScanningEnabled) {
|
if (camId && qrCodeScanner && !scanningEnabled) {
|
||||||
qrCodeScanner
|
qrCodeScanner
|
||||||
.start(
|
.start(
|
||||||
camId.id,
|
camId.id,
|
||||||
@ -662,12 +662,12 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
icon: <IconX />
|
icon: <IconX />
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setIsScanning(true);
|
setScanningEnabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function btnStopScanning() {
|
function btnStopScanning() {
|
||||||
if (qrCodeScanner && ScanningEnabled) {
|
if (qrCodeScanner && scanningEnabled) {
|
||||||
qrCodeScanner.stop().catch((err: string) => {
|
qrCodeScanner.stop().catch((err: string) => {
|
||||||
showNotification({
|
showNotification({
|
||||||
title: t`Error while stopping`,
|
title: t`Error while stopping`,
|
||||||
@ -676,7 +676,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
icon: <IconX />
|
icon: <IconX />
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
setIsScanning(false);
|
setScanningEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +690,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
const cam = cameras.find((cam) => cam.id === cameraValue);
|
const cam = cameras.find((cam) => cam.id === cameraValue);
|
||||||
|
|
||||||
// stop scanning if cam changed while scanning
|
// stop scanning if cam changed while scanning
|
||||||
if (qrCodeScanner && ScanningEnabled) {
|
if (qrCodeScanner && scanningEnabled) {
|
||||||
// stop scanning
|
// stop scanning
|
||||||
qrCodeScanner.stop().then(() => {
|
qrCodeScanner.stop().then(() => {
|
||||||
// change ID
|
// change ID
|
||||||
@ -723,7 +723,7 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
})}
|
})}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
{ScanningEnabled ? (
|
{scanningEnabled ? (
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
onClick={btnStopScanning}
|
onClick={btnStopScanning}
|
||||||
title={t`Stop scanning`}
|
title={t`Stop scanning`}
|
||||||
@ -742,8 +742,8 @@ function InputImageBarcode({ action }: Readonly<ScanInputInterface>) {
|
|||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
)}
|
)}
|
||||||
<Space style={{ flex: 1 }} />
|
<Space style={{ flex: 1 }} />
|
||||||
<Badge color={ScanningEnabled ? 'green' : 'orange'}>
|
<Badge color={scanningEnabled ? 'green' : 'orange'}>
|
||||||
{ScanningEnabled ? t`Scanning` : t`Not scanning`}
|
{scanningEnabled ? t`Scanning` : t`Not scanning`}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
<Container px={0} id="reader" w={'100%'} mih="300px" />
|
<Container px={0} id="reader" w={'100%'} mih="300px" />
|
||||||
|
@ -204,7 +204,7 @@ function EmailContent() {
|
|||||||
|
|
||||||
function SsoContent({ dataProvider }: { dataProvider: any | undefined }) {
|
function SsoContent({ dataProvider }: { dataProvider: any | undefined }) {
|
||||||
const [value, setValue] = useState<string>('');
|
const [value, setValue] = useState<string>('');
|
||||||
const [currentProviders, setcurrentProviders] = useState<[]>();
|
const [currentProviders, setCurrentProviders] = useState<[]>();
|
||||||
const { isLoading, data } = useQuery({
|
const { isLoading, data } = useQuery({
|
||||||
queryKey: ['sso-list'],
|
queryKey: ['sso-list'],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
@ -225,7 +225,7 @@ function SsoContent({ dataProvider }: { dataProvider: any | undefined }) {
|
|||||||
// remove providers that are used currently
|
// remove providers that are used currently
|
||||||
let newData = dataProvider.providers;
|
let newData = dataProvider.providers;
|
||||||
newData = newData.filter(isAlreadyInUse);
|
newData = newData.filter(isAlreadyInUse);
|
||||||
setcurrentProviders(newData);
|
setCurrentProviders(newData);
|
||||||
}, [dataProvider, data]);
|
}, [dataProvider, data]);
|
||||||
|
|
||||||
function removeProvider() {
|
function removeProvider() {
|
||||||
|
@ -120,18 +120,16 @@ export default function UserSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Stack gap="xs">
|
||||||
<Stack gap="xs">
|
<SettingsHeader
|
||||||
<SettingsHeader
|
title={t`Account Settings`}
|
||||||
title={t`Account Settings`}
|
subtitle={`${user?.first_name} ${user?.last_name}`}
|
||||||
subtitle={`${user?.first_name} ${user?.last_name}`}
|
shorthand={user?.username || ''}
|
||||||
shorthand={user?.username || ''}
|
switch_link="/settings/system"
|
||||||
switch_link="/settings/system"
|
switch_text={<Trans>Switch to System Setting</Trans>}
|
||||||
switch_text={<Trans>Switch to System Setting</Trans>}
|
switch_condition={user?.is_staff || false}
|
||||||
switch_condition={user?.is_staff || false}
|
/>
|
||||||
/>
|
<PanelGroup pageKey="user-settings" panels={userSettingsPanels} />
|
||||||
<PanelGroup pageKey="user-settings" panels={userSettingsPanels} />
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -147,11 +147,9 @@ export default function NotificationsPage() {
|
|||||||
}, [unreadTable, readTable]);
|
}, [unreadTable, readTable]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Stack>
|
||||||
<Stack>
|
<PageDetail title={t`Notifications`} />
|
||||||
<PageDetail title={t`Notifications`} />
|
<PanelGroup pageKey="notifications" panels={notificationPanels} />
|
||||||
<PanelGroup pageKey="notifications" panels={notificationPanels} />
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Stack } from '@mantine/core';
|
import { Stack } from '@mantine/core';
|
||||||
|
|
||||||
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
|
import { UserRoles } from '../../enums/Roles';
|
||||||
|
import { useUserState } from '../../states/UserState';
|
||||||
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
|
import { BuildOrderTable } from '../../tables/build/BuildOrderTable';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build Order index page
|
* Build Order index page
|
||||||
*/
|
*/
|
||||||
export default function BuildIndex() {
|
export default function BuildIndex() {
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
|
if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.build)) {
|
||||||
|
return <PermissionDenied />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Stack>
|
||||||
<Stack>
|
<PageDetail title={t`Build Orders`} actions={[]} />
|
||||||
<PageDetail title={t`Build Orders`} actions={[]} />
|
<BuildOrderTable />
|
||||||
<BuildOrderTable />
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import { UserRoles } from '../../enums/Roles';
|
|||||||
import { companyFields } from '../../forms/CompanyForms';
|
import { companyFields } from '../../forms/CompanyForms';
|
||||||
import { useEditApiFormModal } from '../../hooks/UseForm';
|
import { useEditApiFormModal } from '../../hooks/UseForm';
|
||||||
import { useInstance } from '../../hooks/UseInstance';
|
import { useInstance } from '../../hooks/UseInstance';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
|
||||||
import { useUserState } from '../../states/UserState';
|
import { useUserState } from '../../states/UserState';
|
||||||
import { AddressTable } from '../../tables/company/AddressTable';
|
import { AddressTable } from '../../tables/company/AddressTable';
|
||||||
import { ContactTable } from '../../tables/company/ContactTable';
|
import { ContactTable } from '../../tables/company/ContactTable';
|
||||||
|
@ -31,11 +31,7 @@ export enum panelOptions {
|
|||||||
export default function PartPricingPanel({ part }: { part: any }) {
|
export default function PartPricingPanel({ part }: { part: any }) {
|
||||||
const user = useUserState();
|
const user = useUserState();
|
||||||
|
|
||||||
const {
|
const { instance: pricing, instanceQuery } = useInstance({
|
||||||
instance: pricing,
|
|
||||||
refreshInstance,
|
|
||||||
instanceQuery
|
|
||||||
} = useInstance({
|
|
||||||
pk: part?.pk,
|
pk: part?.pk,
|
||||||
hasPrimaryKey: true,
|
hasPrimaryKey: true,
|
||||||
endpoint: ApiEndpoints.part_pricing_get,
|
endpoint: ApiEndpoints.part_pricing_get,
|
||||||
|
@ -12,11 +12,7 @@ import { ReactNode, useMemo, useState } from 'react';
|
|||||||
|
|
||||||
import { CHART_COLORS } from '../../../components/charts/colors';
|
import { CHART_COLORS } from '../../../components/charts/colors';
|
||||||
import { tooltipFormatter } from '../../../components/charts/tooltipFormatter';
|
import { tooltipFormatter } from '../../../components/charts/tooltipFormatter';
|
||||||
import {
|
import { formatDecimal, formatPriceRange } from '../../../defaults/formatters';
|
||||||
formatCurrency,
|
|
||||||
formatDecimal,
|
|
||||||
formatPriceRange
|
|
||||||
} from '../../../defaults/formatters';
|
|
||||||
import { ApiEndpoints } from '../../../enums/ApiEndpoints';
|
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';
|
||||||
|
@ -7,12 +7,17 @@ import {
|
|||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup } from '../../components/nav/PanelGroup';
|
import { PanelGroup } from '../../components/nav/PanelGroup';
|
||||||
|
import { UserRoles } from '../../enums/Roles';
|
||||||
|
import { useUserState } from '../../states/UserState';
|
||||||
import { CompanyTable } from '../../tables/company/CompanyTable';
|
import { CompanyTable } from '../../tables/company/CompanyTable';
|
||||||
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
|
import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable';
|
||||||
|
|
||||||
export default function PurchasingIndex() {
|
export default function PurchasingIndex() {
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const panels = useMemo(() => {
|
const panels = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -46,12 +51,14 @@ export default function PurchasingIndex() {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.purchase_order)) {
|
||||||
|
return <PermissionDenied />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Stack>
|
||||||
<Stack>
|
<PageDetail title={t`Purchasing`} />
|
||||||
<PageDetail title={t`Purchasing`} />
|
<PanelGroup pageKey="purchasing-index" panels={panels} />
|
||||||
<PanelGroup pageKey="purchasing-index" panels={panels} />
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,18 @@ import {
|
|||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
import PermissionDenied from '../../components/errors/PermissionDenied';
|
||||||
import { PageDetail } from '../../components/nav/PageDetail';
|
import { PageDetail } from '../../components/nav/PageDetail';
|
||||||
import { PanelGroup } from '../../components/nav/PanelGroup';
|
import { PanelGroup } from '../../components/nav/PanelGroup';
|
||||||
|
import { UserRoles } from '../../enums/Roles';
|
||||||
|
import { useUserState } from '../../states/UserState';
|
||||||
import { CompanyTable } from '../../tables/company/CompanyTable';
|
import { CompanyTable } from '../../tables/company/CompanyTable';
|
||||||
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
|
import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable';
|
||||||
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
|
import { SalesOrderTable } from '../../tables/sales/SalesOrderTable';
|
||||||
|
|
||||||
export default function PurchasingIndex() {
|
export default function PurchasingIndex() {
|
||||||
|
const user = useUserState();
|
||||||
|
|
||||||
const panels = useMemo(() => {
|
const panels = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -39,12 +44,14 @@ export default function PurchasingIndex() {
|
|||||||
];
|
];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.sales_order)) {
|
||||||
|
return <PermissionDenied />;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Stack>
|
||||||
<Stack>
|
<PageDetail title={t`Sales`} />
|
||||||
<PageDetail title={t`Sales`} />
|
<PanelGroup pageKey="sales-index" panels={panels} />
|
||||||
<PanelGroup pageKey="sales-index" panels={panels} />
|
</Stack>
|
||||||
</Stack>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { ActionIcon, Menu, Tooltip } from '@mantine/core';
|
|
||||||
import {
|
import {
|
||||||
IconDownload,
|
IconDownload,
|
||||||
IconFileSpreadsheet,
|
IconFileSpreadsheet,
|
||||||
@ -33,12 +32,10 @@ export function DownloadAction({
|
|||||||
}, [formatOptions, downloadCallback]);
|
}, [formatOptions, downloadCallback]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ActionDropdown
|
||||||
<ActionDropdown
|
tooltip={t`Download Data`}
|
||||||
tooltip={t`Download Data`}
|
icon={<IconDownload />}
|
||||||
icon={<IconDownload />}
|
actions={actions}
|
||||||
actions={actions}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,5 @@ import { IconUpload } from '@tabler/icons-react';
|
|||||||
import { ActionButton } from '../components/buttons/ActionButton';
|
import { ActionButton } from '../components/buttons/ActionButton';
|
||||||
|
|
||||||
export function UploadAction({}) {
|
export function UploadAction({}) {
|
||||||
return (
|
return <ActionButton icon={<IconUpload />} tooltip={t`Upload Data`} />;
|
||||||
<>
|
|
||||||
<ActionButton icon={<IconUpload />} tooltip={t`Upload Data`} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
IconUpload,
|
IconUpload,
|
||||||
IconX
|
IconX
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
|
import { ReactNode, useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import { api } from '../../App';
|
import { api } from '../../App';
|
||||||
import { ActionButton } from '../../components/buttons/ActionButton';
|
import { ActionButton } from '../../components/buttons/ActionButton';
|
||||||
@ -28,7 +28,7 @@ import { useUserState } from '../../states/UserState';
|
|||||||
import { TableColumn } from '../Column';
|
import { TableColumn } from '../Column';
|
||||||
import { TableFilter } from '../Filter';
|
import { TableFilter } from '../Filter';
|
||||||
import { InvenTreeTable } from '../InvenTreeTable';
|
import { InvenTreeTable } from '../InvenTreeTable';
|
||||||
import { RowAction, RowDeleteAction, RowEditAction } from '../RowActions';
|
import { RowDeleteAction, RowEditAction } from '../RowActions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define set of columns to display for the attachment table
|
* Define set of columns to display for the attachment table
|
||||||
|
@ -128,13 +128,13 @@ export function PartThumbTable({
|
|||||||
pk,
|
pk,
|
||||||
setImage
|
setImage
|
||||||
}: ThumbTableProps) {
|
}: ThumbTableProps) {
|
||||||
const [img, selectImage] = useState<string | null>(null);
|
const [thumbImage, setThumbImage] = useState<string | null>(null);
|
||||||
const [filterInput, setFilterInput] = useState<string>('');
|
const [filterInput, setFilterInput] = useState<string>('');
|
||||||
const [filterQuery, setFilter] = useState<string>(search);
|
const [filterQuery, setFilterQuery] = useState<string>(search);
|
||||||
|
|
||||||
// Keep search filters from updating while user is typing
|
// Keep search filters from updating while user is typing
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timeoutId = setTimeout(() => setFilter(filterInput), 500);
|
const timeoutId = setTimeout(() => setFilterQuery(filterInput), 500);
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
}, [filterInput]);
|
}, [filterInput]);
|
||||||
|
|
||||||
@ -160,30 +160,28 @@ export function PartThumbTable({
|
|||||||
<Suspense>
|
<Suspense>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Paper p="sm">
|
<Paper p="sm">
|
||||||
<>
|
<SimpleGrid cols={8}>
|
||||||
<SimpleGrid cols={8}>
|
{!thumbQuery.isFetching
|
||||||
{!thumbQuery.isFetching
|
? thumbQuery.data?.data.map(
|
||||||
? thumbQuery.data?.data.map(
|
(data: ImageElement, index: number) => (
|
||||||
(data: ImageElement, index: number) => (
|
<PartThumbComponent
|
||||||
<PartThumbComponent
|
element={data}
|
||||||
element={data}
|
key={index}
|
||||||
key={index}
|
selected={thumbImage}
|
||||||
selected={img}
|
selectImage={setThumbImage}
|
||||||
selectImage={selectImage}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
: [...Array(limit)].map((elem, idx) => (
|
|
||||||
<Skeleton
|
|
||||||
height={150}
|
|
||||||
width={150}
|
|
||||||
radius="sm"
|
|
||||||
key={idx}
|
|
||||||
style={{ padding: '5px' }}
|
|
||||||
/>
|
/>
|
||||||
))}
|
)
|
||||||
</SimpleGrid>
|
)
|
||||||
</>
|
: [...Array(limit)].map((elem, idx) => (
|
||||||
|
<Skeleton
|
||||||
|
height={150}
|
||||||
|
width={150}
|
||||||
|
radius="sm"
|
||||||
|
key={idx}
|
||||||
|
style={{ padding: '5px' }}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</SimpleGrid>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
@ -197,8 +195,8 @@ export function PartThumbTable({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
disabled={!img}
|
disabled={!thumbImage}
|
||||||
onClick={() => setNewImage(img, pk, setImage)}
|
onClick={() => setNewImage(thumbImage, pk, setImage)}
|
||||||
>
|
>
|
||||||
<Trans>Select</Trans>
|
<Trans>Select</Trans>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { Text } from '@mantine/core';
|
import { Text } from '@mantine/core';
|
||||||
import { Action } from '@mdxeditor/editor';
|
|
||||||
import { IconFileArrowLeft, IconSquareArrowRight } from '@tabler/icons-react';
|
import { IconFileArrowLeft, IconSquareArrowRight } from '@tabler/icons-react';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import { RowAction, RowDeleteAction } from '../RowActions';
|
|||||||
|
|
||||||
export default function ImportSesssionTable() {
|
export default function ImportSesssionTable() {
|
||||||
const table = useTable('importsession');
|
const table = useTable('importsession');
|
||||||
const user = useUserState();
|
|
||||||
|
|
||||||
const [opened, setOpened] = useState<boolean>(false);
|
const [opened, setOpened] = useState<boolean>(false);
|
||||||
|
|
||||||
|
@ -50,20 +50,18 @@ export default function InstalledItemsTable({
|
|||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<InvenTreeTable
|
||||||
<InvenTreeTable
|
url={apiUrl(ApiEndpoints.stock_item_list)}
|
||||||
url={apiUrl(ApiEndpoints.stock_item_list)}
|
tableState={table}
|
||||||
tableState={table}
|
columns={tableColumns}
|
||||||
columns={tableColumns}
|
props={{
|
||||||
props={{
|
tableActions: tableActions,
|
||||||
tableActions: tableActions,
|
modelType: ModelType.stockitem,
|
||||||
modelType: ModelType.stockitem,
|
params: {
|
||||||
params: {
|
belongs_to: parentId,
|
||||||
belongs_to: parentId,
|
part_detail: true
|
||||||
part_detail: true
|
}
|
||||||
}
|
}}
|
||||||
}}
|
/>
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { expect } from './baseFixtures.js';
|
import { expect } from './baseFixtures.js';
|
||||||
import { baseUrl, loginUrl, logoutUrl, user } from './defaults';
|
import { baseUrl, logoutUrl, user } from './defaults';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform form based login operation from the "login" URL
|
* Perform form based login operation from the "login" URL
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { expect, test } from './baseFixtures.js';
|
import { expect, test } from './baseFixtures.js';
|
||||||
import { baseUrl, loginUrl, user } from './defaults.js';
|
import { baseUrl, user } from './defaults.js';
|
||||||
import { doLogin, doQuickLogin } from './login.js';
|
import { doLogin, doQuickLogin } from './login.js';
|
||||||
|
|
||||||
test('PUI - Basic Login Test', async ({ page }) => {
|
test('PUI - Basic Login Test', async ({ page }) => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { test } from './baseFixtures.js';
|
import { test } from './baseFixtures.js';
|
||||||
import { baseUrl } from './defaults.js';
|
import { baseUrl } from './defaults.js';
|
||||||
import { doLogout, doQuickLogin } from './login.js';
|
import { doQuickLogin } from './login.js';
|
||||||
|
|
||||||
test('PUI - Parts', async ({ page }) => {
|
test('PUI - Parts', async ({ page }) => {
|
||||||
await doQuickLogin(page);
|
await doQuickLogin(page);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { test } from './baseFixtures.js';
|
import { test } from './baseFixtures.js';
|
||||||
import { baseUrl } from './defaults.js';
|
import { baseUrl } from './defaults.js';
|
||||||
import { doLogout, doQuickLogin } from './login.js';
|
import { doQuickLogin } from './login.js';
|
||||||
|
|
||||||
test('PUI - Admin', async ({ page }) => {
|
test('PUI - Admin', async ({ page }) => {
|
||||||
// Note here we login with admin access
|
// Note here we login with admin access
|
||||||
|
Loading…
Reference in New Issue
Block a user