Support data import on GoToSocial
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@@ -38,10 +38,10 @@ const messages = defineMessages({
|
||||
mutesSuccess: { id: 'import_data.success.mutes', defaultMessage: 'Mutes imported successfully' },
|
||||
});
|
||||
|
||||
const importFollows = (list: File | string) =>
|
||||
const importFollows = (list: File | string, overwrite?: boolean) =>
|
||||
(dispatch: React.Dispatch<ImportDataActions>, getState: () => RootState) => {
|
||||
dispatch({ type: IMPORT_FOLLOWS_REQUEST });
|
||||
return getClient(getState).settings.importFollows(list).then(response => {
|
||||
return getClient(getState).settings.importFollows(list, overwrite ? 'overwrite' : 'merge').then(response => {
|
||||
toast.success(messages.followersSuccess);
|
||||
dispatch({ type: IMPORT_FOLLOWS_SUCCESS, response });
|
||||
}).catch(error => {
|
||||
@@ -49,10 +49,10 @@ const importFollows = (list: File | string) =>
|
||||
});
|
||||
};
|
||||
|
||||
const importBlocks = (list: File | string) =>
|
||||
const importBlocks = (list: File | string, overwrite?: boolean) =>
|
||||
(dispatch: React.Dispatch<ImportDataActions>, getState: () => RootState) => {
|
||||
dispatch({ type: IMPORT_BLOCKS_REQUEST });
|
||||
return getClient(getState).settings.importBlocks(list).then(response => {
|
||||
return getClient(getState).settings.importBlocks(list, overwrite ? 'overwrite' : 'merge').then(response => {
|
||||
toast.success(messages.blocksSuccess);
|
||||
dispatch({ type: IMPORT_BLOCKS_SUCCESS, response });
|
||||
}).catch(error => {
|
||||
|
||||
@@ -133,7 +133,7 @@ const accountToCredentials = (account: Account): AccountCredentials => {
|
||||
note: account.__meta.source?.note ?? '',
|
||||
fields_attributes: [...account.__meta.source?.fields ?? []],
|
||||
stranger_notifications: account.__meta.pleroma?.notification_settings?.block_from_strangers === true,
|
||||
accepts_email_list: account.__meta.pleroma.accepts_email_list === true,
|
||||
accepts_email_list: account.__meta.pleroma?.accepts_email_list === true,
|
||||
hide_followers: hideNetwork,
|
||||
hide_follows: hideNetwork,
|
||||
hide_followers_count: hideNetwork,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React, { useState } from 'react';
|
||||
import { MessageDescriptor, useIntl } from 'react-intl';
|
||||
import { FormattedMessage, MessageDescriptor, useIntl } from 'react-intl';
|
||||
|
||||
import { Button, FileInput, Form, FormActions, FormGroup, Text } from 'soapbox/components/ui';
|
||||
import { useAppDispatch } from 'soapbox/hooks';
|
||||
import List, { ListItem } from 'soapbox/components/list';
|
||||
import { Button, FileInput, Form, FormActions, FormGroup, Text, Toggle } from 'soapbox/components/ui';
|
||||
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
|
||||
|
||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||
|
||||
@@ -12,20 +13,23 @@ interface IDataImporter {
|
||||
input_hint: MessageDescriptor;
|
||||
submit: MessageDescriptor;
|
||||
};
|
||||
action: (list: File | string) => (dispatch: AppDispatch, getState: () => RootState) => Promise<void>;
|
||||
action: (list: File | string, overwrite?: boolean) => (dispatch: AppDispatch, getState: () => RootState) => Promise<void>;
|
||||
accept?: string;
|
||||
allowOverwrite?: boolean;
|
||||
}
|
||||
|
||||
const DataImporter: React.FC<IDataImporter> = ({ messages, action, accept = '.csv,text/csv' }) => {
|
||||
const DataImporter: React.FC<IDataImporter> = ({ messages, action, accept = '.csv,text/csv', allowOverwrite }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
const features = useFeatures();
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [file, setFile] = useState<File | null | undefined>(null);
|
||||
const [overwrite, setOverwrite] = useState(false);
|
||||
|
||||
const handleSubmit: React.FormEventHandler = (event) => {
|
||||
setIsLoading(true);
|
||||
dispatch(action(file!)).then(() => {
|
||||
dispatch(action(file!, overwrite)).then(() => {
|
||||
setIsLoading(false);
|
||||
}).catch(() => {
|
||||
setIsLoading(false);
|
||||
@@ -51,6 +55,20 @@ const DataImporter: React.FC<IDataImporter> = ({ messages, action, accept = '.cs
|
||||
required
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{features.importOverwrite && (
|
||||
<List>
|
||||
<ListItem
|
||||
label={<FormattedMessage id='import_data.overwrite' defaultMessage='Overwrite instead of appending' />}
|
||||
>
|
||||
<Toggle
|
||||
checked={overwrite}
|
||||
onChange={({ target }) => setOverwrite(target.checked)}
|
||||
/>
|
||||
</ListItem>
|
||||
</List>
|
||||
)}
|
||||
|
||||
<FormActions>
|
||||
<Button type='submit' theme='primary' disabled={isLoading}>
|
||||
{intl.formatMessage(messages.submit)}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
importMutes,
|
||||
} from 'soapbox/actions/import-data';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
import { useFeatures } from 'soapbox/hooks';
|
||||
|
||||
import DataImporter from './components/data-importer';
|
||||
|
||||
@@ -35,12 +36,13 @@ const muteMessages = defineMessages({
|
||||
|
||||
const ImportData = () => {
|
||||
const intl = useIntl();
|
||||
const features = useFeatures();
|
||||
|
||||
return (
|
||||
<Column label={intl.formatMessage(messages.heading)}>
|
||||
<DataImporter action={importFollows} messages={followMessages} />
|
||||
<DataImporter action={importBlocks} messages={blockMessages} />
|
||||
<DataImporter action={importMutes} messages={muteMessages} />
|
||||
{features.importFollows && <DataImporter action={importFollows} messages={followMessages} allowOverwrite />}
|
||||
{features.importBlocks && <DataImporter action={importBlocks} messages={blockMessages} allowOverwrite />}
|
||||
{features.importMutes && <DataImporter action={importMutes} messages={muteMessages} />}
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -140,7 +140,9 @@ const Settings = () => {
|
||||
</CardBody>
|
||||
|
||||
{any([
|
||||
features.importData,
|
||||
features.importBlocks,
|
||||
features.importFollows,
|
||||
features.importMutes,
|
||||
features.exportData,
|
||||
features.accountBackups,
|
||||
features.federating && features.accountMoving,
|
||||
@@ -154,7 +156,7 @@ const Settings = () => {
|
||||
|
||||
<CardBody>
|
||||
<List>
|
||||
{features.importData && (
|
||||
{(features.importBlocks || features.importFollows || features.importMutes) && (
|
||||
<ListItem label={intl.formatMessage(messages.importData)} to='/settings/import' />
|
||||
)}
|
||||
|
||||
|
||||
@@ -288,7 +288,7 @@ const SwitchingColumnsArea: React.FC<ISwitchingColumnsArea> = ({ children }) =>
|
||||
|
||||
<WrappedRoute path='/settings/profile' page={DefaultPage} component={EditProfile} content={children} />
|
||||
{features.exportData && <WrappedRoute path='/settings/export' page={DefaultPage} component={ExportData} content={children} />}
|
||||
{features.importData && <WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />}
|
||||
{(features.importBlocks || features.importFollows || features.importMutes) && <WrappedRoute path='/settings/import' page={DefaultPage} component={ImportData} content={children} />}
|
||||
{features.manageAccountAliases && <WrappedRoute path='/settings/aliases' page={DefaultPage} component={Aliases} content={children} />}
|
||||
{features.accountMoving && <WrappedRoute path='/settings/migration' page={DefaultPage} component={Migration} content={children} />}
|
||||
{features.accountBackups && <WrappedRoute path='/settings/backups' page={DefaultPage} component={Backups} content={children} />}
|
||||
|
||||
Reference in New Issue
Block a user