Skip to content

Commit

Permalink
Merge pull request #49 from input-output-hk/DAC-290
Browse files Browse the repository at this point in the history
DAC-290 [FE]Result of the broadcasting
  • Loading branch information
amnambiar authored Mar 17, 2023
2 parents 099a2de + 0208d21 commit 2bb3868
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 60 deletions.
3 changes: 2 additions & 1 deletion react-web/.env.production
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
REACT_APP_BASE_URL="https://testing.dapps.iog.io/"
REACT_APP_BASE_URL="https://testing.dapps.iog.io/"
REACT_APP_WALLET_NETWORK="1"
16 changes: 16 additions & 0 deletions react-web/src/app/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,20 @@ header button {
section > svg.spinner {
top: 100px;
left: 50%;
}


#contentWrapper {
margin: 0 auto;
padding: 40px;
color: #2d333a;
@media (max-width: 768px) {
& {
padding: 0;
}
}
}

#globalBanners {
padding: 10px 40px;
}
27 changes: 26 additions & 1 deletion react-web/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React, { lazy, Suspense } from "react";
import React, { lazy, memo, Suspense } from "react";
import { Routes, Route, Outlet } from "react-router-dom";
import { BASE_URL } from "constants/route";
import Alert from '@mui/material/Alert';

import "./App.scss";
import Header from "components/Header/Header";
import PrivateRoutes from "components/PrivateRoutes/PrivateRoutes";
import NotFound from "components/NotFound/NotFound";
import Loader from "components/Loader/Loader";
import { useAppSelector } from "store/store";

const Certification = lazy(() => import("../pages/certification/Certification"));
const MaintenancePage = lazy(() => import("../pages/maintenance/Maintenance"));
Expand All @@ -19,9 +21,32 @@ const Pricing = lazy(() => import("../pages/pricing/Pricing"));


const PageLayout = () => {
const { network } = useAppSelector((state) => state.auth);

// const networkNames:{[x:string]:string} = {
// '0': 'Testnet',
// '1': 'Mainnet'
// }

const Banner = memo(() => {
const networkEnvVar: any = process.env.REACT_APP_WALLET_NETWORK

return (<>
{network !== null && network !== 1 ?
// always show Info if not in Mainnet
<Alert severity="info" style={{marginBottom: '10px'}}>Your connected wallet is not in Mainnet.</Alert> : null}
{/* if not in Mainnet and app-wallet not Mainnet (i.e. in Testnet), show Warning to connect to Preprod. */}
{network !== null && network !== 1 && networkEnvVar !== '1' ?
<Alert severity="warning">Being in a test network, please make sure you are connected to wallet in <strong>Preprod</strong> to avail services without any issues.</Alert> : null}
</>)
})

return (
<>
<Header />
<section id="globalBanners">
<Banner />
</section>
{/* Load page content here */}
<section data-testid="contentWrapper" id="contentWrapper">
<Suspense fallback={<Loader />}>
Expand Down
3 changes: 3 additions & 0 deletions react-web/src/components/ConnectWallet/ConnectWallet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,7 @@
span {
padding: 2px 16px;
}
}
.error {
color: red;
}
38 changes: 29 additions & 9 deletions react-web/src/components/ConnectWallet/ConnectWallet.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useEffect, useState, useCallback } from "react";
import { Address } from "@emurgo/cardano-serialization-lib-browser";
import { useAppDispatch } from "store/store";
import { getProfileDetails } from "store/slices/auth.slice";
import { getProfileDetails, setNetwork } from "store/slices/auth.slice";

import Modal from "components/Modal/Modal";
import Button from "components/Button/Button";
import Loader from "components/Loader/Loader";
import Toast from "components/Toast/Toast";

import './ConnectWallet.scss';

Expand All @@ -24,6 +25,7 @@ const ConnectWallet = () => {
const [walletName, setWalletName] = useState("")
const [address, setAddress] = useState("")
const [isOpen, setIsOpen] = useState(false)
const [errorToast, setErrorToast] = useState<{display: boolean; statusText?: string; message?: string;}>({display: false});
const [walletLoading, setWalletLoading] = useState(false)

const openConnectWalletModal = useCallback(() => setIsOpen(true),[])
Expand All @@ -34,17 +36,27 @@ const ConnectWallet = () => {
try {
setWalletLoading(true)
const enabledWallet = await CardanoNS[walletName].enable();
setWallet(enabledWallet)
setWalletName(walletName)
if (enabledWallet) {
const response = await enabledWallet.getChangeAddress()
setAddress(Address.from_bytes(Buffer.from(response, "hex")).to_bech32())
}
enabledWallet.getNetworkId().then(async (data: number) => {
dispatch(setNetwork(data))
setWallet(enabledWallet)
setWalletName(walletName)
if (enabledWallet) {
const response = await enabledWallet.getChangeAddress()
setAddress(Address.from_bytes(Buffer.from(response, "hex")).to_bech32())
}
})
} catch (e) { handleError(e); }
}

const handleError = (err: any) => {
console.log(err)
const handleError = (error: any) => {
if (error.info) {
setErrorToast({display: true, message: error.info})
} else if (error.response) {
setErrorToast({display: true, statusText: error.response.statusText, message: error.response.data || undefined})
} else {
setErrorToast({display: true})
}
setTimeout(() => { setErrorToast({display: false}) }, 3000)
}

useEffect(() => {
Expand Down Expand Up @@ -88,8 +100,16 @@ const ConnectWallet = () => {
})
}
{ walletLoading ? <Loader /> : null}
{
(errorToast && errorToast.display) ? (<span className="error">{errorToast.message}</span>): null
}
</div>
</Modal>
{/* {(errorToast && errorToast.display) ? (
((errorToast.message && errorToast.statusText) ?
<Toast message={errorToast.message} title={errorToast.statusText}/> :
<Toast />))
: null} */}
</>
)
}
Expand Down
41 changes: 34 additions & 7 deletions react-web/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ import React, { useEffect, useState, memo, useCallback } from "react";
import { useNavigate, Link } from "react-router-dom";
import { Address } from "@emurgo/cardano-serialization-lib-browser";
import { useAppDispatch, useAppSelector } from "store/store";
import { logout, getProfileDetails } from "store/slices/auth.slice";
import { logout, getProfileDetails, setNetwork } from "store/slices/auth.slice";
import "./Header.scss";

import AvatarDropDown from "components/AvatarDropdown/AvatarDropdown";
import ConnectWallet from "components/ConnectWallet/ConnectWallet";
import { useDelayedApi } from "hooks/useDelayedApi";

const Header = () => {
const { isLoggedIn, address, wallet } = useAppSelector((state) => state.auth);
const { isLoggedIn, address, wallet, network } = useAppSelector((state) => state.auth);
const dispatch = useAppDispatch();
const [isActive, setIsActive] = useState(false);
const [pollForAddress, setPollForAddress] = useState(false);
const [pollForNetwork, setPollForNetwork] = useState(false);
const navigate = useNavigate();

useEffect(() => {
Expand All @@ -25,6 +26,9 @@ const Header = () => {
try {
const enabledWallet = await window.cardano[walletNameCache].enable()
dispatch(getProfileDetails({"address": addressCache, "wallet": enabledWallet, "walletName": walletNameCache}))
enabledWallet.getNetworkId().then(async (data: number) => { console.log('new network -', data)
dispatch(setNetwork(data))
})
} catch(e) {
console.log(e)
}
Expand All @@ -42,7 +46,15 @@ const Header = () => {

useEffect(() => {
setPollForAddress(wallet && address && isLoggedIn);
}, [wallet, address, isLoggedIn]);
setPollForNetwork(wallet && address && isLoggedIn && network !== null)
}, [wallet, address, isLoggedIn, network]);

const forceUserLogout = () => {
// account/network has been changed. Force logout the user
setPollForAddress(false);
setPollForNetwork(false)
dispatch(logout());
}

useDelayedApi(
async () => {
Expand All @@ -53,17 +65,32 @@ const Header = () => {
newAddress = Address.from_bytes(Buffer.from(response, "hex")).to_bech32()
}
if (newAddress && address !== newAddress) {
// account has been changed. Force logout the user
dispatch(logout());
setPollForAddress(false);
forceUserLogout()
} else {
setPollForAddress(true);
}
},
3 * 1000,
1 * 1000,
pollForAddress
);

useDelayedApi(
async() => {
setPollForNetwork(false)
wallet.getNetworkId().then((id: number) => {
// Preview/Preprod/Testnet are all 0. Switching among them cannot be distinguished.
// But, switching to-and-fro Mainnet is triggered
if (id !== network) {
forceUserLogout();
} else {
setPollForNetwork(true)
}
})
},
1 * 1000,
pollForNetwork
)

const hasCachedAddress = () => {
return (!localStorage.getItem('address')?.length || !localStorage.getItem('walletName')?.length)
}
Expand Down
11 changes: 0 additions & 11 deletions react-web/src/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,6 @@ body {
// position: relative;
}

#contentWrapper {
margin: 0 auto;
padding: 40px;
color: #2d333a;
@media (max-width: 768px) {
& {
padding: 0;
}
}
}

input {
font-family: monospace, -apple-system, BlinkMacSystemFont, "Segoe UI",
"Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
Expand Down
15 changes: 9 additions & 6 deletions react-web/src/pages/certification/Certification.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,20 @@
}

#resultContainer {

button.back-btn {
background: transparent;
cursor: pointer;
border: none;
img {
width: "30px";
padding: "10px";
}
}
header {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 15px;
.back-btn {
background: transparent;
cursor: pointer;
border: none;
}
&>div {
display: flex;
flex-wrap: wrap;
Expand Down
31 changes: 14 additions & 17 deletions react-web/src/pages/certification/Certification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,24 +292,21 @@ const Certification = () => {
{formSubmitted && (
<>
<div id="resultContainer">
{runStatus !== "finished" ? (
<button
className="back-btn"
onClick={(e) => {
resetStates();
}}
>
{" "}
<img
src="images/back.png"
alt="back_btn"
/>
</button>
) : null}
<header>
{runStatus === "finished" ? (
<button
className="back-btn"
onClick={(e) => {
resetStates();
}}
>
{" "}
<img
src="images/back.png"
alt="back_btn"
style={{ width: "30px", padding: "10px" }}
/>
</button>
) : (
""
)}
<h2
id="breadcrumb"
style={{alignSelf:"center"}}
Expand Down
22 changes: 14 additions & 8 deletions react-web/src/store/slices/auth.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface AuthState {
wallet: any;
userDetails: IUserProfile;
loading: boolean;
network: number | null;
}

// Define the initial state using that type
Expand All @@ -17,19 +18,20 @@ const initialState: AuthState = {
address: '',
wallet: null,
userDetails: {dapp: null},
loading: false
loading: false,
network: null
};

const clearLSCache = () => {
localStorage.removeItem('address')
localStorage.removeItem('walletName')
}

export const getProfileDetails: any = createAsyncThunk("getProfileDetails", async (data: any, { }) => {
localStorage.setItem('address', data.address)
const response = await fetchData.get("/profile/current", data)
// FOR MOCK - const response = await fetchData.get(data.url || 'static/data/current-profile.json', data)
return response.data
export const getProfileDetails: any = createAsyncThunk("getProfileDetails", async (data: any, { rejectWithValue }) => {
localStorage.setItem('address', data.address)
const response = await fetchData.get("/profile/current", data)
// FOR MOCK - const response = await fetchData.get(data.url || 'static/data/current-profile.json', data)
return response.data
})

export const authSlice = createSlice({
Expand All @@ -41,9 +43,13 @@ export const authSlice = createSlice({
clearLSCache();
},
logout: (state) => {
clearLSCache()
clearLSCache();
state.loading = false;
return initialState
},
setNetwork: (state, actions) => {
state.network = actions.payload
}
},
extraReducers: (builder) => {
builder.addCase(getProfileDetails.pending, (state) => {state.loading = true;})
Expand All @@ -70,6 +76,6 @@ export const authSlice = createSlice({
});


export const { logout, clearCache } = authSlice.actions;
export const { logout, clearCache, setNetwork } = authSlice.actions;

export default authSlice.reducer;

0 comments on commit 2bb3868

Please sign in to comment.