Tweaks for JWT auth

This commit is contained in:
Gregory Schier
2025-01-17 15:23:15 -08:00
parent 6ae0bc1ef6
commit 7a6ab60d30
11 changed files with 142 additions and 33 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "@yaakapp/api",
"version": "0.2.29",
"version": "0.3.2",
"main": "lib/index.js",
"typings": "./lib/index.d.ts",
"files": [

View File

@@ -67,6 +67,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -81,6 +85,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -90,7 +98,15 @@ export type FormInputEditor = {
/**
* Placeholder for the text input
*/
placeholder?: string | null, language: EditorLanguage, name: string,
placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
language?: EditorLanguage, name: string,
/**
* Whether the user must fill in the argument
*/
@@ -99,6 +115,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -121,6 +141,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -135,6 +159,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -153,6 +181,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -177,6 +209,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/

View File

@@ -67,6 +67,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -81,6 +85,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -90,7 +98,15 @@ export type FormInputEditor = {
/**
* Placeholder for the text input
*/
placeholder?: string | null, language: EditorLanguage, name: string,
placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
language?: EditorLanguage, name: string,
/**
* Whether the user must fill in the argument
*/
@@ -99,6 +115,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -121,6 +141,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -135,6 +159,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -153,6 +181,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
@@ -177,6 +209,10 @@ optional?: boolean,
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/

View File

@@ -379,6 +379,10 @@ pub struct FormInputBase {
#[ts(optional)]
pub label: Option<String>,
/// Visually hide the label of the input
#[ts(optional)]
pub hide_label: Option<bool>,
/// The default value
#[ts(optional)]
pub default_value: Option<String>,
@@ -430,7 +434,13 @@ pub struct FormInputEditor {
#[ts(optional = nullable)]
pub placeholder: Option<String>,
pub language: EditorLanguage,
/// Don't show the editor gutter (line numbers, folds, etc.)
#[ts(optional)]
pub hide_gutter: Option<bool>,
/// Language for syntax highlighting
#[ts(optional)]
pub language: Option<EditorLanguage>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, TS)]

View File

@@ -13,6 +13,7 @@ import { useCallback } from 'react';
import { useActiveRequest } from '../hooks/useActiveRequest';
import { useFolders } from '../hooks/useFolders';
import { useHttpRequests } from '../hooks/useHttpRequests';
import { capitalize } from '../lib/capitalize';
import { fallbackRequestName } from '../lib/fallbackRequestName';
import { Checkbox } from './core/Checkbox';
import { Editor } from './core/Editor/Editor';
@@ -46,7 +47,7 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
);
return (
<VStack space={3}>
<VStack space={3} className="h-full overflow-auto">
{config.map((a, i) => {
switch (a.type) {
case 'select':
@@ -66,7 +67,7 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
arg={a}
useTemplating={useTemplating || false}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : ''}
value={data[a.name] ? String(data[a.name]) : DYNAMIC_FORM_NULL_ARG}
/>
);
case 'editor':
@@ -77,7 +78,7 @@ export function DynamicForm<T extends Record<string, string | boolean>>({
arg={a}
useTemplating={useTemplating || false}
onChange={(v) => setDataAttr(a.name, v)}
value={data[a.name] ? String(data[a.name]) : ''}
value={data[a.name] ? String(data[a.name]) : DYNAMIC_FORM_NULL_ARG}
/>
);
case 'checkbox':
@@ -137,7 +138,7 @@ function TextArg({
<Input
name={arg.name}
onChange={handleChange}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? '' : value}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
required={!arg.optional}
type={arg.password ? 'password' : 'text'}
label={arg.label ?? arg.name}
@@ -173,8 +174,13 @@ function EditorArg({
const id = `input-${arg.name}`;
return (
<div className="w-full grid grid-rows-[auto_minmax(0,1fr)]">
<Label htmlFor={id} optional={arg.optional}>
<div className=" w-full grid grid-cols-1 grid-rows-[auto_minmax(0,1fr)]">
<Label
htmlFor={id}
optional={arg.optional}
visuallyHidden={arg.hideLabel}
otherTags={arg.language ? [capitalize(arg.language)] : undefined}
>
{arg.label}
</Label>
<Editor
@@ -182,15 +188,17 @@ function EditorArg({
className={classNames(
'border border-border rounded-md overflow-hidden px-2 py-1.5',
'focus-within:border-border-focus',
'max-h-[15rem]', // So it doesn't take up too much space
)}
language={arg.language}
onChange={handleChange}
heightMode="auto"
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? '' : value}
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
placeholder={arg.placeholder ?? arg.defaultValue ?? ''}
useTemplating={useTemplating}
stateKey={stateKey}
forceUpdateKey={stateKey}
hideGutter
/>
</div>
);
@@ -210,6 +218,7 @@ function SelectArg({
label={arg.label ?? arg.name}
name={arg.name}
onChange={onChange}
hideLabel={arg.hideLabel}
value={value}
options={[
...arg.options.map((a) => ({

View File

@@ -97,6 +97,7 @@ export function SettingsGeneral() {
</Heading>
<VStack className="mt-1 w-full" space={3}>
<PlainInput
required
size="sm"
name="requestTimeout"
label="Request Timeout (ms)"

View File

@@ -68,7 +68,7 @@ export function SettingsProxy() {
}}
/>
</HStack>
<Separator className="my-6"/>
<Separator className="my-6" />
<Checkbox
checked={settings.proxy.auth != null}
title="Enable authentication"
@@ -83,6 +83,7 @@ export function SettingsProxy() {
{settings.proxy.auth != null && (
<HStack space={1.5}>
<PlainInput
required
size="sm"
label="User"
placeholder="myUser"

View File

@@ -44,6 +44,7 @@ export type InputProps = Pick<
validate?: boolean | ((v: string) => boolean);
required?: boolean;
wrapLines?: boolean;
multiLine?: boolean;
stateKey: EditorProps['stateKey'];
};
@@ -73,6 +74,7 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
validate,
readOnly,
stateKey,
multiLine,
...props
}: InputProps,
ref,
@@ -144,7 +146,8 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
<Label
htmlFor={id.current}
optional={!required}
className={classNames(labelClassName, hideLabel && 'sr-only')}
visuallyHidden={hideLabel}
className={classNames(labelClassName)}
>
{label}
</Label>
@@ -174,9 +177,11 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
<Editor
ref={editorRef}
id={id.current}
singleLine
hideGutter
singleLine={!multiLine}
stateKey={stateKey}
wrapLines={wrapLines}
heightMode="auto"
onKeyDown={handleKeyDown}
type={type === 'password' && !obscured ? 'text' : type}
defaultValue={defaultValue}
@@ -185,7 +190,7 @@ export const Input = forwardRef<EditorView, InputProps>(function Input(
onChange={handleChange}
onPaste={onPaste}
onPasteOverwrite={onPasteOverwrite}
className={editorClassName}
className={classNames(editorClassName, multiLine && 'py-1.5')}
onFocus={handleFocus}
onBlur={handleBlur}
readOnly={readOnly}

View File

@@ -6,21 +6,33 @@ export function Label({
className,
optional,
children,
visuallyHidden,
otherTags = [],
...props
}: HTMLAttributes<HTMLLabelElement> & { htmlFor: string; optional?: boolean }) {
}: HTMLAttributes<HTMLLabelElement> & {
htmlFor: string;
optional?: boolean;
otherTags?: string[];
visuallyHidden?: boolean;
}) {
const tags = optional ? ['optional', ...otherTags] : otherTags;
return (
<label
className={classNames(className, 'text-text-subtle whitespace-nowrap flex items-center gap-1')}
className={classNames(
className,
visuallyHidden && 'sr-only',
'flex-shrink-0',
'text-text-subtle whitespace-nowrap flex items-center gap-1',
)}
htmlFor={htmlFor}
{...props}
>
{children}
{optional ? (
<>
{' '}
<span className="text-xs text-text-subtlest">(optional)</span>
</>
) : null}
{tags.map((tag, i) => (
<span key={i} className="text-xs text-text-subtlest">
({tag})
</span>
))}
</label>
);
}

View File

@@ -98,7 +98,12 @@ export function PlainInput({
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<Label htmlFor={id} className={classNames(labelClassName, 'flex-shrink-0', hideLabel && 'sr-only')}>
<Label
htmlFor={id}
className={labelClassName}
visuallyHidden={hideLabel}
optional={!required}
>
{label}
</Label>
<HStack

View File

@@ -5,6 +5,7 @@ import { useOsInfo } from '../../hooks/useOsInfo';
import { trackEvent } from '../../lib/analytics';
import type { ButtonProps } from './Button';
import { Button } from './Button';
import { Label } from './Label';
import type { RadioDropdownItem } from './RadioDropdown';
import { RadioDropdown } from './RadioDropdown';
import { HStack } from './Stacks';
@@ -61,16 +62,9 @@ export function Select<T extends string>({
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<label
htmlFor={id}
className={classNames(
labelClassName,
'text-text-subtle whitespace-nowrap',
hideLabel && 'sr-only',
)}
>
<Label htmlFor={id} visuallyHidden={hideLabel} className={labelClassName}>
{label}
</label>
</Label>
{osInfo?.osType === 'macos' ? (
<HStack
space={2}