sforkowany z mirror/soapbox
rodzic
c13b36fed3
commit
5e76b5afca
|
@ -5,10 +5,12 @@ import {
|
||||||
import { unescape } from 'lodash';
|
import { unescape } from 'lodash';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import DatePicker from 'react-datepicker';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import 'react-datepicker/dist/react-datepicker.css';
|
||||||
|
|
||||||
import { updateNotificationSettings } from 'soapbox/actions/accounts';
|
import { updateNotificationSettings } from 'soapbox/actions/accounts';
|
||||||
import { patchMe } from 'soapbox/actions/me';
|
import { patchMe } from 'soapbox/actions/me';
|
||||||
|
@ -49,6 +51,7 @@ const messages = defineMessages({
|
||||||
error: { id: 'edit_profile.error', defaultMessage: 'Profile update failed' },
|
error: { id: 'edit_profile.error', defaultMessage: 'Profile update failed' },
|
||||||
bioPlaceholder: { id: 'edit_profile.fields.bio_placeholder', defaultMessage: 'Tell us about yourself.' },
|
bioPlaceholder: { id: 'edit_profile.fields.bio_placeholder', defaultMessage: 'Tell us about yourself.' },
|
||||||
displayNamePlaceholder: { id: 'edit_profile.fields.display_name_placeholder', defaultMessage: 'Name' },
|
displayNamePlaceholder: { id: 'edit_profile.fields.display_name_placeholder', defaultMessage: 'Name' },
|
||||||
|
birthDatePlaceholder: { id: 'edit_profile.fields.birth_date_placeholder', defaultMessage: 'Your birth date' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
|
@ -58,12 +61,15 @@ const makeMapStateToProps = () => {
|
||||||
const me = state.get('me');
|
const me = state.get('me');
|
||||||
const account = getAccount(state, me);
|
const account = getAccount(state, me);
|
||||||
const soapbox = getSoapboxConfig(state);
|
const soapbox = getSoapboxConfig(state);
|
||||||
|
const features = getFeatures(state.get('instance'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
maxFields: state.getIn(['instance', 'pleroma', 'metadata', 'fields_limits', 'max_fields'], 4),
|
maxFields: state.getIn(['instance', 'pleroma', 'metadata', 'fields_limits', 'max_fields'], 4),
|
||||||
verifiedCanEditName: soapbox.get('verifiedCanEditName'),
|
verifiedCanEditName: soapbox.get('verifiedCanEditName'),
|
||||||
supportsEmailList: getFeatures(state.get('instance')).emailList,
|
supportsEmailList: features.emailList,
|
||||||
|
supportsBirthDates: features.birthDates,
|
||||||
|
minAge: state.getIn(['instance', 'pleroma', 'metadata', 'birth_date_min_age']),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,6 +100,9 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
account: ImmutablePropTypes.map,
|
account: ImmutablePropTypes.map,
|
||||||
maxFields: PropTypes.number,
|
maxFields: PropTypes.number,
|
||||||
verifiedCanEditName: PropTypes.bool,
|
verifiedCanEditName: PropTypes.bool,
|
||||||
|
supportsEmailList: PropTypes.bool,
|
||||||
|
supportsBirthDates: PropTypes.bool,
|
||||||
|
minAge: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -107,6 +116,7 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
const strangerNotifications = account.getIn(['pleroma', 'notification_settings', 'block_from_strangers']);
|
const strangerNotifications = account.getIn(['pleroma', 'notification_settings', 'block_from_strangers']);
|
||||||
const acceptsEmailList = account.getIn(['pleroma', 'accepts_email_list']);
|
const acceptsEmailList = account.getIn(['pleroma', 'accepts_email_list']);
|
||||||
const discoverable = account.getIn(['source', 'pleroma', 'discoverable']);
|
const discoverable = account.getIn(['source', 'pleroma', 'discoverable']);
|
||||||
|
const birthDate = account.getIn(['pleroma', 'birth_date']);
|
||||||
|
|
||||||
const initialState = account.withMutations(map => {
|
const initialState = account.withMutations(map => {
|
||||||
map.merge(map.get('source'));
|
map.merge(map.get('source'));
|
||||||
|
@ -116,6 +126,7 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
map.set('accepts_email_list', acceptsEmailList);
|
map.set('accepts_email_list', acceptsEmailList);
|
||||||
map.set('hide_network', hidesNetwork(account));
|
map.set('hide_network', hidesNetwork(account));
|
||||||
map.set('discoverable', discoverable);
|
map.set('discoverable', discoverable);
|
||||||
|
if (birthDate) map.set('birthDate', new Date(birthDate));
|
||||||
unescapeParams(map, ['display_name', 'bio']);
|
unescapeParams(map, ['display_name', 'bio']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -156,6 +167,7 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
hide_follows: state.hide_network,
|
hide_follows: state.hide_network,
|
||||||
hide_followers_count: state.hide_network,
|
hide_followers_count: state.hide_network,
|
||||||
hide_follows_count: state.hide_network,
|
hide_follows_count: state.hide_network,
|
||||||
|
birth_date: state.birthDate?.toISOString().slice(0, 10),
|
||||||
}, this.getFieldParams().toJS());
|
}, this.getFieldParams().toJS());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +235,12 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleBirthDateChange = (birthDate) => {
|
||||||
|
this.setState({
|
||||||
|
birthDate,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handleAddField = () => {
|
handleAddField = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
fields: this.state.fields.push(ImmutableMap({ name: '', value: '' })),
|
fields: this.state.fields.push(ImmutableMap({ name: '', value: '' })),
|
||||||
|
@ -237,8 +255,15 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isDateValid = date => {
|
||||||
|
const { minAge } = this.props;
|
||||||
|
const allowedDate = new Date();
|
||||||
|
allowedDate.setDate(allowedDate.getDate() - minAge);
|
||||||
|
return date && allowedDate.setHours(0, 0, 0, 0) >= new Date(date).setHours(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { intl, maxFields, account, verifiedCanEditName, supportsEmailList } = this.props;
|
const { intl, maxFields, account, verifiedCanEditName, supportsEmailList, supportsBirthDates } = this.props;
|
||||||
const verified = isVerified(account);
|
const verified = isVerified(account);
|
||||||
const canEditName = verifiedCanEditName || !verified;
|
const canEditName = verifiedCanEditName || !verified;
|
||||||
|
|
||||||
|
@ -267,6 +292,23 @@ class EditProfile extends ImmutablePureComponent {
|
||||||
onChange={this.handleTextChange}
|
onChange={this.handleTextChange}
|
||||||
rows={3}
|
rows={3}
|
||||||
/>
|
/>
|
||||||
|
{supportsBirthDates && (
|
||||||
|
<div className='datepicker'>
|
||||||
|
<div className='datepicker__hint'>
|
||||||
|
<FormattedMessage id='edit_profile.fields.birth_date_label' defaultMessage='Birth date' />
|
||||||
|
</div>
|
||||||
|
<div className='datepicker__input'>
|
||||||
|
<DatePicker
|
||||||
|
selected={this.state.birthDate}
|
||||||
|
dateFormat='d MMMM yyyy'
|
||||||
|
wrapperClassName='react-datepicker-wrapper'
|
||||||
|
onChange={this.handleBirthDateChange}
|
||||||
|
placeholderText={intl.formatMessage(messages.birthDatePlaceholder)}
|
||||||
|
filterDate={this.isDateValid}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<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.makePreviewAccount()} />
|
||||||
|
|
|
@ -103,6 +103,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
||||||
const deactivated = !account.getIn(['pleroma', 'is_active'], true);
|
const deactivated = !account.getIn(['pleroma', 'is_active'], true);
|
||||||
const displayNameHtml = deactivated ? { __html: intl.formatMessage(messages.deactivated) } : { __html: account.get('display_name_html') };
|
const displayNameHtml = deactivated ? { __html: intl.formatMessage(messages.deactivated) } : { __html: account.get('display_name_html') };
|
||||||
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' });
|
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' });
|
||||||
|
const birthDate = account.getIn(['pleroma', 'birth_date']) && intl.formatDate(account.getIn(['pleroma', 'birth_date']), { day: 'numeric', month: 'long', year: 'numeric' });
|
||||||
const verified = isVerified(account);
|
const verified = isVerified(account);
|
||||||
const badges = this.getBadges();
|
const badges = this.getBadges();
|
||||||
|
|
||||||
|
@ -150,6 +151,15 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
|
{birthDate && <div className='profile-info-panel-content__birth-date'>
|
||||||
|
<Icon src={require('@tabler/icons/icons/ballon.svg')} />
|
||||||
|
<FormattedMessage
|
||||||
|
id='account.birth_date' defaultMessage='Birth date: {date}' values={{
|
||||||
|
date: birthDate,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
|
|
||||||
<ProfileStats
|
<ProfileStats
|
||||||
className='profile-info-panel-content__stats'
|
className='profile-info-panel-content__stats'
|
||||||
account={account}
|
account={account}
|
||||||
|
|
|
@ -78,6 +78,7 @@ export const getFeatures = createSelector([
|
||||||
remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
remoteInteractionsAPI: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
||||||
explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'),
|
explicitAddressing: v.software === PLEROMA && gte(v.version, '1.0.0'),
|
||||||
accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
accountEndorsements: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
||||||
|
birthDates: v.software === PLEROMA && gte(v.version, '2.4.50'),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__join-date {
|
&__join-date,
|
||||||
|
&__birth-date {
|
||||||
display: flex;
|
display: flex;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--primary-text-color--faint);
|
color: var(--primary-text-color--faint);
|
||||||
|
|
|
@ -634,6 +634,43 @@ code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.datepicker {
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&__hint {
|
||||||
|
padding-bottom: 0;
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-datepicker {
|
||||||
|
&__navigation {
|
||||||
|
display: flex;
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
margin: 0;
|
||||||
|
background: none;
|
||||||
|
line-height: 24px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__input-container {
|
||||||
|
border: 1px solid var(--highlight-text-color);
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.block-icon {
|
.block-icon {
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"@sentry/browser": "^6.12.0",
|
"@sentry/browser": "^6.12.0",
|
||||||
"@sentry/react": "^6.12.0",
|
"@sentry/react": "^6.12.0",
|
||||||
"@sentry/tracing": "^6.12.0",
|
"@sentry/tracing": "^6.12.0",
|
||||||
"@tabler/icons": "^1.41.2",
|
"@tabler/icons": "^1.53.0",
|
||||||
"array-includes": "^3.0.3",
|
"array-includes": "^3.0.3",
|
||||||
"autoprefixer": "^10.0.0",
|
"autoprefixer": "^10.0.0",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
|
|
|
@ -1519,10 +1519,10 @@
|
||||||
remark "^13.0.0"
|
remark "^13.0.0"
|
||||||
unist-util-find-all-after "^3.0.2"
|
unist-util-find-all-after "^3.0.2"
|
||||||
|
|
||||||
"@tabler/icons@^1.41.2":
|
"@tabler/icons@^1.53.0":
|
||||||
version "1.41.2"
|
version "1.53.0"
|
||||||
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.41.2.tgz#effccbb261539b68609cc7dc660a058683170ee1"
|
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-1.53.0.tgz#51536e01b343cfaf26b701df306b2c0369769e3c"
|
||||||
integrity sha512-X6cQmMC24hiwg0p2BzasvU3IeCCdOk0f/9d6gNNtJM4lzG2TCloTns1bVvU5MAFkITGukxUqjPFE3Ecd6kGsfw==
|
integrity sha512-Skk1BqXEOEhiRsXJgZBYtjFa/+4dMSFA5UyzTUW20oyyUSd3iizhEWrYt0jT87iFu771gWoqVV2/OGobBcGjgQ==
|
||||||
|
|
||||||
"@tootallnate/once@1":
|
"@tootallnate/once@1":
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
|
|
Ładowanie…
Reference in New Issue