Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP / [front] feat: allow to delete a comparison #1978

Draft
wants to merge 2 commits into
base: 1940-replace_sliders_by_buttons
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion frontend/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,28 @@
"comparison": {
"ok": "OK",
"successfullySubmitted": "Comparison successfully submitted.",
"itemsAreSimilar": "These two items are very similar, it is probably not useful to compare them.",
"removeOptionalCriterias": "Remove optional criteria",
"addOptionalCriterias": "Add optional criteria",
"changeOneItem": "Change one of the items to submit a new comparison",
"comparisonInPublicData": "This comparison is included in the public data.",
"comparisonInPublicDataAfterSubmission": "After submission, this comparison will be included in the public data.",
"editComparison": "Edit comparison",
"criteriaSkipped": "skipped",
"itemsAreSimilar": "These two items are very similar, it is probably not useful to compare them.",
"submitAComparison": "Submit a comparison",
"inactivePoll": "This poll is closed.",
"inactivePollComparisonCannotBeSubmittedOrEdited": "No comparison can be submitted or modified.",
"comparisonCriteria": "Comparison criteria"
},
"comparisonActionBar": {
"comparisonDeleted": "Comparison deleted.",
"errorOccurredCannotDeleteComparison": "Sorry, an error has occurred. Cannot delete the comparison.",
"youHaventComparedTheseItemsYet": "You haven't compared these items yet.",
"deleteComparison": "Delete comparison",
"areYouSure": "Are you sure?",
"theScoresGivenToTheCriteriaWillBeDeleted": "The scores given to the criteria will be permanently deleted.",
"back": "Back"
},
"entityContext": {
"entityAtheAssociationWouldLikeToGiveYouContext": "<0>{{entityName}} A</0> - The Tournesol association would like to give you some context.",
"entityBtheAssociationWouldLikeToGiveYouContext": "<0>{{entityName}} B</0> - The Tournesol association would like to give you some context.",
Expand Down
11 changes: 10 additions & 1 deletion frontend/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,28 @@
"comparison": {
"ok": "OK",
"successfullySubmitted": "Comparaison bien enregistrée.",
"itemsAreSimilar": "Ces deux éléments sont très similaires, ce n'est probablement pas une bonne idée de les comparer.",
"removeOptionalCriterias": "Supprimer les critères optionnels",
"addOptionalCriterias": "Ajouter les critères optionnels",
"changeOneItem": "Changez l'un des deux éléments pour faire une nouvelle comparaison.",
"comparisonInPublicData": "Cette comparaison fait partie des données publiques.",
"comparisonInPublicDataAfterSubmission": "Après enregistrement, cette comparaison fera partie des données publiques.",
"editComparison": "Modifier la comparaison",
"criteriaSkipped": "ignoré",
"itemsAreSimilar": "Ces deux éléments sont très similaires, ce n'est probablement pas une bonne idée de les comparer.",
"submitAComparison": "Soumettre une comparaison",
"inactivePoll": "Ce scrutin est fermé.",
"inactivePollComparisonCannotBeSubmittedOrEdited": "Aucune comparaison ne peut être ajoutée ou modifiée.",
"comparisonCriteria": "Critères de comparaison"
},
"comparisonActionBar": {
"comparisonDeleted": "Comparaison supprimée.",
"errorOccurredCannotDeleteComparison": "Désolé, une erreur est survenue. Impossible de supprimer la comparaison.",
"youHaventComparedTheseItemsYet": "Vous n'avez pas encore comparé ces éléments.",
"deleteComparison": "Supprimer la comparaison",
"areYouSure": "Êtes-vous sûr·e ?",
"theScoresGivenToTheCriteriaWillBeDeleted": "Les scores donnés à chaque critère seront supprimés définitivement.",
"back": "Retour"
},
"entityContext": {
"entityAtheAssociationWouldLikeToGiveYouContext": "<0>{{entityName}} A</0> - L'association Tournesol souhaite vous apporter du contexte.",
"entityBtheAssociationWouldLikeToGiveYouContext": "<0>{{entityName}} B</0> - L'association Tournesol souhaite vous apporter du contexte.",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/ContentBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const ContentBox = ({

return (
<Box
position="relative"
px={[noMinPaddingX ? 0 : 2, 2, 3]}
py={2}
// Push the global footer away, to avoid displaying it in the middle
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/components/DialogBox.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React from 'react';
import { useTranslation } from 'react-i18next';

import { Box, Button, Dialog, DialogTitle } from '@mui/material';
import { ButtonOwnProps } from '@mui/material/Button/Button';

interface DialogProps {
title: string;
content: React.ReactNode;
open: boolean;
onClose: () => void;
additionalActionButton?: React.ReactNode;
mainActionColor?: ButtonOwnProps['color'];
mainActionCallback?: () => void;
}

/**
Expand All @@ -20,6 +24,8 @@ const DialogBox = ({
title,
content,
additionalActionButton,
mainActionColor = 'primary',
mainActionCallback,
}: DialogProps) => {
const { t } = useTranslation();

Expand All @@ -42,7 +48,11 @@ const DialogBox = ({
<Box>{content}</Box>
<Box display="flex" justifyContent="flex-end" gap={1}>
{additionalActionButton}
<Button variant="contained" onClick={handleClose}>
<Button
variant="contained"
color={mainActionColor}
onClick={mainActionCallback ?? handleClose}
>
{t('dialogBox.continue')}
</Button>
</Box>
Expand Down
20 changes: 19 additions & 1 deletion frontend/src/features/comparisons/Comparison.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Card,
CircularProgress,
Grid,
Theme,
useMediaQuery,
useTheme,
} from '@mui/material';
Expand All @@ -33,6 +34,7 @@ import { SuggestionHistory } from 'src/features/suggestions/suggestionHistory';
import { autoSuggestionPool } from 'src/features/suggestions/suggestionPool';
import { UID_YT_NAMESPACE } from 'src/utils/constants';
import { useCurrentPoll } from 'src/hooks/useCurrentPoll';
import ComparisonActionBar from './ComparisonActionBar';
import ComparisonEntityContexts from './ComparisonEntityContexts';
import ComparisonHelper from './ComparisonHelper';
import ComparisonInput from './ComparisonInput';
Expand Down Expand Up @@ -96,7 +98,10 @@ const Comparison = ({
const currentLang = i18n.resolvedLanguage;

const theme = useTheme();
const smallScreen = useMediaQuery(theme.breakpoints.down('sm'));
const smallScreen = useMediaQuery(
(theme: Theme) => `${theme.breakpoints.down('sm')}, (pointer: coarse)`,
{ noSsr: true }
);

const history = useHistory();
const location = useLocation();
Expand Down Expand Up @@ -371,6 +376,19 @@ const Comparison = ({
>
<ComparisonHelper />
</Grid>
{!smallScreen && (
<Grid item xs={12}>
<ComparisonActionBar
uidA={uidA}
uidB={uidB}
afterDeletion={() => {
setSelectorA({ uid: uidA, rating: null });
setSelectorB({ uid: uidB, rating: null });
setInitialComparison(null);
}}
/>
</Grid>
)}
<Grid item xs={12} sx={{ '&:empty': { display: 'none' } }}>
<ComparisonEntityContexts
selectorA={selectorA}
Expand Down
155 changes: 155 additions & 0 deletions frontend/src/features/comparisons/ComparisonActionBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';

import {
Box,
Button,
IconButton,
ListItemIcon,
ListItemText,
Menu,
MenuItem,
MenuList,
Typography,
} from '@mui/material';
import { Delete, MoreVert } from '@mui/icons-material';

import DialogBox from 'src/components/DialogBox';
import { useCurrentPoll, useNotifications } from 'src/hooks';
import { UsersService } from 'src/services/openapi';

interface ComparisonActionBarProps {
uidA: string | null;
uidB: string | null;
afterDeletion: () => void;
}

const ComparisonActionBar = ({
uidA,
uidB,
afterDeletion,
}: ComparisonActionBarProps) => {
const { t } = useTranslation();
const { name: pollName } = useCurrentPoll();

const { displayErrorsFrom, showSuccessAlert } = useNotifications();

const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
const menuOpen = Boolean(menuAnchorEl);
const [confirmDeletetionDialog, setConfirmDeletetionDialog] = useState(false);

const openMenu = (event: React.MouseEvent<HTMLElement>) => {
setMenuAnchorEl(event.currentTarget);
};

const closeMenu = () => {
setMenuAnchorEl(null);
};

const openConfirmDeletionDialog = () => {
setConfirmDeletetionDialog(true);
};

const closeConfirmDeletionDialog = () => {
setConfirmDeletetionDialog(false);
};

const deleteComparison = async () => {
if (!uidA || !uidB) {
return;
}

await UsersService.usersMeComparisonsDestroy({
pollName: pollName,
uidA: uidA,
uidB: uidB,
});
};

const onDeletionConfirmed = async () => {
try {
await deleteComparison();
showSuccessAlert(t('comparisonActionBar.comparisonDeleted'));
afterDeletion();
} catch (error) {
displayErrorsFrom(
error,
t('comparisonActionBar.errorOccurredCannotDeleteComparison'),
[
{
status: 404,
variant: 'warning',
msg: t('comparisonActionBar.youHaventComparedTheseItemsYet'),
},
]
);
} finally {
closeConfirmDeletionDialog();
closeMenu();
}
};

return (
<Box>
<IconButton
aria-label="more"
id="comparison-actions"
aria-controls={menuOpen ? 'comparison-footer-menu' : undefined}
aria-expanded={menuOpen ? 'true' : undefined}
aria-haspopup="true"
onClick={openMenu}
>
<MoreVert />
</IconButton>
<Menu
id="comparison-footer-menu"
anchorEl={menuAnchorEl}
open={menuOpen}
onClose={closeMenu}
MenuListProps={{
'aria-labelledby': 'comparison-actions',
}}
>
<MenuList dense sx={{ py: 0 }}>
<MenuItem
onClick={openConfirmDeletionDialog}
disabled={!uidA || !uidB}
>
<ListItemIcon>
<Delete />
</ListItemIcon>
<ListItemText>
{t('comparisonActionBar.deleteComparison')}
</ListItemText>
</MenuItem>
</MenuList>
</Menu>
<DialogBox
open={confirmDeletetionDialog}
onClose={closeConfirmDeletionDialog}
mainActionColor="error"
mainActionCallback={onDeletionConfirmed}
title={t('comparisonActionBar.areYouSure')}
content={
<Typography paragraph>
{t('comparisonActionBar.theScoresGivenToTheCriteriaWillBeDeleted')}
</Typography>
}
additionalActionButton={
<Button
color="secondary"
variant="outlined"
onClick={() => {
closeConfirmDeletionDialog();
closeMenu();
}}
>
{t('comparisonActionBar.back')}
</Button>
}
/>
</Box>
);
};

export default ComparisonActionBar;
Loading