Skip to content

Commit

Permalink
[frontend] add accordion
Browse files Browse the repository at this point in the history
  • Loading branch information
savacano28 committed Aug 9, 2024
1 parent 4197deb commit 5da4241
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import React, { FunctionComponent, useState } from 'react';
import { Alert, AlertTitle, Chip, Divider, List, ListItemButton, ListItemIcon, ListItemText, Tooltip, Typography } from '@mui/material';
import { AssignmentTurnedIn } from '@mui/icons-material';
import {
Accordion,
AccordionDetails,
AccordionSummary,
Alert,
AlertTitle,
Chip,
Divider,
List,
ListItemButton,
ListItemIcon,
ListItemText,
Tooltip,
Typography,
} from '@mui/material';
import { AssignmentTurnedIn, ExpandMore } from '@mui/icons-material';
import { makeStyles } from '@mui/styles';
import * as R from 'ramda';
import type { InjectExpectationsStore } from '../../../../common/injects/expectations/Expectation';
Expand All @@ -10,8 +24,15 @@ import colorStyles from '../../../../../../components/Color';
import Drawer from '../../../../../../components/common/Drawer';
import ManualExpectationsValidationForm from './ManualExpectationsValidationForm';
import ExpandableText from '../../../../../../components/common/ExpendableText';
import type { Inject } from '../../../../../../utils/api-types';
import type { Inject, Team, User } from '../../../../../../utils/api-types';
import Paper from '../../../../../../components/common/Paper';
import { computeColorStyle, computeLabel, resolveUserName, truncate } from '../../../../../../utils/String';
import { useHelper } from '../../../../../../store';
import type { TeamsHelper } from '../../../../../../actions/teams/team-helper';
import type { UserHelper } from '../../../../../../actions/helper';
import { useAppDispatch } from '../../../../../../utils/hooks';
import useDataLoader from '../../../../../../utils/hooks/useDataLoader';
import { fetchUsers } from '../../../../../../actions/User';

const useStyles = makeStyles((theme: Theme) => ({
item: {
Expand All @@ -32,6 +53,14 @@ const useStyles = makeStyles((theme: Theme) => ({
textTransform: 'uppercase',
width: 200,
},
chipStatusAcc: {
height: 30,
borderRadius: 4,
textTransform: 'uppercase',
width: 150,
float: 'right',
marginLeft: 5,
},
points: {
height: 20,
backgroundColor: 'rgba(236, 64, 122, 0.08)',
Expand Down Expand Up @@ -60,6 +89,20 @@ const ManualExpectations: FunctionComponent<Props> = ({
const [selectedItem, setSelectedItem] = useState<string | null>(null);
const [currentExpectations, setCurrentExpectations] = useState<InjectExpectationsStore[] | null>(null);

const { teamsMap, usersMap }: {
teamsMap: Record<string, Team>,
usersMap: Record<string, User>
} = useHelper((helper: TeamsHelper & UserHelper) => {
return ({
teamsMap: helper.getTeamsMap(),
usersMap: helper.getUsersMap(),
});
});
const dispatch = useAppDispatch();
useDataLoader(() => {
dispatch(fetchUsers());
});

const handleItemClick = (expectationsToUpdate: InjectExpectationsStore[]) => {
setSelectedItem(expectationsToUpdate[0]?.inject_expectation_name || null);
setCurrentExpectations(expectationsToUpdate);
Expand All @@ -80,6 +123,16 @@ const ManualExpectations: FunctionComponent<Props> = ({

const style = isAllValidated ? colorStyles.green : colorStyles.orange;

const targetLabel = (expectationToProcess: InjectExpectationsStore) => {
if (expectationToProcess.inject_expectation_user && usersMap[expectationToProcess.inject_expectation_user]) {
return truncate(resolveUserName(usersMap[expectationToProcess.inject_expectation_user]), 22);
}
if (expectationToProcess.inject_expectation_team) {
return teamsMap[expectationToProcess.inject_expectation_team]?.team_name;
}
return t('Unknown');
};

return (
<>
<List component="div" disablePadding>
Expand Down Expand Up @@ -141,7 +194,7 @@ const ManualExpectations: FunctionComponent<Props> = ({
expectations[0].inject_expectation_group
? t('At least one player (per team) must validate the expectation')
: t('All players (per team) must validate the expectation')
}
}
limit={120}
/>
</AlertTitle>
Expand All @@ -167,10 +220,28 @@ const ManualExpectations: FunctionComponent<Props> = ({
</Typography>
<div style={{ maxHeight: '80vh', overflowY: 'auto', padding: 10 }}>
{childrenExpectations && childrenExpectations.map((e) => (
<div key={e.inject_expectation_id}>
<ManualExpectationsValidationForm expectation={e}/>
<Divider style={{ margin: '20px 0' }}/>
</div>
<Accordion key={e.inject_expectation_id}>
<AccordionSummary
expandIcon={<ExpandMore/>}
aria-controls={`panel-${e.inject_expectation_id}-content`}
id={`panel-${e.inject_expectation_id}-header`}
>
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
<Typography>{targetLabel(e)}</Typography>
<div style={{ display: 'flex', alignItems: 'center' }}>
{e.inject_expectation_score && (<Chip label={e.inject_expectation_score}/>)}
<Chip
classes={{ root: classes.chipStatusAcc }}
style={computeColorStyle(e.inject_expectation_status)}
label={t(computeLabel(e.inject_expectation_status))}
/>
</div>
</div>
</AccordionSummary>
<AccordionDetails>
<ManualExpectationsValidationForm expectation={e} withSummary={false}/>
</AccordionDetails>
</Accordion>
))}
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ import { useFormatter } from '../../../../../../components/i18n';
import { updateInjectExpectation } from '../../../../../../actions/Exercise';
import { useAppDispatch } from '../../../../../../utils/hooks';
import type { Theme } from '../../../../../../components/Theme';
import colorStyles from '../../../../../../components/Color';
import { zodImplement } from '../../../../../../utils/Zod';
import type { TeamsHelper } from '../../../../../../actions/teams/team-helper';
import type { UserHelper } from '../../../../../../actions/helper';
import { useHelper } from '../../../../../../store';
import type { Team, User } from '../../../../../../utils/api-types';
import { resolveUserName, truncate } from '../../../../../../utils/String';
import { resolveUserName, truncate, computeLabel, computeColorStyle } from '../../../../../../utils/String';
import useDataLoader from '../../../../../../utils/hooks/useDataLoader';
import { fetchUsers } from '../../../../../../actions/User';
import { fetchTeams } from '../../../../../../actions/teams/team-actions';

const useStyles = makeStyles((theme: Theme) => ({
marginTop_2: {
Expand All @@ -40,9 +40,10 @@ const useStyles = makeStyles((theme: Theme) => ({
interface FormProps {
expectation: InjectExpectationsStore;
onUpdate?: () => void;
withSummary?: boolean;
}

const ManualExpectationsValidationForm: FunctionComponent<FormProps> = ({ expectation, onUpdate }) => {
const ManualExpectationsValidationForm: FunctionComponent<FormProps> = ({ expectation, onUpdate, withSummary = true }) => {
const classes = useStyles();
const { t } = useFormatter();
const { teamsMap, usersMap }: {
Expand All @@ -57,6 +58,7 @@ const ManualExpectationsValidationForm: FunctionComponent<FormProps> = ({ expect
const dispatch = useAppDispatch();
useDataLoader(() => {
dispatch(fetchUsers());
dispatch(fetchTeams());
});
const onSubmit = (data: { expectation_score: number }) => {
dispatch(updateInjectExpectation(expectation.inject_expectation_id, {
Expand Down Expand Up @@ -89,31 +91,6 @@ const ManualExpectationsValidationForm: FunctionComponent<FormProps> = ({ expect
});
}, [expectation, reset]);

const computeLabel = (e: InjectExpectationsStore) => {
if (e.inject_expectation_status === 'PENDING') {
return t('Pending validation');
}
if (e.inject_expectation_status === 'SUCCESS') {
return t('Success');
}
if (e.inject_expectation_status === 'PARTIAL') {
return t('Partial');
}
return t('Failed');
};
const computeColorStyle = (e: InjectExpectationsStore) => {
if (e.inject_expectation_status === 'PENDING') {
return colorStyles.blueGrey;
}
if (e.inject_expectation_status === 'SUCCESS') {
return colorStyles.green;
}
if (e.inject_expectation_status === 'PARTIAL') {
return colorStyles.orange;
}
return colorStyles.red;
};

const targetLabel = (expectationToProcess: InjectExpectationsStore) => {
if (expectationToProcess.inject_expectation_user && usersMap[expectationToProcess.inject_expectation_user]) {
return truncate(resolveUserName(usersMap[expectationToProcess.inject_expectation_user]), 22);
Expand All @@ -127,13 +104,13 @@ const ManualExpectationsValidationForm: FunctionComponent<FormProps> = ({ expect
return (
<div style={{ marginTop: 10 }}>
<form id="expectationForm" onSubmit={handleSubmit(onSubmit)}>
<Chip
{withSummary && (<Chip
classes={{ root: classes.chipInList }}
style={computeColorStyle(expectation)}
label={computeLabel(expectation)}
/>
<Typography variant="h3">{expectation.inject_expectation_user ? t('Player') : t('Team')}</Typography>
{targetLabel(expectation)}
style={computeColorStyle(expectation.inject_expectation_status)}
label={t(computeLabel(expectation.inject_expectation_status))}
/>)}
{withSummary && (<Typography variant="h3">{expectation.inject_expectation_user ? t('Player') : t('Team')}</Typography>)}
{withSummary && targetLabel(expectation)}
<MuiTextField
className={classes.marginTop_2}
variant="standard"
Expand Down
29 changes: 29 additions & 0 deletions openbas-front/src/utils/String.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isNotEmptyField } from './utils';
import colorStyles from '../components/Color';

export const truncate = (str, limit) => {
if (str === undefined || str === null || str.length <= limit) {
Expand Down Expand Up @@ -52,3 +53,31 @@ export const getLabelOfRemainingItems = (items, start, property) => {
export const getRemainingItemsCount = (items, visibleItems) => {
return (items && visibleItems && items.length - visibleItems.length) || null;
};

// Compute label for status
export const computeLabel = (status) => {
if (status === 'PENDING') {
return 'Pending validation';
}
if (status === 'SUCCESS') {
return 'Success';
}
if (status === 'PARTIAL') {
return 'Partial';
}
return 'Failed';
};

// compute color for status
export const computeColorStyle = (status) => {
if (status === 'PENDING') {
return colorStyles.blueGrey;
}
if (status === 'SUCCESS') {
return colorStyles.green;
}
if (status === 'PARTIAL') {
return colorStyles.orange;
}
return colorStyles.red;
};

0 comments on commit 5da4241

Please sign in to comment.