@nu-art/user-account-frontend 0.400.5

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 (48) hide show
  1. package/_ats/account-editor/ATS_AccountEditor.d.ts +15 -0
  2. package/_ats/account-editor/ATS_AccountEditor.js +45 -0
  3. package/_ats/account-editor/ATS_AccountEditor.scss +127 -0
  4. package/_ats_session-data/ATS_SessionData.d.ts +18 -0
  5. package/_ats_session-data/ATS_SessionData.js +40 -0
  6. package/_entity/account/ModuleFE_Account.d.ts +47 -0
  7. package/_entity/account/ModuleFE_Account.js +153 -0
  8. package/_entity/account/consts.d.ts +8 -0
  9. package/_entity/account/consts.js +7 -0
  10. package/_entity/account/index.d.ts +3 -0
  11. package/_entity/account/index.js +3 -0
  12. package/_entity/account/module-pack.d.ts +2 -0
  13. package/_entity/account/module-pack.js +3 -0
  14. package/_entity/session/ModuleFE_Session.d.ts +33 -0
  15. package/_entity/session/ModuleFE_Session.js +95 -0
  16. package/_entity.d.ts +3 -0
  17. package/_entity.js +3 -0
  18. package/account-editor/Component_AccountEditor.d.ts +38 -0
  19. package/account-editor/Component_AccountEditor.js +134 -0
  20. package/account-editor/Component_AccountEditor.scss +139 -0
  21. package/consts.d.ts +1 -0
  22. package/consts.js +1 -0
  23. package/index.d.ts +9 -0
  24. package/index.js +26 -0
  25. package/module-pack.d.ts +2 -0
  26. package/module-pack.js +21 -0
  27. package/package.json +81 -0
  28. package/ui/Component_AccountThumbnail/Component_AccountThumbnail.d.ts +14 -0
  29. package/ui/Component_AccountThumbnail/Component_AccountThumbnail.js +59 -0
  30. package/ui/Component_AccountThumbnail/Component_AccountThumbnail.scss +66 -0
  31. package/ui/Component_ChangePassword/Component_ChangePassword.d.ts +17 -0
  32. package/ui/Component_ChangePassword/Component_ChangePassword.js +52 -0
  33. package/ui/Component_GoogleSAMLLogin/Component_GoogleSAMLLogin.d.ts +6 -0
  34. package/ui/Component_GoogleSAMLLogin/Component_GoogleSAMLLogin.js +16 -0
  35. package/ui/Component_GoogleSAMLLogin/Component_GoogleSAMLLogin.scss +20 -0
  36. package/ui/Component_Login/Component_Login.d.ts +23 -0
  37. package/ui/Component_Login/Component_Login.js +124 -0
  38. package/ui/Component_Login/Component_Login.scss +66 -0
  39. package/ui/Component_Login/index.d.ts +1 -0
  40. package/ui/Component_Login/index.js +18 -0
  41. package/ui/Component_LoginBlocked/Component_LoginBlocked.d.ts +19 -0
  42. package/ui/Component_LoginBlocked/Component_LoginBlocked.js +35 -0
  43. package/ui/Component_LoginBlocked/Component_LoginBlocked.scss +3 -0
  44. package/ui/Component_Register.d.ts +26 -0
  45. package/ui/Component_Register.js +152 -0
  46. package/ui/PopUp_AccountMenu/PopUp_AccountMenu.d.ts +62 -0
  47. package/ui/PopUp_AccountMenu/PopUp_AccountMenu.js +130 -0
  48. package/ui/PopUp_AccountMenu/PopUp_AccountMenu.scss +167 -0
@@ -0,0 +1,134 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import * as React from 'react';
3
+ import { accountTypes } from '@nu-art/user-account-shared';
4
+ import { _className, Button, ComponentSync, Grid, LL_H_C, LL_V_L, ModuleFE_Thunderstorm, ModuleFE_Toaster, performAction, SimpleListAdapter, TS_DropDown, TS_Input, TS_PropRenderer } from '@nu-art/thunderstorm-frontend/index';
5
+ import { capitalizeFirstLetter, DateTimeFormat_yyyyMMDDTHHmmss, JwtTools, Year } from '@nu-art/ts-common';
6
+ import './Component_AccountEditor.scss';
7
+ import { TS_Icons } from '@nu-art/ts-styles';
8
+ import { ModuleFE_Account } from '../_entity.js';
9
+ export class Component_AccountEditor extends ComponentSync {
10
+ deriveStateFromProps(nextProps, state) {
11
+ state.sessions = [];
12
+ state.isPreview = !!nextProps.isPreview;
13
+ state.user = nextProps.user;
14
+ const accountId = nextProps.user?._id;
15
+ if (accountId)
16
+ ModuleFE_Account._v1.getSessions({ _id: accountId }).execute(async (response) => {
17
+ const sessions = await Promise.all(response.sessions.map(async (session) => {
18
+ const sessionJWT = await JwtTools.decode(session.sessionIdJwt);
19
+ return {
20
+ ...sessionJWT,
21
+ _id: session._id,
22
+ label: session.label,
23
+ deviceId: session.deviceId,
24
+ sessionIdJwt: session.sessionIdJwt,
25
+ };
26
+ }));
27
+ this.setState({ sessions });
28
+ });
29
+ return state;
30
+ }
31
+ addAccount = async () => {
32
+ return performAction(async () => {
33
+ const account = await ModuleFE_Account._v1.createAccount({
34
+ password: this.state.password,
35
+ type: this.state.type,
36
+ email: this.state.email,
37
+ passwordCheck: this.state.password
38
+ }).executeSync();
39
+ this.props.onComplete?.(account._id);
40
+ this.setState({
41
+ email: undefined,
42
+ password: undefined,
43
+ passwordCheck: undefined,
44
+ type: undefined
45
+ });
46
+ }, {
47
+ type: 'notification',
48
+ notificationLabels: {
49
+ inProgress: 'Creating Account',
50
+ success: 'Account Created',
51
+ failed: 'Failed Creating Account'
52
+ }
53
+ });
54
+ };
55
+ canCreate = () => {
56
+ const baseConditions = !!(this.state.email && this.state.type);
57
+ let extraConditions = true;
58
+ if (this.state.type === 'user')
59
+ extraConditions = !!this.state.password;
60
+ return baseConditions && extraConditions;
61
+ };
62
+ renderDropdown = () => {
63
+ if (this.state.isPreview)
64
+ return _jsx(TS_PropRenderer.Vertical, { label: 'User Type', children: _jsx("div", { children: capitalizeFirstLetter(this.state.user?.type ? this.state.user.type : '') }) });
65
+ return _jsx(TS_PropRenderer.Vertical, { label: 'User Type', children: _jsx(TS_DropDown, { placeholder: 'account type', selected: this.state.type, adapter: SimpleListAdapter([...accountTypes], i => _jsx("div", { className: 'node-data', children: _jsx("span", { children: i.item }) })), onSelected: (type) => {
66
+ type === 'service' ? this.setState({
67
+ type,
68
+ password: undefined
69
+ }) : this.setState({ type });
70
+ } }) });
71
+ };
72
+ renderInputs = () => {
73
+ if (this.state.isPreview)
74
+ return _jsxs(LL_H_C, { className: 'inputs-row', children: [_jsx(TS_PropRenderer.Vertical, { label: 'Email', children: _jsx("div", { children: this.state.user?.email }) }), this.state.user?.type !== 'service' && _jsx(TS_PropRenderer.Vertical, { label: 'Need To Set Password', children: _jsx("div", { children: this.state.user?._newPasswordRequired ? 'Yes' : 'No' }) })] });
75
+ return _jsxs(LL_H_C, { className: 'inputs-row', children: [_jsx(TS_PropRenderer.Vertical, { label: 'Email', children: _jsx(TS_Input, { type: 'text', placeholder: 'Email', value: this.state.email, onBlur: (email) => this.setState({ email }) }) }), _jsx(TS_PropRenderer.Vertical, { disabled: !(this.state.type === 'user'), label: 'Temporary Password', children: _jsx(TS_Input, { disabled: !(this.state.type === 'user'), type: 'password', value: this.state.password, placeholder: 'Temporary Password', onBlur: (password) => this.setState({ password }) }) })] });
76
+ };
77
+ renderSubmitButton = () => {
78
+ if (this.state.isPreview)
79
+ return '';
80
+ const disabled = !this.canCreate();
81
+ const className = _className(disabled && 'disabled');
82
+ return _jsx(Button, { variant: 'primary', className: className, disabled: disabled, onClick: this.addAccount, children: "Add Account" });
83
+ };
84
+ renderGenToken = () => {
85
+ if (!this.state.isPreview || this.state.user?.type !== 'service')
86
+ return;
87
+ const options = [
88
+ { label: '1 Year', ttl: 1 * Year },
89
+ { label: '2 Year', ttl: 2 * Year },
90
+ { label: '3 Year', ttl: 3 * Year },
91
+ { label: '5 Year', ttl: 5 * Year },
92
+ { label: '10 Year', ttl: 10 * Year },
93
+ ];
94
+ return _jsx(TS_PropRenderer.Vertical, { label: 'Generate New Token', children: _jsxs(LL_H_C, { className: 'gen-token-row', children: [_jsx(TS_PropRenderer.Vertical, { label: 'TTL', children: _jsx(TS_DropDown, { placeholder: 'Select Session TTL', selected: options.find(option => option.ttl === this.state.tokenTTL), adapter: SimpleListAdapter(options, item => _jsx(_Fragment, { children: item.item.label })), onSelected: option => this.setState({ tokenTTL: option.ttl }) }) }), _jsx(TS_PropRenderer.Vertical, { label: 'Label (Optional)', children: _jsx(TS_Input, { type: "text", value: this.state.tokenLabel, onBlur: tokenLabel => this.setState({ tokenLabel }) }) }), _jsx(Button, { variant: 'primary', onClick: async () => {
95
+ try {
96
+ const token = await ModuleFE_Account._v1.createToken({
97
+ accountId: this.state.user._id,
98
+ ttl: this.state.tokenTTL,
99
+ label: this.state.tokenLabel
100
+ })
101
+ .executeSync();
102
+ await ModuleFE_Thunderstorm.copyToClipboard(token.token);
103
+ ModuleFE_Toaster.toastSuccess('Token copied to clipboard');
104
+ this.reDeriveState();
105
+ }
106
+ catch (e) {
107
+ ModuleFE_Toaster.toastError(e.message);
108
+ this.logError(e);
109
+ }
110
+ }, children: "Generate Token" })] }) });
111
+ };
112
+ renderSessionGrid = () => {
113
+ if (!this.state.sessions.length)
114
+ return '';
115
+ return _jsx(TS_PropRenderer.Vertical, { label: 'Sessions', children: _jsxs(Grid, { children: [_jsx("div", { className: 'grid-title', children: "Label" }), _jsx("div", { className: 'grid-title', children: "Created At" }), _jsx("div", { className: 'grid-title', children: "Expiry Date" }), _jsx("div", { className: 'grid-title', children: "Device Id" }), _jsx("div", { className: 'grid-title' }), this.state.sessions.map(session => {
116
+ try {
117
+ const createdAt = DateTimeFormat_yyyyMMDDTHHmmss.format(session.iat * 1000);
118
+ const validTill = DateTimeFormat_yyyyMMDDTHHmmss.format(session.exp * 1000);
119
+ return _jsxs(React.Fragment, { children: [_jsx(LL_H_C, { className: 'grid-cell', children: session.label ?? 'No Label' }), _jsx(LL_H_C, { className: 'grid-cell', children: `${createdAt}` }), _jsx(LL_H_C, { className: 'grid-cell', children: `${validTill}` }), _jsx(LL_H_C, { className: 'grid-cell', children: session.deviceId }), _jsx(TS_Icons.copy.component, { onClick: () => ModuleFE_Thunderstorm.copyToClipboard(session.sessionIdJwt) })] }, session._id);
120
+ }
121
+ catch (e) {
122
+ return '';
123
+ }
124
+ })] }) });
125
+ };
126
+ renderDescription = () => {
127
+ if (!this.state.user?.description)
128
+ return '';
129
+ return _jsx(TS_PropRenderer.Vertical, { label: 'description', children: this.state.user.description });
130
+ };
131
+ render() {
132
+ return _jsxs(LL_V_L, { className: 'account-editor', children: [_jsxs(LL_V_L, { className: 'editor-section', children: [this.renderDropdown(), this.renderInputs(), this.renderSubmitButton(), this.renderDescription()] }), _jsxs(LL_V_L, { className: 'editor-section', children: [this.renderSessionGrid(), this.renderGenToken()] })] });
133
+ }
134
+ }
@@ -0,0 +1,139 @@
1
+ @use '@nu-art/ts-styles' as styles;
2
+
3
+ .account-editor {
4
+ padding: 14px;
5
+ min-width: 70%;
6
+ min-height: 40%;
7
+ background: white;
8
+ border-radius: 4px;
9
+ gap: 30px;
10
+
11
+ .editor-section {
12
+ gap: 15px;
13
+ }
14
+
15
+ .gen-token-row {
16
+ align-items: flex-end;
17
+ width: 100%;
18
+ gap: 5%;
19
+
20
+ .ts-dropdown {
21
+ max-width: 100%;
22
+ }
23
+
24
+ .ts-prop-renderer {
25
+ max-width: 33%;
26
+ }
27
+ }
28
+
29
+ .inputs-row {
30
+ gap: 10px;
31
+ width: 100%;
32
+ }
33
+
34
+ .ts-input {
35
+ padding: 2px 10px 2px 10px;
36
+ border-radius: 4px;
37
+ max-width: 100%;
38
+ background: none;
39
+ border: 1px solid #e3e9f2;
40
+
41
+ &::placeholder {
42
+ font-style: normal;
43
+ }
44
+ }
45
+
46
+ .ts-dropdown {
47
+ max-width: 300px;
48
+
49
+ .ts-dropdown__items-container {
50
+ margin: 0;
51
+ }
52
+
53
+ .ts-dropdown__header {
54
+ background: none;
55
+ border-radius: 4px;
56
+ border: 1px solid #e3e9f2;
57
+ padding: 2px 10px 2px 10px;
58
+ text-align: center;
59
+
60
+ .ts-dropdown__placeholder {
61
+ font-style: normal;
62
+ padding: 0;
63
+ }
64
+ }
65
+
66
+ .ts-dropdown__items-container {
67
+ border: none;
68
+ }
69
+
70
+
71
+ .ts-tree {
72
+ .ts-tree__children-container {
73
+ .ts-tree__node {
74
+ background: none;
75
+ padding: 4px;
76
+ cursor: pointer;
77
+ border: 1px solid #e3e9f2;
78
+
79
+ &:hover {
80
+ background: rgb(210, 219, 234);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+
87
+ .ts-prop-renderer {
88
+ .ts-grid {
89
+ grid-template-columns: repeat(5, max-content);
90
+ column-gap: 15px;
91
+ row-gap: 10px;
92
+
93
+ .grid-title {
94
+ font-size: 15px;
95
+ color: #004a72;
96
+ }
97
+
98
+ .grid-cell {
99
+ font-size: 14px;
100
+ color: #333333;
101
+ justify-content: center;
102
+ }
103
+
104
+ .icon--wrapper {
105
+ cursor: pointer;
106
+ }
107
+ }
108
+ }
109
+
110
+ .ts-busy-button {
111
+ background: white;
112
+ font-size: 12px;
113
+ border-radius: 5px;
114
+ min-width: 20%;
115
+ color: inherit;
116
+ padding: 2px 10px 2px 10px;
117
+ height: 40px;
118
+ font-weight: 400;
119
+ border: 1px #e3e9f2 solid;
120
+ margin-inline: 0;
121
+ transition: all 500ms;
122
+
123
+ &:hover {
124
+ background: #6C87B0FF;
125
+ color: white;
126
+ }
127
+
128
+ &.disabled {
129
+ background: styles.gray(7);
130
+ color: styles.gray(4);
131
+ cursor: not-allowed;
132
+
133
+ &:hover {
134
+ background: styles.gray(7);
135
+ color: styles.gray(4);
136
+ }
137
+ }
138
+ }
139
+ }
package/consts.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const RendererKey_AccountMenu_SubHeader = "account-menu_sub-header";
package/consts.js ADDED
@@ -0,0 +1 @@
1
+ export const RendererKey_AccountMenu_SubHeader = 'account-menu_sub-header';
package/index.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from './_entity.js';
2
+ export * from './module-pack.js';
3
+ export * from './_entity/account/ModuleFE_Account.js';
4
+ export * from './ui/Component_Login/Component_Login.js';
5
+ export * from './ui/Component_Register.js';
6
+ export * from './ui/Component_GoogleSAMLLogin/Component_GoogleSAMLLogin.js';
7
+ export * from './ui/Component_ChangePassword/Component_ChangePassword.js';
8
+ export * from './ui/Component_AccountThumbnail/Component_AccountThumbnail.js';
9
+ export * from './ui/PopUp_AccountMenu/PopUp_AccountMenu.js';
package/index.js ADDED
@@ -0,0 +1,26 @@
1
+ /*
2
+ * User secured registration and login management system..
3
+ *
4
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ export * from './_entity.js';
19
+ export * from './module-pack.js';
20
+ export * from './_entity/account/ModuleFE_Account.js';
21
+ export * from './ui/Component_Login/Component_Login.js';
22
+ export * from './ui/Component_Register.js';
23
+ export * from './ui/Component_GoogleSAMLLogin/Component_GoogleSAMLLogin.js';
24
+ export * from './ui/Component_ChangePassword/Component_ChangePassword.js';
25
+ export * from './ui/Component_AccountThumbnail/Component_AccountThumbnail.js';
26
+ export * from './ui/PopUp_AccountMenu/PopUp_AccountMenu.js';
@@ -0,0 +1,2 @@
1
+ import { Module } from '@nu-art/ts-common';
2
+ export declare const ModulePackFE_Accounts: Module[];
package/module-pack.js ADDED
@@ -0,0 +1,21 @@
1
+ /*
2
+ * User secured registration and login management system..
3
+ *
4
+ * Copyright (C) 2020 Adam van der Kruk aka TacB0sS
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+ import { ModulePackFE_AccountDB } from './_entity.js';
19
+ export const ModulePackFE_Accounts = [
20
+ ...ModulePackFE_AccountDB,
21
+ ];
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "@nu-art/user-account-frontend",
3
+ "version": "0.400.5",
4
+ "description": "User Account Frontend",
5
+ "keywords": [
6
+ "TacB0sS",
7
+ "create account",
8
+ "express",
9
+ "infra",
10
+ "login",
11
+ "nu-art",
12
+ "saml",
13
+ "thunderstorm",
14
+ "typescript",
15
+ "user-account"
16
+ ],
17
+ "homepage": "https://github.com/nu-art-js/user-account",
18
+ "bugs": {
19
+ "url": "https://github.com/nu-art-js/user-account/issues"
20
+ },
21
+ "publishConfig": {
22
+ "directory": "dist",
23
+ "linkDirectory": true
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+ssh://git@github.com:nu-art-js/user-account.git"
28
+ },
29
+ "license": "Apache-2.0",
30
+ "author": "TacB0sS",
31
+ "scripts": {
32
+ "build": "tsc",
33
+ "run-tests": "firebase emulators:exec \"npm run test\"",
34
+ "test": "ts-mocha -w -p src/test/tsconfig.json --timeout 0 --inspect=8107 --watch-files 'src/test/**/*.test.ts' src/test/**/*.test.ts"
35
+ },
36
+ "dependencies": {
37
+ "@nu-art/user-account-shared": "0.400.5",
38
+ "@nu-art/firebase-frontend": "0.400.5",
39
+ "@nu-art/firebase-shared": "0.400.5",
40
+ "@nu-art/slack-frontend": "0.400.5",
41
+ "@nu-art/slack-shared": "0.400.5",
42
+ "@nu-art/thunderstorm-frontend": "0.400.5",
43
+ "@nu-art/thunderstorm-shared": "0.400.5",
44
+ "@nu-art/ts-common": "0.400.5",
45
+ "@nu-art/ts-styles": "0.400.5",
46
+ "express": "^4.18.2",
47
+ "firebase": "^11.9.0",
48
+ "firebase-admin": "13.4.0",
49
+ "firebase-functions": "6.3.2",
50
+ "moment": "^2.29.4",
51
+ "pako": "^2.1.0",
52
+ "react": "^18.0.0",
53
+ "request": "^2.88.0",
54
+ "saml2-js": "^4.0.1",
55
+ "xmlbuilder": "^15.1.1"
56
+ },
57
+ "devDependencies": {
58
+ "@nu-art/google-services-backend": "0.400.5",
59
+ "@types/react": "^18.0.0",
60
+ "@types/express": "^4.17.17",
61
+ "@types/history": "^4.7.2",
62
+ "@types/request": "^2.48.1",
63
+ "@types/saml2-js": "^1.6.8",
64
+ "@types/pako": "^2.0.0",
65
+ "@types/jsonwebtoken": "^9.0.6"
66
+ },
67
+ "unitConfig": {
68
+ "type": "typescript-lib"
69
+ },
70
+ "type": "module",
71
+ "exports": {
72
+ ".": {
73
+ "types": "./index.d.ts",
74
+ "import": "./index.js"
75
+ },
76
+ "./*": {
77
+ "types": "./*.d.ts",
78
+ "import": "./*.js"
79
+ }
80
+ }
81
+ }
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ import { ModuleFE_BaseApi } from '@nu-art/thunderstorm-frontend/index';
3
+ import { ResolvableContent, UniqueId } from '@nu-art/ts-common';
4
+ import { DB_Account } from '@nu-art/user-account-shared';
5
+ import './Component_AccountThumbnail.scss';
6
+ type Props = {
7
+ accountId: ResolvableContent<UniqueId>;
8
+ onClick?: (e: React.MouseEvent, account: DB_Account) => void;
9
+ acronymComposer?: (accountId: UniqueId) => string | undefined;
10
+ };
11
+ export declare const Component_AccountThumbnail: (props: Props & {
12
+ modulesToAwait?: ModuleFE_BaseApi<any>[];
13
+ }) => import("react/jsx-runtime").JSX.Element;
14
+ export {};
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { _className, AwaitModules, ComponentSync, TS_ErrorBoundary, TS_Loader } from '@nu-art/thunderstorm-frontend/index';
3
+ import { cloneObj, filterDuplicates, MUSTNeverHappenException, resolveContent } from '@nu-art/ts-common';
4
+ import { ModuleFE_Account } from '../../_entity/account/index.js';
5
+ import { TS_Icons } from '@nu-art/ts-styles';
6
+ import './Component_AccountThumbnail.scss';
7
+ export const Component_AccountThumbnail = (props) => {
8
+ const { modulesToAwait, ...rest } = props;
9
+ const modules = [...(modulesToAwait ?? []), ModuleFE_Account];
10
+ return _jsx(AwaitModules, { modules: filterDuplicates(modules), customLoader: () => _jsx(TS_Loader, { className: 'user-thumbnail__loader' }), children: _jsx(Component_AccountThumbnail_Impl, { ...rest }) });
11
+ };
12
+ class Component_AccountThumbnail_Impl extends ComponentSync {
13
+ // ######################### Lifecycle #########################
14
+ shouldReDeriveState() {
15
+ return true;
16
+ }
17
+ __onAccountsUpdated = (...params) => {
18
+ this.reDeriveState();
19
+ };
20
+ deriveStateFromProps(nextProps, state) {
21
+ const accountId = resolveContent(nextProps.accountId);
22
+ state.account = ModuleFE_Account.cache.unique(accountId);
23
+ if (!state.account)
24
+ throw new MUSTNeverHappenException(`Could not find account for id ${accountId}`);
25
+ state.acronym = this.generateThumbnailAcronym(state.account);
26
+ return state;
27
+ }
28
+ // ######################### Logic #########################
29
+ generateThumbnailAcronym(account) {
30
+ const accountAcronym = account.displayName ? account.displayName.substring(0, 2).toUpperCase() : account.email.substring(0, 2).toUpperCase();
31
+ if (!this.props.acronymComposer)
32
+ return accountAcronym;
33
+ return this.props.acronymComposer(account._id) ?? accountAcronym;
34
+ }
35
+ onClick = (e) => {
36
+ if (!this.props.onClick || !this.state.account)
37
+ return;
38
+ this.props.onClick(e, cloneObj(this.state.account));
39
+ };
40
+ // ######################### Render #########################
41
+ render() {
42
+ const className = _className('user-thumbnail', this.props.onClick && 'clickable');
43
+ return _jsx(TS_ErrorBoundary, { children: _jsxs("div", { className: className, onClick: this.onClick, children: [this.renderContent(), this.renderImageUploadOverlay()] }) });
44
+ }
45
+ renderContent = () => {
46
+ if (this.state.account?.thumbnail)
47
+ return this.renderUserImage();
48
+ return _jsx("div", { className: 'user-thumbnail__acronym', children: this.state.acronym });
49
+ };
50
+ renderUserImage = () => {
51
+ const src = `data:image/jpeg;base64,${this.state.account.thumbnail}`;
52
+ return _jsx("img", { src: src, alt: 'user-image', className: 'user-thumbnail__image' });
53
+ };
54
+ renderImageUploadOverlay = () => {
55
+ if (this.props.onClick !== ModuleFE_Account.uploadAccountThumbnail)
56
+ return;
57
+ return _jsx("div", { className: 'user-thumbnail__upload-image-overlay', children: _jsx(TS_Icons.addImage.component, {}) });
58
+ };
59
+ }
@@ -0,0 +1,66 @@
1
+ @use '@nu-art/ts-styles' as tsStyles;
2
+
3
+ .user-thumbnail {
4
+ width: 26px;
5
+ height: 26px;
6
+ position: relative;
7
+ border-radius: 50%;
8
+ overflow: hidden;
9
+ border: 1px solid #1d496f;
10
+ background: white;
11
+
12
+ .user-thumbnail__acronym {
13
+ width: 100%;
14
+ height: 100%;
15
+ display: flex;
16
+ justify-content: center;
17
+ align-items: center;
18
+ font: {
19
+ size: 14px;
20
+ weight: bold;
21
+ }
22
+ text-transform: uppercase;
23
+ color: #1d496f;
24
+ }
25
+
26
+ .user-thumbnail__image {
27
+ width: 100%;
28
+ height: 100%;
29
+ }
30
+
31
+ .user-thumbnail__upload-image-overlay {
32
+ width: 100%;
33
+ height: 100%;
34
+ position: absolute;
35
+ top: 0;
36
+ left: 0;
37
+ background: #0008;
38
+ opacity: 0;
39
+ transition: opacity 200ms linear;
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+
44
+ .icon--wrapper {
45
+ width: 50%;
46
+ height: 50%;
47
+
48
+ @include tsStyles.color-svg(white);
49
+ }
50
+ }
51
+
52
+ &.clickable {
53
+ cursor: pointer;
54
+ }
55
+
56
+ &:hover {
57
+ .user-thumbnail__upload-image-overlay {
58
+ opacity: 1;
59
+ }
60
+ }
61
+ }
62
+
63
+ .user-thumbnail__loader {
64
+ width: 26px;
65
+ height: 26px;
66
+ }
@@ -0,0 +1,17 @@
1
+ import { ComponentSync } from '@nu-art/thunderstorm-frontend/index';
2
+ type Props = {
3
+ postSubmitAction?: () => void;
4
+ };
5
+ type State = {
6
+ shouldGiveCurrentPassword: boolean;
7
+ currentPassword?: string;
8
+ newPassword?: string;
9
+ newPasswordCheck?: string;
10
+ };
11
+ export declare class Component_ChangePassword extends ComponentSync<Props, State> {
12
+ protected deriveStateFromProps(nextProps: any, state: State): State;
13
+ private submitNewPassword;
14
+ private renderCurrentPassword;
15
+ render(): import("react/jsx-runtime").JSX.Element;
16
+ }
17
+ export {};
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, ComponentSync, LL_V_L, TS_Input, TS_PropRenderer } from '@nu-art/thunderstorm-frontend/index';
3
+ import { ThisShouldNotHappenException } from '@nu-art/ts-common';
4
+ import { ModuleFE_Account, SessionKeyFE_Account } from '../../_entity.js';
5
+ export class Component_ChangePassword extends ComponentSync {
6
+ // ######################## Life Cycle ########################
7
+ deriveStateFromProps(nextProps, state) {
8
+ const account = SessionKeyFE_Account.get();
9
+ if (!account)
10
+ throw new ThisShouldNotHappenException('Rendering a change password component without user logged in');
11
+ state.shouldGiveCurrentPassword = account.hasPassword;
12
+ return state;
13
+ }
14
+ // ######################## Logic ########################
15
+ submitNewPassword = async () => {
16
+ if (!this.state.newPassword || !this.state.newPasswordCheck) {
17
+ this.logError('No password or password check');
18
+ return;
19
+ }
20
+ try {
21
+ if (!this.state.shouldGiveCurrentPassword)
22
+ await ModuleFE_Account._v1.setPassword({
23
+ password: this.state.newPassword,
24
+ passwordCheck: this.state.newPasswordCheck,
25
+ }).executeSync();
26
+ else {
27
+ if (!this.state.currentPassword) {
28
+ this.logError('No current password given');
29
+ return;
30
+ }
31
+ await ModuleFE_Account._v1.changePassword({
32
+ oldPassword: this.state.currentPassword,
33
+ password: this.state.newPassword,
34
+ passwordCheck: this.state.newPasswordCheck,
35
+ }).executeSync();
36
+ }
37
+ this.props.postSubmitAction?.();
38
+ }
39
+ catch (e) {
40
+ this.logError(e);
41
+ }
42
+ };
43
+ // ######################## Render ########################
44
+ renderCurrentPassword = () => {
45
+ if (!this.state.shouldGiveCurrentPassword)
46
+ return '';
47
+ return _jsx(TS_PropRenderer.Vertical, { label: 'Current Password', children: _jsx(TS_Input, { type: 'password', value: this.state.currentPassword, onChange: val => this.setState({ currentPassword: val }) }) });
48
+ };
49
+ render() {
50
+ return _jsxs(LL_V_L, { className: 'ts-account__change-password', children: [this.renderCurrentPassword(), _jsx(TS_PropRenderer.Vertical, { label: 'New Password', children: _jsx(TS_Input, { type: 'password', value: this.state.newPassword, onChange: val => this.setState({ newPassword: val }) }) }), _jsx(TS_PropRenderer.Vertical, { label: 'New Password Check', children: _jsx(TS_Input, { type: 'password', value: this.state.newPasswordCheck, onChange: val => this.setState({ newPasswordCheck: val }) }) }), _jsx(Button, { variant: 'primary', onClick: this.submitNewPassword, children: "Submit" })] });
51
+ }
52
+ }
@@ -0,0 +1,6 @@
1
+ import './Component_GoogleSAMLLogin.scss';
2
+ type Props = {
3
+ text?: string;
4
+ };
5
+ export declare const Component_GoogleSAMLLogin: (props: Props) => import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from '@nu-art/thunderstorm-frontend/index';
3
+ import { TS_Icons } from '@nu-art/ts-styles';
4
+ import './Component_GoogleSAMLLogin.scss';
5
+ import { ModuleFE_Account, StorageKey_DeviceId } from '../../_entity.js';
6
+ import { MUSTNeverHappenException } from '@nu-art/ts-common';
7
+ export const Component_GoogleSAMLLogin = (props) => {
8
+ const onClick = async () => {
9
+ const url = ModuleFE_Account.composeSAMLUrl();
10
+ const deviceId = StorageKey_DeviceId.get();
11
+ if (!deviceId)
12
+ throw new MUSTNeverHappenException('Missing deviceId, how did this happen?');
13
+ await ModuleFE_Account._v1.loginSaml({ redirectUrl: url, deviceId }).executeSync();
14
+ };
15
+ return _jsxs(Button, { variant: 'primary', className: 'ts-account__saml-button', onClick: onClick, children: [props.text ?? 'Login With Google', _jsx(TS_Icons.google.component, { className: 'ts-account__saml-button__icon' })] });
16
+ };