side-navigation-bar.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <div class="side-navigation"
  3. :class="{
  4. wide: window.wide,
  5. narrow: !window.wide,
  6. active: window.menu ,
  7. collapsed: collapsed
  8. }">
  9. <div class="items">
  10. <div class="item"
  11. :class="{active: window.content === 'projects'}"
  12. @click="show('projects')">
  13. <img src="@/assets/icons/rocket.svg">
  14. <span>Projects</span>
  15. </div>
  16. <div class="item"
  17. :class="{active: window.content === 'settings', inactive: !currentProject}"
  18. @click="ifProjectIsOpened(show, 'settings')">
  19. <img src="@/assets/icons/gear.svg">
  20. <span>Settings</span>
  21. </div>
  22. <div class="item"
  23. :class="{active: window.content === 'add_data', inactive: !currentProject}"
  24. @click="ifProjectIsOpened(show, 'add_data')">
  25. <img src="@/assets/icons/package-dependencies.svg">
  26. <span>Data</span>
  27. </div>
  28. <div class="item"
  29. :class="{active: window.content === 'labels', inactive: !currentProject || !labelsEnabled}"
  30. @click="ifProjectIsOpened(show, 'labels')">
  31. <img src="@/assets/icons/tag.svg">
  32. <span>Labels</span>
  33. </div>
  34. <div class="item"
  35. :class="{active: window.content === 'view_data', inactive: !currentProject || !mediaAvailable}"
  36. @click="ifProjectIsOpened(show, 'view_data')">
  37. <img src="@/assets/icons/file-media.svg">
  38. <span>Session</span>
  39. </div>
  40. <div class="item"
  41. :class="{active: window.content === 'model_interaction', inactive: !currentProject || !mediaAvailable}"
  42. @click="ifProjectIsOpened(show, 'model_interaction')">
  43. <img src="@/assets/icons/cpu.svg">
  44. <span>Model</span>
  45. </div>
  46. <div class="item"
  47. :class="{active: window.content === 'about'}"
  48. @click="show('about')">
  49. <img src="@/assets/icons/info.svg">
  50. <span>About</span>
  51. </div>
  52. <div v-if="window.wide"
  53. class="item"
  54. :class="{rotate: !collapsed}"
  55. @click="collapse">
  56. <img src="@/assets/icons/paper-airplane.svg">
  57. <span>Collapse</span>
  58. </div>
  59. </div>
  60. <!-- clickable overlay -->
  61. <div class="overlay"
  62. v-if="!window.wide"
  63. @click="closeSelf"/>
  64. </div>
  65. </template>
  66. <script>
  67. export default {
  68. name: "side-navigation-bar",
  69. props: ['window', 'socket', 'status', 'currentProject'],
  70. computed: {
  71. collapsed: function () {
  72. if (!this.status)
  73. return false;
  74. return this.status.settings.frontend.collapse;
  75. },
  76. mediaAvailable: function () {
  77. return this.currentProject && 'data' in this.currentProject && Object.keys(this.currentProject.data).length > 0;
  78. },
  79. labelsEnabled: function () {
  80. return this.currentProject
  81. && (
  82. this.currentProject.model.supports.includes('labeled-images')
  83. || this.currentProject.model.supports.includes('labeled-bounding-boxes')
  84. );
  85. }
  86. },
  87. methods: {
  88. closeSelf: function () {
  89. this.$emit('close', null);
  90. },
  91. ifProjectIsOpened: function (fun, ...args) {
  92. if (this.currentProject)
  93. fun.bind(fun)(...args);
  94. },
  95. show: function (value) {
  96. this.window.content = value;
  97. this.closeSelf();
  98. },
  99. collapse: function () {
  100. this.socket.post('/settings', {
  101. frontend: {
  102. collapse: !this.collapsed
  103. }
  104. });
  105. // TODO then / error
  106. }
  107. }
  108. }
  109. </script>
  110. <style scoped>
  111. .side-navigation {
  112. color: whitesmoke;
  113. }
  114. .side-navigation.wide {
  115. flex-grow: 0;
  116. height: 100%;
  117. }
  118. .side-navigation.narrow {
  119. width: 100vw;
  120. left: -100vw;
  121. position: absolute;
  122. top: 0;
  123. bottom: 0;
  124. transition: 0.2s ease-out;
  125. display: flex;
  126. z-index: 1000;
  127. }
  128. .side-navigation.narrow.active {
  129. left: 0;
  130. }
  131. .items {
  132. flex-grow: 0;
  133. height: 100%;
  134. background-color: #2f2f2f;
  135. min-width: 66%;
  136. }
  137. .item {
  138. cursor: pointer;
  139. white-space: nowrap;
  140. display: flex;
  141. align-items: center;
  142. }
  143. .item:hover:not(.inactive) {
  144. background-color: #292929;
  145. }
  146. .item.active:not(.inactive) {
  147. background-color: #1f1f1f;
  148. }
  149. .item.inactive {
  150. color: #7f7f7f;
  151. }
  152. .item:not(:last-child) {
  153. border-bottom: 1px solid rgba(255, 255, 255, 0.25);
  154. }
  155. .item img {
  156. width: 1.2rem;
  157. margin-left: 1rem;
  158. filter: invert(1);
  159. }
  160. .item.rotate img {
  161. transform: rotate(180deg);
  162. }
  163. .item.inactive img {
  164. opacity: 0.5;
  165. }
  166. .item span {
  167. margin: 1rem 4rem 1rem 0.75rem
  168. }
  169. .side-navigation.wide.collapsed .item {
  170. padding: 1rem 1rem 1rem 0;
  171. }
  172. .side-navigation.wide.collapsed .item span {
  173. display: none;
  174. }
  175. .overlay {
  176. flex-grow: 1;
  177. }
  178. </style>