-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSceneHome.tsx
288 lines (258 loc) · 9.77 KB
/
SceneHome.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
import * as React from "react";
import * as Actions from "@common/actions";
import * as Strings from "@common/strings";
import styles from "@scenes/SceneHome.module.scss";
import Header from "@components/Header";
import Layout from "@components/Layout";
import LayoutLeft from "@components/LayoutLeft";
import LayoutRight from "@components/LayoutRight";
import LineItem from "@components/LineItem";
import StatePreview from "@components/StatePreview";
import Content from "@components/Content";
import Input from "@components/Input";
import Button from "@components/Button";
import Tip from "@components/Tip";
import H1 from "@components/H1";
import H2 from "@components/H2";
import P from "@components/P";
declare const window: any;
const handleChange = (e, state, setState) => {
setState({ ...state, [e.target.name]: e.target.value });
};
function SceneHome(props) {
const [state, setState] = React.useState({ email: "", password: "" });
let maybeRenderGoogleAuth =
!props.viewer && !Strings.isEmpty(props.googleURL);
if (
props.viewer &&
!Strings.isEmpty(props.googleURL) &&
props.viewer.data &&
!props.viewer.data.google
) {
maybeRenderGoogleAuth = true;
}
return (
<section className={styles.scene}>
<Header>
<Content>
<H1>www-react-postgres 0.1</H1>
</Content>
</Header>
<Layout>
<LayoutLeft>
{props.viewer && (
<React.Fragment>
<LineItem>
<Content>
<H2>Sign out</H2>
<P>
This method will delete string that holds the JWT in the
cookie. To authenticate again you will need to sign in.
</P>
<Button
onClick={() => Actions.execute("SIGN_OUT")}
style={{ background: `var(--color-warning)` }}
>
Sign out
</Button>
</Content>
</LineItem>
<LineItem>
<Content>
<H2>Delete Account</H2>
<P>
This method will delete the user entry from the user table.
If the user is part of an organization this will delete the
user from the organization but will not delete the
organization row even if it has no members.
</P>
<Button
onClick={() => Actions.execute("VIEWER_DELETE_USER")}
style={{ background: `var(--color-failure)` }}
>
Delete {props.viewer.id}
</Button>
</Content>
</LineItem>
</React.Fragment>
)}
{!props.viewer && (
<LineItem>
<Content>
<H2>Sign in</H2>
<P>
This is a traditional username and password sign in, if an
account exists it will check if the credentials are correct,
if the account does not exist a new user entry will be added
in your Postgres database. You will need to figure out a way
to verify the e-mail address on your own.
</P>
<Input
autoComplete="off"
value={state.email}
placeholder="someone@something.com"
name="email"
onChange={(e) => handleChange(e, state, setState)}
/>
<Input
style={{ marginTop: 12, marginBottom: 24 }}
autoComplete="off"
value={state.password}
name="password"
placeholder="Enter a password"
type="password"
onChange={(e) => handleChange(e, state, setState)}
/>
<Button onClick={() => Actions.execute("SIGN_IN", state)}>
Continue
</Button>
</Content>
</LineItem>
)}
{maybeRenderGoogleAuth && (
<LineItem>
<Content>
{props.viewer ? (
<H2>Continue with Google</H2>
) : (
<H2>Sign in with Google</H2>
)}
<P>
This is a traditional Google sign in flow. The necessary
client ID and client secret are provided by Google. Unlike the
local authentication strategy with a username and password, a
user using this method will have a verified e-mail.
</P>
{props.viewer && (
<P>
If a user continues with a Google account that does not
match the local authentication e-mail, it will sign that
user into that account instead.
</P>
)}
<Button href={props.googleURL}>Continue to Google</Button>
</Content>
</LineItem>
)}
{props.state.isMetamaskEnabled && !window.ethereum.selectedAddress && (
<LineItem>
<Content>
<H2>Connect Metamask to {props.host}</H2>
<P>
The user has Metamask installed in their browser. A user can
now click the button below to connect their Ethereum address
to {props.host}. This action will also create an Ethereum
address entry in the Postgres table.
</P>
<Button
onClick={() =>
Actions.execute("VIEWER_CONNECT_METAMASK", state)
}
>
Connect Metamask
</Button>
</Content>
</LineItem>
)}
{props.state.isMetamaskEnabled && window.ethereum.selectedAddress && (
<LineItem>
<Content>
<H2>
Metamask is connected and an Ethereum address is selected.
</H2>
<P>
As the developer you could write some code that associates the
Ethereum address with the authenticated user. However it is
common advice to wait for an actual need.
</P>
<P>From this point on you can build your DAPP or DAO.</P>
</Content>
</LineItem>
)}
{props.state.isPhantomEnabled && !props.state.solana && (
<LineItem>
<Content>
<H2>Connect Phantom to {props.host}</H2>
<P>
The user has Phantom installed in their browser. A user can
now click the button below to connect their Solana address to{" "}
{props.host}. This action will also create an Solana address
entry in the Postgres table.
</P>
<Button
onClick={() =>
Actions.execute("VIEWER_CONNECT_PHANTOM", state)
}
>
Connect Phantom
</Button>
</Content>
</LineItem>
)}
{props.state.isPhantomEnabled && props.state.solana && (
<LineItem>
<Content>
<H2>
Phantom is connected and the Solana address is selected.
</H2>
<P>
As the developer you could write some code that associates the
Solana address with the authenticated user. However it is
common advice to wait for an actual need.
</P>
</Content>
</LineItem>
)}
{!props.state.isMetamaskEnabled && (
<LineItem>
<Content>
<H2>Install Metamask</H2>
<Button href="https://metamask.io/">Visit metamask.io</Button>
</Content>
</LineItem>
)}
{!props.state.isPhantomEnabled && (
<LineItem>
<Content>
<H2>Install Phantom</H2>
<Button href="https://phantom.app/">Visit phantom.app</Button>
</Content>
</LineItem>
)}
</LayoutLeft>
<LayoutRight>
{props.state.isMetamaskEnabled && window.ethereum.selectedAddress ? (
<Tip>Metamask ➝ {window.ethereum.selectedAddress}</Tip>
) : null}
{props.state.isMetamaskEnabled && props.state.ethereum && (
<Tip>
Ethereum address ➝ {props.state.ethereum.address} has an entry in
this server's Postgres database.
</Tip>
)}
{props.state.isPhantomEnabled && props.state.solana && (
<Tip>
Solana address (Phantom public key) ➝ {props.state.solana.address}{" "}
has an entry in this server's Postgres database.
</Tip>
)}
{props.viewer && props.viewer.data.verified && (
<Tip>{props.viewer.email} is verified.</Tip>
)}
{props.viewer && props.viewer.data.google && (
<Tip style={{ background: `var(--color-primary)` }}>
{props.viewer.email} has connected Google to their account.
</Tip>
)}
{props.viewer && !props.viewer.data.verified && (
<Tip style={{ background: `var(--color-warning)` }}>
{props.viewer.email} is not verified.
</Tip>
)}
<StatePreview state={props} />
</LayoutRight>
</Layout>
</section>
);
}
export default SceneHome;