1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-01-08 15:06:08 +02:00

Merge branch 'kamre-gh-1059-fix-empty-placeholder-in-card-dialog'

This commit is contained in:
Chen-I Lim 2021-09-24 16:51:18 -07:00
commit cc5c712bd0
18 changed files with 71 additions and 43 deletions

View File

@ -3,16 +3,14 @@
exports[`components/propertyValueElement should match snapshot, date, array value 1`] = ` exports[`components/propertyValueElement should match snapshot, date, array value 1`] = `
<div> <div>
<div <div
class="DateRange " class="DateRange empty"
> >
<button <button
class="Button " class="Button "
type="button" type="button"
> >
<span> <span>
<span Empty
title="Empty"
/>
</span> </span>
</button> </button>
</div> </div>
@ -44,7 +42,7 @@ exports[`components/propertyValueElement should match snapshot, person, array va
<div> <div>
<input <input
class="Editable octo-propertyvalue" class="Editable octo-propertyvalue"
placeholder="" placeholder="Empty"
spellcheck="true" spellcheck="true"
title="" title=""
value="" value=""
@ -99,7 +97,7 @@ exports[`components/propertyValueElement should match snapshot, url, array value
> >
<input <input
class="Editable octo-propertyvalue" class="Editable octo-propertyvalue"
placeholder="" placeholder="Empty"
title="http://localhost" title="http://localhost"
value="http://localhost" value="http://localhost"
/> />
@ -124,7 +122,7 @@ exports[`components/propertyValueElement should match snapshot, url, array value
> >
<input <input
class="Editable octo-propertyvalue" class="Editable octo-propertyvalue"
placeholder="" placeholder="Empty"
title="http://localhost" title="http://localhost"
value="http://localhost" value="http://localhost"
/> />

View File

@ -58,7 +58,7 @@ const CardDetailProperties = React.memo((props: Props) => {
contents={contents} contents={contents}
comments={comments} comments={comments}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue='Empty' showEmptyPlaceholder={true}
/> />
</div> </div>
) )

View File

@ -167,7 +167,7 @@ const GalleryCard = React.memo((props: Props) => {
readOnly={true} readOnly={true}
card={card} card={card}
propertyTemplate={template} propertyTemplate={template}
emptyDisplayValue='' showEmptyPlaceholder={false}
/> />
</Tooltip> </Tooltip>
))} ))}

View File

@ -123,7 +123,7 @@ const KanbanCard = React.memo((props: Props) => {
contents={contents} contents={contents}
comments={comments} comments={comments}
propertyTemplate={template} propertyTemplate={template}
emptyDisplayValue='' showEmptyPlaceholder={false}
/> />
</Tooltip> </Tooltip>
))} ))}

View File

@ -37,17 +37,13 @@ exports[`components/properties/dateRange handle clear 1`] = `
exports[`components/properties/dateRange returns default correctly 1`] = ` exports[`components/properties/dateRange returns default correctly 1`] = `
<div> <div>
<div <div
class="DateRange " class="DateRange empty"
> >
<button <button
class="Button " class="Button "
type="button" type="button"
> >
<span> <span />
<span
title="Empty"
/>
</span>
</button> </button>
</div> </div>
</div> </div>

View File

@ -1,10 +1,6 @@
.DateRange { .DateRange {
width: 100%; width: 100%;
.octo-propertyvalue {
white-space: none;
}
.inputContainer { .inputContainer {
display: flex; display: flex;
@ -43,6 +39,11 @@
margin-bottom: 100px; margin-bottom: 100px;
} }
&.empty .Button {
color: rgba(var(--center-channel-color-rgb), 0.4);
padding: 0 3px;
}
.Button { .Button {
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -60,6 +60,7 @@ describe('components/properties/dateRange', () => {
<DateRange <DateRange
className='octo-propertyvalue' className='octo-propertyvalue'
value={''} value={''}
showEmptyPlaceholder={true}
onChange={callback} onChange={callback}
/>, />,
) )
@ -68,7 +69,7 @@ describe('components/properties/dateRange', () => {
const fifteenth = Date.UTC(date.getFullYear(), date.getMonth(), 15, 12) const fifteenth = Date.UTC(date.getFullYear(), date.getMonth(), 15, 12)
const {getByText, getByTitle} = render(component) const {getByText, getByTitle} = render(component)
const dayDisplay = getByTitle('Empty') const dayDisplay = getByText('Empty')
userEvent.click(dayDisplay) userEvent.click(dayDisplay)
const day = getByText('15') const day = getByText('15')
@ -86,13 +87,14 @@ describe('components/properties/dateRange', () => {
<DateRange <DateRange
className='octo-propertyvalue' className='octo-propertyvalue'
value={''} value={''}
showEmptyPlaceholder={true}
onChange={callback} onChange={callback}
/>, />,
) )
// open modal // open modal
const {getByText, getByTitle} = render(component) const {getByText, getByTitle} = render(component)
const dayDisplay = getByTitle('Empty') const dayDisplay = getByText('Empty')
userEvent.click(dayDisplay) userEvent.click(dayDisplay)
// select start date // select start date
@ -249,6 +251,7 @@ describe('components/properties/dateRange', () => {
<DateRange <DateRange
className='octo-propertyvalue' className='octo-propertyvalue'
value={''} value={''}
showEmptyPlaceholder={true}
onChange={callback} onChange={callback}
/>, />,
) )
@ -261,7 +264,7 @@ describe('components/properties/dateRange', () => {
const today = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) const today = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())
const {getByText, getByTitle} = render(component) const {getByText, getByTitle} = render(component)
const dayDisplay = getByTitle('Empty') const dayDisplay = getByText('Empty')
userEvent.click(dayDisplay) userEvent.click(dayDisplay)
const day = getByText('Today') const day = getByText('Today')

View File

@ -22,6 +22,7 @@ import {Utils} from '../../../utils'
type Props = { type Props = {
className: string className: string
value: string value: string
showEmptyPlaceholder?: boolean
onChange: (value: string) => void onChange: (value: string) => void
} }
@ -35,7 +36,7 @@ type DateProperty = {
const loadedLocales: Record<string, any> = {} const loadedLocales: Record<string, any> = {}
function DateRange(props: Props): JSX.Element { function DateRange(props: Props): JSX.Element {
const {className, value, onChange} = props const {className, value, showEmptyPlaceholder, onChange} = props
const intl = useIntl() const intl = useIntl()
const timeZoneOffset = new Date().getTimezoneOffset() * 60 * 1000 const timeZoneOffset = new Date().getTimezoneOffset() * 60 * 1000
@ -151,12 +152,17 @@ function DateRange(props: Props): JSX.Element {
setShowDialog(false) setShowDialog(false)
} }
let buttonText = displayValue
if (!buttonText && showEmptyPlaceholder) {
buttonText = intl.formatMessage({id: 'DateRange.empty', defaultMessage: 'Empty'})
}
return ( return (
<div className={'DateRange '}> <div className={`DateRange ${displayValue ? '' : 'empty'}`}>
<Button <Button
onClick={() => setShowDialog(true)} onClick={() => setShowDialog(true)}
> >
{displayValue || <span title={intl.formatMessage({id: 'DateRange.empty', defaultMessage: 'Empty'})}/>} {buttonText}
</Button> </Button>
{showDialog && {showDialog &&

View File

@ -7,7 +7,6 @@ exports[`components/properties/link returns link properties correctly 1`] = `
> >
<input <input
class="Editable octo-propertyvalue" class="Editable octo-propertyvalue"
placeholder=""
title="https://github.com/mattermost/focalboard" title="https://github.com/mattermost/focalboard"
value="https://github.com/mattermost/focalboard" value="https://github.com/mattermost/focalboard"
/> />

View File

@ -12,6 +12,7 @@ import LinkIcon from '../../../widgets/icons/Link'
type Props = { type Props = {
value: string value: string
readonly?: boolean readonly?: boolean
placeholder?: string
onChange: (value: string) => void onChange: (value: string) => void
onSave: () => void onSave: () => void
onCancel: () => void onCancel: () => void
@ -38,7 +39,7 @@ const URLProperty = (props: Props): JSX.Element => {
<div className='URLProperty property-link url'> <div className='URLProperty property-link url'>
<Editable <Editable
className='octo-propertyvalue' className='octo-propertyvalue'
placeholderText='' placeholderText={props.placeholder}
value={props.value} value={props.value}
readonly={props.readonly} readonly={props.readonly}
onChange={props.onChange} onChange={props.onChange}

View File

@ -46,7 +46,7 @@ const MultiSelectProperty = (props: Props): JSX.Element => {
{values.length === 0 && ( {values.length === 0 && (
<Label <Label
color='empty' color='empty'
>{''}</Label> >{emptyValue}</Label>
)} )}
</div> </div>
) )

View File

@ -111,9 +111,9 @@ exports[`components/properties/user not readonly not existing user 1`] = `
class=" css-kpfmlq-ValueContainer" class=" css-kpfmlq-ValueContainer"
> >
<div <div
class=" css-1wa3eu0-placeholder" class=" css-1oswhd8-placeholder"
> >
Select... Empty
</div> </div>
<div <div
class="css-1shkodo-Input" class="css-1shkodo-Input"

View File

@ -3,6 +3,7 @@
import React from 'react' import React from 'react'
import Select from 'react-select' import Select from 'react-select'
import {CSSObject} from '@emotion/serialize'
import {IUser} from '../../../user' import {IUser} from '../../../user'
import {getWorkspaceUsersList, getWorkspaceUsers} from '../../../store/users' import {getWorkspaceUsersList, getWorkspaceUsers} from '../../../store/users'
@ -17,6 +18,14 @@ type Props = {
onChange: (value: string) => void, onChange: (value: string) => void,
} }
const selectStyles = {
...getSelectBaseStyle(),
placeholder: (provided: CSSObject): CSSObject => ({
...provided,
color: 'rgba(var(--center-channel-color-rgb), 0.4)',
}),
}
const UserProperty = (props: Props): JSX.Element => { const UserProperty = (props: Props): JSX.Element => {
const workspaceUsers = useAppSelector<IUser[]>(getWorkspaceUsersList) const workspaceUsers = useAppSelector<IUser[]>(getWorkspaceUsersList)
const workspaceUsersById = useAppSelector<{[key:string]: IUser}>(getWorkspaceUsers) const workspaceUsersById = useAppSelector<{[key:string]: IUser}>(getWorkspaceUsers)
@ -32,7 +41,8 @@ const UserProperty = (props: Props): JSX.Element => {
isClearable={true} isClearable={true}
backspaceRemovesValue={true} backspaceRemovesValue={true}
className={'UserProperty'} className={'UserProperty'}
styles={getSelectBaseStyle()} styles={selectStyles}
placeholder={'Empty'}
getOptionLabel={(o: IUser) => o.username} getOptionLabel={(o: IUser) => o.username}
getOptionValue={(a: IUser) => a.id} getOptionValue={(a: IUser) => a.id}
value={workspaceUsersById[props.value] || null} value={workspaceUsersById[props.value] || null}

View File

@ -39,7 +39,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate || board.fields.cardProperties[0]} propertyTemplate={propertyTemplate || board.fields.cardProperties[0]}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -57,7 +57,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate || board.fields.cardProperties[0]} propertyTemplate={propertyTemplate || board.fields.cardProperties[0]}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -91,7 +91,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -116,7 +116,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -141,7 +141,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -166,7 +166,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
@ -191,7 +191,7 @@ describe('components/propertyValueElement', () => {
contents={[]} contents={[]}
comments={[comments]} comments={[comments]}
propertyTemplate={propertyTemplate} propertyTemplate={propertyTemplate}
emptyDisplayValue={'empty'} showEmptyPlaceholder={true}
/>, />,
) )
const {container} = render(component) const {container} = render(component)

View File

@ -31,17 +31,18 @@ type Props = {
contents: Array<ContentBlock|ContentBlock[]> contents: Array<ContentBlock|ContentBlock[]>
comments: CommentBlock[] comments: CommentBlock[]
propertyTemplate: IPropertyTemplate propertyTemplate: IPropertyTemplate
emptyDisplayValue: string showEmptyPlaceholder: boolean
} }
const PropertyValueElement = (props:Props): JSX.Element => { const PropertyValueElement = (props:Props): JSX.Element => {
const [value, setValue] = useState(props.card.fields.properties[props.propertyTemplate.id] || '') const [value, setValue] = useState(props.card.fields.properties[props.propertyTemplate.id] || '')
const [serverValue, setServerValue] = useState(props.card.fields.properties[props.propertyTemplate.id] || '') const [serverValue, setServerValue] = useState(props.card.fields.properties[props.propertyTemplate.id] || '')
const {card, propertyTemplate, readOnly, emptyDisplayValue, board, contents, comments} = props const {card, propertyTemplate, readOnly, showEmptyPlaceholder, board, contents, comments} = props
const intl = useIntl() const intl = useIntl()
const propertyValue = card.fields.properties[propertyTemplate.id] const propertyValue = card.fields.properties[propertyTemplate.id]
const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, propertyTemplate, intl) const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, propertyTemplate, intl)
const emptyDisplayValue = showEmptyPlaceholder ? intl.formatMessage({id: 'PropertyValueElement.empty', defaultMessage: 'Empty'}) : ''
const finalDisplayValue = displayValue || emptyDisplayValue const finalDisplayValue = displayValue || emptyDisplayValue
const editableFields: Array<PropertyType> = ['text', 'number', 'email', 'url', 'phone'] const editableFields: Array<PropertyType> = ['text', 'number', 'email', 'url', 'phone']
@ -169,6 +170,7 @@ const PropertyValueElement = (props:Props): JSX.Element => {
<DateRange <DateRange
className='octo-propertyvalue' className='octo-propertyvalue'
value={value.toString()} value={value.toString()}
showEmptyPlaceholder={showEmptyPlaceholder}
onChange={(newValue) => mutator.changePropertyValue(card, propertyTemplate.id, newValue)} onChange={(newValue) => mutator.changePropertyValue(card, propertyTemplate.id, newValue)}
/> />
) )
@ -177,6 +179,7 @@ const PropertyValueElement = (props:Props): JSX.Element => {
<URLProperty <URLProperty
value={value.toString()} value={value.toString()}
readonly={readOnly} readonly={readOnly}
placeholder={emptyDisplayValue}
onChange={setValue} onChange={setValue}
onSave={saveTextProperty} onSave={saveTextProperty}
onCancel={() => setValue(propertyValue)} onCancel={() => setValue(propertyValue)}
@ -228,7 +231,7 @@ const PropertyValueElement = (props:Props): JSX.Element => {
return ( return (
<Editable <Editable
className='octo-propertyvalue' className='octo-propertyvalue'
placeholderText='' placeholderText={emptyDisplayValue}
value={value.toString()} value={value.toString()}
onChange={setValue} onChange={setValue}
onSave={saveTextProperty} onSave={saveTextProperty}

View File

@ -140,7 +140,7 @@ const TableRow = React.memo((props: Props) => {
contents={contents} contents={contents}
comments={comments} comments={comments}
propertyTemplate={template} propertyTemplate={template}
emptyDisplayValue='' showEmptyPlaceholder={false}
/> />
</div>) </div>)
})} })}

View File

@ -12,6 +12,13 @@
font-weight: 600; font-weight: 600;
font-size: 13px; font-size: 13px;
&.empty {
color: rgba(var(--center-channel-color-rgb), 0.4);
padding: 3px;
text-transform: none;
font-weight: normal;
}
input { input {
line-height: 20px; line-height: 20px;
color: rgba(var(--center-channel-color-rgb), 0.8); color: rgba(var(--center-channel-color-rgb), 0.8);

View File

@ -125,6 +125,10 @@ const valueSelectorStyle = {
top: 'unset', top: 'unset',
transform: 'unset', transform: 'unset',
}), }),
placeholder: (provided: CSSObject): CSSObject => ({
...provided,
color: 'rgba(var(--center-channel-color-rgb), 0.4)',
}),
multiValue: (provided: CSSObject): CSSObject => ({ multiValue: (provided: CSSObject): CSSObject => ({
...provided, ...provided,
margin: 0, margin: 0,