@things-factory/auth-ui 8.0.5 → 9.0.0-beta.12

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 (146) hide show
  1. package/dist-client/components/abstract-auth-page.d.ts +1 -1
  2. package/dist-client/components/abstract-auth-page.js +12 -10
  3. package/dist-client/components/abstract-auth-page.js.map +1 -1
  4. package/dist-client/components/abstract-password-reset.d.ts +2 -3
  5. package/dist-client/components/abstract-password-reset.js +10 -17
  6. package/dist-client/components/abstract-password-reset.js.map +1 -1
  7. package/dist-client/components/abstract-sign.js +12 -11
  8. package/dist-client/components/abstract-sign.js.map +1 -1
  9. package/dist-client/components/change-password.js +1 -1
  10. package/dist-client/components/change-password.js.map +1 -1
  11. package/dist-client/components/contact-us.d.ts +1 -1
  12. package/dist-client/components/contact-us.js +10 -7
  13. package/dist-client/components/contact-us.js.map +1 -1
  14. package/dist-client/components/create-user.js +28 -5
  15. package/dist-client/components/create-user.js.map +1 -1
  16. package/dist-client/components/invite-user.d.ts +1 -1
  17. package/dist-client/components/invite-user.js +19 -12
  18. package/dist-client/components/invite-user.js.map +1 -1
  19. package/dist-client/components/ownership-transfer-popup.js +3 -3
  20. package/dist-client/components/ownership-transfer-popup.js.map +1 -1
  21. package/dist-client/components/partner-role-editor.js +1 -1
  22. package/dist-client/components/partner-role-editor.js.map +1 -1
  23. package/dist-client/components/profile-component.d.ts +8 -4
  24. package/dist-client/components/profile-component.js +67 -7
  25. package/dist-client/components/profile-component.js.map +1 -1
  26. package/dist-client/components/role-privilege-editor.js +2 -1
  27. package/dist-client/components/role-privilege-editor.js.map +1 -1
  28. package/dist-client/components/user-role-editor.d.ts +2 -2
  29. package/dist-client/components/user-role-editor.js +20 -20
  30. package/dist-client/components/user-role-editor.js.map +1 -1
  31. package/dist-client/constants/index.d.ts +1 -1
  32. package/dist-client/constants/index.js +1 -1
  33. package/dist-client/constants/index.js.map +1 -1
  34. package/dist-client/entries/auth/activate.d.ts +1 -1
  35. package/dist-client/entries/auth/activate.js +1 -1
  36. package/dist-client/entries/auth/activate.js.map +1 -1
  37. package/dist-client/entries/auth/checkin.js +2 -2
  38. package/dist-client/entries/auth/checkin.js.map +1 -1
  39. package/dist-client/entries/auth/forgot-password.d.ts +2 -2
  40. package/dist-client/entries/auth/forgot-password.js +13 -4
  41. package/dist-client/entries/auth/forgot-password.js.map +1 -1
  42. package/dist-client/entries/auth/reset-password.d.ts +1 -1
  43. package/dist-client/entries/auth/reset-password.js +1 -1
  44. package/dist-client/entries/auth/reset-password.js.map +1 -1
  45. package/dist-client/entries/auth/result.d.ts +1 -1
  46. package/dist-client/entries/auth/result.js +1 -1
  47. package/dist-client/entries/auth/result.js.map +1 -1
  48. package/dist-client/entries/auth/signin.d.ts +1 -1
  49. package/dist-client/entries/auth/signin.js +1 -1
  50. package/dist-client/entries/auth/signin.js.map +1 -1
  51. package/dist-client/entries/auth/signup.d.ts +3 -1
  52. package/dist-client/entries/auth/signup.js +45 -9
  53. package/dist-client/entries/auth/signup.js.map +1 -1
  54. package/dist-client/entries/auth/unlock-user.d.ts +1 -1
  55. package/dist-client/entries/auth/unlock-user.js +1 -1
  56. package/dist-client/entries/auth/unlock-user.js.map +1 -1
  57. package/dist-client/entries/oauth2/oauth2-decision-page.d.ts +1 -1
  58. package/dist-client/entries/oauth2/oauth2-decision-page.js +1 -1
  59. package/dist-client/entries/oauth2/oauth2-decision-page.js.map +1 -1
  60. package/dist-client/entries/public/home.js +2 -2
  61. package/dist-client/entries/public/home.js.map +1 -1
  62. package/dist-client/index.js +1 -1
  63. package/dist-client/index.js.map +1 -1
  64. package/dist-client/pages/application/application.js +1 -1
  65. package/dist-client/pages/application/application.js.map +1 -1
  66. package/dist-client/pages/domain/domain-management.d.ts +1 -1
  67. package/dist-client/pages/domain/domain-management.js +1 -1
  68. package/dist-client/pages/domain/domain-management.js.map +1 -1
  69. package/dist-client/pages/partner/partner-management.d.ts +3 -3
  70. package/dist-client/pages/partner/partner-management.js +3 -3
  71. package/dist-client/pages/partner/partner-management.js.map +1 -1
  72. package/dist-client/pages/profile.d.ts +1 -1
  73. package/dist-client/pages/profile.js +1 -1
  74. package/dist-client/pages/profile.js.map +1 -1
  75. package/dist-client/pages/role/role-management.d.ts +3 -3
  76. package/dist-client/pages/role/role-management.js +3 -3
  77. package/dist-client/pages/role/role-management.js.map +1 -1
  78. package/dist-client/pages/user/user-management.d.ts +9 -5
  79. package/dist-client/pages/user/user-management.js +10 -11
  80. package/dist-client/pages/user/user-management.js.map +1 -1
  81. package/dist-client/tsconfig.tsbuildinfo +1 -1
  82. package/dist-server/tsconfig.tsbuildinfo +1 -1
  83. package/package.json +12 -12
  84. package/translations/en.json +6 -2
  85. package/translations/ja.json +6 -2
  86. package/translations/ko.json +6 -2
  87. package/translations/ms.json +6 -2
  88. package/translations/zh.json +6 -2
  89. package/client/auth-style-sign.ts +0 -194
  90. package/client/bootstrap.ts +0 -51
  91. package/client/components/abstract-auth-page.ts +0 -301
  92. package/client/components/abstract-password-reset.ts +0 -168
  93. package/client/components/abstract-sign.ts +0 -127
  94. package/client/components/change-password.ts +0 -153
  95. package/client/components/contact-us.ts +0 -113
  96. package/client/components/create-domain-popup.ts +0 -141
  97. package/client/components/create-role.ts +0 -123
  98. package/client/components/create-user.ts +0 -95
  99. package/client/components/credential-manager.ts +0 -64
  100. package/client/components/delete-user-popup.ts +0 -117
  101. package/client/components/domain-switch.ts +0 -127
  102. package/client/components/invite-customer.ts +0 -104
  103. package/client/components/invite-user.ts +0 -96
  104. package/client/components/my-login-history.ts +0 -101
  105. package/client/components/ownership-transfer-popup.ts +0 -110
  106. package/client/components/partner-info-card.ts +0 -89
  107. package/client/components/partner-role-editor.ts +0 -153
  108. package/client/components/profile-component.ts +0 -332
  109. package/client/components/role-edit-form.ts +0 -92
  110. package/client/components/role-privilege-editor.ts +0 -267
  111. package/client/components/role-selector.ts +0 -102
  112. package/client/components/user-role-editor.ts +0 -499
  113. package/client/constants/application.ts +0 -9
  114. package/client/constants/index.ts +0 -1
  115. package/client/entries/auth/activate.ts +0 -272
  116. package/client/entries/auth/checkin.ts +0 -190
  117. package/client/entries/auth/forgot-password.ts +0 -103
  118. package/client/entries/auth/reset-password.ts +0 -22
  119. package/client/entries/auth/result.ts +0 -193
  120. package/client/entries/auth/signin.ts +0 -18
  121. package/client/entries/auth/signup.ts +0 -109
  122. package/client/entries/auth/unlock-user.ts +0 -22
  123. package/client/entries/oauth2/oauth2-decision-error-page.ts +0 -50
  124. package/client/entries/oauth2/oauth2-decision-page.ts +0 -196
  125. package/client/entries/public/home.ts +0 -246
  126. package/client/index.ts +0 -124
  127. package/client/pages/app-binding/app-binding.ts +0 -423
  128. package/client/pages/app-binding/app-bindings.ts +0 -171
  129. package/client/pages/appliance/appliance.ts +0 -452
  130. package/client/pages/appliance/home.ts +0 -177
  131. package/client/pages/appliance/register.ts +0 -183
  132. package/client/pages/application/application.ts +0 -428
  133. package/client/pages/application/applications.ts +0 -182
  134. package/client/pages/application/register.ts +0 -211
  135. package/client/pages/attribute/attribute-set-item-list.ts +0 -237
  136. package/client/pages/attribute/attribute-set-management.ts +0 -282
  137. package/client/pages/auth-provider/auth-provider-management.ts +0 -381
  138. package/client/pages/domain/domain-management.ts +0 -410
  139. package/client/pages/partner/partner-management.ts +0 -112
  140. package/client/pages/profile.ts +0 -32
  141. package/client/pages/role/role-management.ts +0 -134
  142. package/client/pages/user/user-management.ts +0 -224
  143. package/client/route.ts +0 -67
  144. package/client/themes/auth-theme.css +0 -65
  145. package/client/utils/password-rule.ts +0 -37
  146. package/server/index.ts +0 -0
@@ -25,7 +25,7 @@ export declare abstract class AbstractAuthPage extends AbstractAuthPage_base {
25
25
  get formElements(): HTMLInputElement[];
26
26
  get formfields(): import("lit-html").TemplateResult<1>;
27
27
  get links(): import("lit-html").TemplateResult<1>;
28
- _onSubmit(e: any): Promise<void>;
28
+ _onSubmit(e: any): Promise<boolean>;
29
29
  checkValidity(): boolean;
30
30
  abstract submit(): any;
31
31
  showSnackbar({ level, message, timer }?: {
@@ -41,6 +41,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
41
41
  if (e.key == 'Enter')
42
42
  this._onSubmit(e);
43
43
  }}
44
+ @submit=${e => e.preventDefault()}
44
45
  >
45
46
  ${this.formfields}
46
47
  </form>
@@ -99,21 +100,21 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
99
100
  }
100
101
  get formfields() {
101
102
  var _a;
102
- const email = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.email) || '';
103
- // .validationMessage=${String(i18next.t('text.invalid-email'))}
103
+ const username = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.username) || '';
104
+ // .validationMessage=${String(i18next.t('text.invalid-username'))}
104
105
  return html `
105
106
  <input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
106
107
 
107
108
  <div class="field">
108
109
  <md-filled-text-field
109
- name="email"
110
- type="email"
111
- label=${String(i18next.t('field.email'))}
110
+ name="username"
111
+ type="text"
112
+ label=${String(i18next.t('field.user-id or email'))}
112
113
  required
113
- .value=${email}
114
+ .value=${username}
114
115
  autocomplete="off"
115
116
  autocapitalize="off"
116
- ><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
117
+ ><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
117
118
  >
118
119
  </div>
119
120
  <div class="field">
@@ -123,11 +124,11 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
123
124
  label=${String(i18next.t('field.password'))}
124
125
  autocomplete="off"
125
126
  required
126
- ><md-icon slot="leading-icon">vpn_key</md-icon></md-filled-text-field
127
+ ><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
127
128
  >
128
129
  </div>
129
130
 
130
- <md-elevated-button class="ui" type="submit" raised @click=${e => this._onSubmit(e)}>
131
+ <md-elevated-button class="ui" type="button" raised @click=${e => this._onSubmit(e)}>
131
132
  <ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
132
133
  </md-elevated-button>
133
134
  `;
@@ -154,7 +155,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
154
155
  ${ssoLinks.map(sso => html `
155
156
  <a class="link" href=${sso.link}>
156
157
  <md-text-button>
157
- <md-icon slot="icon">badge</md-icon>
158
+ <md-icon slot="icon">id_card</md-icon>
158
159
  ${i18next.t('label.signin with', { title: sso.title })}
159
160
  </md-text-button>
160
161
  </a>
@@ -165,6 +166,7 @@ export class AbstractAuthPage extends localize(i18next)(LitElement) {
165
166
  if (this.checkValidity()) {
166
167
  this.submit();
167
168
  }
169
+ return false;
168
170
  }
169
171
  checkValidity() {
170
172
  return this.formElements.every(el => el.checkValidity());
@@ -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/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\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\n .content {\n flex: 1;\n overflow: auto;\n }\n\n .home {\n position: absolute;\n padding: var(--padding-dufault, 9px);\n left: 20px;\n top: 10px;\n color: var(--md-sys-color-on-primary);\n }\n\n div.field {\n margin-bottom: var(--spacing-medium);\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 get autocompletable() {\n return false\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 md-typescale-display-medium\">\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 autocomplete=${this.autocompletable ? 'on' : 'off'}\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\"><md-icon>language</md-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 <md-icon-button class=\"home\" @click=${e => (window.location.href = '/')}\n ><md-icon>home</md-icon></md-icon-button\n >\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('md-filled-text-field') 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 // .validationMessage=${String(i18next.t('text.invalid-email'))}\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"email\"\n type=\"email\"\n label=${String(i18next.t('field.email'))}\n required\n .value=${email}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n ><md-icon slot=\"leading-icon\">mail</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">vpn_key</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button class=\"ui\" type=\"submit\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-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 <md-text-button>\n <md-icon slot=\"icon\">add_task</md-icon>\n <ox-i18n msgid=\"field.sign up\"></ox-i18n>\n </md-text-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <md-text-button>\n <md-icon slot=\"icon\">lock_open</md-icon>\n <ox-i18n msgid=\"field.forgot-password\"></ox-i18n>\n </md-text-button>\n </a>\n `\n : nothing}\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <md-text-button>\n <md-icon slot=\"icon\">badge</md-icon>\n ${i18next.t('label.signin with', { title: sso.title })}\n </md-text-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/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/button/text-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\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\n .content {\n flex: 1;\n overflow: auto;\n }\n\n .home {\n position: absolute;\n padding: var(--padding-dufault, 9px);\n left: 20px;\n top: 10px;\n color: var(--md-sys-color-on-primary);\n }\n\n div.field {\n margin-bottom: var(--spacing-medium);\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 get autocompletable() {\n return false\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 md-typescale-display-medium\">\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 autocomplete=${this.autocompletable ? 'on' : 'off'}\n @keypress=${e => {\n if (e.key == 'Enter') this._onSubmit(e)\n }}\n @submit=${e => e.preventDefault()}\n >\n ${this.formfields}\n </form>\n ${this.links}\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-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 <md-icon-button class=\"home\" @click=${e => (window.location.href = '/')}\n ><md-icon>home</md-icon></md-icon-button\n >\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('md-filled-text-field') 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 username = this.data?.username || ''\n // .validationMessage=${String(i18next.t('text.invalid-username'))}\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"username\"\n type=\"text\"\n label=${String(i18next.t('field.user-id or email'))}\n required\n .value=${username}\n autocomplete=\"off\"\n autocapitalize=\"off\"\n ><md-icon slot=\"leading-icon\">id_card</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button class=\"ui\" type=\"button\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-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 <md-text-button>\n <md-icon slot=\"icon\">add_task</md-icon>\n <ox-i18n msgid=\"field.sign up\"></ox-i18n>\n </md-text-button>\n </a>\n <a class=\"link\" href=\"/auth/forgot-password\">\n <md-text-button>\n <md-icon slot=\"icon\">lock_open</md-icon>\n <ox-i18n msgid=\"field.forgot-password\"></ox-i18n>\n </md-text-button>\n </a>\n `\n : nothing}\n ${ssoLinks.map(\n sso => html`\n <a class=\"link\" href=${sso.link}>\n <md-text-button>\n <md-icon slot=\"icon\">id_card</md-icon>\n ${i18next.t('label.signin with', { title: sso.title })}\n </md-text-button>\n </a>\n `\n )}\n `\n }\n\n async _onSubmit(e) {\n if (this.checkValidity()) {\n this.submit()\n }\n\n return false\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,12 +1,11 @@
1
1
  import '@material/web/icon/icon.js';
2
2
  import '@material/web/button/elevated-button.js';
3
3
  import '@material/web/textfield/filled-text-field.js';
4
- import '@operato/lottie-player';
5
- import '../components/profile-component';
6
4
  import '@operato/i18n/ox-i18n.js';
7
5
  import '@operato/i18n/ox-i18n-selector.js';
8
6
  import '@operato/layout/ox-snack-bar.js';
9
- import { AbstractAuthPage } from './abstract-auth-page';
7
+ import '../components/profile-component.js';
8
+ import { AbstractAuthPage } from './abstract-auth-page.js';
10
9
  export declare abstract class AbstractPasswordReset extends AbstractAuthPage {
11
10
  static styles: import("lit").CSSResult[];
12
11
  data: any;
@@ -2,18 +2,16 @@ import { __decorate, __metadata } from "tslib";
2
2
  import '@material/web/icon/icon.js';
3
3
  import '@material/web/button/elevated-button.js';
4
4
  import '@material/web/textfield/filled-text-field.js';
5
- import '@operato/lottie-player';
6
- import '../components/profile-component';
7
5
  import '@operato/i18n/ox-i18n.js';
8
6
  import '@operato/i18n/ox-i18n-selector.js';
9
7
  import '@operato/layout/ox-snack-bar.js';
8
+ import '../components/profile-component.js';
10
9
  import { css, html, nothing } from 'lit';
11
10
  import { property, query } from 'lit/decorators.js';
12
11
  import { i18next } from '@operato/i18n';
13
- import { isSafari } from '@operato/utils';
14
- import { AUTH_STYLE_SIGN } from '../auth-style-sign';
15
- import { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule';
16
- import { AbstractAuthPage } from './abstract-auth-page';
12
+ import { AUTH_STYLE_SIGN } from '../auth-style-sign.js';
13
+ import { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule.js';
14
+ import { AbstractAuthPage } from './abstract-auth-page.js';
17
15
  export class AbstractPasswordReset extends AbstractAuthPage {
18
16
  constructor() {
19
17
  super(...arguments);
@@ -56,7 +54,8 @@ export class AbstractPasswordReset extends AbstractAuthPage {
56
54
  this.confirmPass.setAttribute('pattern', val.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '[$&]'));
57
55
  }}
58
56
  required
59
- ></md-filled-text-field>
57
+ ><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
58
+ >
60
59
  </div>
61
60
 
62
61
  <div class="field">
@@ -67,10 +66,11 @@ export class AbstractPasswordReset extends AbstractAuthPage {
67
66
  label=${String(i18next.t('field.confirm password'))}
68
67
  autocomplete="off"
69
68
  required
70
- ></md-filled-text-field>
69
+ ><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
70
+ >
71
71
  </div>
72
72
 
73
- <md-elevated-button id="submit-button" type="submit" @click=${e => this._onSubmit(e)}>
73
+ <md-elevated-button id="submit-button" type="button" @click=${e => this._onSubmit(e)}>
74
74
  <ox-i18n msgid="${this.submitButtonLabel}"></ox-i18n>
75
75
  </md-elevated-button>
76
76
 
@@ -93,15 +93,8 @@ export class AbstractPasswordReset extends AbstractAuthPage {
93
93
  </form>
94
94
  </div>
95
95
  </div>
96
- <ox-snack-bar id="snackbar" level="error" .message=${this.message}></ox-snack-bar>
97
96
 
98
- ${isSafari()
99
- ? html ``
100
- : html `
101
- <div class="lottie-container">
102
- <lottie-player autoplay loop src="../../assets/images/background-animation.json"></lottie-player>
103
- </div>
104
- `}
97
+ <ox-snack-bar id="snackbar" level="error" .message=${this.message}></ox-snack-bar>
105
98
  `;
106
99
  }
107
100
  updated(changed) {
@@ -1 +1 @@
1
- {"version":3,"file":"abstract-password-reset.js","sourceRoot":"","sources":["../../client/components/abstract-password-reset.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\nimport '@operato/lottie-player'\nimport '../components/profile-component'\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport { css, html, nothing } from 'lit'\nimport { property, query } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\nimport { isSafari } from '@operato/utils'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign'\nimport { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule'\nimport { AbstractAuthPage } from './abstract-auth-page'\n\nexport abstract class AbstractPasswordReset extends AbstractAuthPage {\n static styles = [\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\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 }) token?: string\n\n @query('#confirm-password') confirmPass!: HTMLElement\n\n private passwordPattern: string = ''\n private passwordHelp: string = ''\n\n abstract get submitButtonLabel(): string\n\n render() {\n var { icon, title, description } = this.applicationMeta\n const { disableUserFavoredLanguage, languages } = this.data || {}\n\n return html`\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.title}\"></ox-i18n></h3>\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 <input name=\"token\" type=\"hidden\" .value=${this.token || ''} required />\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('label.password'))}\n pattern=${this.passwordPattern || ''}\n supporting-text=${this.passwordHelp}\n autocomplete=\"off\"\n @input=${e => {\n var val = e.target.value\n this.confirmPass.setAttribute('pattern', val.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '[$&]'))\n }}\n required\n ></md-filled-text-field>\n </div>\n\n <div class=\"field\">\n <md-filled-text-field\n id=\"confirm-password\"\n name=\"confirm-password\"\n type=\"password\"\n label=${String(i18next.t('field.confirm password'))}\n autocomplete=\"off\"\n required\n ></md-filled-text-field>\n </div>\n\n <md-elevated-button id=\"submit-button\" type=\"submit\" @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"${this.submitButtonLabel}\"></ox-i18n>\n </md-elevated-button>\n\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-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 </form>\n </div>\n </div>\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 `\n }\n\n updated(changed) {\n super.updated(changed)\n if (changed.has('data')) {\n this.token = this.data.token\n }\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n timer: -1\n })\n }\n }\n }\n\n languageUpdated() {\n this.passwordPattern = generatePasswordPatternRegExp(this.data.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.data.passwordRule)\n }\n\n async submit() {\n this.formEl.submit()\n }\n}\n"]}
1
+ {"version":3,"file":"abstract-password-reset.js","sourceRoot":"","sources":["../../client/components/abstract-password-reset.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/textfield/filled-text-field.js'\n\nimport '@operato/i18n/ox-i18n.js'\nimport '@operato/i18n/ox-i18n-selector.js'\nimport '@operato/layout/ox-snack-bar.js'\n\nimport '../components/profile-component.js'\n\nimport { css, html, nothing } from 'lit'\nimport { property, query } from 'lit/decorators.js'\n\nimport { i18next } from '@operato/i18n'\n\nimport { AUTH_STYLE_SIGN } from '../auth-style-sign.js'\nimport { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule.js'\nimport { AbstractAuthPage } from './abstract-auth-page.js'\n\nexport abstract class AbstractPasswordReset extends AbstractAuthPage {\n static styles = [\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\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 }) token?: string\n\n @query('#confirm-password') confirmPass!: HTMLElement\n\n private passwordPattern: string = ''\n private passwordHelp: string = ''\n\n abstract get submitButtonLabel(): string\n\n render() {\n var { icon, title, description } = this.applicationMeta\n const { disableUserFavoredLanguage, languages } = this.data || {}\n\n return html`\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.title}\"></ox-i18n></h3>\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 <input name=\"token\" type=\"hidden\" .value=${this.token || ''} required />\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('label.password'))}\n pattern=${this.passwordPattern || ''}\n supporting-text=${this.passwordHelp}\n autocomplete=\"off\"\n @input=${e => {\n var val = e.target.value\n this.confirmPass.setAttribute('pattern', val.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '[$&]'))\n }}\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <div class=\"field\">\n <md-filled-text-field\n id=\"confirm-password\"\n name=\"confirm-password\"\n type=\"password\"\n label=${String(i18next.t('field.confirm password'))}\n autocomplete=\"off\"\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <md-elevated-button id=\"submit-button\" type=\"button\" @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"${this.submitButtonLabel}\"></ox-i18n>\n </md-elevated-button>\n\n ${!disableUserFavoredLanguage\n ? html` <div id=\"locale-area\">\n <label for=\"locale-selector\"><md-icon>language</md-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 </form>\n </div>\n </div>\n\n <ox-snack-bar id=\"snackbar\" level=\"error\" .message=${this.message}></ox-snack-bar>\n `\n }\n\n updated(changed) {\n super.updated(changed)\n\n if (changed.has('data')) {\n this.token = this.data.token\n }\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n timer: -1\n })\n }\n }\n }\n\n languageUpdated() {\n this.passwordPattern = generatePasswordPatternRegExp(this.data.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.data.passwordRule)\n }\n\n async submit() {\n this.formEl.submit()\n }\n}\n"]}
@@ -25,30 +25,31 @@ export class AbstractSign extends AbstractAuthPage {
25
25
  }
26
26
  get formfields() {
27
27
  var _a;
28
- const email = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.email) || '';
28
+ const username = ((_a = this.data) === null || _a === void 0 ? void 0 : _a.username) || '';
29
29
  const autocompletable = this.autocompletable;
30
30
  return html `
31
31
  <input id="redirectTo" type="hidden" name="redirectTo" .value=${this.redirectTo || '/'} />
32
32
 
33
33
  <div class="field">
34
34
  <md-filled-text-field
35
- name="email"
36
- type="email"
37
- label=${String(i18next.t('field.email'))}
35
+ name="username"
36
+ type="text"
37
+ label=${String(i18next.t('field.user-id or email'))}
38
38
  required
39
- .value=${email}
40
- autocomplete=${autocompletable ? "username" : "off"}
39
+ .value=${username}
40
+ autocomplete=${autocompletable ? 'username' : 'off'}
41
41
  autocapitalize="off"
42
+ pattern="^(?:[A-Za-z0-9]*|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,})$"
42
43
  @input=${(e) => {
43
44
  const target = e.target;
44
45
  if (target.validity.typeMismatch) {
45
- target.setCustomValidity(i18next.t('text.invalid-email'));
46
+ target.setCustomValidity(i18next.t('text.invalid-username'));
46
47
  }
47
48
  else {
48
49
  target.setCustomValidity('');
49
50
  }
50
51
  }}
51
- ><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
52
+ ><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
52
53
  >
53
54
  </div>
54
55
  <div class="field">
@@ -56,14 +57,14 @@ export class AbstractSign extends AbstractAuthPage {
56
57
  name="password"
57
58
  type="password"
58
59
  label=${String(i18next.t('field.password'))}
59
- autocomplete=${autocompletable ? "current-password" : "off"}
60
+ autocomplete=${autocompletable ? 'current-password' : 'off'}
60
61
  required
61
- ><md-icon slot="leading-icon">vpn_key</md-icon></md-filled-text-field
62
+ ><md-icon slot="leading-icon">password</md-icon></md-filled-text-field
62
63
  >
63
64
  </div>
64
65
 
65
66
  <div class="submit-buttons-container">
66
- <md-elevated-button class="submit-button" type="submit" raised @click=${e => this._onSubmit(e)}>
67
+ <md-elevated-button class="submit-button" type="button" raised @click=${e => this._onSubmit(e)}>
67
68
  <ox-i18n msgid="field.${this.pageName}"> </ox-i18n>
68
69
  </md-elevated-button>
69
70
  ${isAvailableWebauthn
@@ -1 +1 @@
1
- {"version":3,"file":"abstract-sign.js","sourceRoot":"","sources":["../../client/components/abstract-sign.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/i18n/ox-i18n.js'\n\nimport { html, nothing } from 'lit'\nimport { startAuthentication } from '@simplewebauthn/browser'\n\nimport { i18next } from '@operato/i18n'\nimport { notify } from '@operato/layout'\n\nimport { AbstractAuthPage } from './abstract-auth-page.js'\n\nconst isAvailableWebauthn = 'PublicKeyCredential' in window\n\ninterface AssertionResponse {\n id: string\n rawId?: number[]\n response: {\n authenticatorData: string\n clientDataJSON: string\n signature: string\n userHandle: string | null\n }\n type: PublicKeyCredentialType\n authenticatorAttachment?: AuthenticatorAttachment\n}\n\nexport abstract class AbstractSign extends AbstractAuthPage {\n async submit() {\n this.formEl.submit()\n }\n\n updated(changed) {\n super.updated(changed)\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n level: 'error',\n timer: -1\n })\n }\n }\n }\n\n get formfields() {\n const email = this.data?.email || ''\n const autocompletable = this.autocompletable\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"email\"\n type=\"email\"\n label=${String(i18next.t('field.email'))}\n required\n .value=${email}\n autocomplete=${autocompletable ? \"username\" : \"off\"}\n autocapitalize=\"off\"\n @input=${(e: Event) => {\n const target = e.target as HTMLInputElement\n if (target.validity.typeMismatch) {\n target.setCustomValidity(i18next.t('text.invalid-email'))\n } else {\n target.setCustomValidity('')\n }\n }}\n ><md-icon slot=\"leading-icon\">mail</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=${autocompletable ? \"current-password\" : \"off\"}\n required\n ><md-icon slot=\"leading-icon\">vpn_key</md-icon></md-filled-text-field\n >\n </div>\n\n <div class=\"submit-buttons-container\">\n <md-elevated-button class=\"submit-button\" type=\"submit\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-button>\n ${isAvailableWebauthn\n ? html` <md-icon class=\"fingerprint\" raised @click=${e => this.authenticateUser()}> fingerprint </md-icon>`\n : nothing}\n </div>\n `\n }\n\n async authenticateUser() {\n try {\n const options = await fetch('/auth/signin-webauthn/challenge').then(res => res.json())\n const assertionResp = await startAuthentication(options)\n const verification = await fetch('/auth/signin-webauthn', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(assertionResp)\n }).then(res => res.json())\n\n if (verification.verified) {\n const { redirectURL } = verification\n \n if (redirectURL) {\n window.location.href = redirectURL\n }\n } else {\n notify({\n level: 'error',\n message: verification.message\n })\n }\n \n } catch (error) {\n notify({\n level: 'error',\n message: i18next.t('error.authn verification failed')\n })\n }\n }\n}\n"]}
1
+ {"version":3,"file":"abstract-sign.js","sourceRoot":"","sources":["../../client/components/abstract-sign.ts"],"names":[],"mappings":"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","sourcesContent":["import '@operato/i18n/ox-i18n.js'\n\nimport { html, nothing } from 'lit'\nimport { startAuthentication } from '@simplewebauthn/browser'\n\nimport { i18next } from '@operato/i18n'\nimport { notify } from '@operato/layout'\n\nimport { AbstractAuthPage } from './abstract-auth-page.js'\n\nconst isAvailableWebauthn = 'PublicKeyCredential' in window\n\ninterface AssertionResponse {\n id: string\n rawId?: number[]\n response: {\n authenticatorData: string\n clientDataJSON: string\n signature: string\n userHandle: string | null\n }\n type: PublicKeyCredentialType\n authenticatorAttachment?: AuthenticatorAttachment\n}\n\nexport abstract class AbstractSign extends AbstractAuthPage {\n async submit() {\n this.formEl.submit()\n }\n\n updated(changed) {\n super.updated(changed)\n\n if (changed.has('message')) {\n if (!this.message) {\n this.hideSnackbar()\n } else {\n this.showSnackbar({\n level: 'error',\n timer: -1\n })\n }\n }\n }\n\n get formfields() {\n const username = this.data?.username || ''\n const autocompletable = this.autocompletable\n\n return html`\n <input id=\"redirectTo\" type=\"hidden\" name=\"redirectTo\" .value=${this.redirectTo || '/'} />\n\n <div class=\"field\">\n <md-filled-text-field\n name=\"username\"\n type=\"text\"\n label=${String(i18next.t('field.user-id or email'))}\n required\n .value=${username}\n autocomplete=${autocompletable ? 'username' : 'off'}\n autocapitalize=\"off\"\n pattern=\"^(?:[A-Za-z0-9]*|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,})$\"\n @input=${(e: Event) => {\n const target = e.target as HTMLInputElement\n if (target.validity.typeMismatch) {\n target.setCustomValidity(i18next.t('text.invalid-username'))\n } else {\n target.setCustomValidity('')\n }\n }}\n ><md-icon slot=\"leading-icon\">id_card</md-icon></md-filled-text-field\n >\n </div>\n <div class=\"field\">\n <md-filled-text-field\n name=\"password\"\n type=\"password\"\n label=${String(i18next.t('field.password'))}\n autocomplete=${autocompletable ? 'current-password' : 'off'}\n required\n ><md-icon slot=\"leading-icon\">password</md-icon></md-filled-text-field\n >\n </div>\n\n <div class=\"submit-buttons-container\">\n <md-elevated-button class=\"submit-button\" type=\"button\" raised @click=${e => this._onSubmit(e)}>\n <ox-i18n msgid=\"field.${this.pageName}\"> </ox-i18n>\n </md-elevated-button>\n ${isAvailableWebauthn\n ? html` <md-icon class=\"fingerprint\" raised @click=${e => this.authenticateUser()}> fingerprint </md-icon>`\n : nothing}\n </div>\n `\n }\n\n async authenticateUser() {\n try {\n const options = await fetch('/auth/signin-webauthn/challenge').then(res => res.json())\n const assertionResp = await startAuthentication(options)\n const verification = await fetch('/auth/signin-webauthn', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json'\n },\n body: JSON.stringify(assertionResp)\n }).then(res => res.json())\n\n if (verification.verified) {\n const { redirectURL } = verification\n\n if (redirectURL) {\n window.location.href = redirectURL\n }\n } else {\n notify({\n level: 'error',\n message: verification.message\n })\n }\n } catch (error) {\n notify({\n level: 'error',\n message: i18next.t('error.authn verification failed')\n })\n }\n }\n}\n"]}
@@ -3,7 +3,7 @@ import { css, html, LitElement } from 'lit';
3
3
  import { customElement, property, query } from 'lit/decorators.js';
4
4
  import { i18next, localize } from '@operato/i18n';
5
5
  import { auth } from '@things-factory/auth-base/dist-client/auth.js';
6
- import { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule';
6
+ import { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule.js';
7
7
  let ChangePassword = class ChangePassword extends localize(i18next)(LitElement) {
8
8
  constructor() {
9
9
  super(...arguments);
@@ -1 +1 @@
1
- {"version":3,"file":"change-password.js","sourceRoot":"","sources":["../../client/components/change-password.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { auth } from '@things-factory/auth-base/dist-client/auth.js'\nimport { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule'\n\n@customElement('change-password')\nexport class ChangePassword extends localize(i18next)(LitElement) {\n static styles = [\n css`\n * {\n box-sizing: border-box;\n }\n\n *:focus {\n outline: none;\n }\n\n form {\n display: flex;\n flex-direction: column;\n }\n\n input {\n border: var(--change-password-field-border);\n border-radius: var(--change-password-field-border-radius);\n margin: var(--change-password-field-margin);\n padding: var(--change-password-field-padding);\n\n font: var(--change-password-field-font);\n width: var(--change-password-field-width);\n }\n\n input:focus {\n border: 1px solid var(--focus-background-color);\n }\n\n ::placeholder {\n font-size: 0.8rem;\n text-transform: capitalize;\n }\n\n md-elevated-button {\n margin: var(--spacing-small) auto var(--spacing-medium) auto;\n text-transform: capitalize;\n }\n\n button {\n background-color: var(--secondary-color, #394e64);\n margin: 2px 2px 10px 2px;\n height: var(--button-height, 28px);\n color: var(--button-color, #fff);\n font: var(--button-font);\n border-radius: var(--button-radius, 5px);\n border: var(--button-border, 1px solid transparent);\n line-height: 1.5;\n }\n\n button:hover,\n button:active {\n background-color: var(--button-active-background-color, #22a6a7);\n border: var(--button-active-border);\n }\n\n .helper-text {\n font-size: 12px;\n color: var(--md-sys-color-) #6c757d;\n margin-top: 4px;\n display: block; /* 텍스트를 입력 필드 아래에 배치 */\n line-height: 1.5; /* 텍스트 줄 간격 조절 */\n }\n `\n ]\n\n @property({ type: Object }) passwordRule: {\n lowerCase?: boolean\n upperCase?: boolean\n digit?: boolean\n specialCharacter?: boolean\n allowRepeat?: boolean\n useTightPattern?: boolean\n useLoosePattern?: boolean\n tightCharacterLength?: number\n looseCharacterLength?: number\n } = {}\n\n @query('form') form!: HTMLFormElement\n\n private passwordPattern: string = ''\n private passwordHelp: string = ''\n\n render() {\n return html`\n <form>\n <div class=\"field\">\n <input type=\"password\" name=\"current_pass\" placeholder=${i18next.t('text.current password')} required />\n </div>\n <span id=\"password-helper\" class=\"helper-text\">${this.passwordHelp}</span>\n <div class=\"field\">\n <input\n type=\"password\"\n name=\"new_pass\"\n placeholder=${i18next.t('text.new password')}\n required\n pattern=${this.passwordPattern}\n aria-describedby=\"password-helper\"\n />\n </div>\n <div class=\"field\">\n <input type=\"password\" name=\"confirm_pass\" placeholder=${i18next.t('text.confirm password')} required />\n </div>\n\n <md-elevated-button @click=${this.submit.bind(this)}>${i18next.t('text.change password')}</md-elevated-button>\n </form>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('passwordRule')) {\n this.passwordPattern = generatePasswordPatternRegExp(this.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.passwordRule)\n }\n }\n\n languageUpdated() {\n this.passwordPattern = generatePasswordPatternRegExp(this.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.passwordRule)\n }\n\n async submit() {\n const formData = new FormData(this.form)\n let params = {}\n for (const [key, value] of formData.entries()) {\n if (!value) {\n const placeholder = (this.form.querySelector(`[name=${key}]`) as HTMLInputElement)?.placeholder\n return this.showToast(i18next.t('error.value is empty', { value: placeholder || key }))\n }\n params[key] = value\n }\n\n if (params['new_pass'] !== params['confirm_pass']) {\n return this.showToast(i18next.t('error.new-password-and-confirm-password-do-not-match'))\n }\n\n auth.changePassword(params)\n this.form.reset()\n }\n\n showToast(message) {\n document.dispatchEvent(new CustomEvent('notify', { detail: { message } }))\n }\n}\n"]}
1
+ {"version":3,"file":"change-password.js","sourceRoot":"","sources":["../../client/components/change-password.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, PropertyValues } from 'lit'\nimport { customElement, property, query } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { auth } from '@things-factory/auth-base/dist-client/auth.js'\nimport { generatePasswordPatternHelp, generatePasswordPatternRegExp } from '../utils/password-rule.js'\n\n@customElement('change-password')\nexport class ChangePassword extends localize(i18next)(LitElement) {\n static styles = [\n css`\n * {\n box-sizing: border-box;\n }\n\n *:focus {\n outline: none;\n }\n\n form {\n display: flex;\n flex-direction: column;\n }\n\n input {\n border: var(--change-password-field-border);\n border-radius: var(--change-password-field-border-radius);\n margin: var(--change-password-field-margin);\n padding: var(--change-password-field-padding);\n\n font: var(--change-password-field-font);\n width: var(--change-password-field-width);\n }\n\n input:focus {\n border: 1px solid var(--focus-background-color);\n }\n\n ::placeholder {\n font-size: 0.8rem;\n text-transform: capitalize;\n }\n\n md-elevated-button {\n margin: var(--spacing-small) auto var(--spacing-medium) auto;\n text-transform: capitalize;\n }\n\n button {\n background-color: var(--secondary-color, #394e64);\n margin: 2px 2px 10px 2px;\n height: var(--button-height, 28px);\n color: var(--button-color, #fff);\n font: var(--button-font);\n border-radius: var(--button-radius, 5px);\n border: var(--button-border, 1px solid transparent);\n line-height: 1.5;\n }\n\n button:hover,\n button:active {\n background-color: var(--button-active-background-color, #22a6a7);\n border: var(--button-active-border);\n }\n\n .helper-text {\n font-size: 12px;\n color: var(--md-sys-color-) #6c757d;\n margin-top: 4px;\n display: block; /* 텍스트를 입력 필드 아래에 배치 */\n line-height: 1.5; /* 텍스트 줄 간격 조절 */\n }\n `\n ]\n\n @property({ type: Object }) passwordRule: {\n lowerCase?: boolean\n upperCase?: boolean\n digit?: boolean\n specialCharacter?: boolean\n allowRepeat?: boolean\n useTightPattern?: boolean\n useLoosePattern?: boolean\n tightCharacterLength?: number\n looseCharacterLength?: number\n } = {}\n\n @query('form') form!: HTMLFormElement\n\n private passwordPattern: string = ''\n private passwordHelp: string = ''\n\n render() {\n return html`\n <form>\n <div class=\"field\">\n <input type=\"password\" name=\"current_pass\" placeholder=${i18next.t('text.current password')} required />\n </div>\n <span id=\"password-helper\" class=\"helper-text\">${this.passwordHelp}</span>\n <div class=\"field\">\n <input\n type=\"password\"\n name=\"new_pass\"\n placeholder=${i18next.t('text.new password')}\n required\n pattern=${this.passwordPattern}\n aria-describedby=\"password-helper\"\n />\n </div>\n <div class=\"field\">\n <input type=\"password\" name=\"confirm_pass\" placeholder=${i18next.t('text.confirm password')} required />\n </div>\n\n <md-elevated-button @click=${this.submit.bind(this)}>${i18next.t('text.change password')}</md-elevated-button>\n </form>\n `\n }\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('passwordRule')) {\n this.passwordPattern = generatePasswordPatternRegExp(this.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.passwordRule)\n }\n }\n\n languageUpdated() {\n this.passwordPattern = generatePasswordPatternRegExp(this.passwordRule).source\n this.passwordHelp = generatePasswordPatternHelp(this.passwordRule)\n }\n\n async submit() {\n const formData = new FormData(this.form)\n let params = {}\n for (const [key, value] of formData.entries()) {\n if (!value) {\n const placeholder = (this.form.querySelector(`[name=${key}]`) as HTMLInputElement)?.placeholder\n return this.showToast(i18next.t('error.value is empty', { value: placeholder || key }))\n }\n params[key] = value\n }\n\n if (params['new_pass'] !== params['confirm_pass']) {\n return this.showToast(i18next.t('error.new-password-and-confirm-password-do-not-match'))\n }\n\n auth.changePassword(params)\n this.form.reset()\n }\n\n showToast(message) {\n document.dispatchEvent(new CustomEvent('notify', { detail: { message } }))\n }\n}\n"]}
@@ -8,7 +8,7 @@ declare const ContactUs_base: (new (...args: any[]) => LitElement) & typeof LitE
8
8
  export declare class ContactUs extends ContactUs_base {
9
9
  static get styles(): import("lit").CSSResult[];
10
10
  dialog: HTMLElement & {
11
- open: boolean;
11
+ show: () => void;
12
12
  };
13
13
  subjectInput: HTMLInputElement;
14
14
  senderInput: HTMLInputElement;
@@ -30,15 +30,16 @@ let ContactUs = class ContactUs extends localize(i18next)(LitElement) {
30
30
  }
31
31
  render() {
32
32
  return html `
33
- <md-elevated-button @click=${e => (this.dialog.open = true)}>${i18next.t('button.need help')}</md-elevated-button>
33
+ <md-elevated-button @click=${e => this.dialog.show()}>${i18next.t('button.need help')}</md-elevated-button>
34
34
 
35
35
  <md-dialog id="dialog" heading=${i18next.t('title.need help')}>
36
- <form action="" method="POST">
36
+ <form action="" method="post">
37
37
  <input id="subject-input" name="subject" type="hidden" />
38
38
  <input id="sender-input" name="sender" type="hidden" />
39
39
  <input id="content-input" name="content" type="hidden" />
40
40
  </form>
41
- <div id="input-form">
41
+
42
+ <div id="input-form" slot="content">
42
43
  <md-filled-text-field
43
44
  type="text"
44
45
  label=${i18next.t('label.subject')}
@@ -49,6 +50,7 @@ let ContactUs = class ContactUs extends localize(i18next)(LitElement) {
49
50
  this.subjectInput.value = val;
50
51
  }}
51
52
  ></md-filled-text-field>
53
+
52
54
  <md-filled-text-field
53
55
  type="text"
54
56
  name="sender"
@@ -59,6 +61,7 @@ let ContactUs = class ContactUs extends localize(i18next)(LitElement) {
59
61
  this.senderInput.value = val;
60
62
  }}
61
63
  ></md-filled-text-field>
64
+
62
65
  <md-filled-text-field
63
66
  name="content"
64
67
  type="textarea"
@@ -70,11 +73,11 @@ let ContactUs = class ContactUs extends localize(i18next)(LitElement) {
70
73
  this.contentInput.value = val;
71
74
  }}
72
75
  ></md-filled-text-field>
76
+
77
+ <md-elevated-button slot="primaryAction" type="button" @click=${e => this._submit(e)}
78
+ >${i18next.t('button.submit')}</md-elevated-button
79
+ >
73
80
  </div>
74
- <md-elevated-button slot="primaryAction" type="submit" @click=${e => this._submit(e)}
75
- >${i18next.t('button.submit')}</md-elevated-button
76
- >
77
- <md-text-button slot="secondaryAction" dialogAction="cancel">${i18next.t('button.cancel')}</md-text-button>
78
81
  </md-dialog>
79
82
  `;
80
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"contact-us.js","sourceRoot":"","sources":["../../client/components/contact-us.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/textfield/filled-text-field.js'\nimport '@material/web/dialog/dialog.js'\n\nimport '@operato/i18n'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, query } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { auth } from '@things-factory/auth-base/dist-client/auth.js'\n\n@customElement('contact-us')\nexport class ContactUs extends localize(i18next)(LitElement) {\n static get styles() {\n return [\n css`\n * {\n box-sizing: border-box;\n }\n\n *:focus {\n outline: none;\n }\n\n #input-form {\n display: grid;\n grid-template-rows: 1fr 1fr 3fr;\n grid-gap: 10px 0;\n }\n `\n ]\n }\n\n @query('#dialog') dialog!: HTMLElement & { open: boolean }\n @query('#subject-input') subjectInput!: HTMLInputElement\n @query('#sender-input') senderInput!: HTMLInputElement\n @query('#content-input') contentInput!: HTMLInputElement\n\n render() {\n return html`\n <md-elevated-button @click=${e => (this.dialog.open = true)}>${i18next.t('button.need help')}</md-elevated-button>\n\n <md-dialog id=\"dialog\" heading=${i18next.t('title.need help')}>\n <form action=\"\" method=\"POST\">\n <input id=\"subject-input\" name=\"subject\" type=\"hidden\" />\n <input id=\"sender-input\" name=\"sender\" type=\"hidden\" />\n <input id=\"content-input\" name=\"content\" type=\"hidden\" />\n </form>\n <div id=\"input-form\">\n <md-filled-text-field\n type=\"text\"\n label=${i18next.t('label.subject')}\n dialogInitialFocus\n required\n @input=${e => {\n const val = e.target.value\n this.subjectInput.value = val\n }}\n ></md-filled-text-field>\n <md-filled-text-field\n type=\"text\"\n name=\"sender\"\n label=${i18next.t('label.email')}\n required\n @input=${e => {\n const val = e.target.value\n this.senderInput.value = val\n }}\n ></md-filled-text-field>\n <md-filled-text-field\n name=\"content\"\n type=\"textarea\"\n label=${i18next.t('label.content')}\n required\n @keydown=${e => e.stopPropagation()}\n @input=${e => {\n const val = e.target.value\n this.contentInput.value = val\n }}\n ></md-filled-text-field>\n </div>\n <md-elevated-button slot=\"primaryAction\" type=\"submit\" @click=${e => this._submit(e)}\n >${i18next.t('button.submit')}</md-elevated-button\n >\n <md-text-button slot=\"secondaryAction\" dialogAction=\"cancel\">${i18next.t('button.cancel')}</md-text-button>\n </md-dialog>\n `\n }\n\n _checkValidity(): boolean {\n return false\n }\n\n _submit(e: MouseEvent) {\n if (!this._checkValidity()) return\n\n const form = e.target as HTMLFormElement\n\n const formData = new FormData(form)\n let json = {}\n\n //convert form into json\n for (const [key, value] of formData.entries()) {\n json[key] = value\n }\n\n auth.changePassword(json)\n\n form.reset()\n }\n}\n"]}
1
+ {"version":3,"file":"contact-us.js","sourceRoot":"","sources":["../../client/components/contact-us.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.js'\nimport '@material/web/button/elevated-button.js'\nimport '@material/web/textfield/filled-text-field.js'\nimport '@material/web/dialog/dialog.js'\n\nimport '@operato/i18n'\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, query } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { auth } from '@things-factory/auth-base/dist-client/auth.js'\n\n@customElement('contact-us')\nexport class ContactUs extends localize(i18next)(LitElement) {\n static get styles() {\n return [\n css`\n * {\n box-sizing: border-box;\n }\n\n *:focus {\n outline: none;\n }\n\n #input-form {\n display: grid;\n grid-template-rows: 1fr 1fr 3fr;\n grid-gap: 10px 0;\n }\n `\n ]\n }\n\n @query('#dialog') dialog!: HTMLElement & { show: () => void }\n @query('#subject-input') subjectInput!: HTMLInputElement\n @query('#sender-input') senderInput!: HTMLInputElement\n @query('#content-input') contentInput!: HTMLInputElement\n\n render() {\n return html`\n <md-elevated-button @click=${e => this.dialog.show()}>${i18next.t('button.need help')}</md-elevated-button>\n\n <md-dialog id=\"dialog\" heading=${i18next.t('title.need help')}>\n <form action=\"\" method=\"post\">\n <input id=\"subject-input\" name=\"subject\" type=\"hidden\" />\n <input id=\"sender-input\" name=\"sender\" type=\"hidden\" />\n <input id=\"content-input\" name=\"content\" type=\"hidden\" />\n </form>\n\n <div id=\"input-form\" slot=\"content\">\n <md-filled-text-field\n type=\"text\"\n label=${i18next.t('label.subject')}\n dialogInitialFocus\n required\n @input=${e => {\n const val = e.target.value\n this.subjectInput.value = val\n }}\n ></md-filled-text-field>\n\n <md-filled-text-field\n type=\"text\"\n name=\"sender\"\n label=${i18next.t('label.email')}\n required\n @input=${e => {\n const val = e.target.value\n this.senderInput.value = val\n }}\n ></md-filled-text-field>\n\n <md-filled-text-field\n name=\"content\"\n type=\"textarea\"\n label=${i18next.t('label.content')}\n required\n @keydown=${e => e.stopPropagation()}\n @input=${e => {\n const val = e.target.value\n this.contentInput.value = val\n }}\n ></md-filled-text-field>\n\n <md-elevated-button slot=\"primaryAction\" type=\"button\" @click=${e => this._submit(e)}\n >${i18next.t('button.submit')}</md-elevated-button\n >\n </div>\n </md-dialog>\n `\n }\n\n _checkValidity(): boolean {\n return false\n }\n\n _submit(e: MouseEvent) {\n if (!this._checkValidity()) return\n\n const form = e.target as HTMLFormElement\n\n const formData = new FormData(form)\n let json = {}\n\n //convert form into json\n for (const [key, value] of formData.entries()) {\n json[key] = value\n }\n\n auth.changePassword(json)\n\n form.reset()\n }\n}\n"]}
@@ -4,24 +4,41 @@ import '@material/web/textfield/filled-text-field.js';
4
4
  import { css, html, LitElement } from 'lit';
5
5
  import { customElement, query } from 'lit/decorators.js';
6
6
  import { i18next } from '@operato/i18n';
7
+ function capitalize(str) {
8
+ return str ? str.charAt(0).toUpperCase() + str.slice(1) : '';
9
+ }
7
10
  let CreateUser = class CreateUser extends LitElement {
8
11
  render() {
9
12
  return html `
13
+ <md-filled-text-field
14
+ type="text"
15
+ name="username"
16
+ label=${capitalize(i18next.t('label.user-id'))}
17
+ pattern="^(?:[A-Za-z0-9]*|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,})$"
18
+ ><md-icon slot="leading-icon">badge</md-icon></md-filled-text-field
19
+ >
20
+
10
21
  <md-filled-text-field
11
22
  type="text"
12
23
  name="name"
13
- label=${String(i18next.t('label.x name', { x: i18next.t('label.user') }))}
14
- ></md-filled-text-field>
24
+ label=${capitalize(i18next.t('label.x name', { x: i18next.t('label.user') }))}
25
+ ><md-icon slot="leading-icon">id_card</md-icon></md-filled-text-field
26
+ >
15
27
 
16
- <md-filled-text-field type="email" name="email" label=${String(i18next.t('field.email'))}></md-filled-text-field>
28
+ <md-filled-text-field type="email" name="email" label=${capitalize(i18next.t('field.email'))}
29
+ ><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
30
+ >
17
31
 
18
32
  <md-outlined-button @click=${this.onCreateUser.bind(this)}
19
- >${String(i18next.t('button.create'))}</md-outlined-button
33
+ >${capitalize(i18next.t('button.create'))}</md-outlined-button
20
34
  >
21
35
  `;
22
36
  }
23
37
  async onCreateUser() {
24
38
  try {
39
+ if (!this.usernameInput.value) {
40
+ throw new Error(i18next.t('error.value is empty', { value: 'name' }));
41
+ }
25
42
  if (!this.emailInput.checkValidity()) {
26
43
  throw new Error(i18next.t('error.not valid pattern of type', { type: 'e-mail' }));
27
44
  }
@@ -29,10 +46,12 @@ let CreateUser = class CreateUser extends LitElement {
29
46
  throw new Error(i18next.t('error.value is empty', { value: 'name' }));
30
47
  }
31
48
  const user = {
49
+ username: this.usernameInput.value.trim(),
32
50
  name: this.nameInput.value.trim(),
33
51
  email: this.emailInput.value.trim()
34
52
  };
35
53
  await this.dispatchEvent(new CustomEvent('create-user', { detail: user }));
54
+ this.usernameInput.value = '';
36
55
  this.nameInput.value = '';
37
56
  this.emailInput.value = '';
38
57
  }
@@ -56,7 +75,7 @@ CreateUser.styles = css `
56
75
  box-shadow: var(--box-shadow);
57
76
 
58
77
  display: grid;
59
- grid-template-columns: 1fr 2fr auto;
78
+ grid-template-columns: 1fr 2fr 2fr auto;
60
79
  gap: 5px 15px;
61
80
  clear: both;
62
81
  max-width: var(--input-container-max-width);
@@ -84,6 +103,10 @@ __decorate([
84
103
  query('[name=name]'),
85
104
  __metadata("design:type", HTMLInputElement)
86
105
  ], CreateUser.prototype, "nameInput", void 0);
106
+ __decorate([
107
+ query('[name=username]'),
108
+ __metadata("design:type", HTMLInputElement)
109
+ ], CreateUser.prototype, "usernameInput", void 0);
87
110
  __decorate([
88
111
  query('[name=email]'),
89
112
  __metadata("design:type", HTMLInputElement)