@proteinjs/user-ui 1.0.34 → 1.0.36

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/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [1.0.36](https://github.com/proteinjs/user/compare/@proteinjs/user-ui@1.0.35...@proteinjs/user-ui@1.0.36) (2024-07-12)
7
+
8
+ **Note:** Version bump only for package @proteinjs/user-ui
9
+
10
+
11
+
12
+
13
+
6
14
  ## [1.0.27](https://github.com/proteinjs/user/compare/@proteinjs/user-ui@1.0.26...@proteinjs/user-ui@1.0.27) (2024-06-27)
7
15
 
8
16
  **Note:** Version bump only for package @proteinjs/user-ui
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Brent Bahry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,4 +1,6 @@
1
1
  /** Load Dependency Source Graphs */
2
+ import '@mui/icons-material';
3
+ import '@mui/material';
2
4
  import '@proteinjs/reflection';
3
5
  import '@proteinjs/server-api';
4
6
  import '@proteinjs/ui';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,eAAe,CAAC;AACvB,OAAO,iBAAiB,CAAC;AACzB,OAAO,QAAQ,CAAC;AAChB,OAAO,OAAO,CAAC;AACf,OAAO,WAAW,CAAC;AAyBnB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,qBAAqB,CAAC;AAC7B,OAAO,eAAe,CAAC;AACvB,OAAO,uBAAuB,CAAC;AAC/B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,eAAe,CAAC;AACvB,OAAO,iBAAiB,CAAC;AACzB,OAAO,QAAQ,CAAC;AAChB,OAAO,OAAO,CAAC;AACf,OAAO,WAAW,CAAC;AA6BnB,cAAc,UAAU,CAAC"}
@@ -15,6 +15,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
+ require("@mui/icons-material");
19
+ require("@mui/material");
18
20
  require("@proteinjs/reflection");
19
21
  require("@proteinjs/server-api");
20
22
  require("@proteinjs/ui");
@@ -23,12 +25,16 @@ require("moment");
23
25
  require("react");
24
26
  require("react-dom");
25
27
  /** Generate Source Graph */
26
- var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"/Omit\"},{\"v\":\"@proteinjs/user-ui/loginPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"loginPage\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/ui/src/pages/Login.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/loginPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/user-ui/signupPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"signupPage\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/ui/src/pages/Signup.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/signupPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-ui/loginPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-ui/signupPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"}]}";
28
+ var sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"/Omit\"},{\"v\":\"@proteinjs/user-ui/forgotPasswordPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"forgotPasswordPage\",\"filePath\":\"/home/runner/work/user/user/packages/ui/src/pages/ForgotPassword.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/forgotPasswordPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/user-ui/loginPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"loginPage\",\"filePath\":\"/home/runner/work/user/user/packages/ui/src/pages/Login.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/loginPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-ui/passwordResetPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"passwordResetPage\",\"filePath\":\"/home/runner/work/user/user/packages/ui/src/pages/PasswordReset.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/passwordResetPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/user-ui/signupPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"signupPage\",\"filePath\":\"/home/runner/work/user/user/packages/ui/src/pages/Signup.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/signupPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-ui/forgotPasswordPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-ui/loginPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-ui/passwordResetPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-ui/signupPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"}]}";
27
29
  /** Generate Source Links */
30
+ var ForgotPassword_1 = require("../src/pages/ForgotPassword");
28
31
  var Login_1 = require("../src/pages/Login");
32
+ var PasswordReset_1 = require("../src/pages/PasswordReset");
29
33
  var Signup_1 = require("../src/pages/Signup");
30
34
  var sourceLinks = {
35
+ '@proteinjs/user-ui/forgotPasswordPage': ForgotPassword_1.forgotPasswordPage,
31
36
  '@proteinjs/user-ui/loginPage': Login_1.loginPage,
37
+ '@proteinjs/user-ui/passwordResetPage': PasswordReset_1.passwordResetPage,
32
38
  '@proteinjs/user-ui/signupPage': Signup_1.signupPage,
33
39
  };
34
40
  /** Load Source Graph and Links */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,iCAA+B;AAC/B,iCAA+B;AAC/B,yBAAuB;AACvB,2BAAyB;AACzB,kBAAgB;AAChB,iBAAe;AACf,qBAAmB;AAGnB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,2oDAA2oD,CAAC;AAGhqD,4BAA4B;AAE5B,4CAA+C;AAC/C,8CAAiD;AAEjD,IAAM,WAAW,GAAG;IACnB,8BAA8B,EAAE,iBAAS;IACzC,+BAA+B,EAAE,mBAAU;CAC3C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../generated/index.ts"],"names":[],"mappings":";AAAA,oCAAoC;;;;;;;;;;;;;;;;AAEpC,+BAA6B;AAC7B,yBAAuB;AACvB,iCAA+B;AAC/B,iCAA+B;AAC/B,yBAAuB;AACvB,2BAAyB;AACzB,kBAAgB;AAChB,iBAAe;AACf,qBAAmB;AAGnB,4BAA4B;AAE5B,IAAM,WAAW,GAAG,8gGAA8gG,CAAC;AAGniG,4BAA4B;AAE5B,8DAAiE;AACjE,4CAA+C;AAC/C,4DAA+D;AAC/D,8CAAiD;AAEjD,IAAM,WAAW,GAAG;IACnB,uCAAuC,EAAE,mCAAkB;IAC3D,8BAA8B,EAAE,iBAAS;IACzC,sCAAsC,EAAE,iCAAiB;IACzD,+BAA+B,EAAE,mBAAU;CAC3C,CAAC;AAGF,kCAAkC;AAElC,oDAAyD;AACzD,6BAAgB,CAAC,KAAK,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;AAGjD,2CAAyB"}
@@ -0,0 +1,4 @@
1
+ import { Page } from '@proteinjs/ui';
2
+ export declare const forgotPasswordPath = "login/forgot-password";
3
+ export declare const forgotPasswordPage: Page;
4
+ //# sourceMappingURL=ForgotPassword.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ForgotPassword.d.ts","sourceRoot":"","sources":["../../../src/pages/ForgotPassword.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAkD,MAAM,eAAe,CAAC;AAIrF,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAC1D,eAAO,MAAM,kBAAkB,EAAE,IAgBhC,CAAC"}
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ };
26
+ var __generator = (this && this.__generator) || function (thisArg, body) {
27
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
28
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
29
+ function verb(n) { return function (v) { return step([n, v]); }; }
30
+ function step(op) {
31
+ if (f) throw new TypeError("Generator is already executing.");
32
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
33
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
34
+ if (y = 0, t) op = [op[0] & 2, t.value];
35
+ switch (op[0]) {
36
+ case 0: case 1: t = op; break;
37
+ case 4: _.label++; return { value: op[1], done: false };
38
+ case 5: _.label++; y = op[1]; op = [0]; continue;
39
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
40
+ default:
41
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
42
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
43
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
44
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
45
+ if (t[2]) _.ops.pop();
46
+ _.trys.pop(); continue;
47
+ }
48
+ op = body.call(thisArg, _);
49
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
50
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
51
+ }
52
+ };
53
+ var __importDefault = (this && this.__importDefault) || function (mod) {
54
+ return (mod && mod.__esModule) ? mod : { "default": mod };
55
+ };
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ exports.forgotPasswordPage = exports.forgotPasswordPath = void 0;
58
+ var react_1 = __importDefault(require("react"));
59
+ var ui_1 = require("@proteinjs/ui");
60
+ var user_1 = require("@proteinjs/user");
61
+ var PasswordReset_1 = require("./PasswordReset");
62
+ exports.forgotPasswordPath = 'login/forgot-password';
63
+ exports.forgotPasswordPage = {
64
+ name: 'Forgot Password',
65
+ path: exports.forgotPasswordPath,
66
+ auth: {
67
+ public: true,
68
+ },
69
+ component: function () { return (react_1.default.createElement(ui_1.FormPage, null,
70
+ react_1.default.createElement(ui_1.Form, { name: 'Forgot Password', createFields: function () { return new ForgotPasswordFields(); }, fieldLayout: ['email'], buttons: buttons }))); },
71
+ };
72
+ var ForgotPasswordFields = /** @class */ (function (_super) {
73
+ __extends(ForgotPasswordFields, _super);
74
+ function ForgotPasswordFields() {
75
+ var _this = _super !== null && _super.apply(this, arguments) || this;
76
+ _this.email = (0, ui_1.textField)({
77
+ name: 'email',
78
+ });
79
+ return _this;
80
+ }
81
+ ForgotPasswordFields.create = function () {
82
+ return new ForgotPasswordFields();
83
+ };
84
+ return ForgotPasswordFields;
85
+ }(ui_1.Fields));
86
+ var buttons = {
87
+ submit: {
88
+ name: 'Submit',
89
+ style: {
90
+ color: 'primary',
91
+ variant: 'contained',
92
+ },
93
+ onClick: function (fields, buttons) { return __awaiter(void 0, void 0, void 0, function () {
94
+ var response, body;
95
+ return __generator(this, function (_a) {
96
+ switch (_a.label) {
97
+ case 0: return [4 /*yield*/, fetch(user_1.routes.initiatePasswordReset.path, {
98
+ method: user_1.routes.initiatePasswordReset.method,
99
+ body: JSON.stringify({
100
+ email: fields.email.field.value,
101
+ resetPath: PasswordReset_1.passwordResetPath,
102
+ }),
103
+ redirect: 'follow',
104
+ credentials: 'same-origin',
105
+ headers: {
106
+ 'Content-Type': 'application/json',
107
+ },
108
+ })];
109
+ case 1:
110
+ response = _a.sent();
111
+ if (response.status != 200) {
112
+ throw new Error("Failed to initiate forgot password.");
113
+ }
114
+ return [4 /*yield*/, response.json()];
115
+ case 2:
116
+ body = _a.sent();
117
+ if (body.error) {
118
+ throw new Error("Failed to initiate forgot password.");
119
+ }
120
+ return [2 /*return*/, "Successfully sent an email with a link to reset your password."];
121
+ }
122
+ });
123
+ }); },
124
+ },
125
+ };
126
+ //# sourceMappingURL=ForgotPassword.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ForgotPassword.js","sourceRoot":"","sources":["../../../src/pages/ForgotPassword.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAA0B;AAC1B,oCAAqF;AACrF,wCAAyC;AACzC,iDAAoD;AAEvC,QAAA,kBAAkB,GAAG,uBAAuB,CAAC;AAC7C,QAAA,kBAAkB,GAAS;IACtC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,0BAAkB;IACxB,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI;KACb;IACD,SAAS,EAAE,cAAM,OAAA,CACf,8BAAC,aAAQ;QACP,8BAAC,SAAI,IACH,IAAI,EAAC,iBAAiB,EACtB,YAAY,EAAE,cAAM,OAAA,IAAI,oBAAoB,EAAE,EAA1B,CAA0B,EAC9C,WAAW,EAAE,CAAC,OAAO,CAAC,EACtB,OAAO,EAAE,OAAO,GAChB,CACO,CACZ,EATgB,CAShB;CACF,CAAC;AAEF;IAAmC,wCAAM;IAAzC;QAAA,qEAQC;QAHC,WAAK,GAAG,IAAA,cAAS,EAAuB;YACtC,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;;IACL,CAAC;IAPQ,2BAAM,GAAb;QACE,OAAO,IAAI,oBAAoB,EAAE,CAAC;IACpC,CAAC;IAKH,2BAAC;AAAD,CAAC,AARD,CAAmC,WAAM,GAQxC;AAED,IAAM,OAAO,GAAsC;IACjD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE;YACL,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,WAAW;SACrB;QACD,OAAO,EAAE,UAAO,MAA4B,EAAE,OAA0C;;;;4BACrE,qBAAM,KAAK,CAAC,aAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE;4BAC9D,MAAM,EAAE,aAAM,CAAC,qBAAqB,CAAC,MAAM;4BAC3C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;gCAC/B,SAAS,EAAE,iCAAiB;6BAC7B,CAAC;4BACF,QAAQ,EAAE,QAAQ;4BAClB,WAAW,EAAE,aAAa;4BAC1B,OAAO,EAAE;gCACP,cAAc,EAAE,kBAAkB;6BACnC;yBACF,CAAC,EAAA;;wBAXI,QAAQ,GAAG,SAWf;wBACF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE;4BAC1B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;yBACxD;wBAEY,qBAAM,QAAQ,CAAC,IAAI,EAAE,EAAA;;wBAA5B,IAAI,GAAG,SAAqB;wBAClC,IAAI,IAAI,CAAC,KAAK,EAAE;4BACd,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;yBACxD;wBAED,sBAAO,gEAAgE,EAAC;;;aACzE;KACF;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Login.d.ts","sourceRoot":"","sources":["../../../src/pages/Login.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAA+D,MAAM,eAAe,CAAC;AAGlG,eAAO,MAAM,SAAS,UAAU,CAAC;AACjC,eAAO,MAAM,SAAS,EAAE,IAgBvB,CAAC"}
1
+ {"version":3,"file":"Login.d.ts","sourceRoot":"","sources":["../../../src/pages/Login.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAA+D,MAAM,eAAe,CAAC;AAGlG,eAAO,MAAM,SAAS,UAAU,CAAC;AACjC,eAAO,MAAM,SAAS,EAAE,IAiBvB,CAAC"}
@@ -66,7 +66,7 @@ exports.loginPage = {
66
66
  public: true,
67
67
  },
68
68
  component: function () { return (react_1.default.createElement(ui_1.FormPage, null,
69
- react_1.default.createElement(ui_1.Form, { name: 'Login', createFields: function () { return new LoginFields(); }, fieldLayout: ['email', 'password'], buttons: buttons }))); },
69
+ react_1.default.createElement(ui_1.Form, { name: 'Login', createFields: function () { return new LoginFields(); }, fieldLayout: ['email', 'password'], buttons: buttons, maxWidth: 'xs' }))); },
70
70
  };
71
71
  var LoginFields = /** @class */ (function (_super) {
72
72
  __extends(LoginFields, _super);
@@ -87,6 +87,18 @@ var LoginFields = /** @class */ (function (_super) {
87
87
  return LoginFields;
88
88
  }(ui_1.Fields));
89
89
  var buttons = {
90
+ forgotPassword: {
91
+ name: 'Forgot password',
92
+ style: {
93
+ variant: 'text',
94
+ align: 'left',
95
+ },
96
+ redirect: function () { return __awaiter(void 0, void 0, void 0, function () {
97
+ return __generator(this, function (_a) {
98
+ return [2 /*return*/, { path: '/login/forgot-password' }];
99
+ });
100
+ }); },
101
+ },
90
102
  clear: ui_1.clearButton,
91
103
  login: {
92
104
  name: 'Login',
@@ -1 +1 @@
1
- {"version":3,"file":"Login.js","sourceRoot":"","sources":["../../../src/pages/Login.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAA0B;AAC1B,oCAAkG;AAClG,wCAAyC;AAE5B,QAAA,SAAS,GAAG,OAAO,CAAC;AACpB,QAAA,SAAS,GAAS;IAC7B,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,iBAAS;IACf,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI;KACb;IACD,SAAS,EAAE,cAAM,OAAA,CACf,8BAAC,aAAQ;QACP,8BAAC,SAAI,IACH,IAAI,EAAC,OAAO,EACZ,YAAY,EAAE,cAAM,OAAA,IAAI,WAAW,EAAE,EAAjB,CAAiB,EACrC,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAClC,OAAO,EAAE,OAAO,GAChB,CACO,CACZ,EATgB,CAShB;CACF,CAAC;AAEF;IAA0B,+BAAM;IAAhC;QAAA,qEAaC;QARC,WAAK,GAAG,IAAA,cAAS,EAAc;YAC7B,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,cAAQ,GAAG,IAAA,cAAS,EAAc;YAChC,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;;IACL,CAAC;IAZQ,kBAAM,GAAb;QACE,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;IAUH,kBAAC;AAAD,CAAC,AAbD,CAA0B,WAAM,GAa/B;AAED,IAAM,OAAO,GAA6B;IACxC,KAAK,EAAE,gBAAW;IAClB,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,WAAW;SACrB;QACD,OAAO,EAAE,UAAO,MAAmB,EAAE,OAAiC;;;;4BACnD,qBAAM,KAAK,CAAC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE;4BAC9C,MAAM,EAAE,aAAM,CAAC,KAAK,CAAC,MAAM;4BAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;gCAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK;6BACtC,CAAC;4BACF,QAAQ,EAAE,QAAQ;4BAClB,WAAW,EAAE,aAAa;4BAC1B,OAAO,EAAE;gCACP,cAAc,EAAE,kBAAkB;6BACnC;yBACF,CAAC,EAAA;;wBAXI,QAAQ,GAAG,SAWf;wBACF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE;4BAC1B,MAAM,IAAI,KAAK,CAAC,kCAA2B,QAAQ,CAAC,UAAU,CAAE,CAAC,CAAC;yBACnE;wBAEY,qBAAM,QAAQ,CAAC,IAAI,EAAE,EAAA;;wBAA5B,IAAI,GAAG,SAAqB;wBAClC,IAAI,IAAI,CAAC,KAAK,EAAE;4BACd,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;yBAC7B;wBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;;;;aAC5B;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"Login.js","sourceRoot":"","sources":["../../../src/pages/Login.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAA0B;AAC1B,oCAAkG;AAClG,wCAAyC;AAE5B,QAAA,SAAS,GAAG,OAAO,CAAC;AACpB,QAAA,SAAS,GAAS;IAC7B,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,iBAAS;IACf,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI;KACb;IACD,SAAS,EAAE,cAAM,OAAA,CACf,8BAAC,aAAQ;QACP,8BAAC,SAAI,IACH,IAAI,EAAC,OAAO,EACZ,YAAY,EAAE,cAAM,OAAA,IAAI,WAAW,EAAE,EAAjB,CAAiB,EACrC,WAAW,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,IAAI,GACd,CACO,CACZ,EAVgB,CAUhB;CACF,CAAC;AAEF;IAA0B,+BAAM;IAAhC;QAAA,qEAaC;QARC,WAAK,GAAG,IAAA,cAAS,EAAc;YAC7B,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,cAAQ,GAAG,IAAA,cAAS,EAAc;YAChC,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;;IACL,CAAC;IAZQ,kBAAM,GAAb;QACE,OAAO,IAAI,WAAW,EAAE,CAAC;IAC3B,CAAC;IAUH,kBAAC;AAAD,CAAC,AAbD,CAA0B,WAAM,GAa/B;AAED,IAAM,OAAO,GAA6B;IACxC,cAAc,EAAE;QACd,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,MAAM;SACd;QACD,QAAQ,EAAE;;gBACR,sBAAO,EAAE,IAAI,EAAE,wBAAwB,EAAE,EAAC;;aAC3C;KACF;IACD,KAAK,EAAE,gBAAW;IAClB,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE;YACL,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,WAAW;SACrB;QACD,OAAO,EAAE,UAAO,MAAmB,EAAE,OAAiC;;;;4BACnD,qBAAM,KAAK,CAAC,aAAM,CAAC,KAAK,CAAC,IAAI,EAAE;4BAC9C,MAAM,EAAE,aAAM,CAAC,KAAK,CAAC,MAAM;4BAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gCACnB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;gCAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK;6BACtC,CAAC;4BACF,QAAQ,EAAE,QAAQ;4BAClB,WAAW,EAAE,aAAa;4BAC1B,OAAO,EAAE;gCACP,cAAc,EAAE,kBAAkB;6BACnC;yBACF,CAAC,EAAA;;wBAXI,QAAQ,GAAG,SAWf;wBACF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE;4BAC1B,MAAM,IAAI,KAAK,CAAC,kCAA2B,QAAQ,CAAC,UAAU,CAAE,CAAC,CAAC;yBACnE;wBAEY,qBAAM,QAAQ,CAAC,IAAI,EAAE,EAAA;;wBAA5B,IAAI,GAAG,SAAqB;wBAClC,IAAI,IAAI,CAAC,KAAK,EAAE;4BACd,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;yBAC7B;wBAED,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;;;;aAC5B;KACF;CACF,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Page } from '@proteinjs/ui';
2
+ export declare const passwordResetPath = "login/password-reset";
3
+ export declare const passwordResetPage: Page;
4
+ //# sourceMappingURL=PasswordReset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasswordReset.d.ts","sourceRoot":"","sources":["../../../src/pages/PasswordReset.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAkD,MAAM,eAAe,CAAC;AAIrF,eAAO,MAAM,iBAAiB,yBAAyB,CAAC;AA6HxD,eAAO,MAAM,iBAAiB,EAAE,IAO/B,CAAC"}
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
41
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
42
+ return new (P || (P = Promise))(function (resolve, reject) {
43
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
44
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
45
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
46
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
47
+ });
48
+ };
49
+ var __generator = (this && this.__generator) || function (thisArg, body) {
50
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
51
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
52
+ function verb(n) { return function (v) { return step([n, v]); }; }
53
+ function step(op) {
54
+ if (f) throw new TypeError("Generator is already executing.");
55
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
56
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
57
+ if (y = 0, t) op = [op[0] & 2, t.value];
58
+ switch (op[0]) {
59
+ case 0: case 1: t = op; break;
60
+ case 4: _.label++; return { value: op[1], done: false };
61
+ case 5: _.label++; y = op[1]; op = [0]; continue;
62
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
63
+ default:
64
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
65
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
66
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
67
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
68
+ if (t[2]) _.ops.pop();
69
+ _.trys.pop(); continue;
70
+ }
71
+ op = body.call(thisArg, _);
72
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
73
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
74
+ }
75
+ };
76
+ Object.defineProperty(exports, "__esModule", { value: true });
77
+ exports.passwordResetPage = exports.passwordResetPath = void 0;
78
+ var react_1 = __importStar(require("react"));
79
+ var ui_1 = require("@proteinjs/ui");
80
+ var user_1 = require("@proteinjs/user");
81
+ var material_1 = require("@mui/material");
82
+ exports.passwordResetPath = 'login/password-reset';
83
+ var PasswordResetComponent = function () {
84
+ var _a = (0, react_1.useState)(''), token = _a[0], setToken = _a[1];
85
+ var _b = (0, react_1.useState)(false), isValidating = _b[0], setIsValidating = _b[1];
86
+ var _c = (0, react_1.useState)(null), validationError = _c[0], setValidationError = _c[1];
87
+ var _d = (0, react_1.useState)(false), resetSuccess = _d[0], setResetSuccess = _d[1];
88
+ var buttons = {
89
+ submit: {
90
+ name: 'Reset Password',
91
+ style: {
92
+ color: 'primary',
93
+ variant: 'contained',
94
+ },
95
+ onClick: function (fields) { return __awaiter(void 0, void 0, void 0, function () {
96
+ var response;
97
+ return __generator(this, function (_a) {
98
+ switch (_a.label) {
99
+ case 0:
100
+ if (fields.newPassword.field.value !== fields.confirmPassword.field.value) {
101
+ throw new Error('Passwords do not match');
102
+ }
103
+ return [4 /*yield*/, fetch(user_1.routes.executePasswordReset.path, {
104
+ method: user_1.routes.executePasswordReset.method,
105
+ body: JSON.stringify({
106
+ token: fields.token.field.value,
107
+ newPassword: fields.newPassword.field.value,
108
+ }),
109
+ credentials: 'same-origin',
110
+ headers: {
111
+ 'Content-Type': 'application/json',
112
+ },
113
+ })];
114
+ case 1:
115
+ response = _a.sent();
116
+ if (response.status !== 200) {
117
+ throw new Error('Failed to reset password');
118
+ }
119
+ setResetSuccess(true);
120
+ return [2 /*return*/, 'Your password has been successfully reset. You can now log in with your new password.'];
121
+ }
122
+ });
123
+ }); },
124
+ },
125
+ };
126
+ (0, react_1.useEffect)(function () {
127
+ var searchParams = new URLSearchParams(window.location.search);
128
+ var resetToken = searchParams.get('token');
129
+ if (resetToken) {
130
+ setToken(resetToken);
131
+ validateToken(resetToken);
132
+ }
133
+ else {
134
+ setValidationError('No reset token provided');
135
+ }
136
+ }, []);
137
+ var validateToken = function (token) { return __awaiter(void 0, void 0, void 0, function () {
138
+ var response, data, error_1;
139
+ return __generator(this, function (_a) {
140
+ switch (_a.label) {
141
+ case 0:
142
+ setIsValidating(true);
143
+ _a.label = 1;
144
+ case 1:
145
+ _a.trys.push([1, 4, 5, 6]);
146
+ return [4 /*yield*/, fetch("".concat(user_1.routes.validateResetToken.path, "?token=").concat(token), {
147
+ method: user_1.routes.validateResetToken.method,
148
+ credentials: 'same-origin',
149
+ })];
150
+ case 2:
151
+ response = _a.sent();
152
+ return [4 /*yield*/, response.json()];
153
+ case 3:
154
+ data = _a.sent();
155
+ if (!data.isValid) {
156
+ setValidationError(data.message || 'Invalid or expired token');
157
+ }
158
+ return [3 /*break*/, 6];
159
+ case 4:
160
+ error_1 = _a.sent();
161
+ setValidationError('An error occurred while validating the token');
162
+ return [3 /*break*/, 6];
163
+ case 5:
164
+ setIsValidating(false);
165
+ return [7 /*endfinally*/];
166
+ case 6: return [2 /*return*/];
167
+ }
168
+ });
169
+ }); };
170
+ if (isValidating) {
171
+ return react_1.default.createElement(ui_1.FormPage, null, "Validating reset token...");
172
+ }
173
+ if (validationError) {
174
+ return (react_1.default.createElement(ui_1.FormPage, null,
175
+ react_1.default.createElement(material_1.Stack, { alignItems: 'center', spacing: 3 },
176
+ react_1.default.createElement(material_1.Typography, { variant: 'h1', gutterBottom: true }, "Invalid password reset link"),
177
+ react_1.default.createElement(material_1.Typography, { variant: 'body1', gutterBottom: true }, "The password reset link is invalid or has expired. Please request a new password reset."),
178
+ react_1.default.createElement(material_1.Button, { variant: 'contained', color: 'primary', href: '/login' }, "Go to login page"))));
179
+ }
180
+ if (resetSuccess) {
181
+ return (react_1.default.createElement(ui_1.FormPage, null,
182
+ react_1.default.createElement(material_1.Stack, { alignItems: 'center', spacing: 3 },
183
+ react_1.default.createElement(material_1.Typography, { variant: 'h6', gutterBottom: true }, "Password reset successful"),
184
+ react_1.default.createElement(material_1.Typography, { variant: 'body1', gutterBottom: true }, "Your password has been successfully reset. You can now log in with your new password."),
185
+ react_1.default.createElement(material_1.Button, { variant: 'contained', color: 'primary', href: '/login' }, "Go to login page"))));
186
+ }
187
+ return (react_1.default.createElement(ui_1.FormPage, null,
188
+ react_1.default.createElement(ui_1.Form, { name: 'Reset Password', createFields: function () { return new ResetPasswordFields(); }, fieldLayout: ['newPassword', 'confirmPassword'], buttons: buttons, onLoad: function (fields) { return __awaiter(void 0, void 0, void 0, function () {
189
+ return __generator(this, function (_a) {
190
+ fields.token.field.value = token;
191
+ return [2 /*return*/];
192
+ });
193
+ }); } })));
194
+ };
195
+ exports.passwordResetPage = {
196
+ name: 'Reset Password',
197
+ path: exports.passwordResetPath,
198
+ auth: {
199
+ public: true,
200
+ },
201
+ component: PasswordResetComponent,
202
+ };
203
+ var ResetPasswordFields = /** @class */ (function (_super) {
204
+ __extends(ResetPasswordFields, _super);
205
+ function ResetPasswordFields() {
206
+ var _this = _super !== null && _super.apply(this, arguments) || this;
207
+ _this.token = (0, ui_1.textField)({
208
+ name: 'token',
209
+ accessibility: { hidden: true },
210
+ });
211
+ _this.newPassword = (0, ui_1.textField)({
212
+ name: 'New Password',
213
+ isPassword: true,
214
+ });
215
+ _this.confirmPassword = (0, ui_1.textField)({
216
+ name: 'Confirm New Password',
217
+ isPassword: true,
218
+ });
219
+ return _this;
220
+ }
221
+ ResetPasswordFields.create = function () {
222
+ return new ResetPasswordFields();
223
+ };
224
+ return ResetPasswordFields;
225
+ }(ui_1.Fields));
226
+ //# sourceMappingURL=PasswordReset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasswordReset.js","sourceRoot":"","sources":["../../../src/pages/PasswordReset.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,7 @@
1
1
  /** Load Dependency Source Graphs */
2
2
 
3
+ import '@mui/icons-material';
4
+ import '@mui/material';
3
5
  import '@proteinjs/reflection';
4
6
  import '@proteinjs/server-api';
5
7
  import '@proteinjs/ui';
@@ -8,27 +10,28 @@ import 'moment';
8
10
  import 'react';
9
11
  import 'react-dom';
10
12
 
11
-
12
13
  /** Generate Source Graph */
13
14
 
14
- const sourceGraph = "{\"options\":{\"directed\":true,\"multigraph\":false,\"compound\":false},\"nodes\":[{\"v\":\"/Omit\"},{\"v\":\"@proteinjs/user-ui/loginPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"loginPage\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/ui/src/pages/Login.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/loginPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}},{\"v\":\"@proteinjs/ui/Page\"},{\"v\":\"@proteinjs/user-ui/signupPage\",\"value\":{\"packageName\":\"@proteinjs/user-ui\",\"name\":\"signupPage\",\"filePath\":\"/Users/veronica/Repositories/n3xa-meta-repo/packages/proteinjs/packages/user/packages/ui/src/pages/Signup.tsx\",\"qualifiedName\":\"@proteinjs/user-ui/signupPage\",\"type\":{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":[{\"packageName\":\"@proteinjs/ui\",\"name\":\"Page\",\"filePath\":null,\"qualifiedName\":\"@proteinjs/ui/Page\",\"typeParameters\":[],\"directParents\":null}]},\"isExported\":true,\"isConst\":true,\"sourceType\":0}}],\"edges\":[{\"v\":\"@proteinjs/user-ui/loginPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"},{\"v\":\"@proteinjs/user-ui/signupPage\",\"w\":\"@proteinjs/ui/Page\",\"value\":\"has type\"}]}";
15
-
15
+ const sourceGraph =
16
+ '{"options":{"directed":true,"multigraph":false,"compound":false},"nodes":[{"v":"/Omit"},{"v":"@proteinjs/user-ui/forgotPasswordPage","value":{"packageName":"@proteinjs/user-ui","name":"forgotPasswordPage","filePath":"/home/runner/work/user/user/packages/ui/src/pages/ForgotPassword.tsx","qualifiedName":"@proteinjs/user-ui/forgotPasswordPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/ui/Page"},{"v":"@proteinjs/user-ui/loginPage","value":{"packageName":"@proteinjs/user-ui","name":"loginPage","filePath":"/home/runner/work/user/user/packages/ui/src/pages/Login.tsx","qualifiedName":"@proteinjs/user-ui/loginPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-ui/passwordResetPage","value":{"packageName":"@proteinjs/user-ui","name":"passwordResetPage","filePath":"/home/runner/work/user/user/packages/ui/src/pages/PasswordReset.tsx","qualifiedName":"@proteinjs/user-ui/passwordResetPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}},{"v":"@proteinjs/user-ui/signupPage","value":{"packageName":"@proteinjs/user-ui","name":"signupPage","filePath":"/home/runner/work/user/user/packages/ui/src/pages/Signup.tsx","qualifiedName":"@proteinjs/user-ui/signupPage","type":{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":[{"packageName":"@proteinjs/ui","name":"Page","filePath":null,"qualifiedName":"@proteinjs/ui/Page","typeParameters":[],"directParents":null}]},"isExported":true,"isConst":true,"sourceType":0}}],"edges":[{"v":"@proteinjs/user-ui/forgotPasswordPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/user-ui/loginPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/user-ui/passwordResetPage","w":"@proteinjs/ui/Page","value":"has type"},{"v":"@proteinjs/user-ui/signupPage","w":"@proteinjs/ui/Page","value":"has type"}]}';
16
17
 
17
18
  /** Generate Source Links */
18
19
 
20
+ import { forgotPasswordPage } from '../src/pages/ForgotPassword';
19
21
  import { loginPage } from '../src/pages/Login';
22
+ import { passwordResetPage } from '../src/pages/PasswordReset';
20
23
  import { signupPage } from '../src/pages/Signup';
21
24
 
22
25
  const sourceLinks = {
23
- '@proteinjs/user-ui/loginPage': loginPage,
24
- '@proteinjs/user-ui/signupPage': signupPage,
26
+ '@proteinjs/user-ui/forgotPasswordPage': forgotPasswordPage,
27
+ '@proteinjs/user-ui/loginPage': loginPage,
28
+ '@proteinjs/user-ui/passwordResetPage': passwordResetPage,
29
+ '@proteinjs/user-ui/signupPage': signupPage,
25
30
  };
26
31
 
27
-
28
32
  /** Load Source Graph and Links */
29
33
 
30
34
  import { SourceRepository } from '@proteinjs/reflection';
31
35
  SourceRepository.merge(sourceGraph, sourceLinks);
32
36
 
33
-
34
- export * from '../index';
37
+ export * from '../index';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteinjs/user-ui",
3
- "version": "1.0.34",
3
+ "version": "1.0.36",
4
4
  "description": "User ui components",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -21,10 +21,12 @@
21
21
  "watch": "reflection-watch"
22
22
  },
23
23
  "dependencies": {
24
+ "@mui/icons-material": "5.14.11",
25
+ "@mui/material": "5.14.11",
24
26
  "@proteinjs/reflection": "1.1.6",
25
27
  "@proteinjs/server-api": "1.3.3",
26
28
  "@proteinjs/ui": "2.2.0",
27
- "@proteinjs/user": "^1.0.32",
29
+ "@proteinjs/user": "^1.0.34",
28
30
  "moment": "2.29.4",
29
31
  "react": "18.2.0",
30
32
  "react-dom": "18.2.0"
@@ -42,5 +44,6 @@
42
44
  "typescript": "5.2.2"
43
45
  },
44
46
  "main": "./dist/generated/index.js",
45
- "types": "./dist/generated/index.d.ts"
46
- }
47
+ "types": "./dist/generated/index.d.ts",
48
+ "gitHead": "392402662a3066f07526c715703f2b381c899ed3"
49
+ }
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import { Page, Form, Fields, textField, FormButtons, FormPage } from '@proteinjs/ui';
3
+ import { routes } from '@proteinjs/user';
4
+ import { passwordResetPath } from './PasswordReset';
5
+
6
+ export const forgotPasswordPath = 'login/forgot-password';
7
+ export const forgotPasswordPage: Page = {
8
+ name: 'Forgot Password',
9
+ path: forgotPasswordPath,
10
+ auth: {
11
+ public: true,
12
+ },
13
+ component: () => (
14
+ <FormPage>
15
+ <Form<ForgotPasswordFields, typeof buttons>
16
+ name='Forgot Password'
17
+ createFields={() => new ForgotPasswordFields()}
18
+ fieldLayout={['email']}
19
+ buttons={buttons}
20
+ />
21
+ </FormPage>
22
+ ),
23
+ };
24
+
25
+ class ForgotPasswordFields extends Fields {
26
+ static create() {
27
+ return new ForgotPasswordFields();
28
+ }
29
+
30
+ email = textField<ForgotPasswordFields>({
31
+ name: 'email',
32
+ });
33
+ }
34
+
35
+ const buttons: FormButtons<ForgotPasswordFields> = {
36
+ submit: {
37
+ name: 'Submit',
38
+ style: {
39
+ color: 'primary',
40
+ variant: 'contained',
41
+ },
42
+ onClick: async (fields: ForgotPasswordFields, buttons: FormButtons<ForgotPasswordFields>) => {
43
+ const response = await fetch(routes.initiatePasswordReset.path, {
44
+ method: routes.initiatePasswordReset.method,
45
+ body: JSON.stringify({
46
+ email: fields.email.field.value,
47
+ resetPath: passwordResetPath,
48
+ }),
49
+ redirect: 'follow',
50
+ credentials: 'same-origin',
51
+ headers: {
52
+ 'Content-Type': 'application/json',
53
+ },
54
+ });
55
+ if (response.status != 200) {
56
+ throw new Error(`Failed to initiate forgot password.`);
57
+ }
58
+
59
+ const body = await response.json();
60
+ if (body.error) {
61
+ throw new Error(`Failed to initiate forgot password.`);
62
+ }
63
+
64
+ return `Successfully sent an email with a link to reset your password.`;
65
+ },
66
+ },
67
+ };
@@ -16,6 +16,7 @@ export const loginPage: Page = {
16
16
  createFields={() => new LoginFields()}
17
17
  fieldLayout={['email', 'password']}
18
18
  buttons={buttons}
19
+ maxWidth={'xs'}
19
20
  />
20
21
  </FormPage>
21
22
  ),
@@ -37,6 +38,16 @@ class LoginFields extends Fields {
37
38
  }
38
39
 
39
40
  const buttons: FormButtons<LoginFields> = {
41
+ forgotPassword: {
42
+ name: 'Forgot password',
43
+ style: {
44
+ variant: 'text',
45
+ align: 'left',
46
+ },
47
+ redirect: async () => {
48
+ return { path: '/login/forgot-password' };
49
+ },
50
+ },
40
51
  clear: clearButton,
41
52
  login: {
42
53
  name: 'Login',
@@ -0,0 +1,159 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { Page, Form, Fields, textField, FormButtons, FormPage } from '@proteinjs/ui';
3
+ import { routes } from '@proteinjs/user';
4
+ import { Button, Stack, Typography } from '@mui/material';
5
+
6
+ export const passwordResetPath = 'login/password-reset';
7
+ const PasswordResetComponent: React.FC = () => {
8
+ const [token, setToken] = useState('');
9
+ const [isValidating, setIsValidating] = useState(false);
10
+ const [validationError, setValidationError] = useState<string | null>(null);
11
+ const [resetSuccess, setResetSuccess] = useState(false);
12
+
13
+ const buttons: FormButtons<ResetPasswordFields> = {
14
+ submit: {
15
+ name: 'Reset Password',
16
+ style: {
17
+ color: 'primary',
18
+ variant: 'contained',
19
+ },
20
+ onClick: async (fields: ResetPasswordFields) => {
21
+ if (fields.newPassword.field.value !== fields.confirmPassword.field.value) {
22
+ throw new Error('Passwords do not match');
23
+ }
24
+
25
+ const response = await fetch(routes.executePasswordReset.path, {
26
+ method: routes.executePasswordReset.method,
27
+ body: JSON.stringify({
28
+ token: fields.token.field.value,
29
+ newPassword: fields.newPassword.field.value,
30
+ }),
31
+ credentials: 'same-origin',
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ },
35
+ });
36
+
37
+ if (response.status !== 200) {
38
+ throw new Error('Failed to reset password');
39
+ }
40
+
41
+ setResetSuccess(true);
42
+ return 'Your password has been successfully reset. You can now log in with your new password.';
43
+ },
44
+ },
45
+ };
46
+
47
+ useEffect(() => {
48
+ const searchParams = new URLSearchParams(window.location.search);
49
+ const resetToken = searchParams.get('token');
50
+ if (resetToken) {
51
+ setToken(resetToken);
52
+ validateToken(resetToken);
53
+ } else {
54
+ setValidationError('No reset token provided');
55
+ }
56
+ }, []);
57
+
58
+ const validateToken = async (token: string) => {
59
+ setIsValidating(true);
60
+ try {
61
+ const response = await fetch(`${routes.validateResetToken.path}?token=${token}`, {
62
+ method: routes.validateResetToken.method,
63
+ credentials: 'same-origin',
64
+ });
65
+ const data = await response.json();
66
+ if (!data.isValid) {
67
+ setValidationError(data.message || 'Invalid or expired token');
68
+ }
69
+ } catch (error) {
70
+ setValidationError('An error occurred while validating the token');
71
+ } finally {
72
+ setIsValidating(false);
73
+ }
74
+ };
75
+
76
+ if (isValidating) {
77
+ return <FormPage>Validating reset token...</FormPage>;
78
+ }
79
+
80
+ if (validationError) {
81
+ return (
82
+ <FormPage>
83
+ <Stack alignItems='center' spacing={3}>
84
+ <Typography variant='h1' gutterBottom>
85
+ Invalid password reset link
86
+ </Typography>
87
+ <Typography variant='body1' gutterBottom>
88
+ The password reset link is invalid or has expired. Please request a new password reset.
89
+ </Typography>
90
+ <Button variant='contained' color='primary' href='/login'>
91
+ Go to login page
92
+ </Button>
93
+ </Stack>
94
+ </FormPage>
95
+ );
96
+ }
97
+
98
+ if (resetSuccess) {
99
+ return (
100
+ <FormPage>
101
+ <Stack alignItems='center' spacing={3}>
102
+ <Typography variant='h6' gutterBottom>
103
+ Password reset successful
104
+ </Typography>
105
+ <Typography variant='body1' gutterBottom>
106
+ Your password has been successfully reset. You can now log in with your new password.
107
+ </Typography>
108
+ <Button variant='contained' color='primary' href='/login'>
109
+ Go to login page
110
+ </Button>
111
+ </Stack>
112
+ </FormPage>
113
+ );
114
+ }
115
+
116
+ return (
117
+ <FormPage>
118
+ <Form<ResetPasswordFields, typeof buttons>
119
+ name='Reset Password'
120
+ createFields={() => new ResetPasswordFields()}
121
+ fieldLayout={['newPassword', 'confirmPassword']}
122
+ buttons={buttons}
123
+ onLoad={async (fields) => {
124
+ fields.token.field.value = token;
125
+ }}
126
+ />
127
+ </FormPage>
128
+ );
129
+ };
130
+
131
+ export const passwordResetPage: Page = {
132
+ name: 'Reset Password',
133
+ path: passwordResetPath,
134
+ auth: {
135
+ public: true,
136
+ },
137
+ component: PasswordResetComponent,
138
+ };
139
+
140
+ class ResetPasswordFields extends Fields {
141
+ static create() {
142
+ return new ResetPasswordFields();
143
+ }
144
+
145
+ token = textField<ResetPasswordFields>({
146
+ name: 'token',
147
+ accessibility: { hidden: true },
148
+ });
149
+
150
+ newPassword = textField<ResetPasswordFields>({
151
+ name: 'New Password',
152
+ isPassword: true,
153
+ });
154
+
155
+ confirmPassword = textField<ResetPasswordFields>({
156
+ name: 'Confirm New Password',
157
+ isPassword: true,
158
+ });
159
+ }