Allow creating events, events list
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
7c4aca51dc
commit
683504c997
10 changed files with 234 additions and 8 deletions
|
@ -4,6 +4,7 @@ import api, { getLinks } from '../api';
|
||||||
|
|
||||||
import { fetchRelationships } from './accounts';
|
import { fetchRelationships } from './accounts';
|
||||||
import { importFetchedGroups, importFetchedAccounts } from './importer';
|
import { importFetchedGroups, importFetchedAccounts } from './importer';
|
||||||
|
import { closeModal } from './modals';
|
||||||
import { deleteFromTimelines } from './timelines';
|
import { deleteFromTimelines } from './timelines';
|
||||||
|
|
||||||
import type { AxiosError } from 'axios';
|
import type { AxiosError } from 'axios';
|
||||||
|
@ -95,13 +96,14 @@ const GROUP_MEMBERSHIP_REQUEST_REJECT_SUCCESS = 'GROUP_MEMBERSHIP_REQUEST_REJECT
|
||||||
const GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL = 'GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL';
|
const GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL = 'GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL';
|
||||||
|
|
||||||
const GROUP_EDITOR_TITLE_CHANGE = 'GROUP_EDITOR_TITLE_CHANGE';
|
const GROUP_EDITOR_TITLE_CHANGE = 'GROUP_EDITOR_TITLE_CHANGE';
|
||||||
|
const GROUP_EDITOR_DESCRIPTION_CHANGE = 'GROUP_EDITOR_DESCRIPTION_CHANGE';
|
||||||
const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET';
|
const GROUP_EDITOR_RESET = 'GROUP_EDITOR_RESET';
|
||||||
|
|
||||||
const createGroup = (displayName: string, shouldReset?: boolean) =>
|
const createGroup = (displayName: string, note: string, shouldReset?: boolean) =>
|
||||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
dispatch(createGroupRequest());
|
dispatch(createGroupRequest());
|
||||||
|
|
||||||
api(getState).post('/api/v1/groups', { display_name: displayName })
|
api(getState).post('/api/v1/groups', { display_name: displayName, note })
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
dispatch(importFetchedGroups([data]));
|
dispatch(importFetchedGroups([data]));
|
||||||
dispatch(createGroupSuccess(data));
|
dispatch(createGroupSuccess(data));
|
||||||
|
@ -109,6 +111,7 @@ const createGroup = (displayName: string, shouldReset?: boolean) =>
|
||||||
if (shouldReset) {
|
if (shouldReset) {
|
||||||
dispatch(resetGroupEditor());
|
dispatch(resetGroupEditor());
|
||||||
}
|
}
|
||||||
|
dispatch(closeModal('MANAGE_GROUP'));
|
||||||
}).catch(err => dispatch(createGroupFail(err)));
|
}).catch(err => dispatch(createGroupFail(err)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -760,6 +763,11 @@ const changeGroupEditorTitle = (value: string) => ({
|
||||||
value,
|
value,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const changeGroupEditorDescription = (value: string) => ({
|
||||||
|
type: GROUP_EDITOR_DESCRIPTION_CHANGE,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
|
||||||
const resetGroupEditor = () => ({
|
const resetGroupEditor = () => ({
|
||||||
type: GROUP_EDITOR_RESET,
|
type: GROUP_EDITOR_RESET,
|
||||||
});
|
});
|
||||||
|
@ -767,9 +775,10 @@ const resetGroupEditor = () => ({
|
||||||
const submitGroupEditor = (shouldReset?: boolean) => (dispatch: AppDispatch, getState: () => RootState) => {
|
const submitGroupEditor = (shouldReset?: boolean) => (dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
const groupId = getState().group_editor.groupId;
|
const groupId = getState().group_editor.groupId;
|
||||||
const displayName = getState().group_editor.displayName;
|
const displayName = getState().group_editor.displayName;
|
||||||
|
const note = getState().group_editor.note;
|
||||||
|
|
||||||
if (groupId === null) {
|
if (groupId === null) {
|
||||||
dispatch(createGroup(displayName, shouldReset));
|
dispatch(createGroup(displayName, note, shouldReset));
|
||||||
} else {
|
} else {
|
||||||
// TODO: dispatch(updateList(listId, title, shouldReset));
|
// TODO: dispatch(updateList(listId, title, shouldReset));
|
||||||
}
|
}
|
||||||
|
@ -840,6 +849,7 @@ export {
|
||||||
GROUP_MEMBERSHIP_REQUEST_REJECT_SUCCESS,
|
GROUP_MEMBERSHIP_REQUEST_REJECT_SUCCESS,
|
||||||
GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL,
|
GROUP_MEMBERSHIP_REQUEST_REJECT_FAIL,
|
||||||
GROUP_EDITOR_TITLE_CHANGE,
|
GROUP_EDITOR_TITLE_CHANGE,
|
||||||
|
GROUP_EDITOR_DESCRIPTION_CHANGE,
|
||||||
GROUP_EDITOR_RESET,
|
GROUP_EDITOR_RESET,
|
||||||
createGroup,
|
createGroup,
|
||||||
createGroupRequest,
|
createGroupRequest,
|
||||||
|
@ -926,6 +936,7 @@ export {
|
||||||
rejectGroupMembershipRequestSuccess,
|
rejectGroupMembershipRequestSuccess,
|
||||||
rejectGroupMembershipRequestFail,
|
rejectGroupMembershipRequestFail,
|
||||||
changeGroupEditorTitle,
|
changeGroupEditorTitle,
|
||||||
|
changeGroupEditorDescription,
|
||||||
resetGroupEditor,
|
resetGroupEditor,
|
||||||
submitGroupEditor,
|
submitGroupEditor,
|
||||||
};
|
};
|
||||||
|
|
|
@ -79,7 +79,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
|
||||||
const scheduledStatusCount = useAppSelector((state) => state.get('scheduled_statuses').size);
|
const scheduledStatusCount = useAppSelector((state) => state.get('scheduled_statuses').size);
|
||||||
const features = useFeatures();
|
const features = useFeatures();
|
||||||
|
|
||||||
const { text, suggestions, spoiler, spoiler_text: spoilerText, privacy, focusDate, caretPosition, is_submitting: isSubmitting, is_changing_upload: isChangingUpload, is_uploading: isUploading, schedule: scheduledAt } = compose;
|
const { text, suggestions, spoiler, spoiler_text: spoilerText, privacy, focusDate, caretPosition, is_submitting: isSubmitting, is_changing_upload: isChangingUpload, is_uploading: isUploading, schedule: scheduledAt, group_id: groupId } = compose;
|
||||||
const prevSpoiler = usePrevious(spoiler);
|
const prevSpoiler = usePrevious(spoiler);
|
||||||
|
|
||||||
const hasPoll = !!compose.poll;
|
const hasPoll = !!compose.poll;
|
||||||
|
@ -229,7 +229,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
|
||||||
{features.media && <UploadButtonContainer composeId={id} />}
|
{features.media && <UploadButtonContainer composeId={id} />}
|
||||||
<EmojiPickerDropdown onPickEmoji={handleEmojiPick} />
|
<EmojiPickerDropdown onPickEmoji={handleEmojiPick} />
|
||||||
{features.polls && <PollButton composeId={id} />}
|
{features.polls && <PollButton composeId={id} />}
|
||||||
{features.privacyScopes && !group && <PrivacyDropdown composeId={id} />}
|
{features.privacyScopes && !group && !groupId && <PrivacyDropdown composeId={id} />}
|
||||||
{features.scheduledStatuses && <ScheduleButton composeId={id} />}
|
{features.scheduledStatuses && <ScheduleButton composeId={id} />}
|
||||||
{features.spoilers && <SpoilerButton composeId={id} />}
|
{features.spoilers && <SpoilerButton composeId={id} />}
|
||||||
{features.richText && <MarkdownButton composeId={id} />}
|
{features.richText && <MarkdownButton composeId={id} />}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { openModal } from 'soapbox/actions/modals';
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
import StillImage from 'soapbox/components/still-image';
|
import StillImage from 'soapbox/components/still-image';
|
||||||
import { Avatar, HStack, IconButton, Menu, MenuButton, MenuDivider, MenuItem, MenuLink, MenuList } from 'soapbox/components/ui';
|
import { Avatar, Button, HStack, IconButton, Menu, MenuButton, MenuDivider, MenuItem, MenuLink, MenuList } from 'soapbox/components/ui';
|
||||||
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
import SvgIcon from 'soapbox/components/ui/icon/svg-icon';
|
||||||
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
import { useAppDispatch, useOwnAccount } from 'soapbox/hooks';
|
||||||
import { normalizeAttachment } from 'soapbox/normalizers';
|
import { normalizeAttachment } from 'soapbox/normalizers';
|
||||||
|
@ -83,7 +83,24 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
|
||||||
return menu;
|
return menu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const makeActionButton = () => {
|
||||||
|
if (group.relationship?.role === 'admin') {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
theme='primary'
|
||||||
|
// to={`/@${account.acct}/events/${status.id}`}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='group.manage' defaultMessage='Manage' />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const menu = makeMenu();
|
const menu = makeMenu();
|
||||||
|
const actionButton = makeActionButton();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='-mt-4 -mx-4'>
|
<div className='-mt-4 -mx-4'>
|
||||||
|
@ -155,6 +172,8 @@ const GroupHeader: React.FC<IGroupHeader> = ({ group }) => {
|
||||||
</MenuList>
|
</MenuList>
|
||||||
</Menu>
|
</Menu>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{actionButton}
|
||||||
</HStack>
|
</HStack>
|
||||||
</div>
|
</div>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
85
app/soapbox/features/groups/index.tsx
Normal file
85
app/soapbox/features/groups/index.tsx
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
import { fetchGroups } from 'soapbox/actions/groups';
|
||||||
|
import { openModal } from 'soapbox/actions/modals';
|
||||||
|
import Icon from 'soapbox/components/icon';
|
||||||
|
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||||
|
import { Button, Column, HStack, Spinner } from 'soapbox/components/ui';
|
||||||
|
import { useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
import type { RootState } from 'soapbox/store';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
heading: { id: 'column.groups', defaultMessage: 'Groups' },
|
||||||
|
});
|
||||||
|
|
||||||
|
const getOrderedGroups = createSelector([
|
||||||
|
(state: RootState) => state.groups,
|
||||||
|
(state: RootState) => state.group_relationships,
|
||||||
|
], (groups, group_relationships) => {
|
||||||
|
if (!groups) {
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups.toList().filter(item => !!item && group_relationships.get(item.id)?.member).sort((a, b) => a.display_name.localeCompare(b.display_name));
|
||||||
|
});
|
||||||
|
|
||||||
|
const Lists: React.FC = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const groups = useAppSelector((state) => getOrderedGroups(state));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetchGroups());
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onCreateGroup = () => {
|
||||||
|
dispatch(openModal('MANAGE_GROUP'));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!groups) {
|
||||||
|
return (
|
||||||
|
<Column>
|
||||||
|
<Spinner />
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const emptyMessage = <FormattedMessage id='empty_column.groups' defaultMessage='You are not in any group yet. When you join one, it will show up here.' />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column label={intl.formatMessage(messages.heading)}>
|
||||||
|
<HStack>
|
||||||
|
<Button
|
||||||
|
className='ml-auto'
|
||||||
|
theme='primary'
|
||||||
|
size='sm'
|
||||||
|
onClick={onCreateGroup}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='groups.create_group' defaultMessage='Create group' />
|
||||||
|
</Button>
|
||||||
|
</HStack>
|
||||||
|
<div className='space-y-4'>
|
||||||
|
<ScrollableList
|
||||||
|
scrollKey='lists'
|
||||||
|
emptyMessage={emptyMessage}
|
||||||
|
itemClassName='py-2'
|
||||||
|
>
|
||||||
|
{groups.map((group: any) => (
|
||||||
|
<Link key={group.id} to={`/groups/${group.id}`} className='flex items-center gap-1.5 p-2 text-gray-900 dark:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg'>
|
||||||
|
<Icon src={require('@tabler/icons/users.svg')} fixedWidth />
|
||||||
|
<span className='flex-grow' dangerouslySetInnerHTML={{ __html: group.display_name_html }} />
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</ScrollableList>
|
||||||
|
</div>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Lists;
|
|
@ -36,6 +36,7 @@ import {
|
||||||
EventMapModal,
|
EventMapModal,
|
||||||
EventParticipantsModal,
|
EventParticipantsModal,
|
||||||
PolicyModal,
|
PolicyModal,
|
||||||
|
ManageGroupModal,
|
||||||
} from 'soapbox/features/ui/util/async-components';
|
} from 'soapbox/features/ui/util/async-components';
|
||||||
|
|
||||||
import BundleContainer from '../containers/bundle-container';
|
import BundleContainer from '../containers/bundle-container';
|
||||||
|
@ -79,6 +80,7 @@ const MODAL_COMPONENTS = {
|
||||||
'EVENT_MAP': EventMapModal,
|
'EVENT_MAP': EventMapModal,
|
||||||
'EVENT_PARTICIPANTS': EventParticipantsModal,
|
'EVENT_PARTICIPANTS': EventParticipantsModal,
|
||||||
'POLICY': PolicyModal,
|
'POLICY': PolicyModal,
|
||||||
|
'MANAGE_GROUP': ManageGroupModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModalType = keyof typeof MODAL_COMPONENTS | null;
|
export type ModalType = keyof typeof MODAL_COMPONENTS | null;
|
||||||
|
|
|
@ -45,7 +45,6 @@ const messages = defineMessages({
|
||||||
cancelEditing: { id: 'confirmations.cancel_editing.confirm', defaultMessage: 'Cancel editing' },
|
cancelEditing: { id: 'confirmations.cancel_editing.confirm', defaultMessage: 'Cancel editing' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
interface IAccount {
|
interface IAccount {
|
||||||
eventId: string,
|
eventId: string,
|
||||||
id: string,
|
id: string,
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import {
|
||||||
|
changeGroupEditorTitle,
|
||||||
|
changeGroupEditorDescription,
|
||||||
|
submitGroupEditor,
|
||||||
|
} from 'soapbox/actions/groups';
|
||||||
|
import { Form, FormGroup, Input, Modal, Stack, Textarea } from 'soapbox/components/ui';
|
||||||
|
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
groupNamePlaceholder: { id: 'manage_group.fields.name_placeholder', defaultMessage: 'Name' },
|
||||||
|
groupDescriptionPlaceholder: { id: 'manage_group.fields.description_placeholder', defaultMessage: 'Description' },
|
||||||
|
});
|
||||||
|
|
||||||
|
interface IManageGroupModal {
|
||||||
|
onClose: (type?: string) => void,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ManageGroupModal: React.FC<IManageGroupModal> = ({ onClose }) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const name = useAppSelector((state) => state.group_editor.displayName);
|
||||||
|
const description = useAppSelector((state) => state.group_editor.note);
|
||||||
|
|
||||||
|
const id = useAppSelector((state) => state.group_editor.groupId);
|
||||||
|
|
||||||
|
const isSubmitting = useAppSelector((state) => state.group_editor.isSubmitting);
|
||||||
|
|
||||||
|
const onChangeName: React.ChangeEventHandler<HTMLInputElement> = ({ target }) => {
|
||||||
|
dispatch(changeGroupEditorTitle(target.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeDescription: React.ChangeEventHandler<HTMLTextAreaElement> = ({ target }) => {
|
||||||
|
dispatch(changeGroupEditorDescription(target.value));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClickClose = () => {
|
||||||
|
onClose('manage_group');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
dispatch(submitGroupEditor(true));
|
||||||
|
};
|
||||||
|
|
||||||
|
const body = (
|
||||||
|
<Form>
|
||||||
|
<FormGroup
|
||||||
|
labelText={<FormattedMessage id='manage_group.fields.name_label' defaultMessage='Group name' />}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type='text'
|
||||||
|
placeholder={intl.formatMessage(messages.groupNamePlaceholder)}
|
||||||
|
value={name}
|
||||||
|
onChange={onChangeName}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup
|
||||||
|
labelText={<FormattedMessage id='manage_group.fields.description_label' defaultMessage='Group description' />}
|
||||||
|
>
|
||||||
|
<Textarea
|
||||||
|
autoComplete='off'
|
||||||
|
placeholder={intl.formatMessage(messages.groupDescriptionPlaceholder)}
|
||||||
|
value={description}
|
||||||
|
onChange={onChangeDescription}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={id
|
||||||
|
? <FormattedMessage id='navigation_bar.manage_group' defaultMessage='Manage group' />
|
||||||
|
: <FormattedMessage id='navigation_bar.create_group' defaultMessage='Create new group' />}
|
||||||
|
confirmationAction={handleSubmit}
|
||||||
|
confirmationText={id
|
||||||
|
? <FormattedMessage id='manage_group.update' defaultMessage='Update' />
|
||||||
|
: <FormattedMessage id='manage_group.create' defaultMessage='Create' />}
|
||||||
|
confirmationDisabled={isSubmitting}
|
||||||
|
onClose={onClickClose}
|
||||||
|
>
|
||||||
|
<Stack space={2}>
|
||||||
|
{body}
|
||||||
|
</Stack>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ManageGroupModal;
|
|
@ -112,6 +112,7 @@ import {
|
||||||
EventInformation,
|
EventInformation,
|
||||||
EventDiscussion,
|
EventDiscussion,
|
||||||
Events,
|
Events,
|
||||||
|
Groups,
|
||||||
GroupTimeline,
|
GroupTimeline,
|
||||||
} from './util/async-components';
|
} from './util/async-components';
|
||||||
import { WrappedRoute } from './util/react-router-helpers';
|
import { WrappedRoute } from './util/react-router-helpers';
|
||||||
|
@ -274,6 +275,7 @@ const SwitchingColumnsArea: React.FC = ({ children }) => {
|
||||||
<WrappedRoute path='/@:username/events/:statusId/discussion' publicRoute exact page={EventPage} component={EventDiscussion} content={children} />
|
<WrappedRoute path='/@:username/events/:statusId/discussion' publicRoute exact page={EventPage} component={EventDiscussion} content={children} />
|
||||||
<Redirect from='/@:username/:statusId' to='/@:username/posts/:statusId' />
|
<Redirect from='/@:username/:statusId' to='/@:username/posts/:statusId' />
|
||||||
|
|
||||||
|
<WrappedRoute path='/groups' exact page={DefaultPage} component={Groups} content={children} />
|
||||||
<WrappedRoute path='/groups/:id' exact page={GroupPage} component={GroupTimeline} content={children} />
|
<WrappedRoute path='/groups/:id' exact page={GroupPage} component={GroupTimeline} content={children} />
|
||||||
|
|
||||||
<WrappedRoute path='/statuses/new' page={DefaultPage} component={NewStatus} content={children} exact />
|
<WrappedRoute path='/statuses/new' page={DefaultPage} component={NewStatus} content={children} exact />
|
||||||
|
|
|
@ -542,6 +542,10 @@ export function Events() {
|
||||||
return import(/* webpackChunkName: "features/events" */'../../events');
|
return import(/* webpackChunkName: "features/events" */'../../events');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function Groups() {
|
||||||
|
return import(/* webpackChunkName: "features/groups" */'../../groups');
|
||||||
|
}
|
||||||
|
|
||||||
export function GroupTimeline() {
|
export function GroupTimeline() {
|
||||||
return import(/* webpackChunkName: "features/groups" */'../../group/group-timeline');
|
return import(/* webpackChunkName: "features/groups" */'../../group/group-timeline');
|
||||||
}
|
}
|
||||||
|
@ -549,3 +553,7 @@ export function GroupTimeline() {
|
||||||
export function GroupInfoPanel() {
|
export function GroupInfoPanel() {
|
||||||
return import(/* webpackChunkName: "features/groups" */'../../group/components/group-info-panel');
|
return import(/* webpackChunkName: "features/groups" */'../../group/components/group-info-panel');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ManageGroupModal() {
|
||||||
|
return import(/* webpackChunkName: "features/manage_group_modal" */'../components/modals/manage-group-modal/manage-group-modal');
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Record as ImmutableRecord } from 'immutable';
|
||||||
import {
|
import {
|
||||||
GROUP_EDITOR_RESET,
|
GROUP_EDITOR_RESET,
|
||||||
GROUP_EDITOR_TITLE_CHANGE,
|
GROUP_EDITOR_TITLE_CHANGE,
|
||||||
|
GROUP_EDITOR_DESCRIPTION_CHANGE,
|
||||||
GROUP_CREATE_REQUEST,
|
GROUP_CREATE_REQUEST,
|
||||||
GROUP_CREATE_FAIL,
|
GROUP_CREATE_FAIL,
|
||||||
GROUP_CREATE_SUCCESS,
|
GROUP_CREATE_SUCCESS,
|
||||||
|
@ -12,12 +13,14 @@ import type { AnyAction } from 'redux';
|
||||||
|
|
||||||
const ReducerRecord = ImmutableRecord({
|
const ReducerRecord = ImmutableRecord({
|
||||||
groupId: null as string | null,
|
groupId: null as string | null,
|
||||||
|
isUploading: false,
|
||||||
isSubmitting: false,
|
isSubmitting: false,
|
||||||
isChanged: false,
|
isChanged: false,
|
||||||
displayName: '',
|
displayName: '',
|
||||||
note: '',
|
note: '',
|
||||||
avatar: null,
|
avatar: null,
|
||||||
header: null,
|
header: null,
|
||||||
|
locked: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
type State = ReturnType<typeof ReducerRecord>;
|
type State = ReturnType<typeof ReducerRecord>;
|
||||||
|
@ -31,6 +34,11 @@ export default function groupEditor(state: State = ReducerRecord(), action: AnyA
|
||||||
map.set('displayName', action.value);
|
map.set('displayName', action.value);
|
||||||
map.set('isChanged', true);
|
map.set('isChanged', true);
|
||||||
});
|
});
|
||||||
|
case GROUP_EDITOR_DESCRIPTION_CHANGE:
|
||||||
|
return state.withMutations(map => {
|
||||||
|
map.set('note', action.value);
|
||||||
|
map.set('isChanged', true);
|
||||||
|
});
|
||||||
case GROUP_CREATE_REQUEST:
|
case GROUP_CREATE_REQUEST:
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.set('isSubmitting', true);
|
map.set('isSubmitting', true);
|
||||||
|
|
Loading…
Reference in a new issue