@things-factory/auth-ui 6.2.8 → 6.2.10
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/client/components/abstract-auth-page.ts +34 -27
- package/client/components/abstract-password-reset.ts +22 -18
- package/client/components/profile-component.ts +8 -3
- package/client/components/role-privilege-editor.ts +2 -2
- package/client/entries/auth/checkin.ts +3 -3
- package/client/entries/auth/forgot-password.ts +1 -1
- package/client/entries/auth/signup.ts +15 -9
- package/dist-client/components/abstract-auth-page.js +33 -27
- package/dist-client/components/abstract-auth-page.js.map +1 -1
- package/dist-client/components/abstract-password-reset.js +22 -18
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/profile-component.d.ts +5 -1
- package/dist-client/components/profile-component.js +13 -3
- package/dist-client/components/profile-component.js.map +1 -1
- package/dist-client/components/role-privilege-editor.js +2 -2
- package/dist-client/components/role-privilege-editor.js.map +1 -1
- package/dist-client/entries/auth/checkin.js +3 -3
- package/dist-client/entries/auth/checkin.js.map +1 -1
- package/dist-client/entries/auth/forgot-password.js +1 -1
- package/dist-client/entries/auth/forgot-password.js.map +1 -1
- package/dist-client/entries/auth/signup.js +15 -9
- package/dist-client/entries/auth/signup.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -7,8 +7,8 @@ import '@operato/i18n/ox-i18n.js'
|
|
|
7
7
|
import '@operato/i18n/ox-i18n-selector.js'
|
|
8
8
|
import '@operato/layout/ox-snack-bar.js'
|
|
9
9
|
|
|
10
|
-
import { css, html, LitElement } from 'lit'
|
|
11
|
-
import { property, query } from 'lit/decorators.js'
|
|
10
|
+
import { css, html, LitElement, nothing } from 'lit'
|
|
11
|
+
import { property, query, state } from 'lit/decorators.js'
|
|
12
12
|
|
|
13
13
|
import { i18next, localize } from '@operato/i18n'
|
|
14
14
|
import { ScrollbarStyles } from '@operato/styles'
|
|
@@ -79,6 +79,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
render() {
|
|
82
|
+
const { disableUserFavoredLanguage, languages } = this.data || {}
|
|
82
83
|
var { icon, title, description } = this.applicationMeta
|
|
83
84
|
|
|
84
85
|
return html`
|
|
@@ -96,7 +97,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
96
97
|
<form
|
|
97
98
|
id="form"
|
|
98
99
|
action="${this.actionUrl}"
|
|
99
|
-
method="
|
|
100
|
+
method="post"
|
|
100
101
|
@keypress=${e => {
|
|
101
102
|
if (e.key == 'Enter') this._onSubmit(e)
|
|
102
103
|
}}
|
|
@@ -104,19 +105,22 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
104
105
|
${this.formfields}
|
|
105
106
|
</form>
|
|
106
107
|
${this.links}
|
|
107
|
-
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
${!disableUserFavoredLanguage
|
|
109
|
+
? html` <div id="locale-area">
|
|
110
|
+
<label for="locale-selector"><mwc-icon>language</mwc-icon></label>
|
|
111
|
+
<ox-i18n-selector
|
|
112
|
+
id="locale-selector"
|
|
113
|
+
value=${i18next.language || 'en-US'}
|
|
114
|
+
.languages=${languages}
|
|
115
|
+
@change=${e => {
|
|
116
|
+
var locale = e.detail
|
|
117
|
+
if (!locale) return
|
|
118
|
+
|
|
119
|
+
i18next.changeLanguage(locale)
|
|
120
|
+
}}
|
|
121
|
+
></ox-i18n-selector>
|
|
122
|
+
</div>`
|
|
123
|
+
: nothing}
|
|
120
124
|
</div>
|
|
121
125
|
</div>
|
|
122
126
|
|
|
@@ -168,10 +172,10 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
168
172
|
<mwc-textfield
|
|
169
173
|
name="email"
|
|
170
174
|
type="email"
|
|
171
|
-
label=${i18next.t('field.email')}
|
|
175
|
+
label=${String(i18next.t('field.email'))}
|
|
172
176
|
required
|
|
173
177
|
.value=${email}
|
|
174
|
-
.validationMessage=${i18next.t('text.invalid-email')}
|
|
178
|
+
.validationMessage=${String(i18next.t('text.invalid-email'))}
|
|
175
179
|
autocomplete="username"
|
|
176
180
|
autocapitalize="off"
|
|
177
181
|
></mwc-textfield>
|
|
@@ -180,7 +184,7 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
180
184
|
<mwc-textfield
|
|
181
185
|
name="password"
|
|
182
186
|
type="password"
|
|
183
|
-
label=${i18next.t('field.password')}
|
|
187
|
+
label=${String(i18next.t('field.password'))}
|
|
184
188
|
autocomplete="current-password"
|
|
185
189
|
required
|
|
186
190
|
></mwc-textfield>
|
|
@@ -193,16 +197,19 @@ export abstract class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
193
197
|
}
|
|
194
198
|
|
|
195
199
|
get links() {
|
|
196
|
-
const ssoLinks = this.data
|
|
200
|
+
const { disableUserSignupProcess, ssoLinks = [] } = this.data || {}
|
|
197
201
|
|
|
198
202
|
return html`
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
${!disableUserSignupProcess
|
|
204
|
+
? html`
|
|
205
|
+
<a class="link" href="/auth/signup">
|
|
206
|
+
<mwc-button icon="add_task"><ox-i18n msgid="field.sign up"></ox-i18n></mwc-button>
|
|
207
|
+
</a>
|
|
208
|
+
<a class="link" href="/auth/forgot-password">
|
|
209
|
+
<mwc-button icon="lock_open"><ox-i18n msgid="field.forgot-password"></ox-i18n></mwc-button>
|
|
210
|
+
</a>
|
|
211
|
+
`
|
|
212
|
+
: nothing}
|
|
206
213
|
${ssoLinks.map(
|
|
207
214
|
sso => html`
|
|
208
215
|
<a class="link" href=${sso.link}>
|
|
@@ -6,7 +6,7 @@ import '@operato/i18n/ox-i18n.js'
|
|
|
6
6
|
import '@operato/i18n/ox-i18n-selector.js'
|
|
7
7
|
import '@operato/layout/ox-snack-bar.js'
|
|
8
8
|
|
|
9
|
-
import { css, html } from 'lit'
|
|
9
|
+
import { css, html, nothing } from 'lit'
|
|
10
10
|
import { property, query } from 'lit/decorators.js'
|
|
11
11
|
|
|
12
12
|
import { i18next } from '@operato/i18n'
|
|
@@ -55,6 +55,7 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
55
55
|
|
|
56
56
|
render() {
|
|
57
57
|
var { icon, title, description } = this.applicationMeta
|
|
58
|
+
const { disableUserFavoredLanguage, languages } = this.data || {}
|
|
58
59
|
|
|
59
60
|
return html`
|
|
60
61
|
<div class="wrap">
|
|
@@ -69,17 +70,17 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
69
70
|
<form
|
|
70
71
|
id="form"
|
|
71
72
|
action="${this.actionUrl}"
|
|
72
|
-
method="
|
|
73
|
+
method="post"
|
|
73
74
|
@keypress=${e => {
|
|
74
75
|
if (e.key == 'Enter') this._onSubmit(e)
|
|
75
76
|
}}
|
|
76
77
|
>
|
|
77
|
-
<input name="token" type="hidden" .value=${this.token} required />
|
|
78
|
+
<input name="token" type="hidden" .value=${this.token || ''} required />
|
|
78
79
|
<div class="field">
|
|
79
80
|
<mwc-textfield
|
|
80
81
|
name="password"
|
|
81
82
|
type="password"
|
|
82
|
-
label=${i18next.t('label.password')}
|
|
83
|
+
label=${String(i18next.t('label.password'))}
|
|
83
84
|
.pattern=${this.passwordPattern}
|
|
84
85
|
helper=${this.passwordHelp}
|
|
85
86
|
helperPersistent
|
|
@@ -96,7 +97,7 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
96
97
|
id="confirm-password"
|
|
97
98
|
name="confirm-password"
|
|
98
99
|
type="password"
|
|
99
|
-
label=${i18next.t('field.confirm password')}
|
|
100
|
+
label=${String(i18next.t('field.confirm password'))}
|
|
100
101
|
required
|
|
101
102
|
></mwc-textfield>
|
|
102
103
|
</div>
|
|
@@ -105,19 +106,22 @@ export abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
105
106
|
<ox-i18n msgid="${this.submitButtonLabel}"></ox-i18n>
|
|
106
107
|
</mwc-button>
|
|
107
108
|
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
${!disableUserFavoredLanguage
|
|
110
|
+
? html` <div id="locale-area">
|
|
111
|
+
<label for="locale-selector"><mwc-icon>language</mwc-icon></label>
|
|
112
|
+
<ox-i18n-selector
|
|
113
|
+
id="locale-selector"
|
|
114
|
+
value=${i18next.language || 'en-US'}
|
|
115
|
+
.languages=${languages}
|
|
116
|
+
@change=${e => {
|
|
117
|
+
var locale = e.detail
|
|
118
|
+
if (!locale) return
|
|
119
|
+
|
|
120
|
+
i18next.changeLanguage(locale)
|
|
121
|
+
}}
|
|
122
|
+
></ox-i18n-selector>
|
|
123
|
+
</div>`
|
|
124
|
+
: nothing}
|
|
121
125
|
</form>
|
|
122
126
|
</div>
|
|
123
127
|
</div>
|
|
@@ -5,11 +5,11 @@ import './delete-user-popup'
|
|
|
5
5
|
import './my-login-history'
|
|
6
6
|
|
|
7
7
|
import { css, html, LitElement } from 'lit'
|
|
8
|
-
import { customElement, property, query } from 'lit/decorators.js'
|
|
8
|
+
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
9
9
|
|
|
10
10
|
import { i18next, localize } from '@operato/i18n'
|
|
11
11
|
import { notify, openPopup } from '@operato/layout'
|
|
12
|
-
import { auth } from '@things-factory/auth-base/dist-client'
|
|
12
|
+
import { auth, getLanguages } from '@things-factory/auth-base/dist-client'
|
|
13
13
|
|
|
14
14
|
@customElement('profile-component')
|
|
15
15
|
export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
@@ -109,15 +109,19 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
109
109
|
@property({ type: String }) email?: string
|
|
110
110
|
@property({ type: String }) name?: string
|
|
111
111
|
|
|
112
|
+
@state() languages: { code: string; display: string }[] = []
|
|
113
|
+
|
|
112
114
|
@query('#name') nameEl!: HTMLInputElement
|
|
113
115
|
@query('#locale') localeEl!: HTMLInputElement
|
|
114
116
|
|
|
115
|
-
firstUpdated() {
|
|
117
|
+
async firstUpdated() {
|
|
116
118
|
auth.on('profile', ({ credential }) => {
|
|
117
119
|
this.setCredential(credential)
|
|
118
120
|
})
|
|
119
121
|
|
|
120
122
|
this.setCredential(auth.credential)
|
|
123
|
+
|
|
124
|
+
this.languages = await getLanguages()
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
setCredential(credential) {
|
|
@@ -145,6 +149,7 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
|
|
|
145
149
|
id="locale"
|
|
146
150
|
@change=${e => this.onLocaleChanged(e.detail)}
|
|
147
151
|
value=${i18next.language || 'en-US'}
|
|
152
|
+
.languages=${this.languages}
|
|
148
153
|
></ox-i18n-selector>
|
|
149
154
|
|
|
150
155
|
<hr />
|
|
@@ -107,12 +107,12 @@ class RolePrivilegeEditor extends localize(i18next)(LitElement) {
|
|
|
107
107
|
</ul>
|
|
108
108
|
|
|
109
109
|
<div buttons>
|
|
110
|
-
<mwc-button @click=${e => this.onSave()} outlined label
|
|
110
|
+
<mwc-button @click=${e => this.onSave()} outlined label=${String(i18next.t('button.save'))}></mwc-button>
|
|
111
111
|
<mwc-button
|
|
112
112
|
@click=${e => this.onDeleteRole()}
|
|
113
113
|
raised
|
|
114
114
|
danger
|
|
115
|
-
label
|
|
115
|
+
label=${String(i18next.t('button.delete role'))}
|
|
116
116
|
></mwc-button>
|
|
117
117
|
</div>
|
|
118
118
|
`
|
|
@@ -96,7 +96,7 @@ export class AuthCheckIn extends localize(i18next)(LitElement) {
|
|
|
96
96
|
<div class="content">
|
|
97
97
|
<div class="wrap">
|
|
98
98
|
<div class="auth-brand">
|
|
99
|
-
<img src=${icon} />
|
|
99
|
+
<img src=${icon || ''} />
|
|
100
100
|
<strong class="name">${title}</strong>
|
|
101
101
|
<span class="welcome-msg">${description}</span>
|
|
102
102
|
</div>
|
|
@@ -127,14 +127,14 @@ export class AuthCheckIn extends localize(i18next)(LitElement) {
|
|
|
127
127
|
<div class="button-container">
|
|
128
128
|
<mwc-button
|
|
129
129
|
raised
|
|
130
|
-
label
|
|
130
|
+
label=${String(i18next.t('button.logout'))}
|
|
131
131
|
@click="${() => (location.pathname = '/auth/signout')}"
|
|
132
132
|
></mwc-button>
|
|
133
133
|
|
|
134
134
|
${this.domainType?.toLowerCase() === 'company'
|
|
135
135
|
? html`<mwc-button
|
|
136
136
|
raised
|
|
137
|
-
label
|
|
137
|
+
label=${String(i18next.t('button.register business domain'))}
|
|
138
138
|
@click=${e => (location.href = `/public/business-register?email=${this.user?.email}`)}
|
|
139
139
|
></mwc-button> `
|
|
140
140
|
: ''}
|
|
@@ -28,32 +28,38 @@ export class AuthSignup extends AbstractSign {
|
|
|
28
28
|
|
|
29
29
|
return html`
|
|
30
30
|
<div class="field">
|
|
31
|
-
<mwc-textfield
|
|
31
|
+
<mwc-textfield
|
|
32
|
+
name="name"
|
|
33
|
+
type="text"
|
|
34
|
+
label=${String(i18next.t('field.name'))}
|
|
35
|
+
.value=${name}
|
|
36
|
+
required
|
|
37
|
+
></mwc-textfield>
|
|
32
38
|
</div>
|
|
33
39
|
<div class="field">
|
|
34
40
|
<mwc-textfield
|
|
35
41
|
name="email"
|
|
36
42
|
type="email"
|
|
37
|
-
label=${i18next.t('field.email')}
|
|
43
|
+
label=${String(i18next.t('field.email'))}
|
|
38
44
|
required
|
|
39
45
|
.value=${email}
|
|
40
|
-
.validationMessage=${i18next.t('text.invalid-email')}
|
|
46
|
+
.validationMessage=${String(i18next.t('text.invalid-email'))}
|
|
41
47
|
></mwc-textfield>
|
|
42
48
|
</div>
|
|
43
49
|
<div class="field">
|
|
44
50
|
<mwc-textfield
|
|
45
51
|
name="password"
|
|
46
52
|
type="password"
|
|
47
|
-
label=${i18next.t('field.password')}
|
|
48
|
-
.pattern=${this.passwordPattern}
|
|
49
|
-
helper=${this.passwordHelp}
|
|
53
|
+
label=${String(i18next.t('field.password'))}
|
|
54
|
+
.pattern=${this.passwordPattern || ''}
|
|
55
|
+
helper=${this.passwordHelp || ''}
|
|
50
56
|
helperPersistent
|
|
51
57
|
required
|
|
52
58
|
@input=${e => {
|
|
53
59
|
var val = e.target.value
|
|
54
60
|
this.confirmPass.setAttribute('pattern', val.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '[$&]'))
|
|
55
61
|
}}
|
|
56
|
-
.validationMessage=${this.passwordHelp}
|
|
62
|
+
.validationMessage=${this.passwordHelp || ''}
|
|
57
63
|
></mwc-textfield>
|
|
58
64
|
</div>
|
|
59
65
|
<div class="field">
|
|
@@ -61,9 +67,9 @@ export class AuthSignup extends AbstractSign {
|
|
|
61
67
|
id="confirm-password"
|
|
62
68
|
name="confirm-password"
|
|
63
69
|
type="password"
|
|
64
|
-
label=${i18next.t('field.confirm password')}
|
|
70
|
+
label=${String(i18next.t('field.confirm password'))}
|
|
65
71
|
required
|
|
66
|
-
.validationMessage=${i18next.t('text.passwords do not match')}
|
|
72
|
+
.validationMessage=${String(i18next.t('text.passwords do not match'))}
|
|
67
73
|
></mwc-textfield>
|
|
68
74
|
</div>
|
|
69
75
|
<mwc-button class="ui button" raised @click=${e => this._onSubmit(e)}>
|
|
@@ -7,7 +7,7 @@ import '@operato/lottie-player';
|
|
|
7
7
|
import '@operato/i18n/ox-i18n.js';
|
|
8
8
|
import '@operato/i18n/ox-i18n-selector.js';
|
|
9
9
|
import '@operato/layout/ox-snack-bar.js';
|
|
10
|
-
import { css, html, LitElement } from 'lit';
|
|
10
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
11
11
|
import { property, query } from 'lit/decorators.js';
|
|
12
12
|
import { i18next, localize } from '@operato/i18n';
|
|
13
13
|
import { ScrollbarStyles } from '@operato/styles';
|
|
@@ -15,6 +15,7 @@ import { isSafari } from '@operato/utils';
|
|
|
15
15
|
import { AUTH_STYLE_SIGN } from '../auth-style-sign.js';
|
|
16
16
|
export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
17
17
|
render() {
|
|
18
|
+
const { disableUserFavoredLanguage, languages } = this.data || {};
|
|
18
19
|
var { icon, title, description } = this.applicationMeta;
|
|
19
20
|
return html `
|
|
20
21
|
<div class="content">
|
|
@@ -31,7 +32,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
31
32
|
<form
|
|
32
33
|
id="form"
|
|
33
34
|
action="${this.actionUrl}"
|
|
34
|
-
method="
|
|
35
|
+
method="post"
|
|
35
36
|
@keypress=${e => {
|
|
36
37
|
if (e.key == 'Enter')
|
|
37
38
|
this._onSubmit(e);
|
|
@@ -40,19 +41,22 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
40
41
|
${this.formfields}
|
|
41
42
|
</form>
|
|
42
43
|
${this.links}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
44
|
+
${!disableUserFavoredLanguage
|
|
45
|
+
? html ` <div id="locale-area">
|
|
46
|
+
<label for="locale-selector"><mwc-icon>language</mwc-icon></label>
|
|
47
|
+
<ox-i18n-selector
|
|
48
|
+
id="locale-selector"
|
|
49
|
+
value=${i18next.language || 'en-US'}
|
|
50
|
+
.languages=${languages}
|
|
51
|
+
@change=${e => {
|
|
52
|
+
var locale = e.detail;
|
|
53
|
+
if (!locale)
|
|
54
|
+
return;
|
|
55
|
+
i18next.changeLanguage(locale);
|
|
56
|
+
}}
|
|
57
|
+
></ox-i18n-selector>
|
|
58
|
+
</div>`
|
|
59
|
+
: nothing}
|
|
56
60
|
</div>
|
|
57
61
|
</div>
|
|
58
62
|
|
|
@@ -97,10 +101,10 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
97
101
|
<mwc-textfield
|
|
98
102
|
name="email"
|
|
99
103
|
type="email"
|
|
100
|
-
label=${i18next.t('field.email')}
|
|
104
|
+
label=${String(i18next.t('field.email'))}
|
|
101
105
|
required
|
|
102
106
|
.value=${email}
|
|
103
|
-
.validationMessage=${i18next.t('text.invalid-email')}
|
|
107
|
+
.validationMessage=${String(i18next.t('text.invalid-email'))}
|
|
104
108
|
autocomplete="username"
|
|
105
109
|
autocapitalize="off"
|
|
106
110
|
></mwc-textfield>
|
|
@@ -109,7 +113,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
109
113
|
<mwc-textfield
|
|
110
114
|
name="password"
|
|
111
115
|
type="password"
|
|
112
|
-
label=${i18next.t('field.password')}
|
|
116
|
+
label=${String(i18next.t('field.password'))}
|
|
113
117
|
autocomplete="current-password"
|
|
114
118
|
required
|
|
115
119
|
></mwc-textfield>
|
|
@@ -121,16 +125,18 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
|
|
|
121
125
|
`;
|
|
122
126
|
}
|
|
123
127
|
get links() {
|
|
124
|
-
|
|
125
|
-
const ssoLinks = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.ssoLinks) || [];
|
|
128
|
+
const { disableUserSignupProcess, ssoLinks = [] } = this.data || {};
|
|
126
129
|
return html `
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
${!disableUserSignupProcess
|
|
131
|
+
? html `
|
|
132
|
+
<a class="link" href="/auth/signup">
|
|
133
|
+
<mwc-button icon="add_task"><ox-i18n msgid="field.sign up"></ox-i18n></mwc-button>
|
|
134
|
+
</a>
|
|
135
|
+
<a class="link" href="/auth/forgot-password">
|
|
136
|
+
<mwc-button icon="lock_open"><ox-i18n msgid="field.forgot-password"></ox-i18n></mwc-button>
|
|
137
|
+
</a>
|
|
138
|
+
`
|
|
139
|
+
: nothing}
|
|
134
140
|
${ssoLinks.map(sso => html `
|
|
135
141
|
<a class="link" href=${sso.link}>
|
|
136
142
|
<mwc-button icon="badge">${i18next.t('label.signin with', { title: sso.title })}</mwc-button>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-auth-page.js","sourceRoot":"","sources":["../../client/components/abstract-auth-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/mwc-button'\nimport '@material/mwc-icon'\nimport '@material/mwc-icon-button'\nimport '@material/mwc-textfield'\nimport '@operato/lottie-player'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport { css, html, LitElement } from 'lit'\nimport { property, query } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isSafari } from '@operato/utils'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign.js'\n\nexport abstract class AbstractAuthPage extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: relative;\n overflow: hidden;\n\n display: flex;\n flex-direction: row;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n .content {\n flex: 1;\n overflow: auto;\n }\n\n [home] {\n position: absolute;\n top: 10px;\n left: 10px;\n font-size: 2em;\n color: white;\n }\n\n [hidden] {\n display: none;\n }\n\n #snackbar {\n width: 100%;\n z-index: 10;\n }\n\n @media print {\n :host {\n width: 100%;\n height: 100%;\n min-height: 100vh;\n min-height: 100dvh;\n }\n }\n `,\n AUTH_STYLE_SIGN\n ]\n\n @property({ type: Object }) data: any\n @property({ type: String }) message?: string\n @property({ type: Object }) detail: any\n @property({ type: String }) redirectTo?: string\n\n @query('#form') formEl!: HTMLFormElement\n\n private _applicationMeta?: {\n icon: string\n title: string\n description: string\n }\n\n render() {\n var { icon, title, description } = this.applicationMeta\n\n return html`\n <div class=\"content\">\n <div class=\"wrap\">\n <div class=\"auth-brand\">\n <img src=${icon} />\n <strong class=\"name\">${title}</strong>\n <span class=\"welcome-msg\">${description}</span>\n </div>\n\n <div class=\"auth-form\">\n <h3><ox-i18n msgid=\"title.${this.pageName}\"></ox-i18n></h3>\n\n <form\n id=\"form\"\n action=\"${this.actionUrl}\"\n method=\"POST\"\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n >\n ${this.formfields}\n </form>\n ${this.links}\n <div id=\"locale-area\">\n <label for=\"locale-selector\"><mwc-icon>language</mwc-icon></label>\n <ox-i18n-selector\n id=\"locale-selector\"\n value=${i18next.language || 'en-US'}\n @change=${e => {\n var locale = e.detail\n if (!locale) return\n\n i18next.changeLanguage(locale)\n }}\n ></ox-i18n-selector>\n </div>\n </div>\n </div>\n\n <mwc-icon-button home icon=\"home\" @click=${e => (window.location.href = '/')}></mwc-icon-button>\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n\n ${isSafari()\n ? html``\n : html`\n <div class=\"lottie-container\">\n <lottie-player autoplay loop src=\"../../assets/images/background-animation.json\"></lottie-player>\n </div>\n `}\n </div>\n `\n }\n\n firstUpdated() {\n setTimeout(() => {\n ;(this.renderRoot.querySelector('mwc-textfield') as any).focus()\n }, 100)\n\n this.formEl.reset = () => {\n this.formElements.filter(el => !(el.hidden || el.type == 'hidden')).forEach(el => (el.value = ''))\n }\n }\n\n updated(changed) {\n if (changed.has('data') && this.data) {\n this.message = this.data.message\n this.redirectTo = this.data.redirectTo\n }\n }\n\n abstract get pageName(): string\n abstract get actionUrl(): string\n\n get formElements(): HTMLInputElement[] {\n return Array.from(this.formEl.querySelectorAll('[name]'))\n }\n\n get formfields() {\n const email = this.data?.email || ''\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <mwc-textfield\n name=\"email\"\n type=\"email\"\n label=${i18next.t('field.email')}\n required\n .value=${email}\n .validationMessage=${i18next.t('text.invalid-email')}\n autocomplete=\"username\"\n autocapitalize=\"off\"\n ></mwc-textfield>\n </div>\n <div class=\"field\">\n <mwc-textfield\n name=\"password\"\n type=\"password\"\n label=${i18next.t('field.password')}\n autocomplete=\"current-password\"\n required\n ></mwc-textfield>\n </div>\n\n <mwc-button class=\"ui\" type=\"submit\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </mwc-button>\n `\n }\n\n get links() {\n const ssoLinks = this.data?.ssoLinks || []\n\n return html`\n <a class=\"link\" href=\"/auth/signup\">\n <mwc-button icon=\"add_task\"><ox-i18n msgid=\"field.sign up\"></ox-i18n></mwc-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <mwc-button icon=\"lock_open\"><ox-i18n msgid=\"field.forgot-password\"></ox-i18n></mwc-button>\n </a>\n\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <mwc-button icon=\"badge\">${i18next.t('label.signin with', { title: sso.title })}</mwc-button>\n </a>\n `\n )}\n `\n }\n\n async _onSubmit(e) {\n if (this.checkValidity()) {\n this.submit()\n }\n }\n\n checkValidity() {\n return this.formElements.every(el => el.checkValidity())\n }\n\n abstract submit()\n\n showSnackbar({ level, message, timer = 3000 }: { level?: string; message?: string; timer?: number } = {}) {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n if (level) snackbar.level = level\n if (message) snackbar.message = message\n snackbar.active = true\n\n if (timer > -1)\n setTimeout(() => {\n this.hideSnackbar()\n }, timer)\n }\n\n hideSnackbar() {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n snackbar.active = false\n }\n\n get applicationMeta() {\n if (!this._applicationMeta) {\n var iconLink: HTMLLinkElement | null = document.querySelector('link[rel=\"application-icon\"]')\n var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-name\"]')\n var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-description\"]')\n\n this._applicationMeta = {\n icon: iconLink?.href || '',\n title: titleMeta?.content || 'Things Factory',\n description: descriptionMeta?.content || 'Reimagining Software'\n }\n }\n\n return this._applicationMeta\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"abstract-auth-page.js","sourceRoot":"","sources":["../../client/components/abstract-auth-page.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/mwc-button'\nimport '@material/mwc-icon'\nimport '@material/mwc-icon-button'\nimport '@material/mwc-textfield'\nimport '@operato/lottie-player'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\nimport { isSafari } from '@operato/utils'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign.js'\n\nexport abstract class AbstractAuthPage extends localize(i18next)(LitElement) {\n static styles = [\n ScrollbarStyles,\n css`\n :host {\n position: relative;\n overflow: hidden;\n\n display: flex;\n flex-direction: row;\n\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n }\n .content {\n flex: 1;\n overflow: auto;\n }\n\n [home] {\n position: absolute;\n top: 10px;\n left: 10px;\n font-size: 2em;\n color: white;\n }\n\n [hidden] {\n display: none;\n }\n\n #snackbar {\n width: 100%;\n z-index: 10;\n }\n\n @media print {\n :host {\n width: 100%;\n height: 100%;\n min-height: 100vh;\n min-height: 100dvh;\n }\n }\n `,\n AUTH_STYLE_SIGN\n ]\n\n @property({ type: Object }) data: any\n @property({ type: String }) message?: string\n @property({ type: Object }) detail: any\n @property({ type: String }) redirectTo?: string\n\n @query('#form') formEl!: HTMLFormElement\n\n private _applicationMeta?: {\n icon: string\n title: string\n description: string\n }\n\n render() {\n const { disableUserFavoredLanguage, languages } = this.data || {}\n var { icon, title, description } = this.applicationMeta\n\n return html`\n <div class=\"content\">\n <div class=\"wrap\">\n <div class=\"auth-brand\">\n <img src=${icon} />\n <strong class=\"name\">${title}</strong>\n <span class=\"welcome-msg\">${description}</span>\n </div>\n\n <div class=\"auth-form\">\n <h3><ox-i18n msgid=\"title.${this.pageName}\"></ox-i18n></h3>\n\n <form\n id=\"form\"\n action=\"${this.actionUrl}\"\n method=\"post\"\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n >\n ${this.formfields}\n </form>\n ${this.links}\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><mwc-icon>language</mwc-icon></label>\n <ox-i18n-selector\n id=\"locale-selector\"\n value=${i18next.language || 'en-US'}\n .languages=${languages}\n @change=${e => {\n var locale = e.detail\n if (!locale) return\n\n i18next.changeLanguage(locale)\n }}\n ></ox-i18n-selector>\n </div>`\n : nothing}\n </div>\n </div>\n\n <mwc-icon-button home icon=\"home\" @click=${e => (window.location.href = '/')}></mwc-icon-button>\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n\n ${isSafari()\n ? html``\n : html`\n <div class=\"lottie-container\">\n <lottie-player autoplay loop src=\"../../assets/images/background-animation.json\"></lottie-player>\n </div>\n `}\n </div>\n `\n }\n\n firstUpdated() {\n setTimeout(() => {\n ;(this.renderRoot.querySelector('mwc-textfield') as any).focus()\n }, 100)\n\n this.formEl.reset = () => {\n this.formElements.filter(el => !(el.hidden || el.type == 'hidden')).forEach(el => (el.value = ''))\n }\n }\n\n updated(changed) {\n if (changed.has('data') && this.data) {\n this.message = this.data.message\n this.redirectTo = this.data.redirectTo\n }\n }\n\n abstract get pageName(): string\n abstract get actionUrl(): string\n\n get formElements(): HTMLInputElement[] {\n return Array.from(this.formEl.querySelectorAll('[name]'))\n }\n\n get formfields() {\n const email = this.data?.email || ''\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <mwc-textfield\n name=\"email\"\n type=\"email\"\n label=${String(i18next.t('field.email'))}\n required\n .value=${email}\n .validationMessage=${String(i18next.t('text.invalid-email'))}\n autocomplete=\"username\"\n autocapitalize=\"off\"\n ></mwc-textfield>\n </div>\n <div class=\"field\">\n <mwc-textfield\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=\"current-password\"\n required\n ></mwc-textfield>\n </div>\n\n <mwc-button class=\"ui\" type=\"submit\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </mwc-button>\n `\n }\n\n get links() {\n const { disableUserSignupProcess, ssoLinks = [] } = this.data || {}\n\n return html`\n ${!disableUserSignupProcess\n ? html`\n <a class=\"link\" href=\"/auth/signup\">\n <mwc-button icon=\"add_task\"><ox-i18n msgid=\"field.sign up\"></ox-i18n></mwc-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <mwc-button icon=\"lock_open\"><ox-i18n msgid=\"field.forgot-password\"></ox-i18n></mwc-button>\n </a>\n `\n : nothing}\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <mwc-button icon=\"badge\">${i18next.t('label.signin with', { title: sso.title })}</mwc-button>\n </a>\n `\n )}\n `\n }\n\n async _onSubmit(e) {\n if (this.checkValidity()) {\n this.submit()\n }\n }\n\n checkValidity() {\n return this.formElements.every(el => el.checkValidity())\n }\n\n abstract submit()\n\n showSnackbar({ level, message, timer = 3000 }: { level?: string; message?: string; timer?: number } = {}) {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n if (level) snackbar.level = level\n if (message) snackbar.message = message\n snackbar.active = true\n\n if (timer > -1)\n setTimeout(() => {\n this.hideSnackbar()\n }, timer)\n }\n\n hideSnackbar() {\n const snackbar = this.renderRoot.querySelector('#snackbar') as HTMLElement & {\n level: string\n message: string\n active: boolean\n }\n\n snackbar.active = false\n }\n\n get applicationMeta() {\n if (!this._applicationMeta) {\n var iconLink: HTMLLinkElement | null = document.querySelector('link[rel=\"application-icon\"]')\n var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-name\"]')\n var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name=\"application-description\"]')\n\n this._applicationMeta = {\n icon: iconLink?.href || '',\n title: titleMeta?.content || 'Things Factory',\n description: descriptionMeta?.content || 'Reimagining Software'\n }\n }\n\n return this._applicationMeta\n }\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import '../components/profile-component';
|
|
|
6
6
|
import '@operato/i18n/ox-i18n.js';
|
|
7
7
|
import '@operato/i18n/ox-i18n-selector.js';
|
|
8
8
|
import '@operato/layout/ox-snack-bar.js';
|
|
9
|
-
import { css, html } from 'lit';
|
|
9
|
+
import { css, html, nothing } from 'lit';
|
|
10
10
|
import { property, query } from 'lit/decorators.js';
|
|
11
11
|
import { i18next } from '@operato/i18n';
|
|
12
12
|
import { isSafari } from '@operato/utils';
|
|
@@ -21,6 +21,7 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
21
21
|
}
|
|
22
22
|
render() {
|
|
23
23
|
var { icon, title, description } = this.applicationMeta;
|
|
24
|
+
const { disableUserFavoredLanguage, languages } = this.data || {};
|
|
24
25
|
return html `
|
|
25
26
|
<div class="wrap">
|
|
26
27
|
<div class="auth-brand">
|
|
@@ -34,18 +35,18 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
34
35
|
<form
|
|
35
36
|
id="form"
|
|
36
37
|
action="${this.actionUrl}"
|
|
37
|
-
method="
|
|
38
|
+
method="post"
|
|
38
39
|
@keypress=${e => {
|
|
39
40
|
if (e.key == 'Enter')
|
|
40
41
|
this._onSubmit(e);
|
|
41
42
|
}}
|
|
42
43
|
>
|
|
43
|
-
<input name="token" type="hidden" .value=${this.token} required />
|
|
44
|
+
<input name="token" type="hidden" .value=${this.token || ''} required />
|
|
44
45
|
<div class="field">
|
|
45
46
|
<mwc-textfield
|
|
46
47
|
name="password"
|
|
47
48
|
type="password"
|
|
48
|
-
label=${i18next.t('label.password')}
|
|
49
|
+
label=${String(i18next.t('label.password'))}
|
|
49
50
|
.pattern=${this.passwordPattern}
|
|
50
51
|
helper=${this.passwordHelp}
|
|
51
52
|
helperPersistent
|
|
@@ -62,7 +63,7 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
62
63
|
id="confirm-password"
|
|
63
64
|
name="confirm-password"
|
|
64
65
|
type="password"
|
|
65
|
-
label=${i18next.t('field.confirm password')}
|
|
66
|
+
label=${String(i18next.t('field.confirm password'))}
|
|
66
67
|
required
|
|
67
68
|
></mwc-textfield>
|
|
68
69
|
</div>
|
|
@@ -71,19 +72,22 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
71
72
|
<ox-i18n msgid="${this.submitButtonLabel}"></ox-i18n>
|
|
72
73
|
</mwc-button>
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
${!disableUserFavoredLanguage
|
|
76
|
+
? html ` <div id="locale-area">
|
|
77
|
+
<label for="locale-selector"><mwc-icon>language</mwc-icon></label>
|
|
78
|
+
<ox-i18n-selector
|
|
79
|
+
id="locale-selector"
|
|
80
|
+
value=${i18next.language || 'en-US'}
|
|
81
|
+
.languages=${languages}
|
|
82
|
+
@change=${e => {
|
|
83
|
+
var locale = e.detail;
|
|
84
|
+
if (!locale)
|
|
85
|
+
return;
|
|
86
|
+
i18next.changeLanguage(locale);
|
|
87
|
+
}}
|
|
88
|
+
></ox-i18n-selector>
|
|
89
|
+
</div>`
|
|
90
|
+
: nothing}
|
|
87
91
|
</form>
|
|
88
92
|
</div>
|
|
89
93
|
</div>
|