Merge branch 'edit-profile-fixes' into 'develop'

Edit profile fixes

Closes #1018

See merge request soapbox-pub/soapbox-fe!1597
This commit is contained in:
Alex Gleason 2022-07-06 15:07:27 +00:00
commit d222eb2a0c
7 changed files with 57 additions and 46 deletions

View file

@ -6,7 +6,7 @@ import api from '../api';
import { loadCredentials } from './auth';
import { importFetchedAccount } from './importer';
import type { AxiosError } from 'axios';
import type { AxiosError, AxiosRequestHeaders } from 'axios';
import type { AppDispatch, RootState } from 'soapbox/store';
import type { APIEntity } from 'soapbox/types/entities';
@ -62,12 +62,16 @@ const persistAuthAccount = (account: APIEntity, params: Record<string, any>) =>
}
};
const patchMe = (params: Record<string, any>) =>
const patchMe = (params: Record<string, any>, isFormData = false) =>
(dispatch: AppDispatch, getState: () => RootState) => {
dispatch(patchMeRequest());
const headers: AxiosRequestHeaders = isFormData ? {
'Content-Type': 'multipart/form-data',
} : {};
return api(getState)
.patch('/api/v1/accounts/update_credentials', params)
.patch('/api/v1/accounts/update_credentials', params, { headers })
.then(response => {
persistAuthAccount(response.data, params);
dispatch(patchMeSuccess(response.data));

View file

@ -4,9 +4,19 @@ import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { updateNotificationSettings } from 'soapbox/actions/accounts';
import { patchMe } from 'soapbox/actions/me';
import snackbar from 'soapbox/actions/snackbar';
import BirthdayInput from 'soapbox/components/birthday_input';
import List, { ListItem } from 'soapbox/components/list';
import { Button, Column, Form, FormActions, FormGroup, Input, Textarea, HStack, Toggle, FileInput } from 'soapbox/components/ui';
import {
Button,
Column,
FileInput,
Form,
FormActions,
FormGroup,
HStack,
Input,
Textarea,
Toggle,
} from 'soapbox/components/ui';
import Streamfield, { StreamfieldComponent } from 'soapbox/components/ui/streamfield/streamfield';
import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures } from 'soapbox/hooks';
import { normalizeAccount } from 'soapbox/normalizers';
@ -25,25 +35,6 @@ const hidesNetwork = (account: Account): boolean => {
return Boolean(hide_followers && hide_follows && hide_followers_count && hide_follows_count);
};
/** Converts JSON objects to FormData. */
// https://stackoverflow.com/a/60286175/8811886
// @ts-ignore
const toFormData = (f => f(f))(h => f => f(x => h(h)(f)(x)))(f => fd => pk => d => {
if (d instanceof Object) {
// eslint-disable-next-line consistent-return
Object.keys(d).forEach(k => {
const v = d[k];
if (pk) k = `${pk}[${k}]`;
if (v instanceof Object && !(v instanceof Date) && !(v instanceof File)) {
return f(fd)(k)(v);
} else {
fd.append(k, v);
}
});
}
return fd;
})(new FormData())();
const messages = defineMessages({
heading: { id: 'column.edit_profile', defaultMessage: 'Edit profile' },
header: { id: 'edit_profile.header', defaultMessage: 'Edit Profile' },
@ -205,9 +196,8 @@ const EditProfile: React.FC = () => {
const handleSubmit: React.FormEventHandler = (event) => {
const promises = [];
const formData = toFormData(data);
promises.push(dispatch(patchMe(formData)));
promises.push(dispatch(patchMe(data, true)));
if (features.muteStrangers) {
promises.push(
@ -242,10 +232,6 @@ const EditProfile: React.FC = () => {
};
};
const handleBirthdayChange = (date: string) => {
updateData('birthday', date);
};
const handleHideNetworkChange: React.ChangeEventHandler<HTMLInputElement> = e => {
const hide = e.target.checked;
@ -329,9 +315,12 @@ const EditProfile: React.FC = () => {
<FormGroup
labelText={<FormattedMessage id='edit_profile.fields.birthday_label' defaultMessage='Birthday' />}
>
<BirthdayInput
<Input
type='text'
value={data.birthday}
onChange={handleBirthdayChange}
onChange={handleTextChange('birthday')}
placeholder='YYYY-MM-DD'
pattern='\d{4}-\d{2}-\d{2}'
/>
</FormGroup>
)}

View file

@ -47,6 +47,13 @@ describe('normalizeAccount()', () => {
expect(result.birthday).toEqual('1993-07-03');
});
it('normalizes undefined birthday to empty string', () => {
const account = require('soapbox/__fixtures__/mastodon-account.json');
const result = normalizeAccount(account);
expect(result.birthday).toEqual('');
});
it('normalizes Pleroma legacy fields', () => {
const account = require('soapbox/__fixtures__/pleroma-2.2.2-account.json');
const result = normalizeAccount(account);

View file

@ -24,7 +24,7 @@ export const AccountRecord = ImmutableRecord({
acct: '',
avatar: '',
avatar_static: '',
birthday: undefined as string | undefined,
birthday: '',
bot: false,
created_at: new Date(),
discoverable: false,
@ -261,6 +261,12 @@ const normalizeDiscoverable = (account: ImmutableMap<string, any>) => {
return account.set('discoverable', discoverable);
};
/** Normalize undefined/null birthday to empty string. */
const fixBirthday = (account: ImmutableMap<string, any>) => {
const birthday = account.get('birthday');
return account.set('birthday', birthday || '');
};
export const normalizeAccount = (account: Record<string, any>) => {
return AccountRecord(
ImmutableMap(fromJS(account)).withMutations(account => {
@ -280,6 +286,7 @@ export const normalizeAccount = (account: Record<string, any>) => {
addStaffFields(account);
fixUsername(account);
fixDisplayName(account);
fixBirthday(account);
addInternalFields(account);
}),
);

View file

@ -148,9 +148,7 @@ const getInstanceFeatures = (instance: Instance) => {
* @see POST /api/v1/accounts
* @see PATCH /api/v1/accounts/update_credentials
*/
// birthdays: v.software === PLEROMA && gte(v.version, '2.4.50'),
// FIXME: temporarily disabled until they can be deleted on the backend.
birthdays: false,
birthdays: v.software === PLEROMA && v.build === SOAPBOX && gte(v.version, '2.4.50'),
/** Whether people who blocked you are visible through the API. */
blockersVisible: features.includes('blockers_visible'),

View file

@ -91,7 +91,7 @@
"@types/uuid": "^8.3.4",
"array-includes": "^3.1.5",
"autoprefixer": "^10.4.2",
"axios": "^0.27.2",
"axios": "^1.0.0-alpha.1",
"axios-mock-adapter": "^1.21.1",
"babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4",

View file

@ -3506,13 +3506,14 @@ axios-mock-adapter@^1.21.1:
fast-deep-equal "^3.1.3"
is-buffer "^2.0.5"
axios@^0.27.2:
version "0.27.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
axios@^1.0.0-alpha.1:
version "1.0.0-alpha.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.0.0-alpha.1.tgz#ce69c17ca7605d01787ca754dd906e6fccdf71ee"
integrity sha512-p+meG161943WT+K7sJYquHR46xxi/z0tk7vnSmEf/LrfEAyiP+0uTMMYk1OEo1IRF18oGRhnFxN1y8fLcXaTMw==
dependencies:
follow-redirects "^1.14.9"
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
axobject-query@^2.2.0:
version "2.2.0"
@ -5827,10 +5828,10 @@ follow-redirects@^1.0.0:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
follow-redirects@^1.14.9:
version "1.14.9"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
follow-redirects@^1.15.0:
version "1.15.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
foreach@^2.0.5:
version "2.0.5"
@ -9501,6 +9502,11 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
psl@^1.1.33:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"