diff --git a/backend/controllers/users.js b/backend/controllers/users.js
index e479995..d771f5d 100644
--- a/backend/controllers/users.js
+++ b/backend/controllers/users.js
@@ -2,6 +2,26 @@ const usersRouter = require('express').Router()
const db = require('../models/index')
const { checkLogin, checkInstructor } = require('../middleware')
+usersRouter.put('/consent/:studentNumber', checkLogin, async (req, res) => {
+ const { research_consent } = req.body
+ const { studentNumber } = req.params
+
+ try {
+ const user = await db.User.findOne({
+ where: { student_number: studentNumber },
+ })
+ if (!user) {
+ return res.status(400).json({ error: 'user does not exist' })
+ }
+ const updatedUser = await user.update({ research_consent })
+ const refreshedUser = await updatedUser.reload()
+ res.status(200).json({ user: refreshedUser })
+ } catch (error) {
+ console.log(error)
+ res.status(500).json({ error: 'Something is wrong... try reloading the page' })
+ }
+})
+
usersRouter.put('/:studentNumber', checkLogin, async (req, res) => {
const { email } = req.body
const { studentNumber } = req.params
diff --git a/backend/migrations/20261007130200-user-research-consent.js b/backend/migrations/20261007130200-user-research-consent.js
new file mode 100644
index 0000000..580c5de
--- /dev/null
+++ b/backend/migrations/20261007130200-user-research-consent.js
@@ -0,0 +1,15 @@
+'use strict'
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ await queryInterface.addColumn('users', 'research_consent', {
+ type: Sequelize.BOOLEAN,
+ defaultValue: false,
+ allowNull: false,
+ })
+ },
+ // eslint-disable-next-line no-unused-vars
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.removeColumn('users', 'research_consent')
+ },
+}
diff --git a/backend/models/user.js b/backend/models/user.js
index c68fb45..a84fed3 100644
--- a/backend/models/user.js
+++ b/backend/models/user.js
@@ -23,6 +23,10 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
+ research_consent: {
+ type: Sequelize.BOOLEAN,
+ defaultValue: false,
+ },
},
{
underscored: true,
diff --git a/frontend/src/components/RegistrationDetailsPage.jsx b/frontend/src/components/RegistrationDetailsPage.jsx
index a23d71c..c2395ab 100644
--- a/frontend/src/components/RegistrationDetailsPage.jsx
+++ b/frontend/src/components/RegistrationDetailsPage.jsx
@@ -1,15 +1,26 @@
import { withRouter } from '../utils/withRouter'
-import React from 'react'
+import React, { useState } from 'react'
import { Link } from 'react-router-dom'
-import { connect } from 'react-redux'
+import { connect, useDispatch } from 'react-redux'
import registrationActions from '../reducers/actions/registrationActions'
import { setError } from '../reducers/actions/notificationActions'
-
+import { updateConsent } from '../reducers/actions/userActions'
import peerReviewService from '../services/peerReview'
import Typography from '@mui/material/Typography'
-import { Input, Card, CardContent, Select, MenuItem } from '@mui/material'
+import {
+ Input,
+ Card,
+ CardContent,
+ Select,
+ MenuItem,
+ RadioGroup,
+ Radio,
+ FormControl,
+ FormControlLabel,
+ Button,
+} from '@mui/material'
import CourseMaterial from './common/CourseMaterial'
import SortableTopicList from './SortableTopicList'
@@ -67,6 +78,59 @@ class PeerReviewInfo extends React.Component {
}
}
+const ResearchConsent = ({ student }) => {
+ const [consent, setConsent] = useState(student.research_consent)
+ const dispatch = useDispatch()
+ const handleUpdate = () => {
+ dispatch(updateConsent(consent, student))
+ }
+ return (
+
+ Tutkimuslupa
+
+ Yliopiston tehtäviin kuuluvat opetuksen lisäksi myös tutkimuksen teko. Te opiskelijat olette
+ tärkeä osa prosessia, ilman teitä laadukasta yliopisto-opetuksen tutkimusta on vaikea tehdä.
+ Olemme tekemässä Helsingin yliopistossa tutkimusta generatiivisen tekoälyn käytöstä
+ opintojen aikana. Mikäli osallistut tutkimukseen, vastauksesi kysymyksiin voidaan yhdistää
+ arvosana- ja kurssisuoritustietoihisi, mutta sinua tai ryhmääsi ei voida tunnistaa
+ julkaistusta tutkimuksesta. Lisätietoja voi kysyä Matti Luukkaiselta (vastuuopettaja) tai
+ Outi Savolaiselta (opettaja).
+
+
+
+ Vertaisarviossa tai tuntikirjanpidossa antamasi vastaukset tekoälynkäytöstä eivät vaikuta
+ arvosanaasi tai kohteluusi kurssilla.
+
+
+ setConsent(!consent)}
+ >
+ }
+ label="Osallistun oppimiseen liittyvään tutkimukseen."
+ />
+ }
+ label="En osallistu oppimiseen liittyvään tutkimukseen."
+ />
+
+
+ Tallenna valintasi
+
+
+
+ )
+}
+
const GroupDetails = ({ groupDetails }) => {
return (
@@ -187,6 +251,7 @@ class RegistrationDetailsPage extends React.Component {
projectRegistrationConf,
peerReviewOpen,
peerReviewRound,
+ user,
} = this.props
if (groupDetails) {
@@ -198,6 +263,7 @@ class RegistrationDetailsPage extends React.Component {
peerReviewRound={peerReviewRound}
groupDetails={groupDetails}
/>
+
)
}
@@ -249,6 +315,7 @@ const mapStateToProps = (state) => {
peerReviewRound: state.registrationManagement.peerReviewRound,
peerReviewConf: state.registrationManagement.peerReviewConf,
projectRegistrationConf: state.registrationManagement.projectRegistrationConf,
+ user: state.login.user.user,
}
}
diff --git a/frontend/src/reducers/actions/userActions.js b/frontend/src/reducers/actions/userActions.js
index d7e0fd3..89eaa70 100644
--- a/frontend/src/reducers/actions/userActions.js
+++ b/frontend/src/reducers/actions/userActions.js
@@ -7,6 +7,18 @@ const updateIsInstructor = (user, isInstructor) => ({
instructor: isInstructor,
})
+export const updateConsent = (consent, user) => {
+ return async (dispatch) => {
+ const { user: updatedUser } = await userService.updateUserConsent(consent, user)
+ dispatch({
+ type: 'UPDATE_CONSENT',
+ payload: {
+ research_consent: updatedUser.research_consent,
+ },
+ })
+ }
+}
+
export const loginUser = (userCredentials) => {
return async (dispatch) => {
const { user, token } = await loginService.login(userCredentials)
diff --git a/frontend/src/reducers/loginReducer.js b/frontend/src/reducers/loginReducer.js
index d7acd45..fa5382a 100644
--- a/frontend/src/reducers/loginReducer.js
+++ b/frontend/src/reducers/loginReducer.js
@@ -17,6 +17,11 @@ const loginReducer = (state = initialState, action) => {
...state,
user: null,
}
+ case 'UPDATE_CONSENT':
+ return {
+ ...state,
+ research_consent: action.payload,
+ }
case 'UPDATE_USERNAME':
return {
...state,
diff --git a/frontend/src/services/user.js b/frontend/src/services/user.js
index 8e7c4b7..f95b5b7 100644
--- a/frontend/src/services/user.js
+++ b/frontend/src/services/user.js
@@ -20,6 +20,19 @@ const update = async (user) => {
return response.data
}
+const updateUserConsent = async (consent, user) => {
+ const config = {
+ headers: { Authorization: 'bearer ' + getUserToken() },
+ }
+ const studentNumber = user.student_number
+ const response = await axios.put(
+ url + '/consent/' + studentNumber,
+ { research_consent: consent },
+ config,
+ )
+ return response.data
+}
+
const checkInstructor = async (token) => {
const config = {
headers: { Authorization: 'bearer ' + token },
@@ -28,4 +41,4 @@ const checkInstructor = async (token) => {
return response.data
}
-export default { get, update, checkInstructor }
+export default { get, update, checkInstructor, updateUserConsent }