[Glitch] Merge collection settings into single editor page
Port c118ff708f to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
@@ -13,8 +13,9 @@ import { CollectionMenu } from './collection_menu';
|
|||||||
|
|
||||||
export const CollectionMetaData: React.FC<{
|
export const CollectionMetaData: React.FC<{
|
||||||
collection: ApiCollectionJSON;
|
collection: ApiCollectionJSON;
|
||||||
|
extended?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
}> = ({ collection, className }) => {
|
}> = ({ collection, extended, className }) => {
|
||||||
return (
|
return (
|
||||||
<ul className={classNames(classes.metaList, className)}>
|
<ul className={classNames(classes.metaList, className)}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
@@ -23,6 +24,30 @@ export const CollectionMetaData: React.FC<{
|
|||||||
values={{ count: collection.item_count }}
|
values={{ count: collection.item_count }}
|
||||||
tagName='li'
|
tagName='li'
|
||||||
/>
|
/>
|
||||||
|
{extended && (
|
||||||
|
<>
|
||||||
|
{collection.discoverable ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_public'
|
||||||
|
defaultMessage='Public'
|
||||||
|
tagName='li'
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_unlisted'
|
||||||
|
defaultMessage='Unlisted'
|
||||||
|
tagName='li'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{collection.sensitive && (
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.sensitive'
|
||||||
|
defaultMessage='Sensitive'
|
||||||
|
tagName='li'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='collections.last_updated_at'
|
id='collections.last_updated_at'
|
||||||
defaultMessage='Last updated: {date}'
|
defaultMessage='Last updated: {date}'
|
||||||
|
|||||||
@@ -55,10 +55,6 @@ export const CollectionMenu: React.FC<{
|
|||||||
text: intl.formatMessage(editorMessages.editDetails),
|
text: intl.formatMessage(editorMessages.editDetails),
|
||||||
to: `/collections/${id}/edit/details`,
|
to: `/collections/${id}/edit/details`,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: intl.formatMessage(editorMessages.editSettings),
|
|
||||||
to: `/collections/${id}/edit/settings`,
|
|
||||||
},
|
|
||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
text: intl.formatMessage(messages.delete),
|
text: intl.formatMessage(messages.delete),
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ const CollectionHeader: React.FC<{ collection: ApiCollectionJSON }> = ({
|
|||||||
{description && <p className={classes.description}>{description}</p>}
|
{description && <p className={classes.description}>{description}</p>}
|
||||||
<AuthorNote id={collection.account_id} />
|
<AuthorNote id={collection.account_id} />
|
||||||
<CollectionMetaData
|
<CollectionMetaData
|
||||||
|
extended
|
||||||
collection={collection}
|
collection={collection}
|
||||||
className={classes.metaData}
|
className={classes.metaData}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
|
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { isFulfilled } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ApiCollectionJSON,
|
ApiCollectionJSON,
|
||||||
ApiCreateCollectionPayload,
|
ApiCreateCollectionPayload,
|
||||||
@@ -11,11 +13,17 @@ import type {
|
|||||||
} from 'flavours/glitch/api_types/collections';
|
} from 'flavours/glitch/api_types/collections';
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import {
|
import {
|
||||||
|
CheckboxField,
|
||||||
|
Fieldset,
|
||||||
FormStack,
|
FormStack,
|
||||||
|
RadioButtonField,
|
||||||
TextAreaField,
|
TextAreaField,
|
||||||
} from 'flavours/glitch/components/form_fields';
|
} from 'flavours/glitch/components/form_fields';
|
||||||
import { TextInputField } from 'flavours/glitch/components/form_fields/text_input_field';
|
import { TextInputField } from 'flavours/glitch/components/form_fields/text_input_field';
|
||||||
import { updateCollection } from 'flavours/glitch/reducers/slices/collections';
|
import {
|
||||||
|
createCollection,
|
||||||
|
updateCollection,
|
||||||
|
} from 'flavours/glitch/reducers/slices/collections';
|
||||||
import { useAppDispatch } from 'flavours/glitch/store';
|
import { useAppDispatch } from 'flavours/glitch/store';
|
||||||
|
|
||||||
import type { TempCollectionState } from './state';
|
import type { TempCollectionState } from './state';
|
||||||
@@ -30,12 +38,21 @@ export const CollectionDetails: React.FC<{
|
|||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const location = useLocation<TempCollectionState>();
|
const location = useLocation<TempCollectionState>();
|
||||||
|
|
||||||
const { id, initialName, initialDescription, initialTopic, initialItemIds } =
|
const {
|
||||||
getCollectionEditorState(collection, location.state);
|
id,
|
||||||
|
initialName,
|
||||||
|
initialDescription,
|
||||||
|
initialTopic,
|
||||||
|
initialItemIds,
|
||||||
|
initialDiscoverable,
|
||||||
|
initialSensitive,
|
||||||
|
} = getCollectionEditorState(collection, location.state);
|
||||||
|
|
||||||
const [name, setName] = useState(initialName);
|
const [name, setName] = useState(initialName);
|
||||||
const [description, setDescription] = useState(initialDescription);
|
const [description, setDescription] = useState(initialDescription);
|
||||||
const [topic, setTopic] = useState(initialTopic);
|
const [topic, setTopic] = useState(initialTopic);
|
||||||
|
const [discoverable, setDiscoverable] = useState(initialDiscoverable);
|
||||||
|
const [sensitive, setSensitive] = useState(initialSensitive);
|
||||||
|
|
||||||
const handleNameChange = useCallback(
|
const handleNameChange = useCallback(
|
||||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@@ -58,6 +75,20 @@ export const CollectionDetails: React.FC<{
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDiscoverableChange = useCallback(
|
||||||
|
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setDiscoverable(event.target.value === 'public');
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSensitiveChange = useCallback(
|
||||||
|
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setSensitive(event.target.checked);
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
const handleSubmit = useCallback(
|
||||||
(e: React.FormEvent) => {
|
(e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -68,108 +99,208 @@ export const CollectionDetails: React.FC<{
|
|||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
tag_name: topic || null,
|
tag_name: topic || null,
|
||||||
|
discoverable,
|
||||||
|
sensitive,
|
||||||
};
|
};
|
||||||
|
|
||||||
void dispatch(updateCollection({ payload })).then(() => {
|
void dispatch(updateCollection({ payload })).then(() => {
|
||||||
history.push(`/collections/${id}`);
|
history.goBack();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const payload: Partial<ApiCreateCollectionPayload> = {
|
const payload: ApiCreateCollectionPayload = {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
tag_name: topic || null,
|
discoverable,
|
||||||
|
sensitive,
|
||||||
account_ids: initialItemIds,
|
account_ids: initialItemIds,
|
||||||
};
|
};
|
||||||
|
if (topic) {
|
||||||
|
payload.tag_name = topic;
|
||||||
|
}
|
||||||
|
|
||||||
history.replace('/collections/new', payload);
|
void dispatch(
|
||||||
history.push('/collections/new/settings', payload);
|
createCollection({
|
||||||
|
payload,
|
||||||
|
}),
|
||||||
|
).then((result) => {
|
||||||
|
if (isFulfilled(result)) {
|
||||||
|
history.replace(
|
||||||
|
`/collections/${result.payload.collection.id}/edit/details`,
|
||||||
|
);
|
||||||
|
history.push(`/collections/${result.payload.collection.id}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[id, name, description, topic, dispatch, history, initialItemIds],
|
[
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
topic,
|
||||||
|
discoverable,
|
||||||
|
sensitive,
|
||||||
|
dispatch,
|
||||||
|
history,
|
||||||
|
initialItemIds,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormStack as='form' onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit} className={classes.form}>
|
||||||
{!id && (
|
<FormStack className={classes.formFieldStack}>
|
||||||
<WizardStepHeader
|
{!id && (
|
||||||
step={2}
|
<WizardStepHeader
|
||||||
title={
|
step={2}
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.create.basic_details_title'
|
||||||
|
defaultMessage='Basic details'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<TextInputField
|
||||||
|
required
|
||||||
|
label={
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='collections.create.basic_details_title'
|
id='collections.collection_name'
|
||||||
defaultMessage='Basic details'
|
defaultMessage='Name'
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
hint={
|
||||||
)}
|
|
||||||
<TextInputField
|
|
||||||
required
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.collection_name'
|
|
||||||
defaultMessage='Name'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.name_length_hint'
|
|
||||||
defaultMessage='40 characters limit'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value={name}
|
|
||||||
onChange={handleNameChange}
|
|
||||||
maxLength={40}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextAreaField
|
|
||||||
required
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.collection_description'
|
|
||||||
defaultMessage='Description'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.description_length_hint'
|
|
||||||
defaultMessage='100 characters limit'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value={description}
|
|
||||||
onChange={handleDescriptionChange}
|
|
||||||
maxLength={100}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextInputField
|
|
||||||
required={false}
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.collection_topic'
|
|
||||||
defaultMessage='Topic'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.topic_hint'
|
|
||||||
defaultMessage='Add a hashtag that helps others understand the main topic of this collection.'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value={topic}
|
|
||||||
onChange={handleTopicChange}
|
|
||||||
maxLength={40}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={classes.actionWrapper}>
|
|
||||||
<Button type='submit'>
|
|
||||||
{id ? (
|
|
||||||
<FormattedMessage id='lists.save' defaultMessage='Save' />
|
|
||||||
) : (
|
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='collections.continue'
|
id='collections.name_length_hint'
|
||||||
defaultMessage='Continue'
|
defaultMessage='40 characters limit'
|
||||||
/>
|
/>
|
||||||
)}
|
}
|
||||||
</Button>
|
value={name}
|
||||||
|
onChange={handleNameChange}
|
||||||
|
maxLength={40}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextAreaField
|
||||||
|
required
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.collection_description'
|
||||||
|
defaultMessage='Description'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.description_length_hint'
|
||||||
|
defaultMessage='100 characters limit'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={description}
|
||||||
|
onChange={handleDescriptionChange}
|
||||||
|
maxLength={100}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInputField
|
||||||
|
required={false}
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.collection_topic'
|
||||||
|
defaultMessage='Topic'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.topic_hint'
|
||||||
|
defaultMessage='Add a hashtag that helps others understand the main topic of this collection.'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={topic}
|
||||||
|
onChange={handleTopicChange}
|
||||||
|
maxLength={40}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Fieldset
|
||||||
|
legend={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_title'
|
||||||
|
defaultMessage='Visibility'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<RadioButtonField
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_public'
|
||||||
|
defaultMessage='Public'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_public_hint'
|
||||||
|
defaultMessage='Discoverable in search results and other areas where recommendations appear.'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value='public'
|
||||||
|
checked={discoverable}
|
||||||
|
onChange={handleDiscoverableChange}
|
||||||
|
/>
|
||||||
|
<RadioButtonField
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_unlisted'
|
||||||
|
defaultMessage='Unlisted'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.visibility_unlisted_hint'
|
||||||
|
defaultMessage='Visible to anyone with a link. Hidden from search results and recommendations.'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value='unlisted'
|
||||||
|
checked={!discoverable}
|
||||||
|
onChange={handleDiscoverableChange}
|
||||||
|
/>
|
||||||
|
</Fieldset>
|
||||||
|
|
||||||
|
<Fieldset
|
||||||
|
legend={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.content_warning'
|
||||||
|
defaultMessage='Content warning'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<CheckboxField
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.mark_as_sensitive'
|
||||||
|
defaultMessage='Mark as sensitive'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
hint={
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.mark_as_sensitive_hint'
|
||||||
|
defaultMessage="Hides the collection's description and accounts behind a content warning. The collection name will still be visible."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
checked={sensitive}
|
||||||
|
onChange={handleSensitiveChange}
|
||||||
|
/>
|
||||||
|
</Fieldset>
|
||||||
|
</FormStack>
|
||||||
|
|
||||||
|
<div className={classes.stickyFooter}>
|
||||||
|
<div className={classes.actionWrapper}>
|
||||||
|
<Button type='submit'>
|
||||||
|
{id ? (
|
||||||
|
<FormattedMessage id='lists.save' defaultMessage='Save' />
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id='collections.create_collection'
|
||||||
|
defaultMessage='Create collection'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FormStack>
|
</form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
|||||||
|
|
||||||
import { CollectionAccounts } from './accounts';
|
import { CollectionAccounts } from './accounts';
|
||||||
import { CollectionDetails } from './details';
|
import { CollectionDetails } from './details';
|
||||||
import { CollectionSettings } from './settings';
|
|
||||||
|
|
||||||
export const messages = defineMessages({
|
export const messages = defineMessages({
|
||||||
create: {
|
create: {
|
||||||
@@ -34,20 +33,12 @@ export const messages = defineMessages({
|
|||||||
},
|
},
|
||||||
editDetails: {
|
editDetails: {
|
||||||
id: 'collections.edit_details',
|
id: 'collections.edit_details',
|
||||||
defaultMessage: 'Edit basic details',
|
defaultMessage: 'Edit details',
|
||||||
},
|
},
|
||||||
manageAccounts: {
|
manageAccounts: {
|
||||||
id: 'collections.manage_accounts',
|
id: 'collections.manage_accounts',
|
||||||
defaultMessage: 'Manage accounts',
|
defaultMessage: 'Manage accounts',
|
||||||
},
|
},
|
||||||
manageAccountsLong: {
|
|
||||||
id: 'collections.manage_accounts_in_collection',
|
|
||||||
defaultMessage: 'Manage accounts in this collection',
|
|
||||||
},
|
|
||||||
editSettings: {
|
|
||||||
id: 'collections.edit_settings',
|
|
||||||
defaultMessage: 'Edit settings',
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function usePageTitle(id: string | undefined) {
|
function usePageTitle(id: string | undefined) {
|
||||||
@@ -62,8 +53,6 @@ function usePageTitle(id: string | undefined) {
|
|||||||
return messages.manageAccounts;
|
return messages.manageAccounts;
|
||||||
} else if (matchPath(location.pathname, { path: `${path}/details` })) {
|
} else if (matchPath(location.pathname, { path: `${path}/details` })) {
|
||||||
return messages.editDetails;
|
return messages.editDetails;
|
||||||
} else if (matchPath(location.pathname, { path: `${path}/settings` })) {
|
|
||||||
return messages.editSettings;
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('No page title defined for route');
|
throw new Error('No page title defined for route');
|
||||||
}
|
}
|
||||||
@@ -117,11 +106,6 @@ export const CollectionEditorPage: React.FC<{
|
|||||||
// eslint-disable-next-line react/jsx-no-bind
|
// eslint-disable-next-line react/jsx-no-bind
|
||||||
render={() => <CollectionDetails collection={collection} />}
|
render={() => <CollectionDetails collection={collection} />}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path={`${path}/settings`}
|
|
||||||
// eslint-disable-next-line react/jsx-no-bind
|
|
||||||
render={() => <CollectionSettings collection={collection} />}
|
|
||||||
/>
|
|
||||||
</Switch>
|
</Switch>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,199 +0,0 @@
|
|||||||
import { useCallback, useState } from 'react';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
|
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { isFulfilled } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
import type {
|
|
||||||
ApiCollectionJSON,
|
|
||||||
ApiCreateCollectionPayload,
|
|
||||||
ApiUpdateCollectionPayload,
|
|
||||||
} from 'flavours/glitch/api_types/collections';
|
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
|
||||||
import {
|
|
||||||
Fieldset,
|
|
||||||
FormStack,
|
|
||||||
CheckboxField,
|
|
||||||
RadioButtonField,
|
|
||||||
} from 'flavours/glitch/components/form_fields';
|
|
||||||
import {
|
|
||||||
createCollection,
|
|
||||||
updateCollection,
|
|
||||||
} from 'flavours/glitch/reducers/slices/collections';
|
|
||||||
import { useAppDispatch } from 'flavours/glitch/store';
|
|
||||||
|
|
||||||
import type { TempCollectionState } from './state';
|
|
||||||
import { getCollectionEditorState } from './state';
|
|
||||||
import classes from './styles.module.scss';
|
|
||||||
import { WizardStepHeader } from './wizard_step_header';
|
|
||||||
|
|
||||||
export const CollectionSettings: React.FC<{
|
|
||||||
collection?: ApiCollectionJSON | null;
|
|
||||||
}> = ({ collection }) => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const history = useHistory();
|
|
||||||
const location = useLocation<TempCollectionState>();
|
|
||||||
|
|
||||||
const { id, initialDiscoverable, initialSensitive, ...editorState } =
|
|
||||||
getCollectionEditorState(collection, location.state);
|
|
||||||
|
|
||||||
const [discoverable, setDiscoverable] = useState(initialDiscoverable);
|
|
||||||
const [sensitive, setSensitive] = useState(initialSensitive);
|
|
||||||
|
|
||||||
const handleDiscoverableChange = useCallback(
|
|
||||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setDiscoverable(event.target.value === 'public');
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSensitiveChange = useCallback(
|
|
||||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setSensitive(event.target.checked);
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSubmit = useCallback(
|
|
||||||
(e: React.FormEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (id) {
|
|
||||||
const payload: ApiUpdateCollectionPayload = {
|
|
||||||
id,
|
|
||||||
discoverable,
|
|
||||||
sensitive,
|
|
||||||
};
|
|
||||||
|
|
||||||
void dispatch(updateCollection({ payload })).then(() => {
|
|
||||||
history.push(`/collections/${id}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const payload: ApiCreateCollectionPayload = {
|
|
||||||
name: editorState.initialName,
|
|
||||||
description: editorState.initialDescription,
|
|
||||||
discoverable,
|
|
||||||
sensitive,
|
|
||||||
account_ids: editorState.initialItemIds,
|
|
||||||
};
|
|
||||||
if (editorState.initialTopic) {
|
|
||||||
payload.tag_name = editorState.initialTopic;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dispatch(
|
|
||||||
createCollection({
|
|
||||||
payload,
|
|
||||||
}),
|
|
||||||
).then((result) => {
|
|
||||||
if (isFulfilled(result)) {
|
|
||||||
history.replace(
|
|
||||||
`/collections/${result.payload.collection.id}/edit/settings`,
|
|
||||||
);
|
|
||||||
history.push(`/collections`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[id, discoverable, sensitive, dispatch, history, editorState],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormStack as='form' onSubmit={handleSubmit}>
|
|
||||||
{!id && (
|
|
||||||
<WizardStepHeader
|
|
||||||
step={3}
|
|
||||||
title={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.create.settings_title'
|
|
||||||
defaultMessage='Settings'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Fieldset
|
|
||||||
legend={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.visibility_title'
|
|
||||||
defaultMessage='Visibility'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RadioButtonField
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.visibility_public'
|
|
||||||
defaultMessage='Public'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.visibility_public_hint'
|
|
||||||
defaultMessage='Discoverable in search results and other areas where recommendations appear.'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value='public'
|
|
||||||
checked={discoverable}
|
|
||||||
onChange={handleDiscoverableChange}
|
|
||||||
/>
|
|
||||||
<RadioButtonField
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.visibility_unlisted'
|
|
||||||
defaultMessage='Unlisted'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.visibility_unlisted_hint'
|
|
||||||
defaultMessage='Visible to anyone with a link. Hidden from search results and recommendations.'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
value='unlisted'
|
|
||||||
checked={!discoverable}
|
|
||||||
onChange={handleDiscoverableChange}
|
|
||||||
/>
|
|
||||||
</Fieldset>
|
|
||||||
|
|
||||||
<Fieldset
|
|
||||||
legend={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.content_warning'
|
|
||||||
defaultMessage='Content warning'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<CheckboxField
|
|
||||||
label={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.mark_as_sensitive'
|
|
||||||
defaultMessage='Mark as sensitive'
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.mark_as_sensitive_hint'
|
|
||||||
defaultMessage="Hides the collection's description and accounts behind a content warning. The collection name will still be visible."
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
checked={sensitive}
|
|
||||||
onChange={handleSensitiveChange}
|
|
||||||
/>
|
|
||||||
</Fieldset>
|
|
||||||
|
|
||||||
<div className={classes.actionWrapper}>
|
|
||||||
<Button type='submit'>
|
|
||||||
{id ? (
|
|
||||||
<FormattedMessage id='lists.save' defaultMessage='Save' />
|
|
||||||
) : (
|
|
||||||
<FormattedMessage
|
|
||||||
id='collections.create_collection'
|
|
||||||
defaultMessage='Create collection'
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</FormStack>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -12,7 +12,7 @@ export const WizardStepHeader: React.FC<{
|
|||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='collections.create.steps'
|
id='collections.create.steps'
|
||||||
defaultMessage='Step {step}/{total}'
|
defaultMessage='Step {step}/{total}'
|
||||||
values={{ step, total: 3 }}
|
values={{ step, total: 2 }}
|
||||||
>
|
>
|
||||||
{(content) => <p className={classes.step}>{content}</p>}
|
{(content) => <p className={classes.step}>{content}</p>}
|
||||||
</FormattedMessage>
|
</FormattedMessage>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import type {
|
|||||||
ApiCreateCollectionPayload,
|
ApiCreateCollectionPayload,
|
||||||
ApiUpdateCollectionPayload,
|
ApiUpdateCollectionPayload,
|
||||||
} from '@/flavours/glitch/api_types/collections';
|
} from '@/flavours/glitch/api_types/collections';
|
||||||
|
import { me } from '@/flavours/glitch/initial_state';
|
||||||
import {
|
import {
|
||||||
createAppSelector,
|
createAppSelector,
|
||||||
createDataLoadingThunk,
|
createDataLoadingThunk,
|
||||||
@@ -111,6 +112,14 @@ const collectionSlice = createSlice({
|
|||||||
const { collectionId } = action.meta.arg;
|
const { collectionId } = action.meta.arg;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
delete state.collections[collectionId];
|
delete state.collections[collectionId];
|
||||||
|
if (me) {
|
||||||
|
let accountCollectionIds = state.accountCollections[me]?.collectionIds;
|
||||||
|
if (accountCollectionIds) {
|
||||||
|
accountCollectionIds = accountCollectionIds.filter(
|
||||||
|
(id) => id !== collectionId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user