0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00

fix(console): add json validator to connector config (#2774)

This commit is contained in:
wangsijie 2022-12-30 15:43:42 +08:00 committed by GitHub
parent 09b1fa370f
commit 2a723f01a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 76 additions and 45 deletions

View file

@ -57,3 +57,9 @@
}
}
}
.errorMessage {
font: var(--font-body-medium);
color: var(--color-error);
margin-top: _.unit(1);
}

View file

@ -14,6 +14,8 @@ type Props = {
value?: string;
onChange?: (value: string) => void;
tabSize?: number;
hasError?: boolean;
errorMessage?: string;
};
const CodeEditor = ({
@ -23,6 +25,8 @@ const CodeEditor = ({
value = '',
onChange,
tabSize = 2,
hasError,
errorMessage,
}: Props) => {
const textareaRef = useRef<HTMLTextAreaElement>(null);
@ -49,49 +53,52 @@ const CodeEditor = ({
};
return (
<div className={classNames(styles.container, className)}>
<CopyToClipboard value={value} variant="icon" className={styles.copy} />
<div className={styles.editor}>
{/* SyntaxHighlighter is a readonly component, so a transparent <textarea> layer is needed
in order to support user interactions, such as code editing, copy-pasting, etc. */}
<textarea
ref={textareaRef}
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
data-gramm="false"
readOnly={isReadonly}
spellCheck="false"
value={value}
onChange={handleChange}
onKeyDown={handleKeydown}
/>
{/* SyntaxHighlighter will generate a <pre> tag and a inner <code> tag. Both have
inline-styles by default. Therefore, We can only use inline styles to customize them.
Some styles have to be applied multiple times to each of them for the sake of consistency. */}
<SyntaxHighlighter
wrapLongLines
codeTagProps={{
style: {
fontFamily: "'Roboto Mono', monospace", // Override default font-family of <code>
},
}}
customStyle={{
background: 'transparent',
fontSize: '14px',
margin: '0',
padding: '0',
borderRadius: '0',
wordBreak: 'break-all',
fontFamily: "'Roboto Mono', monospace", // Override default font-family of <pre>
}}
language={language}
style={theme}
>
{value}
</SyntaxHighlighter>
<>
<div className={classNames(styles.container, className)}>
<CopyToClipboard value={value} variant="icon" className={styles.copy} />
<div className={styles.editor}>
{/* SyntaxHighlighter is a readonly component, so a transparent <textarea> layer is needed
in order to support user interactions, such as code editing, copy-pasting, etc. */}
<textarea
ref={textareaRef}
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
data-gramm="false"
readOnly={isReadonly}
spellCheck="false"
value={value}
onChange={handleChange}
onKeyDown={handleKeydown}
/>
{/* SyntaxHighlighter will generate a <pre> tag and a inner <code> tag. Both have
inline-styles by default. Therefore, We can only use inline styles to customize them.
Some styles have to be applied multiple times to each of them for the sake of consistency. */}
<SyntaxHighlighter
wrapLongLines
codeTagProps={{
style: {
fontFamily: "'Roboto Mono', monospace", // Override default font-family of <code>
},
}}
customStyle={{
background: 'transparent',
fontSize: '14px',
margin: '0',
padding: '0',
borderRadius: '0',
wordBreak: 'break-all',
fontFamily: "'Roboto Mono', monospace", // Override default font-family of <pre>
}}
language={language}
style={theme}
>
{value}
</SyntaxHighlighter>
</div>
</div>
</div>
{hasError && errorMessage && <div className={styles.errorMessage}>{errorMessage}</div>}
</>
);
};

View file

@ -12,7 +12,7 @@ import FormField from '@/components/FormField';
import Select from '@/components/Select';
import TextInput from '@/components/TextInput';
import TextLink from '@/components/TextLink';
import { uriValidator } from '@/utilities/validator';
import { uriValidator, jsonValidator } from '@/utilities/validator';
import type { ConnectorFormType } from '../../types';
import { SyncProfileMode } from '../../types';
@ -127,9 +127,17 @@ const ConnectorForm = ({ connector, isAllowEditTarget }: Props) => {
name="config"
control={control}
defaultValue={configTemplate}
rules={{ required: true }}
rules={{
validate: (value) => jsonValidator(value) || t('errors.invalid_json_format'),
}}
render={({ field: { onChange, value } }) => (
<CodeEditor language="json" value={value} onChange={onChange} />
<CodeEditor
hasError={Boolean(errors.config)}
errorMessage={errors.config?.message}
language="json"
value={value}
onChange={onChange}
/>
)}
/>
</FormField>

View file

@ -16,3 +16,13 @@ export const uriOriginValidator = (value: string) => {
return false;
}
};
export const jsonValidator = (value: string) => {
try {
JSON.parse(value);
} catch {
return false;
}
return true;
};