import {Fragment, useState} from 'react'; import styled from '@emotion/styled'; import {ModalRenderProps} from 'sentry/actionCreators/modal'; import ActionButton from 'sentry/components/actions/button'; import Button from 'sentry/components/button'; import Field from 'sentry/components/forms/field'; import SelectField from 'sentry/components/forms/selectField'; import Input from 'sentry/components/input'; import { DEBUG_SOURCE_CASINGS, DEBUG_SOURCE_LAYOUTS, DEBUG_SOURCE_TYPES, } from 'sentry/data/debugFileSources'; import {IconClose} from 'sentry/icons/iconClose'; import {t, tct} from 'sentry/locale'; import {INPUT_PADDING} from 'sentry/styles/input'; import space from 'sentry/styles/space'; import {uniqueId} from 'sentry/utils/guid'; const CLEAR_PASSWORD_BUTTON_SIZE = 22; const PASSWORD_INPUT_PADDING_RIGHT = INPUT_PADDING + CLEAR_PASSWORD_BUTTON_SIZE; type InitialData = { id: string; layout: { casing: keyof typeof DEBUG_SOURCE_CASINGS; type: keyof typeof DEBUG_SOURCE_LAYOUTS; }; name: string; url: string; password?: { 'hidden-secret': boolean; }; username?: string; }; type Data = Partial> & Omit & { 'layout.casing': keyof typeof DEBUG_SOURCE_CASINGS; 'layout.type': keyof typeof DEBUG_SOURCE_LAYOUTS; password?: string; }; type SubmitData = Omit & Pick & { password?: | { 'hidden-secret': boolean; } | string; }; type Props = Pick & { onSubmit: (data: SubmitData) => void; initialData?: InitialData; }; function Http({Header, Body, Footer, onSubmit, ...props}: Props) { const initialData: Data = { id: props.initialData?.id ?? uniqueId(), name: props.initialData?.name, url: props.initialData?.url, username: props.initialData?.username, password: typeof props.initialData?.password === 'object' ? undefined : '', 'layout.type': props.initialData?.layout.type ?? 'native', 'layout.casing': props.initialData?.layout.casing ?? 'default', }; const [data, setData] = useState(initialData); function isFormInvalid() { return !data.name || !data.url; } function formUnchanged() { return data === initialData; } function handleSubmit() { const validData = data as SubmitData; onSubmit({ id: validData.id, name: validData.name, url: validData.url, 'layout.type': validData['layout.type'], 'layout.casing': validData['layout.casing'], username: validData.username, password: validData.password === undefined ? {'hidden-secret': true} : !validData.password ? undefined : validData.password, }); } function handleClearPassword() { setData({...data, password: ''}); } return (
{initialData ? tct('Update [name] Repository', {name: DEBUG_SOURCE_TYPES.http}) : tct('Add [name] Repository', {name: DEBUG_SOURCE_TYPES.http})}
setData({ ...data, name: e.target.value, }) } />
setData({ ...data, url: e.target.value, }) } /> setData({ ...data, username: e.target.value, }) } /> setData({ ...data, password: e.target.value, }) } /> {(data.password === undefined || (typeof data.password === 'string' && !!data.password)) && ( } size="xs" title={t('Clear password')} aria-label={t('Clear password')} borderless /> )}
({ value: key, label: DEBUG_SOURCE_LAYOUTS[key], }))} value={data['layout.type']} onChange={value => setData({ ...data, ['layout.type']: value, }) } inline={false} flexibleControlStateSize stacked /> ({ value: key, label: DEBUG_SOURCE_CASINGS[key], }))} value={data['layout.casing']} onChange={value => setData({ ...data, ['layout.casing']: value, }) } inline={false} flexibleControlStateSize stacked />
); } export default Http; const StyledSelectField = styled(SelectField)` padding-right: 0; `; const PasswordInput = styled(Input)` padding-right: ${PASSWORD_INPUT_PADDING_RIGHT}px; `; const ClearPasswordButton = styled(ActionButton)` background: transparent; height: ${CLEAR_PASSWORD_BUTTON_SIZE}px; width: ${CLEAR_PASSWORD_BUTTON_SIZE}px; padding: 0; position: absolute; top: 50%; right: ${space(0.75)}; transform: translateY(-50%); svg { color: ${p => p.theme.gray400}; :hover { color: hsl(0, 0%, 60%); } } `;