Make update consent for research possible

This commit is contained in:
outisa
2026-10-07 21:39:43 +03:00
parent c6f7c8edeb
commit 8410871a06
7 changed files with 141 additions and 5 deletions
+20
View File
@@ -2,6 +2,26 @@ const usersRouter = require('express').Router()
const db = require('../models/index') const db = require('../models/index')
const { checkLogin, checkInstructor } = require('../middleware') 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) => { usersRouter.put('/:studentNumber', checkLogin, async (req, res) => {
const { email } = req.body const { email } = req.body
const { studentNumber } = req.params const { studentNumber } = req.params
@@ -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')
},
}
+4
View File
@@ -23,6 +23,10 @@ module.exports = (sequelize, Sequelize) => {
type: Sequelize.BOOLEAN, type: Sequelize.BOOLEAN,
defaultValue: false, defaultValue: false,
}, },
research_consent: {
type: Sequelize.BOOLEAN,
defaultValue: false,
},
}, },
{ {
underscored: true, underscored: true,
@@ -1,15 +1,26 @@
import { withRouter } from '../utils/withRouter' import { withRouter } from '../utils/withRouter'
import React from 'react' import React, { useState } from 'react'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { connect } from 'react-redux' import { connect, useDispatch } from 'react-redux'
import registrationActions from '../reducers/actions/registrationActions' import registrationActions from '../reducers/actions/registrationActions'
import { setError } from '../reducers/actions/notificationActions' import { setError } from '../reducers/actions/notificationActions'
import { updateConsent } from '../reducers/actions/userActions'
import peerReviewService from '../services/peerReview' import peerReviewService from '../services/peerReview'
import Typography from '@mui/material/Typography' 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 CourseMaterial from './common/CourseMaterial'
import SortableTopicList from './SortableTopicList' 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 (
<div>
<Typography variant="h2">Tutkimuslupa</Typography>
<Typography style={{ width: '60%' }}>
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).
</Typography>
<br />
<Typography style={{ width: '60%' }}>
Vertaisarviossa tai tuntikirjanpidossa antamasi vastaukset tekoälynkäytöstä eivät vaikuta
arvosanaasi tai kohteluusi kurssilla.
</Typography>
<FormControl>
<RadioGroup
name="research-consent-group"
value={consent ? 'consentGiven' : 'denied'}
onChange={() => setConsent(!consent)}
>
<FormControlLabel
value={'consentGiven'}
control={<Radio />}
label="Osallistun oppimiseen liittyvään tutkimukseen."
/>
<FormControlLabel
value={'denied'}
control={<Radio />}
label="En osallistu oppimiseen liittyvään tutkimukseen."
/>
</RadioGroup>
<Button
style={{ marginRight: '10px', height: '40px', width: 250 }}
color="inherit"
variant="outlined"
onClick={handleUpdate}
>
Tallenna valintasi
</Button>
</FormControl>
</div>
)
}
const GroupDetails = ({ groupDetails }) => { const GroupDetails = ({ groupDetails }) => {
return ( return (
<div> <div>
@@ -187,6 +251,7 @@ class RegistrationDetailsPage extends React.Component {
projectRegistrationConf, projectRegistrationConf,
peerReviewOpen, peerReviewOpen,
peerReviewRound, peerReviewRound,
user,
} = this.props } = this.props
if (groupDetails) { if (groupDetails) {
@@ -198,6 +263,7 @@ class RegistrationDetailsPage extends React.Component {
peerReviewRound={peerReviewRound} peerReviewRound={peerReviewRound}
groupDetails={groupDetails} groupDetails={groupDetails}
/> />
<ResearchConsent student={user} />
</div> </div>
) )
} }
@@ -249,6 +315,7 @@ const mapStateToProps = (state) => {
peerReviewRound: state.registrationManagement.peerReviewRound, peerReviewRound: state.registrationManagement.peerReviewRound,
peerReviewConf: state.registrationManagement.peerReviewConf, peerReviewConf: state.registrationManagement.peerReviewConf,
projectRegistrationConf: state.registrationManagement.projectRegistrationConf, projectRegistrationConf: state.registrationManagement.projectRegistrationConf,
user: state.login.user.user,
} }
} }
@@ -7,6 +7,18 @@ const updateIsInstructor = (user, isInstructor) => ({
instructor: 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) => { export const loginUser = (userCredentials) => {
return async (dispatch) => { return async (dispatch) => {
const { user, token } = await loginService.login(userCredentials) const { user, token } = await loginService.login(userCredentials)
+5
View File
@@ -17,6 +17,11 @@ const loginReducer = (state = initialState, action) => {
...state, ...state,
user: null, user: null,
} }
case 'UPDATE_CONSENT':
return {
...state,
research_consent: action.payload,
}
case 'UPDATE_USERNAME': case 'UPDATE_USERNAME':
return { return {
...state, ...state,
+14 -1
View File
@@ -20,6 +20,19 @@ const update = async (user) => {
return response.data 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 checkInstructor = async (token) => {
const config = { const config = {
headers: { Authorization: 'bearer ' + token }, headers: { Authorization: 'bearer ' + token },
@@ -28,4 +41,4 @@ const checkInstructor = async (token) => {
return response.data return response.data
} }
export default { get, update, checkInstructor } export default { get, update, checkInstructor, updateUserConsent }