* feat: init localization-management * feat: resource api * Merge branch 'main' into T-62 * chore: change name * feat: basic feature * feat: support filter & sync * feat: support auto get texts afterSave * Merge branch 'main' into T-62 * chore: upgrade * fix: dependency * fix: field type * fix: type error * chore: remove some translations * feat: support extract text from menu * chore: cache text keys * chore: remove test key * fix: issue of extracting menu titles * feat: translate collections & fields name * fix: remove unique of text * refactor: improve cache * chore: remove listeners after disable * chore: translation * fix: lang switch bug * refactor: actions & filter * fix: translation * refactor: merge lang bundles at backend * fix: style & field name * fix: translate issues * fix: cache bug * fix: translation merge bug * fix: translate issues * fix: map translation * fix: translation issues * fix: card title bug * feat: cover mobile client tabbar * fix: menu title * refactor: add locale plugin * chore: merge locale plugin * fix: map translation * chore: remove no data * style: change button style * fix: sync bug * docs: add README * chore: change name --------- Co-authored-by: chenos <chenlinxh@gmail.com>
87 lines
2.2 KiB
TypeScript
87 lines
2.2 KiB
TypeScript
import { LoginOutlined } from '@ant-design/icons';
|
|
import { Authenticator, css, useAPIClient, useRedirect } from '@nocobase/client';
|
|
import { useMemoizedFn } from 'ahooks';
|
|
import { Button, Space } from 'antd';
|
|
import React, { useEffect, useState } from 'react';
|
|
import { useOidcTranslation } from './locale';
|
|
|
|
export interface OIDCProvider {
|
|
clientId: string;
|
|
title: string;
|
|
}
|
|
|
|
export const OIDCButton = (props: { authenticator: Authenticator }) => {
|
|
const { t } = useOidcTranslation();
|
|
const [windowHandler, setWindowHandler] = useState<Window | undefined>();
|
|
const api = useAPIClient();
|
|
const redirect = useRedirect();
|
|
|
|
/**
|
|
* 打开登录弹出框
|
|
*/
|
|
const handleOpen = async (name: string) => {
|
|
const response = await api.request({
|
|
method: 'post',
|
|
url: 'oidc:getAuthUrl',
|
|
headers: {
|
|
'X-Authenticator': name,
|
|
},
|
|
});
|
|
|
|
const authUrl = response?.data?.data;
|
|
const { width, height } = screen;
|
|
|
|
const win = window.open(
|
|
authUrl,
|
|
'_blank',
|
|
`width=800,height=600,left=${(width - 800) / 2},top=${
|
|
(height - 600) / 2
|
|
},toolbar=no,menubar=no,location=no,status=no`,
|
|
);
|
|
|
|
setWindowHandler(win);
|
|
};
|
|
|
|
/**
|
|
* 从弹出窗口,发消息回来进行登录
|
|
*/
|
|
const handleOIDCLogin = useMemoizedFn(async (event: MessageEvent) => {
|
|
const { state } = event.data;
|
|
const search = new URLSearchParams(state);
|
|
const authenticator = search.get('name');
|
|
try {
|
|
await api.auth.signIn(event.data, authenticator);
|
|
redirect();
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* 监听弹出窗口的消息
|
|
*/
|
|
useEffect(() => {
|
|
if (!windowHandler) return;
|
|
|
|
const channel = new BroadcastChannel('nocobase-oidc-response');
|
|
channel.onmessage = handleOIDCLogin;
|
|
return () => {
|
|
channel.close();
|
|
};
|
|
}, [windowHandler, handleOIDCLogin]);
|
|
|
|
const authenticator = props.authenticator;
|
|
return (
|
|
<Space
|
|
direction="vertical"
|
|
className={css`
|
|
display: flex;
|
|
`}
|
|
>
|
|
<Button shape="round" block icon={<LoginOutlined />} onClick={() => handleOpen(authenticator.name)}>
|
|
{t(authenticator.title)}
|
|
</Button>
|
|
</Space>
|
|
);
|
|
};
|