mirror of
https://github.com/logto-io/logto.git
synced 2024-12-30 20:33:54 -05:00
feat(elements): update name
This commit is contained in:
parent
2c1e326949
commit
85545d4cee
10 changed files with 141 additions and 67 deletions
|
@ -36,7 +36,7 @@ if (isDevFeaturesEnabled) {
|
|||
initLocalization();
|
||||
}
|
||||
|
||||
const { LogtoProfileCard, LogtoThemeProvider } = createReactComponents(React);
|
||||
const { LogtoProfileCard, LogtoThemeProvider, LogtoUserProvider } = createReactComponents(React);
|
||||
|
||||
function Profile() {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
@ -70,6 +70,7 @@ function Profile() {
|
|||
return (
|
||||
<AppBoundary>
|
||||
<LogtoThemeProvider theme="dark">
|
||||
<LogtoUserProvider api={api}>
|
||||
<div className={styles.pageContainer}>
|
||||
<Topbar hideTenantSelector hideTitle />
|
||||
<OverlayScrollbar className={styles.scrollable}>
|
||||
|
@ -124,6 +125,7 @@ function Profile() {
|
|||
</OverlayScrollbar>
|
||||
{childrenRoutes}
|
||||
</div>
|
||||
</LogtoUserProvider>
|
||||
</LogtoThemeProvider>
|
||||
</AppBoundary>
|
||||
);
|
||||
|
|
|
@ -11,6 +11,10 @@ export default function koaCors<StateT, ContextT, ResponseBodyT>(
|
|||
origin: (ctx) => {
|
||||
const { origin } = ctx.request.headers;
|
||||
|
||||
if (!EnvSet.values.isProduction) {
|
||||
return origin ?? '';
|
||||
}
|
||||
|
||||
if (
|
||||
origin &&
|
||||
urlSets.some((set) => {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<body style="background: #111;">
|
||||
<logto-theme-provider theme="dark">
|
||||
<logto-user-provider user='{"name": "Johnny Silverhand", "avatar": "https://github.com/logto-io.png"}'>
|
||||
<logto-user-provider>
|
||||
<logto-profile-card></logto-profile-card>
|
||||
</logto-user-provider>
|
||||
</logto-theme-provider>
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"@lit/localize": "^0.12.1",
|
||||
"@lit/react": "^1.0.5",
|
||||
"@silverhand/essentials": "^2.9.1",
|
||||
"ky": "^1.2.3",
|
||||
"lit": "^3.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -25,6 +25,9 @@ export class LogtoProfileCard extends LitElement {
|
|||
@state()
|
||||
updateNameOpened = false;
|
||||
|
||||
@state()
|
||||
name = '';
|
||||
|
||||
render() {
|
||||
const user = this.userContext?.user;
|
||||
|
||||
|
@ -74,6 +77,7 @@ export class LogtoProfileCard extends LitElement {
|
|||
size="small"
|
||||
@click=${() => {
|
||||
this.updateNameOpened = true;
|
||||
this.name = user.name ?? '';
|
||||
}}
|
||||
>
|
||||
${msg('Update', { id: 'general.update' })}
|
||||
|
@ -100,10 +104,22 @@ export class LogtoProfileCard extends LitElement {
|
|||
id: 'account.profile.personal-info.name-placeholder',
|
||||
desc: 'The placeholder for the name input field.',
|
||||
})}
|
||||
value=""
|
||||
.value=${this.name}
|
||||
@input=${(event: InputEvent) => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
this.name = (event.target as HTMLInputElement).value;
|
||||
}}
|
||||
/>
|
||||
</logto-text-input>
|
||||
<logto-button slot="footer" size="large" type="primary">
|
||||
<logto-button
|
||||
slot="footer"
|
||||
size="large"
|
||||
type="primary"
|
||||
@click=${async () => {
|
||||
await this.userContext?.updateUser({ name: this.name });
|
||||
this.updateNameOpened = false;
|
||||
}}
|
||||
>
|
||||
${msg('Save', { id: 'general.save' })}
|
||||
</logto-button>
|
||||
</logto-modal-layout>
|
||||
|
|
|
@ -10,5 +10,9 @@ export * from './components/logto-modal-layout.js';
|
|||
export * from './components/logto-modal.js';
|
||||
export * from './components/logto-text-input.js';
|
||||
export * from './elements/logto-profile-card.js';
|
||||
export * from './utils/locale.js';
|
||||
|
||||
export * from './providers/logto-theme-provider.js';
|
||||
export * from './providers/logto-user-provider.js';
|
||||
|
||||
export * from './utils/api.js';
|
||||
export * from './utils/locale.js';
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
import { createContext, provide } from '@lit/context';
|
||||
import { type UserInfo } from '@logto/schemas';
|
||||
import { noop } from '@silverhand/essentials';
|
||||
import { LitElement, type PropertyValues, html } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
|
||||
import { LogtoAccountApi } from '../utils/api.js';
|
||||
|
||||
/** @see {@link UserContext} */
|
||||
export type UserContextType = { user?: UserInfo };
|
||||
export type UserContextType = Readonly<{
|
||||
user?: UserInfo;
|
||||
updateUser: (user: Partial<UserInfo>) => void | Promise<void>;
|
||||
}>;
|
||||
|
||||
/**
|
||||
* Context for the current user. It's a fundamental context for the account-related elements.
|
||||
|
@ -12,7 +18,9 @@ export type UserContextType = { user?: UserInfo };
|
|||
export const UserContext = createContext<UserContextType>('modal-context');
|
||||
|
||||
/** The default value for the user context. */
|
||||
export const userContext: UserContextType = {};
|
||||
export const userContext: UserContextType = Object.freeze({
|
||||
updateUser: noop,
|
||||
});
|
||||
|
||||
const tagName = 'logto-user-provider';
|
||||
|
||||
|
@ -24,23 +32,30 @@ export class LogtoUserProvider extends LitElement {
|
|||
context = userContext;
|
||||
|
||||
@property({ type: Object })
|
||||
user?: UserInfo;
|
||||
api!: LogtoAccountApi | ConstructorParameters<typeof LogtoAccountApi>[0];
|
||||
|
||||
render() {
|
||||
return html`<slot></slot>`;
|
||||
}
|
||||
|
||||
protected handlePropertiesChange(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has('user')) {
|
||||
this.context.user = this.user;
|
||||
protected updateContext(context: Partial<UserContextType>) {
|
||||
this.context = Object.freeze({ ...this.context, ...context });
|
||||
}
|
||||
|
||||
protected async handlePropertiesChange(changedProperties: PropertyValues) {
|
||||
if (changedProperties.has('api')) {
|
||||
const api = this.api instanceof LogtoAccountApi ? this.api : new LogtoAccountApi(this.api);
|
||||
this.updateContext({
|
||||
updateUser: async (user) => {
|
||||
const updated = await api.updateUser(user);
|
||||
this.updateContext({ user: updated });
|
||||
},
|
||||
user: await api.getUser(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected firstUpdated(changedProperties: PropertyValues): void {
|
||||
this.handlePropertiesChange(changedProperties);
|
||||
}
|
||||
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
this.handlePropertiesChange(changedProperties);
|
||||
void this.handlePropertiesChange(changedProperties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@ import {
|
|||
LogtoFormCard,
|
||||
LogtoProfileCard,
|
||||
LogtoList,
|
||||
LogtoUserProvider,
|
||||
} from './index.js';
|
||||
|
||||
export * from './utils/locale.js';
|
||||
export * from './utils/api.js';
|
||||
|
||||
export const createReactComponents = (react: Parameters<typeof createComponent>[0]['react']) => {
|
||||
return {
|
||||
|
@ -37,5 +39,10 @@ export const createReactComponents = (react: Parameters<typeof createComponent>[
|
|||
elementClass: LogtoThemeProvider,
|
||||
react,
|
||||
}),
|
||||
LogtoUserProvider: createComponent({
|
||||
tagName: LogtoUserProvider.tagName,
|
||||
elementClass: LogtoUserProvider,
|
||||
react,
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
|
22
packages/elements/src/utils/api.ts
Normal file
22
packages/elements/src/utils/api.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { type UserInfo } from '@logto/schemas';
|
||||
import originalKy, { type Options, type KyInstance } from 'ky';
|
||||
|
||||
/**
|
||||
* CAUTION: The current implementation is based on the admin tenant's `/me` API which is interim.
|
||||
* The final implementation should be based on the Account API.
|
||||
*/
|
||||
export class LogtoAccountApi {
|
||||
protected ky: KyInstance;
|
||||
|
||||
constructor(init: KyInstance | Options) {
|
||||
this.ky = 'create' in init ? init : originalKy.create(init);
|
||||
}
|
||||
|
||||
async getUser() {
|
||||
return this.ky('me').json<UserInfo>();
|
||||
}
|
||||
|
||||
async updateUser(user: Partial<UserInfo>) {
|
||||
return this.ky.patch('me', { json: user }).json<UserInfo>();
|
||||
}
|
||||
}
|
|
@ -3572,6 +3572,9 @@ importers:
|
|||
'@silverhand/essentials':
|
||||
specifier: ^2.9.1
|
||||
version: 2.9.1
|
||||
ky:
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3
|
||||
lit:
|
||||
specifier: ^3.1.4
|
||||
version: 3.1.4
|
||||
|
|
Loading…
Reference in a new issue