kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Added branding_preview. Edited index
rodzic
2af5149ed3
commit
eef32c96e3
|
@ -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,
|
Checkbox,
|
||||||
FileChooser,
|
FileChooser,
|
||||||
} from 'soapbox/features/forms';
|
} from 'soapbox/features/forms';
|
||||||
|
import BrandingPreview from './components/branding_preview';
|
||||||
import {
|
import {
|
||||||
Map as ImmutableMap,
|
Map as ImmutableMap,
|
||||||
List as ImmutableList,
|
List as ImmutableList,
|
||||||
|
@ -19,82 +20,37 @@ import {
|
||||||
import { patchMe } from 'soapbox/actions/me';
|
import { patchMe } from 'soapbox/actions/me';
|
||||||
import { unescape } from 'lodash';
|
import { unescape } from 'lodash';
|
||||||
|
|
||||||
|
const MAX_FIELDS = 6; // Max promoPanel fields
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
|
heading: { id: 'column.soapbox_settings', defaultMessage: 'Soapbox settings' },
|
||||||
metaFieldLabel: { id: 'edit_profile.fields.meta_fields.label_placeholder', defaultMessage: 'Label' },
|
promoPanelIcon: { id: 'soapbox_settings.promo_panel.meta_fields.icon_placeholder', defaultMessage: 'Icon' },
|
||||||
metaFieldContent: { id: 'edit_profile.fields.meta_fields.content_placeholder', defaultMessage: 'Content' },
|
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 mapStateToProps = state => {
|
||||||
const soapbox = state.get('soapbox');
|
const soapbox = state.get('soapbox');
|
||||||
return {
|
return {
|
||||||
themeCss: generateThemeCss(state.getIn(['soapbox', 'brandColor'])),
|
themeCss: generateThemeCss(state.getIn(['soapbox', 'brandColor'])),
|
||||||
customCss: state.getIn(['soapbox', 'customCss']),
|
|
||||||
logo: state.getIn(['soapbox', 'logo']),
|
|
||||||
logo: state.getIn(['soapbox', 'logo']),
|
logo: state.getIn(['soapbox', 'logo']),
|
||||||
promoPanel: state.getIn(['soapbox', 'promoPanel', 'items']),
|
promoPanel: state.getIn(['soapbox', 'promoPanel', 'items']),
|
||||||
patronEnabled: state.getIn(['soapbox', 'extensions', 'patron', 'enabled']),
|
patronEnabled: state.getIn(['soapbox', 'extensions', 'patron', 'enabled']),
|
||||||
displayMode: state.getIn(['soapbox', 'defaultSettings', 'mode']),
|
autoPlayGif: state.getIn(['soapbox', 'defaultSettings', 'autoPlayGif']),
|
||||||
copyright: state.getIn(['soapbox', 'copyright']),
|
copyright: state.getIn(['soapbox', 'copyright']),
|
||||||
homeFooter: state.getIn(['soapbox', 'navLinks', 'homeFooter']),
|
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>
|
// HTML unescape for special chars, eg <br>
|
||||||
const unescapeParams = (map, params) => (
|
const unescapeParams = (map, params) => (
|
||||||
params.reduce((map, param) => (
|
params.reduce((map, param) => (
|
||||||
|
@ -109,26 +65,31 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.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 = {
|
state = {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
fields: normalizeFields(Array.from({ length: MAX_FIELDS })),
|
promoPanel: normalizeFields(Array.from({ length: MAX_FIELDS })),
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
const initialState = props.account.withMutations(map => {
|
const initialState = props.withMutations(map => {
|
||||||
map.merge(map.get('source'));
|
map.merge(map.get('source'));
|
||||||
map.delete('source');
|
map.delete('source');
|
||||||
map.set('fields', normalizeFields(map.get('fields')));
|
map.set('promoPanel', normalizeFields(map.get('promoPanel')));
|
||||||
unescapeParams(map, ['display_name', 'note']);
|
|
||||||
});
|
});
|
||||||
this.state = initialState.toObject();
|
this.state = initialState.toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
makePreviewAccount = () => {
|
makePreviewLogo = () => {
|
||||||
const { account } = this.props;
|
const { account } = this.props;
|
||||||
return account.merge(ImmutableMap({
|
return account.merge(ImmutableMap({
|
||||||
header: this.state.header,
|
header: this.state.header,
|
||||||
|
@ -137,12 +98,12 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
getFieldParams = () => {
|
getPromoPanelParams = () => {
|
||||||
let params = ImmutableMap();
|
let params = ImmutableMap();
|
||||||
this.state.fields.forEach((f, i) =>
|
this.state.promoPanel.forEach((f, i) =>
|
||||||
params = params
|
params = params
|
||||||
.set(`fields_attributes[${i}][name]`, f.get('name'))
|
.set(`promo_panel_attributes[${i}][name]`, f.get('name'))
|
||||||
.set(`fields_attributes[${i}][value]`, f.get('value'))
|
.set(`promo_panel_attributes[${i}][value]`, f.get('value'))
|
||||||
);
|
);
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
@ -150,21 +111,20 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
getParams = () => {
|
getParams = () => {
|
||||||
const { state } = this;
|
const { state } = this;
|
||||||
return Object.assign({
|
return Object.assign({
|
||||||
discoverable: state.discoverable,
|
themeCss: state.themeCss,
|
||||||
bot: state.bot,
|
logoFile: state.logoFile,
|
||||||
display_name: state.display_name,
|
patronEnabled: state.patronEnabled,
|
||||||
note: state.note,
|
displayMode: state.displayMode,
|
||||||
avatar: state.avatar_file,
|
copyright: state.copyright,
|
||||||
header: state.header_file,
|
homeFooter: state.homeFooter,
|
||||||
locked: state.locked,
|
}, this.getPromoPanelParams().toJS());
|
||||||
}, this.getFieldParams().toJS());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormdata = () => {
|
getFormdata = () => {
|
||||||
const data = this.getParams();
|
const data = this.getParams();
|
||||||
let formData = new FormData();
|
let formData = new FormData();
|
||||||
for (let key in data) {
|
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] || '');
|
if (shouldAppend) formData.append(key, data[key] || '');
|
||||||
}
|
}
|
||||||
return formData;
|
return formData;
|
||||||
|
@ -189,7 +149,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
this.setState({ [e.target.name]: e.target.value });
|
this.setState({ [e.target.name]: e.target.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFieldChange = (i, key) => {
|
handlePromoPanelChange = (i, key) => {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
fields: this.state.fields.setIn([i, key], e.target.value),
|
fields: this.state.fields.setIn([i, key], e.target.value),
|
||||||
|
@ -212,7 +172,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
const { intl } = this.props;
|
const { intl } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column icon='user' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
<Column icon='gears' heading={intl.formatMessage(messages.heading)} backBtnSlim>
|
||||||
<SimpleForm onSubmit={this.handleSubmit}>
|
<SimpleForm onSubmit={this.handleSubmit}>
|
||||||
<fieldset disabled={this.state.isLoading}>
|
<fieldset disabled={this.state.isLoading}>
|
||||||
<FieldsGroup>
|
<FieldsGroup>
|
||||||
|
@ -230,7 +190,7 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
/>
|
/>
|
||||||
<div className='fields-row'>
|
<div className='fields-row'>
|
||||||
<div className='fields-row__column fields-row__column-6'>
|
<div className='fields-row__column fields-row__column-6'>
|
||||||
<ProfilePreview account={this.makePreviewAccount()} />
|
<ProfilePreview account={this.makePreviewLogo()} />
|
||||||
</div>
|
</div>
|
||||||
<div className='fields-row__column fields-group fields-row__column-6'>
|
<div className='fields-row__column fields-group fields-row__column-6'>
|
||||||
<FileChooser
|
<FileChooser
|
||||||
|
@ -275,12 +235,12 @@ class ConfigSoapbox extends ImmutablePureComponent {
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={intl.formatMessage(messages.metaFieldLabel)}
|
placeholder={intl.formatMessage(messages.metaFieldLabel)}
|
||||||
value={field.get('name')}
|
value={field.get('name')}
|
||||||
onChange={this.handleFieldChange(i, 'name')}
|
onChange={this.handlePromoPanelChange(i, 'name')}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder={intl.formatMessage(messages.metaFieldContent)}
|
placeholder={intl.formatMessage(messages.metaFieldContent)}
|
||||||
value={field.get('value')}
|
value={field.get('value')}
|
||||||
onChange={this.handleFieldChange(i, 'value')}
|
onChange={this.handlePromoPanelChange(i, 'value')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
|
|
@ -71,6 +71,7 @@ import {
|
||||||
LoginPage,
|
LoginPage,
|
||||||
Preferences,
|
Preferences,
|
||||||
EditProfile,
|
EditProfile,
|
||||||
|
ConfigSoapbox,
|
||||||
PasswordReset,
|
PasswordReset,
|
||||||
SecurityForm,
|
SecurityForm,
|
||||||
} from './util/async-components';
|
} from './util/async-components';
|
||||||
|
@ -253,6 +254,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
||||||
<Redirect exact from='/settings' to='/settings/preferences' />
|
<Redirect exact from='/settings' to='/settings/preferences' />
|
||||||
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
<WrappedRoute path='/settings/preferences' layout={LAYOUT.DEFAULT} component={Preferences} content={children} />
|
||||||
<WrappedRoute path='/settings/profile' layout={LAYOUT.DEFAULT} component={EditProfile} 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} />
|
<WrappedRoute layout={LAYOUT.EMPTY} component={GenericNotFound} content={children} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -178,6 +178,10 @@ export function EditProfile() {
|
||||||
return import(/* webpackChunkName: "features/edit_profile" */'../../edit_profile');
|
return import(/* webpackChunkName: "features/edit_profile" */'../../edit_profile');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ConfigSoapbox() {
|
||||||
|
return import(/* webpackChunkName: "features/configuration" */'../../configuration');
|
||||||
|
}
|
||||||
|
|
||||||
export function PasswordReset() {
|
export function PasswordReset() {
|
||||||
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
|
return import(/* webpackChunkName: "features/auth_login" */'../../auth_login/components/password_reset');
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue