Update frontend. Fixed CreateInstallation and delete Installation bug

This commit is contained in:
Noe 2025-09-11 14:28:49 +02:00
parent 73880f0737
commit 2b1d550571
11 changed files with 166 additions and 187 deletions

View File

@ -312,8 +312,7 @@ public static class SessionMethods
&& installation is not null && installation is not null
&& user.UserType != 0) && user.UserType != 0)
{ {
if (installation.Product is (int)ProductType.Salimax or (int)ProductType.Salidomo || installation.Product == (int)ProductType.SodiStoreMax)
{
return return
Db.Delete(installation) Db.Delete(installation)
&& await installation.RevokeReadKey() && await installation.RevokeReadKey()
@ -321,12 +320,7 @@ public static class SessionMethods
&& await installation.RemoveReadRole() && await installation.RemoveReadRole()
&& await installation.RemoveWriteRole() && await installation.RemoveWriteRole()
&& await installation.DeleteBucket(); && await installation.DeleteBucket();
}
else
{
return Db.Delete(installation);
}
} }
return false; return false;

View File

@ -22,6 +22,8 @@ import { UserContext } from '../../../contexts/userContext';
import { UserType } from '../../../interfaces/UserTypes'; import { UserType } from '../../../interfaces/UserTypes';
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider'; import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
import { useLocation, useNavigate } from 'react-router-dom';
interface InformationProps { interface InformationProps {
values: I_Installation; values: I_Installation;
s3Credentials: I_S3Credentials; s3Credentials: I_S3Credentials;
@ -82,10 +84,28 @@ function Information(props: InformationProps) {
setOpenModalDeleteInstallation(true); setOpenModalDeleteInstallation(true);
}; };
const location = useLocation();
const navigate = useNavigate();
const deleteInstallationModalHandle = () => { const deleteInstallationModalHandle = () => {
setOpenModalDeleteInstallation(false); setOpenModalDeleteInstallation(false);
deleteInstallation(formValues, props.type); deleteInstallation(formValues, props.type);
setLoading(false); setLoading(false);
const pathSegments = location.pathname.split('/'); // e.g. ['', 'sodiohome_installations', 'list', 'installation', '123', 'information']
const base = `/${pathSegments[1]}`;
const isListView = pathSegments.includes('list');
const isTreeView = pathSegments.includes('tree');
if (isListView) {
navigate(`${base}/list/`);
} else if (isTreeView) {
navigate(`${base}/tree/`);
} else {
// fallback
navigate(`${base}/list/`);
}
}; };
const deleteInstallationModalHandleCancel = () => { const deleteInstallationModalHandleCancel = () => {

View File

@ -51,6 +51,7 @@ function InstallationTabs(props: InstallationTabsProps) {
if (path[path.length - 2] === 'list') { if (path[path.length - 2] === 'list') {
setCurrentTab('list'); setCurrentTab('list');
fetchAllInstallations(product, false);
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {

View File

@ -26,7 +26,6 @@ function installationForm(props: installationFormProps) {
const theme = useTheme(); const theme = useTheme();
const [open, setOpen] = useState(true); const [open, setOpen] = useState(true);
console.log('productToInsert IS ', props.productToInsert);
const [formValues, setFormValues] = useState<Partial<I_Installation>>({ const [formValues, setFormValues] = useState<Partial<I_Installation>>({
installationName: '', installationName: '',
name: '', name: '',
@ -64,6 +63,7 @@ function installationForm(props: installationFormProps) {
formValues.parentId = props.parentid; formValues.parentId = props.parentid;
formValues.product = props.productToInsert; formValues.product = props.productToInsert;
const responseData = await createInstallation(formValues); const responseData = await createInstallation(formValues);
console.log('awaited');
props.submit(); props.submit();
}; };
const handleCancelSubmit = (e) => { const handleCancelSubmit = (e) => {

View File

@ -35,7 +35,7 @@ function SalidomoInstallationTabs(props: InstallationTabsProps) {
const { const {
salidomoInstallations, salidomoInstallations,
fetchAllSalidomoInstallations, fetchAllInstallations,
socket, socket,
openSocket, openSocket,
closeSocket closeSocket
@ -48,6 +48,7 @@ function SalidomoInstallationTabs(props: InstallationTabsProps) {
if (path[path.length - 2] === 'list') { if (path[path.length - 2] === 'list') {
setCurrentTab('list'); setCurrentTab('list');
fetchAllInstallations(product, false);
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {
@ -62,7 +63,7 @@ function SalidomoInstallationTabs(props: InstallationTabsProps) {
useEffect(() => { useEffect(() => {
if (product == props.product) { if (product == props.product) {
fetchAllSalidomoInstallations(); fetchAllInstallations(product);
} }
}, [product]); }, [product]);

View File

@ -37,7 +37,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
useState<boolean>(false); useState<boolean>(false);
const { const {
sodiohomeInstallations, sodiohomeInstallations,
fetchAllSodiohomeInstallations, fetchAllInstallations,
socket, socket,
openSocket, openSocket,
closeSocket closeSocket
@ -49,6 +49,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
if (path[path.length - 2] === 'list') { if (path[path.length - 2] === 'list') {
setCurrentTab('list'); setCurrentTab('list');
fetchAllInstallations(product, false);
} else if (path[path.length - 2] === 'tree') { } else if (path[path.length - 2] === 'tree') {
setCurrentTab('tree'); setCurrentTab('tree');
} else { } else {
@ -63,7 +64,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) {
useEffect(() => { useEffect(() => {
if (product == props.product) { if (product == props.product) {
fetchAllSodiohomeInstallations(); fetchAllInstallations(product);
} }
}, [product]); }, [product]);

View File

@ -46,6 +46,7 @@ function CustomTreeItem(props: CustomTreeItemProps) {
const handleSelectOneInstallation = (): void => { const handleSelectOneInstallation = (): void => {
let installation = props.node; let installation = props.node;
let installation_path = let installation_path =
installation.product == 0 installation.product == 0
? routes.installations ? routes.installations
@ -60,7 +61,7 @@ function CustomTreeItem(props: CustomTreeItemProps) {
? routes.installations ? routes.installations
: product == 1 : product == 1
? routes.salidomo_installations ? routes.salidomo_installations
: installation.product == 2 : product == 2
? routes.sodiohome_installations ? routes.sodiohome_installations
: routes.sodistore_installations; : routes.sodistore_installations;

View File

@ -54,17 +54,17 @@ function TreeInformation(props: TreeInformationProps) {
updated, updated,
setUpdated, setUpdated,
updateFolder, updateFolder,
deleteFolder deleteFolder,
fetchAllInstallations
} = installationContext; } = installationContext;
const [product, setProduct] = useState('Salimax'); const [product, setProduct] = useState('Salimax');
const handleChangeInstallationChoice = (e) => { const handleChangeInstallationChoice = (e) => {
setProduct(e.target.value); // Directly update the product state setProduct(e.target.value); // Directly update the product state
// console.log('Selected Product:', e.target.value);
}; };
const ProductTypes = ['Salimax', 'Salidomo', 'Sodiohome', 'SodistoreMax']; const ProductTypes = ['Salimax', 'Salidomo', 'SodistoreHome', 'SodistoreMax'];
const isMobile = window.innerWidth <= 1490; const isMobile = window.innerWidth <= 1490;
@ -84,7 +84,6 @@ function TreeInformation(props: TreeInformationProps) {
const handleNewInstallationInsertion = () => { const handleNewInstallationInsertion = () => {
setOpenModalInstallationChoice(true); setOpenModalInstallationChoice(true);
//setOpenModalInstallation(true);
}; };
const handleCancelSubmitInstallationChoice = () => { const handleCancelSubmitInstallationChoice = () => {
@ -323,7 +322,7 @@ function TreeInformation(props: TreeInformationProps) {
)} )}
{openModalInstallation && {openModalInstallation &&
(product == 'Salimax' || (product == 'Salimax' ||
product == 'Sodiohome' || product == 'SodistoreHome' ||
product == 'SodistoreMax') && ( product == 'SodistoreMax') && (
<InstallationForm <InstallationForm
cancel={handleFormCancel} cancel={handleFormCancel}
@ -339,13 +338,6 @@ function TreeInformation(props: TreeInformationProps) {
parentid={props.folder.id} parentid={props.folder.id}
/> />
)} )}
{/*{openModalInstallation && product == 'Sodiohome' && (*/}
{/* <SodiohomeInstallationForm*/}
{/* cancel={handleFormCancel}*/}
{/* submit={handleInstallationFormSubmit}*/}
{/* parentid={props.folder.id}*/}
{/* />*/}
{/*)}*/}
<Container maxWidth="xl"> <Container maxWidth="xl">
<Grid <Grid

View File

@ -80,7 +80,7 @@ function InstallationTree() {
key={installation.id} key={installation.id}
path={routes.installation + installation.id + '*'} path={routes.installation + installation.id + '*'}
element={ element={
installation.product == 0 ? ( installation.product == 0 || installation.product == 3 ? (
<Installation <Installation
key={installation.id} key={installation.id}
current_installation={installation} current_installation={installation}

View File

@ -1,4 +1,3 @@
import { AxiosError, AxiosResponse } from 'axios';
import { import {
createContext, createContext,
ReactNode, ReactNode,
@ -39,12 +38,8 @@ const InstallationsContextProvider = ({
const navigate = useNavigate(); const navigate = useNavigate();
const tokencontext = useContext(TokenContext); const tokencontext = useContext(TokenContext);
const { removeToken } = tokencontext; const { removeToken } = tokencontext;
// const [socket, setSocket] = useState<WebSocket>(null);
const socket = useRef<WebSocket | null>(null); // Using useRef instead of useState const socket = useRef<WebSocket | null>(null); // Using useRef instead of useState
//const [currentProduct, setcurrentProduct] = useState<number>(0);
//Store pending updates and apply them in batches //Store pending updates and apply them in batches
const pendingUpdates = useRef< const pendingUpdates = useRef<
Record<number, { status: number; testingMode: boolean }> Record<number, { status: number; testingMode: boolean }>
@ -165,56 +160,36 @@ const InstallationsContextProvider = ({
// Function to fetch installations and manage the socket // Function to fetch installations and manage the socket
const fetchAllInstallations = useCallback( const fetchAllInstallations = useCallback(
async (product: number) => { async (product: number, open_socket: boolean = true) => {
axiosConfig try {
.get(`/GetAllInstallationsFromProduct?product=${product}`) const res = await axiosConfig.get(
.then((res: AxiosResponse<I_Installation[]>) => { `/GetAllInstallationsFromProduct?product=${product}`
setSalimax_Or_Sodistore_Installations(res.data); // Update installations );
openSocket(res.data); // Open a new socket after installations are fetched
}) if (product === 2) {
.catch((err: AxiosError) => { setSodiohomeInstallations(res.data);
if (err.response?.status === 401) { } else if (product === 1) {
removeToken(); setSalidomoInstallations(res.data);
navigate(routes.login); } else if (product === 0 || product === 3) {
} setSalimax_Or_Sodistore_Installations(res.data);
}); }
if (open_socket) {
openSocket(res.data);
}
} catch (err: any) {
if (err.response?.status === 401) {
removeToken();
navigate(routes.login);
}
}
}, },
[navigate, removeToken] [navigate, removeToken]
); );
const fetchAllSalidomoInstallations = useCallback(async () => {
axiosConfig
.get('/GetAllSalidomoInstallations')
.then((res: AxiosResponse<I_Installation[]>) => {
setSalidomoInstallations(res.data);
openSocket(res.data);
})
.catch((err: AxiosError) => {
if (err.response?.status === 401) {
removeToken();
navigate(routes.login);
}
});
}, [navigate, removeToken]);
const fetchAllSodiohomeInstallations = useCallback(async () => {
axiosConfig
.get('/GetAllSodioHomeInstallations')
.then((res: AxiosResponse<I_Installation[]>) => {
setSodiohomeInstallations(res.data);
openSocket(res.data);
})
.catch((err: AxiosError) => {
if (err.response?.status === 401) {
removeToken();
navigate(routes.login);
}
});
}, [navigate, removeToken]);
const fetchAllFoldersAndInstallations = useCallback( const fetchAllFoldersAndInstallations = useCallback(
async (product: number) => { async (product: number) => {
axiosConfig await axiosConfig
.get(`/GetAllFoldersAndInstallations?productId=${product}`) .get(`/GetAllFoldersAndInstallations?productId=${product}`)
.then((res) => setFoldersAndInstallations(res.data)) .then((res) => setFoldersAndInstallations(res.data))
.catch((err) => { .catch((err) => {
@ -229,52 +204,50 @@ const InstallationsContextProvider = ({
const createInstallation = useCallback( const createInstallation = useCallback(
async (formValues: Partial<I_Installation>) => { async (formValues: Partial<I_Installation>) => {
axiosConfig try {
.post('/CreateInstallation', formValues) // wait for the POST to finish
.then(() => { const res = await axiosConfig.post('/CreateInstallation', formValues);
setLoading(false); const product = formValues.product; // or res.data.product
fetchAllFoldersAndInstallations(formValues.product); await Promise.resolve(fetchAllFoldersAndInstallations(product));
}) await Promise.resolve(fetchAllInstallations(product));
.catch((error) => { setLoading(false);
setError(true);
if (error.response?.status === 401) { return res.data; // let callers await this if they want
removeToken(); } catch (error: any) {
navigate(routes.login); setError(true);
} setLoading(false);
}); if (error.response?.status === 401) {
removeToken();
navigate(routes.login);
}
}
}, },
[fetchAllFoldersAndInstallations, navigate, removeToken] [navigate, removeToken, fetchAllFoldersAndInstallations]
); );
const updateInstallation = useCallback( const updateInstallation = useCallback(
async (formValues: I_Installation, view: string) => { async (formValues: I_Installation, view: string) => {
axiosConfig try {
.put('/UpdateInstallation', formValues) const res = await axiosConfig.put('/UpdateInstallation', formValues);
.then(() => {
setUpdated(true); setUpdated(true);
setLoading(false); setLoading(false);
if (formValues.product === 0 && view === 'installation') const product = formValues.product; // or res.data.product
fetchAllInstallations(formValues.product); await Promise.resolve(fetchAllFoldersAndInstallations(product));
else if (formValues.product === 1 && view === 'installation') await Promise.resolve(fetchAllInstallations(product));
fetchAllSalidomoInstallations(); setTimeout(() => setUpdated(false), 3000);
else if (formValues.product === 2 && view === 'installation') } catch (error) {
fetchAllSodiohomeInstallations(); setError(true);
else fetchAllFoldersAndInstallations(formValues.product); setLoading(false);
setTimeout(() => setUpdated(false), 3000); if (error.response?.status === 401) {
}) removeToken();
.catch((error) => { navigate(routes.login);
setError(true); }
if (error.response?.status === 401) { }
removeToken();
navigate(routes.login);
}
});
}, },
[ [
fetchAllFoldersAndInstallations, fetchAllFoldersAndInstallations,
fetchAllInstallations, fetchAllInstallations,
fetchAllSalidomoInstallations,
fetchAllSodiohomeInstallations,
navigate, navigate,
removeToken removeToken
] ]
@ -282,97 +255,96 @@ const InstallationsContextProvider = ({
const deleteInstallation = useCallback( const deleteInstallation = useCallback(
async (formValues: I_Installation, view: string) => { async (formValues: I_Installation, view: string) => {
axiosConfig try {
.delete(`/DeleteInstallation?installationId=${formValues.id}`) // wait for the POST to finish
.then(() => { const res = await axiosConfig.delete(
setUpdated(true); `/DeleteInstallation?installationId=${formValues.id}`
setLoading(false); );
if (formValues.product === 0 && view === 'installation') setUpdated(true);
fetchAllInstallations(formValues.product); setTimeout(() => setUpdated(false), 3000);
else if (formValues.product === 1 && view === 'installation') setLoading(false);
fetchAllSalidomoInstallations();
else if (formValues.product === 2 && view === 'installation') const product = formValues.product; // or res.data.product
fetchAllSodiohomeInstallations(); await Promise.resolve(fetchAllFoldersAndInstallations(product));
else fetchAllFoldersAndInstallations(formValues.product); await Promise.resolve(fetchAllInstallations(product));
setTimeout(() => setUpdated(false), 3000);
}) return res.data; // let callers await this if they want
.catch((error) => { } catch (error: any) {
setError(true); setError(true);
if (error.response?.status === 401) { setLoading(false);
removeToken(); if (error.response?.status === 401) {
navigate(routes.login); removeToken();
} navigate(routes.login);
}); }
}
}, },
[ [
fetchAllFoldersAndInstallations,
fetchAllInstallations,
fetchAllSalidomoInstallations,
fetchAllSodiohomeInstallations,
navigate, navigate,
removeToken removeToken,
sodiohomeInstallations,
fetchAllFoldersAndInstallations,
fetchAllInstallations
] ]
); );
const createFolder = useCallback( const createFolder = useCallback(
async (formValues: Partial<I_Folder>, product: number) => { async (formValues: Partial<I_Folder>, product: number) => {
axiosConfig try {
.post('/CreateFolder', formValues) const res = await axiosConfig.post('/CreateFolder', formValues);
.then(() => {
setLoading(false); setLoading(false);
fetchAllFoldersAndInstallations(product); await Promise.resolve(fetchAllFoldersAndInstallations(product));
}) } catch (error) {
.catch((error) => { setError(true);
setError(true); if (error.response?.status === 401) {
if (error.response?.status === 401) { removeToken();
removeToken(); navigate(routes.login);
navigate(routes.login); }
} }
});
}, },
[fetchAllFoldersAndInstallations, navigate, removeToken] [fetchAllFoldersAndInstallations, navigate, removeToken]
); );
const updateFolder = useCallback( const updateFolder = useCallback(
async (formValues: I_Folder, product: number) => { async (formValues: I_Folder, product: number) => {
axiosConfig try {
.put('/UpdateFolder', formValues) const res = await axiosConfig.put('/UpdateFolder', formValues);
.then(() => {
setLoading(false);
setUpdated(true);
fetchAllFoldersAndInstallations(product); setLoading(false);
setTimeout(() => setUpdated(false), 3000); setUpdated(true);
setLoading(false); setTimeout(() => setUpdated(false), 3000);
})
.catch((error) => { await Promise.resolve(fetchAllFoldersAndInstallations(product));
setError(true);
if (error.response?.status === 401) { setLoading(false);
removeToken(); } catch (error) {
navigate(routes.login); setError(true);
} if (error.response?.status === 401) {
}); removeToken();
navigate(routes.login);
}
}
}, },
[fetchAllFoldersAndInstallations, navigate, removeToken] [fetchAllFoldersAndInstallations, navigate, removeToken]
); );
const deleteFolder = useCallback( const deleteFolder = useCallback(
async (formValues: I_Folder, product: number) => { async (formValues: I_Folder, product: number) => {
axiosConfig try {
.delete(`/DeleteFolder?folderId=${formValues.id}`) const res = await axiosConfig.delete(
.then(() => { `/DeleteFolder?folderId=${formValues.id}`
setUpdated(true); );
setLoading(false); setUpdated(true);
fetchAllFoldersAndInstallations(product); setLoading(false);
setTimeout(() => setUpdated(false), 3000); await Promise.resolve(fetchAllFoldersAndInstallations(product));
}) setTimeout(() => setUpdated(false), 3000);
.catch((error) => { } catch (error) {
setError(true); setError(true);
if (error.response?.status === 401) { if (error.response?.status === 401) {
removeToken(); removeToken();
navigate(routes.login); navigate(routes.login);
} }
}); }
}, },
[fetchAllFoldersAndInstallations, navigate, removeToken] [fetchAllFoldersAndInstallations, navigate, removeToken]
); );
@ -384,8 +356,6 @@ const InstallationsContextProvider = ({
sodiohomeInstallations, sodiohomeInstallations,
foldersAndInstallations, foldersAndInstallations,
fetchAllInstallations, fetchAllInstallations,
fetchAllSalidomoInstallations,
fetchAllSodiohomeInstallations,
fetchAllFoldersAndInstallations, fetchAllFoldersAndInstallations,
createInstallation, createInstallation,
updateInstallation, updateInstallation,
@ -413,7 +383,6 @@ const InstallationsContextProvider = ({
error, error,
updated, updated,
socket socket
//currentProduct
] ]
); );

View File

@ -255,7 +255,7 @@ function SidebarMenu() {
<Box sx={{ marginTop: '3px' }}> <Box sx={{ marginTop: '3px' }}>
<FormattedMessage <FormattedMessage
id="sodiohome" id="sodiohome"
defaultMessage="Sodiohome" defaultMessage="Sodistore Home"
/> />
</Box> </Box>
</Button> </Button>