Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,11 @@ export const RequestParametersEditor: FC<Props> = ({
);
}

const pairsIds = activeRequest.parameters.map((param, index) => param.id || index).join(',');

return (
<KeyValueEditor
key={pairsIds}
allowMultiline
namePlaceholder="name"
valuePlaceholder="value"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ interface Pair {
multiline?: boolean | string;
}

function createEmptyPair() {
return {
id: generateId('pair'),
name: '',
value: '',
description: '',
disabled: false,
};
}

type AutocompleteHandler = (pair: Pair) => string[] | PromiseLike<string[]>;

interface Props {
Expand Down Expand Up @@ -55,14 +65,14 @@ export const KeyValueEditor: FC<Props> = ({
const [showDescription, setShowDescription] = React.useState(false);
const { enabled: nunjucksEnabled } = useNunjucksEnabled();
const pairsList = useListData({
initialItems: pairs.map(pair => {
initialItems: pairs.length > 0 ? pairs.map(pair => {
const pairId = pair.id || generateId('pair');
return { ...pair, id: pairId };
}),
}) : [createEmptyPair()],
getKey: item => item.id,
});

const items = pairsList.items.length > 0 ? pairsList.items : [{ id: 'pair-empty', name: '', value: '', description: '', disabled: false }];
const items = pairsList.items.length > 0 ? pairsList.items : [];

const readOnlyPairsList = useListData({
initialItems: readOnlyPairs?.map(pair => {
Expand All @@ -89,21 +99,26 @@ export const KeyValueEditor: FC<Props> = ({
if (pairsList.getItem(id)) {
pairsList.remove(id);
const items = pairsList.items.filter(pair => pair.id !== id);

if (pairsList.items.length === 0) {
pairsList.append(createEmptyPair());
}

onChange(items);
}
}, [onChange, pairsList]);

const removeAllPairs = useCallback(function removeAllPairs() {
pairsList.setSelectedKeys(new Set(pairsList.items.map(item => item.id)));
pairsList.removeSelectedItems();
pairsList.append(createEmptyPair());
onChange([]);
}, [onChange, pairsList]);

const { dragAndDropHooks } = useDragAndDrop({
getItems: keys =>
[...keys].map(key => {
const pair = pairsList.getItem(key);
console.log('drag-pair', pair);
return { 'text/plain': `${pair.id}` };
}),
onReorder(e) {
Expand Down Expand Up @@ -135,7 +150,6 @@ export const KeyValueEditor: FC<Props> = ({
renderDragPreview(items) {
const pair = pairsList.getItem(items[0]['text/plain']);

console.log({ pair });
const element = document.querySelector(`[data-key="${pair.id}"]`);

const isFile = pair.type === 'file';
Expand Down Expand Up @@ -347,7 +361,8 @@ export const KeyValueEditor: FC<Props> = ({
// dependencies={[showDescription, nunjucksEnabled]}
className="flex pt-1 flex-col w-full overflow-y-auto flex-1 relative"
dragAndDropHooks={dragAndDropHooks}
items={items.map(pair => ({ ...pair, upsertPair, removePair }))}
dependencies={[upsertPair, removePair, showDescription, nunjucksEnabled]}
items={items}
>
{pair => {
const isFile = pair.type === 'file';
Expand All @@ -357,11 +372,12 @@ export const KeyValueEditor: FC<Props> = ({
let valueEditor = (
<OneLineEditor
id={'key-value-editor__value' + pair.id}
key={'key-value-editor__value' + pair.id + pair.disabled}
placeholder={valuePlaceholder || 'Value'}
defaultValue={pair.value}
readOnly={pair.disabled || isDisabled}
getAutocompleteConstants={() => handleGetAutocompleteValueConstants?.(pair) || []}
onChange={value => pair.upsertPair({ ...pair, value })}
onChange={value => upsertPair({ ...pair, value })}
/>
);

Expand All @@ -373,7 +389,7 @@ export const KeyValueEditor: FC<Props> = ({
disabled={pair.disabled || isDisabled}
className="px-2 py-1 w-full fle flex-shrink-0 flex-1 items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] rounded-sm text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-sm overflow-hidden"
path={pair.fileName || ''}
onChange={fileName => pair.upsertPair({ ...pair, fileName })}
onChange={fileName => upsertPair({ ...pair, fileName })}
/>
);
}
Expand All @@ -389,8 +405,8 @@ export const KeyValueEditor: FC<Props> = ({
defaultValue: pair.value,
enableRender: nunjucksEnabled,
mode: pair.multiline && typeof pair.multiline === 'string' ? pair.multiline : 'text/plain',
onChange: (value: string) => pair.upsertPair({ ...pair, value }),
onModeChange: (mode: string) => pair.upsertPair({ ...pair, multiline: mode }),
onChange: (value: string) => upsertPair({ ...pair, value }),
onModeChange: (mode: string) => upsertPair({ ...pair, multiline: mode }),
})}
>
<i className="fa fa-pencil-square-o space-right" />
Expand Down Expand Up @@ -420,20 +436,24 @@ export const KeyValueEditor: FC<Props> = ({
</div>
<OneLineEditor
id={'key-value-editor__name' + pair.id}
key={'key-value-editor__name' + pair.id + pair.disabled}
placeholder={namePlaceholder || 'Name'}
defaultValue={pair.name}
readOnly={pair.disabled || isDisabled}
getAutocompleteConstants={() => handleGetAutocompleteNameConstants?.(pair) || []}
onChange={name => pair.upsertPair({ ...pair, name })}
onChange={name => {
upsertPair({ ...pair, name });
}}
/>
{valueEditor}
{showDescription && (
<OneLineEditor
id={'key-value-editor__description' + pair.id}
key={'key-value-editor__description' + pair.id + pair.disabled}
placeholder={descriptionPlaceholder || 'Description'}
defaultValue={pair.description || ''}
readOnly={pair.disabled || isDisabled}
onChange={description => pair.upsertPair({ ...pair, description })}
onChange={description => upsertPair({ ...pair, description })}
/>
)}
<Toolbar className="flex items-center gap-1">
Expand All @@ -455,22 +475,22 @@ export const KeyValueEditor: FC<Props> = ({
id: 'text',
name: 'Text',
textValue: 'Text',
onAction: () => pair.upsertPair({ ...pair, type: 'text', multiline: false }),
onAction: () => upsertPair({ ...pair, type: 'text', multiline: false }),
},
...allowMultiline ? [
{
id: 'multiline-text',
name: 'Multiline text',
textValue: 'Multiline text',
onAction: () => pair.upsertPair({ ...pair, type: 'text', multiline: true }),
onAction: () => upsertPair({ ...pair, type: 'text', multiline: true }),
},
] : [],
...allowFile ? [
{
id: 'file',
name: 'File',
textValue: 'File',
onAction: () => pair.upsertPair({ ...pair, type: 'file' }),
onAction: () => upsertPair({ ...pair, type: 'file' }),
},
] : [],
]}
Expand All @@ -491,7 +511,7 @@ export const KeyValueEditor: FC<Props> = ({
</MenuTrigger>
<ToggleButton
className="flex items-center justify-center h-7 aspect-square rounded-sm text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-sm"
onChange={isSelected => pair.upsertPair({ ...pair, disabled: !isSelected })}
onChange={isSelected => upsertPair({ ...pair, disabled: !isSelected })}
isSelected={!pair.disabled}
>
<Icon icon={pair.disabled ? 'square' : 'check-square'} />
Expand All @@ -501,7 +521,7 @@ export const KeyValueEditor: FC<Props> = ({
className="flex items-center disabled:opacity-50 justify-center h-7 aspect-square aria-pressed:bg-[--hl-sm] rounded-sm text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-sm"
confirmMessage=''
doneMessage=''
onClick={() => pair.removePair(pair.id)}
onClick={() => removePair(pair.id)}
>
<Icon icon="trash-can" />
</PromptButton>
Expand Down