@social-mail/social-mail-client 1.0.19 → 1.0.21
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 +225 -150
- package/dist/admin/AdminAppIndex.pack.js.map +1 -1
- package/dist/admin/AdminAppIndex.pack.min.js +12 -5
- package/dist/admin/AdminAppIndex.pack.min.js.map +1 -1
- package/dist/admin/drawer/AdminDrawer.js +3 -3
- package/dist/admin/drawer/AdminDrawer.js.map +1 -1
- package/dist/admin/pages/domains/services/AdminDomainService.js +1 -1
- package/dist/admin/pages/domains/services/AdminDomainService.js.map +1 -1
- package/dist/admin/pages/users/EditUserPage.js +65 -69
- package/dist/admin/pages/users/EditUserPage.js.map +1 -1
- package/dist/admin/pages/users/UserListPage.js +26 -4
- package/dist/admin/pages/users/UserListPage.js.map +1 -1
- package/dist/common/controls/password/PasswordStrength.js +59 -0
- package/dist/common/controls/password/PasswordStrength.js.map +1 -0
- package/dist/common/pages/user/LoginPage.js +44 -7
- package/dist/common/pages/user/LoginPage.js.map +1 -1
- package/dist/common/validators/Validators.js +27 -0
- package/dist/common/validators/Validators.js.map +1 -0
- package/dist/model/model.js +4 -2
- package/dist/model/model.js.map +1 -1
- package/dist/style/OverrideAppStyle.js +6 -0
- package/dist/style/OverrideAppStyle.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web/AppIndex.pack.js +151 -13
- package/dist/web/AppIndex.pack.js.map +1 -1
- package/dist/web/AppIndex.pack.min.js +12 -5
- package/dist/web/AppIndex.pack.min.js.map +1 -1
- package/dist/web/drawer/AppDrawer.js +2 -2
- package/dist/web/drawer/AppDrawer.js.map +1 -1
- package/dist/web/page/mails/MailsPage.js +1 -1
- package/dist/web/page/mails/MailsPage.js.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.d.ts.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.js +1 -0
- package/node_modules/@web-atoms/web-controls/dist/mobile-app/MobileApp.js.map +1 -1
- package/node_modules/@web-atoms/web-controls/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@web-atoms/web-controls/package.json +1 -1
- package/node_modules/@web-atoms/web-controls/src/mobile-app/MobileApp.tsx +1 -0
- package/package.json +2 -2
- package/src/admin/drawer/AdminDrawer.tsx +3 -3
- package/src/admin/pages/domains/services/AdminDomainService.ts +2 -1
- package/src/admin/pages/users/EditUserPage.tsx +58 -57
- package/src/admin/pages/users/UserListPage.tsx +15 -2
- package/src/common/controls/password/PasswordStrength.tsx +43 -0
- package/src/common/pages/user/LoginPage.tsx +52 -3
- package/src/common/validators/Validators.ts +27 -0
- package/src/model/model.ts +6 -5
- package/src/style/OverrideAppStyle.ts +6 -0
- package/src/web/drawer/AppDrawer.tsx +2 -2
- package/src/web/page/mails/MailsPage.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@social-mail/social-mail-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.21",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@web-atoms/font-awesome": "^1.0.37",
|
|
20
20
|
"@web-atoms/hybrid-clr": "^1.0.21",
|
|
21
21
|
"@web-atoms/module-loader": "^2.1.32",
|
|
22
|
-
"@web-atoms/web-controls": "^2.3.
|
|
22
|
+
"@web-atoms/web-controls": "^2.3.250",
|
|
23
23
|
"reflect-metadata": "^0.1.13"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
@@ -33,17 +33,17 @@ export default class AdminDrawer extends Drawer {
|
|
|
33
33
|
commandLink={AdminCommands.openHome.displayRoute({})}
|
|
34
34
|
/>
|
|
35
35
|
<MenuItem
|
|
36
|
-
icon="fas fa-
|
|
36
|
+
icon="fas fa-folder"
|
|
37
37
|
label="Domains"
|
|
38
38
|
commandLink={AdminCommands.openDomainList.displayRoute({})}
|
|
39
39
|
/>
|
|
40
40
|
<MenuItem
|
|
41
|
-
icon="fas fa-
|
|
41
|
+
icon="fas fa-user"
|
|
42
42
|
label="Users"
|
|
43
43
|
commandLink={AdminCommands.openUserList.displayRoute({})}
|
|
44
44
|
/>
|
|
45
45
|
<MenuItem
|
|
46
|
-
icon="fas fa-
|
|
46
|
+
icon="fas fa-envelope"
|
|
47
47
|
label="Mailboxes"
|
|
48
48
|
commandLink={AdminCommands.openMailboxList.displayRoute({})}
|
|
49
49
|
/>
|
|
@@ -18,7 +18,8 @@ export default class AdminDomainService {
|
|
|
18
18
|
|
|
19
19
|
public save(domain: IHostedDomain) {
|
|
20
20
|
const clone = this.entityService.cloner(domain)
|
|
21
|
-
.include((x) =>
|
|
21
|
+
.include((x) =>x.domainUsers)
|
|
22
|
+
.include((x) => x.domain);
|
|
22
23
|
return this.entityService.save(clone.copy);
|
|
23
24
|
}
|
|
24
25
|
|
|
@@ -1,65 +1,73 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { PopupWindowPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
|
|
2
|
+
import { IUser } from "../../../model/model";
|
|
3
3
|
import XNode from "@web-atoms/core/dist/core/XNode";
|
|
4
4
|
import Form from "@web-atoms/web-controls/dist/basic/Form";
|
|
5
5
|
import FormField from "@web-atoms/web-controls/dist/basic/FormField";
|
|
6
|
+
import PasswordBox from "@web-atoms/web-controls/dist/basic/PasswordBox";
|
|
6
7
|
import Bind from "@web-atoms/core/dist/core/Bind";
|
|
7
|
-
import
|
|
8
|
+
import { IPasswordValidation, Validators } from "../../../common/validators/Validators";
|
|
9
|
+
import PasswordStrength from "../../../common/controls/password/PasswordStrength";
|
|
8
10
|
import Action from "@web-atoms/core/dist/view-model/Action";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import AdminUserService from "./services/AdminUserService";
|
|
13
|
-
import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
|
|
11
|
+
import EntityService from "../../../services/EntityService";
|
|
12
|
+
import DateTime from "@web-atoms/date-time/dist/DateTime";
|
|
13
|
+
import Checkbox from "@web-atoms/web-controls/dist/basic/Checkbox";
|
|
14
14
|
|
|
15
|
-
export default class EditUserPage extends
|
|
15
|
+
export default class EditUserPage extends PopupWindowPage {
|
|
16
16
|
|
|
17
|
-
public parameters:
|
|
17
|
+
public parameters: IUser;
|
|
18
18
|
|
|
19
|
-
public model: IUser
|
|
19
|
+
public model: IUser;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
private adminUserService: AdminUserService;
|
|
21
|
+
private password: string = "";
|
|
23
22
|
|
|
24
23
|
async init() {
|
|
25
24
|
|
|
26
|
-
this.model = this.parameters
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
this.model = this.parameters;
|
|
26
|
+
|
|
27
|
+
this.model.changePassword ??= {
|
|
28
|
+
newPassword: "",
|
|
29
|
+
forceChangePasswordOnLogin: true
|
|
31
30
|
};
|
|
32
31
|
|
|
33
|
-
this.
|
|
34
|
-
<Form>
|
|
35
|
-
<TextFormField label="Display Name" autofocus={true} required={true} value={() => this.model.displayName}/>
|
|
36
|
-
<TextFormField label="Username" required={true} value={() => this.model.userName}/>
|
|
37
|
-
{ this.model.userID
|
|
38
|
-
? <PasswordFormField
|
|
39
|
-
label="Password"
|
|
40
|
-
required={true}
|
|
41
|
-
value={() => this.model.password}/>
|
|
42
|
-
: <PasswordFormField
|
|
43
|
-
label="Password"
|
|
44
|
-
placeholder="Leave empty..."
|
|
45
|
-
value={() => this.model.password}/>
|
|
46
|
-
}
|
|
32
|
+
this.title = `Reset Password for ${this.model.displayName} (${this.model.userID}, ${this.model.userName})` ;
|
|
47
33
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
34
|
+
this.renderer = <div>
|
|
35
|
+
<Form>
|
|
36
|
+
{ !this.model.userID && <FormField label="Display Name">
|
|
37
|
+
<input value={Bind.twoWaysImmediate(() => this.model.displayName)}/>
|
|
38
|
+
</FormField>}
|
|
39
|
+
{ !this.model.userID && <FormField label="Username">
|
|
40
|
+
<input value={Bind.twoWaysImmediate(() => this.model.userName)}/>
|
|
41
|
+
</FormField>}
|
|
42
|
+
<FormField
|
|
43
|
+
label="Password"
|
|
44
|
+
required={true}
|
|
45
|
+
error={Bind.oneWay(() => Validators.isValidPassword(this.password) ? "" : "Password is invalid" )}
|
|
46
|
+
>
|
|
47
|
+
<PasswordBox
|
|
48
|
+
value={Bind.twoWaysImmediate(() => this.password)}
|
|
56
49
|
/>
|
|
57
|
-
</
|
|
58
|
-
|
|
50
|
+
</FormField>
|
|
51
|
+
<PasswordStrength
|
|
52
|
+
password={Bind.oneWay(() => this.password)}
|
|
53
|
+
/>
|
|
54
|
+
<FormField
|
|
55
|
+
label="Password again"
|
|
56
|
+
required={true}
|
|
57
|
+
error={Bind.oneWay(() => this.password !== this.model.changePassword.newPassword ? "Passwords do not match" : "")}>
|
|
58
|
+
<PasswordBox
|
|
59
|
+
value={Bind.twoWaysImmediate(() => this.model.changePassword.newPassword)}
|
|
60
|
+
/>
|
|
61
|
+
</FormField>
|
|
62
|
+
<FormField label="Force Change Password">
|
|
63
|
+
<Checkbox
|
|
64
|
+
checked={Bind.twoWaysImmediate(() => this.model.changePassword.forceChangePasswordOnLogin)}
|
|
65
|
+
text="Force user to change password on next login."
|
|
66
|
+
/>
|
|
67
|
+
</FormField>
|
|
59
68
|
<div data-layout="command-row">
|
|
60
69
|
<button
|
|
61
|
-
data-submit-event="
|
|
62
|
-
data-layout="accept-button"
|
|
70
|
+
data-submit-event="reset-password"
|
|
63
71
|
text="Save"
|
|
64
72
|
/>
|
|
65
73
|
</div>
|
|
@@ -67,19 +75,12 @@ export default class EditUserPage extends ContentPage {
|
|
|
67
75
|
</div>;
|
|
68
76
|
}
|
|
69
77
|
|
|
70
|
-
@Action({ onEvent: "
|
|
71
|
-
async
|
|
72
|
-
const
|
|
73
|
-
this.model.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
@Action({ onEvent: "save-user", close: true })
|
|
80
|
-
async saveUser() {
|
|
81
|
-
await this.adminUserService.save(this.model);
|
|
82
|
-
return this.model;
|
|
78
|
+
@Action({ onEvent: "reset-password", success: "Information saved successfully.", close: true})
|
|
79
|
+
async resetPassword() {
|
|
80
|
+
const entityService = this.resolve(EntityService);
|
|
81
|
+
this.model.dateUpdated = DateTime.utcNow;
|
|
82
|
+
const clone = entityService.cloner(this.model).include((x) => x.changePassword).copy;
|
|
83
|
+
await entityService.save(clone);
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
}
|
|
@@ -4,7 +4,7 @@ import PageNavigator from "@web-atoms/web-controls/dist/PageNavigator";
|
|
|
4
4
|
import AtomRepeater from "@web-atoms/web-controls/dist/basic/AtomRepeater";
|
|
5
5
|
import { ContentPage } from "@web-atoms/web-controls/dist/mobile-app/MobileApp";
|
|
6
6
|
import EditDomainPage from "../domains/edit/EditDomainPage";
|
|
7
|
-
import { IUser } from "../../../model/model";
|
|
7
|
+
import { IUser, User } from "../../../model/model";
|
|
8
8
|
import AdminUserService from "./services/AdminUserService";
|
|
9
9
|
import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
|
|
10
10
|
import InfiniteRepeater from "../../../common/controls/repeater/InfiniteRepeater";
|
|
@@ -39,6 +39,7 @@ export default class UserListPage extends ContentPage {
|
|
|
39
39
|
<td>{user.userID}</td>
|
|
40
40
|
<td>{user.userName}</td>
|
|
41
41
|
<td>{user.displayName}</td>
|
|
42
|
+
<td><i data-cursor="pointer" class="fas fa-key" title="Change Password" data-click-event="user-change-password"/></td>
|
|
42
43
|
</tr> }
|
|
43
44
|
/>
|
|
44
45
|
</div>;
|
|
@@ -46,8 +47,20 @@ export default class UserListPage extends ContentPage {
|
|
|
46
47
|
|
|
47
48
|
@Action({ onEvent: "add-user"})
|
|
48
49
|
async addDomain() {
|
|
49
|
-
await PageNavigator.pushPageForResult(EditUserPage, {
|
|
50
|
+
await PageNavigator.pushPageForResult(EditUserPage, User.create({
|
|
51
|
+
userName: "",
|
|
52
|
+
displayName: "",
|
|
53
|
+
changePassword: {
|
|
54
|
+
forceChangePasswordOnLogin: true,
|
|
55
|
+
newPassword: ""
|
|
56
|
+
}
|
|
57
|
+
}) );
|
|
50
58
|
this.version++;
|
|
51
59
|
}
|
|
52
60
|
|
|
61
|
+
@Action({ onEvent: "user-change-password"})
|
|
62
|
+
async userChangePassword(model: IUser) {
|
|
63
|
+
PageNavigator.pushPage(EditUserPage, model);
|
|
64
|
+
}
|
|
65
|
+
|
|
53
66
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Bind from "@web-atoms/core/dist/core/Bind";
|
|
2
|
+
import XNode from "@web-atoms/core/dist/core/XNode";
|
|
3
|
+
import { AtomControl } from "@web-atoms/core/dist/web/controls/AtomControl";
|
|
4
|
+
import { IPasswordValidation, Validators } from "../../validators/Validators";
|
|
5
|
+
|
|
6
|
+
export default class PasswordStrength extends AtomControl {
|
|
7
|
+
|
|
8
|
+
public password: string = "";
|
|
9
|
+
|
|
10
|
+
public validation: IPasswordValidation = {
|
|
11
|
+
hasMinimumLength: false,
|
|
12
|
+
hasNumber: false,
|
|
13
|
+
hasSymbol: false,
|
|
14
|
+
isValid: false
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
protected preCreate(): void {
|
|
18
|
+
this.render(<div data-layout="vertical-flex" validation={Bind.oneWay(() => Validators.checkPassword(this.password))}>
|
|
19
|
+
|
|
20
|
+
<div data-layout="row">
|
|
21
|
+
<i
|
|
22
|
+
data-color={Bind.oneWay(() => this.validation.hasMinimumLength ? "green" : "red")}
|
|
23
|
+
class={Bind.oneWay(() => this.validation.hasMinimumLength ? "fas fa-check" : "fas fa-times")}/>
|
|
24
|
+
<span text="Password is at least 7 characters long."/>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div data-layout="row">
|
|
28
|
+
<i
|
|
29
|
+
data-color={Bind.oneWay(() => this.validation.hasNumber ? "green" : "red")}
|
|
30
|
+
class={Bind.oneWay(() => this.validation.hasNumber ? "fas fa-check" : "fas fa-times")}/>
|
|
31
|
+
<span text="Password has a number."/>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div data-layout="row">
|
|
35
|
+
<i
|
|
36
|
+
data-color={Bind.oneWay(() => this.validation.hasSymbol ? "green" : "red")}
|
|
37
|
+
class={Bind.oneWay(() => this.validation.hasSymbol ? "fas fa-check" : "fas fa-times")}/>
|
|
38
|
+
<span text="Password has a symbol."/>
|
|
39
|
+
</div>
|
|
40
|
+
</div>);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
}
|
|
@@ -8,6 +8,10 @@ import PasswordBox from "@web-atoms/web-controls/dist/basic/PasswordBox";
|
|
|
8
8
|
import Action from "@web-atoms/core/dist/view-model/Action";
|
|
9
9
|
import InjectProperty from "@web-atoms/core/dist/core/InjectProperty";
|
|
10
10
|
import UserService from "../../../services/UserService";
|
|
11
|
+
import { PasswordFormField } from "../../controls/form/RequiredFormField";
|
|
12
|
+
import sleep from "@web-atoms/core/dist/core/sleep";
|
|
13
|
+
import PasswordStrength from "../../controls/password/PasswordStrength";
|
|
14
|
+
import { Validators } from "../../validators/Validators";
|
|
11
15
|
|
|
12
16
|
export default class LoginPage extends ContentPage {
|
|
13
17
|
|
|
@@ -16,13 +20,15 @@ export default class LoginPage extends ContentPage {
|
|
|
16
20
|
|
|
17
21
|
private model: ILoginSession;
|
|
18
22
|
|
|
23
|
+
private password?: string = "";
|
|
24
|
+
|
|
19
25
|
async init() {
|
|
20
26
|
this.model = LoginSession.create({});
|
|
21
27
|
this.model.userName = "";
|
|
22
28
|
this.model.checkPassword = "";
|
|
23
29
|
this.render(<div>
|
|
24
30
|
<div data-layout="center-all">
|
|
25
|
-
<Form
|
|
31
|
+
<Form>
|
|
26
32
|
<FormField label="Username">
|
|
27
33
|
<input value={Bind.twoWaysImmediate(() => this.model.userName)}/>
|
|
28
34
|
</FormField>
|
|
@@ -34,7 +40,7 @@ export default class LoginPage extends ContentPage {
|
|
|
34
40
|
<div>
|
|
35
41
|
<button
|
|
36
42
|
data-layout="accent-button"
|
|
37
|
-
data-
|
|
43
|
+
data-submit-event="login"
|
|
38
44
|
text="Login"
|
|
39
45
|
/>
|
|
40
46
|
</div>
|
|
@@ -45,7 +51,50 @@ export default class LoginPage extends ContentPage {
|
|
|
45
51
|
|
|
46
52
|
@Action({ onEvent: "login" })
|
|
47
53
|
async login() {
|
|
48
|
-
|
|
54
|
+
try {
|
|
55
|
+
await this.userService.login(this.model);
|
|
56
|
+
return;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if(!/change the password/i.test(error.stack ?? error)) {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.model.newPassword = "";
|
|
64
|
+
|
|
65
|
+
this.renderer = <div>
|
|
66
|
+
<div data-layout="center-all">
|
|
67
|
+
<Form>
|
|
68
|
+
<div>Update your password, your one time password is expired.</div>
|
|
69
|
+
<FormField
|
|
70
|
+
label="Password"
|
|
71
|
+
required={true}
|
|
72
|
+
error={Bind.oneWay(() => Validators.isValidPassword(this.password)
|
|
73
|
+
? ""
|
|
74
|
+
: "Password must contain one symbol, one number and should be minimum 7 characters" )}>
|
|
75
|
+
<PasswordBox
|
|
76
|
+
value={Bind.twoWaysImmediate(() => this.password)}
|
|
77
|
+
/>
|
|
78
|
+
</FormField>
|
|
79
|
+
<PasswordStrength
|
|
80
|
+
password={Bind.oneWay(() => this.password)}
|
|
81
|
+
/>
|
|
82
|
+
<FormField
|
|
83
|
+
label="Password Again"
|
|
84
|
+
required={true}
|
|
85
|
+
error={Bind.oneWay(() => this.model.newPassword !== this.password ? "Passwords do not match" : "")}>
|
|
86
|
+
<PasswordBox
|
|
87
|
+
value={Bind.twoWaysImmediate(() => this.model.newPassword)}
|
|
88
|
+
/>
|
|
89
|
+
</FormField>
|
|
90
|
+
<div data-layout="command-row">
|
|
91
|
+
<button
|
|
92
|
+
data-submit-event="login"
|
|
93
|
+
text="Change Password & Login"/>
|
|
94
|
+
</div>
|
|
95
|
+
</Form>
|
|
96
|
+
</div>
|
|
97
|
+
</div>;
|
|
49
98
|
}
|
|
50
99
|
|
|
51
100
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface IPasswordValidation {
|
|
2
|
+
hasMinimumLength: boolean;
|
|
3
|
+
hasNumber: boolean;
|
|
4
|
+
hasSymbol: boolean;
|
|
5
|
+
isValid: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const Validators = {
|
|
9
|
+
|
|
10
|
+
checkPassword: (password: string) => {
|
|
11
|
+
const hasMinimumLength = password.length >= 7;
|
|
12
|
+
const hasNumber = /\d/.test(password);
|
|
13
|
+
const hasSymbol = /[\@\#\$\%\^\&\*\!]/.test(password);
|
|
14
|
+
return {
|
|
15
|
+
hasMinimumLength,
|
|
16
|
+
hasNumber,
|
|
17
|
+
hasSymbol,
|
|
18
|
+
isValid: hasMinimumLength && hasNumber && hasSymbol
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
isValidPassword: (password: string) => {
|
|
23
|
+
return Validators.checkPassword(password).isValid;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
};
|
|
27
|
+
|
package/src/model/model.ts
CHANGED
|
@@ -219,12 +219,13 @@ export interface IMailboxThread extends IClrEntity {
|
|
|
219
219
|
lastEmailID?: number;
|
|
220
220
|
dateUpdated?: DateTime;
|
|
221
221
|
unread?: number;
|
|
222
|
+
total?: number;
|
|
222
223
|
mailbox?: IMailbox;
|
|
223
224
|
emailAddress?: IEmailAddress;
|
|
224
225
|
lastEmail?: IEmail;
|
|
225
226
|
}
|
|
226
227
|
|
|
227
|
-
export const MailboxThread: IModel<IMailboxThread> = new Model<IMailboxThread>("MailboxThread", { mailboxID: 0,emailAddressID: 0,lastEmailID: 0,dateUpdated: new DateTime(),unread: 0 });
|
|
228
|
+
export const MailboxThread: IModel<IMailboxThread> = new Model<IMailboxThread>("MailboxThread", { mailboxID: 0,emailAddressID: 0,lastEmailID: 0,dateUpdated: new DateTime(),unread: 0,total: 0 });
|
|
228
229
|
|
|
229
230
|
export interface IMailboxThreadEmail extends IClrEntity {
|
|
230
231
|
mailboxID?: number;
|
|
@@ -240,17 +241,16 @@ export interface IUser extends IClrEntity {
|
|
|
240
241
|
userID?: number;
|
|
241
242
|
userName?: string;
|
|
242
243
|
displayName?: string;
|
|
243
|
-
|
|
244
|
-
password?: string;
|
|
244
|
+
dateUpdated?: DateTime;
|
|
245
245
|
/** Save this to change password */
|
|
246
|
-
changePassword?: { oldPassword?: string;newPassword?: string };
|
|
246
|
+
changePassword?: { oldPassword?: string;newPassword?: string;forceChangePasswordOnLogin?: boolean };
|
|
247
247
|
domainUsers?: ICollection<IDomainUser>;
|
|
248
248
|
roles?: ICollection<IUserRole>;
|
|
249
249
|
userMailboxes?: ICollection<IUserMailbox>;
|
|
250
250
|
sessions?: ICollection<ILoginSession>;
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
export const User: IModel<IUser> = new Model<IUser>("User", { userName: "",displayName: "" });
|
|
253
|
+
export const User: IModel<IUser> = new Model<IUser>("User", { userName: "",displayName: "",dateUpdated: new DateTime() });
|
|
254
254
|
|
|
255
255
|
export interface IUserRole extends IClrEntity {
|
|
256
256
|
userID?: number;
|
|
@@ -278,6 +278,7 @@ export interface ILoginSession extends IClrEntity {
|
|
|
278
278
|
invalid?: boolean;
|
|
279
279
|
userName?: string;
|
|
280
280
|
checkPassword?: string;
|
|
281
|
+
newPassword?: string;
|
|
281
282
|
user?: IUser;
|
|
282
283
|
}
|
|
283
284
|
|
|
@@ -34,12 +34,12 @@ export default class AppDrawer extends Drawer {
|
|
|
34
34
|
commandLink={AppCommands.openHome.displayRoute({})}
|
|
35
35
|
/>
|
|
36
36
|
<MenuItem
|
|
37
|
-
icon="fas fa-
|
|
37
|
+
icon="fas fa-envelope"
|
|
38
38
|
label="Mails"
|
|
39
39
|
commandLink={AppCommands.openMails.displayRoute({})}
|
|
40
40
|
/>
|
|
41
41
|
<MenuItem
|
|
42
|
-
icon="fas fa-
|
|
42
|
+
icon="fas fa-folder"
|
|
43
43
|
label="Mailboxes"
|
|
44
44
|
commandLink={AppCommands.openMailboxList.displayRoute({})}
|
|
45
45
|
/>
|
|
@@ -36,7 +36,7 @@ export default class MailsPage extends MasterDetailPage {
|
|
|
36
36
|
|
|
37
37
|
const first = mailboxes[0];
|
|
38
38
|
this.currentMailboxID = first.mailboxID;
|
|
39
|
-
this.
|
|
39
|
+
this.titleRenderer = () => <div data-layout="row">
|
|
40
40
|
<DropDown
|
|
41
41
|
items={mailboxes}
|
|
42
42
|
labelPath={(item) => item.emailAddress.emailAddress}
|