side-navigation-bar.vue 4.3 KB

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