import React from 'react';
import { connect } from 'react-redux';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Column from '../ui/components/column';
import {
SimpleForm,
FieldsGroup,
TextInput,
Checkbox,
FileChooser,
SimpleTextarea,
FileChooserLogo,
FormPropTypes,
} from 'soapbox/features/forms';
import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
import { updateAdminConfig } from 'soapbox/actions/admin';
import Icon from 'soapbox/components/icon';
import { defaultConfig } from 'soapbox/actions/soapbox';
import { uploadMedia } from 'soapbox/actions/media';
import { SketchPicker } from 'react-color';
import Overlay from 'react-overlays/lib/Overlay';
import { isMobile } from 'soapbox/is_mobile';
import detectPassiveEvents from 'detect-passive-events';
import Accordion from '../ui/components/accordion';
const messages = defineMessages({
heading: { id: 'column.soapbox_config', defaultMessage: 'Soapbox config' },
copyrightFooterLabel: { id: 'soapbox_config.copyright_footer.meta_fields.label_placeholder', defaultMessage: 'Copyright footer' },
promoItemIcon: { id: 'soapbox_config.promo_panel.meta_fields.icon_placeholder', defaultMessage: 'Icon' },
promoItemLabel: { id: 'soapbox_config.promo_panel.meta_fields.label_placeholder', defaultMessage: 'Label' },
promoItemURL: { id: 'soapbox_config.promo_panel.meta_fields.url_placeholder', defaultMessage: 'URL' },
homeFooterItemLabel: { id: 'soapbox_config.home_footer.meta_fields.label_placeholder', defaultMessage: 'Label' },
homeFooterItemURL: { id: 'soapbox_config.home_footer.meta_fields.url_placeholder', defaultMessage: 'URL' },
customCssLabel: { id: 'soapbox_config.custom_css.meta_fields.url_placeholder', defaultMessage: 'URL' },
rawJSONLabel: { id: 'soapbox_config.raw_json_label', defaultMessage: 'Advanced: Edit raw JSON data' },
rawJSONHint: { id: 'soapbox_config.raw_json_hint', defaultMessage: 'Edit the settings data directly. Changes made directly to the JSON file will override the form fields above. Click "Save" to apply your changes.' },
});
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
const templates = {
promoPanelItem: ImmutableMap({ icon: '', text: '', url: '' }),
footerItem: ImmutableMap({ title: '', url: '' }),
};
const mapStateToProps = state => ({
soapbox: state.get('soapbox'),
});
export default @connect(mapStateToProps)
@injectIntl
class SoapboxConfig extends ImmutablePureComponent {
static propTypes = {
soapbox: ImmutablePropTypes.map.isRequired,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
state = {
isLoading: false,
soapbox: this.props.soapbox,
rawJSON: JSON.stringify(this.props.soapbox, null, 2),
jsonValid: true,
}
setConfig = (path, value) => {
const { soapbox } = this.state;
const config = soapbox.setIn(path, value);
this.setState({ soapbox: config, jsonValid: true });
};
putConfig = config => {
this.setState({ soapbox: config, jsonValid: true });
};
getParams = () => {
const { soapbox } = this.state;
return {
configs: [{
group: ':pleroma',
key: ':frontend_configurations',
value: [{
tuple: [':soapbox_fe', soapbox.toJS()],
}],
}],
};
}
handleSubmit = (event) => {
const { dispatch } = this.props;
dispatch(updateAdminConfig(this.getParams())).then(() => {
this.setState({ isLoading: false });
}).catch((error) => {
this.setState({ isLoading: false });
});
this.setState({ isLoading: true });
event.preventDefault();
}
handleChange = (path, getValue) => {
return e => {
this.setConfig(path, getValue(e));
};
};
handleFileChange = path => {
return e => {
const data = new FormData();
data.append('file', e.target.files[0]);
this.props.dispatch(uploadMedia(data)).then(({ data }) => {
this.handleChange(path, e => data.url)(e);
}).catch(() => {});
};
};
handleAddItem = (path, template) => {
return e => {
this.setConfig(
path,
this.getSoapboxConfig().getIn(path, ImmutableList()).push(template),
);
};
};
handleDeleteItem = path => {
return e => {
const soapbox = this.state.soapbox.deleteIn(path);
this.setState({ soapbox });
};
};
handleItemChange = (path, key, field, template) => {
return this.handleChange(
path, (e) =>
template
.merge(field)
.set(key, e.target.value)
);
};
handlePromoItemChange = (index, key, field) => {
return this.handleItemChange(
['promoPanel', 'items', index], key, field, templates.promoPanelItem
);
};
handleHomeFooterItemChange = (index, key, field) => {
return this.handleItemChange(
['navlinks', 'homeFooter', index], key, field, templates.footerItem
);
};
handleEditJSON = e => {
this.setState({ rawJSON: e.target.value });
}
getSoapboxConfig = () => {
return defaultConfig.mergeDeep(this.state.soapbox);
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.soapbox !== this.props.soapbox) {
this.putConfig(this.props.soapbox);
}
if (prevState.soapbox !== this.state.soapbox) {
this.setState({ rawJSON: JSON.stringify(this.state.soapbox, null, 2) });
}
if (prevState.rawJSON !== this.state.rawJSON) {
try {
const data = fromJS(JSON.parse(this.state.rawJSON));
this.putConfig(data);
} catch {
this.setState({ jsonValid: false });
}
}
}
render() {
const { intl } = this.props;
const soapbox = this.getSoapboxConfig();
return (