WithReference.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <div>
  3. <v-container grid-list-md text-xs-center fluid>
  4. <v-layout row wrap>
  5. <v-flex xs12>
  6. <h1>Experiment with reference</h1>
  7. <v-card dark>
  8. <v-container grid-list-sm fluid>
  9. <v-layout row wrap>
  10. <v-flex
  11. xs12
  12. >
  13. <h1>Configuration</h1>
  14. <v-card-text class="px-0">Extracts per line (horizontal)</v-card-text>
  15. <v-slider
  16. v-model="experimentConfig.x"
  17. always-dirty
  18. persistent-hint
  19. thumb-label="always"
  20. min="1"
  21. max="25"
  22. />
  23. <v-card-text class="px-0">Extracts per row (vertical)</v-card-text>
  24. <v-slider
  25. v-model="experimentConfig.y"
  26. always-dirty
  27. persistent-hint
  28. thumb-label="always"
  29. min="1"
  30. max="25"
  31. />
  32. <v-btn @click="setConfig" :disabled="!isConfigNew">Confirm</v-btn>
  33. <v-alert v-if="loadingErrorMessage" :value="true" type="error" v-text="loadingErrorMessage" />
  34. </v-flex>
  35. </v-layout>
  36. </v-container>
  37. </v-card>
  38. </v-flex>
  39. <!-- Loading screen -->
  40. <loader v-if="loadingMessage" :message="loadingMessage" />
  41. <!--/ Loading screen -->
  42. <!-- Experiment -->
  43. <template v-else-if="!loadingErrorMessage">
  44. <v-flex xs12 sm6>
  45. <v-card dark color="primary">
  46. <v-card-text class="px-0">Experiment image</v-card-text>
  47. <v-container class="pa-1">
  48. <template v-for="i in extractConfig.x">
  49. <v-layout row wrap :key="`row-${i}`">
  50. <v-flex
  51. v-for="(anExtract, index) in extracts.slice(extractConfig.x * (i - 1), (extractConfig.x * i))"
  52. :key="`extract-${i}-${extractConfig.x}-${extractConfig.y}-${index}-${anExtract.quality}`"
  53. class="pa-0"
  54. >
  55. <v-card flat tile class="d-flex height100">
  56. <div
  57. v-if="anExtract.loading"
  58. class="img-loader"
  59. @click.right.prevent
  60. >
  61. <v-progress-circular
  62. :indeterminate="true"
  63. />
  64. </div>
  65. <v-img
  66. v-else
  67. :src="anExtract.link"
  68. @click.left.prevent="extractAction($event, anExtract)"
  69. @click.right.prevent="extractAction($event, anExtract)"
  70. class="cursor extract"
  71. >
  72. <template v-slot:placeholder>
  73. <v-layout
  74. fill-height
  75. align-center
  76. justify-center
  77. ma-0
  78. >
  79. <v-progress-circular indeterminate color="grey lighten-5" />
  80. </v-layout>
  81. </template>
  82. </v-img>
  83. </v-card>
  84. </v-flex>
  85. </v-layout>
  86. </template>
  87. </v-container>
  88. </v-card>
  89. </v-flex>
  90. <v-flex sm6 xs12>
  91. <v-card dark color="primary">
  92. <v-card-text>Reference image</v-card-text>
  93. <v-img v-if="referenceImage" :src="referenceImage" />
  94. </v-card>
  95. </v-flex>
  96. </template>
  97. <!--/ Experiment -->
  98. </v-layout>
  99. </v-container>
  100. </div>
  101. </template>
  102. <script>
  103. import { mapGetters, mapActions } from 'vuex'
  104. import { API_ROUTES, findNearestUpper, findNearestLower } from '@/functions'
  105. import Loader from '@/components/Loader.vue'
  106. export default {
  107. name: 'ExperimentWithReference',
  108. components: {
  109. Loader
  110. },
  111. props: {
  112. sceneId: {
  113. type: String,
  114. required: true
  115. }
  116. },
  117. data() {
  118. return {
  119. referenceImage: null,
  120. qualities: null,
  121. experimentConfig: { // Experiment config sliders
  122. x: 8,
  123. y: 4,
  124. error: null
  125. },
  126. extractConfig: { // Updated when `setConfig` is called
  127. x: 8,
  128. y: 4
  129. },
  130. loadingMessage: null,
  131. loadingErrorMessage: null,
  132. extracts: []
  133. }
  134. },
  135. computed: {
  136. ...mapGetters(['getHostURI']),
  137. isConfigNew() {
  138. return this.extractConfig.x !== this.experimentConfig.x || this.extractConfig.y !== this.experimentConfig.y
  139. }
  140. },
  141. async mounted() {
  142. await this.getReferenceImage()
  143. await this.getQualitiesList()
  144. // Get default extracts : min quality, cut config : x = 4, y = 4
  145. await this.setConfig()
  146. },
  147. methods: {
  148. ...mapActions([]),
  149. async getReferenceImage() {
  150. const URI = `${this.getHostURI}${API_ROUTES.getImage(this.sceneId, 'max')}`
  151. const { data } = await fetch(URI).then(res => res.json())
  152. this.referenceImage = this.getHostURI + data.link
  153. },
  154. async getQualitiesList() {
  155. const URI = `${this.getHostURI}${API_ROUTES.listSceneQualities(this.sceneId)}`
  156. const { data } = await fetch(URI).then(res => res.json())
  157. this.qualities = data
  158. },
  159. async getExtracts(quality = 'max') {
  160. const URI = `${this.getHostURI}${API_ROUTES.getImageExtracts(this.sceneId, quality, this.extractConfig.x, this.extractConfig.y)}`
  161. const { data } = await fetch(URI)
  162. .then(async res => {
  163. res.json = await res.json()
  164. return res
  165. })
  166. .then(res => {
  167. if (!res.ok) throw new Error(res.json.message + res.json.data ? `\n${res.json.data}` : '')
  168. return res.json
  169. })
  170. return data
  171. },
  172. async setConfig() {
  173. // Check if the config is the same
  174. if (this.extracts.length > 0 && !this.isConfigNew) return
  175. this.loadingMessage = 'Loading configuration extracts...'
  176. this.loadingErrorMessage = null
  177. try {
  178. this.extractConfig.x = this.experimentConfig.x
  179. this.extractConfig.y = this.experimentConfig.y
  180. const data = await this.getExtracts()
  181. const hostURI = this.getHostURI
  182. this.extracts = data.extracts.map((url, i) => ({
  183. link: hostURI + url,
  184. quality: data.info.image.quality,
  185. zone: i + 1,
  186. index: i,
  187. nextQuality: findNearestUpper(data.info.image.quality, this.qualities),
  188. precQuality: findNearestLower(data.info.image.quality, this.qualities),
  189. loading: false
  190. }))
  191. }
  192. catch (err) {
  193. console.error('Failed to load new configuration', err)
  194. this.loadingErrorMessage = 'Failed to load new configuration. ' + err.message
  195. }
  196. this.loadingMessage = null
  197. },
  198. async extractAction(event, extractObj) {
  199. console.log(event, extractObj)
  200. const { index, nextQuality, precQuality, quality } = extractObj
  201. let newQuality
  202. if (event.button === 0) newQuality = precQuality // Left click
  203. if (event.button === 2) newQuality = nextQuality // Right click
  204. // Do not load a new extract if same quality
  205. if (newQuality === quality) return
  206. // Set loading state
  207. this.extracts[index].loading = true
  208. try {
  209. // Loading new extract
  210. const data = await this.getExtracts(newQuality)
  211. this.extracts[index].link = this.getHostURI + data.extracts[index]
  212. this.extracts[index].quality = data.info.image.quality
  213. this.extracts[index].nextQuality = findNearestUpper(data.info.image.quality, this.qualities)
  214. this.extracts[index].precQuality = findNearestLower(data.info.image.quality, this.qualities)
  215. this.extracts[index].loading = false
  216. }
  217. catch (err) {
  218. // TODO: toast message if fail
  219. console.error('Failed to load extract', err)
  220. }
  221. finally {
  222. this.extracts[index].loading = false
  223. }
  224. }
  225. }
  226. }
  227. </script>
  228. <style scoped>
  229. .height100 {
  230. height: 100%;
  231. }
  232. .img-loader {
  233. height: 100%;
  234. width: 0px;
  235. display: flex;
  236. justify-content: center;
  237. align-items: center;
  238. }
  239. .cursor {
  240. cursor: pointer;
  241. }
  242. .extract:hover {
  243. z-index: 999999;
  244. outline: 2px #f4f4f4 solid;
  245. }
  246. </style>