diff --git a/pkg/dashboard/frontend/cypress/e2e/api-explorer.cy.ts b/pkg/dashboard/frontend/cypress/e2e/api-explorer.cy.ts index d859827c..c07a0732 100644 --- a/pkg/dashboard/frontend/cypress/e2e/api-explorer.cy.ts +++ b/pkg/dashboard/frontend/cypress/e2e/api-explorer.cy.ts @@ -99,6 +99,8 @@ describe('APIs spec', () => { cy.getTestEl('query-0-key').type('firstParam') cy.getTestEl('query-0-value').type('myValue') + cy.getTestEl('add-row-btn').click() + cy.getTestEl('query-1-key').type('secondParam') cy.getTestEl('query-1-value').type('mySecondValue') @@ -149,6 +151,8 @@ describe('APIs spec', () => { cy.getTestEl('header-2-key').clear().type('X-First-Header') cy.getTestEl('header-2-value').clear().type('the value') + cy.getTestEl('add-row-btn').click() + cy.getTestEl('header-3-key').clear().type('X-Second-Header') cy.getTestEl('header-3-value').clear().type('the second value') diff --git a/pkg/dashboard/frontend/cypress/e2e/websockets.cy.ts b/pkg/dashboard/frontend/cypress/e2e/websockets.cy.ts index 30e481e8..2946691b 100644 --- a/pkg/dashboard/frontend/cypress/e2e/websockets.cy.ts +++ b/pkg/dashboard/frontend/cypress/e2e/websockets.cy.ts @@ -94,6 +94,8 @@ describe('Websockets Spec', () => { cy.getTestEl('query-0-key').type('firstParam') cy.getTestEl('query-0-value').type('myValue') + cy.getTestEl('add-row-btn').click() + cy.getTestEl('query-1-key').type('secondParam') cy.getTestEl('query-1-value').type('mySecondValue') diff --git a/pkg/dashboard/frontend/src/components/apis/APIExplorer.tsx b/pkg/dashboard/frontend/src/components/apis/APIExplorer.tsx index c964b26c..ae8d2c7d 100644 --- a/pkg/dashboard/frontend/src/components/apis/APIExplorer.tsx +++ b/pkg/dashboard/frontend/src/components/apis/APIExplorer.tsx @@ -82,6 +82,10 @@ const requestDefault = { key: 'User-Agent', value: 'Nitric Client (https://www.nitric.io)', }, + { + key: 'Content-Type', + value: 'application/json', + }, ], } @@ -318,17 +322,19 @@ const APIExplorer = () => { const url = `http://${getHost()}/api/call` + path // Set a default content type if not set - if (!headers.find(({ key }) => key.toLowerCase() === 'content-type')) { - headers.push({ - key: 'Content-Type', - value: currentBodyTab.contentType, - }) - } + const shouldAddContentType = !headers.find( + ({ key }) => key.toLowerCase() === 'content-type', + ) const requestOptions: RequestInit = { method, headers: fieldRowArrToHeaders([ - ...headers, + ...(shouldAddContentType + ? [ + ...headers, + { key: 'Content-Type', value: currentBodyTab.contentType }, + ] + : headers), { key: 'X-Nitric-Local-Call-Address', value: apiAddress || 'localhost:4001', @@ -600,6 +606,7 @@ const APIExplorer = () => { { setRequest((prev) => ({ ...prev, @@ -615,6 +622,7 @@ const APIExplorer = () => { { setRequest((prev) => ({ ...prev, diff --git a/pkg/dashboard/frontend/src/components/apis/APIHistory.tsx b/pkg/dashboard/frontend/src/components/apis/APIHistory.tsx index 814fb7c1..911137cd 100644 --- a/pkg/dashboard/frontend/src/components/apis/APIHistory.tsx +++ b/pkg/dashboard/frontend/src/components/apis/APIHistory.tsx @@ -57,7 +57,7 @@ const APIHistory: React.FC = ({ }) if (!requestHistory.length) { - return

There is no history.

+ return

There is no history.

} return ( diff --git a/pkg/dashboard/frontend/src/components/shared/FieldRows.tsx b/pkg/dashboard/frontend/src/components/shared/FieldRows.tsx index 65add6fb..d590eb5e 100644 --- a/pkg/dashboard/frontend/src/components/shared/FieldRows.tsx +++ b/pkg/dashboard/frontend/src/components/shared/FieldRows.tsx @@ -1,8 +1,9 @@ import { ExclamationCircleIcon, XMarkIcon } from '@heroicons/react/20/solid' import { cn } from '@/lib/utils' -import React, { useEffect, useId } from 'react' +import React, { useId } from 'react' import { Input } from '../ui/input' import { Label } from '../ui/label' +import { Button } from '../ui/button' export interface FieldRow { key: string @@ -14,10 +15,10 @@ interface Props { rows: FieldRow[] lockKeys?: boolean readOnly?: boolean - canClearRow?: boolean valueRequired?: boolean valueErrors?: Record setRows: (value: FieldRow[]) => void + addRowLabel?: string } const FieldRows: React.FC = ({ @@ -28,127 +29,133 @@ const FieldRows: React.FC = ({ setRows, valueErrors, valueRequired, - canClearRow = true, + addRowLabel = 'Add Row', }) => { const id = useId() - useEffect(() => { - if ( - !lockKeys && - (rows[rows.length - 1].key || rows[rows.length - 1].value) - ) { - setRows([ - ...rows, - { - key: '', - value: '', - }, - ]) - } - }, [rows]) - return ( -
    - {rows.map((r, i) => { - const keyId = `${id}-${i}-key` - const valueId = `${id}-${i}-value` - const valueHasError = Boolean(valueErrors && valueErrors[i]) +
    +
      + {rows.map((r, i) => { + const keyId = `${id}-${i}-key` + const valueId = `${id}-${i}-value` + const valueHasError = Boolean(valueErrors && valueErrors[i]) - return ( -
    • -
      - -
      - { - const updatedRow: FieldRow = { ...r, key: e.target.value } - const newArr = [...rows] + return ( +
    • +
      + +
      + { + const updatedRow: FieldRow = { ...r, key: e.target.value } + const newArr = [...rows] - newArr[i] = updatedRow + newArr[i] = updatedRow - setRows(newArr) - }} - value={r.key} - name={keyId} - id={keyId} - /> + setRows(newArr) + }} + value={r.key} + name={keyId} + id={keyId} + /> +
      -
    -
    - -
    - { - const updatedRow: FieldRow = { - ...r, - value: e.target.value, - } - const newArr = [...rows] +
    + +
    + { + const updatedRow: FieldRow = { + ...r, + value: e.target.value, + } + const newArr = [...rows] - newArr[i] = updatedRow + newArr[i] = updatedRow - setRows(newArr) + setRows(newArr) + }} + required={valueRequired} + name={valueId} + id={valueId} + value={r.value} + className={cn( + valueHasError && + 'text-red-900 !ring-red-500 placeholder:text-red-300', + )} + /> + {valueHasError && ( +
    +
    + )} +
    +
    + {!lockKeys && ( +
    -
    - {canClearRow && ( - - )} + > +
+ )} + + {!lockKeys && ( + + )} + ) } diff --git a/pkg/dashboard/frontend/src/components/websockets/WSExplorer.tsx b/pkg/dashboard/frontend/src/components/websockets/WSExplorer.tsx index 4ec483e4..7267b572 100644 --- a/pkg/dashboard/frontend/src/components/websockets/WSExplorer.tsx +++ b/pkg/dashboard/frontend/src/components/websockets/WSExplorer.tsx @@ -559,6 +559,7 @@ const WSExplorer = () => { { setQueryParams(rows) @@ -587,7 +588,6 @@ const WSExplorer = () => {