@things-factory/auth-ui 8.0.0-beta.9 → 8.0.2

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 (100) hide show
  1. package/client/auth-style-sign.ts +194 -0
  2. package/client/bootstrap.ts +51 -0
  3. package/client/components/abstract-auth-page.ts +301 -0
  4. package/client/components/abstract-password-reset.ts +168 -0
  5. package/client/components/abstract-sign.ts +127 -0
  6. package/client/components/change-password.ts +153 -0
  7. package/client/components/contact-us.ts +113 -0
  8. package/client/components/create-domain-popup.ts +141 -0
  9. package/client/components/create-role.ts +123 -0
  10. package/client/components/create-user.ts +95 -0
  11. package/client/components/credential-manager.ts +64 -0
  12. package/client/components/delete-user-popup.ts +117 -0
  13. package/client/components/domain-switch.ts +127 -0
  14. package/client/components/invite-customer.ts +104 -0
  15. package/client/components/invite-user.ts +96 -0
  16. package/client/components/my-login-history.ts +101 -0
  17. package/client/components/ownership-transfer-popup.ts +110 -0
  18. package/client/components/partner-info-card.ts +89 -0
  19. package/client/components/partner-role-editor.ts +153 -0
  20. package/client/components/profile-component.ts +332 -0
  21. package/client/components/role-edit-form.ts +92 -0
  22. package/client/components/role-privilege-editor.ts +267 -0
  23. package/client/components/role-selector.ts +102 -0
  24. package/client/components/user-role-editor.ts +499 -0
  25. package/client/constants/application.ts +9 -0
  26. package/client/constants/index.ts +1 -0
  27. package/client/entries/auth/activate.ts +272 -0
  28. package/client/entries/auth/checkin.ts +190 -0
  29. package/client/entries/auth/forgot-password.ts +103 -0
  30. package/client/entries/auth/reset-password.ts +22 -0
  31. package/client/entries/auth/result.ts +193 -0
  32. package/client/entries/auth/signin.ts +18 -0
  33. package/client/entries/auth/signup.ts +109 -0
  34. package/client/entries/auth/unlock-user.ts +22 -0
  35. package/client/entries/oauth2/oauth2-decision-error-page.ts +50 -0
  36. package/client/entries/oauth2/oauth2-decision-page.ts +196 -0
  37. package/client/entries/public/home.ts +246 -0
  38. package/client/index.ts +124 -0
  39. package/client/pages/app-binding/app-binding.ts +423 -0
  40. package/client/pages/app-binding/app-bindings.ts +171 -0
  41. package/client/pages/appliance/appliance.ts +452 -0
  42. package/client/pages/appliance/home.ts +177 -0
  43. package/client/pages/appliance/register.ts +183 -0
  44. package/client/pages/application/application.ts +428 -0
  45. package/client/pages/application/applications.ts +182 -0
  46. package/client/pages/application/register.ts +211 -0
  47. package/client/pages/attribute/attribute-set-item-list.ts +237 -0
  48. package/client/pages/attribute/attribute-set-management.ts +282 -0
  49. package/client/pages/auth-provider/auth-provider-management.ts +381 -0
  50. package/client/pages/domain/domain-management.ts +410 -0
  51. package/client/pages/partner/partner-management.ts +112 -0
  52. package/client/pages/profile.ts +32 -0
  53. package/client/pages/role/role-management.ts +134 -0
  54. package/client/pages/user/user-management.ts +224 -0
  55. package/client/route.ts +67 -0
  56. package/client/themes/auth-theme.css +65 -0
  57. package/client/utils/password-rule.ts +37 -0
  58. package/dist-client/components/abstract-auth-page.js +10 -10
  59. package/dist-client/components/abstract-auth-page.js.map +1 -1
  60. package/dist-client/components/abstract-password-reset.d.ts +2 -1
  61. package/dist-client/components/abstract-password-reset.js +14 -7
  62. package/dist-client/components/abstract-password-reset.js.map +1 -1
  63. package/dist-client/components/abstract-sign.js +11 -12
  64. package/dist-client/components/abstract-sign.js.map +1 -1
  65. package/dist-client/components/contact-us.d.ts +1 -1
  66. package/dist-client/components/contact-us.js +7 -10
  67. package/dist-client/components/contact-us.js.map +1 -1
  68. package/dist-client/components/create-user.js +5 -28
  69. package/dist-client/components/create-user.js.map +1 -1
  70. package/dist-client/components/invite-user.js +11 -19
  71. package/dist-client/components/invite-user.js.map +1 -1
  72. package/dist-client/components/ownership-transfer-popup.js +3 -3
  73. package/dist-client/components/ownership-transfer-popup.js.map +1 -1
  74. package/dist-client/components/profile-component.d.ts +1 -5
  75. package/dist-client/components/profile-component.js +4 -64
  76. package/dist-client/components/profile-component.js.map +1 -1
  77. package/dist-client/components/role-privilege-editor.js +1 -2
  78. package/dist-client/components/role-privilege-editor.js.map +1 -1
  79. package/dist-client/components/user-role-editor.js +18 -18
  80. package/dist-client/components/user-role-editor.js.map +1 -1
  81. package/dist-client/entries/auth/checkin.js +1 -1
  82. package/dist-client/entries/auth/checkin.js.map +1 -1
  83. package/dist-client/entries/auth/forgot-password.js +2 -11
  84. package/dist-client/entries/auth/forgot-password.js.map +1 -1
  85. package/dist-client/entries/auth/signup.js +7 -13
  86. package/dist-client/entries/auth/signup.js.map +1 -1
  87. package/dist-client/index.js +1 -1
  88. package/dist-client/index.js.map +1 -1
  89. package/dist-client/pages/user/user-management.d.ts +1 -5
  90. package/dist-client/pages/user/user-management.js +7 -6
  91. package/dist-client/pages/user/user-management.js.map +1 -1
  92. package/dist-client/tsconfig.tsbuildinfo +1 -1
  93. package/dist-server/tsconfig.tsbuildinfo +1 -1
  94. package/package.json +12 -12
  95. package/server/index.ts +0 -0
  96. package/translations/en.json +2 -6
  97. package/translations/ja.json +2 -6
  98. package/translations/ko.json +2 -6
  99. package/translations/ms.json +2 -6
  100. package/translations/zh.json +2 -6
@@ -0,0 +1,272 @@
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+
4
+ import '@operato/i18n/ox-i18n.js'
5
+ import '@operato/layout/ox-snack-bar.js'
6
+ import '@operato/lottie-player'
7
+ import '../../components/contact-us'
8
+
9
+ import { css, html, LitElement } from 'lit'
10
+ import { customElement, property, query } from 'lit/decorators.js'
11
+
12
+ import { i18next, localize } from '@operato/i18n'
13
+
14
+ @customElement('auth-activate')
15
+ export class AuthActivate extends localize(i18next)(LitElement) {
16
+ static styles = [
17
+ css`
18
+ :host {
19
+ display: flex;
20
+ width: 100vw;
21
+ height: 100vh;
22
+ height: 100dvh;
23
+ background-color: var(--md-sys-color-primary);
24
+ color: var(--md-sys-color-on-primary);
25
+ }
26
+
27
+ .wrap {
28
+ display: block;
29
+ width: 450px;
30
+ min-width: 350px;
31
+ margin: 0 auto;
32
+ text-align: center;
33
+ }
34
+
35
+ .auth-brand {
36
+ color: #fff;
37
+ }
38
+
39
+ .auth-brand img {
40
+ margin: 15% auto 5px auto;
41
+ width: 100px;
42
+ border: 3px solid var(--md-sys-color-on-primary);
43
+ border-radius: 25px;
44
+ box-shadow: var(--box-shadow);
45
+ }
46
+
47
+ .name {
48
+ display: block;
49
+ font: var(--auth-brand-name);
50
+ text-shadow: var(--auth-brand-name-shadow);
51
+ }
52
+
53
+ h1 {
54
+ margin: 50px 0 0 0;
55
+ padding: 0;
56
+ font-size: 24px;
57
+ color: var(--auth-title-color, var(--md-sys-color-on-primary));
58
+ }
59
+
60
+ p {
61
+ margin: 0;
62
+ padding: var(--auth-description-padding);
63
+ font: var(--auth-description-font);
64
+ color: var(--auth-description-color, var(--md-sys-color-on-secondary));
65
+ }
66
+
67
+ #button-area {
68
+ border-top: 1px dashed #ccc;
69
+ padding-top: 10px;
70
+ }
71
+
72
+ md-elevated-button {
73
+ --md-elevated-button-horizontal-padding: var(--spacing-medium);
74
+ --md-elevated-button-ink-color: var(--md-sys-color-primary);
75
+ }
76
+
77
+ contact-us {
78
+ display: flex;
79
+ padding: 50px;
80
+ flex-direction: column;
81
+ }
82
+
83
+ .lottie-container {
84
+ width: 100%;
85
+ height: 300px;
86
+ position: absolute;
87
+ left: 0;
88
+ bottom: 0;
89
+ pointer-events: none;
90
+ }
91
+
92
+ .lottie-container lottie-player {
93
+ position: absolute;
94
+ bottom: -6%;
95
+ width: 100%;
96
+ height: auto;
97
+ }
98
+
99
+ @media (max-width: 450px) {
100
+ .wrap {
101
+ width: 85%;
102
+ min-width: 320px;
103
+ padding-bottom: 100px;
104
+ }
105
+
106
+ .auth-form {
107
+ grid-template-columns: 1fr;
108
+ }
109
+
110
+ .auth-brand img {
111
+ margin: 12% auto 5px auto;
112
+ width: 75px;
113
+ }
114
+
115
+ .lottie-container {
116
+ overflow: hidden;
117
+ height: 200px;
118
+ pointer-events: none;
119
+ }
120
+
121
+ .lottie-container lottie-player {
122
+ width: 1200px;
123
+ left: -30%;
124
+ }
125
+ }
126
+ `
127
+ ]
128
+
129
+ @property({ type: Object }) data: any
130
+ @property({ type: String }) email?: string | null
131
+
132
+ @query('#form') form!: HTMLFormElement
133
+
134
+ private _applicationMeta?: { icon?: string; title?: string; description?: string }
135
+
136
+ render() {
137
+ var { icon, title, description } = this.applicationMeta
138
+
139
+ return html`
140
+ <div class="wrap">
141
+ <div class="auth-brand">
142
+ <img src=${icon} />
143
+ <strong class="name">${title}</strong>
144
+ <span class="welcome-msg">${description}</span>
145
+ </div>
146
+
147
+ <h1><ox-i18n msgid="text.your account is not activated"></ox-i18n></h1>
148
+
149
+ <!--description message container-->
150
+ <p></p>
151
+
152
+ <form
153
+ id="form"
154
+ action="/auth/resend-verification-email"
155
+ method="POST"
156
+ @submit=${e => {
157
+ this.requestResend(e)
158
+ }}
159
+ hidden
160
+ >
161
+ <input name="email" type="hidden" .value=${this.email || ''} required />
162
+ <button id="submit-button" type="submit"><ox-i18n msgid="label.change password"></ox-i18n></button>
163
+ </form>
164
+
165
+ <div id="button-area">
166
+ <md-elevated-button @click=${e => this.requestResend(e)}>
167
+ <md-icon slot="icon">mail_outline</md-icon>
168
+ ${i18next.t('label.send activation email')}
169
+ </md-elevated-button>
170
+ <md-elevated-button
171
+ @click=${e => {
172
+ window.location.replace('/auth/signin')
173
+ }}
174
+ >
175
+ <md-icon slot="icon">home</md-icon>
176
+ ${i18next.t('button.go to home')}
177
+ </md-elevated-button>
178
+ </div>
179
+ <contact-us></contact-us>
180
+
181
+ <!--lottie animation begin-->
182
+ <div class="lottie-container">
183
+ <lottie-player autoplay loop src="../../assets/images/background-animation.json"></lottie-player>
184
+ </div>
185
+ <!--lottie animation end-->
186
+ </div>
187
+
188
+ <ox-snack-bar id="snackbar"></ox-snack-bar>
189
+ `
190
+ }
191
+
192
+ get applicationMeta() {
193
+ if (!this._applicationMeta) {
194
+ var iconLink: HTMLLinkElement | null = document.querySelector('link[rel="application-icon"]')
195
+ var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-name"]')
196
+ var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-description"]')
197
+
198
+ this._applicationMeta = {
199
+ icon: iconLink?.href,
200
+ title: titleMeta ? titleMeta.content : 'Things Factory',
201
+ description: descriptionMeta ? descriptionMeta.content : 'Reimagining Software'
202
+ }
203
+ }
204
+
205
+ return this._applicationMeta
206
+ }
207
+
208
+ firstUpdated() {
209
+ var searchParams = new URLSearchParams(window.location.search)
210
+ this.email = searchParams.get('email')
211
+ }
212
+
213
+ updated(changed) {
214
+ if (changed.has('data')) {
215
+ this.email = this.data?.email
216
+ }
217
+ }
218
+
219
+ async requestResend(e) {
220
+ var timer
221
+ var formData = new FormData(this.form)
222
+ var button = e.target
223
+ try {
224
+ var controller = new AbortController()
225
+ var signal = controller.signal
226
+
227
+ button.disabled = true
228
+ timer = setTimeout(() => {
229
+ controller.abort()
230
+ throw new Error('timeout')
231
+ }, 30 * 1000)
232
+
233
+ var response = await fetch('/auth/resend-verification-email', {
234
+ credentials: 'include',
235
+ method: 'POST',
236
+ headers: {
237
+ 'Content-Type': 'application/json'
238
+ },
239
+ body: JSON.stringify(Object.fromEntries(formData.entries())),
240
+ signal
241
+ })
242
+
243
+ if (response) {
244
+ this.showSnackbar({
245
+ level: response.ok ? 'info' : 'error',
246
+ message: await response.text()
247
+ })
248
+ }
249
+ } catch (e) {
250
+ } finally {
251
+ button.disabled = false
252
+ clearTimeout(timer)
253
+ }
254
+ }
255
+
256
+ showSnackbar({ level, message, timer = 3000 }: { level: 'info' | 'error'; message: string; timer?: number }) {
257
+ const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {
258
+ level: 'info' | 'error'
259
+ message: string
260
+ active: boolean
261
+ }
262
+
263
+ snackbar.level = level
264
+ snackbar.message = message
265
+ snackbar.active = true
266
+
267
+ if (timer > -1)
268
+ setTimeout(() => {
269
+ snackbar.active = false
270
+ }, timer)
271
+ }
272
+ }
@@ -0,0 +1,190 @@
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+
4
+ import '@operato/lottie-player'
5
+
6
+ import { css, html, LitElement } from 'lit'
7
+ import { customElement, property } from 'lit/decorators.js'
8
+
9
+ import { i18next, localize } from '@operato/i18n'
10
+ import { ScrollbarStyles } from '@operato/styles'
11
+ import { isSafari } from '@operato/utils'
12
+
13
+ import { AUTH_STYLE_SIGN } from '../../auth-style-sign'
14
+
15
+ @customElement('auth-checkin')
16
+ export class AuthCheckIn extends localize(i18next)(LitElement) {
17
+ static styles = [
18
+ ScrollbarStyles,
19
+ css`
20
+ :host {
21
+ display: flex;
22
+ flex-direction: column;
23
+ margin: auto;
24
+ background-color: var(--md-sys-color-primary);
25
+ color: var(--md-sys-color-on-primary);
26
+ height: 100vh;
27
+ height: 100dvh;
28
+ }
29
+
30
+ .header {
31
+ background-color: var(--md-sys-color-primary);
32
+ color: var(--md-sys-color-on-primary);
33
+ height: var(--checkin-header-height);
34
+ }
35
+
36
+ .content {
37
+ flex: 1;
38
+ overflow: auto;
39
+ }
40
+
41
+ .domains {
42
+ margin: var(--spacing-large) 0;
43
+ padding: 0;
44
+ background-color: var(--md-sys-color-surface);
45
+ color: var(--md-sys-color-on-surface);
46
+ border-radius: var(--border-radius);
47
+ border: var(--border-dim-color);
48
+ list-style: none;
49
+ }
50
+
51
+ li {
52
+ border-bottom: var(--border-dim-color);
53
+ padding: var(--spacing-medium) var(--spacing-large);
54
+ font-size: 18px;
55
+ text-align: left;
56
+
57
+ cursor: pointer;
58
+ }
59
+
60
+ li:hover {
61
+ background-color: var(--md-sys-color-primary-container);
62
+ color: var(--md-sys-color-on-primary-container);
63
+ }
64
+
65
+ li span {
66
+ display: block;
67
+ font: normal var(--fontsize-default) var(--theme-font);
68
+ }
69
+
70
+ li md-icon {
71
+ float: right;
72
+ margin: 10px 0 0 0;
73
+ opacity: 0.5;
74
+ }
75
+
76
+ .button-container {
77
+ text-align: center;
78
+ }
79
+
80
+ .button-container md-elevated-button {
81
+ margin-left: var(--spacing-small);
82
+ }
83
+
84
+ @media (max-width: 450px) {
85
+ .button-container md-elevated-button {
86
+ width: 100%;
87
+ margin: var(--spacing-medium) 0 0 0;
88
+ }
89
+ }
90
+ `,
91
+ AUTH_STYLE_SIGN
92
+ ]
93
+
94
+ @property({ type: Object }) data: any
95
+ @property({ type: Array }) domains: any[] = []
96
+ @property({ type: String }) domainType?: string
97
+ @property({ type: Object }) user: any
98
+
99
+ private _applicationMeta?: { icon?: string; title?: string; description?: string }
100
+ private redirectTo?: string
101
+
102
+ render() {
103
+ var { icon, title, description } = this.applicationMeta
104
+
105
+ return html`
106
+ <div class="content md-typescale-display-medium">
107
+ <div class="wrap">
108
+ <div class="auth-brand">
109
+ <img src=${icon || ''} />
110
+ <strong class="name">${title}</strong>
111
+ <span class="welcome-msg">${description}</span>
112
+ </div>
113
+
114
+ <h3>${i18next.t('label.select_domain')}</h3>
115
+
116
+ ${this.domains?.length
117
+ ? html`
118
+ <ul class="domains">
119
+ ${this.domains.map(
120
+ domain => html`
121
+ <li
122
+ @click=${() =>
123
+ (location.href = `/auth/checkin/${domain.subdomain}?redirect_to=${encodeURIComponent(this.redirectTo || '/')}`)}
124
+ >
125
+ <md-icon>keyboard_arrow_right</md-icon>
126
+ <strong>${domain.name}</strong>
127
+ <span>${domain.description}&nbsp;</span>
128
+ </li>
129
+ `
130
+ )}
131
+ </ul>
132
+ `
133
+ : html` <h3>${i18next.t('text.no domain available')}</h3> `}
134
+
135
+ <div class="button-container">
136
+ <md-elevated-button @click=${() => (location.pathname = '/auth/signout')}
137
+ >${String(i18next.t('button.logout'))}</md-elevated-button
138
+ >
139
+
140
+ ${this.domainType?.toLowerCase() === 'company'
141
+ ? html`<md-elevated-button
142
+ @click=${e => (location.href = `/public/business-register?email=${this.user?.email}`)}
143
+ >${String(i18next.t('button.register business domain'))}</md-elevated-button
144
+ > `
145
+ : ''}
146
+ </div>
147
+
148
+ ${isSafari()
149
+ ? html``
150
+ : html`
151
+ <div class="lottie-container">
152
+ <lottie-player autoplay loop src="../../assets/images/background-animation.json"></lottie-player>
153
+ </div>
154
+ `}
155
+ </div>
156
+ </div>
157
+ `
158
+ }
159
+
160
+ updated(changed) {
161
+ if (changed.has('data')) {
162
+ this.domains = this.data.domains
163
+ this.user = this.data.user
164
+ this.domainType = this.data.domainType
165
+ this.redirectTo = this.data.redirectTo
166
+
167
+ this.requestUpdate()
168
+ }
169
+ }
170
+
171
+ navigateToUrl(url) {
172
+ location.pathname = url
173
+ }
174
+
175
+ get applicationMeta() {
176
+ if (!this._applicationMeta) {
177
+ var iconLink: HTMLLinkElement | null = document.querySelector('link[rel="application-icon"]')
178
+ var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-name"]')
179
+ var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-description"]')
180
+
181
+ this._applicationMeta = {
182
+ icon: iconLink?.href,
183
+ title: titleMeta ? titleMeta.content : 'Things Factory',
184
+ description: descriptionMeta ? descriptionMeta.content : 'Reimagining Software'
185
+ }
186
+ }
187
+
188
+ return this._applicationMeta
189
+ }
190
+ }
@@ -0,0 +1,103 @@
1
+ import '@material/web/button/elevated-button.js'
2
+ import '@material/web/button/text-button.js'
3
+
4
+ import '@operato/i18n/ox-i18n.js'
5
+ import '../../components/profile-component'
6
+
7
+ import { html } from 'lit'
8
+ import { customElement, query } from 'lit/decorators.js'
9
+
10
+ import { i18next } from '@operato/i18n'
11
+
12
+ import { AbstractAuthPage } from '../../components/abstract-auth-page'
13
+
14
+ @customElement('forgot-password')
15
+ export class ForgotPassword extends AbstractAuthPage {
16
+ @query('#email') emailInput!: HTMLInputElement
17
+ @query('#submit-button') button!: HTMLInputElement
18
+
19
+ get pageName() {
20
+ return 'forgot password'
21
+ }
22
+
23
+ get actionUrl() {
24
+ return '/auth/forgot-password'
25
+ }
26
+
27
+ get formfields() {
28
+ const email = this.data?.email || ''
29
+
30
+ return html`
31
+ <div class="field">
32
+ <md-filled-text-field
33
+ name="email"
34
+ type="email"
35
+ label=${String(i18next.t('label.email'))}
36
+ .value=${email}
37
+ required
38
+ @input=${(e: Event) => {
39
+ const target = e.target as HTMLInputElement
40
+ if (target.validity.typeMismatch) {
41
+ target.setCustomValidity(i18next.t('text.invalid-email'))
42
+ } else {
43
+ target.setCustomValidity('')
44
+ }
45
+ }}
46
+ ></md-filled-text-field>
47
+ </div>
48
+ <md-elevated-button id="submit-button" class="ui button" type="submit" @click=${e => this._onSubmit(e)}>
49
+ <ox-i18n msgid="button.submit"></ox-i18n>
50
+ </md-elevated-button>
51
+ `
52
+ }
53
+
54
+ get links() {
55
+ return html`
56
+ <a class="link" href="/auth/signin">
57
+ <md-text-button><ox-i18n msgid="field.sign in"></ox-i18n></md-text-button>
58
+ </a>
59
+ `
60
+ }
61
+
62
+ async submit() {
63
+ var timer
64
+ var formData = new FormData(this.formEl)
65
+
66
+ try {
67
+ var controller = new AbortController()
68
+ var signal = controller.signal
69
+
70
+ this.button.disabled = true
71
+ timer = setTimeout(() => {
72
+ controller.abort()
73
+ throw new Error('timeout')
74
+ }, 30 * 1000)
75
+
76
+ var response = await fetch('/auth/forgot-password', {
77
+ credentials: 'include',
78
+ method: 'POST',
79
+ headers: {
80
+ 'Content-Type': 'application/json'
81
+ },
82
+ body: JSON.stringify(Object.fromEntries(formData.entries())),
83
+ signal
84
+ })
85
+
86
+ this.showSnackbar({
87
+ message: await response.text(),
88
+ level: response.ok ? 'info' : 'error'
89
+ })
90
+ } catch (e) {
91
+ } finally {
92
+ this.button.disabled = false
93
+ clearTimeout(timer)
94
+ }
95
+ }
96
+
97
+ showSnackbar({ message, level }) {
98
+ super.showSnackbar({
99
+ level,
100
+ message
101
+ })
102
+ }
103
+ }
@@ -0,0 +1,22 @@
1
+ import { customElement } from 'lit/decorators.js'
2
+
3
+ import { AbstractPasswordReset } from '../../components/abstract-password-reset'
4
+
5
+ @customElement('reset-password')
6
+ export class ResetPassword extends AbstractPasswordReset {
7
+ get pageName() {
8
+ return 'reset password'
9
+ }
10
+
11
+ get actionUrl() {
12
+ return '/auth/reset-password'
13
+ }
14
+
15
+ get submitButtonLabel() {
16
+ return 'label.change password'
17
+ }
18
+
19
+ get title() {
20
+ return 'reset password'
21
+ }
22
+ }