diff --git a/client/package-lock.json b/client/package-lock.json
index 667b75859fe71467505839e687c7e478b8a52834..72fcea719f2d7503990a778ded3a56f7b0e55e5f 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -2526,6 +2526,15 @@
         "csstype": "^3.0.2"
       }
     },
+    "@types/react-beautiful-dnd": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz",
+      "integrity": "sha512-by80tJ8aTTDXT256Gl+RfLRtFjYbUWOnZuEigJgNsJrSEGxvFe5eY6k3g4VIvf0M/6+xoLgfYWoWonlOo6Wqdg==",
+      "dev": true,
+      "requires": {
+        "@types/react": "*"
+      }
+    },
     "@types/react-dom": {
       "version": "17.0.0",
       "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz",
@@ -5161,6 +5170,14 @@
         "postcss": "^7.0.5"
       }
     },
+    "css-box-model": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
+      "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
+      "requires": {
+        "tiny-invariant": "^1.0.6"
+      }
+    },
     "css-color-keywords": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
@@ -11058,6 +11075,11 @@
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
     },
+    "memoize-one": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+      "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+    },
     "memory-fs": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
@@ -13519,6 +13541,11 @@
         "performance-now": "^2.1.0"
       }
     },
+    "raf-schd": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz",
+      "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ=="
+    },
     "railroad-diagrams": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
@@ -13610,6 +13637,20 @@
       "resolved": "https://registry.npmjs.org/react-axios/-/react-axios-2.0.4.tgz",
       "integrity": "sha512-QsTq7C/NwsjfrSmFVxPo29BdX6DtLpRF0fZTJv5/R4BanOm+c4639B3Xb4lF83ZfAOX5IW8XG7htz4V+WNF+WA=="
     },
+    "react-beautiful-dnd": {
+      "version": "13.1.0",
+      "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.0.tgz",
+      "integrity": "sha512-aGvblPZTJowOWUNiwd6tNfEpgkX5OxmpqxHKNW/4VmvZTNTbeiq7bA3bn5T+QSF2uibXB0D1DmJsb1aC/+3cUA==",
+      "requires": {
+        "@babel/runtime": "^7.9.2",
+        "css-box-model": "^1.2.0",
+        "memoize-one": "^5.1.1",
+        "raf-schd": "^4.0.2",
+        "react-redux": "^7.2.0",
+        "redux": "^4.0.4",
+        "use-memo-one": "^1.1.1"
+      }
+    },
     "react-dev-utils": {
       "version": "11.0.3",
       "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.3.tgz",
@@ -16568,6 +16609,11 @@
       "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
       "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
     },
+    "use-memo-one": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz",
+      "integrity": "sha512-u2qFKtxLsia/r8qG0ZKkbytbztzRb317XCkT7yP8wxL0tZ/CzK2G+WWie5vWvpyeP7+YoPIwbJoIHJ4Ba4k0oQ=="
+    },
     "util": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
@@ -17239,8 +17285,7 @@
         },
         "ssri": {
           "version": "6.0.1",
-          "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
-          "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+          "resolved": "",
           "requires": {
             "figgy-pudding": "^3.5.1"
           }
diff --git a/client/package.json b/client/package.json
index 8733d1d45b7c2e4c2349167573e7411aa66afd45..a0c8b7f5c74a6587f48cdf6c7d478311f2529185 100644
--- a/client/package.json
+++ b/client/package.json
@@ -24,6 +24,7 @@
     "jwt-decode": "^3.1.2",
     "react": "^17.0.1",
     "react-axios": "^2.0.4",
+    "react-beautiful-dnd": "^13.1.0",
     "react-dom": "^17.0.1",
     "react-redux": "^7.2.2",
     "react-rnd": "^10.2.4",
@@ -41,6 +42,7 @@
   },
   "devDependencies": {
     "@types/enzyme": "^3.10.8",
+    "@types/react-beautiful-dnd": "^13.0.0",
     "@types/react-redux": "^7.1.16",
     "@types/react-router-dom": "^5.1.7",
     "@types/redux-mock-store": "^1.0.2",
diff --git a/client/src/Main.tsx b/client/src/Main.tsx
index 5cd27cc3d83e96bda772e2e9b07282903ed069f5..a44d182334d526e3632f038f8c8b1b5875d8dc8b 100644
--- a/client/src/Main.tsx
+++ b/client/src/Main.tsx
@@ -28,30 +28,10 @@ const Main: React.FC = () => {
           component={PresentationEditorPage}
         />
         <Route exact path="/:code" component={ViewSelectPage} />
-        <SecureRoute
-          authLevel="competition"
-          exact
-          path="/team/competition-id=:competitionId"
-          component={TeamViewPage}
-        />
-        <SecureRoute
-          authLevel="competition"
-          exact
-          path="/operator/competition-id=:competitionId"
-          component={OperatorViewPage}
-        />
-        <SecureRoute
-          authLevel="competition"
-          exact
-          path="/judge/competition-id=:competitionId"
-          component={JudgeViewPage}
-        />
-        <SecureRoute
-          authLevel="competition"
-          exact
-          path="/audience/competition-id=:competitionId"
-          component={AudienceViewPage}
-        />
+        <SecureRoute authLevel="Team" exact path="/view/team" component={TeamViewPage} />
+        <SecureRoute authLevel="Operator" exact path="/view/operator" component={OperatorViewPage} />
+        <SecureRoute authLevel="Judge" exact path="/view/judge" component={JudgeViewPage} />
+        <SecureRoute authLevel="Audience" exact path="/view/audience" component={AudienceViewPage} />
       </Switch>
     </BrowserRouter>
   )
diff --git a/client/src/actions/competitionLogin.ts b/client/src/actions/competitionLogin.ts
index 448eec249f360acbadeb6161abac6412daccb32b..97dc76e4499551bbfba87222aedae6e7a30bad72 100644
--- a/client/src/actions/competitionLogin.ts
+++ b/client/src/actions/competitionLogin.ts
@@ -4,12 +4,14 @@ This file handles actions for the competitionLogin redux state
 
 import axios from 'axios'
 import { History } from 'history'
-import { AppDispatch } from '../store'
+import { AppDispatch, RootState } from '../store'
+import { getPresentationCompetition } from './presentation'
 import Types from './types'
 
 // Action creator to attempt to login with competition code
 export const loginCompetition = (code: string, history: History, redirect: boolean) => async (
-  dispatch: AppDispatch
+  dispatch: AppDispatch,
+  getState: () => RootState
 ) => {
   dispatch({ type: Types.LOADING_COMPETITION_LOGIN })
   await axios
@@ -27,7 +29,8 @@ export const loginCompetition = (code: string, history: History, redirect: boole
           view: res.data.view,
         },
       })
-      if (redirect && res.data && res.data.view_type_id) {
+      getPresentationCompetition(res.data.competition_id)(dispatch, getState)
+      if (redirect && res.data && res.data.view) {
         history.push(`/${code}`)
       }
     })
diff --git a/client/src/actions/types.ts b/client/src/actions/types.ts
index b422f95423539cc2f2ea0bf4e7ecdc58f78bdbc8..0ca8a02ffa1d115e165091276b740131be9d9758 100644
--- a/client/src/actions/types.ts
+++ b/client/src/actions/types.ts
@@ -15,7 +15,6 @@ export default {
   SET_ERRORS: 'SET_ERRORS',
   CLEAR_ERRORS: 'CLEAR_ERRORS',
   SET_COMPETITION_LOGIN_DATA: 'SET_COMPETITION_LOGIN_DATA',
-  SET_COMPETITION_LOGIN_AUTHENTICATED: 'SET_COMPETITION_LOGIN_AUTHENTICATED',
   SET_COMPETITION_LOGIN_UNAUTHENTICATED: 'SET_COMPETITION_LOGIN_UNAUTHENTICATED',
   SET_COMPETITION_LOGIN_ERRORS: 'SET_COMPETITION_LOGIN_ERRORS',
   CLEAR_COMPETITION_LOGIN_ERRORS: 'CLEAR_COMPETITION_LOGIN_ERRORS',
diff --git a/client/src/pages/admin/competitions/CompetitionManager.tsx b/client/src/pages/admin/competitions/CompetitionManager.tsx
index b7184d55595b23333c895604b2d311a0a80e530c..affd5c26c192025afb800314a9ce1728c9d31935 100644
--- a/client/src/pages/admin/competitions/CompetitionManager.tsx
+++ b/client/src/pages/admin/competitions/CompetitionManager.tsx
@@ -1,17 +1,17 @@
 import {
+  Box,
   Button,
-  Menu,
-  ListItem,
-  TablePagination,
-  TextField,
-  Typography,
   Dialog,
-  DialogTitle,
-  DialogContent,
   DialogActions,
+  DialogContent,
+  DialogTitle,
+  ListItem,
   ListItemText,
+  Menu,
+  TablePagination,
+  TextField,
   Tooltip,
-  Box,
+  Typography,
 } from '@material-ui/core'
 import FormControl from '@material-ui/core/FormControl'
 import InputLabel from '@material-ui/core/InputLabel'
@@ -25,7 +25,10 @@ import TableCell from '@material-ui/core/TableCell'
 import TableContainer from '@material-ui/core/TableContainer'
 import TableHead from '@material-ui/core/TableHead'
 import TableRow from '@material-ui/core/TableRow'
+import FileCopyIcon from '@material-ui/icons/FileCopy'
+import LinkIcon from '@material-ui/icons/Link'
 import MoreHorizIcon from '@material-ui/icons/MoreHoriz'
+import RefreshIcon from '@material-ui/icons/Refresh'
 import axios from 'axios'
 import React, { useEffect } from 'react'
 import { Link, useHistory } from 'react-router-dom'
@@ -35,8 +38,6 @@ import { Team } from '../../../interfaces/ApiModels'
 import { CompetitionFilterParams } from '../../../interfaces/FilterParams'
 import { FilterContainer, RemoveMenuItem, TopBar, YearFilterTextField } from '../styledComp'
 import AddCompetition from './AddCompetition'
-import FileCopyIcon from '@material-ui/icons/FileCopy'
-import RefreshIcon from '@material-ui/icons/Refresh'
 
 /**
  * Component description:
@@ -83,14 +84,16 @@ const CompetitionManager: React.FC = (props: any) => {
   const filterParams = useAppSelector((state) => state.competitions.filterParams)
   const competitionTotal = useAppSelector((state) => state.competitions.total)
   const cities = useAppSelector((state) => state.cities.cities)
-
   const classes = useStyles()
   const noFilterText = 'Alla'
   const dispatch = useAppDispatch()
   const history = useHistory()
+
   const handleClick = (event: React.MouseEvent<HTMLButtonElement>, id: number) => {
-    setAnchorEl(event.currentTarget)
     setActiveId(id)
+    getCodes(id)
+    getTeams(id)
+    setAnchorEl(event.currentTarget)
   }
 
   const handleClose = () => {
@@ -129,24 +132,26 @@ const CompetitionManager: React.FC = (props: any) => {
   }
 
   const handleStartCompetition = () => {
-    history.push(`/operator/id=${activeId}&code=123123`)
+    const operatorCode = codes.find((code) => code.view_type_id === 4)?.code
+    if (operatorCode) {
+      history.push(`/${operatorCode}`)
+    }
   }
 
-  const getCodes = async () => {
+  const getCodes = async (id: number) => {
     await axios
-      .get(`/api/competitions/${activeId}/codes`)
+      .get(`/api/competitions/${id}/codes`)
       .then((response) => {
-        console.log(response.data)
         setCodes(response.data.items)
       })
       .catch(console.log)
   }
 
-  const getTeams = async () => {
+  const getTeams = async (id: number) => {
     await axios
-      .get(`/api/competitions/${activeId}/teams`)
+      .get(`/api/competitions/${id}/teams`)
       .then((response) => {
-        console.log(response.data.items)
+        // console.log(response.data.items)
         setTeams(response.data.items)
       })
       .catch((err) => {
@@ -158,7 +163,7 @@ const CompetitionManager: React.FC = (props: any) => {
     await axios
       .get(`/api/competitions/${activeId}`)
       .then((response) => {
-        console.log(response.data.name)
+        // console.log(response.data.name)
         setCompetitionName(response.data.name)
       })
       .catch((err) => {
@@ -194,8 +199,6 @@ const CompetitionManager: React.FC = (props: any) => {
   }
 
   const handleOpenDialog = async () => {
-    await getCodes()
-    await getTeams()
     await getCompetitionName()
     setDialogIsOpen(true)
   }
@@ -225,15 +228,17 @@ const CompetitionManager: React.FC = (props: any) => {
   }
 
   const refreshCode = async (code: Code) => {
-    await axios
-      .put(`/api/competitions/${activeId}/codes/${code.id}`)
-      .then(() => {
-        getCodes()
-        dispatch(getCompetitions())
-      })
-      .catch(({ response }) => {
-        console.warn(response.data)
-      })
+    if (activeId) {
+      await axios
+        .put(`/api/competitions/${activeId}/codes/${code.id}`)
+        .then(() => {
+          getCodes(activeId)
+          dispatch(getCompetitions())
+        })
+        .catch(({ response }) => {
+          console.warn(response.data)
+        })
+    }
   }
 
   return (
@@ -373,6 +378,16 @@ const CompetitionManager: React.FC = (props: any) => {
                   <FileCopyIcon fontSize="small" />
                 </Button>
               </Tooltip>
+              <Tooltip title="Kopiera länk" arrow>
+                <Button
+                  margin-right="0px"
+                  onClick={() => {
+                    navigator.clipboard.writeText(`${window.location.host}/${code.code}`)
+                  }}
+                >
+                  <LinkIcon fontSize="small" />
+                </Button>
+              </Tooltip>
             </ListItem>
           ))}
         </DialogContent>
diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.test.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.test.tsx
index 5426152ff33783745f8dc1181237cd2926b0a16a..7254a69d3bdae4e39c6ce1097dc06e753ff333f0 100644
--- a/client/src/pages/presentationEditor/PresentationEditorPage.test.tsx
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.test.tsx
@@ -13,7 +13,7 @@ it('renders presentation editor', () => {
       id: 0,
       year: 0,
       city_id: 0,
-      slides: [{ id: 5 }],
+      slides: [{ id: 5, order: 2 }],
       teams: [],
     },
   }
diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
index 886f8d19a24ea6f8d7469b1481a5a11def854469..ddbe7468df6489d4abe69258b4fb504b90dde3b5 100644
--- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
@@ -1,9 +1,10 @@
-import { Button, CircularProgress, Divider, Menu, MenuItem } from '@material-ui/core'
+import { Button, ButtonGroup, CircularProgress, Divider, Menu, MenuItem } from '@material-ui/core'
 import CssBaseline from '@material-ui/core/CssBaseline'
 import ListItemText from '@material-ui/core/ListItemText'
 import AddOutlinedIcon from '@material-ui/icons/AddOutlined'
 import axios from 'axios'
 import React, { useEffect, useState } from 'react'
+import { DragDropContext, Draggable, Droppable, DropResult } from 'react-beautiful-dnd'
 import { Link, useParams } from 'react-router-dom'
 import { getCities } from '../../actions/cities'
 import { getEditorCompetition, setEditorSlideId, setEditorViewId } from '../../actions/editor'
@@ -31,7 +32,6 @@ import {
   ToolBarContainer,
   ToolbarMargin,
   ViewButton,
-  ViewButtonGroup,
 } from './styled'
 
 const initialState = {
@@ -101,7 +101,7 @@ const PresentationEditorPage: React.FC = () => {
   }
 
   const viewTypes = useAppSelector((state) => state.types.viewTypes)
-  const [activeViewTypeName, setActiveViewTypeName] = useState('')
+  const [activeViewTypeName, setActiveViewTypeName] = useState('Audience')
   const changeView = (clickedViewTypeName: string) => {
     setActiveViewTypeName(clickedViewTypeName)
     const clickedViewTypeId = viewTypes.find((viewType) => viewType.name === clickedViewTypeName)?.id
@@ -110,6 +110,20 @@ const PresentationEditorPage: React.FC = () => {
     }
   }
 
+  const onDragEnd = async (result: DropResult) => {
+    // dropped outside the list
+    if (!result.destination) {
+      return
+    }
+    const draggedIndex = result.source.index
+    const draggedSlideId = competition.slides.find((slide) => slide.order === draggedIndex)?.id
+    if (draggedSlideId) {
+      await axios
+        .put(`/api/competitions/${competitionId}/slides/${draggedSlideId}/order`, { order: result.destination.index })
+        .then(() => dispatch(getEditorCompetition(competitionId)))
+        .catch(console.log)
+    }
+  }
   return (
     <PresentationEditorContainer>
       <CssBaseline />
@@ -122,10 +136,9 @@ const PresentationEditorPage: React.FC = () => {
             {competition.name}
           </CompetitionName>
 
-          <ViewButtonGroup>
+          <ButtonGroup color="secondary" variant="contained">
             <ViewButton
               $activeView={activeViewTypeName === 'Audience'}
-              variant="contained"
               color="secondary"
               onClick={() => changeView('Audience')}
             >
@@ -133,40 +146,53 @@ const PresentationEditorPage: React.FC = () => {
             </ViewButton>
             <ViewButton
               $activeView={activeViewTypeName === 'Team'}
-              variant="contained"
               color="secondary"
               onClick={() => changeView('Team')}
             >
               Deltagarvy
             </ViewButton>
-          </ViewButtonGroup>
+          </ButtonGroup>
         </ToolBarContainer>
       </AppBarEditor>
       <LeftDrawer $leftDrawerWidth={leftDrawerWidth} $rightDrawerWidth={undefined} variant="permanent" anchor="left">
         <FillLeftContainer $leftDrawerWidth={leftDrawerWidth} $rightDrawerWidth={undefined}>
           <ToolbarMargin />
           <SlideList>
-            {competition.slides &&
-              competition.slides.map((slide) => (
-                <SlideListItem
-                  divider
-                  button
-                  key={slide.id}
-                  selected={slide.id === activeSlideId}
-                  onClick={() => setActiveSlideId(slide.id)}
-                  onContextMenu={(event) => handleRightClick(event, slide.id)}
-                >
-                  {renderSlideIcon(slide)}
-                  <ListItemText primary={`Sida ${slide.order + 1}`} />
-                </SlideListItem>
-              ))}
+            <DragDropContext onDragEnd={onDragEnd}>
+              <Droppable droppableId="droppable">
+                {(provided) => (
+                  <div key={provided.innerRef.toString()} ref={provided.innerRef} {...provided.droppableProps}>
+                    {competition.slides &&
+                      competition.slides.map((slide, index) => (
+                        <Draggable key={slide.order} draggableId={slide.id.toString()} index={index}>
+                          {(provided, snapshot) => (
+                            <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
+                              <SlideListItem
+                                divider
+                                button
+                                selected={slide.id === activeSlideId}
+                                onClick={() => setActiveSlideId(slide.id)}
+                                onContextMenu={(event) => handleRightClick(event, slide.id)}
+                              >
+                                {renderSlideIcon(slide)}
+                                <ListItemText primary={`Sida ${slide.order + 1}`} />
+                              </SlideListItem>
+                            </div>
+                          )}
+                        </Draggable>
+                      ))}
+                    {provided.placeholder}
+                  </div>
+                )}
+              </Droppable>
+            </DragDropContext>
           </SlideList>
           <PositionBottom>
             <Divider />
             <SlideListItem divider button onClick={() => createNewSlide()}>
               <ListItemText primary="Ny sida" />
               <AddOutlinedIcon />
-              </SlideListItem>
+            </SlideListItem>
           </PositionBottom>
         </FillLeftContainer>
       </LeftDrawer>
@@ -187,7 +213,7 @@ const PresentationEditorPage: React.FC = () => {
 
       <Content leftDrawerWidth={leftDrawerWidth} rightDrawerWidth={rightDrawerWidth}>
         <InnerContent>
-          <SlideDisplay variant="editor" activeViewTypeId={activeViewTypeId} />
+          {competitionLoading && <SlideDisplay variant="editor" activeViewTypeId={activeViewTypeId} />}
         </InnerContent>
       </Content>
       <Menu
diff --git a/client/src/pages/presentationEditor/components/RndComponent.tsx b/client/src/pages/presentationEditor/components/RndComponent.tsx
index c13126be31fc2f0f55618b19be5e14527f28b232..4c09280042bd038fee1e3adc4b5bf3b7aef8ef6a 100644
--- a/client/src/pages/presentationEditor/components/RndComponent.tsx
+++ b/client/src/pages/presentationEditor/components/RndComponent.tsx
@@ -1,15 +1,18 @@
-import { Card, IconButton, Tooltip } from '@material-ui/core'
+import { Card, IconButton, Menu, MenuItem, Tooltip } from '@material-ui/core'
 import axios from 'axios'
 import React, { useEffect, useState } from 'react'
 import { Rnd } from 'react-rnd'
+import { getEditorCompetition } from '../../../actions/editor'
 import { ComponentTypes } from '../../../enum/ComponentTypes'
-import { useAppSelector } from '../../../hooks'
+import { useAppDispatch, useAppSelector } from '../../../hooks'
 import { Component, ImageComponent, TextComponent } from '../../../interfaces/ApiModels'
 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'
 
 type RndComponentProps = {
   component: Component
@@ -18,6 +21,8 @@ type RndComponentProps = {
   scale: number
 }
 
+const initialMenuState = { menuIsOpen: false, mouseX: null, mouseY: null, componentId: null }
+
 const RndComponent = ({ component, width, height, scale }: RndComponentProps) => {
   const [hover, setHover] = useState(false)
   const [currentPos, setCurrentPos] = useState<Position>({ x: component.x, y: component.y })
@@ -28,6 +33,14 @@ const RndComponent = ({ component, width, height, scale }: RndComponentProps) =>
   const typeName = useAppSelector(
     (state) => state.types.componentTypes.find((componentType) => componentType.id === component.type_id)?.name
   )
+  const [menuState, setMenuState] = useState<{
+    menuIsOpen: boolean
+    mouseX: null | number
+    mouseY: null | number
+    componentId: null | number
+  }>(initialMenuState)
+  const dispatch = useAppDispatch()
+
   const handleUpdatePos = (pos: Position) => {
     axios.put(`/api/competitions/${competitionId}/slides/${slideId}/components/${component.id}`, {
       x: pos.x,
@@ -50,6 +63,37 @@ const RndComponent = ({ component, width, height, scale }: RndComponentProps) =>
     setCurrentPos({ x: currentPos.x, y: centerY })
     handleUpdatePos({ x: currentPos.x, y: centerY })
   }
+  const handleRightClick = (event: React.MouseEvent<HTMLDivElement>, componentId: number) => {
+    event.preventDefault()
+    setMenuState({
+      menuIsOpen: true,
+      mouseX: event.clientX - 2,
+      mouseY: event.clientY - 4,
+      componentId: componentId,
+    })
+  }
+  const handleCloseMenu = () => {
+    setMenuState(initialMenuState)
+  }
+  const handleDuplicateComponent = async (viewTypeId: number) => {
+    console.log('Duplicate')
+    await axios
+      .post(
+        `/api/competitions/${competitionId}/slides/${slideId}/components/${menuState.componentId}/copy/${viewTypeId}`
+      )
+      .then(() => dispatch(getEditorCompetition(competitionId.toString())))
+      .catch(console.log)
+    setMenuState(initialMenuState)
+  }
+  const handleRemoveComponent = async () => {
+    console.log('Remove')
+    await axios
+      .delete(`/api/competitions/${competitionId}/slides/${slideId}/components/${menuState.componentId}`)
+      .then(() => dispatch(getEditorCompetition(competitionId.toString())))
+      .catch(console.log)
+    setMenuState(initialMenuState)
+  }
+
   useEffect(() => {
     const downHandler = (ev: KeyboardEvent) => {
       if (ev.key === 'Shift') setShiftPressed(true)
@@ -109,6 +153,8 @@ const RndComponent = ({ component, width, height, scale }: RndComponentProps) =>
       lockAspectRatio={shiftPressed}
       onMouseEnter={() => setHover(true)}
       onMouseLeave={() => setHover(false)}
+      //Right click to open menu
+      onContextMenu={(event: React.MouseEvent<HTMLDivElement>) => handleRightClick(event, component.id)}
       //Multiply by scale to show components correctly for current screen size
       size={{ width: currentSize.w * scale, height: currentSize.h * scale }}
       position={{ x: currentPos.x * scale, y: currentPos.y * scale }}
@@ -136,6 +182,23 @@ const RndComponent = ({ component, width, height, scale }: RndComponentProps) =>
         </Card>
       )}
       {renderInnerComponent()}
+      <Menu
+        keepMounted
+        open={menuState.menuIsOpen}
+        onClose={handleCloseMenu}
+        anchorReference="anchorPosition"
+        anchorPosition={
+          menuState.mouseY !== null && menuState.mouseX !== null
+            ? { top: menuState.mouseY, left: menuState.mouseX }
+            : undefined
+        }
+      >
+        {/* <NestedMenuItem label="Duplicera"> */}
+        <MenuItem onClick={() => handleDuplicateComponent(3)}>Duplicera till åskådarvy</MenuItem>
+        <MenuItem onClick={() => handleDuplicateComponent(1)}>Duplicera till deltagarvy</MenuItem>
+        {/* </NestedMenuItem> */}
+        <RemoveMenuItem onClick={handleRemoveComponent}>Ta bort</RemoveMenuItem>
+      </Menu>
     </Rnd>
   )
 }
diff --git a/client/src/pages/presentationEditor/components/TextComponentEdit.tsx b/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
index 04ddd6daa7bb015b3e48b905b3f17f3594c8ba98..521752778b5c7377c8bfe26c6cd2a3dbebcaeb50 100644
--- a/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
+++ b/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
@@ -50,7 +50,7 @@ const TextComponentEdit = ({ component }: ImageComponentProps) => {
   }
 
   return (
-    <div style={{ minHeight: '300px', height: '100%', width: '100%' }}>
+    <>
       <Editor
         value={content || ''}
         init={{
@@ -81,7 +81,7 @@ const TextComponentEdit = ({ component }: ImageComponentProps) => {
       <DeleteTextButton variant="contained" color="secondary" onClick={() => handleDeleteText(component.id)}>
         Ta bort
       </DeleteTextButton>
-    </div>
+    </>
   )
 }
 
diff --git a/client/src/pages/presentationEditor/components/slideSettingsComponents/Instructions.tsx b/client/src/pages/presentationEditor/components/slideSettingsComponents/Instructions.tsx
index 48917fcc01967b72e121b506fc6e4e05ac883c40..99b4b1d8d118e65595b38077e8fd15afa103ad05 100644
--- a/client/src/pages/presentationEditor/components/slideSettingsComponents/Instructions.tsx
+++ b/client/src/pages/presentationEditor/components/slideSettingsComponents/Instructions.tsx
@@ -54,6 +54,7 @@ const Instructions = ({ activeSlide, competitionId }: InstructionsProps) => {
       <ListItem divider>
         <Center>
           <TextField
+            multiline
             id="outlined-basic"
             defaultValue={activeSlide.questions[0].correcting_instructions}
             onChange={updateInstructionsText}
diff --git a/client/src/pages/presentationEditor/styled.tsx b/client/src/pages/presentationEditor/styled.tsx
index 4f830687898bd87fbd7c637dfd19706324fe909e..779599dab4cd748333631b734decf2051389389c 100644
--- a/client/src/pages/presentationEditor/styled.tsx
+++ b/client/src/pages/presentationEditor/styled.tsx
@@ -20,20 +20,13 @@ export const ToolBarContainer = styled(Toolbar)`
 `
 
 export const ViewButton = styled(Button)<ViewButtonProps>`
-  margin-right: 8px;
   background: ${(props) => (props.$activeView ? '#5a0017' : undefined)};
 `
 
 export const ViewButtonClicked = styled(Button)`
-  margin-right: 8px;
   background: #5a0017;
 `
 
-export const ViewButtonGroup = styled.div`
-  display: flex;
-  flex-direction: row;
-`
-
 export const SlideList = styled(List)`
   height: calc(100% - ${SlideListHeight}px);
   padding: 0px;
@@ -70,6 +63,7 @@ export const LeftDrawer = styled(Drawer)<DrawerSizeProps>`
   flex-shrink: 0;
   position: relative;
   z-index: 1;
+  overflow: hidden;
 `
 
 export const RightDrawer = styled(Drawer)<DrawerSizeProps>`
diff --git a/client/src/pages/views/AudienceViewPage.tsx b/client/src/pages/views/AudienceViewPage.tsx
index 48b92c4686c762536c629e1c33f5bb33ade9cc59..28280c90bb0b370802c39b7646c7e59ded4b0f55 100644
--- a/client/src/pages/views/AudienceViewPage.tsx
+++ b/client/src/pages/views/AudienceViewPage.tsx
@@ -1,21 +1,15 @@
 import { Typography } from '@material-ui/core'
 import React, { useEffect } from 'react'
-import { useParams } from 'react-router-dom'
-import { getPresentationCompetition } from '../../actions/presentation'
-import { useAppDispatch, useAppSelector } from '../../hooks'
-import { ViewParams } from '../../interfaces/ViewParams'
+import { useAppSelector } from '../../hooks'
 import { socketConnect, socketJoinPresentation } from '../../sockets'
 import SlideDisplay from '../presentationEditor/components/SlideDisplay'
 import { PresentationBackground, PresentationContainer } from './styled'
 
 const AudienceViewPage: React.FC = () => {
-  const { competitionId }: ViewParams = useParams()
   const code = useAppSelector((state) => state.presentation.code)
-  const dispatch = useAppDispatch()
   const viewTypes = useAppSelector((state) => state.types.viewTypes)
   const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Audience')?.id
   useEffect(() => {
-    dispatch(getPresentationCompetition(competitionId))
     if (code && code !== '') {
       socketConnect()
       socketJoinPresentation()
diff --git a/client/src/pages/views/OperatorViewPage.tsx b/client/src/pages/views/OperatorViewPage.tsx
index e92dc1b9b470977c563b8bc6b955af7da984b6ea..fd3dd05b78403f3193e3eedd4543368fc7a92306 100644
--- a/client/src/pages/views/OperatorViewPage.tsx
+++ b/client/src/pages/views/OperatorViewPage.tsx
@@ -25,11 +25,8 @@ import SupervisorAccountIcon from '@material-ui/icons/SupervisorAccount'
 import TimerIcon from '@material-ui/icons/Timer'
 import axios from 'axios'
 import React, { useEffect } from 'react'
-import { useHistory, useParams } from 'react-router-dom'
-import { getPresentationCompetition } from '../../actions/presentation'
-import { useAppDispatch, useAppSelector } from '../../hooks'
-import { Team } from '../../interfaces/ApiModels'
-import { ViewParams } from '../../interfaces/ViewParams'
+import { useHistory } from 'react-router-dom'
+import { useAppSelector } from '../../hooks'
 import {
   socketConnect,
   socketEndPresentation,
@@ -62,7 +59,6 @@ import {
  *  TODO:
  *  - Instead of copying code for others to join the competition, copy URL.
  *
- *  - Make code popup less code by using .map instead
  *
  *  - Fix scoreboard
  *
@@ -100,24 +96,21 @@ const OperatorViewPage: React.FC = () => {
   const [openAlert, setOpen] = React.useState(false)
   const [openAlertCode, setOpenCode] = React.useState(false)
   const [codes, setCodes] = React.useState<Code[]>([])
-  const [teams, setTeams] = React.useState<Team[]>([])
   const [competitionName, setCompetitionName] = React.useState<string | undefined>(undefined)
 
   //const fullScreen = useMediaQuery(theme.breakpoints.down('sm'))
 
   const classes = useStyles()
-  //const teams = useAppSelector((state) => state.presentation.competition.teams)
+  const teams = useAppSelector((state) => state.presentation.competition.teams)
   const [anchorEl, setAnchorEl] = React.useState<HTMLButtonElement | null>(null)
-  const { competitionId }: ViewParams = useParams()
+  const competitionId = useAppSelector((state) => state.competitionLogin.data?.competition_id)
   const presentation = useAppSelector((state) => state.presentation)
   const activeId = useAppSelector((state) => state.presentation.competition.id)
   const history = useHistory()
-  const dispatch = useAppDispatch()
   const viewTypes = useAppSelector((state) => state.types.viewTypes)
   const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Audience')?.id
 
   useEffect(() => {
-    dispatch(getPresentationCompetition(competitionId))
     socketConnect()
     socketSetSlide // Behövs denna?
     handleOpenCodes()
@@ -153,15 +146,10 @@ const OperatorViewPage: React.FC = () => {
 
   const handleOpenCodes = async () => {
     await getCodes()
-    await getTeams()
     await getCompetitionName()
     setOpenCode(true)
   }
 
-  const handleCopy = () => {
-    console.log('copied code to clipboard')
-  }
-
   const endCompetition = () => {
     setOpen(false)
     socketEndPresentation()
@@ -178,17 +166,6 @@ const OperatorViewPage: React.FC = () => {
       .catch(console.log)
   }
 
-  const getTeams = async () => {
-    await axios
-      .get(`/api/competitions/${activeId}/teams`)
-      .then((response) => {
-        setTeams(response.data.items)
-      })
-      .catch((err) => {
-        console.log(err)
-      })
-  }
-
   const getCompetitionName = async () => {
     await axios
       .get(`/api/competitions/${activeId}`)
@@ -227,6 +204,16 @@ const OperatorViewPage: React.FC = () => {
     return typeName
   }
 
+  const addScore = (id: number) => {
+    // Sums the scores for the teams. id must be id-1 because it starts at 1
+    
+    let totalScore = 0
+    for (let j = 0; j < teams[id - 1].question_answers.length; j++) {
+      totalScore = totalScore + teams[id - 1].question_answers[j].score
+    }
+    return totalScore
+  }
+
   return (
     <OperatorContainer>
       <Dialog
@@ -386,7 +373,7 @@ const OperatorViewPage: React.FC = () => {
           {teams &&
             teams.map((team) => (
               <ListItem key={team.id}>
-                {team.name} score: {'666'}
+                {team.name} score:{addScore(team.id)}
               </ListItem>
             ))}
         </List>
diff --git a/client/src/pages/views/TeamViewPage.tsx b/client/src/pages/views/TeamViewPage.tsx
index 13791b3acd7b1ee5688ba3314aa4daa6e04f7272..c2d2ff8323acd61c2a503e5c0947650950a4a892 100644
--- a/client/src/pages/views/TeamViewPage.tsx
+++ b/client/src/pages/views/TeamViewPage.tsx
@@ -1,21 +1,14 @@
 import React, { useEffect } from 'react'
-import { useHistory, useParams } from 'react-router-dom'
-import { getPresentationCompetition } from '../../actions/presentation'
-import { useAppDispatch, useAppSelector } from '../../hooks'
-import { ViewParams } from '../../interfaces/ViewParams'
+import { useAppSelector } from '../../hooks'
 import { socketConnect, socketJoinPresentation } from '../../sockets'
 import SlideDisplay from '../presentationEditor/components/SlideDisplay'
 import { PresentationBackground, PresentationContainer } from './styled'
 
 const TeamViewPage: React.FC = () => {
-  const history = useHistory()
   const code = useAppSelector((state) => state.presentation.code)
   const viewTypes = useAppSelector((state) => state.types.viewTypes)
   const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Team')?.id
-  const { competitionId }: ViewParams = useParams()
-  const dispatch = useAppDispatch()
   useEffect(() => {
-    dispatch(getPresentationCompetition(competitionId))
     if (code && code !== '') {
       socketConnect()
       socketJoinPresentation()
diff --git a/client/src/pages/views/ViewSelectPage.tsx b/client/src/pages/views/ViewSelectPage.tsx
index d69dc8b4243d680647802fe9d6f72acbd23618ba..75bf84986e57ffdb552a803ea190243ad3426c4d 100644
--- a/client/src/pages/views/ViewSelectPage.tsx
+++ b/client/src/pages/views/ViewSelectPage.tsx
@@ -22,13 +22,13 @@ const ViewSelectPage: React.FC = () => {
     if (competitionId) {
       switch (viewType) {
         case 'Team':
-          return <Redirect to={`/team/competition-id=${competitionId}`} />
+          return <Redirect to={`/view/team`} />
         case 'Judge':
-          return <Redirect to={`/judge/competition-id=${competitionId}`} />
+          return <Redirect to={`/view/judge`} />
         case 'Audience':
-          return <Redirect to={`/audience/competition-id=${competitionId}`} />
+          return <Redirect to={`/view/audience`} />
         case 'Operator':
-          return <Redirect to={`/operator/competition-id=${competitionId}`} />
+          return <Redirect to={`/view/operator`} />
         default:
           return (
             <ViewSelectContainer>
diff --git a/client/src/pages/views/components/JudgeScoringInstructions.tsx b/client/src/pages/views/components/JudgeScoringInstructions.tsx
index 97062246b33a5105efd34fbfb2ac3a66296ee93b..f8c21667504524720523004ce9e853616c84e41f 100644
--- a/client/src/pages/views/components/JudgeScoringInstructions.tsx
+++ b/client/src/pages/views/components/JudgeScoringInstructions.tsx
@@ -1,16 +1,7 @@
-import { Box, Card, Typography } from '@material-ui/core'
-import axios from 'axios'
+import { Typography } from '@material-ui/core'
 import React from 'react'
-import { getPresentationCompetition } from '../../../actions/presentation'
-import { useAppDispatch, useAppSelector } from '../../../hooks'
 import { RichQuestion } from '../../../interfaces/ApiRichModels'
-import {
-  AnswerContainer,
-  JudgeScoringInstructionsContainer,
-  ScoreDisplayContainer,
-  ScoreDisplayHeader,
-  ScoreInput,
-} from './styled'
+import { JudgeScoringInstructionsContainer, ScoringInstructionsInner } from './styled'
 
 type JudgeScoringInstructionsProps = {
   question: RichQuestion
@@ -19,8 +10,14 @@ type JudgeScoringInstructionsProps = {
 const JudgeScoringInstructions = ({ question }: JudgeScoringInstructionsProps) => {
   return (
     <JudgeScoringInstructionsContainer elevation={3}>
-      <Typography variant="h4">Rättningsinstruktioner</Typography>
-      <Typography variant="body1">{question?.correcting_instructions}</Typography>
+      <ScoringInstructionsInner>
+        <Typography variant="h4">Rättningsinstruktioner</Typography>
+        <Typography variant="body1">
+          {question?.correcting_instructions !== null
+            ? question?.correcting_instructions
+            : 'Det finns inga rättningsinstruktioner för denna fråga'}
+        </Typography>
+      </ScoringInstructionsInner>
     </JudgeScoringInstructionsContainer>
   )
 }
diff --git a/client/src/pages/views/components/styled.tsx b/client/src/pages/views/components/styled.tsx
index fef186f792dafe8ee259faa693cf6707975d06ba..a5142d0b8a7353212b18fad8739e9b32eedd1625 100644
--- a/client/src/pages/views/components/styled.tsx
+++ b/client/src/pages/views/components/styled.tsx
@@ -1,4 +1,4 @@
-import { Card, Paper, TextField } from '@material-ui/core'
+import { Paper, TextField } from '@material-ui/core'
 import styled from 'styled-components'
 
 export const SlideContainer = styled.div`
@@ -38,6 +38,11 @@ export const JudgeScoringInstructionsContainer = styled(Paper)`
   bottom: 0;
   height: 250px;
   width: 100%;
+`
+
+export const ScoringInstructionsInner = styled.div`
+  margin-left: 15px;
+  margin-right: 15px;
   display: flex;
   align-items: center;
   flex-direction: column;
diff --git a/client/src/reducers/competitionLoginReducer.ts b/client/src/reducers/competitionLoginReducer.ts
index 6d425f97209c810cd1646c3f9722dd9ec5666ff8..72e5e22ee81aa98b735f670a581ad0c39a810ea9 100644
--- a/client/src/reducers/competitionLoginReducer.ts
+++ b/client/src/reducers/competitionLoginReducer.ts
@@ -36,13 +36,6 @@ export default function (state = initialState, action: AnyAction) {
         authenticated: true,
         initialized: true,
       }
-
-    case Types.SET_COMPETITION_LOGIN_AUTHENTICATED:
-      return {
-        ...state,
-        authenticated: true,
-        initialized: true,
-      }
     case Types.SET_COMPETITION_LOGIN_ERRORS:
       return {
         ...state,
diff --git a/client/src/utils/SecureRoute.tsx b/client/src/utils/SecureRoute.tsx
index e2885501748c468eb898e833481ae219516c5946..2b08b40cfd33cc630d67f80f91921e46aa163e4d 100644
--- a/client/src/utils/SecureRoute.tsx
+++ b/client/src/utils/SecureRoute.tsx
@@ -7,7 +7,7 @@ import { CheckAuthenticationCompetition } from './checkAuthenticationCompetition
 interface SecureRouteProps extends RouteProps {
   component: React.ComponentType<any>
   rest?: any
-  authLevel: 'competition' | 'admin' | 'login'
+  authLevel: 'admin' | 'login' | 'Operator' | 'Team' | 'Judge' | 'Audience'
 }
 
 /** Utility component to use for authentication, replace all routes that should be private with secure routes*/
@@ -16,6 +16,7 @@ const SecureRoute: React.FC<SecureRouteProps> = ({ component: Component, authLev
   const compAuthenticated = useAppSelector((state) => state.competitionLogin.authenticated)
   const [initialized, setInitialized] = React.useState(false)
   const compInitialized = useAppSelector((state) => state.competitionLogin.initialized)
+  const viewType = useAppSelector((state) => state.competitionLogin.data?.view)
   React.useEffect(() => {
     if (authLevel === 'admin' || authLevel === 'login') {
       CheckAuthenticationAdmin().then(() => setInitialized(true))
@@ -32,11 +33,16 @@ const SecureRoute: React.FC<SecureRouteProps> = ({ component: Component, authLev
           render={(props) => (userAuthenticated ? <Redirect to="/admin" /> : <Component {...props} />)}
         />
       )
-    else if (authLevel === 'competition' && compInitialized)
+    else if (compInitialized && viewType && authLevel !== 'admin') {
       return (
-        <Route {...rest} render={(props) => (compAuthenticated ? <Component {...props} /> : <Redirect to="/" />)} />
+        <Route
+          {...rest}
+          render={(props) =>
+            compAuthenticated && viewType === authLevel ? <Component {...props} /> : <Redirect to="/" />
+          }
+        />
       )
-    else
+    } else
       return (
         <Route {...rest} render={(props) => (userAuthenticated ? <Component {...props} /> : <Redirect to="/" />)} />
       )
diff --git a/client/src/utils/checkAuthenticationCompetition.ts b/client/src/utils/checkAuthenticationCompetition.ts
index db0c32360a9928459dd4cac4e65bfb1715a8353f..9877b674214fc5fae2899148fd9e57c9a0a3bc28 100644
--- a/client/src/utils/checkAuthenticationCompetition.ts
+++ b/client/src/utils/checkAuthenticationCompetition.ts
@@ -1,7 +1,7 @@
 import axios from 'axios'
 import jwtDecode from 'jwt-decode'
 import { logoutCompetition } from '../actions/competitionLogin'
-import { setPresentationCode } from '../actions/presentation'
+import { getPresentationCompetition, setPresentationCode } from '../actions/presentation'
 import Types from '../actions/types'
 import store from '../store'
 
@@ -15,19 +15,18 @@ export const CheckAuthenticationCompetition = async () => {
     const decodedToken: any = jwtDecode(authToken)
     if (decodedToken.exp * 1000 >= Date.now()) {
       axios.defaults.headers.common['Authorization'] = authToken
-      console.log(decodedToken.user_claims)
       await axios
         .get('/api/auth/test')
         .then((res) => {
-          store.dispatch({ type: Types.SET_COMPETITION_LOGIN_AUTHENTICATED })
           store.dispatch({
             type: Types.SET_COMPETITION_LOGIN_DATA,
             payload: {
               competition_id: decodedToken.user_claims.competition_id,
               team_id: decodedToken.user_claims.team_id,
-              view: res.data.view,
+              view: decodedToken.user_claims.view,
             },
           })
+          getPresentationCompetition(decodedToken.user_claims.competition_id)(store.dispatch, store.getState)
           setPresentationCode(decodedToken.user_claims.code)(store.dispatch)
         })
         .catch((error) => {
diff --git a/server/app/__init__.py b/server/app/__init__.py
index 4a28018cd5805ae6a99d70d7e749672b6f906eb2..5bdffe8261feeb26ec16288ae38e3f791640948a 100644
--- a/server/app/__init__.py
+++ b/server/app/__init__.py
@@ -45,15 +45,3 @@ def create_app(config_name="configmodule.DevelopmentConfig"):
             return response
 
     return app, sio
-
-
-def identity(payload):
-    user_id = payload["identity"]
-    return models.User.query.filter_by(id=user_id)
-
-
-@jwt.token_in_blacklist_loader
-def check_if_token_in_blacklist(decrypted_token):
-    jti = decrypted_token["jti"]
-
-    return models.Blacklist.query.filter_by(jti=jti).first() is not None
diff --git a/server/app/apis/__init__.py b/server/app/apis/__init__.py
index e5ec3d2ca1e1d9de6d4c5cca5ec1e3fba40f33ee..3cb924884d1616ea27433ef72ebb21090590cf38 100644
--- a/server/app/apis/__init__.py
+++ b/server/app/apis/__init__.py
@@ -1,5 +1,3 @@
-from functools import wraps
-
 import app.core.http_codes as http_codes
 from flask_jwt_extended import verify_jwt_in_request
 from flask_jwt_extended.utils import get_jwt_claims
diff --git a/server/app/apis/answers.py b/server/app/apis/answers.py
index 3990e4e1d7b75fa35d13cc592906e4c4aa921024..6d0490a9328af2b903522fbeefe5224dcc645e06 100644
--- a/server/app/apis/answers.py
+++ b/server/app/apis/answers.py
@@ -1,4 +1,3 @@
-import app.core.http_codes as codes
 import app.database.controller as dbc
 from app.apis import item_response, list_response, protect_route
 from app.core.dto import QuestionAnswerDTO
diff --git a/server/app/apis/auth.py b/server/app/apis/auth.py
index a3be209155aa5fc03b1dcd16478bd94e51f45826..bf9eeefde781f3fcacfd4bdafade8829db24acaa 100644
--- a/server/app/apis/auth.py
+++ b/server/app/apis/auth.py
@@ -5,10 +5,10 @@ import app.database.controller as dbc
 from app.apis import item_response, protect_route, text_response
 from app.core import sockets
 from app.core.codes import verify_code
-from app.core.dto import AuthDTO, CodeDTO
-from flask_jwt_extended import (create_access_token, create_refresh_token,
-                                get_jwt_identity, get_raw_jwt,
-                                jwt_refresh_token_required)
+from app.core.dto import AuthDTO
+from app.database.models import Whitelist
+from flask_jwt_extended import create_access_token, get_jti, get_raw_jwt
+from flask_jwt_extended.utils import get_jti
 from flask_restx import Resource, inputs, reqparse
 
 api = AuthDTO.api
@@ -32,7 +32,12 @@ def get_user_claims(item_user):
 
 
 def get_code_claims(item_code):
-    return {"view": item_code.view_type.name, "competition_id": item_code.competition_id, "team_id": item_code.team_id, "code": item_code.code}
+    return {
+        "view": item_code.view_type.name,
+        "competition_id": item_code.competition_id,
+        "team_id": item_code.team_id,
+        "code": item_code.code,
+    }
 
 
 @api.route("/test")
@@ -56,18 +61,16 @@ class AuthSignup(Resource):
         return item_response(schema.dump(item_user))
 
 
-@api.route("/delete/<ID>")
-@api.param("ID")
+@api.route("/delete/<user_id>")
+@api.param("user_id")
 class AuthDelete(Resource):
     @protect_route(allowed_roles=["Admin"])
-    def delete(self, ID):
-        item_user = dbc.get.user(ID)
-
+    def delete(self, user_id):
+        item_user = dbc.get.user(user_id)
+        dbc.delete.whitelist_to_blacklist(Whitelist.user_id == user_id)
         dbc.delete.default(item_user)
-        if int(ID) == get_jwt_identity():
-            jti = get_raw_jwt()["jti"]
-            dbc.add.blacklist(jti)
-        return text_response(f"User {ID} deleted")
+
+        return text_response(f"User {user_id} deleted")
 
 
 @api.route("/login")
@@ -82,9 +85,10 @@ class AuthLogin(Resource):
             api.abort(codes.UNAUTHORIZED, "Invalid email or password")
 
         access_token = create_access_token(item_user.id, user_claims=get_user_claims(item_user))
-        refresh_token = create_refresh_token(item_user.id)
+        # refresh_token = create_refresh_token(item_user.id)
 
-        response = {"id": item_user.id, "access_token": access_token, "refresh_token": refresh_token}
+        response = {"id": item_user.id, "access_token": access_token}
+        dbc.add.whitelist(get_jti(access_token), item_user.id)
         return response
 
 
@@ -98,7 +102,7 @@ class AuthLoginCode(Resource):
             api.abort(codes.UNAUTHORIZED, "Invalid code")
 
         item_code = dbc.get.code_by_code(code)
-    
+
         if item_code.view_type_id != 4:
             if item_code.competition_id not in sockets.presentations:
                 api.abort(codes.UNAUTHORIZED, "Competition not active")
@@ -107,6 +111,7 @@ class AuthLoginCode(Resource):
             item_code.id, user_claims=get_code_claims(item_code), expires_delta=timedelta(hours=8)
         )
 
+        dbc.add.whitelist(get_jti(access_token), competition_id=item_code.competition_id)
         response = {
             "competition_id": item_code.competition_id,
             "view": item_code.view_type.name,
@@ -122,9 +127,12 @@ class AuthLogout(Resource):
     def post(self):
         jti = get_raw_jwt()["jti"]
         dbc.add.blacklist(jti)
+        Whitelist.query.filter(Whitelist.jti == jti).delete()
+        dbc.utils.commit()
         return text_response("Logout")
 
 
+"""
 @api.route("/refresh")
 class AuthRefresh(Resource):
     @protect_route(allowed_roles=["*"])
@@ -137,3 +145,4 @@ class AuthRefresh(Resource):
         dbc.add.blacklist(old_jti)
         response = {"access_token": access_token}
         return response
+"""
diff --git a/server/app/apis/codes.py b/server/app/apis/codes.py
index d07e17435aed31417254acfd83ed9315f1477ba3..6409109ef875efc13a5c12040a100b28822ed6ae 100644
--- a/server/app/apis/codes.py
+++ b/server/app/apis/codes.py
@@ -1,6 +1,5 @@
 import app.database.controller as dbc
 from app.apis import item_response, list_response, protect_route
-from app.core import http_codes as codes
 from app.core.dto import CodeDTO
 from app.database.models import Code
 from flask_restx import Resource
@@ -13,7 +12,7 @@ list_schema = CodeDTO.list_schema
 @api.route("")
 @api.param("competition_id")
 class CodesList(Resource):
-    @protect_route(allowed_roles=["*"])
+    @protect_route(allowed_roles=["*"], allowed_views=["Operator"])
     def get(self, competition_id):
         items = dbc.get.code_list(competition_id)
         return list_response(list_schema.dump(items), len(items))
diff --git a/server/app/apis/competitions.py b/server/app/apis/competitions.py
index c5ff37c9131a7a9ec4bc1f394a9e1f5b5727460e..bfd06fac35c811fe276787b3027cad5d0d1f99a9 100644
--- a/server/app/apis/competitions.py
+++ b/server/app/apis/competitions.py
@@ -1,5 +1,3 @@
-import time
-
 import app.database.controller as dbc
 from app.apis import item_response, list_response, protect_route
 from app.core.dto import CompetitionDTO
diff --git a/server/app/apis/components.py b/server/app/apis/components.py
index 0368fc82a207d2bddf2990cab933c2611dafec67..9fff1d07a72115bdb215bb441606aa189c962702 100644
--- a/server/app/apis/components.py
+++ b/server/app/apis/components.py
@@ -54,6 +54,16 @@ class ComponentByID(Resource):
         return {}, codes.NO_CONTENT
 
 
+@api.route("/<component_id>/copy/<view_type_id>")
+@api.param("competition_id, slide_id, component_id, view_type_id")
+class ComponentList(Resource):
+    @protect_route(allowed_roles=["*"])
+    def post(self, competition_id, slide_id, component_id, view_type_id):
+        item_component = dbc.get.component(competition_id, slide_id, component_id)
+        item = dbc.copy.component(item_component, slide_id, view_type_id)
+        return item_response(schema.dump(item))
+
+
 @api.route("")
 @api.param("competition_id, slide_id")
 class ComponentList(Resource):
diff --git a/server/app/apis/slides.py b/server/app/apis/slides.py
index 52ce4cce1d20fc277c3ee9ec46ea3566a51ec633..aa5bee3cad42e58e83b067eb1970f6b60d2cca27 100644
--- a/server/app/apis/slides.py
+++ b/server/app/apis/slides.py
@@ -2,9 +2,8 @@ import app.core.http_codes as codes
 import app.database.controller as dbc
 from app.apis import item_response, list_response, protect_route
 from app.core.dto import SlideDTO
-from flask_restx import Resource
-from flask_restx import reqparse
 from app.core.parsers import sentinel
+from flask_restx import Resource, reqparse
 
 api = SlideDTO.api
 schema = SlideDTO.schema
diff --git a/server/app/core/__init__.py b/server/app/core/__init__.py
index 94d1daf29b0e20e1f0bd241689b4128439d0c01d..c80bb5c0ade8ae3ffbafdbd50e193677a5692832 100644
--- a/server/app/core/__init__.py
+++ b/server/app/core/__init__.py
@@ -2,7 +2,7 @@
 The core submodule contains everything important to the server that doesn't
 fit neatly in either apis or database.
 """
-
+import app.database.models as models
 from app.database import Base, ExtendedQuery
 from flask_bcrypt import Bcrypt
 from flask_jwt_extended.jwt_manager import JWTManager
@@ -13,3 +13,9 @@ db = SQLAlchemy(model_class=Base, query_class=ExtendedQuery)
 bcrypt = Bcrypt()
 jwt = JWTManager()
 ma = Marshmallow()
+
+
+@jwt.token_in_blacklist_loader
+def check_if_token_in_blacklist(decrypted_token):
+    jti = decrypted_token["jti"]
+    return models.Blacklist.query.filter_by(jti=jti).first() is not None
diff --git a/server/app/core/codes.py b/server/app/core/codes.py
index ad6d844c0fa4a01cf7652a1c966b25f678f73a4e..c52ddf8d82b0b3121249ccf74229ae81c897b696 100644
--- a/server/app/core/codes.py
+++ b/server/app/core/codes.py
@@ -4,7 +4,6 @@ Contains all functions purely related to creating and verifying a code.
 
 import random
 import re
-import string
 
 CODE_LENGTH = 6
 ALLOWED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
diff --git a/server/app/core/files.py b/server/app/core/files.py
index 5d22c8e0ad8672a6db56e7ac4c64087b55a26b74..f45b9bb58f0cea1757498b344a8221e910708805 100644
--- a/server/app/core/files.py
+++ b/server/app/core/files.py
@@ -2,10 +2,9 @@
 Contains functions related to file handling, mainly saving and deleting images.
 """
 
-from PIL import Image, ImageChops
+from PIL import Image
 from flask import current_app, has_app_context
 import os
-import datetime
 from flask_uploads import IMAGES, UploadSet
 
 if has_app_context():
diff --git a/server/app/core/parsers.py b/server/app/core/parsers.py
index 4c1525207990398475fd0c88aec11c56f87eaff1..3b541cf2778e4a3c153c950c96cd911ba3e04323 100644
--- a/server/app/core/parsers.py
+++ b/server/app/core/parsers.py
@@ -2,7 +2,7 @@
 This module contains the parsers used to parse the data gotten in api requests.
 """
 
-from flask_restx import inputs, reqparse
+from flask_restx import reqparse
 
 
 class Sentinel:
diff --git a/server/app/core/schemas.py b/server/app/core/schemas.py
index a2e81c2568f6e1c100fbc5c302a200644e11433d..d9331ae713991c1ecd652f5752532261275ab310 100644
--- a/server/app/core/schemas.py
+++ b/server/app/core/schemas.py
@@ -3,8 +3,6 @@ This module contains schemas used to convert database objects into
 dictionaries.
 """
 
-from marshmallow.decorators import pre_load
-from marshmallow.decorators import pre_dump, post_dump
 import app.database.models as models
 from app.core import ma
 from marshmallow_sqlalchemy import fields
diff --git a/server/app/core/sockets.py b/server/app/core/sockets.py
index b3bb9f878eae260a4cf0c62a11fd8c9445aa56a0..4422d466b29ab3c20e3614d0c7c52c9d36cc86b9 100644
--- a/server/app/core/sockets.py
+++ b/server/app/core/sockets.py
@@ -6,9 +6,8 @@ connected to the same presentation.
 import logging
 from typing import Dict
 
-import app.database.controller as dbc
 from app.core import db
-from app.database.models import Code, Competition, Slide, Team, ViewType
+from app.database.models import Code, Slide, ViewType
 from flask.globals import request
 from flask_jwt_extended import verify_jwt_in_request
 from flask_jwt_extended.utils import get_jwt_claims
diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py
index 9b00283080b17329b83c93fd23e4dcfa3485f9ae..2840c94e7c6fa8ff38e53ddcf0fa8429d7847c72 100644
--- a/server/app/database/__init__.py
+++ b/server/app/database/__init__.py
@@ -3,15 +3,11 @@ The database submodule contaisn all functionality that has to do with the
 database. It can add, get, delete, edit, search and copy items.
 """
 
-import json
-
 from flask_restx import abort
 from flask_sqlalchemy import BaseQuery
 from flask_sqlalchemy.model import Model
-from sqlalchemy import Column, DateTime, Text
+from sqlalchemy import Column, DateTime
 from sqlalchemy.sql import func
-from sqlalchemy.types import TypeDecorator
-from sqlalchemy import event
 
 
 class Base(Model):
diff --git a/server/app/database/controller/add.py b/server/app/database/controller/add.py
index 18bcd4b130a1f6aebd49df520c83e741a819d8cc..3aa0ab709324e21ed69e8db5f1902f9447c9c5f3 100644
--- a/server/app/database/controller/add.py
+++ b/server/app/database/controller/add.py
@@ -6,13 +6,12 @@ import os
 
 import app.core.http_codes as codes
 from app.core import db
-from app.database.controller import get, search, utils
+from app.database.controller import get, utils
 from app.database.models import (
     Blacklist,
     City,
     Code,
     Competition,
-    Component,
     ComponentType,
     ImageComponent,
     Media,
@@ -28,17 +27,14 @@ from app.database.models import (
     TextComponent,
     User,
     ViewType,
+    Whitelist,
 )
+from app.database.types import ID_IMAGE_COMPONENT, ID_QUESTION_COMPONENT, ID_TEXT_COMPONENT
+from flask import current_app
 from flask.globals import current_app
 from flask_restx import abort
 from PIL import Image
 from sqlalchemy import exc
-from sqlalchemy.orm import with_polymorphic
-from sqlalchemy.orm import relation
-from sqlalchemy.orm.session import sessionmaker
-from flask import current_app
-
-from app.database.types import ID_IMAGE_COMPONENT, ID_QUESTION_COMPONENT, ID_TEXT_COMPONENT
 
 
 def db_add(item):
@@ -197,6 +193,12 @@ def blacklist(jti):
     return db_add(Blacklist(jti))
 
 
+def whitelist(jti, user_id=None, competition_id=None):
+    """ Adds a whitelist to the database. """
+
+    return db_add(Whitelist(jti, user_id, competition_id))
+
+
 def mediaType(name):
     """ Adds a media type to the database. """
 
diff --git a/server/app/database/controller/copy.py b/server/app/database/controller/copy.py
index 08d743472035034b3b45eda3bdc6553f26377f60..48dab2db79c33cb1ca819a59f0e934ab23dcc191 100644
--- a/server/app/database/controller/copy.py
+++ b/server/app/database/controller/copy.py
@@ -9,6 +9,7 @@ from app.database.types import ID_IMAGE_COMPONENT, ID_QUESTION_COMPONENT, ID_TEX
 
 def _alternative(item_old, question_id):
     """Internal function. Makes a copy of the provided question alternative"""
+
     return add.question_alternative(item_old.text, item_old.value, question_id)
 
 
@@ -39,6 +40,16 @@ def _component(item_component, item_slide_new):
     Internal function. Makes a copy of the provided
     component item to the specified slide.
     """
+
+    component(item_component, item_slide_new.id, item_component.view_type_id)
+
+
+def component(item_component, slide_id_new, view_type_id):
+    """
+    Makes a copy of the provided component item
+    to the specified slide and view_type.
+    """
+
     data = {}
     if item_component.type_id == ID_TEXT_COMPONENT:
         data["text"] = item_component.text
@@ -46,10 +57,11 @@ def _component(item_component, item_slide_new):
         data["media_id"] = item_component.media_id
     elif item_component.type_id == ID_QUESTION_COMPONENT:
         data["question_id"] = item_component.question_id
-    add.component(
+
+    return add.component(
         item_component.type_id,
-        item_slide_new.id,
-        item_component.view_type_id,
+        slide_id_new,
+        view_type_id,
         item_component.x,
         item_component.y,
         item_component.w,
diff --git a/server/app/database/controller/delete.py b/server/app/database/controller/delete.py
index 93a4c3393bf57fed22f2d672338f6cc592ecc543..b0b36fbaf79843eac05bd4340d0a633a61e325d0 100644
--- a/server/app/database/controller/delete.py
+++ b/server/app/database/controller/delete.py
@@ -5,9 +5,8 @@ This file contains functionality to delete data to the database.
 import app.core.http_codes as codes
 import app.database.controller as dbc
 from app.core import db
-from app.database.models import Blacklist, City, Competition, Role, Slide, User
+from app.database.models import Whitelist
 from flask_restx import abort
-from sqlalchemy import exc
 
 
 def default(item):
@@ -20,6 +19,19 @@ def default(item):
         abort(codes.INTERNAL_SERVER_ERROR, f"Item of type {type(item)} could not be deleted")
 
 
+def whitelist_to_blacklist(filters):
+    """
+    Remove whitelist by condition(filters) and insert those into blacklist
+    Example: When delete user all whitelisted tokens for that user should be blacklisted
+    """
+    whitelist = Whitelist.query.filter(filters).all()
+    for item in whitelist:
+        dbc.add.blacklist(item.jti)
+
+    Whitelist.query.filter(filters).delete()
+    dbc.utils.commit()
+
+
 def component(item_component):
     """ Deletes component. """
 
diff --git a/server/app/database/controller/get.py b/server/app/database/controller/get.py
index ba975d35432437746de480667bb8774267cc5437..b6701ca5579940c9e4545d5542f41cf4b5b431fc 100644
--- a/server/app/database/controller/get.py
+++ b/server/app/database/controller/get.py
@@ -27,17 +27,19 @@ def all(db_type):
     return db_type.query.all()
 
 
-def one(db_type, id):
+def one(db_type, id, required=True):
     """ Get lazy db-item in the table that has the same id. """
 
-    return db_type.query.filter(db_type.id == id).first_extended()
+    return db_type.query.filter(db_type.id == id).first_extended(required=required)
 
 
 ### Codes ###
 def code_by_code(code):
     """ Gets the code object associated with the provided code. """
 
-    return Code.query.filter(Code.code == code.upper()).first_extended( True, "A presentation with that code does not exist")
+    return Code.query.filter(Code.code == code.upper()).first_extended(
+        True, "A presentation with that code does not exist"
+    )
 
 
 def code_list(competition_id):
diff --git a/server/app/database/controller/search.py b/server/app/database/controller/search.py
index bfc40843b83675c8758a63f4d117d98ea6b2f609..4d112a5f4b9d339b48d0add3e1382e81bc700c80 100644
--- a/server/app/database/controller/search.py
+++ b/server/app/database/controller/search.py
@@ -2,7 +2,7 @@
 This file contains functionality to find data to the database.
 """
 
-from app.database.models import Competition, Media, Question, Slide, Team, User
+from app.database.models import Competition, Media, Question, Slide, User
 
 
 def image(filename, page=0, page_size=15, order=1, order_by=None):
diff --git a/server/app/database/controller/utils.py b/server/app/database/controller/utils.py
index c01205a6ec0f9dfc5772d87200268e035db0d14b..14eaa48d0295515e3f53c93dae963eb0ebc6bc92 100644
--- a/server/app/database/controller/utils.py
+++ b/server/app/database/controller/utils.py
@@ -7,7 +7,6 @@ from app.core import db
 from app.core.codes import generate_code_string
 from app.database.models import Code
 from flask_restx import abort
-from sqlalchemy import exc
 
 
 def move_slides(item_competition, start_order, end_order):
diff --git a/server/app/database/models.py b/server/app/database/models.py
index 74f7b39e5dad9ab69a22b10445e9e86baa08125d..a54a77c24b6b77a22187c386e8cd59c1cd006f49 100644
--- a/server/app/database/models.py
+++ b/server/app/database/models.py
@@ -11,10 +11,21 @@ from sqlalchemy.ext.hybrid import hybrid_method, hybrid_property
 STRING_SIZE = 254
 
 
+class Whitelist(db.Model):
+    id = db.Column(db.Integer, primary_key=True)
+    jti = db.Column(db.String, unique=True)
+    user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=True)
+    competition_id = db.Column(db.Integer, db.ForeignKey("competition.id"), nullable=True)
+
+    def __init__(self, jti, user_id=None, competition_id=None):
+        self.jti = jti
+        self.user_id = user_id
+        self.competition_id = competition_id
+
+
 class Blacklist(db.Model):
     id = db.Column(db.Integer, primary_key=True)
     jti = db.Column(db.String, unique=True)
-    expire_date = db.Column(db.Integer, nullable=True)
 
     def __init__(self, jti):
         self.jti = jti
diff --git a/server/configmodule.py b/server/configmodule.py
index 8c07211ed58d7fa2550893fc241a9a2170527a2f..93d21cbe84a5847ed4927a4d2b3d002b487d1f69 100644
--- a/server/configmodule.py
+++ b/server/configmodule.py
@@ -12,7 +12,7 @@ class Config:
     JWT_BLACKLIST_ENABLED = True
     JWT_BLACKLIST_TOKEN_CHECKS = ["access", "refresh"]
     JWT_ACCESS_TOKEN_EXPIRES = timedelta(days=2)
-    JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30)
+    # JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30)
     UPLOADED_PHOTOS_DEST = os.path.join(os.getcwd(), "app", "static", "images")
     THUMBNAIL_SIZE = (120, 120)
     SECRET_KEY = os.urandom(24)
diff --git a/server/populate.py b/server/populate.py
index b7496991b1baef41914541d546c916c73f14551b..9981f0c02f430d56c88738a9b67e89d5fc17af89 100644
--- a/server/populate.py
+++ b/server/populate.py
@@ -43,8 +43,8 @@ def _add_items():
     city_id = City.query.filter(City.name == "Linköping").one().id
 
     # Add users
-    dbc.add.user("admin@test.se", "password", admin_id, city_id)
-    dbc.add.user("test@test.se", "password", editor_id, city_id)
+    dbc.add.user("admin@test.se", "password", admin_id, city_id, "Admina Denfina")
+    dbc.add.user("test@test.se", "password", editor_id, city_id, "Test Osteron")
 
     question_types_items = dbc.get.all(QuestionType)
 
@@ -105,6 +105,14 @@ def _add_items():
         for name in teams:
             dbc.add.team(f"{name}{i}", item_comp.id)
 
+    # question_answer(answer, score, question_id, team_id)
+    dbc.add.question_answer("ett svar som ger 2p", 2, 1, 1)
+    dbc.add.question_answer("ett svar som ger 10p", 10, 2, 1)
+    dbc.add.question_answer("ett svar som ger 6p", 6, 3, 1)
+
+    dbc.add.question_answer("ett svar som ger 2p", 2, 1, 2)
+    dbc.add.question_answer("ett svar som ger 3p", 3, 1, 3)
+
 
 if __name__ == "__main__":
     app, _ = create_app("configmodule.DevelopmentConfig")
diff --git a/server/tests/test_app.py b/server/tests/test_app.py
index d59428a6380b74abe8853c6c09c4df0bafc031e0..2152a6d4c7236f57d099f50dccec3a090ce94c5d 100644
--- a/server/tests/test_app.py
+++ b/server/tests/test_app.py
@@ -112,7 +112,7 @@ def test_competition_api(client):
     assert response.status_code == codes.OK
 
     # Copies competition
-    for _ in range(10):
+    for _ in range(3):
         response, _ = post(client, f"/api/competitions/{competition_id}/copy", headers=headers)
         assert response.status_code == codes.OK
 
@@ -149,7 +149,7 @@ def test_auth_and_user_api(client):
     # Try loggin with right PASSWORD
     response, body = post(client, "/api/auth/login", {"email": "test1@test.se", "password": "abc123"})
     assert response.status_code == codes.OK
-    refresh_token = body["refresh_token"]
+    # refresh_token = body["refresh_token"]
     headers = {"Authorization": "Bearer " + body["access_token"]}
 
     # Get the current user
@@ -330,6 +330,35 @@ def test_slide_api(client):
         assert response.status_code == codes.OK
     """
 
+    # Get a specific component
+    CID = 2
+    SID = 3
+    COMID = 2
+    response, c1 = get(client, f"/api/competitions/{CID}/slides/{SID}/components/{COMID}", headers=headers)
+    assert response.status_code == codes.OK
+
+    # Copy the component to another view
+    view_type_id = 3
+    response, c2 = post(
+        client, f"/api/competitions/{CID}/slides/{SID}/components/{COMID}/copy/{view_type_id}", headers=headers
+    )
+    # Check that the components metch
+    assert response.status_code == codes.OK
+    assert c1 != c2
+    assert c1["x"] == c2["x"]
+    assert c1["y"] == c2["y"]
+    assert c1["w"] == c2["w"]
+    assert c1["h"] == c2["h"]
+    assert c1["slide_id"] == SID
+    assert c2["slide_id"] == SID
+    assert c1["type_id"] == c2["type_id"]
+    if c1["type_id"] == 1:
+        assert c1["text"] == c2["text"]
+    elif c1["type_id"] == 2:
+        assert c1["image_id"] == c2["image_id"]
+    assert c1["view_type_id"] == 1
+    assert c2["view_type_id"] == 3
+
 
 def test_question_api(client):
     add_default_values()
diff --git a/server/tests/test_helpers.py b/server/tests/test_helpers.py
index f55aa68251a5a3b9ea73411c959939acc93f1bc6..85c1f114a8c01da6e7d5370bffe2ccb9ea8aed1c 100644
--- a/server/tests/test_helpers.py
+++ b/server/tests/test_helpers.py
@@ -49,8 +49,8 @@ def add_default_values():
     db.session.add(Code("111111", 1, item_competition.id, item_team1.id))  # Team
     db.session.add(Code("222222", 2, item_competition.id))  # Judge
 
-    dbc.add.QuestionAnswer("hej", 5, item_question.id, item_team1)
-    dbc.add.QuestionAnswer("då", 5, item_question.id, item_team2)
+    dbc.add.question_answer("hej", 5, item_question.id, item_team1.id)
+    dbc.add.question_answer("då", 5, item_question.id, item_team2.id)
 
     db.session.commit()