import React from "react"
import CategorySelect from "misago/components/category-select"
import Editor from "misago/components/editor"
import Form from "misago/components/form"
import Container from "./utils/container"
import Loader from "./utils/loader"
import Message from "./utils/message"
import Options from "./utils/options"
import * as attachments from "./utils/attachments"
import { getPostValidators, getTitleValidators } from "./utils/validators"
import ajax from "misago/services/ajax"
import posting from "misago/services/posting"
import snackbar from "misago/services/snackbar"
export default class extends Form {
constructor(props) {
super(props)
this.state = {
isReady: false,
isLoading: false,
isErrored: false,
showOptions: false,
categoryOptions: null,
title: "",
category: props.category || null,
categories: [],
post: "",
attachments: [],
close: false,
hide: false,
pin: 0,
validators: {
title: getTitleValidators(),
post: getPostValidators()
},
errors: {}
}
}
componentDidMount() {
ajax.get(this.props.config).then(this.loadSuccess, this.loadError)
}
loadSuccess = data => {
let category = null
let showOptions = false
let categoryOptions = null
// hydrate categories, extract posting options
const categories = data.map(item => {
// pick first category that allows posting and if it may, override it with initial one
if (
item.post !== false &&
(!category || item.id == this.state.category)
) {
category = item.id
categoryOptions = item.post
}
if (item.post && (item.post.close || item.post.hide || item.post.pin)) {
showOptions = true
}
return Object.assign(item, {
disabled: item.post === false,
label: item.name,
value: item.id
})
})
this.setState({
isReady: true,
showOptions,
categories,
category,
categoryOptions
})
}
loadError = rejection => {
this.setState({
isErrored: rejection.detail
})
}
onCancel = () => {
const cancel = window.confirm(gettext("Are you sure you want to discard thread?"))
if (cancel) {
posting.close()
}
}
onTitleChange = event => {
this.changeValue("title", event.target.value)
}
onCategoryChange = event => {
const category = this.state.categories.find(item => {
return event.target.value == item.value
})
// if selected pin is greater than allowed, reduce it
let pin = this.state.pin
if (category.post.pin && category.post.pin < pin) {
pin = category.post.pin
}
this.setState({
category: category.id,
categoryOptions: category.post,
pin
})
}
onPostChange = event => {
this.changeValue("post", event.target.value)
}
onAttachmentsChange = attachments => {
this.setState({
attachments
})
}
onClose = () => {
this.changeValue("close", true)
}
onOpen = () => {
this.changeValue("close", false)
}
onPinGlobally = () => {
this.changeValue("pin", 2)
}
onPinLocally = () => {
this.changeValue("pin", 1)
}
onUnpin = () => {
this.changeValue("pin", 0)
}
onHide = () => {
this.changeValue("hide", true)
}
onUnhide = () => {
this.changeValue("hide", false)
}
clean() {
if (!this.state.title.trim().length) {
snackbar.error(gettext("You have to enter thread title."))
return false
}
if (!this.state.post.trim().length) {
snackbar.error(gettext("You have to enter a message."))
return false
}
const errors = this.validate()
if (errors.title) {
snackbar.error(errors.title[0])
return false
}
if (errors.post) {
snackbar.error(errors.post[0])
return false
}
return true
}
send() {
return ajax.post(this.props.submit, {
title: this.state.title,
category: this.state.category,
post: this.state.post,
attachments: attachments.clean(this.state.attachments),
close: this.state.close,
hide: this.state.hide,
pin: this.state.pin
})
}
handleSuccess(success) {
snackbar.success(gettext("Your thread has been posted."))
window.location = success.url
// keep form loading
this.setState({
isLoading: true
})
}
handleError(rejection) {
if (rejection.status === 400) {
const errors = [].concat(
rejection.non_field_errors || [],
rejection.category || [],
rejection.title || [],
rejection.post || [],
rejection.attachments || []
)
snackbar.error(errors[0])
} else {
snackbar.apiError(rejection)
}
}
render() {
if (this.state.isErrored) {
return
}
if (!this.state.isReady) {
return
}
let columns = 0
if (this.state.categoryOptions.close) columns += 1
if (this.state.categoryOptions.hide) columns += 1
if (this.state.categoryOptions.pin) columns += 1
let titleStyle = null
if (columns === 1) {
titleStyle = "col-sm-6"
} else {
titleStyle = "col-sm-8"
}
if (columns === 3) {
titleStyle += " col-md-6"
} else if (columns) {
titleStyle += " col-md-7"
} else {
titleStyle += " col-md-9"
}
return (
)
}
}