Variables under Environment, and render all props

This commit is contained in:
Gregory Schier
2023-10-28 11:29:29 -07:00
parent d0387bdf76
commit 3ad132d77d
17 changed files with 263 additions and 275 deletions

View File

@@ -14,6 +14,7 @@ export function BasicAuth({ requestId, authentication }: Props) {
return (
<VStack className="my-2" space={2}>
<Input
useTemplating
label="Username"
name="username"
size="sm"
@@ -26,6 +27,7 @@ export function BasicAuth({ requestId, authentication }: Props) {
}}
/>
<Input
useTemplating
label="Password"
name="password"
size="sm"

View File

@@ -14,6 +14,7 @@ export function BearerAuth({ requestId, authentication }: Props) {
return (
<VStack className="my-2" space={2}>
<Input
useTemplating
label="Token"
name="token"
size="sm"

View File

@@ -4,16 +4,11 @@ import { Button } from './core/Button';
import type { DropdownItem } from './core/Dropdown';
import { Dropdown } from './core/Dropdown';
import { Icon } from './core/Icon';
import { InlineCode } from './core/InlineCode';
import { useEnvironments } from '../hooks/useEnvironments';
import { useActiveEnvironment } from '../hooks/useActiveEnvironment';
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
import { usePrompt } from '../hooks/usePrompt';
import { useDialog } from './DialogContext';
import { EnvironmentEditDialog } from './EnvironmentEditDialog';
import { useAppRoutes } from '../hooks/useAppRoutes';
import { useDeleteEnvironment } from '../hooks/useDeleteEnvironment';
type Props = {
className?: string;
@@ -24,62 +19,23 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo
}: Props) {
const environments = useEnvironments();
const activeEnvironment = useActiveEnvironment();
const updateEnvironment = useUpdateEnvironment(activeEnvironment?.id ?? null);
const deleteEnvironment = useDeleteEnvironment(activeEnvironment);
const createEnvironment = useCreateEnvironment();
const prompt = usePrompt();
const dialog = useDialog();
const routes = useAppRoutes();
const items: DropdownItem[] = useMemo(() => {
const environmentItems: DropdownItem[] = environments.map(
(e) => ({
key: e.id,
label: e.name,
rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined,
onSelect: async () => {
routes.setEnvironment(e);
},
}),
[activeEnvironment?.id],
);
return [
...environmentItems,
...((environmentItems.length > 0
? [{ type: 'separator', label: activeEnvironment?.name }]
: []) as DropdownItem[]),
...((activeEnvironment != null
? [
{
key: 'rename',
label: 'Rename',
leftSlot: <Icon icon="pencil" />,
onSelect: async () => {
const name = await prompt({
title: 'Rename Environment',
description: (
<>
Enter a new name for <InlineCode>{activeEnvironment?.name}</InlineCode>
</>
),
name: 'name',
label: 'Name',
defaultValue: activeEnvironment?.name,
});
updateEnvironment.mutate({ name });
},
},
{
key: 'delete',
label: 'Delete',
leftSlot: <Icon icon="trash" />,
onSelect: deleteEnvironment.mutate,
variant: 'danger',
},
{ type: 'separator' },
]
: []) as DropdownItem[]),
const items: DropdownItem[] = useMemo(
() => [
...environments.map(
(e) => ({
key: e.id,
label: e.name,
rightSlot: e.id === activeEnvironment?.id ? <Icon icon="check" /> : undefined,
onSelect: async () => {
routes.setEnvironment(e);
},
}),
[activeEnvironment?.id],
),
{ type: 'separator', label: 'Environments' },
...((environments.length > 0
? [
{
@@ -95,32 +51,9 @@ export const EnvironmentActionsDropdown = memo(function EnvironmentActionsDropdo
},
]
: []) as DropdownItem[]),
{
key: 'create-environment',
label: 'Create Environment',
leftSlot: <Icon icon="plus" />,
onSelect: async () => {
const name = await prompt({
name: 'name',
label: 'Name',
defaultValue: 'My Environment',
description: 'Enter a name for the new environment',
title: 'Create Environment',
});
createEnvironment.mutate({ name });
},
},
];
}, [
activeEnvironment,
createEnvironment,
deleteEnvironment,
dialog,
environments,
prompt,
routes,
updateEnvironment,
]);
],
[activeEnvironment, dialog, environments, routes],
);
return (
<Dropdown items={items}>

View File

@@ -1,16 +1,17 @@
import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
import { useEnvironments } from '../hooks/useEnvironments';
import { usePrompt } from '../hooks/usePrompt';
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
import type { Environment } from '../lib/models';
import { Button } from './core/Button';
import { Editor } from './core/Editor';
import classNames from 'classnames';
import { useActiveEnvironment } from '../hooks/useActiveEnvironment';
import { Link } from 'react-router-dom';
import { useAppRoutes } from '../hooks/useAppRoutes';
import { PairEditor } from './core/PairEditor';
import type { PairEditorProps } from './core/PairEditor';
import { useCallback } from 'react';
import { useUpdateEnvironment } from '../hooks/useUpdateEnvironment';
export const EnvironmentEditDialog = function() {
export const EnvironmentEditDialog = function () {
const routes = useAppRoutes();
const prompt = usePrompt();
const environments = useEnvironments();
@@ -58,21 +59,21 @@ export const EnvironmentEditDialog = function() {
);
};
const EnvironmentEditor = function({ environment }: { environment: Environment }) {
const EnvironmentEditor = function ({ environment }: { environment: Environment }) {
const updateEnvironment = useUpdateEnvironment(environment.id);
const handleChange = useCallback<PairEditorProps['onChange']>(
(variables) => {
updateEnvironment.mutate({ variables });
},
[updateEnvironment],
);
return (
<Editor
contentType="application/json"
className="w-full min-h-[40px] !bg-gray-50"
defaultValue={JSON.stringify(environment.data, null, 2)}
forceUpdateKey={environment.id}
onChange={(data) => {
try {
updateEnvironment.mutate({ data: JSON.parse(data) });
} catch (err) {
// That's okay
}
}}
/>
<div>
<PairEditor
forceUpdateKey={environment.id}
pairs={environment.variables}
onChange={handleChange}
/>
</div>
);
};

View File

@@ -63,5 +63,7 @@ const validateHttpHeader = (v: string) => {
return true;
}
const hi = v.replace(/\$\{\[\s*[^\]\s]+\s*]}/gi, 'fo');
console.log('V', v, '-->', hi);
return v.match(/^[a-zA-Z0-9-_]+$/) !== null;
};

View File

@@ -54,6 +54,8 @@
/* Bring above on hover */
@apply hover:z-10 relative;
-webkit-text-security: none;
}
}

View File

@@ -12,7 +12,6 @@ import './Editor.css';
import { baseExtensions, getLanguageExtension, multiLineExtensions } from './extensions';
import type { GenericCompletionConfig } from './genericCompletion';
import { singleLineExt } from './singleLine';
import { useEnvironments } from '../../../hooks/useEnvironments';
import { useActiveEnvironment } from '../../../hooks/useActiveEnvironment';
// Export some things so all the code-split parts are in this file

View File

@@ -48,7 +48,7 @@ const placeholderMatcher = new BetterMatchDecorator({
if (groupMatch == null) {
// Should never happen, but make TS happy
console.warn('Group match was empty', match);
return Decoration.replace({});;
return Decoration.replace({});
}
return Decoration.replace({

View File

@@ -9,11 +9,13 @@ import { twigCompletion } from './completion';
import { parser as twigParser } from './twig';
import type { Environment } from '../../../../lib/models';
export function twig(base: LanguageSupport, environment: Environment | null, autocomplete?: GenericCompletionConfig) {
// TODO: fill variables here
const data = environment?.data ?? {};
const options = Object.keys(data).map(key => ({ name: key }));
const completions = twigCompletion({ options });
export function twig(
base: LanguageSupport,
environment: Environment | null,
autocomplete?: GenericCompletionConfig,
) {
const variables = environment?.variables ?? [];
const completions = twigCompletion({ options: variables });
const language = mixLanguage(base);
const completion = language.data.of({ autocomplete: completions });

View File

@@ -1,5 +1,5 @@
import classNames from 'classnames';
import React, { Fragment, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Fragment, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { XYCoord } from 'react-dnd';
import { useDrag, useDrop } from 'react-dnd';
import { v4 as uuid } from 'uuid';
@@ -24,7 +24,8 @@ export type PairEditorProps = {
valueValidate?: InputProps['validate'];
};
type Pair = {
export type Pair = {
id?: string;
enabled?: boolean;
name: string;
value: string;
@@ -342,6 +343,8 @@ const FormRow = memo(function FormRow({
);
});
const newPairContainer = (pair?: Pair): PairContainer => {
return { pair: pair ?? { name: '', value: '', enabled: true }, id: uuid() };
const newPairContainer = (initialPair?: Pair): PairContainer => {
const id = initialPair?.id ?? uuid();
const pair = initialPair ?? { name: '', value: '', enabled: true };
return { id, pair };
};