@things-factory/auth-ui 10.1.215 → 10.1.219
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/bootstrap.js +18 -14
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/components/abstract-password-reset.d.ts +5 -0
- package/dist-client/components/abstract-password-reset.js +20 -0
- package/dist-client/components/abstract-password-reset.js.map +1 -1
- package/dist-client/components/ownership-transfer-popup.d.ts +3 -1
- package/dist-client/components/ownership-transfer-popup.js +38 -41
- package/dist-client/components/ownership-transfer-popup.js.map +1 -1
- package/dist-client/components/password-setup-link-popup.d.ts +46 -0
- package/dist-client/components/password-setup-link-popup.js +254 -0
- package/dist-client/components/password-setup-link-popup.js.map +1 -0
- package/dist-client/components/user-detail.d.ts +20 -30
- package/dist-client/components/user-detail.js +114 -186
- package/dist-client/components/user-detail.js.map +1 -1
- package/dist-client/components/user-invite.d.ts +18 -25
- package/dist-client/components/user-invite.js +157 -181
- package/dist-client/components/user-invite.js.map +1 -1
- package/dist-client/components/user-popups-standard.test.js +69 -0
- package/dist-client/components/user-popups-standard.test.js.map +1 -0
- package/dist-client/components/user-role-editor.js +5 -26
- package/dist-client/components/user-role-editor.js.map +1 -1
- package/dist-client/components/user-status-renderer.js +4 -0
- package/dist-client/components/user-status-renderer.js.map +1 -1
- package/dist-client/entries/auth/reset-password.d.ts +1 -0
- package/dist-client/entries/auth/reset-password.js +5 -1
- package/dist-client/entries/auth/reset-password.js.map +1 -1
- package/dist-client/index.js +10 -28
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/user/user-list-page.d.ts +5 -1
- package/dist-client/pages/user/user-list-page.js +14 -5
- package/dist-client/pages/user/user-list-page.js.map +1 -1
- package/dist-client/route.js +0 -3
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/link-token.d.ts +3 -3
- package/dist-client/utils/link-token.js +4 -4
- package/dist-client/utils/link-token.js.map +1 -1
- package/dist-client/utils/link-token.test.js +2 -2
- package/dist-client/utils/link-token.test.js.map +1 -1
- package/package.json +6 -5
- package/things-factory.config.js +0 -1
- package/translations/en.json +30 -20
- package/translations/es.json +30 -20
- package/translations/ja.json +30 -20
- package/translations/ko.json +30 -20
- package/translations/ms.json +30 -20
- package/translations/zh.json +30 -20
- package/dist-client/components/accept-invitation.d.ts +0 -47
- package/dist-client/components/accept-invitation.js +0 -258
- package/dist-client/components/accept-invitation.js.map +0 -1
- package/dist-client/entries/auth/accept-invitation.d.ts +0 -3
- package/dist-client/entries/auth/accept-invitation.js +0 -10
- package/dist-client/entries/auth/accept-invitation.js.map +0 -1
- package/dist-client/pages/invitation/invitation-list-query.test.js +0 -69
- package/dist-client/pages/invitation/invitation-list-query.test.js.map +0 -1
- package/dist-client/pages/invitation/invitations.d.ts +0 -63
- package/dist-client/pages/invitation/invitations.js +0 -284
- package/dist-client/pages/invitation/invitations.js.map +0 -1
- /package/dist-client/{pages/invitation/invitation-list-query.test.d.ts → components/user-popups-standard.test.d.ts} +0 -0
package/dist-client/bootstrap.js
CHANGED
|
@@ -4,12 +4,12 @@ import { i18next } from '@operato/i18n';
|
|
|
4
4
|
import '@operato/attribute/grist-editor'; /* for register data-grist editor type 'attributes' */
|
|
5
5
|
import { html } from 'lit-html';
|
|
6
6
|
import { navigate, removeDraftsOf, store } from '@operato/shell';
|
|
7
|
-
import { openPopup, registerNotifyAction
|
|
7
|
+
import { openPopup, registerNotifyAction } from '@operato/layout';
|
|
8
8
|
import { OxGristEditorPrivilege } from '@operato/app/grist-editor/ox-grist-editor-privilege.js';
|
|
9
9
|
import { registerEditor as registerGristEditor, registerRenderer as registerGristRenderer, OxGristRendererJson5 } from '@operato/data-grist';
|
|
10
10
|
import { auth } from '@things-factory/auth-base/dist-client/auth.js';
|
|
11
11
|
import { hasPrivilege } from '@things-factory/auth-base/dist-client';
|
|
12
|
-
import {
|
|
12
|
+
import { ADD_USER_MENU } from '@things-factory/apptool-base/client';
|
|
13
13
|
import { registerPersonAuditSection, registerPersonKind } from './entity360/person-360.js';
|
|
14
14
|
import { requestableFrom } from './utils/access-request.js';
|
|
15
15
|
export default async function bootstrap() {
|
|
@@ -19,25 +19,29 @@ export default async function bootstrap() {
|
|
|
19
19
|
hasPrivilege({ privilege: 'query', category: 'audit', superUserGranted: true }).then(holds => holds && registerPersonAuditSection());
|
|
20
20
|
registerGristEditor('privilege', OxGristEditorPrivilege);
|
|
21
21
|
registerGristRenderer('privilege', OxGristRendererJson5);
|
|
22
|
-
/*
|
|
22
|
+
/*
|
|
23
|
+
* The person's own profile and sign-out are in the menu the header's avatar opens, not among the
|
|
24
|
+
* morendas - those are the app's administration (the rail's 「시스템 › 관리」).
|
|
25
|
+
*/
|
|
23
26
|
store.dispatch({
|
|
24
|
-
type:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
type: ADD_USER_MENU,
|
|
28
|
+
item: {
|
|
29
|
+
name: 'profile',
|
|
30
|
+
icon: 'account_circle',
|
|
31
|
+
label: 'text.auth profile',
|
|
32
|
+
order: 10,
|
|
29
33
|
action: () => {
|
|
30
34
|
navigate('profile');
|
|
31
35
|
}
|
|
32
36
|
}
|
|
33
37
|
});
|
|
34
|
-
/* add sign-out morenda */
|
|
35
38
|
store.dispatch({
|
|
36
|
-
type:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
type: ADD_USER_MENU,
|
|
40
|
+
item: {
|
|
41
|
+
name: 'sign-out',
|
|
42
|
+
icon: 'exit_to_app',
|
|
43
|
+
label: 'field.sign out',
|
|
44
|
+
order: 100,
|
|
41
45
|
action: () => {
|
|
42
46
|
try {
|
|
43
47
|
if (typeof localStorage !== 'undefined') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,0BAA0B,CAAA;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,iCAAiC,CAAA,CAAC,sDAAsD;AAE/F,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../client/bootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\nimport '@operato/i18n/ox-i18n.js'\nimport { i18next } from '@operato/i18n'\nimport '@operato/attribute/grist-editor' /* for register data-grist editor type 'attributes' */\n\nimport { html } from 'lit-html'\n\nimport { navigate, removeDraftsOf, store } from '@operato/shell'\nimport { openPopup, registerNotifyAction } from '@operato/layout'\nimport { OxGristEditorPrivilege } from '@operato/app/grist-editor/ox-grist-editor-privilege.js'\nimport {\n registerEditor as registerGristEditor,\n registerRenderer as registerGristRenderer,\n OxGristRendererJson5\n} from '@operato/data-grist'\n\nimport { auth } from '@things-factory/auth-base/dist-client/auth.js'\nimport { hasPrivilege } from '@things-factory/auth-base/dist-client'\nimport { ADD_USER_MENU } from '@things-factory/apptool-base/client'\nimport { registerPersonAuditSection, registerPersonKind } from './entity360/person-360.js'\nimport { requestableFrom } from './utils/access-request.js'\n\nexport default async function bootstrap() {\n /* the person 360 - a User value anywhere opens it (ADR-0067) */\n registerPersonKind()\n\n /* Whose audit a person 360 shows is `audit:query`'s - only those who hold it get the section (ADR-0141 §5). */\n hasPrivilege({ privilege: 'query', category: 'audit', superUserGranted: true }).then(holds => holds && registerPersonAuditSection())\n\n registerGristEditor('privilege', OxGristEditorPrivilege)\n registerGristRenderer('privilege', OxGristRendererJson5)\n\n /*\n * The person's own profile and sign-out are in the menu the header's avatar opens, not among the\n * morendas - those are the app's administration (the rail's 「시스템 › 관리」).\n */\n store.dispatch({\n type: ADD_USER_MENU,\n item: {\n name: 'profile',\n icon: 'account_circle',\n label: 'text.auth profile',\n order: 10,\n action: () => {\n navigate('profile')\n }\n }\n })\n\n store.dispatch({\n type: ADD_USER_MENU,\n item: {\n name: 'sign-out',\n icon: 'exit_to_app',\n label: 'field.sign out',\n order: 100,\n action: () => {\n try {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem('i18nextLng')\n localStorage.removeItem('i18next')\n }\n\n ;['i18next', 'i18nextLng'].forEach(name => {\n try {\n document.cookie = `${name}=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT;`\n } catch (e) {\n // ignore\n }\n })\n } catch (e) {\n // ignore\n }\n\n auth.signout()\n }\n }\n })\n\n /*\n * Unsaved drafts stay in this browser (ADR-0098). Signing out takes this user's away, so a shared\n * computer keeps none of their edits. Awaited before the page leaves; a browser that keeps no drafts\n * has none to take.\n */\n auth.on('presignout', async () => {\n const user = (auth.credential as any)?.id\n if (user) await removeDraftsOf(user).catch(() => {})\n })\n\n /*\n * A refusal a role would open, of a change the person made, gets one quiet \"request access…\" on its toast. The toast\n * does not know what an error means and @operato/graphql only reports it; this package knows, so it puts the button\n * on (registerNotifyAction, things-factory ADR-0103 decision 5). Where auth-ui is not loaded there is no button.\n */\n registerNotifyAction('access-request', notification => {\n const refusal = Array.isArray(notification.ex) ? notification.ex[0] : undefined\n const detail = requestableFrom(refusal?.extensions, Array.isArray(refusal?.path) ? String(refusal.path[0]) : undefined)\n if (!detail) return null\n return {\n label: i18next.t('access-request.button.request'),\n emphasis: 'quiet',\n callback: () =>\n import('./components/access-request-popup.js').then(() =>\n openPopup(\n html`<access-request-popup\n .category=${detail.category}\n .privilege=${detail.privilege}\n .operationName=${detail.operationName}\n ></access-request-popup>`,\n { size: 'medium', title: i18next.t('access-request.title.request access') }\n )\n )\n }\n })\n\n auth.on('profile', ({ credential }) => {\n if (credential && credential.locale) {\n i18next.changeLanguage(credential.locale)\n }\n })\n\n /* \n Get user profile information from server. \n As soon as response received, auth.on('profile', ...) handlers start to work.\n It's very important point to build UI for the user.\n */\n await auth.profile()\n}\n"]}
|
|
@@ -14,6 +14,11 @@ export declare abstract class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
14
14
|
private passwordPattern;
|
|
15
15
|
private passwordHelp;
|
|
16
16
|
abstract get submitButtonLabel(): string;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the page asks for the address the link was for. The password page does (ADR-0161 decision 3): its link is
|
|
19
|
+
* mailed, forwarded, copied into a chat or onto paper, and holding it should not be enough on its own.
|
|
20
|
+
*/
|
|
21
|
+
get asksEmail(): boolean;
|
|
17
22
|
/**
|
|
18
23
|
* The mailed link is `…#<token>`: the browser does not send what follows `#`, so the token stays
|
|
19
24
|
* out of server and proxy logs. Taken out of the address bar here as well — `replaceState`, so
|
|
@@ -46,6 +46,13 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
46
46
|
`,
|
|
47
47
|
AUTH_STYLE_SIGN
|
|
48
48
|
]; }
|
|
49
|
+
/**
|
|
50
|
+
* Whether the page asks for the address the link was for. The password page does (ADR-0161 decision 3): its link is
|
|
51
|
+
* mailed, forwarded, copied into a chat or onto paper, and holding it should not be enough on its own.
|
|
52
|
+
*/
|
|
53
|
+
get asksEmail() {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
49
56
|
/**
|
|
50
57
|
* The mailed link is `…#<token>`: the browser does not send what follows `#`, so the token stays
|
|
51
58
|
* out of server and proxy logs. Taken out of the address bar here as well — `replaceState`, so
|
|
@@ -82,6 +89,19 @@ export class AbstractPasswordReset extends AbstractAuthPage {
|
|
|
82
89
|
}}
|
|
83
90
|
>
|
|
84
91
|
<input name="token" type="hidden" .value=${this.token || ''} required />
|
|
92
|
+
${this.asksEmail
|
|
93
|
+
? html `<div class="field">
|
|
94
|
+
<md-filled-text-field
|
|
95
|
+
name="email"
|
|
96
|
+
type="email"
|
|
97
|
+
label=${String(i18next.t('field.email'))}
|
|
98
|
+
supporting-text=${String(i18next.t('text.the address this link was sent for'))}
|
|
99
|
+
autocomplete="email"
|
|
100
|
+
required
|
|
101
|
+
><md-icon slot="leading-icon">mail</md-icon></md-filled-text-field
|
|
102
|
+
>
|
|
103
|
+
</div>`
|
|
104
|
+
: nothing}
|
|
85
105
|
<div class="field">
|
|
86
106
|
<md-filled-text-field
|
|
87
107
|
name="password"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abstract-password-reset.js","sourceRoot":"","sources":["../../client/components/abstract-password-reset.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AACnC,OAAO,yCAAyC,CAAA;AAChD,OAAO,8CAA8C,CAAA;AAErD,OAAO,0BAA0B,CAAA;AACjC,OAAO,mCAAmC,CAAA;AAC1C,OAAO,iCAAiC,CAAA;AAExC,OAAO,oCAAoC,CAAA;AAE3C,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,2BAA2B,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAA;AACtG,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAExE,MAAM,OAAgB,qBAAsB,SAAQ,gBAAgB;IAApE;;QAiCU,oBAAe,GAAW,EAAE,CAAA;QAC5B,iBAAY,GAAW,EAAE,CAAA;
|
|
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'\nimport { readLinkToken } from '../utils/link-token.js'\nimport { EntryControlSizeStyles } from '../entry-control-size-styles.js'\n\nexport abstract class AbstractPasswordReset extends AbstractAuthPage {\n static styles = [\n EntryControlSizeStyles,\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 /**\n * Whether the page asks for the address the link was for. The password page does (ADR-0161 decision 3): its link is\n * mailed, forwarded, copied into a chat or onto paper, and holding it should not be enough on its own.\n */\n get asksEmail(): boolean {\n return false\n }\n\n /**\n * The mailed link is `…#<token>`: the browser does not send what follows `#`, so the token stays\n * out of server and proxy logs. Taken out of the address bar here as well — `replaceState`, so\n * going back does not put it on screen.\n */\n connectedCallback() {\n super.connectedCallback()\n\n const { token, clean } = readLinkToken(window.location.href)\n\n this.token = token\n\n if (clean && clean !== window.location.href) {\n window.history.replaceState(null, '', clean)\n }\n }\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 ${this.asksEmail\n ? html`<div class=\"field\">\n <md-filled-text-field\n name=\"email\"\n type=\"email\"\n label=${String(i18next.t('field.email'))}\n supporting-text=${String(i18next.t('text.the address this link was sent for'))}\n autocomplete=\"email\"\n required\n ><md-icon slot=\"leading-icon\">mail</md-icon></md-filled-text-field\n >\n </div>`\n : nothing}\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\"></ox-snack-bar>\n `\n }\n\n updated(changed) {\n super.updated(changed)\n\n /* A refused post renders the form again with the token it carried, in the page, not the address. */\n if (changed.has('data') && this.data?.token) {\n this.token = this.data.token\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,61 +1,57 @@
|
|
|
1
1
|
import { __decorate, __metadata } from "tslib";
|
|
2
|
-
import '@material/web/button/
|
|
2
|
+
import '@material/web/button/text-button.js';
|
|
3
|
+
import '@material/web/button/filled-button.js';
|
|
4
|
+
import '@operato/popup/ox-popup-actions.js';
|
|
3
5
|
import gql from 'graphql-tag';
|
|
4
6
|
import { css, html, LitElement } from 'lit';
|
|
5
|
-
import { customElement, property, query } from 'lit/decorators.js';
|
|
7
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
6
8
|
import { client, gqlContext } from '@operato/graphql';
|
|
7
9
|
import { i18next, localize } from '@operato/i18n';
|
|
8
10
|
import { OxPrompt } from '@operato/popup/ox-prompt.js';
|
|
9
|
-
import {
|
|
11
|
+
import { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles';
|
|
10
12
|
let OwnershipTransferPopup = class OwnershipTransferPopup extends localize(i18next)(LitElement) {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.message = '';
|
|
16
|
+
}
|
|
17
|
+
/* 팝업의 집 모양(page-standard §7·§8): 대상 띠, 라벨 위의 날것 입력, 오류는 칸 바로 아래, 단추 줄은 `ox-popup-actions`. */
|
|
11
18
|
static { this.styles = [
|
|
12
|
-
|
|
19
|
+
CommonPopupStyles,
|
|
20
|
+
PopupBodyStyles,
|
|
21
|
+
FormFieldStyles,
|
|
22
|
+
PopupFieldStyles,
|
|
13
23
|
css `
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
background-color: var(--md-sys-color-background);
|
|
18
|
-
padding: var(--spacing-large);
|
|
19
|
-
overflow: auto;
|
|
20
|
-
}
|
|
21
|
-
.container {
|
|
22
|
-
display: flex;
|
|
23
|
-
flex-direction: column;
|
|
24
|
-
flex: 1;
|
|
25
|
-
}
|
|
26
|
-
input {
|
|
27
|
-
background-color: var(--input-field-background, var(--md-sys-color-surface-container-highest));
|
|
28
|
-
color: var(--input-field-color, var(--md-sys-color-on-surface));
|
|
29
|
-
border: var(--border-dim-color);
|
|
30
|
-
border-radius: var(--border-radius);
|
|
31
|
-
margin: var(--input-margin);
|
|
32
|
-
padding: var(--input-padding);
|
|
33
|
-
min-width: 250px;
|
|
34
|
-
font: var(--input-font);
|
|
24
|
+
[invalid] {
|
|
25
|
+
color: var(--ui-crit, var(--md-sys-color-error));
|
|
26
|
+
font-size: var(--ui-t-small, 11.5px);
|
|
35
27
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
display:
|
|
39
|
-
}
|
|
40
|
-
.input-container md-elevated-button {
|
|
41
|
-
margin: auto 0px auto var(--spacing-large);
|
|
28
|
+
|
|
29
|
+
[invalid]:empty {
|
|
30
|
+
display: none;
|
|
42
31
|
}
|
|
43
32
|
`
|
|
44
33
|
]; }
|
|
45
34
|
render() {
|
|
35
|
+
const user = this.user || {};
|
|
46
36
|
return html `
|
|
47
|
-
<div class="
|
|
48
|
-
<div>${
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
<
|
|
52
|
-
|
|
37
|
+
<div class="body">
|
|
38
|
+
<div class="what">${user.name || user.username || user.email} · ${user.email}</div>
|
|
39
|
+
<label class="field">
|
|
40
|
+
<span>${i18next.t('text.please enter the email of the user you want to transfer owner')}</span>
|
|
41
|
+
<input name="email" type="email" @input=${() => (this.message = '')} />
|
|
42
|
+
<span invalid>${this.message}</span>
|
|
43
|
+
</label>
|
|
53
44
|
</div>
|
|
45
|
+
|
|
46
|
+
<ox-popup-actions>
|
|
47
|
+
<md-text-button slot="cancel" @click=${() => history.back()}>${i18next.t('button.cancel')}</md-text-button>
|
|
48
|
+
<md-filled-button slot="confirm" @click=${this.transferOwnership}>${i18next.t('button.confirm')}</md-filled-button>
|
|
49
|
+
</ox-popup-actions>
|
|
54
50
|
`;
|
|
55
51
|
}
|
|
56
52
|
async transferOwnership() {
|
|
57
53
|
if (!this.doubleCheckEmail()) {
|
|
58
|
-
this.
|
|
54
|
+
this.message = i18next.t('text.email is not matched');
|
|
59
55
|
return;
|
|
60
56
|
}
|
|
61
57
|
if (await OxPrompt.open({
|
|
@@ -91,9 +87,6 @@ let OwnershipTransferPopup = class OwnershipTransferPopup extends localize(i18ne
|
|
|
91
87
|
doubleCheckEmail() {
|
|
92
88
|
return this.emailInput.value === this.user.email;
|
|
93
89
|
}
|
|
94
|
-
showToast(message) {
|
|
95
|
-
document.dispatchEvent(new CustomEvent('notify', { detail: { message, option: { timer: 1000 } } }));
|
|
96
|
-
}
|
|
97
90
|
};
|
|
98
91
|
__decorate([
|
|
99
92
|
property({ type: Object }),
|
|
@@ -103,6 +96,10 @@ __decorate([
|
|
|
103
96
|
query('input[name=email]'),
|
|
104
97
|
__metadata("design:type", HTMLInputElement)
|
|
105
98
|
], OwnershipTransferPopup.prototype, "emailInput", void 0);
|
|
99
|
+
__decorate([
|
|
100
|
+
state(),
|
|
101
|
+
__metadata("design:type", String)
|
|
102
|
+
], OwnershipTransferPopup.prototype, "message", void 0);
|
|
106
103
|
OwnershipTransferPopup = __decorate([
|
|
107
104
|
customElement('ownership-transfer-popup')
|
|
108
105
|
], OwnershipTransferPopup);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ownership-transfer-popup.js","sourceRoot":"","sources":["../../client/components/ownership-transfer-popup.ts"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"ownership-transfer-popup.js","sourceRoot":"","sources":["../../client/components/ownership-transfer-popup.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/button/text-button.js'\nimport '@material/web/button/filled-button.js'\nimport '@operato/popup/ox-popup-actions.js'\n\nimport gql from 'graphql-tag'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { client, gqlContext } from '@operato/graphql'\nimport { i18next, localize } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { CommonPopupStyles, FormFieldStyles, PopupBodyStyles, PopupFieldStyles } from '@operato/styles'\n\n@customElement('ownership-transfer-popup')\nclass OwnershipTransferPopup extends localize(i18next)(LitElement) {\n /* 팝업의 집 모양(page-standard §7·§8): 대상 띠, 라벨 위의 날것 입력, 오류는 칸 바로 아래, 단추 줄은 `ox-popup-actions`. */\n static styles = [\n CommonPopupStyles,\n PopupBodyStyles,\n FormFieldStyles,\n PopupFieldStyles,\n css`\n [invalid] {\n color: var(--ui-crit, var(--md-sys-color-error));\n font-size: var(--ui-t-small, 11.5px);\n }\n\n [invalid]:empty {\n display: none;\n }\n `\n ]\n\n @property({ type: Object }) user: any\n\n @query('input[name=email]') emailInput!: HTMLInputElement\n\n @state() private message: string = ''\n\n render() {\n const user = this.user || {}\n\n return html`\n <div class=\"body\">\n <div class=\"what\">${user.name || user.username || user.email} · ${user.email}</div>\n <label class=\"field\">\n <span>${i18next.t('text.please enter the email of the user you want to transfer owner')}</span>\n <input name=\"email\" type=\"email\" @input=${() => (this.message = '')} />\n <span invalid>${this.message}</span>\n </label>\n </div>\n\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${() => history.back()}>${i18next.t('button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" @click=${this.transferOwnership}>${i18next.t('button.confirm')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n async transferOwnership() {\n if (!this.doubleCheckEmail()) {\n this.message = i18next.t('text.email is not matched')\n\n return\n }\n\n if (\n await OxPrompt.open({\n title: i18next.t('text.are_you_sure'),\n text: i18next.t('text.are_you_sure_to_transfer_owner'),\n confirmButton: { text: i18next.t('button.confirm') },\n cancelButton: { text: i18next.t('button.cancel') }\n })\n ) {\n const response = await client.mutate({\n mutation: gql`\n mutation transferOwner($username: String!) {\n transferOwner(username: $username)\n }\n `,\n variables: { username: this.user.username || this.user.email },\n context: gqlContext()\n })\n\n if (!response.errors?.length) {\n await OxPrompt.open({\n type: 'success',\n title: i18next.t('text.completed'),\n text: i18next.t('text.owner_transfer_completed'),\n confirmButton: { text: i18next.t('button.confirm') }\n })\n\n history.back()\n\n this.dispatchEvent(new CustomEvent('ownershipTransferred', { bubbles: true, composed: true }))\n }\n } else {\n history.back()\n }\n }\n\n doubleCheckEmail() {\n return this.emailInput.value === this.user.email\n }\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import '@material/web/button/text-button.js';
|
|
2
|
+
import '@material/web/button/filled-button.js';
|
|
3
|
+
import '@material/web/button/outlined-button.js';
|
|
4
|
+
import '@operato/popup/ox-popup-actions.js';
|
|
5
|
+
import { LitElement } from 'lit';
|
|
6
|
+
import type { CSSResultGroup } from 'lit';
|
|
7
|
+
declare const PasswordSetupLinkPopup_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
8
|
+
/**
|
|
9
|
+
* Issuing a password setup link - the one way a person gets a password here that an administrator did not set
|
|
10
|
+
* (ADR-0161).
|
|
11
|
+
*
|
|
12
|
+
* ── Before ───────────────────────────────────────────────────────────────────
|
|
13
|
+
* What happens is said before it happens: the password the account has stops working and its open sessions end, and
|
|
14
|
+
* the link works once, for 48 hours, and asks for the address. Then the administrator picks how it travels - by mail,
|
|
15
|
+
* or copied and handed over by them.
|
|
16
|
+
*
|
|
17
|
+
* ── After ────────────────────────────────────────────────────────────────────
|
|
18
|
+
* A copied link is on screen **only now**: the server keeps its hash and nothing else, and there is no way to read it
|
|
19
|
+
* again. Losing it means issuing another, which retires this one.
|
|
20
|
+
*
|
|
21
|
+
* The user detail, the add-user flow and the old role editor all open this one popup (`openPasswordSetupLink`).
|
|
22
|
+
*/
|
|
23
|
+
export declare class PasswordSetupLinkPopup extends PasswordSetupLinkPopup_base {
|
|
24
|
+
static styles: CSSResultGroup;
|
|
25
|
+
/** The person: `username` (or `email`), `email`, `name`, `status`. */
|
|
26
|
+
user: any;
|
|
27
|
+
private mail;
|
|
28
|
+
private issuing;
|
|
29
|
+
private issued?;
|
|
30
|
+
private message;
|
|
31
|
+
private copied;
|
|
32
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
33
|
+
private renderChoice;
|
|
34
|
+
private renderIssued;
|
|
35
|
+
private issue;
|
|
36
|
+
private copy;
|
|
37
|
+
private close;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Open the popup for `user`. `onIssued` runs once a link was issued - the account is now waiting, so a list showing
|
|
41
|
+
* its status reads it again.
|
|
42
|
+
*/
|
|
43
|
+
export declare function openPasswordSetupLink(user: any, { onIssued }?: {
|
|
44
|
+
onIssued?: () => void;
|
|
45
|
+
}): import("@operato/layout").PopupHandle<unknown>;
|
|
46
|
+
export {};
|