diff --git a/typescript/frontend-marios2/src/App.tsx b/typescript/frontend-marios2/src/App.tsx index 368465a5f..088283b84 100644 --- a/typescript/frontend-marios2/src/App.tsx +++ b/typescript/frontend-marios2/src/App.tsx @@ -95,11 +95,19 @@ function App() { const Login = Loader(lazy(() => import('src/components/login'))); const Users = Loader(lazy(() => import('src/content/dashboards/Users'))); - const loginToResetPassword = () => { + useEffect(() => { + if (!username || token) return; + axiosConfigWithoutToken .post('/Login', null, { params: { username, password: '' } }) .then((response) => { if (response.data && response.data.token) { + // Clear the username param from URL to prevent re-login loops + const url = new URL(window.location.href); + url.searchParams.delete('username'); + url.searchParams.delete('reset'); + window.history.replaceState({}, '', url.pathname); + setNewToken(response.data.token); setUser(response.data.user); setAccessToSalimax(response.data.accessToSalimax); @@ -108,27 +116,10 @@ function App() { setAccessToSodistore(response.data.accessToSodistoreMax); setAccessToSodistoreGrid(response.data.accessToSodistoreGrid); setAccessToSodistorePro(response.data.accessToSodistorePro); - if (response.data.accessToSalimax) { - navigate(routes.installations); - } else if (response.data.accessToSalidomo) { - navigate(routes.salidomo_installations); - } else if (response.data.accessToSodistoreMax) { - navigate(routes.sodistore_installations); - } else if (response.data.accessToSodistoreGrid) { - navigate(routes.sodistoregrid_installations); - } else if (response.data.accessToSodistorePro) { - navigate(routes.sodistorepro_installations); - } else { - navigate(routes.sodiohome_installations); - } } }) .catch(() => {}); - }; - - if (username) { - loginToResetPassword(); - } + }, [username]); if (!token) { return ( @@ -162,8 +153,14 @@ function App() { if (token && currentUser?.mustResetPassword) { return ( - - + + + + ); } diff --git a/typescript/frontend-marios2/src/content/dashboards/Information/Information.tsx b/typescript/frontend-marios2/src/content/dashboards/Information/Information.tsx index 01667ed5c..99b3144dd 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Information/Information.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Information/Information.tsx @@ -57,7 +57,7 @@ function Information(props: InformationProps) { const canEdit = currentUser.userType == UserType.admin; const isPartner = currentUser.userType == UserType.partner; - const isSodistore = formValues.product === 3 || formValues.product === 4; + const isSodistore = formValues.product === 3 || formValues.product === 4 || formValues.product === 5; const [networkProviders, setNetworkProviders] = useState([]); const [loadingProviders, setLoadingProviders] = useState(false); @@ -426,12 +426,18 @@ function Information(props: InformationProps) { label="S3 Bucket Name" name="s3bucketname" value={ - formValues.product === 0 || formValues.product == 3 + formValues.product === 0 || formValues.product === 3 ? formValues.s3BucketId + '-3e5b3069-214a-43ee-8d85-57d72000c19d' - : formValues.product == 4 + : formValues.product === 4 ? formValues.s3BucketId + '-5109c126-e141-43ab-8658-f3c44c838ae8' + : formValues.product === 5 + ? formValues.s3BucketId + + '-325c9373-9025-4a8d-bf5a-f9eedf1f155c' + : formValues.product === 1 + ? formValues.s3BucketId + + '-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e' : formValues.s3BucketId + '-e7b9a240-3c5d-4d2e-a019-6d8b1f7b73fa' } diff --git a/typescript/frontend-marios2/src/content/dashboards/Installations/index.tsx b/typescript/frontend-marios2/src/content/dashboards/Installations/index.tsx index 8db02e68a..500088bde 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Installations/index.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Installations/index.tsx @@ -458,6 +458,10 @@ function InstallationTabs(props: InstallationTabsProps) { + ) : props.product === 5 ? ( + ) : ( (false); const { sodiohomeInstallations, + sodistoreProInstallations, fetchAllInstallations, socket, openSocket, @@ -67,6 +68,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) { } = useContext(InstallationsContext); const { product, setProduct } = useContext(ProductIdContext); const baseRoute = props.product === 5 ? routes.sodistorepro_installations : routes.sodiohome_installations; + const installations = props.product === 5 ? sodistoreProInstallations : sodiohomeInstallations; useEffect(() => { let path = location.pathname.split('/'); @@ -258,11 +260,11 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) { !location.pathname.includes('folder'); // Determine if current installation is Growatt (device=3) to hide report tab - const currentInstallation = sodiohomeInstallations.find((i) => + const currentInstallation = installations.find((i) => location.pathname.includes(`/${i.id}/`) ); const isGrowatt = currentInstallation?.device === 3 - || (sodiohomeInstallations.length === 1 && sodiohomeInstallations[0].device === 3); + || (installations.length === 1 && installations[0].device === 3); const tabs = inInstallationView && currentUser.userType == UserType.admin ? [ @@ -434,7 +436,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) { } ]; - return sodiohomeInstallations.length > 1 ? ( + return installations.length > 1 ? ( <> @@ -507,7 +509,7 @@ function SodioHomeInstallationTabs(props: SodioHomeInstallationTabsProps) { - ) : sodiohomeInstallations.length === 1 ? ( + ) : installations.length === 1 ? ( <> diff --git a/typescript/frontend-marios2/src/content/dashboards/Tickets/CreateTicketModal.tsx b/typescript/frontend-marios2/src/content/dashboards/Tickets/CreateTicketModal.tsx index a6baa3296..d10927ea3 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Tickets/CreateTicketModal.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Tickets/CreateTicketModal.tsx @@ -37,7 +37,8 @@ const productOptions = [ { value: 1, label: 'Salidomo' }, { value: 2, label: 'Sodistore Home' }, { value: 3, label: 'Sodistore Max' }, - { value: 4, label: 'Sodistore Grid' } + { value: 4, label: 'Sodistore Grid' }, + { value: 5, label: 'Sodistore Pro' } ]; const deviceOptionsByProduct: Record = { diff --git a/typescript/frontend-marios2/src/content/dashboards/Tree/CustomTreeItem.tsx b/typescript/frontend-marios2/src/content/dashboards/Tree/CustomTreeItem.tsx index b125a9f40..06ba87bc0 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Tree/CustomTreeItem.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Tree/CustomTreeItem.tsx @@ -60,6 +60,8 @@ function CustomTreeItem(props: CustomTreeItemProps) { ? routes.salidomo_installations : installation.product == 2 ? routes.sodiohome_installations + : installation.product == 4 + ? routes.sodistoregrid_installations : installation.product == 5 ? routes.sodistorepro_installations : routes.sodistore_installations; @@ -71,6 +73,8 @@ function CustomTreeItem(props: CustomTreeItemProps) { ? routes.salidomo_installations : product == 2 ? routes.sodiohome_installations + : product == 4 + ? routes.sodistoregrid_installations : product == 5 ? routes.sodistorepro_installations : routes.sodistore_installations; @@ -213,6 +217,10 @@ function CustomTreeItem(props: CustomTreeItemProps) { currentLocation.pathname === routes.installations + routes.tree || currentLocation.pathname === routes.sodiohome_installations + routes.tree || + currentLocation.pathname === + routes.sodistoregrid_installations + routes.tree || + currentLocation.pathname === + routes.sodistorepro_installations + routes.tree || currentLocation.pathname.includes('folder') ? 'block' : 'none', diff --git a/typescript/frontend-marios2/src/content/dashboards/Users/userForm.tsx b/typescript/frontend-marios2/src/content/dashboards/Users/userForm.tsx index 652461f34..1d849e3f5 100644 --- a/typescript/frontend-marios2/src/content/dashboards/Users/userForm.tsx +++ b/typescript/frontend-marios2/src/content/dashboards/Users/userForm.tsx @@ -72,22 +72,24 @@ function userForm(props: userFormProps) { setLoading(true); try { - // fetch product 0 - const res0 = await axiosConfig.get( - `/GetAllInstallationsFromProduct?product=0` - ); - const installations0 = res0.data; + const [res0, res1, res2, res3, res4, res5] = await Promise.all([ + axiosConfig.get(`/GetAllInstallationsFromProduct?product=0`), + axiosConfig.get(`/GetAllInstallationsFromProduct?product=1`), + axiosConfig.get(`/GetAllInstallationsFromProduct?product=2`), + axiosConfig.get(`/GetAllInstallationsFromProduct?product=3`), + axiosConfig.get(`/GetAllInstallationsFromProduct?product=4`), + axiosConfig.get(`/GetAllInstallationsFromProduct?product=5`) + ]); - // fetch product 1 - const res1 = await axiosConfig.get( - `/GetAllInstallationsFromProduct?product=3` - ); - const installations1 = res1.data; + const combined = [ + ...res0.data, + ...res1.data, + ...res2.data, + ...res3.data, + ...res4.data, + ...res5.data + ]; - // aggregate - const combined = [...installations0, ...installations1]; - - // update setInstallations(combined); } catch (err) { if (err.response && err.response.status === 401) { diff --git a/typescript/frontend-marios2/src/contexts/InstallationsContextProvider.tsx b/typescript/frontend-marios2/src/contexts/InstallationsContextProvider.tsx index 926689b19..1efe81d81 100644 --- a/typescript/frontend-marios2/src/contexts/InstallationsContextProvider.tsx +++ b/typescript/frontend-marios2/src/contexts/InstallationsContextProvider.tsx @@ -34,6 +34,9 @@ const InstallationsContextProvider = ({ const [sodistoreGridInstallations, setSodistoreGridInstallations] = useState< I_Installation[] >([]); + const [sodistoreProInstallations, setSodistoreProInstallations] = useState< + I_Installation[] + >([]); const [foldersAndInstallations, setFoldersAndInstallations] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); @@ -105,10 +108,24 @@ const InstallationsContextProvider = ({ } ); + const updatedSodistorePro = sodistoreProInstallations.map( + (installation) => { + const update = pendingUpdates.current[installation.id]; + return update + ? { + ...installation, + status: update.status, + testingMode: update.testingMode + } + : installation; + } + ); + setSalidomoInstallations(updatedSalidomo); setSalimax_Or_Sodistore_Installations(updatedSalimax); setSodiohomeInstallations(updatedSodiohome); setSodistoreGridInstallations(updatedSodistoreGrid); + setSodistoreProInstallations(updatedSodistorePro); // Clear the pending updates after applying pendingUpdates.current = {}; @@ -116,7 +133,8 @@ const InstallationsContextProvider = ({ salidomoInstallations, salimax_or_sodistore_Installations, sodiohomeInstallations, - sodistoreGridInstallations + sodistoreGridInstallations, + sodistoreProInstallations ]); useEffect(() => { @@ -191,8 +209,10 @@ const InstallationsContextProvider = ({ `/GetAllInstallationsFromProduct?product=${product}` ); - if (product === 2 || product === 5) { + if (product === 2) { setSodiohomeInstallations(res.data); + } else if (product === 5) { + setSodistoreProInstallations(res.data); } else if (product === 1) { setSalidomoInstallations(res.data); } else if (product === 0 || product === 3) { @@ -418,6 +438,7 @@ const InstallationsContextProvider = ({ salidomoInstallations, sodiohomeInstallations, sodistoreGridInstallations, + sodistoreProInstallations, foldersAndInstallations, fetchAllInstallations, fetchAllFoldersAndInstallations, @@ -445,6 +466,7 @@ const InstallationsContextProvider = ({ salidomoInstallations, sodiohomeInstallations, sodistoreGridInstallations, + sodistoreProInstallations, foldersAndInstallations, loading, error,