From d0b1c8c1b37a421e9cdcb0e4d3ee300d5cbfcafc Mon Sep 17 00:00:00 2001
From: Emil <Emil>
Date: Tue, 27 Apr 2021 18:47:01 +0200
Subject: [PATCH 1/2] viewType added

---
 client/src/actions/editor.ts                  | 14 ++++-
 client/src/actions/types.ts                   |  1 +
 client/src/interfaces/ApiModels.ts            |  2 +
 .../PresentationEditorPage.tsx                | 14 +++--
 .../components/SlideSettings.tsx              |  9 +++-
 .../components/TextComponentEdit.tsx          |  1 +
 .../slideSettingsComponents/Images.tsx        |  4 +-
 .../slideSettingsComponents/Texts.tsx         |  4 +-
 client/src/reducers/editorReducer.ts          |  7 +++
 server/app/apis/components.py                 |  1 +
 server/app/core/schemas.py                    |  1 +
 server/app/core/sockets.py                    | 52 ++++++++++++++-----
 server/app/database/controller/add.py         |  6 +--
 server/app/database/controller/copy.py        |  1 +
 server/app/database/models.py                 |  3 +-
 server/populate.py                            |  2 +-
 server/tests/test_helpers.py                  |  2 +-
 17 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/client/src/actions/editor.ts b/client/src/actions/editor.ts
index db688dcb..526ad9ff 100644
--- a/client/src/actions/editor.ts
+++ b/client/src/actions/editor.ts
@@ -18,16 +18,28 @@ export const getEditorCompetition = (id: string) => async (dispatch: AppDispatch
       if (getState().editor.activeSlideId === -1 && res.data.slides[0]) {
         setEditorSlideId(res.data.slides[0].id)(dispatch)
       }
+      const defaultViewType = getState().types.viewTypes.find((viewType) => viewType.name === 'Audience')
+      if (getState().editor.activeViewTypeId === -1 && defaultViewType) {
+        setEditorViewId(defaultViewType.id)(dispatch)
+      }
     })
     .catch((err) => {
       console.log(err)
     })
 }
 
-// Set currentSlideId in editor state
+// Set activeSlideId in editor state
 export const setEditorSlideId = (id: number) => (dispatch: AppDispatch) => {
   dispatch({
     type: Types.SET_EDITOR_SLIDE_ID,
     payload: id,
   })
 }
+
+// Set activeViewTypeId in editor state
+export const setEditorViewId = (id: number) => (dispatch: AppDispatch) => {
+  dispatch({
+    type: Types.SET_EDITOR_VIEW_ID,
+    payload: id,
+  })
+}
diff --git a/client/src/actions/types.ts b/client/src/actions/types.ts
index 445a8d86..2e9fc776 100644
--- a/client/src/actions/types.ts
+++ b/client/src/actions/types.ts
@@ -24,6 +24,7 @@ export default {
   SET_COMPETITIONS_COUNT: 'SET_COMPETITIONS_COUNT',
   SET_EDITOR_COMPETITION: 'SET_EDITOR_COMPETITION',
   SET_EDITOR_SLIDE_ID: 'SET_EDITOR_SLIDE_ID',
+  SET_EDITOR_VIEW_ID: 'SET_EDITOR_VIEW_ID',
   SET_PRESENTATION_COMPETITION: 'SET_PRESENTATION_COMPETITION',
   SET_PRESENTATION_SLIDE: 'SET_PRESENTATION_SLIDE',
   SET_PRESENTATION_SLIDE_PREVIOUS: 'SET_PRESENTATION_SLIDE_PREVIOUS',
diff --git a/client/src/interfaces/ApiModels.ts b/client/src/interfaces/ApiModels.ts
index 4de675fb..faecc98f 100644
--- a/client/src/interfaces/ApiModels.ts
+++ b/client/src/interfaces/ApiModels.ts
@@ -81,6 +81,8 @@ export interface Component {
   w: number
   h: number
   type_id: number
+  view_type_id: number
+  slide_id: number
 }
 
 export interface ImageComponent extends Component {
diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
index 3c86afe9..50c3ae52 100644
--- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
@@ -14,7 +14,7 @@ import axios from 'axios'
 import React, { useEffect, useState } from 'react'
 import { Link, useParams } from 'react-router-dom'
 import { getCities } from '../../actions/cities'
-import { getEditorCompetition, setEditorSlideId } from '../../actions/editor'
+import { getEditorCompetition, setEditorSlideId, setEditorViewId } from '../../actions/editor'
 import { getTypes } from '../../actions/typesAction'
 import { useAppDispatch, useAppSelector } from '../../hooks'
 import { RichSlide } from '../../interfaces/ApiRichModels'
@@ -165,6 +165,14 @@ const PresentationEditorPage: React.FC = () => {
   })((props: CheckboxProps) => <Checkbox color="default" {...props} />)
   const [checkbox, setCheckbox] = useState(false)
 
+  const viewTypes = useAppSelector((state) => state.types.viewTypes)
+  const changeView = (clickedViewTypeName: string) => {
+    const clickedViewTypeId = viewTypes.find((viewType) => viewType.name === clickedViewTypeName)?.id
+    if (clickedViewTypeId) {
+      dispatch(setEditorViewId(clickedViewTypeId))
+    }
+  }
+
   return (
     <PresentationEditorContainer>
       <CssBaseline />
@@ -182,10 +190,10 @@ const PresentationEditorPage: React.FC = () => {
             <Typography className={classes.alignCheckboxText} variant="button">
               Applicera ändringar på samtliga vyer
             </Typography>
-            <ViewButton variant="contained" color="secondary">
+            <ViewButton variant="contained" color="secondary" onClick={() => changeView('Audience')}>
               Åskådarvy
             </ViewButton>
-            <ViewButton variant="contained" color="secondary">
+            <ViewButton variant="contained" color="secondary" onClick={() => changeView('Team')}>
               Deltagarvy
             </ViewButton>
           </ViewButtonGroup>
diff --git a/client/src/pages/presentationEditor/components/SlideSettings.tsx b/client/src/pages/presentationEditor/components/SlideSettings.tsx
index 278887c1..41c1354f 100644
--- a/client/src/pages/presentationEditor/components/SlideSettings.tsx
+++ b/client/src/pages/presentationEditor/components/SlideSettings.tsx
@@ -24,6 +24,7 @@ const SlideSettings: React.FC = () => {
     // Gets the slide with id=activeSlideId from the database.
     state.editor.competition.slides.find((slide) => slide && slide.id === state.editor.activeSlideId)
   )
+  const activeViewTypeId = useAppSelector((state) => state.editor.activeViewTypeId)
 
   return (
     <PanelContainer>
@@ -47,9 +48,13 @@ const SlideSettings: React.FC = () => {
         <MultipleChoiceAlternatives activeSlide={activeSlide} competitionId={competitionId} />
       )}
 
-      {activeSlide && <Texts activeSlide={activeSlide} competitionId={competitionId} />}
+      {activeSlide && (
+        <Texts activeViewTypeId={activeViewTypeId} activeSlide={activeSlide} competitionId={competitionId} />
+      )}
 
-      {activeSlide && <Images activeSlide={activeSlide} competitionId={competitionId} />}
+      {activeSlide && (
+        <Images activeViewTypeId={activeViewTypeId} activeSlide={activeSlide} competitionId={competitionId} />
+      )}
 
       <SettingsList>
         <ListItem button>
diff --git a/client/src/pages/presentationEditor/components/TextComponentEdit.tsx b/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
index b03696f3..f6cda576 100644
--- a/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
+++ b/client/src/pages/presentationEditor/components/TextComponentEdit.tsx
@@ -20,6 +20,7 @@ const TextComponentEdit = ({ component }: ImageComponentProps) => {
   const [content, setContent] = useState('')
   const [timerHandle, setTimerHandle] = React.useState<number | undefined>(undefined)
   const activeSlideId = useAppSelector((state) => state.editor.activeSlideId)
+  const activeViewTypeId = useAppSelector((state) => state.editor.activeViewTypeId)
   const dispatch = useAppDispatch()
 
   useEffect(() => {
diff --git a/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx b/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
index fa087dcc..bc83d2fa 100644
--- a/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
+++ b/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
@@ -11,11 +11,12 @@ import { ImageComponent, Media } from '../../../../interfaces/ApiModels'
 import { useAppDispatch, useAppSelector } from '../../../../hooks'
 
 type ImagesProps = {
+  activeViewTypeId: number
   activeSlide: RichSlide
   competitionId: string
 }
 
-const Images = ({ activeSlide, competitionId }: ImagesProps) => {
+const Images = ({ activeViewTypeId, activeSlide, competitionId }: ImagesProps) => {
   const dispatch = useAppDispatch()
 
   const uploadFile = async (formData: FormData) => {
@@ -37,6 +38,7 @@ const Images = ({ activeSlide, competitionId }: ImagesProps) => {
       y: 0,
       media_id: media.id,
       type_id: 2,
+      view_type_id: activeViewTypeId,
     }
     await axios
       .post(`/api/competitions/${competitionId}/slides/${activeSlide?.id}/components`, imageData)
diff --git a/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx b/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
index 39cf09af..b1e9fa9b 100644
--- a/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
+++ b/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
@@ -9,11 +9,12 @@ import axios from 'axios'
 import { getEditorCompetition } from '../../../../actions/editor'
 
 type TextsProps = {
+  activeViewTypeId: number
   activeSlide: RichSlide
   competitionId: string
 }
 
-const Texts = ({ activeSlide, competitionId }: TextsProps) => {
+const Texts = ({ activeViewTypeId, activeSlide, competitionId }: TextsProps) => {
   const texts = useAppSelector(
     (state) =>
       state.editor.competition.slides
@@ -29,6 +30,7 @@ const Texts = ({ activeSlide, competitionId }: TextsProps) => {
         text: 'Ny text',
         w: 315,
         h: 50,
+        view_type_id: activeViewTypeId,
       })
       dispatch(getEditorCompetition(competitionId))
     }
diff --git a/client/src/reducers/editorReducer.ts b/client/src/reducers/editorReducer.ts
index 88e6e368..4f245d1d 100644
--- a/client/src/reducers/editorReducer.ts
+++ b/client/src/reducers/editorReducer.ts
@@ -5,6 +5,7 @@ import { RichCompetition } from '../interfaces/ApiRichModels'
 interface EditorState {
   competition: RichCompetition
   activeSlideId: number
+  activeViewTypeId: number
   loading: boolean
 }
 
@@ -19,6 +20,7 @@ const initialState: EditorState = {
     background_image: undefined,
   },
   activeSlideId: -1,
+  activeViewTypeId: -1,
   loading: true,
 }
 
@@ -35,6 +37,11 @@ export default function (state = initialState, action: AnyAction) {
         ...state,
         activeSlideId: action.payload as number,
       }
+    case Types.SET_EDITOR_VIEW_ID:
+      return {
+        ...state,
+        activeViewTypeId: action.payload as number,
+      }
     default:
       return state
   }
diff --git a/server/app/apis/components.py b/server/app/apis/components.py
index 8ab67b8c..8f253151 100644
--- a/server/app/apis/components.py
+++ b/server/app/apis/components.py
@@ -22,6 +22,7 @@ component_edit_parser.add_argument("media_id", type=str, location="json")
 
 component_create_parser = component_edit_parser.copy()
 component_create_parser.add_argument("type_id", type=int, required=True, location="json")
+component_create_parser.add_argument("view_type_id", type=int, required=True, location="json")
 
 
 @api.route("/<component_id>")
diff --git a/server/app/core/schemas.py b/server/app/core/schemas.py
index 0abe0252..31e79e69 100644
--- a/server/app/core/schemas.py
+++ b/server/app/core/schemas.py
@@ -161,6 +161,7 @@ class ComponentSchema(BaseSchema):
     h = ma.auto_field()
     slide_id = ma.auto_field()
     type_id = ma.auto_field()
+    view_type_id = ma.auto_field()
 
     text = fields.fields.String()
     media = fields.Nested(MediaSchema, many=False)
diff --git a/server/app/core/sockets.py b/server/app/core/sockets.py
index 00b2ddf5..b62f82c9 100644
--- a/server/app/core/sockets.py
+++ b/server/app/core/sockets.py
@@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
 logger.propagate = False
 logger.setLevel(logging.INFO)
 
-formatter = logging.Formatter('[%(levelname)s] %(funcName)s: %(message)s')
+formatter = logging.Formatter("[%(levelname)s] %(funcName)s: %(message)s")
 stream_handler = logging.StreamHandler()
 stream_handler.setFormatter(formatter)
 logger.addHandler(stream_handler)
@@ -44,7 +44,9 @@ def start_presentation(data):
     competition_id = data["competition_id"]
 
     if competition_id in presentations:
-        logger.error(f"Client '{request.sid}' failed to start competition '{competition_id}', presentation already active")
+        logger.error(
+            f"Client '{request.sid}' failed to start competition '{competition_id}', presentation already active"
+        )
         return
 
     presentations[competition_id] = {
@@ -58,16 +60,21 @@ def start_presentation(data):
 
     logger.info(f"Client '{request.sid}' started competition '{competition_id}'")
 
+
 @sio.on("end_presentation")
 def end_presentation(data):
     competition_id = data["competition_id"]
 
     if competition_id not in presentations:
-        logger.error(f"Client '{request.sid}' failed to end presentation '{competition_id}', no such presentation exists")
+        logger.error(
+            f"Client '{request.sid}' failed to end presentation '{competition_id}', no such presentation exists"
+        )
         return
 
     if request.sid not in presentations[competition_id]["clients"]:
-        logger.error(f"Client '{request.sid}' failed to end presentation '{competition_id}', client not in presentation")
+        logger.error(
+            f"Client '{request.sid}' failed to end presentation '{competition_id}', client not in presentation"
+        )
         return
 
     if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
@@ -96,11 +103,15 @@ def join_presentation(data):
     competition_id = item_code.competition_id
 
     if competition_id not in presentations:
-        logger.error(f"Client '{request.sid}' failed to join presentation '{competition_id}', no such presentation exists")
+        logger.error(
+            f"Client '{request.sid}' failed to join presentation '{competition_id}', no such presentation exists"
+        )
         return
 
     if request.sid in presentations[competition_id]["clients"]:
-        logger.error(f"Client '{request.sid}' failed to join presentation '{competition_id}', client already in presentation")
+        logger.error(
+            f"Client '{request.sid}' failed to join presentation '{competition_id}', client already in presentation"
+        )
         return
 
     # TODO: Write function in database controller to do this
@@ -120,21 +131,29 @@ def set_slide(data):
     slide_order = data["slide_order"]
 
     if competition_id not in presentations:
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists"
+        )
         return
 
     if request.sid not in presentations[competition_id]["clients"]:
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation"
+        )
         return
 
     if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator"
+        )
         return
 
     num_slides = db.session.query(Slide).filter(Slide.competition_id == competition_id).count()
 
     if not (0 <= slide_order < num_slides):
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', slide number {slide_order} does not exist")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', slide number {slide_order} does not exist"
+        )
         return
 
     presentations[competition_id]["slide"] = slide_order
@@ -151,15 +170,21 @@ def set_timer(data):
     timer = data["timer"]
 
     if competition_id not in presentations:
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists"
+        )
         return
 
     if request.sid not in presentations[competition_id]["clients"]:
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation"
+        )
         return
 
     if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
-        logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator")
+        logger.error(
+            f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator"
+        )
         return
 
     # TODO: Save timer in presentation, maybe?
@@ -168,4 +193,3 @@ def set_timer(data):
     logger.debug(f"Emitting event 'set_timer' to room {competition_id} including self")
 
     logger.info(f"Client '{request.sid}' set timer '{timer}' in presentation '{competition_id}'")
-
diff --git a/server/app/database/controller/add.py b/server/app/database/controller/add.py
index a83f5b95..f7b0edbb 100644
--- a/server/app/database/controller/add.py
+++ b/server/app/database/controller/add.py
@@ -59,7 +59,7 @@ def db_add(item):
     return item
 
 
-def component(type_id, slide_id, x=0, y=0, w=0, h=0, **data):
+def component(type_id, slide_id, view_type_id, x=0, y=0, w=0, h=0, **data):
     """
     Adds a component to the slide at the specified coordinates with the
     provided size and data .
@@ -80,10 +80,10 @@ def component(type_id, slide_id, x=0, y=0, w=0, h=0, **data):
         h *= ratio
 
     if type_id == 1:
-        item = db_add(TextComponent(slide_id, type_id, x, y, w, h))
+        item = db_add(TextComponent(slide_id, type_id, view_type_id, x, y, w, h))
         item.text = data.get("text")
     elif type_id == 2:
-        item = db_add(ImageComponent(slide_id, type_id, x, y, w, h))
+        item = db_add(ImageComponent(slide_id, type_id, view_type_id, x, y, w, h))
         item.media_id = data.get("media_id")
     else:
         abort(codes.BAD_REQUEST, f"Invalid type_id{type_id}")
diff --git a/server/app/database/controller/copy.py b/server/app/database/controller/copy.py
index 7e9d28d0..1874b5dc 100644
--- a/server/app/database/controller/copy.py
+++ b/server/app/database/controller/copy.py
@@ -45,6 +45,7 @@ def _component(item_component, item_slide_new):
     add.component(
         item_component.type_id,
         item_slide_new.id,
+        item_component.view_type_id,
         item_component.x,
         item_component.y,
         item_component.w,
diff --git a/server/app/database/models.py b/server/app/database/models.py
index 30129389..c84677b2 100644
--- a/server/app/database/models.py
+++ b/server/app/database/models.py
@@ -199,13 +199,14 @@ class Component(db.Model):
 
     __mapper_args__ = {"polymorphic_on": type_id}
 
-    def __init__(self, slide_id, type_id, x=0, y=0, w=1, h=1):
+    def __init__(self, slide_id, type_id, view_type_id, x=0, y=0, w=1, h=1):
         self.x = x
         self.y = y
         self.w = w
         self.h = h
         self.slide_id = slide_id
         self.type_id = type_id
+        self.view_type_id = view_type_id
 
 
 class TextComponent(Component):
diff --git a/server/populate.py b/server/populate.py
index 6a4be4ef..8bd2badc 100644
--- a/server/populate.py
+++ b/server/populate.py
@@ -86,7 +86,7 @@ def _add_items():
                 y = random.randrange(1, 500)
                 w = random.randrange(150, 400)
                 h = random.randrange(150, 400)
-                dbc.add.component(1, item_slide.id, x, y, w, h, text=f"hej{k}")
+                dbc.add.component(1, item_slide.id, 1, x, y, w, h, text=f"hej{k}")
 
         # item_slide = dbc.add.slide(item_comp)
         # item_slide.title = f"Slide {len(item_comp.slides)}"
diff --git a/server/tests/test_helpers.py b/server/tests/test_helpers.py
index b5f1e54e..9603fa59 100644
--- a/server/tests/test_helpers.py
+++ b/server/tests/test_helpers.py
@@ -59,7 +59,7 @@ def add_default_values():
             # dbc.add.question(name=f"Q{i+1}", total_score=i + 1, type_id=1, slide_id=item_slide.id)
 
             # Add text component
-            dbc.add.component(1, item_slide.id, i, 2 * i, 3 * i, 4 * i, text="Text")
+            dbc.add.component(1, item_slide.id, 1, i, 2 * i, 3 * i, 4 * i, text="Text")
 
 
 def get_body(response):
-- 
GitLab


From 61d47b9aa60cce4c0c5faa4f4a435fb6136e8d8e Mon Sep 17 00:00:00 2001
From: Emil <Emil>
Date: Wed, 28 Apr 2021 10:11:19 +0200
Subject: [PATCH 2/2] Feat: change view type in editor

---
 .../PresentationEditorPage.tsx                | 20 +++++++--
 .../components/SlideDisplay.tsx               | 42 +++++++++++--------
 .../slideSettingsComponents/Images.tsx        | 24 ++++++-----
 .../slideSettingsComponents/Texts.tsx         | 14 ++++---
 .../src/pages/presentationEditor/styled.tsx   | 12 +++++-
 client/src/pages/views/AudienceViewPage.tsx   | 15 ++++---
 client/src/pages/views/JudgeViewPage.tsx      |  4 +-
 .../src/pages/views/ParticipantViewPage.tsx   |  4 +-
 client/src/pages/views/PresenterViewPage.tsx  |  4 +-
 9 files changed, 90 insertions(+), 49 deletions(-)

diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
index 50c3ae52..47a746f2 100644
--- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
@@ -30,6 +30,7 @@ import {
   SlideListItem,
   ToolBarContainer,
   ViewButton,
+  ViewButtonClicked,
   ViewButtonGroup,
 } from './styled'
 
@@ -91,6 +92,7 @@ const PresentationEditorPage: React.FC = () => {
   const { competitionId }: CompetitionParams = useParams()
   const dispatch = useAppDispatch()
   const activeSlideId = useAppSelector((state) => state.editor.activeSlideId)
+  const activeViewTypeId = useAppSelector((state) => state.editor.activeViewTypeId)
   const competition = useAppSelector((state) => state.editor.competition)
   const competitionLoading = useAppSelector((state) => state.editor.loading)
   useEffect(() => {
@@ -166,7 +168,9 @@ const PresentationEditorPage: React.FC = () => {
   const [checkbox, setCheckbox] = useState(false)
 
   const viewTypes = useAppSelector((state) => state.types.viewTypes)
+  const [activeViewTypeName, setActiveViewTypeName] = useState('')
   const changeView = (clickedViewTypeName: string) => {
+    setActiveViewTypeName(clickedViewTypeName)
     const clickedViewTypeId = viewTypes.find((viewType) => viewType.name === clickedViewTypeName)?.id
     if (clickedViewTypeId) {
       dispatch(setEditorViewId(clickedViewTypeId))
@@ -190,10 +194,20 @@ const PresentationEditorPage: React.FC = () => {
             <Typography className={classes.alignCheckboxText} variant="button">
               Applicera ändringar på samtliga vyer
             </Typography>
-            <ViewButton variant="contained" color="secondary" onClick={() => changeView('Audience')}>
+            <ViewButton
+              activeView={activeViewTypeName === 'Audience'}
+              variant="contained"
+              color="secondary"
+              onClick={() => changeView('Audience')}
+            >
               Åskådarvy
             </ViewButton>
-            <ViewButton variant="contained" color="secondary" onClick={() => changeView('Team')}>
+            <ViewButton
+              activeView={activeViewTypeName === 'Team'}
+              variant="contained"
+              color="secondary"
+              onClick={() => changeView('Team')}
+            >
               Deltagarvy
             </ViewButton>
           </ViewButtonGroup>
@@ -255,7 +269,7 @@ const PresentationEditorPage: React.FC = () => {
 
       <Content leftDrawerWidth={leftDrawerWidth} rightDrawerWidth={rightDrawerWidth}>
         <InnerContent>
-          <SlideDisplay editor />
+          <SlideDisplay variant="editor" activeViewTypeId={activeViewTypeId} />
         </InnerContent>
       </Content>
       <Menu
diff --git a/client/src/pages/presentationEditor/components/SlideDisplay.tsx b/client/src/pages/presentationEditor/components/SlideDisplay.tsx
index 6ddb38ef..b2ca9233 100644
--- a/client/src/pages/presentationEditor/components/SlideDisplay.tsx
+++ b/client/src/pages/presentationEditor/components/SlideDisplay.tsx
@@ -1,4 +1,3 @@
-import { Button, Typography } from '@material-ui/core'
 import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
 import { getTypes } from '../../../actions/typesAction'
 import { useAppDispatch, useAppSelector } from '../../../hooks'
@@ -8,12 +7,13 @@ import { SlideEditorContainer, SlideEditorContainerRatio, SlideEditorPaper } fro
 
 type SlideDisplayProps = {
   //Prop to distinguish between editor and active competition
-  editor?: boolean | undefined
+  variant: 'editor' | 'presentation'
+  activeViewTypeId: number
 }
 
-const SlideDisplay = ({ editor }: SlideDisplayProps) => {
+const SlideDisplay = ({ variant, activeViewTypeId }: SlideDisplayProps) => {
   const components = useAppSelector((state) => {
-    if (editor)
+    if (variant === 'editor')
       return state.editor.competition.slides.find((slide) => slide.id === state.editor.activeSlideId)?.components
     return state.presentation.competition.slides.find((slide) => slide.id === state.presentation.slide.id)?.components
   })
@@ -43,21 +43,29 @@ const SlideDisplay = ({ editor }: SlideDisplayProps) => {
       <SlideEditorContainerRatio>
         <SlideEditorPaper ref={editorPaperRef}>
           {components &&
-            components.map((component) => {
-              if (editor)
+            components
+              .filter((component) => component.view_type_id === activeViewTypeId)
+              .map((component) => {
+                if (variant === 'editor')
+                  return (
+                    <RndComponent
+                      height={height}
+                      width={width}
+                      key={component.id}
+                      component={component}
+                      scale={scale}
+                    />
+                  )
                 return (
-                  <RndComponent height={height} width={width} key={component.id} component={component} scale={scale} />
+                  <PresentationComponent
+                    height={height}
+                    width={width}
+                    key={component.id}
+                    component={component}
+                    scale={scale}
+                  />
                 )
-              return (
-                <PresentationComponent
-                  height={height}
-                  width={width}
-                  key={component.id}
-                  component={component}
-                  scale={scale}
-                />
-              )
-            })}
+              })}
         </SlideEditorPaper>
       </SlideEditorContainerRatio>
     </SlideEditorContainer>
diff --git a/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx b/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
index bc83d2fa..a76075c4 100644
--- a/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
+++ b/client/src/pages/presentationEditor/components/slideSettingsComponents/Images.tsx
@@ -96,17 +96,19 @@ const Images = ({ activeViewTypeId, activeSlide, competitionId }: ImagesProps) =
         </Center>
       </ListItem>
       {images &&
-        images.map((image) => (
-          <div key={image.id}>
-            <ListItem divider button>
-              <ImportedImage src={`http://localhost:5000/static/images/thumbnail_${image.media?.filename}`} />
-              <Center>
-                <ListItemText primary={image.media?.filename} />
-              </Center>
-              <CloseIcon onClick={() => handleCloseimageClick(image)} />
-            </ListItem>
-          </div>
-        ))}
+        images
+          .filter((image) => image.view_type_id === activeViewTypeId)
+          .map((image) => (
+            <div key={image.id}>
+              <ListItem divider button>
+                <ImportedImage src={`http://localhost:5000/static/images/thumbnail_${image.media?.filename}`} />
+                <Center>
+                  <ListItemText primary={image.media?.filename} />
+                </Center>
+                <CloseIcon onClick={() => handleCloseimageClick(image)} />
+              </ListItem>
+            </div>
+          ))}
 
       <ListItem button style={{ padding: 0 }}>
         <HiddenInput accept="image/*" id="contained-button-file" multiple type="file" onChange={handleFileSelected} />
diff --git a/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx b/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
index b1e9fa9b..03656614 100644
--- a/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
+++ b/client/src/pages/presentationEditor/components/slideSettingsComponents/Texts.tsx
@@ -44,12 +44,14 @@ const Texts = ({ activeViewTypeId, activeSlide, competitionId }: TextsProps) =>
         </Center>
       </ListItem>
       {texts &&
-        texts.map((text) => (
-          <TextCard elevation={4} key={text.id}>
-            <TextComponentEdit component={text} />
-            <Divider />
-          </TextCard>
-        ))}
+        texts
+          .filter((text) => text.view_type_id === activeViewTypeId)
+          .map((text) => (
+            <TextCard elevation={4} key={text.id}>
+              <TextComponentEdit component={text} />
+              <Divider />
+            </TextCard>
+          ))}
       <ListItem button onClick={handleAddText}>
         <Center>
           <AddButton variant="button">Lägg till text</AddButton>
diff --git a/client/src/pages/presentationEditor/styled.tsx b/client/src/pages/presentationEditor/styled.tsx
index d1f05d6b..ea266c5e 100644
--- a/client/src/pages/presentationEditor/styled.tsx
+++ b/client/src/pages/presentationEditor/styled.tsx
@@ -7,8 +7,18 @@ export const ToolBarContainer = styled(Toolbar)`
   padding-left: 0;
 `
 
-export const ViewButton = styled(Button)`
+interface ViewButtonProps {
+  activeView: boolean
+}
+
+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`
diff --git a/client/src/pages/views/AudienceViewPage.tsx b/client/src/pages/views/AudienceViewPage.tsx
index 8d58a364..d03f3367 100644
--- a/client/src/pages/views/AudienceViewPage.tsx
+++ b/client/src/pages/views/AudienceViewPage.tsx
@@ -1,16 +1,15 @@
+import { Typography } from '@material-ui/core'
 import React from 'react'
+import { useAppSelector } from '../../hooks'
 import SlideDisplay from '../presentationEditor/components/SlideDisplay'
-import PresentationComponent from './components/PresentationComponent'
-import mockedAxios from 'axios'
 
 const AudienceViewPage: React.FC = () => {
-  const res = {
-    data: {},
+  const viewTypes = useAppSelector((state) => state.types.viewTypes)
+  const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Audience')?.id
+  if (activeViewTypeId) {
+    return <SlideDisplay variant="presentation" activeViewTypeId={activeViewTypeId} />
   }
-  ;(mockedAxios.get as jest.Mock).mockImplementation(() => {
-    return Promise.resolve(res)
-  })
-  return <SlideDisplay />
+  return <Typography>Error: Åskådarvyn kunde inte laddas</Typography>
 }
 
 export default AudienceViewPage
diff --git a/client/src/pages/views/JudgeViewPage.tsx b/client/src/pages/views/JudgeViewPage.tsx
index de5abe40..f72c052d 100644
--- a/client/src/pages/views/JudgeViewPage.tsx
+++ b/client/src/pages/views/JudgeViewPage.tsx
@@ -46,6 +46,8 @@ const JudgeViewPage = ({ competitionId, code }: JudgeViewPageProps) => {
   const history = useHistory()
   const dispatch = useAppDispatch()
   const [activeSlideIndex, setActiveSlideIndex] = useState<number>(0)
+  const viewTypes = useAppSelector((state) => state.types.viewTypes)
+  const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Judge')?.id
   const teams = useAppSelector((state) => state.presentation.competition.teams)
   const slides = useAppSelector((state) => state.presentation.competition.slides)
   const handleSelectSlide = (index: number) => {
@@ -114,7 +116,7 @@ const JudgeViewPage = ({ competitionId, code }: JudgeViewPageProps) => {
       <div style={{ height: 64 }} />
       <Content leftDrawerWidth={leftDrawerWidth} rightDrawerWidth={rightDrawerWidth}>
         <InnerContent>
-          <SlideDisplay />
+          {activeViewTypeId && <SlideDisplay variant="presentation" activeViewTypeId={activeViewTypeId} />}
         </InnerContent>
       </Content>
     </div>
diff --git a/client/src/pages/views/ParticipantViewPage.tsx b/client/src/pages/views/ParticipantViewPage.tsx
index ffee1ee1..0c4db2c0 100644
--- a/client/src/pages/views/ParticipantViewPage.tsx
+++ b/client/src/pages/views/ParticipantViewPage.tsx
@@ -9,6 +9,8 @@ import { useAppSelector } from '../../hooks'
 const ParticipantViewPage: 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 === 'Participant')?.id
   useEffect(() => {
     //hides the url so people can't sneak peak
     history.push('participant')
@@ -19,7 +21,7 @@ const ParticipantViewPage: React.FC = () => {
   }, [])
   return (
     <ParticipantContainer>
-      <SlideDisplay />
+      {activeViewTypeId && <SlideDisplay variant="presentation" activeViewTypeId={activeViewTypeId} />}
     </ParticipantContainer>
   )
 }
diff --git a/client/src/pages/views/PresenterViewPage.tsx b/client/src/pages/views/PresenterViewPage.tsx
index f221f5a9..6c853a60 100644
--- a/client/src/pages/views/PresenterViewPage.tsx
+++ b/client/src/pages/views/PresenterViewPage.tsx
@@ -61,6 +61,8 @@ const PresenterViewPage: React.FC = () => {
   const presentation = useAppSelector((state) => state.presentation)
   const history = useHistory()
   const dispatch = useAppDispatch()
+  const viewTypes = useAppSelector((state) => state.types.viewTypes)
+  const activeViewTypeId = viewTypes.find((viewType) => viewType.name === 'Presenter')?.id
 
   useEffect(() => {
     dispatch(getPresentationCompetition(id))
@@ -137,7 +139,7 @@ const PresenterViewPage: React.FC = () => {
       <div style={{ height: 0, paddingTop: 120 }} />
       <PresenterContent>
         <PresenterInnerContent>
-          <SlideDisplay />
+          {activeViewTypeId && <SlideDisplay variant="presentation" activeViewTypeId={activeViewTypeId} />}
         </PresenterInnerContent>
       </PresenterContent>
       <div style={{ height: 0, paddingTop: 140 }} />
-- 
GitLab