Progress
This commit is contained in:
@@ -1,28 +1,29 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import classNames from 'classnames/bind'
|
||||
import { length } from 'stringz'
|
||||
import CharacterCounter from '../../../../components/character_counter'
|
||||
import UploadForm from '../upload_form'
|
||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox'
|
||||
import PollButton from '../../components/poll_button'
|
||||
import UploadButton from '../media_upload_button'
|
||||
import SpoilerButton from '../../components/spoiler_button'
|
||||
import RichTextEditorButton from '../../components/rich_text_editor_button'
|
||||
import GifSelectorButton from '../../components/gif_selector_button'
|
||||
import StatusVisibilityButton from '../../components/status_visibility_button'
|
||||
import EmojiPickerButton from '../../components/emoji_picker_button'
|
||||
import PollFormContainer from '../../containers/poll_form_container'
|
||||
import SchedulePostButton from '../schedule_post_button'
|
||||
import StatusContainer from '../../../../containers/status_container'
|
||||
import Button from '../../../../components/button'
|
||||
import Avatar from '../../../../components/avatar'
|
||||
import { isMobile } from '../../../../utils/is_mobile'
|
||||
import { countableText } from '../../util/counter'
|
||||
|
||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d'
|
||||
const maxPostCharacterCount = 3000
|
||||
import { isMobile } from '../../../utils/is_mobile'
|
||||
import { countableText } from '../util/counter'
|
||||
import {
|
||||
CX,
|
||||
MAX_POST_CHARACTER_COUNT,
|
||||
ALLOWED_AROUND_SHORT_CODE,
|
||||
} from '../../../constants'
|
||||
import AutosuggestTextbox from '../../../components/autosuggest_textbox'
|
||||
import Avatar from '../../../components/avatar'
|
||||
import Button from '../../../components/button'
|
||||
import CharacterCounter from '../../../components/character_counter'
|
||||
import EmojiPickerButton from './emoji_picker_button'
|
||||
import GifSelectorButton from './gif_selector_button'
|
||||
import PollButton from './poll_button'
|
||||
import PollForm from './poll_form'
|
||||
import RichTextEditorButton from './rich_text_editor_button'
|
||||
import SchedulePostButton from './schedule_post_button'
|
||||
import SpoilerButton from './spoiler_button'
|
||||
import StatusContainer from '../../../containers/status_container'
|
||||
import StatusVisibilityButton from './status_visibility_button'
|
||||
import UploadButton from './media_upload_button'
|
||||
import UploadForm from './upload_form'
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'compose_form.placeholder', defaultMessage: "What's on your mind?" },
|
||||
@@ -33,8 +34,6 @@ const messages = defineMessages({
|
||||
schedulePost: { id: 'compose_form.schedule_post', defaultMessage: 'Schedule Post' },
|
||||
});
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class ComposeForm extends ImmutablePureComponent {
|
||||
@@ -134,7 +133,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props;
|
||||
const fulltext = [this.props.spoilerText, countableText(this.props.text)].join('');
|
||||
|
||||
if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxPostCharacterCount || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) {
|
||||
if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > MAX_POST_CHARACTER_COUNT || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -211,7 +210,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
handleEmojiPick = (data) => {
|
||||
const { text } = this.props
|
||||
const position = this.autosuggestTextarea.textbox.selectionStart
|
||||
const needsSpace = data.custom && position > 0 && !allowedAroundShortCode.includes(text[position - 1])
|
||||
const needsSpace = data.custom && position > 0 && !ALLOWED_AROUND_SHORT_CODE.includes(text[position - 1])
|
||||
|
||||
this.props.onPickEmoji(position, data, needsSpace)
|
||||
}
|
||||
@@ -240,17 +239,17 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
} = this.props
|
||||
const disabled = isSubmitting
|
||||
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
|
||||
const disabledButton = disabled || isUploading || isChangingUpload || length(text) > maxPostCharacterCount || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||
const disabledButton = disabled || isUploading || isChangingUpload || length(text) > MAX_POST_CHARACTER_COUNT || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
||||
|
||||
const parentContainerClasses = cx({
|
||||
const parentContainerClasses = CX({
|
||||
default: 1,
|
||||
width100PC: 1,
|
||||
flexRow: !shouldCondense,
|
||||
pb10: !shouldCondense,
|
||||
})
|
||||
|
||||
const childContainerClasses = cx({
|
||||
const childContainerClasses = CX({
|
||||
default: 1,
|
||||
flexWrap: 1,
|
||||
overflowHidden: 1,
|
||||
@@ -262,17 +261,17 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
px5: shouldCondense,
|
||||
})
|
||||
|
||||
const actionsContainerClasses = cx({
|
||||
const actionsContainerClasses = CX({
|
||||
default: 1,
|
||||
flexRow: 1,
|
||||
alignItemsCenter: !shouldCondense,
|
||||
alignItemsStart: shouldCondense,
|
||||
mt10: !shouldCondense,
|
||||
px15: !shouldCondense,
|
||||
marginLeftAuto: shouldCondense,
|
||||
mlAuto: shouldCondense,
|
||||
})
|
||||
|
||||
const commentPublishBtnClasses = cx({
|
||||
const commentPublishBtnClasses = CX({
|
||||
default: 1,
|
||||
justifyContentCenter: 1,
|
||||
displayNone: length(this.props.text) === 0 || anyMedia,
|
||||
@@ -284,7 +283,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
{
|
||||
shouldCondense &&
|
||||
<div className={[_s.default, _s.mr10, _s.mt5].join(' ')}>
|
||||
<Avatar account={account} size={28} />
|
||||
<Avatar account={account} size={28} noHover />
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -361,7 +360,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
{
|
||||
!edit && hasPoll &&
|
||||
<div className={[_s.default, _s.px15, _s.mt5].join(' ')}>
|
||||
<PollFormContainer replyToId={replyToId} />
|
||||
<PollForm replyToId={replyToId} />
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -376,7 +375,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
<div className={actionsContainerClasses}>
|
||||
<div className={[_s.default, _s.flexRow, _s.marginRightAuto].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.mrAuto].join(' ')}>
|
||||
{
|
||||
!shouldCondense &&
|
||||
<RichTextEditorButton />
|
||||
@@ -418,7 +417,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
|
||||
{
|
||||
!shouldCondense &&
|
||||
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
||||
<CharacterCounter max={MAX_POST_CHARACTER_COUNT} text={text} />
|
||||
}
|
||||
|
||||
{
|
||||
@@ -1,144 +0,0 @@
|
||||
.compose-form {
|
||||
padding: 10px;
|
||||
|
||||
&__sensitive-button {
|
||||
padding: 0 10px 10px 10px;
|
||||
|
||||
@include text-sizing(14px, 500);
|
||||
|
||||
&.active {
|
||||
color: $highlight-text-color;
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 auto;
|
||||
margin-right: 10px;
|
||||
top: -1px;
|
||||
vertical-align: middle;
|
||||
|
||||
@include size(18px);
|
||||
@include border-design($ui-primary-color, 1px, 4px);
|
||||
|
||||
&.active {
|
||||
border-color: $highlight-text-color;
|
||||
background: $highlight-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker-dropdown {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&.condensed {
|
||||
.autosuggest-textarea__textarea {
|
||||
min-height: 46px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker-wrapper {
|
||||
position: relative;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
&__modifiers {
|
||||
color: $inverted-text-color;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
background: $simple-background-color;
|
||||
}
|
||||
|
||||
&__buttons-wrapper {
|
||||
padding: 10px;
|
||||
background: darken($simple-background-color, 8%);
|
||||
border-radius: 0 0 4px 4px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
@include flex(space-between);
|
||||
|
||||
.compose-form__buttons {
|
||||
display: flex;
|
||||
|
||||
.compose-form__sensitive-button {
|
||||
display: none;
|
||||
|
||||
&.compose-form__sensitive-button--visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.compose-form__sensitive-button__icon {
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
box-sizing: content-box;
|
||||
padding: 0 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&__publish {
|
||||
min-width: 0;
|
||||
flex: 0 0 auto;
|
||||
|
||||
@include flex(flex-end);
|
||||
}
|
||||
|
||||
&__publish-button-wrapper {
|
||||
overflow: hidden;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.spoiler-input {
|
||||
height: 0;
|
||||
transform-origin: bottom;
|
||||
opacity: 0.0;
|
||||
position: relative;
|
||||
|
||||
&--visible {
|
||||
height: 36px;
|
||||
margin-bottom: 11px;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
&__input {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: $inverted-text-color;
|
||||
background: $simple-background-color;
|
||||
padding: 10px;
|
||||
font-family: inherit;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
border-radius: 4px;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@include breakpoint(sm) {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-reduce-motion .spoiler-input {
|
||||
transition: height 0.4s ease, opacity 0.4s ease;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './compose_form'
|
||||
@@ -1,117 +0,0 @@
|
||||
.emoji-picker-dropdown__menu {
|
||||
background: $simple-background-color;
|
||||
position: absolute;
|
||||
box-shadow: 4px 4px 6px rgba($base-shadow-color, 0.4);
|
||||
border-radius: 4px;
|
||||
margin-top: 5px;
|
||||
z-index: 20000;
|
||||
|
||||
.emoji-mart-scroll {
|
||||
transition: opacity 200ms ease;
|
||||
}
|
||||
|
||||
&.selecting .emoji-mart-scroll {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker-dropdown__modifiers {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
right: 11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.emoji-picker-dropdown__modifiers__menu {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
top: -4px;
|
||||
left: -8px;
|
||||
background: $simple-background-color;
|
||||
border-radius: 4px;
|
||||
box-shadow: 1px 2px 6px rgba($base-shadow-color, 0.2);
|
||||
overflow: hidden;
|
||||
|
||||
button {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
border: 0;
|
||||
padding: 4px 8px;
|
||||
background: transparent;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
background: rgba($ui-secondary-color, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-mart-emoji {
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-button {
|
||||
display: block;
|
||||
margin-left: 2px;
|
||||
width: 24px;
|
||||
outline: 0;
|
||||
cursor: pointer;
|
||||
|
||||
@include text-sizing(24px, 400, 24px);
|
||||
|
||||
&:active,
|
||||
&:focus {
|
||||
outline: 0 !important;
|
||||
}
|
||||
|
||||
img {
|
||||
filter: grayscale(100%);
|
||||
opacity: 0.8;
|
||||
display: block;
|
||||
margin: 2px 0 0 0;
|
||||
|
||||
@include size(22px);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
img {
|
||||
opacity: 1;
|
||||
filter: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-reduce-motion .pulse-loading {
|
||||
transform-origin: center center;
|
||||
animation: heartbeat 1.5s ease-in-out infinite both;
|
||||
}
|
||||
|
||||
@keyframes heartbeat {
|
||||
from {
|
||||
transform: scale(1);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
10% {
|
||||
transform: scale(0.91);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
|
||||
17% {
|
||||
transform: scale(0.98);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
33% {
|
||||
transform: scale(0.87);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
|
||||
45% {
|
||||
transform: scale(1);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './emoji_picker_dropdown'
|
||||
@@ -2,6 +2,15 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import classNames from 'classnames/bind'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import {
|
||||
addPollOption,
|
||||
removePollOption,
|
||||
changePollOption,
|
||||
changePollSettings,
|
||||
clearComposeSuggestions,
|
||||
fetchComposeSuggestions,
|
||||
selectComposeSuggestion,
|
||||
} from '../../../actions/compose'
|
||||
import Button from '../../../components/button'
|
||||
import Text from '../../../components/text'
|
||||
import Select from '../../../components/select'
|
||||
@@ -19,108 +28,47 @@ const messages = defineMessages({
|
||||
days: { id: 'intervals.full.days', defaultMessage: '{number, plural, one {# day} other {# days}}' },
|
||||
})
|
||||
|
||||
@injectIntl
|
||||
class PollFormOption extends ImmutablePureComponent {
|
||||
const mapStateToProps = (state) => ({
|
||||
suggestions: state.getIn(['compose', 'suggestions']),
|
||||
options: state.getIn(['compose', 'poll', 'options']),
|
||||
expiresIn: state.getIn(['compose', 'poll', 'expires_in']),
|
||||
isMultiple: state.getIn(['compose', 'poll', 'multiple']),
|
||||
})
|
||||
|
||||
static propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
isPollMultiple: PropTypes.bool,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onToggleMultiple: PropTypes.func.isRequired,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
onClearSuggestions: PropTypes.func.isRequired,
|
||||
onFetchSuggestions: PropTypes.func.isRequired,
|
||||
onSuggestionSelected: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onAddOption() {
|
||||
dispatch(addPollOption(''))
|
||||
},
|
||||
|
||||
handleOptionTitleChange = e => {
|
||||
this.props.onChange(this.props.index, e.target.value);
|
||||
}
|
||||
onRemoveOption(index) {
|
||||
dispatch(removePollOption(index))
|
||||
},
|
||||
|
||||
handleOptionRemove = () => {
|
||||
this.props.onRemove(this.props.index);
|
||||
}
|
||||
onChangeOption(index, title) {
|
||||
dispatch(changePollOption(index, title))
|
||||
},
|
||||
|
||||
handleToggleMultiple = e => {
|
||||
this.props.onToggleMultiple();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
};
|
||||
onChangeSettings(expiresIn, isMultiple) {
|
||||
dispatch(changePollSettings(expiresIn, isMultiple))
|
||||
},
|
||||
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.props.onClearSuggestions();
|
||||
}
|
||||
onClearSuggestions () {
|
||||
dispatch(clearComposeSuggestions())
|
||||
},
|
||||
|
||||
onSuggestionsFetchRequested = (token) => {
|
||||
this.props.onFetchSuggestions(token);
|
||||
}
|
||||
onFetchSuggestions (token) {
|
||||
dispatch(fetchComposeSuggestions(token))
|
||||
},
|
||||
|
||||
onSuggestionSelected = (tokenStart, token, value) => {
|
||||
this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index]);
|
||||
}
|
||||
onSuggestionSelected (position, token, accountId, path) {
|
||||
dispatch(selectComposeSuggestion(position, token, accountId, path))
|
||||
},
|
||||
|
||||
render() {
|
||||
const { isPollMultiple, title, index, intl } = this.props;
|
||||
|
||||
const toggleClasses = cx({
|
||||
default: 1,
|
||||
px10: 1,
|
||||
py10: 1,
|
||||
borderColorSecondary: 1,
|
||||
border1PX: 1,
|
||||
outlineNone: 1,
|
||||
mr10: 1,
|
||||
circle: !isPollMultiple,
|
||||
})
|
||||
|
||||
return (
|
||||
<li className={[_s.default, _s.flexRow, _s.mb10].join(' ')}>
|
||||
<label className={[_s.default, _s.flexRow, _s.flexGrow1, _s.alignItemsCenter].join(' ')}>
|
||||
<span
|
||||
className={toggleClasses}
|
||||
onClick={this.handleToggleMultiple}
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
/>
|
||||
|
||||
<AutosuggestTextbox
|
||||
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
||||
maxLength={25}
|
||||
value={title}
|
||||
onChange={this.handleOptionTitleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
searchTokens={[':']}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{
|
||||
index > 1 &&
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
className={[_s.ml5, _s.justifyContentCenter].join(' ')}
|
||||
icon='close'
|
||||
iconSize='8px'
|
||||
iconClassName={_s.fillColorSecondary}
|
||||
disabled={index <= 1}
|
||||
title={intl.formatMessage(messages.remove_option)}
|
||||
onClick={this.handleOptionRemove}
|
||||
/>
|
||||
}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class PollForm extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
@@ -166,6 +114,7 @@ class PollForm extends ImmutablePureComponent {
|
||||
{
|
||||
options.map((title, i) => (
|
||||
<PollFormOption
|
||||
intl={intl}
|
||||
title={title}
|
||||
key={`poll-form-option-${i}`}
|
||||
index={i}
|
||||
@@ -241,3 +190,102 @@ class PollForm extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PollFormOption extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
index: PropTypes.number.isRequired,
|
||||
isPollMultiple: PropTypes.bool,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onToggleMultiple: PropTypes.func.isRequired,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
onClearSuggestions: PropTypes.func.isRequired,
|
||||
onFetchSuggestions: PropTypes.func.isRequired,
|
||||
onSuggestionSelected: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
handleOptionTitleChange = e => {
|
||||
this.props.onChange(this.props.index, e.target.value)
|
||||
}
|
||||
|
||||
handleOptionRemove = () => {
|
||||
this.props.onRemove(this.props.index)
|
||||
}
|
||||
|
||||
handleToggleMultiple = e => {
|
||||
this.props.onToggleMultiple()
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
onSuggestionsClearRequested = () => {
|
||||
this.props.onClearSuggestions()
|
||||
}
|
||||
|
||||
onSuggestionsFetchRequested = (token) => {
|
||||
this.props.onFetchSuggestions(token)
|
||||
}
|
||||
|
||||
onSuggestionSelected = (tokenStart, token, value) => {
|
||||
this.props.onSuggestionSelected(tokenStart, token, value, ['poll', 'options', this.props.index])
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isPollMultiple, title, index, intl } = this.props
|
||||
|
||||
const toggleClasses = cx({
|
||||
default: 1,
|
||||
px10: 1,
|
||||
py10: 1,
|
||||
borderColorSecondary: 1,
|
||||
border1PX: 1,
|
||||
outlineNone: 1,
|
||||
mr10: 1,
|
||||
circle: !isPollMultiple,
|
||||
})
|
||||
|
||||
return (
|
||||
<li className={[_s.default, _s.flexRow, _s.mb10].join(' ')}>
|
||||
<label className={[_s.default, _s.flexRow, _s.flexGrow1, _s.alignItemsCenter].join(' ')}>
|
||||
<span
|
||||
className={toggleClasses}
|
||||
onClick={this.handleToggleMultiple}
|
||||
role='button'
|
||||
tabIndex='0'
|
||||
/>
|
||||
|
||||
<AutosuggestTextbox
|
||||
placeholder={intl.formatMessage(messages.option_placeholder, { number: index + 1 })}
|
||||
maxLength={25}
|
||||
value={title}
|
||||
onChange={this.handleOptionTitleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
searchTokens={[':']}
|
||||
/>
|
||||
</label>
|
||||
|
||||
{
|
||||
index > 1 &&
|
||||
<Button
|
||||
isNarrow
|
||||
backgroundColor='none'
|
||||
className={[_s.ml5, _s.justifyContentCenter].join(' ')}
|
||||
icon='close'
|
||||
iconSize='8px'
|
||||
iconClassName={_s.fillColorSecondary}
|
||||
disabled={index <= 1}
|
||||
title={intl.formatMessage(messages.remove_option)}
|
||||
onClick={this.handleOptionRemove}
|
||||
/>
|
||||
}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,33 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import HashtagItem from '../../../../components/hashtag_item'
|
||||
import Icon from '../../../../components/icon'
|
||||
import { WhoToFollowPanel } from '../../../../components/panel'
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { fetchSuggestions, dismissSuggestion } from '../../../actions/suggestions';
|
||||
import HashtagItem from '../../../components/hashtag_item'
|
||||
import Icon from '../../../components/icon'
|
||||
import { WhoToFollowPanel } from '../../../components/panel'
|
||||
// import TrendsPanel from '../../ui/components/trends_panel'
|
||||
import GroupListItem from '../../../../components/group_list_item'
|
||||
import Block from '../../../../components/block'
|
||||
import Heading from '../../../../components/heading'
|
||||
import Button from '../../../../components/button'
|
||||
import Text from '../../../../components/text'
|
||||
import Account from '../../../../components/account'
|
||||
import GroupListItem from '../../../components/group_list_item'
|
||||
import Block from '../../../components/block'
|
||||
import Heading from '../../../components/heading'
|
||||
import Button from '../../../components/button'
|
||||
import Text from '../../../components/text'
|
||||
import Account from '../../../components/account'
|
||||
|
||||
// : todo :
|
||||
const mapStateToProps = (state) => ({
|
||||
results: state.getIn(['search', 'results']),
|
||||
suggestions: state.getIn(['suggestions', 'items']),
|
||||
});
|
||||
|
||||
export default class SearchResults extends ImmutablePureComponent {
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
fetchSuggestions: () => dispatch(fetchSuggestions()),
|
||||
dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))),
|
||||
});
|
||||
|
||||
export default
|
||||
@withRouter
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class SearchResults extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
results: ImmutablePropTypes.map.isRequired,
|
||||
@@ -46,12 +59,12 @@ export default class SearchResults extends ImmutablePureComponent {
|
||||
if (results.get('accounts') && results.get('accounts').size > 0 && (isTop || showPeople)) {
|
||||
const size = isTop ? Math.min(results.get('accounts').size, 5) : results.get('accounts').size;
|
||||
accounts = (
|
||||
<div className={[_s.default, _s.py15, _s.px15].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.mb15].join(' ')}>
|
||||
<Heading size='h3'>
|
||||
<div className={[_s.default, _s.py15].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.mb15, _s.px15].join(' ')}>
|
||||
<Heading size='h2'>
|
||||
People
|
||||
</Heading>
|
||||
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||
<div className={[_s.default, _s.mlAuto].join(' ')}>
|
||||
<Button
|
||||
isText
|
||||
backgroundColor='none'
|
||||
@@ -66,7 +79,7 @@ export default class SearchResults extends ImmutablePureComponent {
|
||||
</div>
|
||||
|
||||
{
|
||||
results.get('accounts').slice(0, size).map(accountId => <Account expanded key={accountId} id={accountId} />)
|
||||
results.get('accounts').slice(0, size).map(accountId => <Account compact key={accountId} id={accountId} />)
|
||||
}
|
||||
</div>
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './search_results'
|
||||
@@ -1,40 +0,0 @@
|
||||
.search-results {
|
||||
&__header {
|
||||
color: $dark-text-color;
|
||||
background: lighten($ui-base-color, 2%);
|
||||
padding: 15px;
|
||||
cursor: default;
|
||||
|
||||
@include text-sizing(16px, 500);
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&__section {
|
||||
margin-bottom: 5px;
|
||||
|
||||
h5 {
|
||||
display: flex;
|
||||
background: darken($ui-base-color, 4%);
|
||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
||||
color: $dark-text-color;
|
||||
padding: 15px;
|
||||
cursor: default;
|
||||
|
||||
@include text-sizing(16px, 500);
|
||||
|
||||
.fa {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.account:last-child,
|
||||
&>div:last-child .status {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user