Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into refactor/replace-…
Browse files Browse the repository at this point in the history
…markdown
  • Loading branch information
1emu committed Jun 29, 2023
2 parents 655c5f0 + 4277dec commit fd9321a
Show file tree
Hide file tree
Showing 49 changed files with 1,324 additions and 1,382 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"autoprefixer": "^10.4.4",
"chart.js": "^3.8.2",
"classnames": "^2.3.2",
"clipboard-copy": "^4.0.1",
"core-js": "^3.21.1",
"decentraland-gatsby": "^5.67.2",
"decentraland-ui": "^3.102.0",
Expand Down
33 changes: 33 additions & 0 deletions src/components/Common/Form/TextArea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react'
import { Control, Controller, FieldValues, Path, PathValue } from 'react-hook-form'

import {
TextAreaField as DCLTextArea,
TextAreaFieldProps,
} from 'decentraland-ui/dist/components/TextAreaField/TextAreaField'

interface Props<T extends FieldValues> extends TextAreaFieldProps {
control: Control<T>
name: Path<T>
defaultValue?: PathValue<T, Path<T>> | undefined
rules?: any
}

export default function TextArea<T extends FieldValues>({
control,
name,
defaultValue,
rules,
...fieldProps
}: Props<T>) {
return (
<Controller
control={control}
name={name}
defaultValue={defaultValue}
rules={rules}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
render={({ field: { ref, ...field } }) => <DCLTextArea {...field} {...fieldProps} />}
/>
)
}
19 changes: 0 additions & 19 deletions src/components/Common/Link.css

This file was deleted.

41 changes: 0 additions & 41 deletions src/components/Common/Link.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/Common/Typography/Link.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.Link {
color: var(--primary);
color: var(--dcl-primary);
}

.Link--pointer {
Expand Down
4 changes: 4 additions & 0 deletions src/components/Common/Typography/Text.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
color: var(--secondary-text);
}

.Text.Text--color-error {
color: var(--red-800);
}

.Text.Text--style-normal {
font-style: normal;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Common/Typography/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const DEFAULT_FONT_SIZE: FontSize = 'md'
const DEFAULT_FONT_STYLE: FontStyle = 'normal'
export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
export type FontWeight = 'bold' | 'semi-bold' | 'normal'
type TextColor = 'default' | 'primary' | 'secondary'
type TextColor = 'default' | 'primary' | 'secondary' | 'error'
type FontStyle = 'normal' | 'italic'

interface Props {
Expand Down
111 changes: 49 additions & 62 deletions src/components/Debug/HttpStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react'
import React, { useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'

import useEditor, { assert, createValidator } from 'decentraland-gatsby/dist/hooks/useEditor'
import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Field } from 'decentraland-ui/dist/components/Field/Field'

import { HttpStat } from '../../clients/HttpStat'
import useFormatMessage from '../../hooks/useFormatMessage'
import Field from '../Common/Form/Field'
import Label from '../Common/Typography/Label'
import ErrorMessage from '../Error/ErrorMessage'
import { ContentSection } from '../Layout/ContentLayout'
Expand All @@ -20,96 +20,83 @@ const initialState: TestState = {
sleepTime: 0,
}

const edit = (state: TestState, props: Partial<TestState>) => {
return {
...state,
...props,
}
}

const MAX_SLEEP_TIME = 300000 // 5 minutes

const validate = createValidator<TestState>({
httpStatus: (state) => ({
httpStatus: assert(state.httpStatus.length === 3, 'error.debug.invalid_http_status'),
}),
sleepTime: (state) => ({
sleepTime: assert(state.sleepTime >= 0 && state.sleepTime <= MAX_SLEEP_TIME, 'error.debug.invalid_sleep_time'),
}),
'*': (state) => ({
httpStatus: assert(state.httpStatus.length === 3, 'error.debug.invalid_http_status'),
sleepTime: assert(state.sleepTime >= 0 && state.sleepTime <= MAX_SLEEP_TIME, 'error.debug.invalid_sleep_time'),
}),
})

interface Props {
className?: string
}

export default function HttpStatus({ className }: Props) {
const t = useFormatMessage()
const [state, editor] = useEditor(edit, validate, initialState)
const [formDisabled, setFormDisabled] = useState(false)
const {
handleSubmit,
formState: { isSubmitting, errors },
control,
} = useForm<TestState>({ defaultValues: initialState, mode: 'onTouched' })
const [error, setError] = useState('')

useEffect(() => {
if (state.validated) {
setFormDisabled(true)
Promise.resolve()
.then(async () => {
return HttpStat.get().fetchResponse(state.value.httpStatus, state.value.sleepTime)
})
.then((result) => {
console.log('result', result)
editor.error({ '*': '' })
setFormDisabled(false)
})
.catch((err) => {
console.error(err, { ...err })
editor.error({ '*': err.body?.error || err.message })
setFormDisabled(false)
})
const onSubmit: SubmitHandler<TestState> = async (data) => {
try {
const result = await HttpStat.get().fetchResponse(data.httpStatus, data.sleepTime)
console.log('result', result)
setFormDisabled(false)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
console.error(err, { ...err })
setError(err.body?.error || err.message)
setFormDisabled(false)
}
}, [editor, state.validated, state.value])
}

return (
<div className={className}>
<form className={className} onSubmit={handleSubmit(onSubmit)}>
<ContentSection>
<Label>{'Http Status'}</Label>
<Field
value={state.value.httpStatus}
onChange={(_, { value }) => editor.set({ httpStatus: value })}
onBlur={() => editor.set({ httpStatus: state.value.httpStatus.trim() })}
error={!!state.error.httpStatus}
name="httpStatus"
control={control}
error={!!errors.httpStatus}
message={errors.httpStatus?.message}
disabled={formDisabled}
message={t(state.error.httpStatus)}
rules={{
required: { value: true, message: t('error.draft.title_empty') },
validate: (value: string) => {
if (value.length !== 3) {
return t('error.debug.invalid_http_status')
}
},
}}
/>
</ContentSection>
<ContentSection>
<Label>{'Sleep'}</Label>
<Field
value={state.value.sleepTime}
onChange={(_, { value }) => editor.set({ sleepTime: value ? Number(value) : undefined })}
onBlur={() => editor.set({ sleepTime: state.value.sleepTime })}
error={!!state.error.sleepTime}
message={t(state.error.sleepTime)}
name="sleepTime"
control={control}
error={!!errors.sleepTime}
message={errors.sleepTime?.message}
disabled={formDisabled}
rules={{
required: { value: true, message: t('error.draft.title_empty') },
validate: (value: string) => {
if (Number(value) >= 0 && Number(value) <= MAX_SLEEP_TIME) {
return t('error.debug.invalid_sleep_time')
}
},
}}
/>
</ContentSection>
<ContentSection className="DebugPage__Submit">
<Button
primary
disabled={state.validated || formDisabled}
loading={state.validated || formDisabled}
onClick={() => editor.validate()}
>
<Button type="submit" primary disabled={formDisabled} loading={isSubmitting}>
{t('page.submit.button_submit')}
</Button>
</ContentSection>
{state.error['*'] && (
{error && (
<ContentSection>
<ErrorMessage label={t('page.debug.error_label')} errorMessage={t(state.error['*']) || state.error['*']} />
<ErrorMessage label={t('page.debug.error_label')} errorMessage={t(error) || error} />
</ContentSection>
)}
</div>
</form>
)
}
19 changes: 10 additions & 9 deletions src/components/Error/ErrorMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useCallback, useState } from 'react'
import React, { useState } from 'react'

import classNames from 'classnames'
import useClipboardCopy from 'decentraland-gatsby/dist/hooks/useClipboardCopy'
import { Button } from 'decentraland-ui/dist/components/Button/Button'

import useClipboardCopy from '../../hooks/useClipboardCopy'
import useFormatMessage from '../../hooks/useFormatMessage'
import Time from '../../utils/date/Time'
import Link from '../Common/Typography/Link'
Expand All @@ -19,17 +19,13 @@ interface Props {

export default function ErrorMessage({ label, errorMessage }: Props) {
const t = useFormatMessage()
const [copied, state] = useClipboardCopy(Time.Second)
const { copiedValue, handleCopy } = useClipboardCopy(Time.Second)
const [open, setOpen] = useState(false)

const toggleHandler = () => {
setOpen(!open)
}

const handleCopy = useCallback(() => {
state.copy(errorMessage)
}, [errorMessage, state])

return (
<div className="ErrorMessage__Container">
<div className="ErrorMessage__Header">
Expand All @@ -42,8 +38,13 @@ export default function ErrorMessage({ label, errorMessage }: Props) {
<div className={classNames('ErrorMessage__Content', open && 'ErrorMessage__Content--open')}>
<div className="ErrorMessage__Message">
<pre>{errorMessage}</pre>
<Button className={classNames('Button', 'ErrorMessage__Copy')} primary size="small" onClick={handleCopy}>
<span>{copied ? t('error.message.copied') : t('error.message.copy')}</span>
<Button
className={classNames('Button', 'ErrorMessage__Copy')}
primary
size="small"
onClick={() => handleCopy(errorMessage)}
>
<span>{copiedValue ? t('error.message.copied') : t('error.message.copy')}</span>
</Button>
</div>
<Markdown
Expand Down
Loading

0 comments on commit fd9321a

Please sign in to comment.