Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix <TextEdit /> bugs #1380

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
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
6 changes: 2 additions & 4 deletions src/frontend/components/property-type/array/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@ type ItemRendererProps = {
}

const ItemRenderer: React.FC<EditProps & ItemRendererProps> = (props) => {
const { ItemComponent, property, onDelete, index, record, isDraggable } = props
const uniqueDraggableId = window.btoa(unescape(encodeURIComponent(`${JSON.stringify(flat.get(record.params, property.path))}-${property.path}`)))
const { ItemComponent, property, onDelete, index, isDraggable } = props

return (
<Draggable
draggableId={uniqueDraggableId}
draggableId={property.path}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this fix the issue? property.path is still not unique as it changes when you drag an element between indices.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a fair point will have to dive into that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There doesn't seem to be a convenient value to use as a unique key.

Copy link
Contributor

@dziraf dziraf Jan 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One solution I thought of would be to create a "virtual" property draggableId for all existing array elements when the HOC component first loads, then assign it also when you add new elements. We could use some kind of library like nanoid to create a unique identifier. There could be an issue where AdminJS also sends this property in request payload and an adapter tries to save it. AFAIK some ORMs skip attributes that are not defined in models when generating db queries but other ones could throw errors. A solution to this could be that we treat all properties prefixed with double underscore (__typename, __draggableId, etc) as virtual/readonly and remove them when form is submitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you want that solution as part of this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, yes. If you have doubts though and property.path change works exactly the same as uniqueDraggableId (as it was before) then it's fine to do it another time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer handling it in a separate PR, the current implementation has some quirks like focus going to the wrong field when dragging elements. But that is an existing issue.

index={index}
key={uniqueDraggableId}
isDragDisabled={!isDraggable}
>
{(provided): JSX.Element => (
Expand Down

This file was deleted.

15 changes: 8 additions & 7 deletions src/frontend/components/property-type/currency/edit.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { CurrencyInputProps, FormGroup, FormMessage } from '@adminjs/design-system'
import { CurrencyInput, FormGroup, FormMessage } from '@adminjs/design-system'
import React, { FC, memo } from 'react'
import { EditPropertyProps } from '../base-property-props'
import { recordPropertyIsEqual } from '../record-property-is-equal'
import { PropertyLabel } from '../utils/property-label'
import allowOverride from '../../../hoc/allow-override'
import { CurrencyInputWrapper } from './currency-input-wrapper'

const Edit: FC<EditPropertyProps> = (props) => {
const { onChange, property, record } = props
const propValue = record.params?.[property.path] ?? ''
const propValue = record.params[property.path]
const error = record.errors?.[property.path]

return (
<FormGroup error={Boolean(error)}>
<PropertyLabel property={property} />
<CurrencyInputWrapper
<CurrencyInput
id={property.path}
initial={propValue}
options={property.props as CurrencyInputProps}
onChange={(value) => onChange(property.path, value)}
name={property.path}
value={propValue ?? ''}
placeholder="<null>"
onValueChange={(value) => onChange(property.path, value)}
{...property.props}
/>
<FormMessage>{error && error.message}</FormMessage>
</FormGroup>
Expand Down
21 changes: 7 additions & 14 deletions src/frontend/components/property-type/default-type/edit.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import React, { FC, useState, memo, useEffect } from 'react'
import React, { FC, memo } from 'react'
import { Input, FormMessage, FormGroup, Select } from '@adminjs/design-system'

import { EditPropertyProps } from '../base-property-props'
Expand Down Expand Up @@ -43,26 +43,19 @@ const SelectEdit: FC<CombinedProps> = (props) => {

const TextEdit: FC<CombinedProps> = (props) => {
const { property, record, onChange } = props
const propValue = record.params?.[property.path] ?? ''
const [value, setValue] = useState(propValue)

useEffect(() => {
if (value !== propValue) {
setValue(propValue)
}
}, [propValue])
const propValue = record.params[property.path]

return (
<Input
id={property.path}
name={property.path}
required={property.isRequired}
onChange={(e) => setValue(e.target.value)}
onBlur={() => onChange(property.path, value)}
// handle clicking ENTER
onKeyDown={(e) => e.keyCode === 13 && onChange(property.path, value)}
value={value}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
onChange(property.path, e.target.value)
}}
value={propValue ?? ''}
disabled={property.isDisabled}
placeholder={propValue === null ? '<null>' : undefined}
{...property.props}
/>
)
Expand Down