|
@@ -1,63 +1,15 @@
|
|
|
-import {Fragment, ReactNode} from 'react';
|
|
|
import styled from '@emotion/styled';
|
|
|
|
|
|
-import {
|
|
|
- addErrorMessage,
|
|
|
- addLoadingMessage,
|
|
|
- addSuccessMessage,
|
|
|
-} from 'sentry/actionCreators/indicator';
|
|
|
-import {ModalRenderProps, openModal} from 'sentry/actionCreators/modal';
|
|
|
-import Button from 'sentry/components/actions/button';
|
|
|
-import ButtonBar from 'sentry/components/buttonBar';
|
|
|
import Checkbox from 'sentry/components/checkbox';
|
|
|
-import {DropdownMenu} from 'sentry/components/dropdownMenu';
|
|
|
-import ErrorBoundary from 'sentry/components/errorBoundary';
|
|
|
import decodeMailbox from 'sentry/components/feedback/decodeMailbox';
|
|
|
+import FeedbackListBulkSelection from 'sentry/components/feedback/list/feedbackListBulkSelection';
|
|
|
import MailboxPicker from 'sentry/components/feedback/list/mailboxPicker';
|
|
|
import type useListItemCheckboxState from 'sentry/components/feedback/list/useListItemCheckboxState';
|
|
|
-import useMutateFeedback from 'sentry/components/feedback/useMutateFeedback';
|
|
|
import PanelItem from 'sentry/components/panels/panelItem';
|
|
|
-import {Flex} from 'sentry/components/profiling/flex';
|
|
|
-import {IconEllipsis} from 'sentry/icons/iconEllipsis';
|
|
|
-import {t, tct} from 'sentry/locale';
|
|
|
import {space} from 'sentry/styles/space';
|
|
|
-import {GroupStatus} from 'sentry/types';
|
|
|
import useLocationQuery from 'sentry/utils/url/useLocationQuery';
|
|
|
-import useOrganization from 'sentry/utils/useOrganization';
|
|
|
import useUrlParams from 'sentry/utils/useUrlParams';
|
|
|
|
|
|
-function openConfirmModal({
|
|
|
- onConfirm,
|
|
|
- body,
|
|
|
- footerConfirm,
|
|
|
-}: {
|
|
|
- body: ReactNode;
|
|
|
- footerConfirm: ReactNode;
|
|
|
- onConfirm: () => void | Promise<void>;
|
|
|
-}) {
|
|
|
- openModal(({Body, Footer, closeModal}: ModalRenderProps) => (
|
|
|
- <Fragment>
|
|
|
- <Body>{body}</Body>
|
|
|
- <Footer>
|
|
|
- <Flex gap={space(1)}>
|
|
|
- <ButtonBar gap={1}>
|
|
|
- <Button onClick={closeModal}>{t('Cancel')}</Button>
|
|
|
- <Button
|
|
|
- priority="primary"
|
|
|
- onClick={() => {
|
|
|
- closeModal();
|
|
|
- onConfirm();
|
|
|
- }}
|
|
|
- >
|
|
|
- {footerConfirm}
|
|
|
- </Button>
|
|
|
- </ButtonBar>
|
|
|
- </Flex>
|
|
|
- </Footer>
|
|
|
- </Fragment>
|
|
|
- ));
|
|
|
-}
|
|
|
-
|
|
|
interface Props
|
|
|
extends Pick<
|
|
|
ReturnType<typeof useListItemCheckboxState>,
|
|
@@ -69,11 +21,6 @@ interface Props
|
|
|
| 'selectedIds'
|
|
|
> {}
|
|
|
|
|
|
-const statusToText: Record<string, string> = {
|
|
|
- resolved: 'Resolve',
|
|
|
- unresolved: 'Unresolve',
|
|
|
-};
|
|
|
-
|
|
|
export default function FeedbackListHeader({
|
|
|
countSelected,
|
|
|
deselectAll,
|
|
@@ -102,7 +49,7 @@ export default function FeedbackListHeader({
|
|
|
}}
|
|
|
/>
|
|
|
{isAnySelected ? (
|
|
|
- <HasSelection
|
|
|
+ <FeedbackListBulkSelection
|
|
|
mailbox={mailbox}
|
|
|
countSelected={countSelected}
|
|
|
selectedIds={selectedIds}
|
|
@@ -115,121 +62,6 @@ export default function FeedbackListHeader({
|
|
|
);
|
|
|
}
|
|
|
|
|
|
-interface HasSelectionProps
|
|
|
- extends Pick<
|
|
|
- ReturnType<typeof useListItemCheckboxState>,
|
|
|
- 'countSelected' | 'selectedIds' | 'deselectAll'
|
|
|
- > {
|
|
|
- mailbox: ReturnType<typeof decodeMailbox>;
|
|
|
-}
|
|
|
-
|
|
|
-function HasSelection({
|
|
|
- mailbox,
|
|
|
- countSelected,
|
|
|
- selectedIds,
|
|
|
- deselectAll,
|
|
|
-}: HasSelectionProps) {
|
|
|
- const organization = useOrganization();
|
|
|
- const {markAsRead, resolve} = useMutateFeedback({
|
|
|
- feedbackIds: selectedIds,
|
|
|
- organization,
|
|
|
- });
|
|
|
-
|
|
|
- const mutationOptionsResolve = {
|
|
|
- onError: () => {
|
|
|
- addErrorMessage(t('An error occurred while updating the feedbacks.'));
|
|
|
- },
|
|
|
- onSuccess: () => {
|
|
|
- addSuccessMessage(t('Updated feedbacks'));
|
|
|
- deselectAll();
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
- const mutationOptionsRead = {
|
|
|
- onError: () => {
|
|
|
- addErrorMessage(t('An error occurred while updating the feedbacks.'));
|
|
|
- },
|
|
|
- onSuccess: () => {
|
|
|
- addSuccessMessage(t('Updated feedbacks'));
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
- return (
|
|
|
- <Flex gap={space(1)} align="center" justify="space-between" style={{flexGrow: 1}}>
|
|
|
- <span>
|
|
|
- <strong>
|
|
|
- {tct('[countSelected] Selected', {
|
|
|
- countSelected,
|
|
|
- })}
|
|
|
- </strong>
|
|
|
- </span>
|
|
|
- <Flex gap={space(1)} justify="flex-end">
|
|
|
- <ErrorBoundary mini>
|
|
|
- <Button
|
|
|
- onClick={() => {
|
|
|
- const newStatus =
|
|
|
- mailbox === 'resolved' ? GroupStatus.UNRESOLVED : GroupStatus.RESOLVED;
|
|
|
- openConfirmModal({
|
|
|
- onConfirm: () => {
|
|
|
- addLoadingMessage(t('Updating feedbacks...'));
|
|
|
- resolve(newStatus, mutationOptionsResolve);
|
|
|
- },
|
|
|
- body: tct('Are you sure you want to [status] these feedbacks?', {
|
|
|
- status: statusToText[newStatus].toLowerCase(),
|
|
|
- }),
|
|
|
- footerConfirm: statusToText[newStatus],
|
|
|
- });
|
|
|
- }}
|
|
|
- >
|
|
|
- {mailbox === 'resolved' ? t('Unresolve') : t('Resolve')}
|
|
|
- </Button>
|
|
|
- </ErrorBoundary>
|
|
|
- <ErrorBoundary mini>
|
|
|
- <DropdownMenu
|
|
|
- position="bottom-end"
|
|
|
- triggerProps={{
|
|
|
- 'aria-label': t('Read Menu'),
|
|
|
- icon: <IconEllipsis size="xs" />,
|
|
|
- showChevron: false,
|
|
|
- size: 'xs',
|
|
|
- }}
|
|
|
- items={[
|
|
|
- {
|
|
|
- key: 'mark read',
|
|
|
- label: t('Mark Read'),
|
|
|
- onAction: () => {
|
|
|
- openConfirmModal({
|
|
|
- onConfirm: () => {
|
|
|
- addLoadingMessage(t('Updating feedbacks...'));
|
|
|
- markAsRead(true, mutationOptionsRead);
|
|
|
- },
|
|
|
- body: t('Are you sure you want to mark these feedbacks as read?'),
|
|
|
- footerConfirm: 'Mark read',
|
|
|
- });
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'mark unread',
|
|
|
- label: t('Mark Unread'),
|
|
|
- onAction: () => {
|
|
|
- openConfirmModal({
|
|
|
- onConfirm: () => {
|
|
|
- addLoadingMessage(t('Updating feedbacks...'));
|
|
|
- markAsRead(false, mutationOptionsRead);
|
|
|
- },
|
|
|
- body: t('Are you sure you want to mark these feedbacks as unread?'),
|
|
|
- footerConfirm: 'Mark unread',
|
|
|
- });
|
|
|
- },
|
|
|
- },
|
|
|
- ]}
|
|
|
- />
|
|
|
- </ErrorBoundary>
|
|
|
- </Flex>
|
|
|
- </Flex>
|
|
|
- );
|
|
|
-}
|
|
|
-
|
|
|
const HeaderPanelItem = styled(PanelItem)`
|
|
|
display: flex;
|
|
|
padding: ${space(1)} ${space(2)} ${space(1)} ${space(2)};
|