diff --git a/webapp/src/components/cardDetail.scss b/webapp/src/components/cardDetail.scss index a2f8adbd3..9ce00e0f6 100644 --- a/webapp/src/components/cardDetail.scss +++ b/webapp/src/components/cardDetail.scss @@ -26,6 +26,7 @@ .octo-propertylist { display: flex; flex-direction: column; + width: 100%; } .octo-propertyrow { diff --git a/webapp/src/components/propertyValueElement.tsx b/webapp/src/components/propertyValueElement.tsx index 0d5f457b7..0fa60151c 100644 --- a/webapp/src/components/propertyValueElement.tsx +++ b/webapp/src/components/propertyValueElement.tsx @@ -40,7 +40,7 @@ export default class PropertyValueElement extends React.Component } render(): JSX.Element { - const {card, propertyTemplate, readOnly, emptyDisplayValue} = this.props + const {card, propertyTemplate, readOnly, emptyDisplayValue, boardTree} = this.props const propertyValue = card.properties[propertyTemplate.id] const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, propertyTemplate) const finalDisplayValue = displayValue || emptyDisplayValue @@ -76,6 +76,12 @@ export default class PropertyValueElement extends React.Component onChange={(value) => { mutator.changePropertyValue(card, propertyTemplate.id, value) }} + onChangeColor={(option: IPropertyOption, colorId: string): void => { + mutator.changePropertyOptionColor(boardTree.board, propertyTemplate, option, colorId) + }} + onDeleteOption={(option: IPropertyOption): void => { + mutator.deletePropertyOption(boardTree, propertyTemplate, option) + }} onCreate={ async (value) => { const option: IPropertyOption = { diff --git a/webapp/src/widgets/valueSelector.scss b/webapp/src/widgets/valueSelector.scss index cca77e349..890df1eea 100644 --- a/webapp/src/widgets/valueSelector.scss +++ b/webapp/src/widgets/valueSelector.scss @@ -5,4 +5,16 @@ &:hover { background-color: rgba(var(--main-fg), 0.1), } + + .value-menu-option { + display: flex; + width: 100%; + .octo-label-container { + flex-grow: 1; + } + .MenuWrapper { + display: flex; + align-self: flex-end; + } + } } diff --git a/webapp/src/widgets/valueSelector.tsx b/webapp/src/widgets/valueSelector.tsx index 0327f0696..640ac8601 100644 --- a/webapp/src/widgets/valueSelector.tsx +++ b/webapp/src/widgets/valueSelector.tsx @@ -1,10 +1,18 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {CSSProperties} from 'react' -import {ActionMeta, ValueType} from 'react-select' -import CreatableSelect from 'react-select/creatable'; -import boardCard from 'src/components/boardCard'; +import {injectIntl, IntlShape} from 'react-intl' +import {ActionMeta, ValueType, FormatOptionLabelMeta} from 'react-select' +import CreatableSelect from 'react-select/creatable' + import {IPropertyOption} from '../blocks/board' +import {Constants} from '../constants' + +import Menu from './menu' +import MenuWrapper from './menuWrapper' +import Button from './buttons/button' +import OptionsIcon from './icons/options' +import DeleteIcon from './icons/delete' import './valueSelector.scss' @@ -13,13 +21,49 @@ type Props = { value: IPropertyOption; onCreate?: (value: string) => void onChange?: (value: string) => void + onChangeColor?: (option: IPropertyOption, color: string) => void + onDeleteOption?: (option: IPropertyOption) => void + intl: IntlShape } -export default class ValueSelector extends React.Component { +class ValueSelector extends React.Component { public shouldComponentUpdate(): boolean { return true } + renderLabel = (option: IPropertyOption, meta: FormatOptionLabelMeta): React.ReactNode => { + if (meta.context === 'value') { + return {option.value} + } + return ( +
+
+
{option.value}
+
+ + + + } + name={this.props.intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})} + onClick={() => this.props.onDeleteOption(option)} + /> + + {Constants.menuColors.map((color) => ( + this.props.onChangeColor(option, color.id)} + /> + ))} + + +
+ ) + } + public render(): JSX.Element { return ( { }), option: (provided: CSSProperties, state: {isFocused: boolean}): CSSProperties => ({ ...provided, - background: state.isFocused ? 'rgb(var(--button-bg))' : 'rgb(var(--main-bg))', - color: state.isFocused ? 'rgb(var(--button-fg))' : 'rgb(var(--main-fg))', + background: state.isFocused ? 'rgba(var(--main-fg), 0.1)' : 'rgb(var(--main-bg))', + color: state.isFocused ? 'rgb(var(--main-fg))' : 'rgb(var(--main-fg))', padding: '2px 8px', }), control: (): CSSProperties => ({ @@ -56,9 +100,13 @@ export default class ValueSelector extends React.Component { marginBottom: 0, marginTop: 0, }), + menuList: (provided: CSSProperties): CSSProperties => ({ + ...provided, + overflowY: 'unset', + }), }} + formatOptionLabel={this.renderLabel} className='ValueSelector' - hideSelectedOptions={true} options={this.props.options} getOptionLabel={(o: IPropertyOption) => o.value} getOptionValue={(o: IPropertyOption) => o.id} @@ -75,3 +123,5 @@ export default class ValueSelector extends React.Component { ) } } + +export default injectIntl(ValueSelector)