Skip to content

Commit 2860751

Browse files
committed
some component reorg, usable header links
1 parent 5c275b6 commit 2860751

14 files changed

+195
-26
lines changed

src/App.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { Connection } from "./features/connection/Connection";
1010
import { Configuration } from "./features/connection/Configuration";
1111
import { Messages } from "./features/messages/Messages";
1212
import { ExecuteOptions } from "./features/console/ExecuteOptions";
13+
import { Header } from "./components/Header";
14+
import { Donate } from "./features/accounts/Donate";
1315

1416
setBasePath(
1517
"https://cdn.jsdelivr.net/npm/@shoelace-style/[email protected]/dist/"
@@ -18,10 +20,7 @@ function App() {
1820
return (
1921
<div className="main">
2022
<aside className="sidebar">
21-
<h3 className="header">cøsmwasm devtøøls</h3>
22-
<div className="subhead">
23-
<a href="https://github.com">github</a> | <a href="#">donate</a>
24-
</div>
23+
<Header />
2524
<SlDivider />
2625
<div className="sidebar-main">
2726
<AccountList />
@@ -38,6 +37,7 @@ function App() {
3837
<Configuration />
3938
<Messages />
4039
<ExecuteOptions />
40+
<Donate />
4141
</div>
4242
);
4343
}

src/components/Header.module.css

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.header {
2+
}
3+
4+
.name,
5+
.subhead {
6+
font-family: "Courier New", Courier, monospace;
7+
text-align: center;
8+
font-weight: normal;
9+
margin-bottom: 0;
10+
}
11+
12+
.link {
13+
color: slateblue;
14+
text-decoration: none;
15+
border: none;
16+
background-color: white;
17+
font-family: "Courier New", Courier, monospace;
18+
font-size: 0.9em;
19+
cursor: pointer;
20+
}
21+
22+
.link:hover {
23+
text-decoration: underline;
24+
}

src/components/Header.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { SlDivider } from "@shoelace-style/shoelace/dist/react";
2+
import React from "react";
3+
import { useAppDispatch } from "../app/hooks";
4+
import { AccountList } from "../features/accounts/AccountList";
5+
import { setDonationOpen } from "../features/accounts/accountsSlice";
6+
import { ContractList } from "../features/accounts/ContractList";
7+
import { Connection } from "../features/connection/Connection";
8+
import styles from "./Header.module.css";
9+
10+
const GITHUB_URL = "https://github.com/aswever/cosmwasm-devtools";
11+
12+
export const Header = () => {
13+
const dispatch = useAppDispatch();
14+
return (
15+
<div className={styles.header}>
16+
<h3 className={styles.name}>cøsmwasm devtøøls</h3>
17+
<div className={styles.subhead}>
18+
<a
19+
className={styles.link}
20+
href={GITHUB_URL}
21+
target="_blank"
22+
rel="noreferrer"
23+
>
24+
github
25+
</a>{" "}
26+
|{" "}
27+
<button
28+
className={styles.link}
29+
onClick={() => dispatch(setDonationOpen(true))}
30+
>
31+
donate
32+
</button>
33+
</div>
34+
</div>
35+
);
36+
};

src/components/AccountCard.tsx src/features/accounts/AccountCard.tsx

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { SlCard, SlIcon, SlTooltip } from "@shoelace-style/shoelace/dist/react";
2-
import React, { FC, useEffect, useState } from "react";
3-
import { useAppDispatch, useAppSelector } from "../app/hooks";
2+
import React, { FC, useCallback, useEffect, useState } from "react";
3+
import { useAppDispatch, useAppSelector } from "../../app/hooks";
44
import {
55
Account,
66
AccountType,
77
balanceString,
88
checkBalance,
99
hitFaucet,
1010
setSendCoinsOpen,
11-
} from "../features/accounts/accountsSlice";
11+
} from "./accountsSlice";
1212
import styles from "./AccountCard.module.css";
1313

1414
interface AccountCardProps {
@@ -61,17 +61,25 @@ export const AccountCard: FC<AccountCardProps> = ({
6161
}
6262
}, [account?.address, dispatch, config]);
6363

64-
function copyAddress() {
64+
const copyAddress = useCallback(() => {
6565
if (account?.address) navigator.clipboard.writeText(account.address);
6666
setCopyTooltip("Copied!");
6767
setTimeout(() => setCopyTooltip("Copy to clipboard"), 2000);
68-
}
68+
}, [account?.address]);
69+
70+
const clickX = useCallback(
71+
(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
72+
e.preventDefault();
73+
onClickX();
74+
},
75+
[onClickX]
76+
);
6977

7078
return (
7179
<>
7280
<SlCard
7381
className={classes.join(" ")}
74-
onClick={disabled ? undefined : onClick}
82+
onClick={disabled || selected ? undefined : onClick}
7583
>
7684
<div className={styles.main}>
7785
<div className={styles.left}>
@@ -108,7 +116,7 @@ export const AccountCard: FC<AccountCardProps> = ({
108116
: "Remove account"
109117
}
110118
>
111-
<SlIcon name="x-lg" className={styles.close} onClick={onClickX} />
119+
<SlIcon name="x-lg" className={styles.close} onClick={clickX} />
112120
</SlTooltip>
113121
)}
114122
</div>

src/features/accounts/AccountList.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import {
99
import styles from "./AccountList.module.css";
1010
import { AddAccount } from "./AddAccount";
1111
import { KeplrAccount } from "./KeplrAccount";
12-
import { AccountCard } from "../../components/AccountCard";
13-
import { SendCoins } from "../../components/SendCoins";
12+
import { AccountCard } from "./AccountCard";
13+
import { SendCoins } from "./SendCoins";
1414

1515
interface AccountProps {
1616
account: Account;

src/features/accounts/ContractList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from "./accountsSlice";
99
import styles from "./ContractList.module.css";
1010
import { AddContract } from "./AddContract";
11-
import { AccountCard } from "../../components/AccountCard";
11+
import { AccountCard } from "./AccountCard";
1212
import { Contract } from "../accounts/accountsSlice";
1313

1414
interface ContractProps {
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.form {
2+
display: flex;
3+
flex-direction: column;
4+
justify-content: space-between;
5+
height: 8rem;
6+
margin-top: -1rem;
7+
margin-bottom: 0.5rem;
8+
}

src/features/accounts/Donate.tsx

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import {
2+
SlButton,
3+
SlDialog,
4+
SlInput,
5+
} from "@shoelace-style/shoelace/dist/react";
6+
import type SlInputElement from "@shoelace-style/shoelace/dist/components/input/input";
7+
import React, { FC, useState } from "react";
8+
import { useAppDispatch, useAppSelector } from "../../app/hooks";
9+
import styles from "./Donate.module.css";
10+
import { sendCoins, setDonationOpen } from "./accountsSlice";
11+
import { fromMicroDenom } from "../../util/coins";
12+
import presets from "../connection/presets.json";
13+
14+
const DONATIONS_ADDRESS = "juno1py5lflcm30rgk56jc0ynyu4afn9fpxyk88wyvv";
15+
16+
export const Donate: FC = () => {
17+
const dispatch = useAppDispatch();
18+
const open = useAppSelector((state) => state.accounts.donationOpen);
19+
const sender = useAppSelector((state) => state.accounts.currentAccount!);
20+
const junoConfig = presets["juno-mainnet"];
21+
const [amount, setAmount] = useState("");
22+
const [memo, setMemo] = useState("");
23+
24+
function dispatchSend() {
25+
dispatch(
26+
sendCoins({
27+
sender,
28+
recipient: DONATIONS_ADDRESS,
29+
amount,
30+
memo,
31+
customConfig: junoConfig,
32+
})
33+
);
34+
dispatch(setDonationOpen(false));
35+
setAmount("");
36+
setMemo("");
37+
}
38+
39+
return (
40+
<SlDialog
41+
label="Thank you!"
42+
open={open}
43+
onSlRequestClose={() => dispatch(setDonationOpen(false))}
44+
className={styles.dialog}
45+
>
46+
<div className={styles.form}>
47+
<SlInput
48+
placeholder="Amount"
49+
value={amount}
50+
className={styles.amount}
51+
onSlChange={(e) =>
52+
setAmount((e.target as SlInputElement).value.trim())
53+
}
54+
>
55+
<div slot="suffix">{fromMicroDenom(junoConfig["microDenom"])}</div>
56+
</SlInput>
57+
<SlInput
58+
placeholder="Memo"
59+
value={memo}
60+
className={styles.memo}
61+
onSlChange={(e) => setMemo((e.target as SlInputElement).value.trim())}
62+
/>
63+
<SlButton variant="neutral" onClick={() => dispatchSend()}>
64+
Send
65+
</SlButton>
66+
</div>
67+
</SlDialog>
68+
);
69+
};

src/features/accounts/KeplrAccount.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SlIcon } from "@shoelace-style/shoelace/dist/react";
22
import React, { FC, useCallback } from "react";
33
import { useAppDispatch, useAppSelector } from "../../app/hooks";
4-
import { AccountCard } from "../../components/AccountCard";
4+
import { AccountCard } from "./AccountCard";
55
import { selectAccount, setKeplrAccount } from "./accountsSlice";
66
import styles from "./KeplrAccount.module.css";
77
import { useKeplr } from "./useKeplr";
@@ -11,7 +11,9 @@ export const KeplrAccount: FC = () => {
1111
const { connect } = useKeplr();
1212
const account = useAppSelector((state) => state.accounts.keplrAccount);
1313
const selected = useAppSelector(
14-
(state) => state.accounts.currentAccount === account?.address
14+
(state) =>
15+
state.accounts.currentAccount !== undefined &&
16+
state.accounts.currentAccount === account?.address
1517
);
1618

1719
const reconnect = useCallback(() => connect(), [connect]);
File renamed without changes.

src/components/SendCoins.tsx src/features/accounts/SendCoins.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import {
1010
import type SlSelectElement from "@shoelace-style/shoelace/dist/components/select/select";
1111
import type SlInputElement from "@shoelace-style/shoelace/dist/components/input/input";
1212
import React, { FC, useState } from "react";
13-
import { useAppDispatch, useAppSelector } from "../app/hooks";
13+
import { useAppDispatch, useAppSelector } from "../../app/hooks";
1414
import styles from "./SendCoins.module.css";
1515
import {
1616
AccountType,
1717
contractAccounts,
1818
sendCoins,
1919
setSendCoinsOpen,
20-
} from "../features/accounts/accountsSlice";
21-
import { fromMicroDenom } from "../util/coins";
20+
} from "./accountsSlice";
21+
import { fromMicroDenom } from "../../util/coins";
2222

2323
export const SendCoins: FC = () => {
2424
const dispatch = useAppDispatch();

src/features/accounts/accountsSlice.ts

+29-6
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,13 @@ export interface AccountsState {
4343
currentAccount?: string;
4444
currentContract?: string;
4545
sendCoinsOpen: boolean;
46+
donationOpen: boolean;
4647
}
4748

4849
const initialState: AccountsState = {
4950
accountList: {},
5051
sendCoinsOpen: false,
52+
donationOpen: false,
5153
};
5254

5355
export const importAccount = createAsyncThunk(
@@ -204,29 +206,35 @@ export const sendCoins = createAsyncThunk(
204206
recipient,
205207
amount,
206208
memo,
209+
customConfig,
207210
}: {
208211
sender: string;
209212
recipient: string;
210213
amount: string;
211214
memo?: string;
215+
customConfig?: { [key: string]: string };
212216
},
213217
{ getState, dispatch }
214218
): Promise<void> => {
215219
try {
216220
const state = getState() as RootState;
221+
const config = customConfig ?? state.connection.config;
217222
const senderAccount = state.accounts.accountList[sender];
223+
224+
console.log(sender, senderAccount);
225+
if (!sender) {
226+
throw new Error("No account selected");
227+
}
228+
218229
const client = await connectionManager.getSigningClient(
219230
senderAccount,
220-
state.connection.config
231+
config
221232
);
222233

223234
const coinsAmount = [
224235
{
225-
amount: toMicroAmount(
226-
amount,
227-
state.connection.config["coinDecimals"]
228-
),
229-
denom: state.connection.config["microDenom"],
236+
amount: toMicroAmount(amount, config["coinDecimals"]),
237+
denom: config["microDenom"],
230238
},
231239
];
232240

@@ -281,6 +289,17 @@ export const accountsSlice = createSlice({
281289
if (account) {
282290
state.accountList[account.address] = account;
283291
} else {
292+
console.log(
293+
state.currentAccount,
294+
state.currentAccount &&
295+
state.accountList[state.currentAccount]?.type === AccountType.Keplr
296+
);
297+
if (
298+
state.currentAccount &&
299+
state.accountList[state.currentAccount]?.type === AccountType.Keplr
300+
) {
301+
state.currentAccount = undefined;
302+
}
284303
delete state.accountList[state.keplrAccount!.address];
285304
}
286305

@@ -299,6 +318,9 @@ export const accountsSlice = createSlice({
299318
setSendCoinsOpen: (state, action: PayloadAction<boolean>) => {
300319
state.sendCoinsOpen = action.payload;
301320
},
321+
setDonationOpen: (state, action: PayloadAction<boolean>) => {
322+
state.donationOpen = action.payload;
323+
},
302324
},
303325
extraReducers: (builder) => {
304326
builder
@@ -350,6 +372,7 @@ export const {
350372
setKeplrAccount,
351373
setAccountBalance,
352374
setSendCoinsOpen,
375+
setDonationOpen,
353376
} = accountsSlice.actions;
354377

355378
export const selectedAccount = (state: RootState) =>

src/features/connection/connectionSlice.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
2-
import { config } from "process";
32
import { RootState } from "../../app/store";
43
import { pushMessage } from "../messages/messagesSlice";
54
import connectionManager from "./connectionManager";

0 commit comments

Comments
 (0)