mirror of
https://github.com/logto-io/logto.git
synced 2025-01-27 21:39:16 -05:00
feat(console): edit sync profile (#2573)
This commit is contained in:
parent
e3bc924c86
commit
8f5a8bded0
11 changed files with 78 additions and 8 deletions
|
@ -11,6 +11,7 @@ import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
|||
import useApi from '@/hooks/use-api';
|
||||
import ConnectorForm from '@/pages/Connectors/components/ConnectorForm';
|
||||
import type { ConnectorFormType } from '@/pages/Connectors/types';
|
||||
import { SyncProfileMode } from '@/pages/Connectors/types';
|
||||
import { safeParseJson } from '@/utilities/json';
|
||||
|
||||
import * as styles from '../index.module.scss';
|
||||
|
@ -25,7 +26,12 @@ type Props = {
|
|||
const ConnectorContent = ({ isDeleted, connectorData, onConnectorUpdated }: Props) => {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const api = useApi();
|
||||
const methods = useForm<ConnectorFormType>({ reValidateMode: 'onBlur' });
|
||||
const methods = useForm<ConnectorFormType>({
|
||||
reValidateMode: 'onBlur',
|
||||
defaultValues: {
|
||||
syncProfile: SyncProfileMode.OnlyAtRegister,
|
||||
},
|
||||
});
|
||||
const {
|
||||
formState: { isSubmitting, isDirty },
|
||||
handleSubmit,
|
||||
|
@ -35,17 +41,18 @@ const ConnectorContent = ({ isDeleted, connectorData, onConnectorUpdated }: Prop
|
|||
|
||||
useEffect(() => {
|
||||
const { name, logo, logoDark, target } = connectorData.metadata;
|
||||
const { config } = connectorData;
|
||||
const { config, syncProfile } = connectorData;
|
||||
reset({
|
||||
target,
|
||||
logo,
|
||||
logoDark: logoDark ?? '',
|
||||
name: name?.en,
|
||||
config: JSON.stringify(config, null, 2),
|
||||
syncProfile: syncProfile ? SyncProfileMode.EachSignIn : SyncProfileMode.OnlyAtRegister,
|
||||
});
|
||||
}, [connectorData, reset]);
|
||||
|
||||
const onSubmit = handleSubmit(async ({ config, ...metadata }) => {
|
||||
const onSubmit = handleSubmit(async ({ config, syncProfile, ...metadata }) => {
|
||||
if (!config) {
|
||||
toast.error(t('connector_details.save_error_empty_config'));
|
||||
|
||||
|
@ -60,9 +67,15 @@ const ConnectorContent = ({ isDeleted, connectorData, onConnectorUpdated }: Prop
|
|||
return;
|
||||
}
|
||||
|
||||
const body = connectorData.isStandard
|
||||
? { config: result.data, metadata: { ...metadata, name: { en: metadata.name } } }
|
||||
: { config: result.data };
|
||||
const payload = {
|
||||
config: result.data,
|
||||
syncProfile: syncProfile === SyncProfileMode.EachSignIn,
|
||||
};
|
||||
const standardConnectorPayload = {
|
||||
...payload,
|
||||
metadata: { ...metadata, name: { en: metadata.name } },
|
||||
};
|
||||
const body = connectorData.isStandard ? standardConnectorPayload : payload;
|
||||
|
||||
const updatedConnector = await api
|
||||
.patch(`/api/connectors/${connectorData.id}`, {
|
||||
|
|
|
@ -6,9 +6,11 @@ import { useTranslation } from 'react-i18next';
|
|||
import Button from '@/components/Button';
|
||||
import CodeEditor from '@/components/CodeEditor';
|
||||
import FormField from '@/components/FormField';
|
||||
import Select from '@/components/Select';
|
||||
import TextInput from '@/components/TextInput';
|
||||
|
||||
import type { ConnectorFormType } from '../../types';
|
||||
import { SyncProfileMode } from '../../types';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
type Props = {
|
||||
|
@ -25,6 +27,17 @@ const ConnectorForm = ({ connector }: Props) => {
|
|||
setDarkVisible((previous) => !previous);
|
||||
};
|
||||
|
||||
const syncProfileOptions = [
|
||||
{
|
||||
value: SyncProfileMode.OnlyAtRegister,
|
||||
title: t('connectors.guide.sync_profile_only_at_register'),
|
||||
},
|
||||
{
|
||||
value: SyncProfileMode.EachSignIn,
|
||||
title: t('connectors.guide.sync_profile_each_sign_in'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
{isStandard && (
|
||||
|
@ -79,6 +92,16 @@ const ConnectorForm = ({ connector }: Props) => {
|
|||
)}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField isRequired title="connectors.guide.sync_profile">
|
||||
<Controller
|
||||
name="syncProfile"
|
||||
control={control}
|
||||
rules={{ required: true }}
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Select options={syncProfileOptions} value={value} onChange={onChange} />
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@ import SenderTester from '@/pages/ConnectorDetails/components/SenderTester';
|
|||
import { safeParseJson } from '@/utilities/json';
|
||||
|
||||
import type { ConnectorFormType } from '../../types';
|
||||
import { SyncProfileMode } from '../../types';
|
||||
import ConnectorForm from '../ConnectorForm';
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
|
@ -36,7 +37,12 @@ const Guide = ({ connector, onClose }: Props) => {
|
|||
const connectorName = conditional(isLanguageTag(language) && name[language]) ?? name.en;
|
||||
const isSocialConnector =
|
||||
connectorType !== ConnectorType.Sms && connectorType !== ConnectorType.Email;
|
||||
const methods = useForm<ConnectorFormType>({ reValidateMode: 'onBlur' });
|
||||
const methods = useForm<ConnectorFormType>({
|
||||
reValidateMode: 'onBlur',
|
||||
defaultValues: {
|
||||
syncProfile: SyncProfileMode.OnlyAtRegister,
|
||||
},
|
||||
});
|
||||
const {
|
||||
formState: { isSubmitting },
|
||||
handleSubmit,
|
||||
|
@ -48,7 +54,7 @@ const Guide = ({ connector, onClose }: Props) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const { config, name, ...otherData } = data;
|
||||
const { config, name, syncProfile, ...otherData } = data;
|
||||
const result = safeParseJson(config);
|
||||
|
||||
if (!result.success) {
|
||||
|
@ -64,6 +70,7 @@ const Guide = ({ connector, onClose }: Props) => {
|
|||
json: {
|
||||
config: result.data,
|
||||
connectorId,
|
||||
syncProfile: syncProfile === SyncProfileMode.EachSignIn,
|
||||
metadata: conditional(
|
||||
isStandard && {
|
||||
...otherData,
|
||||
|
|
|
@ -4,4 +4,10 @@ export type ConnectorFormType = {
|
|||
logo: string;
|
||||
logoDark: string;
|
||||
target: string;
|
||||
syncProfile: SyncProfileMode;
|
||||
};
|
||||
|
||||
export enum SyncProfileMode {
|
||||
OnlyAtRegister = 'OnlyAtRegister',
|
||||
EachSignIn = 'EachSignIn',
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ const connectors = {
|
|||
target: 'Connector identity target', // UNTRANSLATED
|
||||
target_tip: 'A unique identifier for the connector.', // UNTRANSLATED
|
||||
config: 'Enter your JSON here', // UNTRANSLATED
|
||||
sync_profile: 'Sync profile information form the social provider', // UNTRANSLATED
|
||||
sync_profile_only_at_register: 'Only sync at register', // UNTRANSLATED
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in', // UNTRANSLATED
|
||||
},
|
||||
platform: {
|
||||
universal: 'Universal',
|
||||
|
|
|
@ -45,6 +45,9 @@ const connectors = {
|
|||
target: 'Connector identity target',
|
||||
target_tip: 'A unique identifier for the connector.',
|
||||
config: 'Enter your JSON here',
|
||||
sync_profile: 'Sync profile information form the social provider',
|
||||
sync_profile_only_at_register: 'Only sync at register',
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in',
|
||||
},
|
||||
platform: {
|
||||
universal: 'Universal',
|
||||
|
|
|
@ -46,6 +46,9 @@ const connectors = {
|
|||
target: 'Connector identity target', // UNTRANSLATED
|
||||
target_tip: 'A unique identifier for the connector.', // UNTRANSLATED
|
||||
config: 'Enter your JSON here', // UNTRANSLATED
|
||||
sync_profile: 'Sync profile information form the social provider', // UNTRANSLATED
|
||||
sync_profile_only_at_register: 'Only sync at register', // UNTRANSLATED
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in', // UNTRANSLATED
|
||||
},
|
||||
platform: {
|
||||
universal: 'Universel',
|
||||
|
|
|
@ -45,6 +45,9 @@ const connectors = {
|
|||
target: 'Connector identity target', // UNTRANSLATED
|
||||
target_tip: 'A unique identifier for the connector.', // UNTRANSLATED
|
||||
config: 'Enter your JSON here', // UNTRANSLATED
|
||||
sync_profile: 'Sync profile information form the social provider', // UNTRANSLATED
|
||||
sync_profile_only_at_register: 'Only sync at register', // UNTRANSLATED
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in', // UNTRANSLATED
|
||||
},
|
||||
platform: {
|
||||
universal: 'Universal',
|
||||
|
|
|
@ -45,6 +45,9 @@ const connectors = {
|
|||
target: 'Connector identity target', // UNTRANSLATED
|
||||
target_tip: 'A unique identifier for the connector.', // UNTRANSLATED
|
||||
config: 'Enter your JSON here', // UNTRANSLATED
|
||||
sync_profile: 'Sync profile information form the social provider', // UNTRANSLATED
|
||||
sync_profile_only_at_register: 'Only sync at register', // UNTRANSLATED
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in', // UNTRANSLATED
|
||||
},
|
||||
platform: {
|
||||
universal: 'Universal',
|
||||
|
|
|
@ -46,6 +46,9 @@ const connectors = {
|
|||
target: 'Connector identity target', // UNTRANSLATED
|
||||
target_tip: 'A unique identifier for the connector.', // UNTRANSLATED
|
||||
config: 'Enter your JSON here', // UNTRANSLATED
|
||||
sync_profile: 'Sync profile information form the social provider', // UNTRANSLATED
|
||||
sync_profile_only_at_register: 'Only sync at register', // UNTRANSLATED
|
||||
sync_profile_each_sign_in: 'Always sync at each sign-in', // UNTRANSLATED
|
||||
},
|
||||
platform: {
|
||||
universal: 'Evrensel',
|
||||
|
|
|
@ -43,6 +43,9 @@ const connectors = {
|
|||
target: '连接器 target',
|
||||
target_tip: '连接器标识符',
|
||||
config: '请在此输入你的 JSON 配置',
|
||||
sync_profile: '从社交服务商同步用户数据',
|
||||
sync_profile_only_at_register: '仅在注册时同步',
|
||||
sync_profile_each_sign_in: '每次登录都同步',
|
||||
},
|
||||
platform: {
|
||||
universal: '通用',
|
||||
|
|
Loading…
Add table
Reference in a new issue