@social-mail/social-mail-client 1.2.205 → 1.2.207
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/AdminAppIndex.pack.js +380 -146
- package/dist/admin/AdminAppIndex.pack.js.map +1 -1
- package/dist/admin/AdminAppIndex.pack.min.js +37 -9
- package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
- package/dist/common/pages/user/login/LoginPage.d.ts +0 -1
- package/dist/common/pages/user/login/LoginPage.d.ts.map +1 -1
- package/dist/common/pages/user/login/LoginPage.js +13 -13
- package/dist/common/pages/user/login/LoginPage.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web/AppIndex.pack.js +380 -146
- package/dist/web/AppIndex.pack.js.map +1 -1
- package/dist/web/AppIndex.pack.min.js +37 -9
- package/dist/web/AppIndex.pack.min.js.map +1 -1
- package/dist/web/commands/AppCommands.d.ts +1 -0
- package/dist/web/commands/AppCommands.d.ts.map +1 -1
- package/dist/web/commands/AppCommands.js +4 -0
- package/dist/web/commands/AppCommands.js.map +1 -1
- package/dist/web/page/users/SignupPage.d.ts +25 -0
- package/dist/web/page/users/SignupPage.d.ts.map +1 -0
- package/dist/web/page/users/SignupPage.js +227 -0
- package/dist/web/page/users/SignupPage.js.map +1 -0
- package/dist/web/page/users/SignupPage.pack.js +17044 -0
- package/dist/web/page/users/SignupPage.pack.js.map +1 -0
- package/dist/web/page/users/SignupPage.pack.min.js +818 -0
- package/dist/web/page/users/SignupPage.pack.min.js.map +1 -0
- package/package.json +1 -1
- package/src/common/pages/user/login/LoginPage.tsx +9 -13
- package/src/web/commands/AppCommands.ts +5 -0
- package/src/web/page/users/SignupPage.tsx +259 -0
package/package.json
CHANGED
|
@@ -19,16 +19,9 @@ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
|
|
|
19
19
|
import ForgotPassword from "../forgot/ForgotPassword";
|
|
20
20
|
import PopupService from "@web-atoms/core/dist/web/services/PopupService";
|
|
21
21
|
import AppForm from "../../../form/AppForm";
|
|
22
|
+
import AppCommands from "../../../../web/commands/AppCommands";
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
label: "Authenticator (TOTP)",
|
|
25
|
-
value: "totp"
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
label: "One Time Password",
|
|
29
|
-
value: "one-time"
|
|
30
|
-
}
|
|
31
|
-
];
|
|
24
|
+
const isSocialMail = /socialmail\.(me|in)/i.test(location.href) || /\d+.\d+.\d+.\d+/i.test(location.href);
|
|
32
25
|
|
|
33
26
|
export default class LoginPage extends ContentPage {
|
|
34
27
|
|
|
@@ -39,8 +32,6 @@ export default class LoginPage extends ContentPage {
|
|
|
39
32
|
|
|
40
33
|
private password?: string = "";
|
|
41
34
|
|
|
42
|
-
private authType = "totp";
|
|
43
|
-
|
|
44
35
|
async init() {
|
|
45
36
|
|
|
46
37
|
this.footerRenderer = () => <div data-layout="row">
|
|
@@ -81,11 +72,16 @@ export default class LoginPage extends ContentPage {
|
|
|
81
72
|
/>
|
|
82
73
|
</div>
|
|
83
74
|
|
|
84
|
-
{ <div data-layout="row">
|
|
75
|
+
{isSocialMail && <div data-layout="row">
|
|
85
76
|
<span
|
|
86
77
|
data-click-event="forgot-password"
|
|
87
78
|
data-layout="link">Forgot password?</span>
|
|
88
79
|
</div>}
|
|
80
|
+
{isSocialMail && <div data-layout="row">
|
|
81
|
+
<a
|
|
82
|
+
data-click-event="route"
|
|
83
|
+
href={AppCommands.signup.displayRoute({})}>Sign Up</a>
|
|
84
|
+
</div>}
|
|
89
85
|
</AppForm>
|
|
90
86
|
</div>
|
|
91
87
|
</div>);
|
|
@@ -203,7 +199,7 @@ export default class LoginPage extends ContentPage {
|
|
|
203
199
|
|
|
204
200
|
@Action({ onEvent: "forgot-password"})
|
|
205
201
|
async forgotPassword() {
|
|
206
|
-
if (
|
|
202
|
+
if (isSocialMail) {
|
|
207
203
|
PageNavigator.openPage(ForgotPassword);
|
|
208
204
|
return;
|
|
209
205
|
}
|
|
@@ -54,6 +54,11 @@ export default class AppCommands extends CommonCommands {
|
|
|
54
54
|
pushPage: () => import("../page/files/preview/media/PreviewMedia")
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
+
static signup = Command.create({
|
|
58
|
+
route: "/social-mail/users/signup",
|
|
59
|
+
openPage: () => import("../page/users/SignupPage")
|
|
60
|
+
});
|
|
61
|
+
|
|
57
62
|
static getPreviewCommand(p: IAppFile) {
|
|
58
63
|
if (FileTypes.isDocument(p)) {
|
|
59
64
|
return this.previewHtml;
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import Bind from "@web-atoms/core/dist/core/Bind";
|
|
2
|
+
import XNode from "@web-atoms/core/dist/core/XNode";
|
|
3
|
+
import Form from "@web-atoms/web-controls/dist/basic/Form";
|
|
4
|
+
import FormField from "@web-atoms/web-controls/dist/basic/FormField";
|
|
5
|
+
import MaskedInput from "@web-atoms/web-controls/dist/basic/MaskedInput";
|
|
6
|
+
import FetchBuilder from "@web-atoms/core/dist/services/FetchBuilder";
|
|
7
|
+
import Action from "@web-atoms/core/dist/view-model/Action";
|
|
8
|
+
import styled from "@web-atoms/core/dist/style/styled";
|
|
9
|
+
import Pack from "@web-atoms/core/dist/Pack";
|
|
10
|
+
import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
|
|
11
|
+
import { CountrySelect, formatForCountry, isdForCountry } from "../../../common/controls/countries/CountrySelect";
|
|
12
|
+
|
|
13
|
+
const css = styled.css `
|
|
14
|
+
& [data-page-element=content] {
|
|
15
|
+
& > * {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
justify-items: center;
|
|
20
|
+
& > * {
|
|
21
|
+
padding: 10px;
|
|
22
|
+
border-radius: 10px;
|
|
23
|
+
border: solid 1px gray;
|
|
24
|
+
& input {
|
|
25
|
+
background: transparent;
|
|
26
|
+
border: none;
|
|
27
|
+
outline: none;
|
|
28
|
+
border-bottom: solid 1px gray;
|
|
29
|
+
&:focus {
|
|
30
|
+
border-bottom: solid 1px purple;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
& [data-suggestion-popup=suggestion-popup] {
|
|
34
|
+
& input {
|
|
35
|
+
color: black;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`.installLocal();
|
|
42
|
+
|
|
43
|
+
interface IVerification {
|
|
44
|
+
id?: string;
|
|
45
|
+
code?: string;
|
|
46
|
+
verified?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Pack
|
|
50
|
+
export default class SignupPage extends ContentPage {
|
|
51
|
+
|
|
52
|
+
termsAgreed = false;
|
|
53
|
+
|
|
54
|
+
model: {
|
|
55
|
+
username: string;
|
|
56
|
+
password: string;
|
|
57
|
+
passwordAgain: string;
|
|
58
|
+
phoneNumber: string;
|
|
59
|
+
country: string;
|
|
60
|
+
phoneNumberText: string;
|
|
61
|
+
name: string;
|
|
62
|
+
captcha: IVerification;
|
|
63
|
+
phone: IVerification;
|
|
64
|
+
} = {
|
|
65
|
+
name: "",
|
|
66
|
+
username: "",
|
|
67
|
+
password: "",
|
|
68
|
+
passwordAgain: "",
|
|
69
|
+
phoneNumber: "",
|
|
70
|
+
country: "US",
|
|
71
|
+
phoneNumberText: "",
|
|
72
|
+
captcha: {
|
|
73
|
+
code: ""
|
|
74
|
+
},
|
|
75
|
+
phone: {
|
|
76
|
+
code: ""
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
async init() {
|
|
81
|
+
|
|
82
|
+
this.hideToolbar = true;
|
|
83
|
+
|
|
84
|
+
this.element.className = css;
|
|
85
|
+
|
|
86
|
+
this.title = "Social Mail Signup";
|
|
87
|
+
|
|
88
|
+
const { id } = await FetchBuilder.put("/api/users/captcha").responseAsJson<{ id }>();
|
|
89
|
+
|
|
90
|
+
this.model.captcha.id = id;
|
|
91
|
+
|
|
92
|
+
this.renderer = <div>
|
|
93
|
+
<div>
|
|
94
|
+
<div data-max-width="size-large">
|
|
95
|
+
<Form>
|
|
96
|
+
<FormField label="Your Name">
|
|
97
|
+
<input
|
|
98
|
+
autofocus={true}
|
|
99
|
+
placeholder="Display Name"
|
|
100
|
+
value={Bind.twoWaysImmediate(() => this.model.name)}/>
|
|
101
|
+
</FormField>
|
|
102
|
+
<FormField label="Email Address">
|
|
103
|
+
<div data-layout="row"
|
|
104
|
+
data-padding="auto">
|
|
105
|
+
<input
|
|
106
|
+
data-border="none"
|
|
107
|
+
placeholder="first-last-name"
|
|
108
|
+
style="outline: none"
|
|
109
|
+
type="text"
|
|
110
|
+
value={Bind.twoWaysImmediate(() => this.model.username)}
|
|
111
|
+
/>
|
|
112
|
+
<span
|
|
113
|
+
text="@socialmail.me"
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</FormField>
|
|
117
|
+
<details>
|
|
118
|
+
<summary>Username Policy</summary>
|
|
119
|
+
Please choose username that resembles your real legal name.
|
|
120
|
+
Any other name will be banned and blocked permanently. And you will not be able
|
|
121
|
+
to create new username with same phone number as well.
|
|
122
|
+
</details>
|
|
123
|
+
<FormField label="Password">
|
|
124
|
+
<input
|
|
125
|
+
type="password"
|
|
126
|
+
value={Bind.twoWaysImmediate(() => this.model.password)}
|
|
127
|
+
/>
|
|
128
|
+
</FormField>
|
|
129
|
+
<FormField label="Password Again">
|
|
130
|
+
<input
|
|
131
|
+
type="password"
|
|
132
|
+
value={Bind.twoWaysImmediate(() => this.model.passwordAgain)}
|
|
133
|
+
/>
|
|
134
|
+
</FormField>
|
|
135
|
+
<FormField label="Phone Number">
|
|
136
|
+
<div data-layout="row">
|
|
137
|
+
<CountrySelect
|
|
138
|
+
value={Bind.twoWaysImmediate(() => this.model.country)}
|
|
139
|
+
/>
|
|
140
|
+
<MaskedInput
|
|
141
|
+
data-mask={Bind.oneWayAsync(() => formatForCountry(this.model.country))}
|
|
142
|
+
value={Bind.twoWaysImmediate(() => this.model.phoneNumberText)}
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
</FormField>
|
|
146
|
+
<div>
|
|
147
|
+
We require phone number verification to prevent misuse and fraud over the email.
|
|
148
|
+
And it will also help you in setting up two factor authentication to prevent hackers
|
|
149
|
+
from accessing your private emails.
|
|
150
|
+
</div>
|
|
151
|
+
<br/>
|
|
152
|
+
<br/>
|
|
153
|
+
<FormField label="Captcha">
|
|
154
|
+
<img src={`/api/users/captcha/${id}`}/>
|
|
155
|
+
</FormField>
|
|
156
|
+
<FormField label="Enter 5 Digit Code">
|
|
157
|
+
<input
|
|
158
|
+
type="tel"
|
|
159
|
+
value={Bind.twoWaysImmediate(() => this.model.captcha.code)}/>
|
|
160
|
+
</FormField>
|
|
161
|
+
<div data-layout="row">
|
|
162
|
+
<input type="checkbox" checked={Bind.twoWaysImmediate(() => this.termsAgreed)}/>
|
|
163
|
+
<span text="I agree the "/>
|
|
164
|
+
<a href="https://socialmail.in/terms.html" target="_blank">Terms & Conditions</a>
|
|
165
|
+
</div>
|
|
166
|
+
<div data-layout="row">
|
|
167
|
+
<button
|
|
168
|
+
data-layout="go-button"
|
|
169
|
+
data-submit-event="signup"
|
|
170
|
+
>Signup</button>
|
|
171
|
+
</div>
|
|
172
|
+
</Form>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</div>;
|
|
176
|
+
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
@Action({ onEvent: "signup"})
|
|
180
|
+
async signup() {
|
|
181
|
+
|
|
182
|
+
const { model } = this;
|
|
183
|
+
|
|
184
|
+
if (!this.termsAgreed) {
|
|
185
|
+
throw new Error("You must agree to Terms & Conditions.");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (!model.password) {
|
|
189
|
+
throw new Error("Password is required");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (model.password.length < 7) {
|
|
193
|
+
throw new Error("Password is cannot be less than 7 characters");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (/\s/i.test(model.password)) {
|
|
197
|
+
throw new Error("Password must not any whitespace characters");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const isdCode = await isdForCountry(model.country);
|
|
201
|
+
const phoneNumber = model.phoneNumberText.replace(/[^0-9]/g,"");
|
|
202
|
+
model.phoneNumber = isdCode.startsWith("+") ? isdCode + phoneNumber: `+${isdCode}${phoneNumber}`;
|
|
203
|
+
const { userID,
|
|
204
|
+
phone = {} as IVerification,
|
|
205
|
+
captcha = {} as IVerification
|
|
206
|
+
} = await FetchBuilder.post("/api/users/signup")
|
|
207
|
+
.jsonBody(model)
|
|
208
|
+
.responseAsJson<any>();
|
|
209
|
+
|
|
210
|
+
if (userID) {
|
|
211
|
+
location.href = "/";
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (captcha) {
|
|
216
|
+
model.captcha.verified = captcha.verified;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if (phone?.verified) {
|
|
221
|
+
model.phone.verified = phone.verified;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (phone?.id) {
|
|
225
|
+
model.phone.id = phone.id;
|
|
226
|
+
await this.askPhoneCode();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async askPhoneCode() {
|
|
231
|
+
this.renderer = <div>
|
|
232
|
+
<div>
|
|
233
|
+
<div data-max-width="size-large">
|
|
234
|
+
<h3>Phone Verification Code</h3>
|
|
235
|
+
<p>We have send text verification code on your phone number,
|
|
236
|
+
please enter the code below to verify.
|
|
237
|
+
</p>
|
|
238
|
+
<Form>
|
|
239
|
+
<FormField label="">
|
|
240
|
+
<input
|
|
241
|
+
type="tel"
|
|
242
|
+
autofocus={true}
|
|
243
|
+
value={Bind.twoWaysImmediate(() => this.model.phone.code)}/>
|
|
244
|
+
</FormField>
|
|
245
|
+
<div>
|
|
246
|
+
<button
|
|
247
|
+
data-layout="go-button"
|
|
248
|
+
data-submit-event="signup"
|
|
249
|
+
>Complete Signup</button>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
</Form>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
</div>;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
}
|