Skip to content

Commit

Permalink
Added event handlers and a Redux store for cooperation (#2061)
Browse files Browse the repository at this point in the history
* Added event handlers and a Redux store for cooperation

* skip tests

* Deleted context and added updateAvailabilityStatus for all resources

* skip test

* Rewrote spec for ProfileInfo.jsx container #2073

* Combined lessons, quizzes, attachments into 'activities' array in cooperation store #2085 (#2168)

* Combined lessons, quizzes, attachments into 'activities' array in cooperation store #2085

* Rewrote spec for CooperationActivitiesList.tsx container #2075

* Added spec for "CourseSectionContainer" container #2071

* Added spec for "CourseSectionsList" container #2072

* Refactored: activities -> resources in Cooperation

* Refactored Cooperation & Course to apply requested changes

* Fixed tests after Cooperation & Course updates

* Fixed date serialization and mask input issues in DatePicker component (#2303)

* Replaced functionality of create course in order to use new handlers #2070

* Rewrote spec for CreateCourse.tsx page #2323

* Added error message on saving section without title or description in cooperation #2327 (#2334)

* Added error message on saving section without title or description in cooperation #2327

* Rewrote spec for CooperationActivities container

* Refactored  CooperationActivities to utilize useAxios

* Added event handlers and a Redux store for cooperation

* skip tests

* Deleted context and added updateAvailabilityStatus for all resources

* skip test

* Rewrote spec for ProfileInfo.jsx container #2073

* Combined lessons, quizzes, attachments into 'activities' array in cooperation store #2085 (#2168)

* Combined lessons, quizzes, attachments into 'activities' array in cooperation store #2085

* Rewrote spec for CooperationActivitiesList.tsx container #2075

* Added spec for "CourseSectionContainer" container #2071

* Added spec for "CourseSectionsList" container #2072

* Fixed failing test in CreateCourse page

* Integrated the "CheckboxWithTooltip" component into the modals in the Course & Cooperation

* Added the possibility to add a resource to a Cooperation in two ways: by duplicating or linking

* Added spec for cooperationsSlice & improved coverage CheckboxWithTooltip, CourseSectionContainer, CooperationActivitiesList

* Added the possibility to add a resource to a Course in two ways: by duplicating or linking

* Rewrote CreateCourse spec to improve code coverage

* Updated icon display based on resource addition method (link & copy) #2370

* Disabled already linked resources in Course/Cooperation in choose resources modals #2367

* Fixed drag-and-drop functionality and unique ID generation

* Resolved BSONTypeError when adding duplicate resources to Course/Cooperation

* Created utility function isValidUUID and spec

* Updated coverage of tests

* Deleted problem test in spec on Create Course page
  • Loading branch information
Olenka-Hryk authored Aug 28, 2024
1 parent 189f1d0 commit 68cbb29
Show file tree
Hide file tree
Showing 75 changed files with 3,779 additions and 1,233 deletions.
10 changes: 9 additions & 1 deletion src/components/checkbox-with-tooltip/CheckboxWithTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ReactNode } from 'react'
import { ReactNode, useCallback } from 'react'

import {
Box,
Expand All @@ -15,13 +15,20 @@ import { styles } from './CheckboxWithTooltip.styles'
interface CheckboxWithTooltipProps extends CheckboxProps {
label: ReactNode
tooltipTitle: ReactNode
onChecked?: (value: boolean) => void
}

const CheckboxWithTooltip = ({
label,
tooltipTitle,
onChecked,
...props
}: CheckboxWithTooltipProps) => {
const onChangeHandler = useCallback(
(_: React.SyntheticEvent, checked: boolean) => onChecked?.(checked),
[onChecked]
)

return (
<Box sx={styles.root}>
<FormControlLabel
Expand All @@ -32,6 +39,7 @@ const CheckboxWithTooltip = ({
}}
control={<Checkbox {...props} />}
label={label}
onChange={onChangeHandler}
sx={styles.label}
/>
<Tooltip
Expand Down
30 changes: 13 additions & 17 deletions src/components/cooperation-section-view/CooperationSectionView.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,34 @@
import Box from '@mui/material/Box'

import { FC, useState, ReactNode, useMemo } from 'react'
import { useTranslation } from 'react-i18next'

import Box from '@mui/material/Box'

import ResourceItem from '~/containers/course-section/resource-item/ResourceItem'
import AppTextField from '~/components/app-text-field/AppTextField'
import HeaderTextWithDropdown from '~/components/header-text-with-dropdown/HeaderTextWithDropdown'
import ResourceItem from '~/containers/course-section/resource-item/ResourceItem'
import { Activities, CourseSection, TextFieldVariantEnum } from '~/types'

import { styles } from '~/components/cooperation-section-view/CooperationSectionView.styles'

import { CourseSection, TextFieldVariantEnum } from '~/types'

interface CooperationSectionViewProps {
id?: string
item: CourseSection
}

const CooperationSectionView: FC<CooperationSectionViewProps> = ({
item,
id
}) => {
const [isVisible, setIsVisible] = useState(true)
const CooperationSectionView: FC<CooperationSectionViewProps> = ({ item }) => {
const { t } = useTranslation()
const [isVisible, setIsVisible] = useState<boolean>(true)

const resources = useMemo<undefined | ReactNode[]>(
() =>
item.activities?.map((activity: Activities) => (
item.resources?.map(({ resource, resourceType }) => (
<ResourceItem
isView
key={activity.resource._id}
resource={activity.resource}
resourceType={activity.resourceType}
key={resource.id}
resource={resource}
resourceType={resourceType}
/>
)),
[item.activities]
[item.resources]
)

return (
Expand All @@ -44,7 +40,7 @@ const CooperationSectionView: FC<CooperationSectionViewProps> = ({
setIsVisible={setIsVisible}
/>
{isVisible && (
<Box key={id} sx={styles.showBlock}>
<Box sx={styles.showBlock}>
<AppTextField
InputProps={styles.descriptionInput}
fullWidth
Expand Down
52 changes: 37 additions & 15 deletions src/components/enhanced-table/EnhancedTable.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'

import { SxProps } from '@mui/material'
Expand All @@ -13,8 +14,8 @@ import EnhancedTableRow from '~/components/enhanced-table/enhanced-table-row/Enh
import FilterRow from '~/components/enhanced-table/filter-row/FilterRow'
import Loader from '~/components/loader/Loader'

import { spliceSx } from '~/utils/helper-functions'
import { styles } from '~/components/enhanced-table/EnhancedTable.styles'
import { spliceSx } from '~/utils/helper-functions'
import {
TableColumn,
TableData,
Expand All @@ -29,14 +30,16 @@ export interface EnhancedTableProps<I, F> extends Omit<TableProps, 'style'> {
columns: TableColumn<I>[]
isSelection?: boolean
rowActions?: TableRowAction[]
onRowClick?: (item: I) => void
select?: TableSelect<I>
filter?: TableFilter<F>
sort: TableSort
rowsPerPage?: number
data: TableData<I>
onRowClick?: (item: I) => void
disableInitialSelectedRows?: boolean
emptyTableKey?: string
selectedRows?: I[]
initialSelectedRows?: I[]
style?: {
root?: SxProps
tableContainer?: SxProps
Expand All @@ -53,27 +56,46 @@ const EnhancedTable = <I extends TableItem, F = undefined>({
sort,
rowsPerPage,
data,
disableInitialSelectedRows = false,
emptyTableKey = 'table.noExactMatches',
selectedRows = [],
initialSelectedRows = [],
style = {},
...props
}: EnhancedTableProps<I, F>) => {
const { t } = useTranslation()
const { items, loading, getData } = data

const rows = items.map((item) => (
<EnhancedTableRow
columns={columns}
isSelection={isSelection}
item={item}
key={item._id}
onRowClick={onRowClick}
refetchData={getData}
rowActions={rowActions}
select={select}
selectedRows={selectedRows}
/>
))
const rows = useMemo(
() =>
items.map((item) => (
<EnhancedTableRow
columns={columns}
initialSelectedRows={initialSelectedRows}
isDisableRow={disableInitialSelectedRows}
isSelection={isSelection}
item={item}
key={item._id}
onRowClick={onRowClick}
refetchData={getData}
rowActions={rowActions}
select={select}
selectedRows={selectedRows}
/>
)),
[
items,
columns,
initialSelectedRows,
disableInitialSelectedRows,
isSelection,
onRowClick,
getData,
rowActions,
select,
selectedRows
]
)

const tableBody = (
<TableContainer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import palette from '~/styles/app-theme/app.pallete'

export const styles = {
row: (isSelected: boolean, isRowOnClick = false) => ({
row: (isSelected: boolean, isRowOnClick = false, isDisableRow = false) => ({
...(isRowOnClick && { cursor: 'pointer' }),
...(isSelected && { background: palette.basic.grey }),
'&:hover .addCategory': {
visibility: 'visible'
}
},
...(isDisableRow && {
pointerEvents: 'none',
opacity: 0.5
})
})
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { ReactNode, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { ReactNode } from 'react'

import MoreVertIcon from '@mui/icons-material/MoreVert'
import Checkbox from '@mui/material/Checkbox'
import MoreVertIcon from '@mui/icons-material/MoreVert'
import IconButton from '@mui/material/IconButton'
import MenuItem from '@mui/material/MenuItem'
import TableCell from '@mui/material/TableCell'
import TableRow from '@mui/material/TableRow'
import useMenu from '~/hooks/use-menu'

import { styles } from '~/components/enhanced-table/enhanced-table-row/EnhancedTableRow.styles'
import useMenu from '~/hooks/use-menu'
import {
TableActionFunc,
TableColumn,
Expand All @@ -22,68 +22,97 @@ import {
export interface EnhancedTableRowProps<I> {
columns: TableColumn<I>[]
isSelection?: boolean
isDisableRow?: boolean
item: I
onRowClick?: (item: I) => void
refetchData?: () => void
rowActions?: TableRowAction[]
select?: TableSelect<I>
selectedRows: I[]
initialSelectedRows?: I[]
}

interface AdditionalProps {
t: ReturnType<typeof useTranslation>['t']
navigate: ReturnType<typeof useNavigate>
}

const EnhancedTableRow = <I extends TableItem>({
columns,
isSelection,
isDisableRow = false,
item,
onRowClick,
refetchData,
rowActions,
onRowClick,
select = {} as TableSelect<I>,
selectedRows
selectedRows,
initialSelectedRows = []
}: EnhancedTableRowProps<I>) => {
const { t } = useTranslation()
const navigate = useNavigate()
const { openMenu, renderMenu, closeMenu } = useMenu()
const { isSelected, handleSelectClick } = select

const onAction = async (actionFunc: TableActionFunc) => {
closeMenu()
await actionFunc(item._id)
refetchData && refetchData()
}
const onAction = useCallback(
async (actionFunc: TableActionFunc) => {
closeMenu()
await actionFunc(item._id)
refetchData && refetchData()
},
[closeMenu, item._id, refetchData]
)

const additionalProps = { t, navigate }
const additionalProps = useMemo(() => ({ t, navigate }), [t, navigate])

const tableCells = columns.map(({ field, label, calculatedCellValue }) => {
let propValue: string | ReactNode
if (calculatedCellValue) {
propValue = calculatedCellValue(item, additionalProps)
} else {
propValue = item[field as keyof I]?.toString()
}
const renderTableCell = useCallback(
(
field: keyof I,
label: string,
calculatedCellValue?: (item: I, props: AdditionalProps) => ReactNode
) => {
const propValue = calculatedCellValue
? calculatedCellValue(item, additionalProps)
: item[field]?.toString()
return <TableCell key={label}>{propValue}</TableCell>
},
[additionalProps, item]
)

return <TableCell key={label}>{propValue}</TableCell>
})
const tableCells = useMemo(
() =>
columns.map(({ field, label, calculatedCellValue }) =>
renderTableCell(field as keyof I, label, calculatedCellValue)
),
[columns, renderTableCell]
)

const menuItems = rowActions?.map(({ label, func }) => (
<MenuItem key={label} onClick={() => void onAction(func)}>
{label}
</MenuItem>
))
const menuItems = useMemo(
() =>
rowActions?.map(({ label, func }) => (
<MenuItem key={label} onClick={() => void onAction(func)}>
{label}
</MenuItem>
)),
[rowActions, onAction]
)

const handleRowClick = () => onRowClick && onRowClick(item)

const handleRowClick = () => (onRowClick ? onRowClick(item) : null)
const isRowSelected = !!(
onRowClick && selectedRows.find((row) => row._id === item._id)
)

const isRowSelected =
onRowClick &&
selectedRows.length &&
selectedRows.find((row) => row._id === item._id)
const isInitialSelected =
isDisableRow && !!initialSelectedRows?.find((row) => row._id === item._id)

return (
<TableRow
hover
key={item._id}
onClick={handleRowClick}
selected={isSelection && isSelected(item._id)}
sx={styles.row(!!isRowSelected, !!onRowClick)}
sx={styles.row(isRowSelected, !!onRowClick, isInitialSelected)}
>
{isSelection && (
<TableCell padding='checkbox'>
Expand Down
Loading

0 comments on commit 68cbb29

Please sign in to comment.