mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-01-11 22:40:26 +01:00
Remove useTemplating prop (#184)
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
|
||||
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
|
||||
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
|
||||
import { Input } from './core/Input';
|
||||
import { VStack } from './core/Stacks';
|
||||
|
||||
interface Props<T> {
|
||||
request: T;
|
||||
}
|
||||
|
||||
export function BasicAuth<T extends HttpRequest | GrpcRequest>({ request }: Props<T>) {
|
||||
const updateHttpRequest = useUpdateAnyHttpRequest();
|
||||
const updateGrpcRequest = useUpdateAnyGrpcRequest();
|
||||
|
||||
return (
|
||||
<VStack className="py-2 overflow-y-auto h-full" space={2}>
|
||||
<Input
|
||||
useTemplating
|
||||
autocompleteVariables
|
||||
stateKey={`basic.username.${request.id}`}
|
||||
forceUpdateKey={request.id}
|
||||
placeholder="username"
|
||||
label="Username"
|
||||
name="username"
|
||||
size="sm"
|
||||
defaultValue={`${request.authentication.username}`}
|
||||
onChange={(username: string) => {
|
||||
if (request.model === 'http_request') {
|
||||
updateHttpRequest.mutate({
|
||||
id: request.id,
|
||||
update: (r: HttpRequest) => ({
|
||||
...r,
|
||||
authentication: { password: r.authentication.password, username },
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
updateGrpcRequest.mutate({
|
||||
id: request.id,
|
||||
update: (r: GrpcRequest) => ({
|
||||
...r,
|
||||
authentication: { password: r.authentication.password, username },
|
||||
}),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
useTemplating
|
||||
autocompleteVariables
|
||||
forceUpdateKey={request?.id}
|
||||
stateKey={`basic.password.${request.id}`}
|
||||
placeholder="password"
|
||||
label="Password"
|
||||
name="password"
|
||||
size="sm"
|
||||
type="password"
|
||||
defaultValue={`${request.authentication.password}`}
|
||||
onChange={(password: string) => {
|
||||
if (request.model === 'http_request') {
|
||||
updateHttpRequest.mutate({
|
||||
id: request.id,
|
||||
update: (r: HttpRequest) => ({
|
||||
...r,
|
||||
authentication: { username: r.authentication.username, password },
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
updateGrpcRequest.mutate({
|
||||
id: request.id,
|
||||
update: (r: GrpcRequest) => ({
|
||||
...r,
|
||||
authentication: { username: r.authentication.username, password },
|
||||
}),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
|
||||
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
|
||||
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
|
||||
import { Input } from './core/Input';
|
||||
import { VStack } from './core/Stacks';
|
||||
|
||||
interface Props<T> {
|
||||
request: T;
|
||||
}
|
||||
|
||||
export function BearerAuth<T extends HttpRequest | GrpcRequest>({ request }: Props<T>) {
|
||||
const updateHttpRequest = useUpdateAnyHttpRequest();
|
||||
const updateGrpcRequest = useUpdateAnyGrpcRequest();
|
||||
|
||||
return (
|
||||
<VStack className="my-2" space={2}>
|
||||
<Input
|
||||
useTemplating
|
||||
autocompleteVariables
|
||||
placeholder="token"
|
||||
stateKey={`bearer.${request.id}`}
|
||||
type="password"
|
||||
label="Token"
|
||||
name="token"
|
||||
size="sm"
|
||||
defaultValue={`${request.authentication.token}`}
|
||||
onChange={(token: string) => {
|
||||
if (request.model === 'http_request') {
|
||||
updateHttpRequest.mutate({
|
||||
id: request.id ?? null,
|
||||
update: (r: HttpRequest) => ({
|
||||
...r,
|
||||
authentication: { token },
|
||||
}),
|
||||
});
|
||||
} else {
|
||||
updateGrpcRequest.mutate({
|
||||
id: request.id ?? null,
|
||||
update: (r: GrpcRequest) => ({
|
||||
...r,
|
||||
authentication: { token },
|
||||
}),
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</VStack>
|
||||
);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ interface Props<T> {
|
||||
inputs: FormInput[] | undefined | null;
|
||||
onChange: (value: T) => void;
|
||||
data: T;
|
||||
useTemplating?: boolean;
|
||||
autocompleteFunctions?: boolean;
|
||||
autocompleteVariables?: boolean;
|
||||
stateKey: string;
|
||||
disabled?: boolean;
|
||||
@@ -44,8 +44,8 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
|
||||
inputs,
|
||||
data,
|
||||
onChange,
|
||||
useTemplating,
|
||||
autocompleteVariables,
|
||||
autocompleteFunctions,
|
||||
stateKey,
|
||||
disabled,
|
||||
}: Props<T>) {
|
||||
@@ -62,7 +62,7 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
|
||||
inputs={inputs}
|
||||
setDataAttr={setDataAttr}
|
||||
stateKey={stateKey}
|
||||
useTemplating={useTemplating}
|
||||
autocompleteFunctions={autocompleteFunctions}
|
||||
autocompleteVariables={autocompleteVariables}
|
||||
data={data}
|
||||
/>
|
||||
@@ -71,13 +71,16 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
|
||||
|
||||
function FormInputs<T extends Record<string, JsonPrimitive>>({
|
||||
inputs,
|
||||
autocompleteFunctions,
|
||||
autocompleteVariables,
|
||||
stateKey,
|
||||
useTemplating,
|
||||
setDataAttr,
|
||||
data,
|
||||
disabled,
|
||||
}: Pick<Props<T>, 'inputs' | 'useTemplating' | 'autocompleteVariables' | 'stateKey' | 'data'> & {
|
||||
}: Pick<
|
||||
Props<T>,
|
||||
'inputs' | 'autocompleteFunctions' | 'autocompleteVariables' | 'stateKey' | 'data'
|
||||
> & {
|
||||
setDataAttr: (name: string, value: JsonPrimitive) => void;
|
||||
disabled?: boolean;
|
||||
}) {
|
||||
@@ -112,7 +115,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
|
||||
key={i}
|
||||
stateKey={stateKey}
|
||||
arg={input}
|
||||
useTemplating={useTemplating || false}
|
||||
autocompleteFunctions={autocompleteFunctions || false}
|
||||
autocompleteVariables={autocompleteVariables || false}
|
||||
onChange={(v) => setDataAttr(input.name, v)}
|
||||
value={
|
||||
@@ -126,7 +129,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
|
||||
key={i}
|
||||
stateKey={stateKey}
|
||||
arg={input}
|
||||
useTemplating={useTemplating || false}
|
||||
autocompleteFunctions={autocompleteFunctions || false}
|
||||
autocompleteVariables={autocompleteVariables || false}
|
||||
onChange={(v) => setDataAttr(input.name, v)}
|
||||
value={
|
||||
@@ -175,7 +178,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
|
||||
inputs={input.inputs}
|
||||
setDataAttr={setDataAttr}
|
||||
stateKey={stateKey}
|
||||
useTemplating={useTemplating}
|
||||
autocompleteFunctions={autocompleteFunctions || false}
|
||||
autocompleteVariables={autocompleteVariables}
|
||||
/>
|
||||
</div>
|
||||
@@ -195,7 +198,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
|
||||
inputs={input.inputs}
|
||||
setDataAttr={setDataAttr}
|
||||
stateKey={stateKey}
|
||||
useTemplating={useTemplating}
|
||||
autocompleteFunctions={autocompleteFunctions || false}
|
||||
autocompleteVariables={autocompleteVariables}
|
||||
/>
|
||||
</Banner>
|
||||
@@ -212,14 +215,14 @@ function TextArg({
|
||||
arg,
|
||||
onChange,
|
||||
value,
|
||||
useTemplating,
|
||||
autocompleteFunctions,
|
||||
autocompleteVariables,
|
||||
stateKey,
|
||||
}: {
|
||||
arg: FormInputText;
|
||||
value: string;
|
||||
onChange: (v: string) => void;
|
||||
useTemplating: boolean;
|
||||
autocompleteFunctions: boolean;
|
||||
autocompleteVariables: boolean;
|
||||
stateKey: string;
|
||||
}) {
|
||||
@@ -237,7 +240,7 @@ function TextArg({
|
||||
hideLabel={arg.label == null}
|
||||
placeholder={arg.placeholder ?? undefined}
|
||||
autocomplete={arg.completionOptions ? { options: arg.completionOptions } : undefined}
|
||||
useTemplating={useTemplating}
|
||||
autocompleteFunctions={autocompleteFunctions}
|
||||
autocompleteVariables={autocompleteVariables}
|
||||
stateKey={stateKey}
|
||||
forceUpdateKey={stateKey}
|
||||
@@ -249,14 +252,14 @@ function EditorArg({
|
||||
arg,
|
||||
onChange,
|
||||
value,
|
||||
useTemplating,
|
||||
autocompleteFunctions,
|
||||
autocompleteVariables,
|
||||
stateKey,
|
||||
}: {
|
||||
arg: FormInputEditor;
|
||||
value: string;
|
||||
onChange: (v: string) => void;
|
||||
useTemplating: boolean;
|
||||
autocompleteFunctions: boolean;
|
||||
autocompleteVariables: boolean;
|
||||
stateKey: string;
|
||||
}) {
|
||||
@@ -290,7 +293,7 @@ function EditorArg({
|
||||
heightMode="auto"
|
||||
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
|
||||
placeholder={arg.placeholder ?? undefined}
|
||||
useTemplating={useTemplating}
|
||||
autocompleteFunctions={autocompleteFunctions}
|
||||
autocompleteVariables={autocompleteVariables}
|
||||
stateKey={stateKey}
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
|
||||
@@ -116,7 +116,7 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) {
|
||||
};
|
||||
|
||||
const EnvironmentEditor = function ({
|
||||
environment,
|
||||
environment: activeEnvironment,
|
||||
className,
|
||||
}: {
|
||||
environment: Environment;
|
||||
@@ -127,8 +127,8 @@ const EnvironmentEditor = function ({
|
||||
key: 'environmentValueVisibility',
|
||||
fallback: true,
|
||||
});
|
||||
const { subEnvironments } = useEnvironments();
|
||||
const updateEnvironment = useUpdateEnvironment(environment?.id ?? null);
|
||||
const { allEnvironments } = useEnvironments();
|
||||
const updateEnvironment = useUpdateEnvironment(activeEnvironment?.id ?? null);
|
||||
const handleChange = useCallback<PairEditorProps['onChange']>(
|
||||
(variables) => updateEnvironment.mutate({ variables }),
|
||||
[updateEnvironment],
|
||||
@@ -136,26 +136,28 @@ const EnvironmentEditor = function ({
|
||||
|
||||
// Gather a list of env names from other environments, to help the user get them aligned
|
||||
const nameAutocomplete = useMemo<GenericCompletionConfig>(() => {
|
||||
const allVariableNames =
|
||||
environment == null
|
||||
? [] // Nothing to autocomplete if we're in the base environment
|
||||
: subEnvironments
|
||||
.filter((e) => e.environmentId != null)
|
||||
.flatMap((e) => e.variables.map((v) => v.name));
|
||||
const options: GenericCompletionOption[] = [];
|
||||
const isBaseEnv = activeEnvironment.environmentId == null;
|
||||
if (isBaseEnv) {
|
||||
return { options };
|
||||
}
|
||||
|
||||
// Filter out empty strings and variables that already exist
|
||||
const variableNames = allVariableNames.filter(
|
||||
(name) => name != '' && !environment.variables.find((v) => v.name === name),
|
||||
);
|
||||
const uniqueVariableNames = [...new Set(variableNames)];
|
||||
const options = uniqueVariableNames.map(
|
||||
(name): GenericCompletionOption => ({
|
||||
const allVariables = allEnvironments.flatMap((e) => e?.variables);
|
||||
const allVariableNames = new Set(allVariables.map((v) => v?.name));
|
||||
for (const name of allVariableNames) {
|
||||
const containingEnvs = allEnvironments.filter((e) =>
|
||||
e.variables.some((v) => v.name === name),
|
||||
);
|
||||
const isAlreadyInActive = containingEnvs.find((e) => e.id === activeEnvironment.id);
|
||||
if (isAlreadyInActive) continue;
|
||||
options.push({
|
||||
label: name,
|
||||
type: 'constant',
|
||||
}),
|
||||
);
|
||||
detail: containingEnvs.map((e) => e.name).join(', '),
|
||||
});
|
||||
}
|
||||
return { options };
|
||||
}, [subEnvironments, environment]);
|
||||
}, [activeEnvironment.environmentId, activeEnvironment.id, allEnvironments]);
|
||||
|
||||
const validateName = useCallback((name: string) => {
|
||||
// Empty just means the variable doesn't have a name yet, and is unusable
|
||||
@@ -167,7 +169,7 @@ const EnvironmentEditor = function ({
|
||||
<VStack space={4} className={classNames(className, 'pl-4')}>
|
||||
<HStack space={2} className="justify-between">
|
||||
<Heading className="w-full flex items-center gap-1">
|
||||
<div>{environment?.name}</div>
|
||||
<div>{activeEnvironment?.name}</div>
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={valueVisibility.value ? 'eye' : 'eye_closed'}
|
||||
@@ -183,15 +185,15 @@ const EnvironmentEditor = function ({
|
||||
allowMultilineValues
|
||||
preferenceName="environment"
|
||||
nameAutocomplete={nameAutocomplete}
|
||||
nameAutocompleteVariables={false}
|
||||
namePlaceholder="VAR_NAME"
|
||||
nameValidate={validateName}
|
||||
valueType={valueVisibility.value ? 'text' : 'password'}
|
||||
valueAutocompleteVariables={true}
|
||||
forceUpdateKey={environment.id}
|
||||
pairs={environment.variables}
|
||||
valueAutocompleteVariables
|
||||
valueAutocompleteFunctions
|
||||
forceUpdateKey={activeEnvironment.id}
|
||||
pairs={activeEnvironment.variables}
|
||||
onChange={handleChange}
|
||||
stateKey={`environment.${environment.id}`}
|
||||
stateKey={`environment.${activeEnvironment.id}`}
|
||||
/>
|
||||
</div>
|
||||
</VStack>
|
||||
|
||||
@@ -40,8 +40,10 @@ export function FormMultipartEditor({ request, forceUpdateKey, onChange }: Props
|
||||
|
||||
return (
|
||||
<PairEditor
|
||||
valueAutocompleteFunctions
|
||||
valueAutocompleteVariables
|
||||
nameAutocompleteVariables
|
||||
nameAutocompleteFunctions
|
||||
allowFileValues
|
||||
allowMultilineValues
|
||||
pairs={pairs}
|
||||
|
||||
@@ -31,7 +31,9 @@ export function FormUrlencodedEditor({ request, forceUpdateKey, onChange }: Prop
|
||||
<PairOrBulkEditor
|
||||
allowMultilineValues
|
||||
preferenceName="form_urlencoded"
|
||||
valueAutocompleteFunctions
|
||||
valueAutocompleteVariables
|
||||
nameAutocompleteFunctions
|
||||
nameAutocompleteVariables
|
||||
namePlaceholder="entry_name"
|
||||
valuePlaceholder="Value"
|
||||
|
||||
@@ -183,7 +183,7 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
|
||||
onChange={handleChangeVariables}
|
||||
placeholder="{}"
|
||||
stateKey={'graphql_vars.' + request.id}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
{...extraEditorProps}
|
||||
/>
|
||||
|
||||
@@ -181,8 +181,8 @@ export function GrpcEditor({
|
||||
<div className="h-full w-full grid grid-cols-1 grid-rows-[minmax(0,100%)_auto_auto_minmax(0,auto)]">
|
||||
<Editor
|
||||
language="json"
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
useTemplating
|
||||
forceUpdateKey={request.id}
|
||||
defaultValue={request.message}
|
||||
heightMode="auto"
|
||||
|
||||
@@ -21,7 +21,9 @@ export function HeadersEditor({ stateKey, headers, onChange, forceUpdateKey }: P
|
||||
<PairOrBulkEditor
|
||||
preferenceName="headers"
|
||||
stateKey={stateKey}
|
||||
valueAutocompleteFunctions
|
||||
valueAutocompleteVariables
|
||||
nameAutocompleteFunctions
|
||||
nameAutocompleteVariables
|
||||
pairs={headers}
|
||||
onChange={onChange}
|
||||
|
||||
@@ -75,7 +75,7 @@ export function HttpAuthenticationEditor({ request }: Props) {
|
||||
<DynamicForm
|
||||
disabled={request.authentication.disabled}
|
||||
autocompleteVariables
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
stateKey={`auth.${request.id}.${request.authenticationType}`}
|
||||
inputs={authConfig.data.args}
|
||||
data={request.authentication}
|
||||
|
||||
@@ -411,7 +411,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
|
||||
{activeRequest.bodyType === BODY_TYPE_JSON ? (
|
||||
<Editor
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
placeholder="..."
|
||||
heightMode={fullHeight ? 'full' : 'auto'}
|
||||
@@ -423,7 +423,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
|
||||
) : activeRequest.bodyType === BODY_TYPE_XML ? (
|
||||
<Editor
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
placeholder="..."
|
||||
heightMode={fullHeight ? 'full' : 'auto'}
|
||||
@@ -462,7 +462,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
|
||||
) : typeof activeRequest.bodyType === 'string' ? (
|
||||
<Editor
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
language={languageFromContentType(contentType)}
|
||||
placeholder="..."
|
||||
|
||||
@@ -68,12 +68,12 @@ export const UrlBar = memo(function UrlBar({
|
||||
<form onSubmit={handleSubmit} className={classNames('x-theme-urlBar', className)}>
|
||||
<Input
|
||||
ref={inputRef}
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
stateKey={stateKey}
|
||||
size="sm"
|
||||
wrapLines={isFocused}
|
||||
hideLabel
|
||||
useTemplating
|
||||
language="url"
|
||||
className="px-1.5 py-0.5"
|
||||
label="Enter URL"
|
||||
|
||||
@@ -35,12 +35,14 @@ export function UrlParametersEditor({ pairs, forceUpdateKey, onChange, stateKey
|
||||
ref={pairEditor}
|
||||
allowMultilineValues
|
||||
forceUpdateKey={forceUpdateKey + urlParametersKey}
|
||||
nameAutocompleteFunctions
|
||||
nameAutocompleteVariables
|
||||
namePlaceholder="param_name"
|
||||
onChange={onChange}
|
||||
pairs={pairs}
|
||||
preferenceName="url_parameters"
|
||||
stateKey={stateKey}
|
||||
valueAutocompleteFunctions
|
||||
valueAutocompleteVariables
|
||||
valuePlaceholder="Value"
|
||||
/>
|
||||
|
||||
@@ -301,7 +301,7 @@ export function WebsocketRequestPane({ style, fullHeight, className, activeReque
|
||||
<TabContent value={TAB_MESSAGE}>
|
||||
<Editor
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
placeholder="..."
|
||||
heightMode={fullHeight ? 'full' : 'auto'}
|
||||
|
||||
@@ -33,7 +33,7 @@ export function BulkPairEditor({
|
||||
|
||||
return (
|
||||
<Editor
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
stateKey={`bulk_pair.${stateKey}`}
|
||||
forceUpdateKey={forceUpdateKey}
|
||||
|
||||
@@ -55,36 +55,36 @@ const keymapExtensions: Record<EditorKeymap, Extension> = {
|
||||
};
|
||||
|
||||
export interface EditorProps {
|
||||
id?: string;
|
||||
readOnly?: boolean;
|
||||
disabled?: boolean;
|
||||
type?: 'text' | 'password';
|
||||
className?: string;
|
||||
heightMode?: 'auto' | 'full';
|
||||
language?: EditorLanguage | 'pairs' | 'url';
|
||||
forceUpdateKey?: string | number;
|
||||
actions?: ReactNode;
|
||||
autoFocus?: boolean;
|
||||
autoSelect?: boolean;
|
||||
autocomplete?: GenericCompletionConfig;
|
||||
autocompleteFunctions?: boolean;
|
||||
autocompleteVariables?: boolean;
|
||||
className?: string;
|
||||
defaultValue?: string | null;
|
||||
placeholder?: string;
|
||||
tooltipContainer?: HTMLElement;
|
||||
useTemplating?: boolean;
|
||||
disableTabIndent?: boolean;
|
||||
disabled?: boolean;
|
||||
extraExtensions?: Extension[];
|
||||
forceUpdateKey?: string | number;
|
||||
format?: (v: string) => Promise<string>;
|
||||
heightMode?: 'auto' | 'full';
|
||||
hideGutter?: boolean;
|
||||
id?: string;
|
||||
language?: EditorLanguage | 'pairs' | 'url';
|
||||
onBlur?: () => void;
|
||||
onChange?: (value: string) => void;
|
||||
onFocus?: () => void;
|
||||
onKeyDown?: (e: KeyboardEvent) => void;
|
||||
onPaste?: (value: string) => void;
|
||||
onPasteOverwrite?: (e: ClipboardEvent, value: string) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onKeyDown?: (e: KeyboardEvent) => void;
|
||||
placeholder?: string;
|
||||
readOnly?: boolean;
|
||||
singleLine?: boolean;
|
||||
wrapLines?: boolean;
|
||||
disableTabIndent?: boolean;
|
||||
format?: (v: string) => Promise<string>;
|
||||
autocomplete?: GenericCompletionConfig;
|
||||
autocompleteVariables?: boolean;
|
||||
extraExtensions?: Extension[];
|
||||
actions?: ReactNode;
|
||||
hideGutter?: boolean;
|
||||
stateKey: string | null;
|
||||
tooltipContainer?: HTMLElement;
|
||||
type?: 'text' | 'password';
|
||||
wrapLines?: boolean;
|
||||
}
|
||||
|
||||
const stateFields = { history: historyField, folds: foldState };
|
||||
@@ -94,34 +94,34 @@ const emptyExtension: Extension = [];
|
||||
|
||||
export const Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
|
||||
{
|
||||
readOnly,
|
||||
type,
|
||||
heightMode,
|
||||
language,
|
||||
actions,
|
||||
autoFocus,
|
||||
autoSelect,
|
||||
placeholder,
|
||||
useTemplating,
|
||||
autocomplete,
|
||||
autocompleteFunctions,
|
||||
autocompleteVariables,
|
||||
className,
|
||||
defaultValue,
|
||||
disableTabIndent,
|
||||
disabled,
|
||||
extraExtensions,
|
||||
forceUpdateKey,
|
||||
format,
|
||||
heightMode,
|
||||
hideGutter,
|
||||
language,
|
||||
onBlur,
|
||||
onChange,
|
||||
onFocus,
|
||||
onKeyDown,
|
||||
onPaste,
|
||||
onPasteOverwrite,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onKeyDown,
|
||||
className,
|
||||
disabled,
|
||||
placeholder,
|
||||
readOnly,
|
||||
singleLine,
|
||||
format,
|
||||
autocomplete,
|
||||
extraExtensions,
|
||||
autocompleteVariables,
|
||||
actions,
|
||||
wrapLines,
|
||||
disableTabIndent,
|
||||
hideGutter,
|
||||
stateKey,
|
||||
type,
|
||||
wrapLines,
|
||||
}: EditorProps,
|
||||
ref,
|
||||
) {
|
||||
@@ -129,6 +129,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
|
||||
const allEnvironmentVariables = useActiveEnvironmentVariables();
|
||||
const environmentVariables = autocompleteVariables ? allEnvironmentVariables : emptyVariables;
|
||||
const useTemplating = !!(autocompleteFunctions || autocompleteVariables || autocomplete);
|
||||
|
||||
if (settings && wrapLines === undefined) {
|
||||
wrapLines = settings.editorSoftWrap;
|
||||
@@ -340,16 +341,19 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
[focusParamValue],
|
||||
);
|
||||
|
||||
const completionOptions = useTemplateFunctionCompletionOptions(onClickFunction);
|
||||
const completionOptions = useTemplateFunctionCompletionOptions(
|
||||
onClickFunction,
|
||||
!!autocompleteFunctions,
|
||||
);
|
||||
|
||||
// Update the language extension when the language changes
|
||||
useEffect(() => {
|
||||
if (cm.current === null) return;
|
||||
const { view, languageCompartment } = cm.current;
|
||||
const ext = getLanguageExtension({
|
||||
useTemplating,
|
||||
language,
|
||||
environmentVariables,
|
||||
useTemplating,
|
||||
autocomplete,
|
||||
completionOptions,
|
||||
onClickVariable,
|
||||
@@ -360,13 +364,13 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
}, [
|
||||
language,
|
||||
autocomplete,
|
||||
useTemplating,
|
||||
environmentVariables,
|
||||
onClickFunction,
|
||||
onClickVariable,
|
||||
onClickMissingVariable,
|
||||
onClickPathParameter,
|
||||
completionOptions,
|
||||
useTemplating,
|
||||
]);
|
||||
|
||||
// Initialize the editor when ref mounts
|
||||
@@ -381,8 +385,8 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
||||
try {
|
||||
const languageCompartment = new Compartment();
|
||||
const langExt = getLanguageExtension({
|
||||
language,
|
||||
useTemplating,
|
||||
language,
|
||||
completionOptions,
|
||||
autocomplete,
|
||||
environmentVariables,
|
||||
|
||||
@@ -91,8 +91,8 @@ const syntaxExtensions: Record<NonNullable<EditorProps['language']>, LanguageSup
|
||||
const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript', 'graphql'];
|
||||
|
||||
export function getLanguageExtension({
|
||||
useTemplating,
|
||||
language = 'text',
|
||||
useTemplating = false,
|
||||
environmentVariables,
|
||||
autocomplete,
|
||||
onClickVariable,
|
||||
@@ -100,12 +100,13 @@ export function getLanguageExtension({
|
||||
onClickPathParameter,
|
||||
completionOptions,
|
||||
}: {
|
||||
useTemplating: boolean;
|
||||
environmentVariables: EnvironmentVariable[];
|
||||
onClickVariable: (option: EnvironmentVariable, tagValue: string, startPos: number) => void;
|
||||
onClickMissingVariable: (name: string, tagValue: string, startPos: number) => void;
|
||||
onClickPathParameter: (name: string) => void;
|
||||
completionOptions: TwigCompletionOption[];
|
||||
} & Pick<EditorProps, 'language' | 'useTemplating' | 'autocomplete'>) {
|
||||
} & Pick<EditorProps, 'language' | 'autocomplete'>) {
|
||||
const extraExtensions: Extension[] = [];
|
||||
|
||||
if (language === 'url') {
|
||||
|
||||
@@ -13,13 +13,13 @@ import { HStack } from './Stacks';
|
||||
export type InputProps = Pick<
|
||||
EditorProps,
|
||||
| 'language'
|
||||
| 'useTemplating'
|
||||
| 'autocomplete'
|
||||
| 'forceUpdateKey'
|
||||
| 'disabled'
|
||||
| 'autoFocus'
|
||||
| 'autoSelect'
|
||||
| 'autocompleteVariables'
|
||||
| 'autocompleteFunctions'
|
||||
| 'onKeyDown'
|
||||
| 'readOnly'
|
||||
> & {
|
||||
|
||||
@@ -43,6 +43,7 @@ export type PairEditorProps = {
|
||||
className?: string;
|
||||
forceUpdateKey?: string;
|
||||
nameAutocomplete?: GenericCompletionConfig;
|
||||
nameAutocompleteFunctions?: boolean;
|
||||
nameAutocompleteVariables?: boolean;
|
||||
namePlaceholder?: string;
|
||||
nameValidate?: InputProps['validate'];
|
||||
@@ -51,6 +52,7 @@ export type PairEditorProps = {
|
||||
pairs: Pair[];
|
||||
stateKey: InputProps['stateKey'];
|
||||
valueAutocomplete?: (name: string) => GenericCompletionConfig | undefined;
|
||||
valueAutocompleteFunctions?: boolean;
|
||||
valueAutocompleteVariables?: boolean;
|
||||
valuePlaceholder?: string;
|
||||
valueType?: 'text' | 'password';
|
||||
@@ -82,6 +84,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
|
||||
className,
|
||||
forceUpdateKey,
|
||||
nameAutocomplete,
|
||||
nameAutocompleteFunctions,
|
||||
nameAutocompleteVariables,
|
||||
namePlaceholder,
|
||||
nameValidate,
|
||||
@@ -89,6 +92,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
|
||||
onChange,
|
||||
pairs: originalPairs,
|
||||
valueAutocomplete,
|
||||
valueAutocompleteFunctions,
|
||||
valueAutocompleteVariables,
|
||||
valuePlaceholder,
|
||||
valueType,
|
||||
@@ -237,6 +241,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
|
||||
index={i}
|
||||
isLast={isLast}
|
||||
nameAutocomplete={nameAutocomplete}
|
||||
nameAutocompleteFunctions={nameAutocompleteFunctions}
|
||||
nameAutocompleteVariables={nameAutocompleteVariables}
|
||||
namePlaceholder={namePlaceholder}
|
||||
nameValidate={nameValidate}
|
||||
@@ -248,6 +253,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
|
||||
pair={p}
|
||||
stateKey={stateKey}
|
||||
valueAutocomplete={valueAutocomplete}
|
||||
valueAutocompleteFunctions={valueAutocompleteFunctions}
|
||||
valueAutocompleteVariables={valueAutocompleteVariables}
|
||||
valuePlaceholder={valuePlaceholder}
|
||||
valueType={valueType}
|
||||
@@ -291,8 +297,10 @@ type PairEditorRowProps = {
|
||||
| 'nameAutocompleteVariables'
|
||||
| 'namePlaceholder'
|
||||
| 'nameValidate'
|
||||
| 'nameAutocompleteFunctions'
|
||||
| 'stateKey'
|
||||
| 'valueAutocomplete'
|
||||
| 'valueAutocompleteFunctions'
|
||||
| 'valueAutocompleteVariables'
|
||||
| 'valuePlaceholder'
|
||||
| 'valueType'
|
||||
@@ -309,9 +317,10 @@ function PairEditorRow({
|
||||
index,
|
||||
isLast,
|
||||
nameAutocomplete,
|
||||
nameAutocompleteVariables,
|
||||
namePlaceholder,
|
||||
nameValidate,
|
||||
nameAutocompleteFunctions,
|
||||
nameAutocompleteVariables,
|
||||
onChange,
|
||||
onDelete,
|
||||
onEnd,
|
||||
@@ -320,6 +329,7 @@ function PairEditorRow({
|
||||
pair,
|
||||
stateKey,
|
||||
valueAutocomplete,
|
||||
valueAutocompleteFunctions,
|
||||
valueAutocompleteVariables,
|
||||
valuePlaceholder,
|
||||
valueType,
|
||||
@@ -486,7 +496,6 @@ function PairEditorRow({
|
||||
<Input
|
||||
ref={nameInputRef}
|
||||
hideLabel
|
||||
useTemplating
|
||||
stateKey={`name.${pair.id}.${stateKey}`}
|
||||
wrapLines={false}
|
||||
readOnly={pair.readOnlyName}
|
||||
@@ -503,6 +512,7 @@ function PairEditorRow({
|
||||
placeholder={namePlaceholder ?? 'name'}
|
||||
autocomplete={nameAutocomplete}
|
||||
autocompleteVariables={nameAutocompleteVariables}
|
||||
autocompleteFunctions={nameAutocompleteFunctions}
|
||||
/>
|
||||
)}
|
||||
<div className="w-full grid grid-cols-[minmax(0,1fr)_auto] gap-1 items-center">
|
||||
@@ -534,7 +544,6 @@ function PairEditorRow({
|
||||
<Input
|
||||
ref={valueInputRef}
|
||||
hideLabel
|
||||
useTemplating
|
||||
stateKey={`value.${pair.id}.${stateKey}`}
|
||||
wrapLines={false}
|
||||
size="sm"
|
||||
@@ -549,6 +558,7 @@ function PairEditorRow({
|
||||
type={isLast ? 'text' : valueType}
|
||||
placeholder={valuePlaceholder ?? 'value'}
|
||||
autocomplete={valueAutocomplete?.(pair.name)}
|
||||
autocompleteFunctions={valueAutocompleteFunctions}
|
||||
autocompleteVariables={valueAutocompleteVariables}
|
||||
/>
|
||||
)}
|
||||
@@ -695,7 +705,7 @@ function MultilineEditDialog({
|
||||
language={language}
|
||||
onChange={setValue}
|
||||
stateKey={null}
|
||||
useTemplating
|
||||
autocompleteFunctions
|
||||
autocompleteVariables
|
||||
/>
|
||||
<div>
|
||||
|
||||
@@ -11,9 +11,13 @@ const templateFunctionsAtom = atom<TemplateFunction[]>([]);
|
||||
|
||||
export function useTemplateFunctionCompletionOptions(
|
||||
onClick: (fn: TemplateFunction, ragTag: string, pos: number) => void,
|
||||
enabled: boolean,
|
||||
) {
|
||||
const templateFunctions = useAtomValue(templateFunctionsAtom);
|
||||
return useMemo<TwigCompletionOption[]>(() => {
|
||||
if (!enabled) {
|
||||
return [];
|
||||
}
|
||||
return (
|
||||
templateFunctions.map((fn) => {
|
||||
const NUM_ARGS = 2;
|
||||
@@ -35,7 +39,7 @@ export function useTemplateFunctionCompletionOptions(
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
}, [onClick, templateFunctions]);
|
||||
}, [enabled, onClick, templateFunctions]);
|
||||
}
|
||||
|
||||
export function useSubscribeTemplateFunctions() {
|
||||
|
||||
Reference in New Issue
Block a user