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

Add settings for the admin #516

Merged
merged 64 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
2d63817
Fix issue with FormikMarkdownTextField.
Dudrie Jul 17, 2020
fac6506
Change FormikMarkdownTextfield to exit preview if value is not present.
Dudrie Jul 17, 2020
57e4829
Change styles in the Logger.
Dudrie Jul 17, 2020
74c6ab1
Split settings into StaticSettings and SettingsService.
Dudrie Jul 23, 2020
c9aac00
Fix deprecated typegoose arrayProp and mapProp decorators.
Dudrie Jul 23, 2020
405114a
Add some basic logic to the SettingsService.
Dudrie Jul 23, 2020
7f63668
Add ability to provide default config through config file.
Dudrie Jul 23, 2020
81a8217
Add proper handling of default settings.
Dudrie Jul 24, 2020
35db1bb
Fix overflow issue with the internals management.
Dudrie Jul 24, 2020
4e1fa1b
Fix issues with new version of @types/luxon.
Dudrie Jul 24, 2020
d2cb483
Change sessions to be saved in the MongoDB.
Dudrie Jul 24, 2020
598122c
Merge branch 'v2' into issue-503-Settings_for_the_admin
Dudrie Jul 24, 2020
6361733
Fix more issues with the @types/luxon update.
Dudrie Jul 24, 2020
474da85
Add eslint-plugin-react-hooks as eslint plugin.
Dudrie Jul 27, 2020
86a9491
Add endpoint to change the client settings.
Dudrie Jul 28, 2020
5eb99f5
Add fetching of settings to the client.
Dudrie Jul 28, 2020
4dd05e1
Add a check if the user would be allowed to excuse a student.
Dudrie Jul 28, 2020
dbf83ff
Add usage of canTutorExcuseStudent setting in client.
Dudrie Jul 28, 2020
86a36f3
Fix failing UserService test.
Dudrie Jul 28, 2020
de68511
Fix UserModel.toDTO returning a CoreMongooseArray for roles.
Dudrie Jul 28, 2020
a06d196
Rename folder view/ -> pages/.
Dudrie Jul 29, 2020
f05fcf7
Add helper function in settings context.
Dudrie Jul 29, 2020
2a5b565
Fix fetching settings to only occur AFTER login.
Dudrie Jul 29, 2020
f9a9d7c
Clean up ununsed client components.
Dudrie Jul 29, 2020
9851bd3
Add linter rule for ununsed module exports.
Dudrie Jul 29, 2020
ae1e188
Add general layout for settings page.
Dudrie Jul 29, 2020
df41c4e
Change style to be more consistent between light & dark theme.
Dudrie Jul 29, 2020
ce6e215
Add helper function to theme palette.
Dudrie Jul 29, 2020
a5ff6a9
Add logic to save new settings in the client.
Dudrie Jul 29, 2020
59e48df
Add 'no-useless-rename' rule to eslint config.
Dudrie Jul 29, 2020
c04c318
Add new promise wrapper that can show notifications on success/error.
Dudrie Jul 29, 2020
7091c01
Add notifications to the submit process of the SettingsPage.
Dudrie Jul 29, 2020
55b4009
Change snackbars to be displayed on the bottom right.
Dudrie Jul 29, 2020
c87802b
Revert style changes partially.
Dudrie Jul 29, 2020
a2b5e57
Change AppBar to always have the dark blue background color.
Dudrie Jul 29, 2020
a785fd9
Fix version clipping over NavigationRail items.
Dudrie Jul 29, 2020
1769178
Change setting titles on the left to be 1.1rem in font-size.
Dudrie Jul 29, 2020
2094a66
Add es2020 TS-lib to allow Promise.allSettled.
Dudrie Jul 29, 2020
4aed016
Move mailing configuration from static settings to SettingsModel.
Dudrie Jul 29, 2020
3524126
Change MailingService to use the new settings from the SettingsModel.
Dudrie Jul 29, 2020
5857170
Change settings dtos to include a mailingConfig property.
Dudrie Jul 30, 2020
2eb7cf2
Add proper model for mailing settings.
Dudrie Jul 30, 2020
0027547
Add more validation to the mailing settings.
Dudrie Jul 30, 2020
fdf7490
Add encryption to MailingSettingsModel.
Dudrie Jul 30, 2020
8377478
Add FormikPasswordField component.
Dudrie Jul 30, 2020
ebac56b
Add e-mail settings to the settings page.
Dudrie Jul 30, 2020
f99e216
Extract GridDivider component from SettingsPage.
Dudrie Jul 30, 2020
988a5a9
Split SettingsPage into different files to keep things organized.
Dudrie Jul 30, 2020
8691349
Add mailing setting to customize the mail subject.
Dudrie Jul 30, 2020
19dadcc
Add 'subject' field to EMailSettings form.
Dudrie Jul 30, 2020
a1bc355
Fix mailingConfig in SettingsModel set to {}.
Dudrie Jul 30, 2020
1ed29b3
Fix wrong creation of transport options.
Dudrie Jul 30, 2020
58a64ad
Add helpertexts to SettingsPage textfields.
Dudrie Jul 31, 2020
d540163
Fix form validation allowing a list for the 'from' email setting.
Dudrie Jul 31, 2020
39e8445
Add direct support for secondary text to ListItemMenu items.
Dudrie Jul 31, 2020
3a9c1e7
Add helper function to determine if server has mailing configuration …
Dudrie Jul 31, 2020
ce32db2
Add disabling of send credentials buttons for users if:
Dudrie Jul 31, 2020
748856a
Remove debug route.
Dudrie Jul 31, 2020
9915ea1
Add more validation to the configuration on server start.
Dudrie Jul 31, 2020
d54760f
Merge branch 'v2' into issue-503-Settings_for_the_admin
Dudrie Jul 31, 2020
9145d04
Update yarn.lock
Dudrie Jul 31, 2020
ac5c95d
Resolve todos.
Dudrie Jul 31, 2020
0e2330c
Fix wrong dependency array.
Dudrie Aug 1, 2020
80dfc65
Fix style issues with the SplitButton.
Dudrie Aug 1, 2020
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
5 changes: 5 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins:

extends:
- 'plugin:react/recommended' # Uses the recommended rules from @eslint-plugin-react
- 'plugin:react-hooks/recommended'
- 'plugin:@typescript-eslint/recommended' # Uses the recommended rules from the @typescript-eslint/eslint-plugin
- 'plugin:import/typescript'
- 'prettier/@typescript-eslint' # Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
Expand Down Expand Up @@ -48,13 +49,17 @@ rules:
'constructor-super': 'error'
'no-console': 'warn'
'no-fallthrough': 'error'
'no-useless-rename': 'warn'
'import/no-restricted-paths':
- 'error'
- zones:
- target: './client'
from: './server/src'
'import/no-unresolved': 'off'
'import/no-named-as-default': 'off'
'import/no-unused-modules':
- 'off'
- unusedExports: true
'react/display-name': 'off'
'react/jsx-no-duplicate-props':
- 'warn'
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"debug.node.autoAttach": "off",
"npm.packageManager": "yarn",
"editor.codeActionsOnSave": {
"source.organizeImports": false
"source.organizeImports": true
}
}
16 changes: 11 additions & 5 deletions client/src/components/ContextWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { MemoryRouterProps } from 'react-router';
import { BrowserRouterProps } from 'react-router-dom';
import DialogService, { getDialogOutsideContext } from '../hooks/DialogService';
import { LoginContextProvider } from '../hooks/LoginService';
import { SettingsProvider } from '../hooks/useSettings';
import { RequireChildrenProp } from '../typings/RequireChildrenProp';
import i18n from '../util/lang/configI18N';
import { getRouteWithPrefix } from '../util/routePrefix';
Expand Down Expand Up @@ -82,11 +83,16 @@ function ContextWrapper({ children, Router }: PropsWithChildren<Props>): JSX.Ele
<I18nextProvider i18n={i18n}>
<CustomThemeProvider>
<LoginContextProvider>
<MuiPickersUtilsProvider locale={navigator.language ?? 'de'} utils={LuxonUtils}>
<SnackbarProvider maxSnack={3}>
<DialogService>{children}</DialogService>
</SnackbarProvider>
</MuiPickersUtilsProvider>
<SettingsProvider>
<MuiPickersUtilsProvider locale={navigator.language ?? 'de'} utils={LuxonUtils}>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
>
<DialogService>{children}</DialogService>
</SnackbarProvider>
</MuiPickersUtilsProvider>
</SettingsProvider>
</LoginContextProvider>
</CustomThemeProvider>
</I18nextProvider>
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/DateOfTutorialSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ function DateOfTutorialSelection({
className={className}
FormControlProps={other}
items={availableDates}
itemToString={(date) => date.toLocaleString(DateTime.DATE_MED)}
itemToValue={(date) => date.toISODate()}
itemToString={(date) => date.toLocaleString(DateTime.DATE_MED) ?? 'DATE_NOTE_PARSEABLE'}
itemToValue={(date) => date.toISODate() ?? 'DATE_NOTE_PARSEABLE'}
/>
);
}
Expand Down
8 changes: 8 additions & 0 deletions client/src/components/GridDivider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Divider } from '@material-ui/core';
import React from 'react';

function GridDivider(): JSX.Element {
return <Divider style={{ gridColumn: '1 / -1' }} />;
}

export default GridDivider;
18 changes: 17 additions & 1 deletion client/src/components/SplitButton.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import {
Button,
ButtonGroup,
ButtonGroupProps,
ButtonProps,
ClickAwayListener,
Grow,
MenuItem,
MenuList,
Paper,
Popper,
ButtonGroupProps,
} from '@material-ui/core';
import { createStyles, fade, makeStyles } from '@material-ui/core/styles';
import { MenuDown as ArrowDropDownIcon } from 'mdi-material-ui';
import React from 'react';

const useStyles = makeStyles((theme) =>
createStyles({
button: {
'&:hover': {
background: fade(theme.palette.primary.main, 0.8),
},
'&:not(:last-child)': {
borderRightColor: theme.palette.getContrastText(theme.palette.primary.main),
},
},
})
);

interface ButtonOption {
label: string;
disabled?: boolean;
Expand All @@ -29,6 +43,7 @@ function SplitButton({ options, variant, color, ...props }: Props): JSX.Element
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef<HTMLDivElement>(null);
const [selectedIndex, setSelectedIndex] = React.useState(0);
const classes = useStyles();

const { ButtonProps: buttonProps } = options[selectedIndex];

Expand Down Expand Up @@ -60,6 +75,7 @@ function SplitButton({ options, variant, color, ...props }: Props): JSX.Element
ref={anchorRef}
aria-label='split button'
{...props}
classes={{ grouped: classes.button }}
>
<Button {...buttonProps}>{options[selectedIndex].label}</Button>
<Button
Expand Down
24 changes: 7 additions & 17 deletions client/src/components/attendance-controls/AttendanceControls.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import { Box, BoxProps } from '@material-ui/core';
import React from 'react';
import { IAttendance, AttendanceState } from 'shared/model/Attendance';
import { Role } from 'shared/model/Role';
import { useLogin } from '../../hooks/LoginService';
import AttendanceButton from '../../view/attendance/components/AttendanceButton';
import { AttendanceState, IAttendance } from 'shared/model/Attendance';
import AttendanceButton from '../../pages/attendance/components/AttendanceButton';
import AttendanceNotePopper, { NoteFormCallback } from './components/AttendanceNotePopper';

export interface AttendanceControlsProps extends BoxProps {
attendance?: IAttendance;
onAttendanceChange: (attendance?: AttendanceState) => void;
onNoteChange: NoteFormCallback;
excuseDisabled: boolean;
}

function AttendanceControls({
attendance,
onAttendanceChange,
onNoteChange,
excuseDisabled,
...props
}: AttendanceControlsProps): JSX.Element {
const { userData } = useLogin();

const handleAttendanceClick = (newState: AttendanceState) => {
if (newState === attendance?.state) {
onAttendanceChange(undefined);
Expand All @@ -36,11 +34,7 @@ function AttendanceControls({
attendanceState={AttendanceState.PRESENT}
isSelected={attendance?.state === AttendanceState.PRESENT}
onClick={() => handleAttendanceClick(AttendanceState.PRESENT)}
disabled={
userData &&
!userData.roles.includes(Role.ADMIN) &&
attendance?.state === AttendanceState.EXCUSED
}
disabled={excuseDisabled && attendance?.state === AttendanceState.EXCUSED}
>
Anwesend
</AttendanceButton>
Expand All @@ -49,7 +43,7 @@ function AttendanceControls({
attendanceState={AttendanceState.EXCUSED}
isSelected={attendance?.state === AttendanceState.EXCUSED}
onClick={() => handleAttendanceClick(AttendanceState.EXCUSED)}
disabled={userData && userData.roles.includes(Role.ADMIN) ? false : true}
disabled={excuseDisabled}
>
Entschuldigt
</AttendanceButton>
Expand All @@ -58,11 +52,7 @@ function AttendanceControls({
attendanceState={AttendanceState.UNEXCUSED}
isSelected={attendance?.state === AttendanceState.UNEXCUSED}
onClick={() => handleAttendanceClick(AttendanceState.UNEXCUSED)}
disabled={
userData &&
!userData.roles.includes(Role.ADMIN) &&
attendance?.state === AttendanceState.EXCUSED
}
disabled={excuseDisabled && attendance?.state === AttendanceState.EXCUSED}
>
Unentschuldigt
</AttendanceButton>
Expand Down
10 changes: 4 additions & 6 deletions client/src/components/date-picker/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { KeyboardDatePicker, KeyboardDatePickerProps } from '@material-ui/pickers';
import { DateTimeFormatOptions, DateTime } from 'luxon';
import { DateTime, DateTimeFormatOptions } from 'luxon';
import React from 'react';

const DATE_FORMAT: DateTimeFormatOptions = {
weekday: 'short',
Expand All @@ -13,11 +13,9 @@ export type CustomDatePickerProps = KeyboardDatePickerProps;

function CustomDatePicker(props: CustomDatePickerProps): JSX.Element {
const labelFunc = (date: DateTime | null, invalidLabel: string) => {
if (!date || !date.isValid) {
return invalidLabel;
}
const label = date?.toLocaleString(DATE_FORMAT);

return date.toLocaleString(DATE_FORMAT);
return !!label ? label : invalidLabel;
};

return (
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/forms/ScheinExamForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function getInitialExamFormState(
scheinExamNo: exam.scheinExamNo.toString(),
exercises,
percentageNeeded: exam.percentageNeeded,
date: exam.date.toISODate(),
date: exam.date.toISODate() ?? '',
};
}

Expand All @@ -48,7 +48,7 @@ export function getInitialExamFormState(
return {
scheinExamNo: (lastScheinExamNo + 1).toString(),
exercises: [],
date: DateTime.local().toISODate(),
date: DateTime.local().toISODate() ?? '',
percentageNeeded: 0.5,
};
}
Expand Down
Loading