From cb2bfd8a76237a05c2743886b70f2f57dc37b136 Mon Sep 17 00:00:00 2001
From: EdwardAJ <13517115@std.stei.itb.ac.id>
Date: Wed, 8 Apr 2020 01:01:58 +0700
Subject: [PATCH] Add design to toolbar

---
 frontend/components/label/Box.vue     |  11 ++-
 frontend/components/label/Toolbar.vue |  64 +++++++++++++
 frontend/components/view/Suggest.vue  |  10 +-
 frontend/pages/viewer/index-edit.vue  |  41 +++++++-
 frontend/pages/viewer/index.vue       | 133 ++++++++++++++++----------
 5 files changed, 202 insertions(+), 57 deletions(-)
 create mode 100644 frontend/components/label/Toolbar.vue

diff --git a/frontend/components/label/Box.vue b/frontend/components/label/Box.vue
index a7aec54..350b319 100644
--- a/frontend/components/label/Box.vue
+++ b/frontend/components/label/Box.vue
@@ -16,7 +16,7 @@
       class="circle"
       :style="{ top: bTop + -6 + 'px', left: bLeft + -6 + 'px'}"
       @mousedown="isLeftCircleActive = true"
-      @mousemove="resizeBox"
+      @mousemove="resizeBoxFromTopLeft"
       @mouseup="onStopResize"
     />
 
@@ -35,7 +35,8 @@
       class="suggestion-form"
       :style="{ top: bTop + -6 + 'px', left: bLeft + bWidth * 0.3 + 'px', width: suggestWidth + 'px'}"
       :class="{'suggest-active': isSuggestActive}"
-      :initialData="bContent"
+      :initial-data="bContent"
+      :suggest-type="suggestType"
       @onEnableForm="handleOnEnableForm"
       @onDisableForm="handleOnDisableForm"
     />
@@ -88,6 +89,10 @@ export default {
       type: String,
       default: ''
     },
+    suggestType: {
+      type: String,
+      default: 'label'
+    },
     canDelete: {
       type: Boolean,
       default: true
@@ -127,7 +132,7 @@ export default {
         this.$emit("onDelete", this.bIndex)
       }
     },
-    resizeBox (e) {
+    resizeBoxFromTopLeft (e) {
       if (this.bActive && this.isLeftCircleActive) {
         this.isOnResize = true
         var prevbLeft = this.bLeft
diff --git a/frontend/components/label/Toolbar.vue b/frontend/components/label/Toolbar.vue
new file mode 100644
index 0000000..11f170d
--- /dev/null
+++ b/frontend/components/label/Toolbar.vue
@@ -0,0 +1,64 @@
+<template>
+  <div class="bg-toolbar">
+    <div class="layout">
+      <i
+        class="first-icon-margin icon fas fa-plus"
+        :class="{'active': activeIcon === 'add-box'}"
+        @click="handleClickEvent('add-box')"
+      />
+      <i
+        class="icon fas fa-expand"
+        :class="{'active': activeIcon === 'resize-box'}"
+        @click="handleClickEvent('resize-box')"
+      />
+      <i
+        class="icon fas fa-trash"
+        :class="{'active': activeIcon === 'delete-box'}"
+        @click="handleClickEvent('delete-box')"
+      />
+    </div>
+  </div>
+</template>
+
+<script scoped>
+export default {
+  data () {
+    return {
+      activeIcon: 'add-box'
+    }
+  },
+  methods: {
+    handleClickEvent (iconName) {
+      this.activeIcon = iconName
+      this.$emit("onIconClick", iconName)
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .bg-toolbar {
+    background-color: #F7F7F7;
+    width: 3.75vw;
+  }
+
+  .icon {
+    font-size: 1.1rem;
+    color: #707070;
+    margin-top: 27px;
+  }
+
+  .first-icon-margin {
+    margin-top: 32px;
+  }
+
+  .layout {
+    margin-left: calc(3.75vw - 2.1rem);
+    cursor: pointer;
+  }
+
+  .active {
+    color: #009DFF;
+  }
+
+</style>
\ No newline at end of file
diff --git a/frontend/components/view/Suggest.vue b/frontend/components/view/Suggest.vue
index e116058..81370f2 100644
--- a/frontend/components/view/Suggest.vue
+++ b/frontend/components/view/Suggest.vue
@@ -27,6 +27,10 @@ export default {
     initialData: {
       type: String,
       default: ''
+    },
+    suggestType: {
+      type: String,
+      default: 'label'
     }
   },
   data() {
@@ -46,7 +50,11 @@ export default {
         this.simpleSuggestionList.push(content['content_name'])
       })
     }
-    this.enableForm()
+    
+    if (this.suggestType !== 'edit') {
+      this.enableForm()
+    }
+
     this.$watch(() => {
       if (this.$refs["form"].isInFocus) {
         this.enableForm()
diff --git a/frontend/pages/viewer/index-edit.vue b/frontend/pages/viewer/index-edit.vue
index 17c8c8a..d15104c 100644
--- a/frontend/pages/viewer/index-edit.vue
+++ b/frontend/pages/viewer/index-edit.vue
@@ -33,6 +33,7 @@
           <Box
             v-if="boxes[i]"
             :key="i"
+            :suggest-type="'edit'"
             :b-width="boxes[i].width"
             :b-height="boxes[i].height"
             :b-top="boxes[i].top"
@@ -89,6 +90,14 @@ export default {
       isEdited: false
     }
   },
+  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)
+  },
   async mounted () {
     this.image.url = this.$route.query.url
     this.image.id = this.$route.query.id
@@ -96,7 +105,21 @@ export default {
     this.dataReady = false
     this.dataReady = true
   },
+  async beforeDestroy () {
+    // window.removeEventListener("beforeunload", true)
+    await this.closeViewer()
+  },
   methods: {
+    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 getAllLabels () {
       var url = '/api/label/imagequery/' + this.image.id
       var response = await this.$axios.get(url).catch( error => console.error(error))
@@ -147,9 +170,25 @@ export default {
       console.log(this.boxes)
       console.log(this.previouslyCreatedBox)
     },
-    closeViewer () {
+    async closeViewer () {
+      try {
+        await this.deleteImageAccessControlByImageID(this.image.id)
+      } catch (error) {
+        console.log(error)
+      }
+      clearInterval(this.timer)
       this.$router.push('/main/edit')
     },
+    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
+      }
+    },
     onMouseDownHandler (e) {
       if (this.drawingBox.active) {
         this.stopDrawingBox()
diff --git a/frontend/pages/viewer/index.vue b/frontend/pages/viewer/index.vue
index 4094326..f179228 100644
--- a/frontend/pages/viewer/index.vue
+++ b/frontend/pages/viewer/index.vue
@@ -1,57 +1,67 @@
 <template>
   <div ref="imageWrapper" class="viewer-background">
-    <div class="btn-close-section">
-      <button
-        type="button"
-        class="btn-label-no-border btn-sm btn-light btn-close-text mt-2"
-        aria-label="Close"
-        @click="closeViewer()"
-      > 
-        <span aria-hidden="true">&times;</span>
-      </button>
-    </div>
-    <div class="viewer-wrapper center center-horizontal" @mousedown="stopDrawingBox">
-      <div id="image">
-        <img
-          ref="image"
-          draggable="false"
-          class="image"
-          :src="image.url"
-          @mousedown="onMouseDownHandler"
-          @mousemove="changeBox"
-          @mouseup="stopDrawingBox"
-        >
-        <Box
-          v-if="drawingBox.active"
-          :b-width="drawingBox.width"
-          :b-height="drawingBox.height"
-          :b-top="drawingBox.top"
-          :b-left="drawingBox.left"
-        />
-        <div v-for="i in Object.keys(boxes)" :key="i">
-          {{ i }}
+    <div class="flex-viewer">
+      <Toolbar
+        @onIconClick="setBoxAction($event)"
+      />
+      <div class="viewer-wrapper center center-horizontal" @mousedown="stopDrawingBox">
+        <div id="image">
+          <img
+            ref="image"
+            draggable="false"
+            class="image"
+            :src="image.url"
+            @mousedown="onMouseDownHandler"
+            @mousemove="changeBox"
+            @mouseup="stopDrawingBox"
+          >
           <Box
-            v-if="boxes[i]"
-            :key="i"
-            :b-width="boxes[i].width"
-            :b-height="boxes[i].height"
-            :b-top="boxes[i].top"
-            :b-left="boxes[i].left"
-            :b-active="i === activeBoxIndex"
-            :b-index="parseInt(i)"
-            :b-content="boxes[i].content"
-            :can-delete="canDelete"
-            @onStopResize="changeBoxAttribute($event, i)"
-            @onDelete="deleteBox(i)"
-            @onSelect="makeCurrentBoxActive(i)"
-            @onDisableForm="changeBoxContent($event, i)"
-            @onEnableForm="makeCurrentBoxActive(i)"
+            v-if="drawingBox.active"
+            :b-width="drawingBox.width"
+            :b-height="drawingBox.height"
+            :b-top="drawingBox.top"
+            :b-left="drawingBox.left"
           />
+          <div v-for="i in Object.keys(boxes)" :key="i">
+            <Box
+              v-if="boxes[i]"
+              :key="i"
+              :b-width="boxes[i].width"
+              :b-height="boxes[i].height"
+              :b-top="boxes[i].top"
+              :b-left="boxes[i].left"
+              :b-active="i === activeBoxIndex"
+              :b-index="parseInt(i)"
+              :b-content="boxes[i].content"
+              :can-delete="canDelete"
+              @onStopResize="changeBoxAttribute($event, i)"
+              @onDelete="deleteBox(i)"
+              @onSelect="makeCurrentBoxActive(i)"
+              @onDisableForm="changeBoxContent($event, i)"
+              @onEnableForm="makeCurrentBoxActive(i)"
+            />
+          </div>
+        </div>
+      </div>
+      <div class="button-block">
+        <div class="btn-close-section">
+          <button
+            type="button"
+            class="btn-label-no-border btn-sm btn-light btn-close-text mt-2"
+            aria-label="Close"
+            @click="closeViewer()"
+          > 
+            <span aria-hidden="true">&times;</span>
+          </button>
         </div>
       </div>
     </div>
-    <div class="btn-section">
-      <button type="button" class="btn-label-no-border btn-lg btn-dark btn-text" @click="saveImage">
+    <div class="btn-save-section">
+      <button
+        type="button"
+        class="btn-label-no-border btn-lg btn-dark btn-text"
+        @click="saveImage"
+      >
         Save Image
       </button>
     </div>
@@ -60,11 +70,13 @@
 
 <script>
 import Box from '~/components/label/Box'
+import Toolbar from '~/components/label/Toolbar'
 import { Cursors } from '~/mixins/label/getCursorPosition'
 
 export default {
   components: {
-    Box
+    Box,
+    Toolbar
   },
   data () {
     return {
@@ -114,6 +126,9 @@ export default {
         await this.closeViewer()
       }
     },
+    setBoxAction (iconName) {
+      console.log("Icon name: ", iconName)
+    },
     async closeViewer () {
       try {
         await this.deleteImageAccessControlByImageID(this.image.id)
@@ -346,7 +361,7 @@ export default {
   }
 
   .viewer-wrapper {
-    height: 87.5vh;
+    /* height: 87.5vh; */
     width: 100vw;
   }
 
@@ -359,10 +374,10 @@ export default {
     justify-content: center;
   }
 
-  .btn-section {
+  .btn-save-section {
     text-align: right;
-    margin-right: 15px;
-    margin-top: -10px;
+    margin-top: -40px;
+    margin-right: 5px;
   }
 
   .btn-text { 
@@ -384,4 +399,18 @@ export default {
     border: 0;
   }
 
+  .btn-lg {
+    width: 115px;
+  }
+
+  .flex-viewer {
+    display: flex;
+    height: 100vh;
+  }
+  
+  .button-block {
+    display: block;
+    height: 100vh;
+  }
+
 </style>
\ No newline at end of file
-- 
GitLab