Skip to content

Commit

Permalink
Merge branch 'main' into Feature-all-exercises-tab
Browse files Browse the repository at this point in the history
  • Loading branch information
Morphenoed authored Jan 18, 2025
2 parents 7978a98 + 8b86e63 commit 12d8bbb
Show file tree
Hide file tree
Showing 20 changed files with 101 additions and 25 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/build-push-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 14.x
node-version: 22.x

- name: Install pnpm
run: npm i -g pnpm@latest-7
- name: Enable Corepack
run: corepack enable

- name: Prepare pnpm using Corepack
run: corepack prepare pnpm

# Change the version to be the correct one so the version in the image is always the correct one.
- name: Set new version
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x

- name: Enable Corepack
run: corepack enable
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x

- name: Enable Corepack
run: corepack enable
Expand Down Expand Up @@ -79,7 +79,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x

- name: Enable Corepack
run: corepack enable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x

- name: Enable Corepack
run: corepack enable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20.x
node-version: 22.x

- name: Enable Corepack
run: corepack enable
Expand Down
1 change: 1 addition & 0 deletions client/src/hooks/useSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface ContextType {
const DEFAULT_SETTINGS: IClientSettings = {
defaultTeamSize: 1,
canTutorExcuseStudents: false,
excludeStudentsByStatus: false,
gradingFilename: '',
tutorialGradingFilename: '',
};
Expand Down
15 changes: 11 additions & 4 deletions client/src/pages/dashboard/components/AdminStatsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import RED from '@mui/material/colors/red';
import createStyles from '@mui/styles/createStyles';
import makeStyles from '@mui/styles/makeStyles';
import Chart from 'react-google-charts';
import { StudentStatus } from 'shared/model/Student';
import { useSettings } from '../../../hooks/useSettings';
import { StudentByTutorialSlotSummaryMap } from '../../../typings/types';

const useStyles = makeStyles((theme: Theme) =>
Expand Down Expand Up @@ -31,6 +33,7 @@ interface Props {
function AdminStatsCard({ studentsByTutorialSummary: summaries }: Props): JSX.Element {
const classes = useStyles();
const theme = useTheme();
const { settings } = useSettings();

function getScheinPassedStatsOfAllStudents() {
const data: [string, number, number][] = [];
Expand All @@ -39,10 +42,14 @@ function AdminStatsCard({ studentsByTutorialSummary: summaries }: Props): JSX.El
let passed = 0;
let notPassed = 0;
summaries.forEach((summary) => {
if (summary.passed) {
passed += 1;
} else {
notPassed += 1;
const shouldIncludeStudent =
!settings.excludeStudentsByStatus ||
![StudentStatus.NO_SCHEIN_REQUIRED, StudentStatus.INACTIVE].includes(
summary.student.status
);

if (shouldIncludeStudent) {
summary.passed ? passed++ : notPassed++;
}
});

Expand Down
17 changes: 17 additions & 0 deletions client/src/pages/dashboard/components/ScheinCrtieriaStatsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import convert from 'color-convert';
import { useEffect, useState } from 'react';
import Chart from 'react-google-charts';
import { IScheinCriteria, ScheinCriteriaStatus } from 'shared/model/ScheinCriteria';
import { StudentStatus } from 'shared/model/Student';
import { getAllScheinCriterias } from '../../../hooks/fetching/Scheincriteria';
import { useSettings } from '../../../hooks/useSettings';
import { useTranslation } from '../../../util/lang/configI18N';
import { TutorialSummaryInfo } from '../Dashboard';

Expand Down Expand Up @@ -47,6 +49,7 @@ function ScheinCriteriaStatsCard({
const classes = useStyles();
const theme = useTheme();
const { t } = useTranslation('scheincriteria');
const { settings } = useSettings();
const numberOfStudents = Object.keys(value.studentInfos).length;

const { backgroundColor, colors, fontStyle } = theme.mixins.chart(theme);
Expand All @@ -57,6 +60,13 @@ function ScheinCriteriaStatsCard({

function filterSummaries(critId: string): ScheinCriteriaStatus[] {
return Object.values(value.studentInfos)
.filter(
(studentInfo) =>
!settings.excludeStudentsByStatus ||
![StudentStatus.NO_SCHEIN_REQUIRED, StudentStatus.INACTIVE].includes(
studentInfo.student.status
)
)
.filter((studentInfo) => Object.keys(studentInfo.scheinCriteriaSummary).includes(critId))
.map((summary) => summary.scheinCriteriaSummary[critId]);
}
Expand Down Expand Up @@ -124,6 +134,13 @@ function ScheinCriteriaStatsCard({

function filterAndSortSummaries(critId: string): ScheinCriteriaStatus[] {
return Object.values(value.studentInfos)
.filter(
(studentInfo) =>
!settings.excludeStudentsByStatus ||
![StudentStatus.NO_SCHEIN_REQUIRED, StudentStatus.INACTIVE].includes(
studentInfo.student.status
)
)
.filter((studentInfo) => Object.keys(studentInfo.scheinCriteriaSummary).includes(critId))
.sort((a, b) => {
const teamIdA = a.student.team?.id || '';
Expand Down
14 changes: 11 additions & 3 deletions client/src/pages/dashboard/components/ScheinPassedStatsCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { CircularProgress, Paper, Theme, Typography, useTheme } from '@mui/material';
import createStyles from '@mui/styles/createStyles';
import makeStyles from '@mui/styles/makeStyles';
import React from 'react';
import Chart from 'react-google-charts';
import { StudentStatus } from 'shared/model/Student';
import { useSettings } from '../../../hooks/useSettings';
import { TutorialSummaryInfo } from '../Dashboard';

const useStyles = makeStyles((theme: Theme) =>
Expand Down Expand Up @@ -33,6 +34,7 @@ interface ScheinPassedStatsCardProps {
function ScheinPassedStatsCard({ value }: ScheinPassedStatsCardProps): JSX.Element {
const classes = useStyles();
const theme = useTheme();
const { settings } = useSettings();

const { backgroundColor, fontStyle } = theme.mixins.chart(theme);

Expand All @@ -42,8 +44,14 @@ function ScheinPassedStatsCard({ value }: ScheinPassedStatsCardProps): JSX.Eleme
let notPassedValue = 0;
const data: (string | number)[][] = [];

Object.values(value.studentInfos).forEach((item) => {
item.passed ? (passedValue += 1) : (notPassedValue += 1);
Object.values(value.studentInfos).forEach(({ student, passed }) => {
const shouldIncludeStudent =
!settings.excludeStudentsByStatus ||
![StudentStatus.NO_SCHEIN_REQUIRED, StudentStatus.INACTIVE].includes(student.status);

if (shouldIncludeStudent) {
passed ? passedValue++ : notPassedValue++;
}
});

const passed = ['Bestanden', passedValue];
Expand Down
17 changes: 14 additions & 3 deletions client/src/pages/dashboard/components/TutorialStatsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Paper, Table, TableBody, TableCell, TableRow, Theme } from '@mui/materi
import createStyles from '@mui/styles/createStyles';
import makeStyles from '@mui/styles/makeStyles';
import { DateTime } from 'luxon';
import React from 'react';
import { StudentStatus } from 'shared/model/Student';
import { useSettings } from '../../../hooks/useSettings';
import { TutorialSummaryInfo } from '../Dashboard';

const useStyles = makeStyles((theme: Theme) =>
createStyles({
statsPaper: {
Expand Down Expand Up @@ -32,15 +32,26 @@ interface TutorialStatsCardProps {

function TutorialStatsCard({ value }: TutorialStatsCardProps): JSX.Element {
const classes = useStyles();
const { settings } = useSettings();
const { studentInfos, tutorial } = value;
let activeStudents = 0;
Object.values(studentInfos).forEach(({ student }) => {
if (student.status === StudentStatus.ACTIVE) {
activeStudents++;
}
});

return (
<Paper className={classes.statsPaper}>
<Table className={classes.tableRoot}>
<TableBody>
<TableRow>
<TableCell className={classes.tableTitle}>Teilnehmer: </TableCell>
<TableCell>{Object.values(studentInfos).length}</TableCell>
<TableCell>
{settings.excludeStudentsByStatus
? `${activeStudents} aktive, ${Object.values(studentInfos).length} insgesamt`
: Object.values(studentInfos).length}
</TableCell>
</TableRow>
<>
<TableRow>
Expand Down
5 changes: 5 additions & 0 deletions client/src/pages/settings/SettingsPage.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Yup from 'yup';

export const validationSchema = Yup.object().shape({
canTutorExcuseStudents: Yup.boolean().required('Benötigt'),
excludeStudentsByStatus: Yup.boolean().required('Benötigt'),
defaultTeamSize: Yup.number()
.integer('Muss eine ganze Zahl sein.')
.min(1, 'Muss mindestens 1 sein.')
Expand Down Expand Up @@ -52,6 +53,7 @@ export const validationSchema = Yup.object().shape({
export interface FormState {
defaultTeamSize: string;
canTutorExcuseStudents: boolean;
excludeStudentsByStatus: boolean;
gradingFilename: string;
tutorialGradingFilename: string;
mailingConfig: {
Expand All @@ -68,12 +70,14 @@ export function getInitialValues(settings: IClientSettings): FormState {
const {
mailingConfig,
canTutorExcuseStudents,
excludeStudentsByStatus,
gradingFilename,
tutorialGradingFilename,
defaultTeamSize,
} = settings;
return {
canTutorExcuseStudents: canTutorExcuseStudents,
excludeStudentsByStatus: excludeStudentsByStatus,
defaultTeamSize: `${defaultTeamSize}`,
gradingFilename,
tutorialGradingFilename,
Expand All @@ -91,6 +95,7 @@ export function getInitialValues(settings: IClientSettings): FormState {
export function convertFormStateToDTO(values: FormState): IClientSettings {
const dto: IClientSettings = {
canTutorExcuseStudents: values.canTutorExcuseStudents,
excludeStudentsByStatus: values.excludeStudentsByStatus,
defaultTeamSize: Number.parseInt(values.defaultTeamSize),
gradingFilename: values.gradingFilename,
tutorialGradingFilename: values.tutorialGradingFilename,
Expand Down
10 changes: 9 additions & 1 deletion client/src/pages/settings/components/SettingsPage.form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Box, Button, Typography } from '@mui/material';
import createStyles from '@mui/styles/createStyles';
import makeStyles from '@mui/styles/makeStyles';
import { useFormikContext } from 'formik';
import React, { useCallback } from 'react';
import { useCallback } from 'react';
import FormikCheckbox from '../../../components/forms/components/FormikCheckbox';
import FormikDebugDisplay from '../../../components/forms/components/FormikDebugDisplay';
import FormikTextField from '../../../components/forms/components/FormikTextField';
Expand Down Expand Up @@ -100,6 +100,14 @@ function SettingsPageForm(): JSX.Element {

<GridDivider />

<Typography className={classes.sectionLabel}>Scheinstatus</Typography>
<FormikCheckbox
label='Studierende mit dem Status „Kein Schein benötigt“ oder „Inaktiv“ werden von der Kriterienberechnung ausgeschlossen'
name='excludeStudentsByStatus'
/>

<GridDivider />

<Typography className={classes.sectionLabel}>Dateinamen</Typography>
<Box display='grid' gridTemplateColumns='1fr'>
<FormikTextField
Expand Down
11 changes: 6 additions & 5 deletions docs/docs/handbook/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ For a complete overview of all configuration options available see the [Configur

## Available settings

| Setting | Default | Description |
| ------------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defaultTeamSize` | `2` | Size of a 'default team'. Teams are **not** validated against this constraint but the client uses it for Quality of Life adjustments. |
| `canTutorExcuseStudents` | `false` | Are tutors able to excuse their students? If this is `true` they can set the attendance state of their students to `excused`. If this is `false` only the administrator can set the attendance states to `excused`. |
| `mailingConfig` | _(optional)_ | `MailingConfiguration` - Options for [nodemailer][nodemailer]. For more information see below. |
| Setting | Default | Description |
| ------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `defaultTeamSize` | `2` | Size of a 'default team'. Teams are **not** validated against this constraint but the client uses it for Quality of Life adjustments. |
| `canTutorExcuseStudents` | `false` | Are tutors able to excuse their students? If this is `true` they can set the attendance state of their students to `excused`. If this is `false` only the administrator can set the attendance states to `excused`. |
| `excludeStudentsByStatus` | `true` | Are students with student status "Hat bereits einen Schein" and "Inaktiv" excluded from the schein criteria calculation? If this is `true` they are excluded and will not be considered in any dashboard diagram. If this is `false` they will not be excluded and will contribute to the dashboard statistics. |
| `mailingConfig` | _(optional)_ | `MailingConfiguration` - Options for [nodemailer][nodemailer]. For more information see below. |

### Mailing Configuration

Expand Down
1 change: 1 addition & 0 deletions scripts/build-test-docker/config/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ database:

defaultSettings:
canTutorExcuseStudents: true
excludeStudentsByStatus: true
defaultTeamSize: 3
1 change: 1 addition & 0 deletions server/config/development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ database:

defaultSettings:
canTutorExcuseStudents: true
excludeStudentsByStatus: true
defaultTeamSize: 3

# Settings used for the gotenberg instance
Expand Down
1 change: 1 addition & 0 deletions server/config/production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ database:

defaultSettings:
canTutorExcuseStudents: true
excludeStudentsByStatus: true
defaultTeamSize: 3

# Settings used for the gotenberg instance
Expand Down
1 change: 1 addition & 0 deletions server/config/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ database:

defaultSettings:
canTutorExcuseStudents: true
excludeStudentsByStatus: true
defaultTeamSize: 3
5 changes: 5 additions & 0 deletions server/src/database/entities/settings.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ export class Setting {
@Property()
canTutorExcuseStudents!: boolean;

@Property()
excludeStudentsByStatus!: boolean;

@Property()
gradingFilename!: string;

Expand All @@ -92,6 +95,7 @@ export class Setting {
return {
defaultTeamSize: this.defaultTeamSize,
canTutorExcuseStudents: this.canTutorExcuseStudents,
excludeStudentsByStatus: this.excludeStudentsByStatus,
gradingFilename: this.gradingFilename,
tutorialGradingFilename: this.tutorialGradingFilename,
mailingConfig: this.mailSettings?.toDTO(),
Expand All @@ -101,6 +105,7 @@ export class Setting {
updateFromDTO(dto?: ClientSettingsDTO): void {
this.defaultTeamSize = dto?.defaultTeamSize ?? 2;
this.canTutorExcuseStudents = dto?.canTutorExcuseStudents ?? false;
this.excludeStudentsByStatus = dto?.excludeStudentsByStatus ?? false;
this.gradingFilename = dto?.gradingFilename ?? 'Ex#{sheetNo}_#{teamName}';
this.tutorialGradingFilename =
dto?.tutorialGradingFilename ?? 'Tutorial_#{tutorialSlot}_Ex#{sheetNo}';
Expand Down
3 changes: 3 additions & 0 deletions server/src/module/settings/settings.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export class ClientSettingsDTO {
@IsBoolean()
canTutorExcuseStudents!: boolean;

@IsBoolean()
excludeStudentsByStatus!: boolean;

@IsOptional()
gradingFilename?: string;

Expand Down
4 changes: 3 additions & 1 deletion server/src/module/settings/settings.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { TestSuite } from '../../../test/helpers/TestSuite';
import { MOCKED_SETTINGS_DOCUMENT } from '../../../test/mocks/entities.mock';
import { Setting } from '../../database/entities/settings.entity';
import { ClientSettingsDTO } from './settings.dto';
import { SettingsService } from './settings.service';
import { SettingsModule } from './settings.module';
import { SettingsService } from './settings.service';

interface AssertSettingsParams {
expected: Setting;
Expand Down Expand Up @@ -37,6 +37,7 @@ function assertSettings({ expected, actual }: AssertSettingsParams) {
const DEFAULT_SETTINGS: ClientSettingsDTO = {
defaultTeamSize: 2,
canTutorExcuseStudents: false,
excludeStudentsByStatus: false,
gradingFilename: 'default_filename',
tutorialGradingFilename: 'default_tutorial_grading_filename',
};
Expand All @@ -63,6 +64,7 @@ describe('SettingsService', () => {
it.each<ClientSettingsDTO>([
{ ...DEFAULT_SETTINGS, defaultTeamSize: 5 },
{ ...DEFAULT_SETTINGS, canTutorExcuseStudents: true },
{ ...DEFAULT_SETTINGS, excludeStudentsByStatus: true },
{
...DEFAULT_SETTINGS,
defaultTeamSize: 3,
Expand Down
Loading

0 comments on commit 12d8bbb

Please sign in to comment.