@things-factory/auth-ui 7.0.1-alpha.88 → 7.0.1-alpha.90

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 (143) hide show
  1. package/client/auth-style-sign.ts +29 -18
  2. package/client/components/abstract-auth-page.ts +41 -22
  3. package/client/components/abstract-password-reset.ts +11 -9
  4. package/client/components/abstract-sign.ts +138 -0
  5. package/client/components/change-password.ts +2 -2
  6. package/client/components/contact-us.ts +18 -16
  7. package/client/components/create-domain-popup.ts +11 -7
  8. package/client/components/create-role.ts +8 -20
  9. package/client/components/create-user.ts +8 -16
  10. package/client/components/credential-manager.ts +64 -0
  11. package/client/components/invite-customer.ts +7 -12
  12. package/client/components/invite-user.ts +2 -7
  13. package/client/components/ownership-transfer-popup.ts +3 -3
  14. package/client/components/partner-role-editor.ts +9 -15
  15. package/client/components/profile-component.ts +124 -7
  16. package/client/components/role-privilege-editor.ts +10 -17
  17. package/client/components/user-role-editor.ts +27 -38
  18. package/client/entries/auth/activate.ts +17 -17
  19. package/client/entries/auth/checkin.ts +15 -19
  20. package/client/entries/auth/forgot-password.ts +8 -6
  21. package/client/entries/auth/result.ts +13 -12
  22. package/client/entries/auth/signup.ts +20 -24
  23. package/client/entries/oauth2/oauth2-decision-error-page.ts +2 -2
  24. package/client/entries/oauth2/oauth2-decision-page.ts +60 -55
  25. package/client/entries/public/home.ts +40 -18
  26. package/client/pages/app-binding/app-binding.ts +5 -9
  27. package/client/pages/app-binding/app-bindings.ts +2 -2
  28. package/client/pages/appliance/appliance.ts +6 -9
  29. package/client/pages/appliance/home.ts +3 -3
  30. package/client/pages/appliance/register.ts +1 -1
  31. package/client/pages/application/application.ts +30 -14
  32. package/client/pages/application/applications.ts +4 -12
  33. package/client/pages/application/register.ts +1 -1
  34. package/client/pages/attribute/attribute-set-management.ts +2 -0
  35. package/client/pages/auth-provider/auth-provider-management.ts +2 -0
  36. package/client/pages/domain/domain-management.ts +2 -0
  37. package/client/pages/user/user-management.ts +5 -5
  38. package/dist-client/auth-style-sign.js +29 -18
  39. package/dist-client/auth-style-sign.js.map +1 -1
  40. package/dist-client/components/abstract-auth-page.d.ts +4 -4
  41. package/dist-client/components/abstract-auth-page.js +40 -22
  42. package/dist-client/components/abstract-auth-page.js.map +1 -1
  43. package/dist-client/components/abstract-password-reset.d.ts +3 -2
  44. package/dist-client/components/abstract-password-reset.js +10 -9
  45. package/dist-client/components/abstract-password-reset.js.map +1 -1
  46. package/dist-client/components/abstract-sign.d.ts +3 -0
  47. package/dist-client/components/abstract-sign.js +110 -0
  48. package/dist-client/components/abstract-sign.js.map +1 -1
  49. package/dist-client/components/change-password.js +2 -2
  50. package/dist-client/components/change-password.js.map +1 -1
  51. package/dist-client/components/contact-us.d.ts +4 -4
  52. package/dist-client/components/contact-us.js +17 -16
  53. package/dist-client/components/contact-us.js.map +1 -1
  54. package/dist-client/components/create-domain-popup.d.ts +1 -1
  55. package/dist-client/components/create-domain-popup.js +11 -7
  56. package/dist-client/components/create-domain-popup.js.map +1 -1
  57. package/dist-client/components/create-role.d.ts +1 -1
  58. package/dist-client/components/create-role.js +7 -19
  59. package/dist-client/components/create-role.js.map +1 -1
  60. package/dist-client/components/create-user.js +6 -14
  61. package/dist-client/components/create-user.js.map +1 -1
  62. package/dist-client/components/credential-manager.d.ts +11 -0
  63. package/dist-client/components/credential-manager.js +64 -0
  64. package/dist-client/components/credential-manager.js.map +1 -0
  65. package/dist-client/components/invite-customer.js +5 -7
  66. package/dist-client/components/invite-customer.js.map +1 -1
  67. package/dist-client/components/invite-user.js +2 -7
  68. package/dist-client/components/invite-user.js.map +1 -1
  69. package/dist-client/components/ownership-transfer-popup.d.ts +1 -1
  70. package/dist-client/components/ownership-transfer-popup.js +3 -3
  71. package/dist-client/components/ownership-transfer-popup.js.map +1 -1
  72. package/dist-client/components/partner-role-editor.js +9 -15
  73. package/dist-client/components/partner-role-editor.js.map +1 -1
  74. package/dist-client/components/profile-component.d.ts +6 -0
  75. package/dist-client/components/profile-component.js +111 -7
  76. package/dist-client/components/profile-component.js.map +1 -1
  77. package/dist-client/components/role-privilege-editor.js +10 -17
  78. package/dist-client/components/role-privilege-editor.js.map +1 -1
  79. package/dist-client/components/user-role-editor.d.ts +2 -0
  80. package/dist-client/components/user-role-editor.js +26 -37
  81. package/dist-client/components/user-role-editor.js.map +1 -1
  82. package/dist-client/entries/auth/activate.d.ts +2 -1
  83. package/dist-client/entries/auth/activate.js +16 -17
  84. package/dist-client/entries/auth/activate.js.map +1 -1
  85. package/dist-client/entries/auth/checkin.d.ts +2 -2
  86. package/dist-client/entries/auth/checkin.js +13 -16
  87. package/dist-client/entries/auth/checkin.js.map +1 -1
  88. package/dist-client/entries/auth/forgot-password.d.ts +2 -1
  89. package/dist-client/entries/auth/forgot-password.js +7 -6
  90. package/dist-client/entries/auth/forgot-password.js.map +1 -1
  91. package/dist-client/entries/auth/result.d.ts +2 -2
  92. package/dist-client/entries/auth/result.js +12 -12
  93. package/dist-client/entries/auth/result.js.map +1 -1
  94. package/dist-client/entries/auth/signup.js +19 -24
  95. package/dist-client/entries/auth/signup.js.map +1 -1
  96. package/dist-client/entries/oauth2/oauth2-decision-error-page.d.ts +1 -1
  97. package/dist-client/entries/oauth2/oauth2-decision-error-page.js +2 -2
  98. package/dist-client/entries/oauth2/oauth2-decision-error-page.js.map +1 -1
  99. package/dist-client/entries/oauth2/oauth2-decision-page.d.ts +1 -1
  100. package/dist-client/entries/oauth2/oauth2-decision-page.js +59 -54
  101. package/dist-client/entries/oauth2/oauth2-decision-page.js.map +1 -1
  102. package/dist-client/entries/public/home.d.ts +3 -2
  103. package/dist-client/entries/public/home.js +40 -18
  104. package/dist-client/entries/public/home.js.map +1 -1
  105. package/dist-client/pages/app-binding/app-binding.d.ts +1 -1
  106. package/dist-client/pages/app-binding/app-binding.js +4 -9
  107. package/dist-client/pages/app-binding/app-binding.js.map +1 -1
  108. package/dist-client/pages/app-binding/app-bindings.js +2 -2
  109. package/dist-client/pages/app-binding/app-bindings.js.map +1 -1
  110. package/dist-client/pages/appliance/appliance.d.ts +1 -1
  111. package/dist-client/pages/appliance/appliance.js +5 -9
  112. package/dist-client/pages/appliance/appliance.js.map +1 -1
  113. package/dist-client/pages/appliance/home.js +3 -3
  114. package/dist-client/pages/appliance/home.js.map +1 -1
  115. package/dist-client/pages/appliance/register.js +1 -1
  116. package/dist-client/pages/appliance/register.js.map +1 -1
  117. package/dist-client/pages/application/application.js +26 -13
  118. package/dist-client/pages/application/application.js.map +1 -1
  119. package/dist-client/pages/application/applications.js +4 -12
  120. package/dist-client/pages/application/applications.js.map +1 -1
  121. package/dist-client/pages/application/register.js +1 -1
  122. package/dist-client/pages/application/register.js.map +1 -1
  123. package/dist-client/pages/attribute/attribute-set-management.d.ts +1 -0
  124. package/dist-client/pages/attribute/attribute-set-management.js +1 -0
  125. package/dist-client/pages/attribute/attribute-set-management.js.map +1 -1
  126. package/dist-client/pages/auth-provider/auth-provider-management.d.ts +1 -0
  127. package/dist-client/pages/auth-provider/auth-provider-management.js +1 -0
  128. package/dist-client/pages/auth-provider/auth-provider-management.js.map +1 -1
  129. package/dist-client/pages/domain/domain-management.d.ts +1 -0
  130. package/dist-client/pages/domain/domain-management.js +1 -0
  131. package/dist-client/pages/domain/domain-management.js.map +1 -1
  132. package/dist-client/pages/user/user-management.d.ts +1 -0
  133. package/dist-client/pages/user/user-management.js +4 -5
  134. package/dist-client/pages/user/user-management.js.map +1 -1
  135. package/dist-client/tsconfig.tsbuildinfo +1 -1
  136. package/package.json +5 -10
  137. package/translations/en.json +1 -0
  138. package/translations/ja.json +1 -0
  139. package/translations/ko.json +1 -0
  140. package/translations/ms.json +1 -0
  141. package/translations/zh.json +1 -0
  142. package/views/auth-page.html +2 -2
  143. package/views/oauth2-page.html +3 -3
@@ -7,7 +7,7 @@ import { i18next } from '@operato/i18n'
7
7
  class CreateUser extends LitElement {
8
8
  static styles = css`
9
9
  :host {
10
- --mdc-text-field-fill-color: var(--theme-white-color);
10
+ --md-text-field-fill-color: var(--theme-white-color);
11
11
  background-color: var(--theme-white-color);
12
12
  margin: var(--margin-wide) 0;
13
13
  padding: var(--padding-wide);
@@ -23,7 +23,7 @@ class CreateUser extends LitElement {
23
23
  align-items: center;
24
24
  }
25
25
 
26
- mwc-button {
26
+ md-outlined-button {
27
27
  margin: var(--input-margin);
28
28
  }
29
29
 
@@ -32,7 +32,7 @@ class CreateUser extends LitElement {
32
32
  grid-template-columns: 1fr 1fr;
33
33
  }
34
34
 
35
- mwc-button {
35
+ md-outlined-button {
36
36
  grid-column: span 2;
37
37
 
38
38
  margin: var(--input-margin);
@@ -45,19 +45,11 @@ class CreateUser extends LitElement {
45
45
 
46
46
  render() {
47
47
  return html`
48
- <mwc-textfield
49
- type="text"
50
- name="name"
51
- label=${String(i18next.t('label.x name', { x: i18next.t('label.user') }))}
52
- ></mwc-textfield>
53
-
54
- <mwc-textfield type="email" name="email" label=${String(i18next.t('field.email'))}></mwc-textfield>
55
-
56
- <mwc-button
57
- @click=${this.onCreateUser.bind(this)}
58
- outlined
59
- label=${String(i18next.t('button.create'))}
60
- ></mwc-button>
48
+ <md-outlined-text-field type="text" name="name" label=${String(i18next.t('label.x name', { x: i18next.t('label.user') }))}></md-outlined-text-field>
49
+
50
+ <md-outlined-text-field type="email" name="email" label=${String(i18next.t('field.email'))}></md-outlined-text-field>
51
+
52
+ <md-outlined-button @click=${this.onCreateUser.bind(this)}>${String(i18next.t('button.create'))}</md-outlined-button>
61
53
  `
62
54
  }
63
55
 
@@ -0,0 +1,64 @@
1
+ import gql from 'graphql-tag'
2
+ import { LitElement, html, css } from 'lit'
3
+ import { customElement, property } from 'lit/decorators.js'
4
+
5
+ import { client } from '@operato/graphql'
6
+
7
+ @customElement('credential-manager')
8
+ export class CredentialManager extends LitElement {
9
+ @property({ type: Array }) credentials: {
10
+ credentialId: string
11
+ }[] = []
12
+
13
+ static styles = css`
14
+ div {
15
+ margin: 20px;
16
+ }
17
+ button {
18
+ margin: 5px;
19
+ }
20
+ `
21
+
22
+ connectedCallback() {
23
+ super.connectedCallback()
24
+ this.fetchCredentials()
25
+ }
26
+
27
+ async fetchCredentials() {
28
+ const response = await fetch('/auth/credentials', {
29
+ method: 'GET',
30
+ credentials: 'include'
31
+ })
32
+ this.credentials = await response.json()
33
+ }
34
+
35
+ async deleteCredential(credentialId: string) {
36
+ const response = await fetch(`/credentials/${credentialId}`, {
37
+ method: 'DELETE',
38
+ credentials: 'include'
39
+ })
40
+ if (response.ok) {
41
+ this.fetchCredentials()
42
+ } else {
43
+ console.error('Failed to delete credential')
44
+ }
45
+ }
46
+
47
+ render() {
48
+ return html`
49
+ <div>
50
+ <h2>Manage Your WebAuthn Credentials</h2>
51
+ <ul>
52
+ ${this.credentials.map(
53
+ credential => html`
54
+ <li>
55
+ ${credential.credentialId}
56
+ <button @click=${() => this.deleteCredential(credential.credentialId)}>Delete</button>
57
+ </li>
58
+ `
59
+ )}
60
+ </ul>
61
+ </div>
62
+ `
63
+ }
64
+ }
@@ -18,7 +18,7 @@ class InviteCustomer extends localize(i18next)(LitElement) {
18
18
  min-width: 250px;
19
19
  font: var(--input-font);
20
20
  }
21
- mwc-button {
21
+ md-outlined-button {
22
22
  margin: var(--input-margin);
23
23
  }
24
24
  @media screen and (max-width: 480px) {
@@ -37,25 +37,20 @@ class InviteCustomer extends localize(i18next)(LitElement) {
37
37
  return html`
38
38
  <div>
39
39
  <input id="customer-name" required />
40
- <mwc-button
41
- @click=${this.invite.bind(this)}
42
- outlined
43
- icon="group_add"
44
- label=${String(i18next.t('label.invite customer'))}
45
- ></mwc-button>
40
+ <md-outlined-button @click=${this.invite.bind(this)}>
41
+ <md-icon slot="icon">group_add</md-icon>
42
+ ${String(i18next.t('label.invite customer'))}
43
+ </md-outlined-button>
46
44
  </div>
47
45
  `
48
46
  }
49
47
 
50
48
  async invite() {
51
49
  try {
52
- if (!this.customerNameInput.value)
53
- throw new Error(i18next.t('error.value is empty', { value: i18next.t('field.name') }))
50
+ if (!this.customerNameInput.value) throw new Error(i18next.t('error.value is empty', { value: i18next.t('field.name') }))
54
51
 
55
52
  if (this.customers.find(c => c.name?.toLowerCase() === this.customerNameInput.value.toLowerCase())) {
56
- throw new Error(
57
- i18next.t('error.x already exists in y', { x: this.customerNameInput.value, y: i18next.t('field.customer') })
58
- )
53
+ throw new Error(i18next.t('error.x already exists in y', { x: this.customerNameInput.value, y: i18next.t('field.customer') }))
59
54
  }
60
55
 
61
56
  if (
@@ -26,7 +26,7 @@ class InviteUser extends localize(i18next)(LitElement) {
26
26
  font: var(--input-font);
27
27
  }
28
28
 
29
- mwc-button {
29
+ md-outlined-button {
30
30
  margin: var(--input-margin);
31
31
  }
32
32
  `
@@ -36,12 +36,7 @@ class InviteUser extends localize(i18next)(LitElement) {
36
36
  render() {
37
37
  return html`
38
38
  <input name="email" type="email" required name="invite-email" autocapitalize="off" />
39
- <mwc-button
40
- @click=${this.invite.bind(this)}
41
- outlined
42
- icon="group_add"
43
- label=${String(i18next.t('label.invite user'))}
44
- ></mwc-button>
39
+ <md-outlined-button @click=${this.invite.bind(this)}> <md-icon slot="icon">group_add</md-icon>${String(i18next.t('label.invite user'))} </md-outlined-button>
45
40
  `
46
41
  }
47
42
 
@@ -1,4 +1,4 @@
1
- import '@material/mwc-button'
1
+ import '@material/web/button/elevated-button.js'
2
2
 
3
3
  import gql from 'graphql-tag'
4
4
  import { css, html, LitElement } from 'lit'
@@ -36,7 +36,7 @@ class OwnershipTransferPopup extends localize(i18next)(LitElement) {
36
36
  margin: auto;
37
37
  display: flex;
38
38
  }
39
- .input-container mwc-button {
39
+ .input-container md-elevated-button {
40
40
  margin: auto 0px auto var(--padding-wide);
41
41
  }
42
42
  `
@@ -52,7 +52,7 @@ class OwnershipTransferPopup extends localize(i18next)(LitElement) {
52
52
  <div>${i18next.t('text.please enter the email of the user you want to transfer owner')}</div>
53
53
  <div class="input-container">
54
54
  <input name="email" />
55
- <mwc-button raised @click=${this.transferOwnership}>${i18next.t('button.confirm')}</mwc-button>
55
+ <md-elevated-button @click=${this.transferOwnership}>${i18next.t('button.confirm')}</md-elevated-button>
56
56
  </div>
57
57
  </div>
58
58
  `
@@ -8,12 +8,14 @@ import { customElement, property, query } from 'lit/decorators.js'
8
8
  import { client, gqlContext } from '@operato/graphql'
9
9
  import { i18next, localize } from '@operato/i18n'
10
10
  import { OxPrompt } from '@operato/popup/ox-prompt.js'
11
+ import { ButtonContainerStyles } from '@operato/styles'
11
12
 
12
13
  import { RoleSelector } from './role-selector'
13
14
 
14
15
  @customElement('partner-role-editor')
15
16
  class PartnerRoleEditor extends localize(i18next)(LitElement) {
16
17
  static styles = [
18
+ ButtonContainerStyles,
17
19
  css`
18
20
  :host {
19
21
  display: flex;
@@ -24,16 +26,13 @@ class PartnerRoleEditor extends localize(i18next)(LitElement) {
24
26
  font: normal 15px var(--theme-font);
25
27
  color: var(--secondary-color);
26
28
  }
27
- [buttons] {
28
- margin: 0;
29
- padding: var(--padding-default);
30
- background-color: rgba(var(--primary-color-rgb), 0.2);
31
- }
32
- mwc-button {
29
+
30
+ md-elevated-button {
33
31
  margin-right: var(--padding-narrow);
34
32
  }
33
+
35
34
  [danger] {
36
- --mdc-theme-primary: var(--mdc-danger-button-primary-color);
35
+ --md-theme-primary: var(--md-danger-button-primary-color);
37
36
  }
38
37
  `
39
38
  ]
@@ -51,14 +50,9 @@ class PartnerRoleEditor extends localize(i18next)(LitElement) {
51
50
  return html`
52
51
  <role-selector .roles="${roles}" .userRoles="${grantingRoles}"></role-selector>
53
52
 
54
- <div buttons>
55
- <mwc-button @click=${this.onSave} raised label="${i18next.t('button.save')}"></mwc-button>
56
- <mwc-button
57
- @click=${this.onTerminateContract}
58
- raised
59
- danger
60
- label="${i18next.t('button.terminate contract')}"
61
- ></mwc-button>
53
+ <div class="button-container">
54
+ <md-elevated-button @click=${this.onSave}>${i18next.t('button.save')}</md-elevated-button>
55
+ <md-elevated-button @click=${this.onTerminateContract} danger>${i18next.t('button.terminate contract')}</md-elevated-button>
62
56
  </div>
63
57
  `
64
58
  }
@@ -4,13 +4,15 @@ import './change-password'
4
4
  import './delete-user-popup'
5
5
  import './my-login-history'
6
6
 
7
- import { css, html, LitElement } from 'lit'
7
+ import base64url from 'base64url'
8
+ import { css, html, LitElement, nothing } from 'lit'
8
9
  import { customElement, property, query, state } from 'lit/decorators.js'
9
10
 
10
11
  import { i18next, localize } from '@operato/i18n'
11
12
  import { notify, openPopup } from '@operato/layout'
12
13
  import { auth, getLanguages } from '@things-factory/auth-base/dist-client'
13
14
 
15
+ const isAvailableWebauthn = 'PublicKeyCredential' in window
14
16
  @customElement('profile-component')
15
17
  export class ProfileComponent extends localize(i18next)(LitElement) {
16
18
  static styles = [
@@ -36,12 +38,12 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
36
38
  }
37
39
 
38
40
  input {
39
- margin: var(--change-password-field-margin);
40
- border: var(--input-field-border);
41
- padding: var(--input-padding);
41
+ margin: var(--margin-narrow) 0;
42
+ border: 1px solid rgba(0, 0, 0, 0.2);
43
+ padding: 9px;
42
44
  border-radius: var(--border-radius);
43
- font: var(--input-font);
44
- width: var(--change-password-field-width);
45
+ font: var(--auth-input-field-font);
46
+ width: var(--auth-input-field-width);
45
47
  }
46
48
  input:focus {
47
49
  border: 1px solid var(--focus-background-color);
@@ -85,7 +87,7 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
85
87
  }
86
88
 
87
89
  [danger] {
88
- --mdc-theme-primary: var(--mdc-danger-button-primary-color);
90
+ --md-theme-primary: var(--md-danger-button-primary-color);
89
91
  }
90
92
 
91
93
  footer {
@@ -160,6 +162,14 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
160
162
 
161
163
  <change-password id="change-password"></change-password>
162
164
 
165
+ ${isAvailableWebauthn
166
+ ? html`
167
+ <md-text-button @click=${() => this.registerWebAuthn()}
168
+ >${i18next.t('button.security-key registration')}</md-text-button
169
+ >
170
+ `
171
+ : nothing}
172
+
163
173
  <footer>
164
174
  <p>
165
175
  ${i18next.t('text.click login history')}
@@ -233,4 +243,111 @@ export class ProfileComponent extends localize(i18next)(LitElement) {
233
243
  title: i18next.t('label.delete account')
234
244
  })
235
245
  }
246
+
247
+ async registerWebAuthn() {
248
+ const challenge = await fetch('/auth/register-webauthn/challenge', {
249
+ method: 'POST',
250
+ headers: {
251
+ 'Content-Type': 'application/json',
252
+ Accept: 'application/json'
253
+ },
254
+ body: JSON.stringify({ email: this.email }),
255
+ credentials: 'include'
256
+ })
257
+
258
+ if (!challenge.ok) {
259
+ notify({
260
+ level: 'error',
261
+ message: await challenge.text()
262
+ })
263
+
264
+ return
265
+ }
266
+
267
+ const options = await challenge.json()
268
+
269
+ const credential = (await navigator.credentials.create({
270
+ publicKey: {
271
+ rp: {
272
+ name: this.applicationMeta.title
273
+ },
274
+ user: {
275
+ /* options.user.id must be the user's email */
276
+ id: Uint8Array.from(base64url.toBuffer(options.user.id)).buffer,
277
+ name: options.user.name,
278
+ displayName: options.user.displayName
279
+ },
280
+ challenge: Uint8Array.from(atob(options.challenge), c => c.charCodeAt(0)),
281
+ pubKeyCredParams: [
282
+ {
283
+ type: 'public-key',
284
+ alg: -7 // ES256
285
+ },
286
+ {
287
+ type: 'public-key',
288
+ alg: -257 // RS256
289
+ }
290
+ ],
291
+ authenticatorSelection: {
292
+ userVerification: 'preferred'
293
+ }
294
+ }
295
+ })) as PublicKeyCredential
296
+
297
+ if (!credential) {
298
+ notify({
299
+ level: 'error',
300
+ message: 'can not get user credential'
301
+ })
302
+
303
+ return
304
+ }
305
+
306
+ const response = credential.response as AuthenticatorAttestationResponse
307
+
308
+ var body = {
309
+ response: {
310
+ clientDataJSON: Buffer.from(response.clientDataJSON).toString('base64'),
311
+ attestationObject: Buffer.from(response.attestationObject).toString('base64')
312
+ } as any
313
+ }
314
+
315
+ if (response.getTransports) {
316
+ body.response.transports = response.getTransports()
317
+ }
318
+
319
+ const signinResponse = await fetch('/auth/signin-webauthn', {
320
+ method: 'POST',
321
+ headers: {
322
+ 'Content-Type': 'application/json',
323
+ Accept: 'application/json'
324
+ },
325
+ body: JSON.stringify(body),
326
+ credentials: 'include'
327
+ })
328
+
329
+ if (!signinResponse.ok) {
330
+ notify({
331
+ level: 'error',
332
+ message: await signinResponse.text()
333
+ })
334
+ } else {
335
+ notify({
336
+ level: 'info',
337
+ message: i18next.t('text.user credential registered successfully')
338
+ })
339
+ }
340
+ }
341
+
342
+ get applicationMeta() {
343
+ var iconLink: HTMLLinkElement | null = document.querySelector('link[rel="application-icon"]')
344
+ var titleMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-name"]')
345
+ var descriptionMeta: HTMLMetaElement | null = document.querySelector('meta[name="application-description"]')
346
+
347
+ return {
348
+ icon: iconLink?.href || '',
349
+ title: titleMeta?.content || 'Things Factory',
350
+ description: descriptionMeta?.content || 'Reimagining Software'
351
+ }
352
+ }
236
353
  }
@@ -5,10 +5,12 @@ import { customElement, property } from 'lit/decorators.js'
5
5
  import { client, gqlContext } from '@operato/graphql'
6
6
  import { i18next, localize } from '@operato/i18n'
7
7
  import { OxPrompt } from '@operato/popup/ox-prompt.js'
8
+ import { ButtonContainerStyles } from '@operato/styles'
8
9
 
9
10
  @customElement('role-privilege-editor')
10
11
  class RolePrivilegeEditor extends localize(i18next)(LitElement) {
11
12
  static styles = [
13
+ ButtonContainerStyles,
12
14
  css`
13
15
  :host {
14
16
  display: flex;
@@ -49,21 +51,15 @@ class RolePrivilegeEditor extends localize(i18next)(LitElement) {
49
51
  font-weight: bold;
50
52
  }
51
53
 
52
- [buttons] {
53
- margin: 0;
54
- padding: 5px;
55
- background-color: rgba(var(--primary-color-rgb), 0.2);
56
- }
57
-
58
- mwc-button {
54
+ md-elevated-button {
59
55
  margin: 5px;
60
56
  background-color: var(--theme-white-color);
61
57
  }
62
58
 
63
59
  [danger] {
64
- --mdc-theme-primary: var(--mdc-danger-button-primary-color);
60
+ --md-theme-primary: var(--md-danger-button-primary-color);
65
61
  }
66
- [outlined] {
62
+ md-outlined-button {
67
63
  background-color: var(--theme-white-color);
68
64
  }
69
65
 
@@ -106,14 +102,11 @@ class RolePrivilegeEditor extends localize(i18next)(LitElement) {
106
102
  )}
107
103
  </ul>
108
104
 
109
- <div buttons>
110
- <mwc-button @click=${e => this.onSave()} outlined label=${String(i18next.t('button.save'))}></mwc-button>
111
- <mwc-button
112
- @click=${e => this.onDeleteRole()}
113
- raised
114
- danger
115
- label=${String(i18next.t('button.delete role'))}
116
- ></mwc-button>
105
+ <div class="button-container">
106
+ <md-elevated-button @click=${e => this.onSave()}>${String(i18next.t('button.save'))}</md-elevated-button>
107
+ <md-elevated-button @click=${e => this.onDeleteRole()} danger
108
+ >${String(i18next.t('button.delete role'))}</md-elevated-button
109
+ >
117
110
  </div>
118
111
  `
119
112
  }
@@ -1,3 +1,6 @@
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+
1
4
  import './ownership-transfer-popup'
2
5
  import './role-selector'
3
6
 
@@ -11,12 +14,13 @@ import { i18next } from '@operato/i18n'
11
14
  import { openPopup } from '@operato/layout'
12
15
  import { store } from '@operato/shell'
13
16
  import { OxPrompt } from '@operato/popup/ox-prompt.js'
14
-
17
+ import { ButtonContainerStyles } from '@operato/styles'
15
18
  import { RoleSelector } from './role-selector'
16
19
 
17
20
  @customElement('user-role-editor')
18
21
  class UserRoleEditor extends connect(store)(LitElement) {
19
22
  static styles = [
23
+ ButtonContainerStyles,
20
24
  css`
21
25
  :host {
22
26
  display: flex;
@@ -51,9 +55,9 @@ class UserRoleEditor extends connect(store)(LitElement) {
51
55
  [detail] {
52
56
  background-color: rgba(var(--primary-color-rgb), 0.05);
53
57
  }
54
- [detail] mwc-icon {
58
+ [detail] md-icon {
59
+ --md-icon-size: var(--fontsize-default);
55
60
  vertical-align: middle;
56
- --mdc-icon-size: var(--fontsize-default);
57
61
  color: var(--primary-color);
58
62
  }
59
63
  [detail] li {
@@ -63,20 +67,15 @@ class UserRoleEditor extends connect(store)(LitElement) {
63
67
  flex: 1;
64
68
  }
65
69
 
66
- [buttons] {
67
- margin: 0;
68
- padding: 5px;
69
- background-color: rgba(var(--primary-color-rgb), 0.2);
70
- }
71
-
72
- mwc-button {
70
+ md-elevated-button {
73
71
  margin: 5px;
74
72
  }
75
73
 
76
74
  [danger] {
77
- --mdc-theme-primary: var(--mdc-danger-button-primary-color);
75
+ --md-theme-primary: var(--md-danger-button-primary-color);
78
76
  }
79
- [outlined] {
77
+
78
+ md-outlined-button {
80
79
  background-color: var(--theme-white-color);
81
80
  }
82
81
 
@@ -117,7 +116,7 @@ class UserRoleEditor extends connect(store)(LitElement) {
117
116
  ? html`
118
117
  <li>
119
118
  <span>
120
- <mwc-icon>email</mwc-icon>
119
+ <md-icon>email</md-icon>
121
120
  ${user.email}
122
121
  </span>
123
122
  </li>
@@ -141,10 +140,9 @@ class UserRoleEditor extends connect(store)(LitElement) {
141
140
  `
142
141
  : ''}
143
142
 
144
- <div buttons>
143
+ <div class="button-container">
145
144
  ${this.isRoleEditable()
146
- ? html` <mwc-button
147
- raised
145
+ ? html` <md-elevated-button
148
146
  @click=${() => {
149
147
  const { availableRoles, selectedRoles } = Array.from(
150
148
  this.renderRoot.querySelectorAll('role-selector') as NodeListOf<RoleSelector>
@@ -169,46 +167,37 @@ class UserRoleEditor extends connect(store)(LitElement) {
169
167
  )
170
168
  this.onSave(user, availableRoles, selectedRoles)
171
169
  }}
172
- label=${String(i18next.t('button.save'))}
173
- ></mwc-button>`
170
+ >${String(i18next.t('button.save'))}</md-elevated-button
171
+ >`
174
172
  : ''}
175
173
  ${user.userType === 'user'
176
174
  ? html`
177
175
  ${this.isTransferable(user)
178
176
  ? html`
179
- <mwc-button
180
- raised
181
- danger
182
- @click=${() => this.onTransfer(user)}
183
- label=${String(i18next.t('button.transfer owner'))}
184
- ></mwc-button>
177
+ <md-elevated-button danger @click=${() => this.onTransfer(user)}
178
+ >${String(i18next.t('button.transfer owner'))}</md-elevated-button
179
+ >
185
180
  `
186
181
  : ''}
187
182
  ${this.isPasswordResettable(user)
188
- ? html`<mwc-button
189
- raised
190
- danger
191
- @click="${() => this.onResetPassword(user)}"
192
- label=${String(i18next.t('title.reset password'))}
193
- ></mwc-button>`
183
+ ? html`<md-elevated-button danger @click=${() => this.onResetPassword(user)}
184
+ >${String(i18next.t('title.reset password'))}</md-elevated-button
185
+ >`
194
186
  : ''}
195
187
  `
196
188
  : ''}
197
189
  ${this.isRemovable(user)
198
190
  ? html`
199
- <mwc-button
200
- raised
201
- danger
202
- label=${String(i18next.t('button.delete user'))}
203
- @click=${() => this.onDelete(user)}
204
- ></mwc-button>
191
+ <md-elevated-button danger @click=${() => this.onDelete(user)}
192
+ >${String(i18next.t('button.delete user'))}</md-elevated-button
193
+ >
205
194
  `
206
195
  : ''}
207
196
  ${this.isActivatable(user)
208
- ? html`<mwc-button raised danger @click="${() => this.onActivate(user)}" label="activate"></mwc-button>`
197
+ ? html`<md-elevated-button danger @click=${() => this.onActivate(user)}>activate</md-elevated-button>`
209
198
  : ''}
210
199
  ${this.isInactivatable(user)
211
- ? html`<mwc-button raised danger @click="${() => this.onInactivate(user)}" label="inactivate"></mwc-button>`
200
+ ? html`<md-elevated-button danger @click=${() => this.onInactivate(user)}>inactivate</md-elevated-button>`
212
201
  : ''}
213
202
  </div>
214
203
  `
@@ -1,4 +1,6 @@
1
- import '@material/mwc-button'
1
+ import '@material/web/icon/icon.js'
2
+ import '@material/web/button/elevated-button.js'
3
+
2
4
  import '@operato/i18n/ox-i18n.js'
3
5
  import '@operato/layout/ox-snack-bar.js'
4
6
  import '@operato/lottie-player'
@@ -66,11 +68,11 @@ export class AuthActivate extends localize(i18next)(LitElement) {
66
68
  padding-top: 10px;
67
69
  }
68
70
 
69
- mwc-button {
70
- --mdc-theme-primary: var(--auth-button-background-color);
71
- --mdc-theme-on-primary: var(--primary-color);
72
- --mdc-button-horizontal-padding: var(--padding-default);
73
- --mdc-button-ink-color: var(--primary-color);
71
+ md-elevated-button {
72
+ --md-theme-primary: var(--auth-button-background-color);
73
+ --md-theme-on-primary: var(--primary-color);
74
+ --md-button-horizontal-padding: var(--padding-default);
75
+ --md-button-ink-color: var(--primary-color);
74
76
  }
75
77
 
76
78
  contact-us {
@@ -162,20 +164,18 @@ export class AuthActivate extends localize(i18next)(LitElement) {
162
164
  </form>
163
165
 
164
166
  <div id="button-area">
165
- <mwc-button
166
- raised
167
- icon="mail_outline"
168
- label=${i18next.t('label.send activation email')}
169
- @click=${e => this.requestResend(e)}
170
- ></mwc-button>
171
- <mwc-button
172
- raised
173
- icon="home"
174
- label=${i18next.t('button.go to home')}
167
+ <md-elevated-button @click=${e => this.requestResend(e)}>
168
+ <md-icon slot="icon">mail_outline</md-icon>
169
+ ${i18next.t('label.send activation email')}
170
+ </md-elevated-button>
171
+ <md-elevated-button
175
172
  @click=${e => {
176
173
  window.location.replace('/auth/signin')
177
174
  }}
178
- ></mwc-button>
175
+ >
176
+ <md-icon slot="icon">home</md-icon>
177
+ ${i18next.t('button.go to home')}
178
+ </md-elevated-button>
179
179
  </div>
180
180
  <contact-us></contact-us>
181
181