Commit a15291d7 authored by Marek Veselý's avatar Marek Veselý
Browse files

Merge branch '785-add-tags-filter-into-assign-equally' into 'main'

Added tags filter into assign equally + changed tags warning text

Closes #785

See merge request inject/frontend!684
parents 3498f741 3fd9af72
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -12,8 +12,10 @@ import { AssignUsersByTags, useTypedMutation } from '@inject/graphql'
import { dialogBody, maximizedDialog, Table } from '@inject/shared'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import { useUserTable } from '../UserTable/useUserTable'
import { AUTH_GROUPS } from '../UserTable/utils'
import { useUserTableSelection } from '../UserTableSelection/useUserTableSelection'
import { SelectUserHandler } from '../UserTableSelection/SelectUserHandler'
import { ASSIGNMENT_USER_COLUMNS } from './columns'

const body = css`
  display: flex;
@@ -48,10 +50,17 @@ const AssignByTags: FC<AssignByTagsProps> = ({ exerciseId }) => {
    }).then(() => reset())
  }, [assignByTags, exerciseId, reset, selectedUsers, tagPrefix])

  const tableProps = useUserTableSelection({
    groups: AUTH_GROUPS,
  const tableProps = useUserTable({
    onClick: (id: string) => {
      SelectUserHandler({ selectedUsers, setSelectedUsers, id })
    },
    selectedUsers,
    setSelectedUsers,
    active: { active: true, inactive: false },
    groups: AUTH_GROUPS,
    tags: [],
    columns: ASSIGNMENT_USER_COLUMNS,
    onSelectAll: (allIds: string[]) => setSelectedUsers(allIds),
    onDeselectAll: () => setSelectedUsers([]),
    /*
     * when tagPrefix changes causing only a subset of users to be displayed,
     * the selected users need not to be reset because if they are not
+25 −5
Original line number Diff line number Diff line
@@ -11,8 +11,11 @@ import { AssignUsersEqually, useTypedMutation } from '@inject/graphql'
import { dialogBody, maximizedDialog, Table } from '@inject/shared'
import type { FC } from 'react'
import { useCallback, useState } from 'react'
import { TagFilters } from '../UserTable/Filters/Tags'
import { useUserTable } from '../UserTable/useUserTable'
import { AUTH_GROUPS } from '../UserTable/utils'
import { useUserTableSelection } from '../UserTableSelection/useUserTableSelection'
import { SelectUserHandler } from '../UserTableSelection/SelectUserHandler'
import { ASSIGNMENT_USER_COLUMNS } from './columns'

const body = css`
  display: flex;
@@ -39,6 +42,7 @@ const AssignEqually: FC<AssignEquallyProps> = ({ exerciseId, teamCount }) => {
  //Q@xvesely please dedupe assign equally and by tags somehow, this is ugly
  const [{ fetching: loading }, assignEqually] =
    useTypedMutation(AssignUsersEqually)

  const handleSubmit = useCallback(() => {
    if (!selectedUsers) return

@@ -53,10 +57,19 @@ const AssignEqually: FC<AssignEquallyProps> = ({ exerciseId, teamCount }) => {
    }).then(() => reset())
  }, [assignEqually, exerciseId, reset, selectedUsers, teamCount, warningOpen])

  const tableProps = useUserTableSelection({
    groups: AUTH_GROUPS,
  const [tags, setTags] = useState<string[]>([])

  const tableProps = useUserTable({
    onClick: (id: string) => {
      SelectUserHandler({ selectedUsers, setSelectedUsers, id })
    },
    selectedUsers,
    setSelectedUsers,
    active: { active: true, inactive: false },
    groups: AUTH_GROUPS,
    tags,
    columns: ASSIGNMENT_USER_COLUMNS,
    onSelectAll: (allIds: string[]) => setSelectedUsers(allIds),
    onDeselectAll: () => setSelectedUsers([]),
  })

  return (
@@ -76,6 +89,13 @@ const AssignEqually: FC<AssignEquallyProps> = ({ exerciseId, teamCount }) => {
        icon='align-justify'
      >
        <DialogBody className={cx(dialogBody, body)}>
          <TagFilters
            selected={tags}
            setSelected={setTags}
            fill={false}
            position='bottom-left'
          />

          <Table<User> {...tableProps} />
        </DialogBody>
        <DialogFooter
@@ -106,7 +126,7 @@ const AssignEqually: FC<AssignEquallyProps> = ({ exerciseId, teamCount }) => {
        onClose={() => setWarningOpen(false)}
        loading={loading}
      >
        <p>{`Some teams will have more users than others, because the number of selected users (${selectedUsers.length}) is not divisible by the number of teams (${teamCount}).`}</p>
        <p>{`Some teams will have different number of users than others, because the number of selected users (${selectedUsers.length}) is not divisible by the number of teams (${teamCount}).`}</p>
        <p>Do you want to proceed?</p>
      </Alert>
    </>
+49 −0
Original line number Diff line number Diff line
import type { User } from '@inject/graphql'
import { maybeSortingFunction, stringSortingFunction } from '@inject/shared'
import { Tags } from '../../components/Tags'

export const ASSIGNMENT_USER_COLUMNS = [
  {
    id: 'username',
    name: 'Username',
    display: true,
    renderValue: (user: User) => user.username,
    sortingFunction: (a: User, b: User) =>
      stringSortingFunction(a.username, b.username),
  },
  {
    id: 'firstName',
    name: 'First name',
    display: true,
    renderValue: (user: User) => user.firstName,
    sortingFunction: (a: User, b: User) =>
      maybeSortingFunction(a.firstName, b.firstName, stringSortingFunction),
  },
  {
    id: 'lastName',
    name: 'Last name',
    display: true,
    renderValue: (user: User) => user.lastName,
    sortingFunction: (a: User, b: User) =>
      maybeSortingFunction(a.lastName, b.lastName, stringSortingFunction),
  },
  {
    id: 'group',
    name: 'Group',
    display: true,
    renderValue: (user: User) => user.group,
    sortingFunction: (a: User, b: User) =>
      stringSortingFunction(a.group, b.group),
  },
  {
    id: 'tags',
    name: 'Tags',
    display: true,
    renderValue: (user: User) => <Tags tags={user.tags.map(tag => tag.name)} />,
    sortingFunction: (a: User, b: User) =>
      stringSortingFunction(
        a.tags.map(tag => tag.name).join(', '),
        b.tags.map(tag => tag.name).join(', ')
      ),
  },
]
+14 −4
Original line number Diff line number Diff line
import { Checkbox } from '@blueprintjs/core'
import { Checkbox, type PopoverPosition } from '@blueprintjs/core'
import { GetTags, useTypedQuery } from '@inject/graphql'
import { notEmpty } from '@inject/shared'
import type { FC } from 'react'
@@ -6,7 +6,17 @@ import { useMemo } from 'react'
import { Filters } from '../../../components'
import type { Filter } from '../utils'

export const TagFilters: FC<Filter<string[]>> = ({ selected, setSelected }) => {
type TagFiltersProps = Filter<string[]> & {
  fill?: boolean
  position?: PopoverPosition
}

export const TagFilters: FC<TagFiltersProps> = ({
  selected,
  setSelected,
  fill = true,
  position = 'left',
}) => {
  const onItemSelect = (tag: string) => setSelected(prev => [...prev, tag])
  const onRemove = (tagToRemove: string) =>
    setSelected(prev => prev.filter(tag => tag !== tagToRemove))
@@ -38,10 +48,10 @@ export const TagFilters: FC<Filter<string[]>> = ({ selected, setSelected }) => {
  return (
    <Filters
      noWrap
      fill
      fill={fill}
      heading='Tags'
      content={filters}
      position='left'
      position={position}
      disabled={allTags.length === 0}
      title={allTags.length === 0 ? 'No tags available' : undefined}
      onSelectAll={() => setSelected(allTags)}
+13 −4
Original line number Diff line number Diff line
@@ -9,8 +9,10 @@ import { css, cx } from '@emotion/css'
import type { User } from '@inject/graphql'
import { maximizedDialog, Table } from '@inject/shared'
import { useCallback, type Dispatch, type FC, type SetStateAction } from 'react'
import { ASSIGNMENT_USER_COLUMNS } from '../ExerciseAssignment/columns'
import { useUserTable } from '../UserTable/useUserTable'
import type { AUTH_GROUPS } from '../UserTable/utils'
import { useUserTableSelection } from './useUserTableSelection'
import { SelectUserHandler } from './SelectUserHandler'

const body = css`
  display: flex;
@@ -39,10 +41,17 @@ const UserTableSelection: FC<UserTableSelectionProps> = ({
    setSelectedUsers([])
  }, [setOpen, setSelectedUsers])

  const tableProps = useUserTableSelection({
    groups,
  const tableProps = useUserTable({
    onClick: (id: string) => {
      SelectUserHandler({ selectedUsers, setSelectedUsers, id })
    },
    selectedUsers,
    setSelectedUsers,
    active: { active: true, inactive: false },
    groups: groups,
    tags: [],
    columns: ASSIGNMENT_USER_COLUMNS,
    onSelectAll: (allIds: string[]) => setSelectedUsers(allIds),
    onDeselectAll: () => setSelectedUsers([]),
  })

  return (
Loading