Compose event modal improvements
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
parent
13ccc3fe7f
commit
403bcba525
|
@ -5,15 +5,18 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import { cancelReplyCompose } from 'soapbox/actions/compose';
|
import { cancelReplyCompose } from 'soapbox/actions/compose';
|
||||||
|
import { cancelEventCompose } from 'soapbox/actions/events';
|
||||||
import { openModal, closeModal } from 'soapbox/actions/modals';
|
import { openModal, closeModal } from 'soapbox/actions/modals';
|
||||||
import { useAppDispatch, useAppSelector, usePrevious } from 'soapbox/hooks';
|
import { useAppDispatch, usePrevious } from 'soapbox/hooks';
|
||||||
|
|
||||||
import type { UnregisterCallback } from 'history';
|
import type { UnregisterCallback } from 'history';
|
||||||
import type { ModalType } from 'soapbox/features/ui/components/modal-root';
|
import type { ModalType } from 'soapbox/features/ui/components/modal-root';
|
||||||
import type { ReducerCompose } from 'soapbox/reducers/compose';
|
import type { ReducerCompose } from 'soapbox/reducers/compose';
|
||||||
|
import type { ReducerRecord as ReducerComposeEvent } from 'soapbox/reducers/compose-event';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
|
cancelEditing: { id: 'confirmations.cancel_editing.confirm', defaultMessage: 'Cancel editing' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export const checkComposeContent = (compose?: ReturnType<typeof ReducerCompose>) => {
|
export const checkComposeContent = (compose?: ReturnType<typeof ReducerCompose>) => {
|
||||||
|
@ -25,6 +28,15 @@ export const checkComposeContent = (compose?: ReturnType<typeof ReducerCompose>)
|
||||||
].some(check => check === true);
|
].some(check => check === true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkEventComposeContent = (compose?: ReturnType<typeof ReducerComposeEvent>) => {
|
||||||
|
return !!compose && [
|
||||||
|
compose.name.length > 0,
|
||||||
|
compose.status.length > 0,
|
||||||
|
compose.location !== null,
|
||||||
|
compose.banner !== null,
|
||||||
|
].some(check => check === true);
|
||||||
|
};
|
||||||
|
|
||||||
interface IModalRoot {
|
interface IModalRoot {
|
||||||
onCancel?: () => void,
|
onCancel?: () => void,
|
||||||
onClose: (type?: ModalType) => void,
|
onClose: (type?: ModalType) => void,
|
||||||
|
@ -46,8 +58,6 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
|
||||||
const prevChildren = usePrevious(children);
|
const prevChildren = usePrevious(children);
|
||||||
const prevType = usePrevious(type);
|
const prevType = usePrevious(type);
|
||||||
|
|
||||||
const isEditing = useAppSelector(state => state.compose.get('compose-modal')?.id !== null);
|
|
||||||
|
|
||||||
const visible = !!children;
|
const visible = !!children;
|
||||||
|
|
||||||
const handleKeyUp = (e: KeyboardEvent) => {
|
const handleKeyUp = (e: KeyboardEvent) => {
|
||||||
|
@ -58,13 +68,20 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
|
||||||
|
|
||||||
const handleOnClose = () => {
|
const handleOnClose = () => {
|
||||||
dispatch((_, getState) => {
|
dispatch((_, getState) => {
|
||||||
const hasComposeContent = checkComposeContent(getState().compose.get('compose-modal'));
|
const compose = getState().compose.get('compose-modal');
|
||||||
|
const hasComposeContent = checkComposeContent(compose);
|
||||||
|
const hasEventComposeContent = checkEventComposeContent(getState().compose_event);
|
||||||
|
|
||||||
if (hasComposeContent && type === 'COMPOSE') {
|
if (hasComposeContent && type === 'COMPOSE') {
|
||||||
|
const isEditing = compose!.id !== null;
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
icon: require('@tabler/icons/trash.svg'),
|
icon: require('@tabler/icons/trash.svg'),
|
||||||
heading: isEditing ? <FormattedMessage id='confirmations.cancel_editing.heading' defaultMessage='Cancel post editing' /> : <FormattedMessage id='confirmations.delete.heading' defaultMessage='Delete post' />,
|
heading: isEditing
|
||||||
message: isEditing ? <FormattedMessage id='confirmations.cancel_editing.message' defaultMessage='Are you sure you want to cancel editing this post? All changes will be lost.' /> : <FormattedMessage id='confirmations.delete.message' defaultMessage='Are you sure you want to delete this post?' />,
|
? <FormattedMessage id='confirmations.cancel_editing.heading' defaultMessage='Cancel post editing' />
|
||||||
|
: <FormattedMessage id='confirmations.delete.heading' defaultMessage='Delete post' />,
|
||||||
|
message: isEditing
|
||||||
|
? <FormattedMessage id='confirmations.cancel_editing.message' defaultMessage='Are you sure you want to cancel editing this post? All changes will be lost.' />
|
||||||
|
: <FormattedMessage id='confirmations.delete.message' defaultMessage='Are you sure you want to delete this post?' />,
|
||||||
confirm: intl.formatMessage(messages.confirm),
|
confirm: intl.formatMessage(messages.confirm),
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
dispatch(closeModal('COMPOSE'));
|
dispatch(closeModal('COMPOSE'));
|
||||||
|
@ -74,7 +91,26 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
|
||||||
dispatch(closeModal('CONFIRM'));
|
dispatch(closeModal('CONFIRM'));
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
} else if (hasComposeContent && type === 'CONFIRM') {
|
} else if (hasEventComposeContent && type === 'COMPOSE_EVENT') {
|
||||||
|
const isEditing = getState().compose_event.id !== null;
|
||||||
|
dispatch(openModal('CONFIRM', {
|
||||||
|
icon: require('@tabler/icons/trash.svg'),
|
||||||
|
heading: isEditing
|
||||||
|
? <FormattedMessage id='confirmations.cancel_event_editing.heading' defaultMessage='Cancel event editing' />
|
||||||
|
: <FormattedMessage id='confirmations.delete_event.heading' defaultMessage='Delete event' />,
|
||||||
|
message: isEditing
|
||||||
|
? <FormattedMessage id='confirmations.cancel_event_editing.message' defaultMessage='Are you sure you want to cancel editing this event? All changes will be lost.' />
|
||||||
|
: <FormattedMessage id='confirmations.delete_event.message' defaultMessage='Are you sure you want to delete this event?' />,
|
||||||
|
confirm: intl.formatMessage(isEditing ? messages.cancelEditing : messages.confirm),
|
||||||
|
onConfirm: () => {
|
||||||
|
dispatch(closeModal('COMPOSE_EVENT'));
|
||||||
|
dispatch(cancelEventCompose());
|
||||||
|
},
|
||||||
|
onCancel: () => {
|
||||||
|
dispatch(closeModal('CONFIRM'));
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
} else if ((hasComposeContent || hasEventComposeContent) && type === 'CONFIRM') {
|
||||||
dispatch(closeModal('CONFIRM'));
|
dispatch(closeModal('CONFIRM'));
|
||||||
} else {
|
} else {
|
||||||
onClose();
|
onClose();
|
||||||
|
|
|
@ -56,9 +56,9 @@ const EventInformation: React.FC<IEventInformation> = ({ params }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderEventLocation = useCallback(() => {
|
const renderEventLocation = useCallback(() => {
|
||||||
const event = status?.event;
|
const event = status!.event!;
|
||||||
|
|
||||||
return event?.location && (
|
return event.location && (
|
||||||
<Stack space={1}>
|
<Stack space={1}>
|
||||||
<Text size='xl' weight='bold'>
|
<Text size='xl' weight='bold'>
|
||||||
<FormattedMessage id='event.location' defaultMessage='Location' />
|
<FormattedMessage id='event.location' defaultMessage='Location' />
|
||||||
|
@ -86,12 +86,12 @@ const EventInformation: React.FC<IEventInformation> = ({ params }) => {
|
||||||
}, [status]);
|
}, [status]);
|
||||||
|
|
||||||
const renderEventDate = useCallback(() => {
|
const renderEventDate = useCallback(() => {
|
||||||
const event = status?.event;
|
const event = status!.event!;
|
||||||
|
|
||||||
|
if (!event.start_time) return null;
|
||||||
|
|
||||||
const startDate = new Date(event.start_time);
|
const startDate = new Date(event.start_time);
|
||||||
const endDate = new Date(event.end_time);
|
const endDate = event.end_time && new Date(event.end_time);
|
||||||
|
|
||||||
if (!startDate) return null;
|
|
||||||
|
|
||||||
const sameDay = endDate && startDate.getDate() === endDate.getDate() && startDate.getMonth() === endDate.getMonth() && startDate.getFullYear() === endDate.getFullYear();
|
const sameDay = endDate && startDate.getDate() === endDate.getDate() && startDate.getMonth() === endDate.getMonth() && startDate.getFullYear() === endDate.getFullYear();
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,12 @@ import {
|
||||||
fetchEventParticipationRequests,
|
fetchEventParticipationRequests,
|
||||||
rejectEventParticipationRequest,
|
rejectEventParticipationRequest,
|
||||||
authorizeEventParticipationRequest,
|
authorizeEventParticipationRequest,
|
||||||
|
cancelEventCompose,
|
||||||
} from 'soapbox/actions/events';
|
} from 'soapbox/actions/events';
|
||||||
|
import { closeModal, openModal } from 'soapbox/actions/modals';
|
||||||
import { ADDRESS_ICONS } from 'soapbox/components/autosuggest-location';
|
import { ADDRESS_ICONS } from 'soapbox/components/autosuggest-location';
|
||||||
import LocationSearch from 'soapbox/components/location-search';
|
import LocationSearch from 'soapbox/components/location-search';
|
||||||
|
import { checkEventComposeContent } from 'soapbox/components/modal-root';
|
||||||
import { Button, Form, FormGroup, HStack, Icon, IconButton, Input, Modal, Spinner, Stack, Tabs, Text, Textarea } from 'soapbox/components/ui';
|
import { Button, Form, FormGroup, HStack, Icon, IconButton, Input, Modal, Spinner, Stack, Tabs, Text, Textarea } from 'soapbox/components/ui';
|
||||||
import AccountContainer from 'soapbox/containers/account-container';
|
import AccountContainer from 'soapbox/containers/account-container';
|
||||||
import { isCurrentOrFutureDate } from 'soapbox/features/compose/components/schedule-form';
|
import { isCurrentOrFutureDate } from 'soapbox/features/compose/components/schedule-form';
|
||||||
|
@ -38,6 +41,8 @@ const messages = defineMessages({
|
||||||
pending: { id: 'compose_event.tabs.pending', defaultMessage: 'Manage requests' },
|
pending: { id: 'compose_event.tabs.pending', defaultMessage: 'Manage requests' },
|
||||||
authorize: { id: 'compose_event.participation_requests.authorize', defaultMessage: 'Authorize' },
|
authorize: { id: 'compose_event.participation_requests.authorize', defaultMessage: 'Authorize' },
|
||||||
reject: { id: 'compose_event.participation_requests.reject', defaultMessage: 'Reject' },
|
reject: { id: 'compose_event.participation_requests.reject', defaultMessage: 'Reject' },
|
||||||
|
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
|
cancelEditing: { id: 'confirmations.cancel_editing.confirm', defaultMessage: 'Cancel editing' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,7 +141,26 @@ const ComposeEventModal: React.FC<IComposeEventModal> = ({ onClose }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClickClose = () => {
|
const onClickClose = () => {
|
||||||
|
dispatch((dispatch, getState) => {
|
||||||
|
if (checkEventComposeContent(getState().compose_event)) {
|
||||||
|
dispatch(openModal('CONFIRM', {
|
||||||
|
icon: require('@tabler/icons/trash.svg'),
|
||||||
|
heading: id
|
||||||
|
? <FormattedMessage id='confirmations.cancel_event_editing.heading' defaultMessage='Cancel event editing' />
|
||||||
|
: <FormattedMessage id='confirmations.delete_event.heading' defaultMessage='Delete event' />,
|
||||||
|
message: id
|
||||||
|
? <FormattedMessage id='confirmations.cancel_event_editing.message' defaultMessage='Are you sure you want to cancel editing this event? All changes will be lost.' />
|
||||||
|
: <FormattedMessage id='confirmations.delete_event.message' defaultMessage='Are you sure you want to delete this event?' />,
|
||||||
|
confirm: intl.formatMessage(messages.confirm),
|
||||||
|
onConfirm: () => {
|
||||||
|
dispatch(closeModal('COMPOSE_EVENT'));
|
||||||
|
dispatch(cancelEventCompose());
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
onClose('COMPOSE_EVENT');
|
onClose('COMPOSE_EVENT');
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFiles = (files: FileList) => {
|
const handleFiles = (files: FileList) => {
|
||||||
|
|
|
@ -120,6 +120,7 @@ import { WrappedRoute } from './util/react-router-helpers';
|
||||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||||
// Without this it ends up in ~8 very commonly used bundles.
|
// Without this it ends up in ~8 very commonly used bundles.
|
||||||
import 'soapbox/components/status';
|
import 'soapbox/components/status';
|
||||||
|
import { uploadEventBanner } from 'soapbox/actions/events';
|
||||||
|
|
||||||
const EmptyPage = HomePage;
|
const EmptyPage = HomePage;
|
||||||
|
|
||||||
|
@ -384,7 +385,9 @@ const UI: React.FC = ({ children }) => {
|
||||||
if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
|
if (e.dataTransfer && e.dataTransfer.files.length >= 1) {
|
||||||
const modals = getState().modals;
|
const modals = getState().modals;
|
||||||
const isModalOpen = modals.last()?.modalType === 'COMPOSE';
|
const isModalOpen = modals.last()?.modalType === 'COMPOSE';
|
||||||
dispatch(uploadCompose(isModalOpen ? 'compose-modal' : 'home', e.dataTransfer.files, intl));
|
const isEventsModalOpen = modals.last()?.modalType === 'COMPOSE_EVENT';
|
||||||
|
if (isEventsModalOpen) dispatch(uploadEventBanner(e.dataTransfer.files[0], intl));
|
||||||
|
else dispatch(uploadCompose(isModalOpen ? 'compose-modal' : 'home', e.dataTransfer.files, intl));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ import chat_message_lists from './chat-message-lists';
|
||||||
import chat_messages from './chat-messages';
|
import chat_messages from './chat-messages';
|
||||||
import chats from './chats';
|
import chats from './chats';
|
||||||
import compose from './compose';
|
import compose from './compose';
|
||||||
import compose_event from './compose_event';
|
import compose_event from './compose-event';
|
||||||
import contexts from './contexts';
|
import contexts from './contexts';
|
||||||
import conversations from './conversations';
|
import conversations from './conversations';
|
||||||
import custom_emojis from './custom-emojis';
|
import custom_emojis from './custom-emojis';
|
||||||
|
|
Loading…
Reference in New Issue