diff --git a/frontend/components/dropdown/Dropdown.vue b/frontend/components/dropdown/Dropdown.vue index 017e0661bb817e2b9109309bd3a3487b35e32554..99fb4da72949fd993e269f08c9afe356d33ce2f8 100644 --- a/frontend/components/dropdown/Dropdown.vue +++ b/frontend/components/dropdown/Dropdown.vue @@ -1,11 +1,13 @@ <template> <div :key="dataReady"> - <vue-dropdown - ref="dropdown" - class="dropdown" - :config="config" - @setSelectedOption="setNewSelectedOption($event)" - /> + <b-dropdown :text="dataset"> + <b-dropdown-item + v-for="(item, idx) in config.options" :key="idx" + @click.native="setNewSelectedOption(item)" + > + {{ item.value }} + </b-dropdown-item> + </b-dropdown> </div> </template> @@ -25,13 +27,8 @@ export default { return { config: { options: [], - width: 200, - placeholder: "Choose folder", - backgroundColor: "white", - textColor: "#1E889B", - border: "" }, - folder: [], + dataset: '', dataReady: false } }, @@ -42,6 +39,18 @@ export default { }) } await this.getOptions() + if (this.dropdownValue) { + this.dataset = this.dropdownValue + } else { + this.dataset = "Choose Folder" + console.log("Dataset: ", this.dataset) + if (!this.isFolderNotExist()) { + if (!this.isUpload) { + this.dataset = this.config.options[0].value + } + } + this.$emit("onDatasetChanged", this.dataset) + } this.dataReady = true }, methods: { @@ -58,19 +67,6 @@ export default { }) } } - if (this.dropdownValue) { - this.config.placeholder = this.dropdownValue - } else { - if (!this.isFolderNotExist()) { - if (this.isUpload) { - this.config.placeholder = this.config.options[1].value - } else { - this.config.placeholder = this.config.options[0].value - } - this.dataset = this.config.placeholder - this.$emit("onDatasetChanged", this.dataset) - } - } }, isFolderNotExist () { if (this.isUpload) { @@ -80,7 +76,6 @@ export default { } }, async setNewSelectedOption(selectedOption) { - this.config.placeholder = selectedOption.value this.dataset = selectedOption.value if (this.dataset === "Add New Folder") { this.createNewFolder() @@ -89,29 +84,36 @@ export default { }, createNewFolder() { this.$swal.fire({ - title: "New folder name", + title: "New folder name: ", input:'text', inputValidator: (value) => { if (!value) { return 'You need to write something!' } else { - this.config.placeholder = value this.dataset = value this.$emit("onDatasetChanged", this.dataset) } }, confirmButtonColor: '#11616F', showCancelButton: true - }) + }).then((result) => { + console.log("Result: ", result) + if (!result.value) { + this.dataset = "Choose Folder" + console.log("Dataset: ", this.dataset) + } + }) }, } } </script> -<style scoped> - .dropdown { - -webkit-box-shadow: 2px 5px 5px 0px rgba(0,0,0,0.15); - -moz-box-shadow: 2px 5px 5px 0px rgba(0,0,0,0.15); - box-shadow: 2px 5px 5px 0px rgba(0,0,0,0.15); +<style> + .dropdown .btn { + background-color: #1E889B; + color: white; + font-family: "Open Sans Bold"; + border: 0; + border-radius: 7px; } </style> \ No newline at end of file diff --git a/frontend/components/label/Label.vue b/frontend/components/label/Label.vue index 80354ab045c2c3c8cc6712b21d9d7af297f201d4..ececc4409dfea08f33932bd610b559d2256b3786 100644 --- a/frontend/components/label/Label.vue +++ b/frontend/components/label/Label.vue @@ -2,24 +2,11 @@ <div class="col"> <div class="ml-4"> <div class="row"> - <div class="col"> - <h5 class="title users-margin"> - {{ title }} - </h5> - </div> - </div> - <br> - <div class="row form-title-margin"> <div class="col"> <div class="flex-display"> - <input - id="imagesID" - type="text" - class="form-control form-border field-length form-content" - placeholder="Search for file name..." - name="imagesID" - @input="debounceWrapper" - > + <h5 class="title users-margin"> + {{ title }} + </h5> <div class="slot-margin"> <slot /> </div> @@ -27,6 +14,19 @@ </div> </div> <br> + <div class="row form-title-margin"> + <div class="col"> + <input + id="imagesID" + type="text" + class="form-control form-border field-length form-content" + placeholder="Search for file name..." + name="imagesID" + @input="debounceWrapper" + > + </div> + </div> + <br> <b-row v-if="images" :key="updateUI"> <b-col v-for="id in Object.keys(images)" :key="id"> <div id="container"> @@ -43,6 +43,14 @@ </div> </b-col> </b-row> + <div + v-if="Object.keys(images).length === 0" + id="container" class="no-image-height animated fast fadeIn" + > + <p class="no-image"> + No Images Found + </p> + </div> <b-pagination v-model="page" class="mt-3" @@ -114,7 +122,15 @@ export default { async created () { this.images = {} await this.getAllImagesWithLabelStatus() - this.timer = setInterval(this.getAllImagesWithLabelStatus, 10000) + if (!this.isOutputViewer) { + this.timer = setInterval(this.getAllImagesWithLabelStatus, 10000) + } else { + if (Object.keys(this.images).length === 0) { + this.$emit("onEmpty", true) + } else { + this.$emit("onEmpty", false) + } + } }, beforeDestroy () { clearInterval(this.timer) @@ -143,6 +159,7 @@ export default { this.images[image.ImageID] = imageObj }) } + }, async getImageCurrentlyBeingLabelled() { var url = '/api/accesscontrol' @@ -164,7 +181,9 @@ export default { async getAllImagesWithLabelStatus() { this.images = {} await this.getAllImages(this.perPage, this.page, this.keyword) - await this.getImageCurrentlyBeingLabelled() + if (!this.isOutputViewer) { + await this.getImageCurrentlyBeingLabelled() + } }, getCurrentTime () { var date = new Date() @@ -242,12 +261,21 @@ export default { } .slot-margin { - margin-left: 1.5rem; - margin-top: -0.15rem; + margin-left: 2.25rem; + margin-top: 3.25rem; } .flex-display { display: flex; } + .no-image { + font-family: "Open Sans Bold"; + color: #D6D6D6; + } + + .no-image-height { + height: 2.5rem; + } + </style> \ No newline at end of file diff --git a/frontend/components/root/Navbar.vue b/frontend/components/root/Navbar.vue index ba1d651e4ca2db14a183c3046c43cf66572a03af..5088f290d48bffcf36ac3ac5612babc19930f519 100644 --- a/frontend/components/root/Navbar.vue +++ b/frontend/components/root/Navbar.vue @@ -1,148 +1,160 @@ <template> - <b-nav vertical class="side-bar-layout side-bar-bg side-bar-font side-bar-padding"> - <!-- User profile info --> - <b-nav-item link-classes="side-bar-color mt-5 ml-4"> - <!-- Username --> - <div id="user-name"> - {{ username }} - </div> - <!-- Role --> - <div id="role"> - Role: {{ role.charAt(0).toUpperCase() + role.slice(1) }} - </div> - </b-nav-item> + <b-sidebar class="side-bar-layout side-bar-bg side-bar-font side-bar-padding"> + <b-nav vertical> + <!-- User profile info --> + <b-nav-item link-classes="side-bar-color mt-5 ml-4"> + <!-- Username --> + <div id="user-name"> + {{ username }} + </div> + <!-- Role --> + <div id="role"> + <div v-if="role"> + Role: {{ role.charAt(0).toUpperCase() + role.slice(1) }} + </div> + </div> + </b-nav-item> - <div v-if="role === 'admin'"> - <!-- Upload Dataset --> - <b-nav-item link-classes="side-bar-color mt-5 ml-4" @click="changeActiveElmtID('upload-dataset')"> - <div id="upload-dataset"> - Upload Dataset + <!-- Logout --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="logout()"> + <div style="font-size: 0.77rem;"> + Logout </div> </b-nav-item> - </div> - <!-- Label Dataset --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('label-dataset')"> - <div id="label-dataset"> - Label Dataset + <div v-if="role === 'admin'"> + <!-- Upload Dataset --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('upload-dataset')"> + <div id="upload-dataset"> + Upload Dataset + </div> + </b-nav-item> </div> - </b-nav-item> - <div v-if="role === 'editor' || role === 'admin'"> - <!-- Edit Dataset --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('edit-dataset')"> - <div id="edit-dataset"> - Edit Dataset + <!-- Label Dataset --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('label-dataset')"> + <div id="label-dataset"> + Label Dataset </div> </b-nav-item> - </div> - <!-- COCO Output --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('coco-output')"> - <div id="coco-output"> - COCO Output + <div v-if="role === 'editor' || role === 'admin'"> + <!-- Edit Dataset --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('edit-dataset')"> + <div id="edit-dataset"> + Edit Dataset + </div> + </b-nav-item> </div> - </b-nav-item> - <!-- Pascal Output --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('pascal-output')"> - <div id="pascal-output"> - Pascal VOC Output - </div> - </b-nav-item> + <!-- COCO Output --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('coco-output')"> + <div id="coco-output"> + COCO Output + </div> + </b-nav-item> - <div v-if="role === 'admin'"> - <!-- User Management --> - <b-nav-item - v-b-toggle.collapse-user-management - link-classes="side-bar-color mt-3 ml-4" - > - <div class="icon-text-wrapper"> - User Management - <i class="ml-3 mt-1 fas fa-caret-down" /> + <!-- Pascal Output --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('pascal-output')"> + <div id="pascal-output"> + Pascal VOC Output </div> </b-nav-item> - <b-collapse id="collapse-user-management" visible role="tabpanel"> - <!-- Show All Users --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('show-all-users')"> + <div v-if="role === 'admin'"> + <!-- User Management --> + <b-nav-item + v-b-toggle.collapse-user-management + link-classes="side-bar-color mt-3 ml-4" + > <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-users" /> - <div id="show-all-users"> - Show All Users - </div> + User Management + <i class="ml-3 mt-1 fas fa-caret-down" /> </div> </b-nav-item> - <!-- Add User --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('add-user')"> - <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-plus-circle" /> - <div id="add-user"> - Add User + <b-collapse id="collapse-user-management" visible role="tabpanel"> + <!-- Show All Users --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('show-all-users')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-users" /> + <div id="show-all-users"> + Show All Users + </div> </div> - </div> - </b-nav-item> + </b-nav-item> - <!-- Edit User --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('edit-user')"> - <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-pen" /> - <div id="edit-user"> - Edit User + <!-- Add User --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('add-user')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-plus-circle" /> + <div id="add-user"> + Add User + </div> </div> - </div> - </b-nav-item> + </b-nav-item> - <!-- Delete User --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('delete-user')"> - <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-trash" /> - <div id="delete-user"> - Delete User + <!-- Edit User --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('edit-user')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-pen" /> + <div id="edit-user"> + Edit User + </div> </div> - </div> - </b-nav-item> - </b-collapse> - </div> - - <div> - <b-nav-item - v-b-toggle.collapse-settings - link-classes="side-bar-color mt-3 ml-4" - > - <div class="icon-text-wrapper"> - Settings - <i class="ml-3 mt-1 fas fa-caret-down" /> - </div> - </b-nav-item> + </b-nav-item> - <b-collapse id="collapse-settings" visible role="tabpanel"> - <!-- Change Username --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('change-username')"> - <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-user" /> - <div id="change-username"> - Change Username + <!-- Delete User --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('delete-user')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-trash" /> + <div id="delete-user"> + Delete User + </div> </div> + </b-nav-item> + </b-collapse> + </div> + + <div> + <b-nav-item + v-b-toggle.collapse-settings + link-classes="side-bar-color mt-3 ml-4" + > + <div class="icon-text-wrapper"> + Settings + <i class="ml-3 mt-1 fas fa-caret-down" /> </div> </b-nav-item> - <!-- Change Password --> - <b-nav-item link-classes="side-bar-color mt-3 ml-4 mb-5" @click="changeActiveElmtID('change-password')"> - <div class="icon-text-wrapper"> - <i class="mt-1 mr-3 fas fa-cog" /> - <div id="change-password"> - Change Password + <b-collapse id="collapse-settings" visible role="tabpanel"> + <!-- Change Password --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4" @click="changeActiveElmtID('change-password')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-cog" /> + <div id="change-password"> + Change Password + </div> </div> - </div> - </b-nav-item> - </b-collapse> - </div> - </b-nav> + </b-nav-item> + + <!-- Change Username --> + <b-nav-item link-classes="side-bar-color mt-3 ml-4 mb-5" @click="changeActiveElmtID('change-username')"> + <div class="icon-text-wrapper"> + <i class="mt-1 mr-3 fas fa-user" /> + <div id="change-username"> + Change Username + </div> + </div> + </b-nav-item> + </b-collapse> + </div> + </b-nav> + </b-sidebar> </template> <script> +import cookies from 'js-cookie' export default { props: { username: { @@ -257,6 +269,10 @@ export default { this.changeActiveElmtID(elmtID) this.setClass(elmtID, 'active') } + }, + logout () { + cookies.remove('Authorization') + this.$nuxt.$router.replace({ path: '/'}) } } } @@ -264,16 +280,27 @@ export default { <style scoped> .side-bar-layout { + /* height: 100%; */ height: auto; left: 0; - min-height: 100vh; + /* min-height: 100vh; */ width: 250px; padding-right: 30px; overflow-y: scroll; - position: relative; + position: fixed; + top: 0; + bottom: 0; + } + + .side-bar-layout::-webkit-scrollbar { + display: none; + } + + .side-bar-layout { + -ms-overflow-style: none; } .side-bar-bg { diff --git a/frontend/mixins/outputs/datasetMethods.js b/frontend/mixins/outputs/datasetMethods.js index b48042f42c14dcb8d6d2f26424b39ff828da5bd0..c908336e4273516ccf7861cdb37347e9403a696d 100644 --- a/frontend/mixins/outputs/datasetMethods.js +++ b/frontend/mixins/outputs/datasetMethods.js @@ -2,7 +2,8 @@ export default { data () { return { dataset: '', - updateUI: false + updateUI: false, + empty: false } }, mounted () { @@ -15,6 +16,10 @@ export default { changeDataset (newDataset) { this.dataset = newDataset this.updateUI = !this.updateUI + }, + handleOnEmpty (isEmpty) { + this.empty = isEmpty + console.log("this empty: ", this.empty) } } } \ No newline at end of file diff --git a/frontend/pages/index.vue b/frontend/pages/index.vue index 2996f6390cc917c120f97fd21e16f4891551b599..21020ad795ebe90131011eee59fed54c0cf72533 100644 --- a/frontend/pages/index.vue +++ b/frontend/pages/index.vue @@ -119,6 +119,7 @@ export default { handleSuccessResponse (response) { // Set cookie cookies.remove('Authorization') + console.log('Authorization', response.data.data.cookie) cookies.set('Authorization', response.data.data.cookie) this.$router.push('/main/label') }, diff --git a/frontend/pages/main.vue b/frontend/pages/main.vue index c83baf15f85b00ee477a486da5695a0a2e3f5262..62c021051ee0d3eaa1989381e4edde7e94534288 100644 --- a/frontend/pages/main.vue +++ b/frontend/pages/main.vue @@ -2,7 +2,7 @@ <div class="container-fluid"> <div class="row"> <Navbar :username="user.username" :role="user.role" /> - <nuxt-child /> + <nuxt-child style="margin-left: 250px;" /> </div> </div> </template> diff --git a/frontend/pages/main/add-user.vue b/frontend/pages/main/add-user.vue index 3bdde7a842be3ff125574c61cd8b98b300bfa21c..f5288b764ba9d5e9029b057abf9906018763a371 100644 --- a/frontend/pages/main/add-user.vue +++ b/frontend/pages/main/add-user.vue @@ -1,5 +1,5 @@ <template> - <div class="col center center-inside-add-user"> + <div class="col"> <div class="ml-4"> <div class="row"> <div class="col"> diff --git a/frontend/pages/main/change-password.vue b/frontend/pages/main/change-password.vue index bd3c70560ca5e46d7c39c23e583fb500b192ec69..d9ba91279b0106bfe3cee198a579efd87ca9265a 100644 --- a/frontend/pages/main/change-password.vue +++ b/frontend/pages/main/change-password.vue @@ -11,7 +11,7 @@ <div class="row mt-4"> <div class="col"> <p class="form-title"> - Password + Current Password </p> </div> </div> @@ -47,13 +47,13 @@ v-model="new_password" type="password" class="form-control form-border field-length form-content" - placeholder="Type new username..." + placeholder="Type new password..." name="new_username" > </div> </div> - <div class="row mt-4"> + <div class="row mt-2"> <div class="col"> <p class="form-title"> Confirm New Password @@ -150,7 +150,7 @@ export default { this.isConfirmPasswordTrue() // Send to backend if ((passcode == oldlValue) && (confirmNewValue == newValue)) { - var text = "You wull change password" + var text = "You will change password" this.showConfirmation("Are You Sure?", text).then((result) => { if (result.value) { this.approveConfirmation(newValue, id) diff --git a/frontend/pages/main/coco.vue b/frontend/pages/main/coco.vue index 2dbab7e08d56611fd0dddfd1d493462043d65b22..430541eca7c4c91620071ff21ab8617eab05daa2 100644 --- a/frontend/pages/main/coco.vue +++ b/frontend/pages/main/coco.vue @@ -10,7 +10,7 @@ /> </div> </div> - <div :key="updateUI" class="row animated fadeIn"> + <div :key="updateUI" class="row animated fadeIn" style="margin-top: -1rem;"> <div class="col"> <div style="display: flex"> <h5 class="title users-margin"> @@ -18,8 +18,11 @@ <span v-if="!dataset" style="margin-left: 20px; font-size: 0.85rem;"> Choose Folder First </span> + <span v-else-if="empty" style="margin-left: 20px; font-size: 0.85rem;"> + No Images Found + </span> </h5> - <button v-if="dataset" class="btn-white margin-download" @click="downloadJSON()"> + <button v-if="dataset && !empty" class="btn-white margin-download" @click="downloadJSON()"> {{ dataset }}.json <i class="ml-3 mt-1 fas fa-download" /> </button> @@ -36,6 +39,7 @@ title="JSON Per Image" viewer-u-r-l="/main/output-view" :output="{type: 'json', standard: standard}" + @onEmpty="handleOnEmpty" /> </div> </div> @@ -95,7 +99,6 @@ export default { var element = document.createElement('a') // var label = await this.getAllLabel(this.standard) var COCOJSON = await this.getCOCOJSON() - console.log("COCO: ", COCOJSON) var text = JSON.stringify(COCOJSON, 0, 5) element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)) element.setAttribute('download',filename) @@ -175,7 +178,7 @@ export default { .margin-dropdown { margin-top: 3.5rem; - margin-left: -0.775rem; + margin-left: -0.1rem; } </style> \ No newline at end of file diff --git a/frontend/pages/main/edit.vue b/frontend/pages/main/edit.vue index fb6d9a6d4d9571570b3a8366d10f176dcc3f8799..1f44a2ee52c949a0618be2851b7efc7dfb7d5b0b 100644 --- a/frontend/pages/main/edit.vue +++ b/frontend/pages/main/edit.vue @@ -1,7 +1,7 @@ <template> <Label :key="dataset" - title="Label Labeled Images" + title="Edit Labeled Images" viewer-u-r-l="/viewer/index-edit" :is-labeled="isLabeled" :dataset="dataset" diff --git a/frontend/pages/main/pascal.vue b/frontend/pages/main/pascal.vue index a567d84687fbf77af11aaaebb74416c84cd04ed5..7468a821bcff2f33b7d34524ca31dc0132c98738 100644 --- a/frontend/pages/main/pascal.vue +++ b/frontend/pages/main/pascal.vue @@ -10,7 +10,7 @@ /> </div> </div> - <div :key="updateUI" class="row animated fadeIn"> + <div :key="updateUI" class="row animated fadeIn" style="margin-top: -1rem;"> <div class="col"> <div style="display: flex"> <h5 class="title users-margin"> @@ -18,8 +18,11 @@ <span v-if="!dataset" style="margin-left: 20px; font-size: 0.85rem;"> Choose Folder First </span> + <span v-else-if="empty" style="margin-left: 20px; font-size: 0.85rem;"> + No Images Found + </span> </h5> - <button v-if="dataset" class="btn-white margin-download" @click="downloadXML()"> + <button v-if="dataset && !empty" class="btn-white margin-download" @click="downloadXML()"> {{ dataset }}.xml <i class="ml-3 mt-1 fas fa-download" /> </button> @@ -36,6 +39,7 @@ title="XML Per Image" viewer-u-r-l="/main/output-view" :output="{type: 'xml', standard: standard}" + @onEmpty="handleOnEmpty" /> </div> </div> @@ -177,7 +181,7 @@ export default { .margin-dropdown { margin-top: 3.5rem; - margin-left: -0.775rem; + margin-left: -0.1rem; } </style> \ No newline at end of file diff --git a/frontend/pages/main/upload.vue b/frontend/pages/main/upload.vue index ea03051cbccc87bbc9e284d3367188f7fe036ab4..531f1e198ea1c2014d326458b5cf848b973d7fdf 100644 --- a/frontend/pages/main/upload.vue +++ b/frontend/pages/main/upload.vue @@ -208,7 +208,7 @@ export default { }, async handleUpload(){ this.files = this.$refs.myDropzone.getAcceptedFiles() - if (!this.dataset) { + if (!this.dataset || this.dataset === "Choose Folder") { this.invalidFolder() } else { if(this.files.length === 0){