Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • tddd96-grupp11/teknikattan-scoring-system
1 result
Show changes
Commits on Source (10)
Showing
with 157 additions and 32 deletions
![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=client:test&key_text=Client+Coverage&key_width=110)
![coverage report](https://gitlab.liu.se/tddd96-grupp11/teknikattan-scoring-system/badges/dev/coverage.svg?job=server:test&key_text=Server+Coverage&key_width=115)
# Scoring system for Teknikåttan
This is the scoring system for Teknikåttan!
......
......@@ -17285,7 +17285,8 @@
},
"ssri": {
"version": "6.0.1",
"resolved": "",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
"integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
"requires": {
"figgy-pudding": "^3.5.1"
}
......
export enum ComponentTypes {
Text = 1,
Image,
QuestionAlternative,
Question,
}
......@@ -94,6 +94,16 @@ export interface TextComponent extends Component {
font: string
}
export interface QuestionAlternativeComponent extends Component {
export interface QuestionComponent extends Component {
id: number
x: number
y: number
w: number
h: number
slide_id: number
type_id: number
view_type_id: number
text: string
media: Media
question_id: number
}
......@@ -131,6 +131,7 @@ const CompetitionManager: React.FC = (props: any) => {
}
}
/** Start the competition by redirecting with URL with Code */
const handleStartCompetition = () => {
const operatorCode = codes.find((code) => code.view_type_id === 4)?.code
if (operatorCode) {
......@@ -138,6 +139,7 @@ const CompetitionManager: React.FC = (props: any) => {
}
}
/** Fetch all the connection codes from the server */
const getCodes = async (id: number) => {
await axios
.get(`/api/competitions/${id}/codes`)
......@@ -147,6 +149,7 @@ const CompetitionManager: React.FC = (props: any) => {
.catch(console.log)
}
/** Fetch all the teams from the server that is connected to a specific competition*/
const getTeams = async (id: number) => {
await axios
.get(`/api/competitions/${id}/teams`)
......@@ -159,6 +162,7 @@ const CompetitionManager: React.FC = (props: any) => {
})
}
/** Fetch the copetition name from the server */
const getCompetitionName = async () => {
await axios
.get(`/api/competitions/${activeId}`)
......@@ -198,16 +202,18 @@ const CompetitionManager: React.FC = (props: any) => {
return typeName
}
/** Handles the opening of the code dialog box */
const handleOpenDialog = async () => {
await getCompetitionName()
setDialogIsOpen(true)
}
/** Handles the closing of the code dialog box */
const handleCloseDialog = () => {
setDialogIsOpen(false)
setAnchorEl(null)
}
/** Function that copies an existing competition */
const handleDuplicateCompetition = async () => {
if (activeId) {
await axios
......
......@@ -6,6 +6,11 @@ import NumberOfCompetitions from './components/NumberOfCompetitions'
import NumberOfRegions from './components/NumberOfRegions'
import NumberOfUsers from './components/NumberOfUsers'
/**
* This is the first page that is shown after a user logs in. It shows som statistics about the site.
*
*/
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
......
......@@ -2,6 +2,8 @@ import { Box, Typography } from '@material-ui/core'
import React from 'react'
import { useAppSelector } from '../../../../hooks'
/** This component show information about the currently logged in user */
const CurrentUser: React.FC = () => {
const currentUser = useAppSelector((state: { user: { userInfo: any } }) => state.user.userInfo)
return (
......
......@@ -2,6 +2,8 @@ import { Box, Typography } from '@material-ui/core'
import React from 'react'
import { useAppSelector } from '../../../../hooks'
/** Shows how many competitions is on the system */
const NumberOfCompetitions: React.FC = () => {
const competitions = useAppSelector((state) => state.statistics.competitions)
......
......@@ -3,6 +3,8 @@ import React, { useEffect } from 'react'
import { getCities } from '../../../../actions/cities'
import { useAppDispatch, useAppSelector } from '../../../../hooks'
/** Shows how many regions is on the system */
const NumberOfRegions: React.FC = () => {
const regions = useAppSelector((state) => state.statistics.regions)
const dispatch = useAppDispatch()
......
......@@ -3,6 +3,8 @@ import React, { useEffect } from 'react'
import { getSearchUsers } from '../../../../actions/searchUser'
import { useAppDispatch, useAppSelector } from '../../../../hooks'
/** Shows how many users are on the system */
const NumberOfUsers: React.FC = () => {
const usersTotal = useAppSelector((state) => state.statistics.users)
const dispatch = useAppDispatch()
......
......@@ -30,6 +30,7 @@ const useStyles = makeStyles((theme: Theme) =>
type formType = FormModel<AddCityModel>
/** add a region form with some constraints. */
const schema: Yup.SchemaOf<formType> = Yup.object({
model: Yup.object()
.shape({
......
......@@ -14,6 +14,9 @@ import { getCities } from '../../../actions/cities'
import { useAppDispatch, useAppSelector } from '../../../hooks'
import { RemoveMenuItem, TopBar } from '../styledComp'
import AddRegion from './AddRegion'
/** shows all the regions in a list */
const useStyles = makeStyles((theme: Theme) =>
createStyles({
table: {
......
/** Add a user component */
import { Button, FormControl, InputLabel, MenuItem, Popover, TextField } from '@material-ui/core'
import PersonAddIcon from '@material-ui/icons/PersonAdd'
import { Alert, AlertTitle } from '@material-ui/lab'
......@@ -16,6 +18,7 @@ type formType = FormModel<AddUserModel>
const noRoleSelected = 'Välj roll'
const noCitySelected = 'Välj stad'
/** Form when adding a user with some constraints */
const userSchema: Yup.SchemaOf<formType> = Yup.object({
model: Yup.object()
.shape({
......
/** This is the login page, it contains two child components, one is
* to log in as an admin, the other is to connect to a competition using a code
*/
import { AppBar, Tab, Tabs } from '@material-ui/core'
import React from 'react'
import AdminLogin from './components/AdminLogin'
......
/** Component that handles the log in when a user is an admin */
import { Button, TextField, Typography } from '@material-ui/core'
import { Alert, AlertTitle } from '@material-ui/lab'
import { Formik, FormikHelpers } from 'formik'
......
/** Component that handles the log in when a user connects to a competition through a code */
import { Button, TextField, Typography } from '@material-ui/core'
import { Alert, AlertTitle } from '@material-ui/lab'
import { Formik } from 'formik'
......@@ -38,7 +40,7 @@ const CompetitionLogin: React.FC = () => {
const handleCompetitionSubmit = async (values: CompetitionLoginFormModel) => {
dispatch(loginCompetition(values.model.code, history, true))
}
return (
<Formik
initialValues={competitionInitialValues}
......
import { Card, Divider, ListItem, Typography } from '@material-ui/core'
import React from 'react'
import { useAppSelector } from '../../../hooks'
import AnswerMultiple from './answerComponents/AnswerMultiple'
import AnswerSingle from './answerComponents/AnswerSingle'
import AnswerText from './answerComponents/AnswerText'
import { Center } from './styled'
type QuestionComponentProps = {
variant: 'editor' | 'presentation'
}
const QuestionComponentDisplay = ({ variant }: QuestionComponentProps) => {
const activeSlide = useAppSelector((state) => {
if (variant === 'editor')
return state.editor.competition.slides.find((slide) => slide.id === state.editor.activeSlideId)
return state.presentation.competition.slides.find((slide) => slide.id === state.presentation.slide?.id)
})
const timer = activeSlide?.timer
const total_score = activeSlide?.questions[0].total_score
const questionName = activeSlide?.questions[0].name
const questionTypeId = activeSlide?.questions[0].type_id
const questionTypeName = useAppSelector(
(state) => state.types.questionTypes.find((qType) => qType.id === questionTypeId)?.name
)
const getAlternatives = () => {
switch (questionTypeName) {
case 'Text':
if (activeSlide) {
return <AnswerText activeSlide={activeSlide} competitionId={activeSlide.competition_id.toString()} />
}
return
case 'Practical':
return
case 'Multiple':
if (activeSlide) {
return (
<AnswerMultiple
variant={variant}
activeSlide={activeSlide}
competitionId={activeSlide.competition_id.toString()}
/>
)
}
return
case 'Single':
if (activeSlide) {
return (
<AnswerSingle
variant={variant}
activeSlide={activeSlide}
competitionId={activeSlide.competition_id.toString()}
/>
)
}
return
default:
break
}
}
return (
<Card style={{ maxHeight: '100%', overflowY: 'auto' }}>
<ListItem>
<Center style={{ justifyContent: 'space-evenly' }}>
<Typography>Poäng: {total_score}</Typography>
<Typography>{questionName}</Typography>
<Typography>Timer: {timer}</Typography>
</Center>
</ListItem>
<Divider />
{getAlternatives()}
</Card>
)
}
export default QuestionComponentDisplay
......@@ -9,6 +9,7 @@ import { Component, ImageComponent, TextComponent } from '../../../interfaces/Ap
import { Position, Size } from '../../../interfaces/Components'
import { RemoveMenuItem } from '../../admin/styledComp'
import ImageComponentDisplay from './ImageComponentDisplay'
import QuestionComponentDisplay from './QuestionComponentDisplay'
import { HoverContainer } from './styled'
import TextComponentDisplay from './TextComponentDisplay'
//import NestedMenuItem from 'material-ui-nested-menu-item'
......@@ -126,6 +127,12 @@ const RndComponent = ({ component, width, height, scale }: RndComponentProps) =>
/>
</HoverContainer>
)
case ComponentTypes.Question:
return (
<HoverContainer hover={hover}>
<QuestionComponentDisplay variant="editor" />
</HoverContainer>
)
default:
break
}
......
......@@ -77,15 +77,7 @@ const SlideDisplay = ({ variant, activeViewTypeId }: SlideDisplayProps) => {
scale={scale}
/>
)
return (
<PresentationComponent
height={height}
width={width}
key={component.id}
component={component}
scale={scale}
/>
)
return <PresentationComponent key={component.id} component={component} scale={scale} />
})}
</SlideEditorPaper>
</SlideEditorContainerRatio>
......
/* This file compiles and renders the right hand slide settings bar, under the tab "SIDA".
*/
import { Divider, List, ListItem, ListItemText, TextField, Typography } from '@material-ui/core'
import React, { useState } from 'react'
import { Divider } from '@material-ui/core'
import React from 'react'
import { useParams } from 'react-router-dom'
import { useAppSelector } from '../../../hooks'
import BackgroundImageSelect from './BackgroundImageSelect'
import Images from './slideSettingsComponents/Images'
import Instructions from './slideSettingsComponents/Instructions'
import MultipleChoiceAlternatives from './slideSettingsComponents/MultipleChoiceAlternatives'
import QuestionSettings from './slideSettingsComponents/QuestionSettings'
import SingleChoiceAlternatives from './slideSettingsComponents/SingleChoiceAlternatives'
import SlideType from './slideSettingsComponents/SlideType'
import { Center, ImportedImage, SettingsList, PanelContainer } from './styled'
import Timer from './slideSettingsComponents/Timer'
import Images from './slideSettingsComponents/Images'
import Texts from './slideSettingsComponents/Texts'
import QuestionSettings from './slideSettingsComponents/QuestionSettings'
import BackgroundImageSelect from './BackgroundImageSelect'
import Timer from './slideSettingsComponents/Timer'
import { PanelContainer, SettingsList } from './styled'
interface CompetitionParams {
competitionId: string
......@@ -36,19 +37,21 @@ const SlideSettings: React.FC = () => {
</SettingsList>
{activeSlide?.questions[0] && <QuestionSettings activeSlide={activeSlide} competitionId={competitionId} />}
{
// Choose answer alternatives depending on the slide type
// Choose answer alternatives, depending on the slide type
}
{activeSlide?.questions[0]?.type_id === 1 && (
<Instructions activeSlide={activeSlide} competitionId={competitionId} />
)}
{activeSlide?.questions[0]?.type_id === 2 && (
{(activeSlide?.questions[0]?.type_id === 1 || activeSlide?.questions[0]?.type_id === 2) && (
<Instructions activeSlide={activeSlide} competitionId={competitionId} />
)}
{activeSlide?.questions[0]?.type_id === 3 && (
<MultipleChoiceAlternatives activeSlide={activeSlide} competitionId={competitionId} />
)}
{activeSlide?.questions[0]?.type_id === 4 && (
<SingleChoiceAlternatives activeSlide={activeSlide} competitionId={competitionId} />
)}
{activeSlide && (
<Texts activeViewTypeId={activeViewTypeId} activeSlide={activeSlide} competitionId={competitionId} />
)}
......