@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.
Files changed (29) hide show
  1. package/dist/admin/AdminAppIndex.pack.js +380 -146
  2. package/dist/admin/AdminAppIndex.pack.js.map +1 -1
  3. package/dist/admin/AdminAppIndex.pack.min.js +37 -9
  4. package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
  5. package/dist/common/pages/user/login/LoginPage.d.ts +0 -1
  6. package/dist/common/pages/user/login/LoginPage.d.ts.map +1 -1
  7. package/dist/common/pages/user/login/LoginPage.js +13 -13
  8. package/dist/common/pages/user/login/LoginPage.js.map +1 -1
  9. package/dist/tsconfig.tsbuildinfo +1 -1
  10. package/dist/web/AppIndex.pack.js +380 -146
  11. package/dist/web/AppIndex.pack.js.map +1 -1
  12. package/dist/web/AppIndex.pack.min.js +37 -9
  13. package/dist/web/AppIndex.pack.min.js.map +1 -1
  14. package/dist/web/commands/AppCommands.d.ts +1 -0
  15. package/dist/web/commands/AppCommands.d.ts.map +1 -1
  16. package/dist/web/commands/AppCommands.js +4 -0
  17. package/dist/web/commands/AppCommands.js.map +1 -1
  18. package/dist/web/page/users/SignupPage.d.ts +25 -0
  19. package/dist/web/page/users/SignupPage.d.ts.map +1 -0
  20. package/dist/web/page/users/SignupPage.js +227 -0
  21. package/dist/web/page/users/SignupPage.js.map +1 -0
  22. package/dist/web/page/users/SignupPage.pack.js +17044 -0
  23. package/dist/web/page/users/SignupPage.pack.js.map +1 -0
  24. package/dist/web/page/users/SignupPage.pack.min.js +818 -0
  25. package/dist/web/page/users/SignupPage.pack.min.js.map +1 -0
  26. package/package.json +1 -1
  27. package/src/common/pages/user/login/LoginPage.tsx +9 -13
  28. package/src/web/commands/AppCommands.ts +5 -0
  29. package/src/web/page/users/SignupPage.tsx +259 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@social-mail/social-mail-client",
3
- "version": "1.2.205",
3
+ "version": "1.2.207",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -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 authTypes = [{
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 (/socialmail\.me/i.test(location.href)) {
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
+ }