media-control.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <div class="media-control">
  3. <button-input ref="previousPage"
  4. type="transparent"
  5. title="previous page (Y)"
  6. style="color: var(--on_error)"
  7. :class="{disabled: !hasPreviousPage}"
  8. @click="$emit('previousPage', true)">
  9. <img alt="next" :class="{disabled: !hasPreviousPage}" src="@/assets/icons/chevron-left.svg">
  10. <img alt="next" :class="{disabled: !hasPreviousPage}" src="@/assets/icons/chevron-left.svg">
  11. </button-input>
  12. <button-input ref="previousElement"
  13. type="transparent"
  14. title="previous element (A)"
  15. style="color: var(--on_error)"
  16. :class="{disabled: !hasPreviousElement}"
  17. @click="$emit('previousElement', true)">
  18. <img alt="next" :class="{disabled: !hasPreviousElement}" src="@/assets/icons/chevron-left.svg">
  19. </button-input>
  20. <select v-if="collections.length > 0"
  21. @change="filter">
  22. <option>no filter</option>
  23. <option>without collection</option>
  24. <option v-for="collection in collections" :key="collection.identifier"
  25. :value="collection.identifier"
  26. :selected="collection.autoselect">
  27. {{ collection.name }}
  28. </option>
  29. </select>
  30. <select v-else @change="only_annotations">
  31. <option>all images</option>
  32. <option>images with annotations</option>
  33. <option>images without annotations</option>
  34. </select>
  35. <button-input ref="nextElement"
  36. type="transparent"
  37. title="next element (D)"
  38. style="color: var(--on_error)"
  39. :class="{disabled: !hasNextElement}"
  40. @click="$emit('nextElement', true)">
  41. <img alt="next" :class="{disabled: !hasNextElement}" src="@/assets/icons/chevron-right.svg">
  42. </button-input>
  43. <button-input ref="nextPage"
  44. type="transparent"
  45. title="next page (C)"
  46. style="color: var(--on_error)"
  47. :class="{disabled: !hasNextPage}"
  48. @click="$emit('nextPage', true)">
  49. <img alt="next" :class="{disabled: !hasNextPage}" src="@/assets/icons/chevron-right.svg">
  50. <img alt="next" :class="{disabled: !hasNextPage}" src="@/assets/icons/chevron-right.svg">
  51. </button-input>
  52. </div>
  53. </template>
  54. <script>
  55. import ButtonInput from "@/components/base/button-input";
  56. export default {
  57. name: "media-control",
  58. components: {ButtonInput},
  59. props: ['current', 'hasPreviousPage', 'hasNextPage', 'hasPreviousElement', 'hasNextElement'],
  60. created: function () {
  61. window.addEventListener('keypress', this.keypressEvent);
  62. // receive collections
  63. this.$root.socket.get(`/projects/${this.$root.project.identifier}/collections`)
  64. .then(response => response.json())
  65. .then(collections => {
  66. this.collections = collections;
  67. for (let collection of collections)
  68. if (collection.autoselect)
  69. this.$emit('filter', collection.identifier);
  70. });
  71. },
  72. destroyed: function () {
  73. window.removeEventListener('keypress', this.keypressEvent);
  74. },
  75. data: function () {
  76. return {
  77. collections: []
  78. }
  79. },
  80. methods: {
  81. keypressEvent: function (event) {
  82. switch (event.key) {
  83. case 'y':
  84. this.$refs.previousPage.click();
  85. break;
  86. case 'a':
  87. this.$refs.previousElement.click();
  88. break;
  89. case 'd':
  90. this.$refs.nextElement.click();
  91. break;
  92. case 'c':
  93. this.$refs.nextPage.click();
  94. break;
  95. }
  96. },
  97. filter: function (e) {
  98. const select = e.target;
  99. switch (select.selectedIndex) {
  100. // no filter
  101. case 0:
  102. this.$emit('filter', false);
  103. break;
  104. // without collection
  105. case 1:
  106. this.$emit('filter', null);
  107. break;
  108. // other
  109. default:
  110. this.$emit('filter', select.options[select.selectedIndex].value);
  111. break;
  112. }
  113. },
  114. only_annotations: function(e) {
  115. const select = e.target;
  116. switch (select.selectedIndex) {
  117. // no filter
  118. case 0:
  119. this.$emit('only_annotations', null);
  120. break;
  121. // only with annotations
  122. case 1:
  123. this.$emit('only_annotations', true);
  124. break;
  125. // only without annotations
  126. default:
  127. this.$emit('only_annotations', false);
  128. break;
  129. }
  130. }
  131. }
  132. }
  133. </script>
  134. <style scoped>
  135. .media-control {
  136. background-color: rgba(0, 0, 0, 0.75);
  137. color: whitesmoke;
  138. display: flex;
  139. flex-direction: row;
  140. justify-content: center;
  141. align-items: center;
  142. }
  143. .button-input {
  144. font-size: 110%;
  145. font-weight: bold;
  146. }
  147. .disabled {
  148. opacity: 0.4;
  149. }
  150. img {
  151. filter: invert(1);
  152. }
  153. img.disabled {
  154. filter: invert(1);
  155. background-color: transparent;
  156. }
  157. select {
  158. flex-grow: 1;
  159. max-width: 15rem;
  160. margin: 0 1rem;
  161. }
  162. </style>