Restore PromoPanel
This commit is contained in:
parent
55c4e3a00b
commit
be778ce533
|
@ -0,0 +1,119 @@
|
||||||
|
{
|
||||||
|
"allowedEmoji": [
|
||||||
|
"👍",
|
||||||
|
"❤️",
|
||||||
|
"😆",
|
||||||
|
"😮",
|
||||||
|
"😢",
|
||||||
|
"😡",
|
||||||
|
"😩"
|
||||||
|
],
|
||||||
|
"brandColor": "#990099",
|
||||||
|
"copyright": "♡2021. Copying is an act of love. Please copy and share.",
|
||||||
|
"cryptoAddresses": [
|
||||||
|
{
|
||||||
|
"address": "bc1qv7lk3algpfg4zpyuhvxfm0uza9ck4parz3y3l5",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "btc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "0xadc66B63bFee7677CD27CFb81b16a8860f1A1226",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "eth"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "DSf7UmRf7DGGsjh4QYhzQaqtjJMTXZ8k79",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "doge"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "ltc1q642pnkuvw0gpuuvddw6vafvl9hhp3efyl9mnqz",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "ltc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "t1faHDsoa4bd3pGaLjaU7DiuUtBPzbnEEse",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "zec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "XchTLkcSMsDoZGESwr4tqtxSU5dideAZVQ",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "dash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "bitcoincash:qp8f80z27294phmhdk55yf05p3f0tkxl4v9r2aavw5",
|
||||||
|
"note": "",
|
||||||
|
"ticker": "bch"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cryptoDonatePanel": {
|
||||||
|
"limit": 1
|
||||||
|
},
|
||||||
|
"customCss": [
|
||||||
|
"/instance/spinster.css"
|
||||||
|
],
|
||||||
|
"defaultSettings": {
|
||||||
|
"autoPlayGif": false,
|
||||||
|
"themeMode": "light"
|
||||||
|
},
|
||||||
|
"extensions": {
|
||||||
|
"patron": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"logo": "https://spinster.xyz/instance/images/spinster-logo.svg",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"promoPanel": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"icon": "shopping-basket",
|
||||||
|
"text": "Buy Spinster Merch",
|
||||||
|
"url": "https://shop.4w.pub/collections/spinster"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "eye-slash",
|
||||||
|
"text": "Privacy Guide",
|
||||||
|
"url": "https://4w.pub/your-guide-to-spinster-privacy-options/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "question-circle",
|
||||||
|
"text": "Spinster FAQs",
|
||||||
|
"url": "https://spinster.xyz/about#faqs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "bug",
|
||||||
|
"text": "Report a Bug",
|
||||||
|
"url": "https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon": "fediverse",
|
||||||
|
"text": "About the Fediverse",
|
||||||
|
"url": "https://jointhefedi.com/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,41 +0,0 @@
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React from 'react';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { getSettings } from 'soapbox/actions/settings';
|
|
||||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
|
||||||
import Icon from 'soapbox/components/icon';
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
|
||||||
promoItems: getSoapboxConfig(state).getIn(['promoPanel', 'items']),
|
|
||||||
locale: getSettings(state).get('locale'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
class PromoPanel extends React.PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
locale: PropTypes.string,
|
|
||||||
promoItems: ImmutablePropTypes.list,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { locale, promoItems } = this.props;
|
|
||||||
if (!promoItems || promoItems.isEmpty()) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='wtf-panel promo-panel'>
|
|
||||||
<div className='promo-panel__container'>
|
|
||||||
{promoItems.map((item, i) =>
|
|
||||||
(<a className='promo-panel-item' href={item.get('url')} target='_blank' key={i}>
|
|
||||||
<Icon id={item.get('icon')} className='promo-panel-item__icon' fixedWidth />
|
|
||||||
{item.getIn(['textLocales', locale]) || item.get('text')}
|
|
||||||
</a>),
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Icon from 'soapbox/components/icon';
|
||||||
|
import { Widget, Stack, Text } from 'soapbox/components/ui';
|
||||||
|
import { useAppSelector, useSettings, useSoapboxConfig } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
const PromoPanel: React.FC = () => {
|
||||||
|
const { promoPanel } = useSoapboxConfig();
|
||||||
|
const settings = useSettings();
|
||||||
|
|
||||||
|
const siteTitle = useAppSelector(state => state.instance.title);
|
||||||
|
const promoItems = promoPanel.get('items');
|
||||||
|
const locale = settings.get('locale');
|
||||||
|
|
||||||
|
if (!promoItems || promoItems.isEmpty()) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Widget title={siteTitle}>
|
||||||
|
<Stack space={2}>
|
||||||
|
{promoItems.map((item, i) => (
|
||||||
|
<Text>
|
||||||
|
<a className='flex items-center' href={item.url} target='_blank' key={i}>
|
||||||
|
<Icon id={item.icon} className='flex-none text-lg mr-2' fixedWidth />
|
||||||
|
{item.textLocales.get(locale) || item.text}
|
||||||
|
</a>
|
||||||
|
</Text>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Widget>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PromoPanel;
|
|
@ -27,4 +27,11 @@ describe('normalizeSoapboxConfig()', () => {
|
||||||
expect(ImmutableRecord.isRecord(result.cryptoAddresses.get(0))).toBe(true);
|
expect(ImmutableRecord.isRecord(result.cryptoAddresses.get(0))).toBe(true);
|
||||||
expect(result.toJS()).toMatchObject(expected);
|
expect(result.toJS()).toMatchObject(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('normalizes promoPanel', () => {
|
||||||
|
const result = normalizeSoapboxConfig(require('soapbox/__fixtures__/spinster-soapbox.json'));
|
||||||
|
expect(ImmutableRecord.isRecord(result.promoPanel)).toBe(true);
|
||||||
|
expect(ImmutableRecord.isRecord(result.promoPanel.items.get(0))).toBe(true);
|
||||||
|
expect(result.promoPanel.items.get(2).icon).toBe('question-circle');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,6 +61,11 @@ export const PromoPanelItemRecord = ImmutableRecord({
|
||||||
icon: '',
|
icon: '',
|
||||||
text: '',
|
text: '',
|
||||||
url: '',
|
url: '',
|
||||||
|
textLocales: ImmutableMap<string, string>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PromoPanelRecord = ImmutableRecord({
|
||||||
|
items: ImmutableList<PromoPanelItem>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const FooterItemRecord = ImmutableRecord({
|
export const FooterItemRecord = ImmutableRecord({
|
||||||
|
@ -86,9 +91,7 @@ export const SoapboxConfigRecord = ImmutableRecord({
|
||||||
defaultSettings: ImmutableMap(),
|
defaultSettings: ImmutableMap(),
|
||||||
extensions: ImmutableMap(),
|
extensions: ImmutableMap(),
|
||||||
greentext: false,
|
greentext: false,
|
||||||
promoPanel: ImmutableMap({
|
promoPanel: PromoPanelRecord(),
|
||||||
items: ImmutableList<PromoPanelItem>(),
|
|
||||||
}),
|
|
||||||
navlinks: ImmutableMap({
|
navlinks: ImmutableMap({
|
||||||
homeFooter: ImmutableList<FooterItem>(),
|
homeFooter: ImmutableList<FooterItem>(),
|
||||||
}),
|
}),
|
||||||
|
@ -160,12 +163,19 @@ const maybeAddMissingColors = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMa
|
||||||
return soapboxConfig.set('colors', missing.mergeDeep(colors));
|
return soapboxConfig.set('colors', missing.mergeDeep(colors));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const normalizePromoPanel = (soapboxConfig: SoapboxConfigMap): SoapboxConfigMap => {
|
||||||
|
const promoPanel = PromoPanelRecord(soapboxConfig.get('promoPanel'));
|
||||||
|
const items = promoPanel.items.map(PromoPanelItemRecord);
|
||||||
|
return soapboxConfig.set('promoPanel', promoPanel.set('items', items));
|
||||||
|
};
|
||||||
|
|
||||||
export const normalizeSoapboxConfig = (soapboxConfig: Record<string, any>) => {
|
export const normalizeSoapboxConfig = (soapboxConfig: Record<string, any>) => {
|
||||||
return SoapboxConfigRecord(
|
return SoapboxConfigRecord(
|
||||||
ImmutableMap(fromJS(soapboxConfig)).withMutations(soapboxConfig => {
|
ImmutableMap(fromJS(soapboxConfig)).withMutations(soapboxConfig => {
|
||||||
normalizeBrandColor(soapboxConfig);
|
normalizeBrandColor(soapboxConfig);
|
||||||
normalizeAccentColor(soapboxConfig);
|
normalizeAccentColor(soapboxConfig);
|
||||||
normalizeColors(soapboxConfig);
|
normalizeColors(soapboxConfig);
|
||||||
|
normalizePromoPanel(soapboxConfig);
|
||||||
maybeAddMissingColors(soapboxConfig);
|
maybeAddMissingColors(soapboxConfig);
|
||||||
normalizeCryptoAddresses(soapboxConfig);
|
normalizeCryptoAddresses(soapboxConfig);
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
WhoToFollowPanel,
|
WhoToFollowPanel,
|
||||||
TrendsPanel,
|
TrendsPanel,
|
||||||
SignUpPanel,
|
SignUpPanel,
|
||||||
|
PromoPanel,
|
||||||
CryptoDonatePanel,
|
CryptoDonatePanel,
|
||||||
BirthdayPanel,
|
BirthdayPanel,
|
||||||
} from 'soapbox/features/ui/util/async-components';
|
} from 'soapbox/features/ui/util/async-components';
|
||||||
|
@ -94,6 +95,9 @@ class HomePage extends ImmutablePureComponent {
|
||||||
{Component => <Component limit={cryptoLimit} />}
|
{Component => <Component limit={cryptoLimit} />}
|
||||||
</BundleContainer>
|
</BundleContainer>
|
||||||
)}
|
)}
|
||||||
|
<BundleContainer fetchComponent={PromoPanel}>
|
||||||
|
{Component => <Component />}
|
||||||
|
</BundleContainer>
|
||||||
{features.birthdays && (
|
{features.birthdays && (
|
||||||
<BundleContainer fetchComponent={BirthdayPanel}>
|
<BundleContainer fetchComponent={BirthdayPanel}>
|
||||||
{Component => <Component limit={10} />}
|
{Component => <Component limit={10} />}
|
||||||
|
|
Loading…
Reference in New Issue