diff --git a/frontend/components/view/Images.vue b/frontend/components/view/Images.vue
index 92a5ea9d2635dabc4b9cfd3106991592175e543e..ea03627e7f507404b3fee10898638f8f46be2930 100644
--- a/frontend/components/view/Images.vue
+++ b/frontend/components/view/Images.vue
@@ -1,8 +1,8 @@
 <template>
-  <article class="blog-card">
-    <img class="post-image" :src="imageURL">
+  <article class="blog-card" :class="{'disable': isCurrentlyLabeled}">
+    <img class="post-image" :class="{'post-image-disabled': isCurrentlyLabeled}" :src="imageURL">
     <div class="article-details">
-      <h3 class="post-title"> 
+      <h3 class="post-title" :class="{'post-title-disabled': isCurrentlyLabeled}"> 
         {{ dataImageName }}
       </h3>
     </div>
@@ -23,6 +23,10 @@ export default {
     imageName: {
       type: String,
       default: ''
+    },
+    isCurrentlyLabeled: {
+      type: Boolean,
+      default: false
     }
   },
   data () {
@@ -62,6 +66,17 @@ export default {
   cursor: pointer;
 }
 
+.disable {
+  background-color: #F0F0F0;
+  -webkit-box-shadow: 0 0 0 0px rgba(0,0,0,0.0);
+  -moz-box-shadow: 0 0 0 0px rgba(0,0,0,0.0);
+  box-shadow: 0 0 0 0px rgba(0,0,0,0.0);
+}
+
+.blog-card:hover {
+  background: #F0F0F0;
+}
+
 .post-image {
   display: block;
   width: 100%;
@@ -69,6 +84,10 @@ export default {
   height: 100%;
 }
 
+.post-image-disabled {
+  opacity: 0.5;
+}
+
 .article-details {
   padding: 1.7rem;
 }
@@ -81,4 +100,8 @@ export default {
   margin: 0 0 0 0;
 }
 
+.post-title-disabled {
+  color: #D6D6D6;
+}
+
 </style>
\ No newline at end of file
diff --git a/frontend/components/view/Suggest.vue b/frontend/components/view/Suggest.vue
index 9af9ba3b3a02ebee331c0dacffa42b414e82f1ed..feb63a1d4ccf68bb79cb9d303080e3f8b2637947 100644
--- a/frontend/components/view/Suggest.vue
+++ b/frontend/components/view/Suggest.vue
@@ -34,9 +34,11 @@ export default {
   },
   async mounted () {
     const response = await this.$axios.get('/api/content/?suggestion=').catch((error) => console.error(error))
-    response.data.data.forEach((content) => {
-      this.simpleSuggestionList.push(content['content_name'])
-    })
+    if (response.data.data) {
+      response.data.data.forEach((content) => {
+        this.simpleSuggestionList.push(content['content_name'])
+      })
+    }
     this.enableForm()
     this.$watch(() => {
       if (this.$refs["form"].isInFocus) {
diff --git a/frontend/mixins/image/getAllLabeledImages.js b/frontend/mixins/image/getAllLabeledImages.js
index 888e93af1aefaeb7d8bfd589aab9e2f8177243bf..301eb469d37b2624bd25d53745d770d0d9237701 100644
--- a/frontend/mixins/image/getAllLabeledImages.js
+++ b/frontend/mixins/image/getAllLabeledImages.js
@@ -20,7 +20,7 @@ export default {
       var url = '/api/image/?PerPage=9999999999&Page=1'
       var response = await this.$axios(url).catch(error => console.log(error))
       if (response && response.status === 200) {
-        return response.data.data
+        return response.data.data.images
       } else {
         return null
       }
@@ -29,6 +29,8 @@ export default {
   async mounted () {
     var labeled = await this.getAllLabeledImages()
     var allImg = await this.getAllImages()
+    console.log("label: ", labeled)
+    console.log("allImg: ", allImg)
     var labeledImageID = []
     if (labeled && allImg) {
       //Get Uniqe All of Labeled Image ID
diff --git a/frontend/pages/main/json-view/index.vue b/frontend/pages/main/json-view/index.vue
index e783b860f1fc56de53f16aa167137e46c15505b9..2858ca41b565529898be6023635261ce46501389 100644
--- a/frontend/pages/main/json-view/index.vue
+++ b/frontend/pages/main/json-view/index.vue
@@ -4,7 +4,7 @@
       <div class="row">
         <div class="col users-margin">
           <h5 class="title">
-            Image ID: {{ id }}
+            Image Name: {{ name }}
           </h5>            
         </div>
       </div>
diff --git a/frontend/pages/main/json.vue b/frontend/pages/main/json.vue
index 38a0ae221e19a299eb56bf6e4b69ef61f7828459..e00ffef30f24a6d5fc57585e3a1d31264dcc1038 100644
--- a/frontend/pages/main/json.vue
+++ b/frontend/pages/main/json.vue
@@ -38,8 +38,9 @@
           <div id="container">
             <nuxt-link :to="{ path: '/main/json-view', query: {id: labs.ImageID, name: labs.Filename}}">
               <Images
+                :image-name="labs.Filename"
                 :image-i-d="labs.ImageID"
-                :image-u-r-l="labs.ImagePath"
+                :image-u-r-l="backendURL + '/api/' + labs.ImagePath"
               />
             </nuxt-link>
             <br>
@@ -63,7 +64,7 @@ export default {
 <script>
 import Images from '~/components/view/Images.vue'
 import getAllLabeledImages from '~/mixins/image/getAllLabeledImages.js'
-
+import  { backendURL } from '~/config.js'
 export default {
   components: {
     Images
@@ -71,6 +72,7 @@ export default {
   mixins: [getAllLabeledImages],
   data () {
     return {
+      backendURL: backendURL,
       // edit: [
       //   { name: 'sdfdosfhdauofhd', image: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1159990/pike-place.jpg', json: '{id:1}'},
       //   { name: 'ssasdassfggfgfd', image: 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1159990/pike-place.jpg', json: '{id:1}'},
diff --git a/frontend/pages/main/label.vue b/frontend/pages/main/label.vue
index 64e725c5c8ab0644dd69c71e34792b0909d29a45..7a51dd0bf8633712c1274af51617e63bc4761e52 100644
--- a/frontend/pages/main/label.vue
+++ b/frontend/pages/main/label.vue
@@ -22,18 +22,18 @@
         </div>
       </div>
       <br>
-      <b-row>
-        <b-col v-for="image in images" :key="image.id">
+      <b-row v-if="images" :key="updateUI">
+        <b-col v-for="id in Object.keys(images)" :key="id">
           <div id="container">
-            <nuxt-link :to="{ path: '/viewer', query: { url: image.url, id: image.id }}">
-              <Images
-                class="animated fast fadeIn"
-                :src="image.url"
-                :image-i-d="image.id"
-                :image-u-r-l="image.url"
-                :image-name="image.name"
-              />
-            </nuxt-link>
+            <Images
+              class="animated fadeIn"
+              :src="images[id].url"
+              :image-i-d="images[id].id"
+              :image-u-r-l="images[id].url"
+              :image-name="images[id].name"
+              :is-currently-labeled="images[id].isCurrentlyLabeled"
+              @click.native="openViewer(images[id])"
+            />
             <br>
           </div>
         </b-col>
@@ -41,7 +41,7 @@
       <b-pagination
         v-model="page"
         class="mt-3"
-        :total-rows="100"
+        :total-rows="totalRows"
         pills
         :per-page="perPage"
       />
@@ -59,20 +59,29 @@ export default {
   },
   data () {
     return {
-      images: [],
+      images: {},
       keyword: '',
       isViewerActive: false,
       perPage: 12,
-      page: 1
+      totalRows: 0,
+      page: 1,
+      timer: '',
+      updateUI: false
     }
   },
   watch: {
     async page () {
-      await this.getAllImages(this.perPage, this.page, this.keyword)
+      this.images = {}
+      await this.getAllImagesWithLabelStatus()
     }
   },
-  async mounted () {
-    await this.getAllImages(this.perPage, this.page, this.keyword)
+  async created () {
+    this.images = {}
+    await this.getAllImagesWithLabelStatus()
+    this.timer = setInterval(this.getAllImagesWithLabelStatus, 5000)
+  },
+  beforeDestroy () {
+    clearInterval(this.timer)
   },
   methods: {
     async getAllImages(perPage, page, keyword) {
@@ -84,27 +93,85 @@ export default {
           search: keyword
         }
       }).catch((error) => console.error(error))
-      this.images = []
-      if (response.data.data) {
-        response.data.data.forEach((image) => {
+      console.log("Images: ", response.data.data.images)
+      if (response.data.data.images) {
+        this.totalRows = (response.data.data["total_page"] + 1) * this.perPage
+        response.data.data.images.forEach((image) => {
           if (!image.Labeled) {
             var imageObj = {
               id: image.ImageID,
               name: image.Filename,
-              url: backendURL + '/api/' + image.ImagePath
+              url: backendURL + '/api/' + image.ImagePath,
+              isCurrentlyLabeled: false
+            }
+            this.images[image.ImageID] = imageObj
+            console.log("Images: ", this.images)
+          }
+        })
+      }
+    },
+    async getImageCurrentlyBeingLabelled() {
+      var url = '/api/accesscontrol'
+      const response = await this.$axios.get(url).catch((error) => console.error(error))
+      console.log("Response image labelled: ", response.data.data)
+      if (response.data.data) {
+        response.data.data.forEach(async (imageStatus) => {
+          // Delete access control
+          if (imageStatus["timeout"] < this.getCurrentTime()) {
+            await this.deleteImageAccessControlByImageID(imageStatus["image_id"]).catch((error) => console.error(error))
+          } else {
+            if (this.images[imageStatus["image_id"]]) {
+              this.images[imageStatus["image_id"]].isCurrentlyLabeled = true
             }
-            this.images.push(imageObj)
           }
         })
       }
+      this.updateUI = !this.updateUI
+    },
+    async getAllImagesWithLabelStatus() {
+      this.images = {}
+      await this.getAllImages(this.perPage, this.page, this.keyword)
+      await this.getImageCurrentlyBeingLabelled()
+    },
+    getCurrentTime () {
+      var date = new Date()
+      return date.toISOString()
+    },
+    async deleteImageAccessControlByImageID (imageID) {
+      var url = '/api/accesscontrol/' + imageID
+      try {
+        var response = await this.$axios.delete(url)
+        if (this.images[imageID]) {
+          this.images[imageID].isCurrentlyLabeled = false
+        }
+        return response.data.status
+      } catch (error) {
+        console.log("Label" , error)
+        throw error
+      }
+    },
+    async openViewer (image) {
+      console.log(image)
+      if (!image.isCurrentlyLabeled) {
+        var url = '/api/accesscontrol/' + image.id
+        try {
+          await this.$axios.get(url)
+          alert("This image is currently Labeled")
+        } catch (e) {
+          this.$router.push({ path: '/viewer', query: { url: image.url, id: image.id }})
+        }
+      }
     },
     debounceWrapper (e) {
       this.page = 1
+      this.keyword = e.target.value
+      // alert(this.keyword)
       this.debounceInput(e)
     },
     // Only fires when user stops typing
-    debounceInput: debounce(async function (e) {
-      await this.getAllImages(this.perPage, this.page, e.target.value)
+    debounceInput: debounce(async function () {
+      await this.getAllImagesWithLabelStatus()
+      // await this.getAllImages(this.perPage, this.page, e.target.value)
     }, 500)
   }
 }
diff --git a/frontend/pages/viewer/index.vue b/frontend/pages/viewer/index.vue
index 8ebb67d9604264058fcd76e2492fec2c95bf461d..409432644ed4f97f3877c0a76fd7a6bea229b8c6 100644
--- a/frontend/pages/viewer/index.vue
+++ b/frontend/pages/viewer/index.vue
@@ -83,15 +83,44 @@ export default {
         url: ''
       },
       canDelete: true,
-      labelCount: 0
+      labelCount: 0,
+      timer: ''
     }
   },
+  async created () {
+    window.addEventListener("beforeunload", async (event) => {
+      await this.closeViewer()
+      event.returnValue= "You have unsaved changes."
+    })
+    await this.startHeartBeat()
+    this.timer = setInterval(this.startHeartBeat, 90000)
+  },
   mounted () {
     this.image.url = this.$route.query.url
     this.image.id = this.$route.query.id
   },
+  async beforeDestroy () {
+    // window.removeEventListener("beforeunload", true)
+    await this.closeViewer()
+  },
   methods: {
-    closeViewer () {
+    async startHeartBeat() {
+      var url = '/api/accesscontrol/requestaccess/' + parseInt(this.$route.query.id)
+      // alert(url)
+      try {
+        await this.$axios.get(url).catch((error) => console.error(error))
+      } catch (error) {
+        this.showFailedAlert("An error occured", error)
+        await this.closeViewer()
+      }
+    },
+    async closeViewer () {
+      try {
+        await this.deleteImageAccessControlByImageID(this.image.id)
+      } catch (error) {
+        console.log(error)
+      }
+      clearInterval(this.timer)
       this.$router.push('/main/label')
     },
     onMouseDownHandler (e) {
@@ -197,8 +226,8 @@ export default {
         try {
           console.log("LABEL PAYLOAD: ", labelPayload)
           await this.createAllLabelsInImage(labelPayload)
-          this.showSuccessAlert("Success!", "Image has been saved!").then(() => {
-            this.closeViewer()
+          this.showSuccessAlert("Success!", "Image has been saved!").then(async () => {
+            await this.closeViewer()
           })
         } catch (error) {
           console.log(error)
@@ -293,6 +322,16 @@ export default {
         console.log("Label" , error)
         throw error
       }
+    },
+    async deleteImageAccessControlByImageID (imageID) {
+      var url = '/api/accesscontrol/' + imageID
+      try {
+        var response = await this.$axios.delete(url)
+        return response.data.status
+      } catch (error) {
+        console.log("Label" , error)
+        throw error
+      }
     }
   }
 }