Added branding_preview. Edited index
This commit is contained in:
parent
2af5149ed3
commit
eef32c96e3
4 changed files with 83 additions and 85 deletions
|
@ -0,0 +1,32 @@
|
|||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { acctFull } from 'soapbox/utils/accounts';
|
||||
import StillImage from 'soapbox/components/still_image';
|
||||
|
||||
const BrandingPreview = ({ account }) => (
|
||||
<div className='card h-card'>
|
||||
<a target='_blank' rel='noopener' href={account.get('url')}>
|
||||
<div className='card__img'>
|
||||
<StillImage alt='' src={account.get('header')} />
|
||||
</div>
|
||||
<div className='card__bar'>
|
||||
<div className='avatar'>
|
||||
<StillImage alt='' className='u-photo' src={account.get('avatar')} width='48' height='48' />
|
||||
</div>
|
||||
<div className='display-name'>
|
||||
<span style={{ display: 'none' }}>{account.get('username')}</span>
|
||||
<bdi>
|
||||
<strong className='emojify p-name'>{account.get('display_name')}</strong>
|
||||
</bdi>
|
||||
<span>{acctFull(account)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
BrandingPreview.propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
export default BrandingPreview;
|
|
@ -12,6 +12,7 @@ import {
|
|||
Checkbox,
|
||||
FileChooser,
|
||||
} from 'soapbox/features/forms';
|
||||
import BrandingPreview from './components/branding_preview';
|
||||
import {
|
||||
Map as ImmutableMap,
|
||||
List as ImmutableList,
|
||||
|
@ -19,82 +20,37 @@ import {
|
|||
import { patchMe } from 'soapbox/actions/me';
|
||||
import { unescape } from 'lodash';
|
||||
|
||||
const MAX_FIELDS = 6; // Max promoPanel fields
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
|
||||
metaFieldLabel: { id: 'edit_profile.fields.meta_fields.label_placeholder', defaultMessage: 'Label' },
|
||||
metaFieldContent: { id: 'edit_profile.fields.meta_fields.content_placeholder', defaultMessage: 'Content' },
|
||||
heading: { id: 'column.soapbox_settings', defaultMessage: 'Soapbox settings' },
|
||||
promoPanelIcon: { id: 'soapbox_settings.promo_panel.meta_fields.icon_placeholder', defaultMessage: 'Icon' },
|
||||
promoPanelLabel: { id: 'soapbox_settings.promo_panel.meta_fields.label_placeholder', defaultMessage: 'Label' },
|
||||
promoPanelURL: { id: 'soapbox_settings.promo_panel.meta_fields.url_placeholder', defaultMessage: 'URL' },
|
||||
homeFooterLabel: { id: 'soapbox_settings.home_footer.meta_fields.label_placeholder', defaultMessage: 'Label' },
|
||||
homeFooterURL: { id: 'soapbox_settings.home_footer.meta_fields.url_placeholder', defaultMessage: 'URL' },
|
||||
});
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const soapbox = state.get('soapbox');
|
||||
return {
|
||||
themeCss: generateThemeCss(state.getIn(['soapbox', 'brandColor'])),
|
||||
customCss: state.getIn(['soapbox', 'customCss']),
|
||||
logo: state.getIn(['soapbox', 'logo']),
|
||||
logo: state.getIn(['soapbox', 'logo']),
|
||||
promoPanel: state.getIn(['soapbox', 'promoPanel', 'items']),
|
||||
patronEnabled: state.getIn(['soapbox', 'extensions', 'patron', 'enabled']),
|
||||
displayMode: state.getIn(['soapbox', 'defaultSettings', 'mode']),
|
||||
autoPlayGif: state.getIn(['soapbox', 'defaultSettings', 'autoPlayGif']),
|
||||
copyright: state.getIn(['soapbox', 'copyright']),
|
||||
homeFooter: state.getIn(['soapbox', 'navLinks', 'homeFooter']),
|
||||
|
||||
// {
|
||||
// soapbox: {
|
||||
// brandColor: '#1ca82b',
|
||||
// logo: '/favicon.png',
|
||||
// promoPanel: {
|
||||
// items: [
|
||||
// {
|
||||
// icon: 'area-chart',
|
||||
// text: 'Gleasonator stats',
|
||||
// url: 'https://fediverse.network/gleasonator.com'
|
||||
// },
|
||||
// {
|
||||
// icon: 'comment-o',
|
||||
// text: 'Gleasonator theme song',
|
||||
// url: 'https://media.gleasonator.com/custom/261905_gleasonator_song.mp3'
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// extensions: {
|
||||
// patron: {
|
||||
// enabled: true
|
||||
// }
|
||||
// },
|
||||
// defaultSettings: {
|
||||
// mode: 'light'
|
||||
// },
|
||||
// copyright: '♡2020. Copying is an act of love. Please copy and share.',
|
||||
// navlinks: {
|
||||
// homeFooter: [
|
||||
// {
|
||||
// title: 'About',
|
||||
// url: '/about'
|
||||
// },
|
||||
// {
|
||||
// title: 'Terms of Service',
|
||||
// url: '/about/tos'
|
||||
// },
|
||||
// {
|
||||
// title: 'Privacy Policy',
|
||||
// url: '/about/privacy'
|
||||
// },
|
||||
// {
|
||||
// title: 'DMCA',
|
||||
// url: '/about/dmca'
|
||||
// },
|
||||
// {
|
||||
// title: 'Source Code',
|
||||
// url: '/about#opensource'
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
// Forces fields to be MAX_SIZE, filling empty values
|
||||
const normalizeFields = fields => (
|
||||
ImmutableList(fields).setSize(MAX_FIELDS).map(field =>
|
||||
field ? field : ImmutableMap({ name: '', value: '' })
|
||||
)
|
||||
);
|
||||
|
||||
// HTML unescape for special chars, eg <br>
|
||||
const unescapeParams = (map, params) => (
|
||||
params.reduce((map, param) => (
|
||||
|
@ -109,26 +65,31 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
themeCss: PropTypes.text,
|
||||
logo: PropTypes.object,
|
||||
promoPanel: ImmutablePropTypes.map,
|
||||
patronEnabled: PropTypes.Boolean,
|
||||
autoPlayGif: PropTypes.Boolean,
|
||||
copyright: PropTypes.text,
|
||||
homeFooter: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
state = {
|
||||
isLoading: false,
|
||||
fields: normalizeFields(Array.from({ length: MAX_FIELDS })),
|
||||
promoPanel: normalizeFields(Array.from({ length: MAX_FIELDS })),
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const initialState = props.account.withMutations(map => {
|
||||
const initialState = props.withMutations(map => {
|
||||
map.merge(map.get('source'));
|
||||
map.delete('source');
|
||||
map.set('fields', normalizeFields(map.get('fields')));
|
||||
unescapeParams(map, ['display_name', 'note']);
|
||||
map.set('promoPanel', normalizeFields(map.get('promoPanel')));
|
||||
});
|
||||
this.state = initialState.toObject();
|
||||
}
|
||||
|
||||
makePreviewAccount = () => {
|
||||
makePreviewLogo = () => {
|
||||
const { account } = this.props;
|
||||
return account.merge(ImmutableMap({
|
||||
header: this.state.header,
|
||||
|
@ -137,12 +98,12 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
}));
|
||||
}
|
||||
|
||||
getFieldParams = () => {
|
||||
getPromoPanelParams = () => {
|
||||
let params = ImmutableMap();
|
||||
this.state.fields.forEach((f, i) =>
|
||||
this.state.promoPanel.forEach((f, i) =>
|
||||
params = params
|
||||
.set(`fields_attributes[${i}][name]`, f.get('name'))
|
||||
.set(`fields_attributes[${i}][value]`, f.get('value'))
|
||||
.set(`promo_panel_attributes[${i}][name]`, f.get('name'))
|
||||
.set(`promo_panel_attributes[${i}][value]`, f.get('value'))
|
||||
);
|
||||
return params;
|
||||
}
|
||||
|
@ -150,21 +111,20 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
getParams = () => {
|
||||
const { state } = this;
|
||||
return Object.assign({
|
||||
discoverable: state.discoverable,
|
||||
bot: state.bot,
|
||||
display_name: state.display_name,
|
||||
note: state.note,
|
||||
avatar: state.avatar_file,
|
||||
header: state.header_file,
|
||||
locked: state.locked,
|
||||
}, this.getFieldParams().toJS());
|
||||
themeCss: state.themeCss,
|
||||
logoFile: state.logoFile,
|
||||
patronEnabled: state.patronEnabled,
|
||||
displayMode: state.displayMode,
|
||||
copyright: state.copyright,
|
||||
homeFooter: state.homeFooter,
|
||||
}, this.getPromoPanelParams().toJS());
|
||||
}
|
||||
|
||||
getFormdata = () => {
|
||||
const data = this.getParams();
|
||||
let formData = new FormData();
|
||||
for (let key in data) {
|
||||
const shouldAppend = Boolean(data[key] || key.startsWith('fields_attributes'));
|
||||
const shouldAppend = Boolean(data[key] || key.startsWith('promo_panel_attributes'));
|
||||
if (shouldAppend) formData.append(key, data[key] || '');
|
||||
}
|
||||
return formData;
|
||||
|
@ -189,7 +149,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
this.setState({ [e.target.name]: e.target.value });
|
||||
}
|
||||
|
||||
handleFieldChange = (i, key) => {
|
||||
handlePromoPanelChange = (i, key) => {
|
||||
return (e) => {
|
||||
this.setState({
|
||||
fields: this.state.fields.setIn([i, key], e.target.value),
|
||||
|
@ -212,7 +172,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
const { intl } = this.props;
|
||||
|
||||
return (
|
||||
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<Column icon='gears' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||
<SimpleForm onSubmit={this.handleSubmit}>
|
||||
<fieldset disabled={this.state.isLoading}>
|
||||
<FieldsGroup>
|
||||
|
@ -230,7 +190,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
/>
|
||||
<div className='fields-row'>
|
||||
<div className='fields-row__column fields-row__column-6'>
|
||||
<ProfilePreview account={this.makePreviewAccount()} />
|
||||
<ProfilePreview account={this.makePreviewLogo()} />
|
||||
</div>
|
||||
<div className='fields-row__column fields-group fields-row__column-6'>
|
||||
<FileChooser
|
||||
|
@ -275,12 +235,12 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
|||
<TextInput
|
||||
placeholder={intl.formatMessage(messages.metaFieldLabel)}
|
||||
value={field.get('name')}
|
||||
onChange={this.handleFieldChange(i, 'name')}
|
||||
onChange={this.handlePromoPanelChange(i, 'name')}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={intl.formatMessage(messages.metaFieldContent)}
|
||||
value={field.get('value')}
|
||||
onChange={this.handleFieldChange(i, 'value')}
|
||||
onChange={this.handlePromoPanelChange(i, 'value')}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
|
|
|
@ -71,6 +71,7 @@ import {
|
|||
LoginPage,
|
||||
Preferences,
|
||||
EditProfile,
|
||||
ConfigSoapbox,
|
||||
PasswordReset,
|
||||
SecurityForm,
|
||||
} from './util/async-components';
|
||||
|
@ -253,6 +254,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
<Redirect exact from='/settings' to='/settings/preferences' />
|
||||
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
||||
<WrappedRoute path='/settings/profile' layout={LAYOUT.DEFAULT} component={EditProfile} content={children} />
|
||||
<WrappedRoute path='/admin' layout={LAYOUT.DEFAULT} component={ConfigSoapbox} content={children} />
|
||||
|
||||
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
||||
</Switch>
|
||||
|
|
|
@ -178,6 +178,10 @@ export function EditProfile() {
|
|||
return import(/* webpackChunkName: "features/edit_profile" */'../../edit_profile');
|
||||
}
|
||||
|
||||
export function ConfigSoapbox() {
|
||||
return import(/* webpackChunkName: "features/configuration" */'../../configuration');
|
||||
}
|
||||
|
||||
export function PasswordReset() {
|
||||
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue