@twab/visualization 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/visualization.js +167 -84
  2. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import VTooltip from 'v-tooltip';
2
2
  import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
3
3
  import { library } from '@fortawesome/fontawesome-svg-core';
4
- import { faBackward, faStepBackward, faClock, faStepForward, faForward, faPlay, faStop, faBorderAll, faSlidersH, faCut, faHourglassStart, faHourglassEnd, faVideo, faInfoCircle, faTachometerAlt, faServer, faEye, faEyeSlash, faBan, faSync, faArrowTurnDown, faArrowCircleDown, faPause, faArrowsLeftRightToLine, faExclamationTriangle, faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
4
+ import { faBackward, faStepBackward, faClock, faStepForward, faForward, faPlay, faStop, faBorderAll, faSlidersH, faCut, faHourglassStart, faHourglassEnd, faVideo, faInfoCircle, faTachometerAlt, faServer, faEye, faEyeSlash, faBan, faSync, faArrowTurnDown, faArrowCircleDown, faPause, faArrowsLeftRightToLine, faExclamationTriangle, faExclamationCircle, faMaximize, faMinimize } from '@fortawesome/free-solid-svg-icons';
5
5
  import VueMask from 'v-mask';
6
6
  import VueLoading from 'vue-loading-twa';
7
7
  import axios from 'axios';
@@ -110,7 +110,9 @@ function registerIcons () {
110
110
  faPause,
111
111
  faArrowsLeftRightToLine,
112
112
  faExclamationTriangle,
113
- faExclamationCircle
113
+ faExclamationCircle,
114
+ faMaximize,
115
+ faMinimize
114
116
  );
115
117
  }
116
118
 
@@ -229,6 +231,10 @@ var script$5 = {
229
231
  type: Number,
230
232
  default: 11 / 9,
231
233
  },
234
+ stretchFrame: {
235
+ type: Boolean,
236
+ default: false,
237
+ },
232
238
  },
233
239
  data() {
234
240
  return {
@@ -360,10 +366,24 @@ var script$5 = {
360
366
  this.width = this.maxWidth;
361
367
  this.height = this.maxWidth / this.aspectRatio;
362
368
  }
363
-
369
+ this.applyImageStyles();
364
370
  this.maxHeight = this.height;
365
371
  },
372
+ applyImageStyles() {
373
+ this.$nextTick(() => {
374
+ const frameImages = this.$el.querySelectorAll(
375
+ '.frame-container img, .dummy-frame img'
376
+ );
366
377
 
378
+ frameImages.forEach((img) => {
379
+ img.style.width = '100%';
380
+ img.style.height = '100%';
381
+ img.style.objectFit = 'fill';
382
+ img.style.aspectRatio = 'auto';
383
+ img.style.display = 'block';
384
+ });
385
+ });
386
+ },
367
387
  async playOrPause() {
368
388
  switch (this.videoStatus) {
369
389
  case Status.stopped:
@@ -707,65 +727,83 @@ var __vue_render__$5 = function () {
707
727
  },
708
728
  }),
709
729
  _vm._v(" "),
710
- _c("div", { staticStyle: { "background-color": "black" } }, [
711
- !_vm.isLoading
712
- ? _c(
713
- "div",
714
- {
715
- class: {
716
- "frame-content":
717
- _vm.frame.title === -1 ||
718
- _vm.videoStatus !== _vm.Status.stopped,
719
- },
720
- style: {
721
- minHeight: _vm.height + "px",
722
- minWidth: _vm.width + "px",
723
- maxHeight: _vm.height + "px",
724
- maxWidth: _vm.width + "px",
725
- color: "white",
726
- },
727
- on: { dblclick: _vm.playOrPause },
728
- },
729
- [
730
- _vm.frame.image && _vm.videoStatus === _vm.Status.stopped
731
- ? _c("div", {
732
- class: { "dummy-frame": _vm.frame.title === -1 },
733
- staticStyle: { width: "100%", height: "100%" },
734
- domProps: { innerHTML: _vm._s(_vm.frame.image) },
735
- })
736
- : _vm._e(),
737
- _vm._v(" "),
738
- !_vm.videoOnModal &&
739
- _vm.videoStatus !== _vm.Status.stopped &&
740
- !_vm.videoIsLoading
741
- ? _c("video", {
742
- ref: "videoPlayer",
743
- style: {
730
+ _c(
731
+ "div",
732
+ {
733
+ style: {
734
+ backgroundColor: "black",
735
+ width: _vm.stretchFrame ? "100%" : "auto",
736
+ height: _vm.stretchFrame ? "100%" : "auto",
737
+ },
738
+ },
739
+ [
740
+ !_vm.isLoading
741
+ ? _c(
742
+ "div",
743
+ {
744
+ class: {
745
+ "frame-content":
746
+ _vm.frame.title === -1 ||
747
+ _vm.videoStatus !== _vm.Status.stopped,
748
+ },
749
+ style: _vm.stretchFrame
750
+ ? {
751
+ height: _vm.maxHeight + "px",
744
752
  width: "100%",
745
- aspectRatio: _vm.aspectRatioFrac,
746
- },
747
- attrs: {
753
+ color: "white",
754
+ }
755
+ : {
756
+ minHeight: _vm.height + "px",
757
+ minWidth: _vm.width + "px",
748
758
  maxHeight: _vm.height + "px",
749
759
  maxWidth: _vm.width + "px",
750
- src: _vm.videoUrlString,
760
+ color: "white",
751
761
  },
752
- on: {
753
- timeupdate: _vm.updateTimeLabel,
754
- ended: _vm.videoEnded,
755
- click: _vm.playOrPause,
756
- canplay: _vm.canPlay,
757
- error: function () {
758
- return _vm.stop(false)
762
+ on: { dblclick: _vm.playOrPause },
763
+ },
764
+ [
765
+ _vm.frame.image && _vm.videoStatus === _vm.Status.stopped
766
+ ? _c("div", {
767
+ class: { "dummy-frame": _vm.frame.title === -1 },
768
+ staticStyle: { width: "100%", height: "100%" },
769
+ domProps: { innerHTML: _vm._s(_vm.frame.image) },
770
+ })
771
+ : _vm._e(),
772
+ _vm._v(" "),
773
+ !_vm.videoOnModal &&
774
+ _vm.videoStatus !== _vm.Status.stopped &&
775
+ !_vm.videoIsLoading
776
+ ? _c("video", {
777
+ ref: "videoPlayer",
778
+ style: {
779
+ width: "100%",
780
+ aspectRatio: _vm.aspectRatioFrac,
759
781
  },
760
- },
761
- })
762
- : _vm._e(),
763
- _vm._v(" "),
764
- !_vm.loading ? _c("div", { staticClass: "overlay" }) : _vm._e(),
765
- ]
766
- )
767
- : _vm._e(),
768
- ]),
782
+ attrs: {
783
+ maxHeight: _vm.height + "px",
784
+ maxWidth: _vm.width + "px",
785
+ src: _vm.videoUrlString,
786
+ },
787
+ on: {
788
+ timeupdate: _vm.updateTimeLabel,
789
+ ended: _vm.videoEnded,
790
+ click: _vm.playOrPause,
791
+ canplay: _vm.canPlay,
792
+ error: function () {
793
+ return _vm.stop(false)
794
+ },
795
+ },
796
+ })
797
+ : _vm._e(),
798
+ _vm._v(" "),
799
+ !_vm.loading
800
+ ? _c("div", { staticClass: "overlay" })
801
+ : _vm._e(),
802
+ ]
803
+ )
804
+ : _vm._e(),
805
+ ]
806
+ ),
769
807
  _vm._v(" "),
770
808
  _c(
771
809
  "dialog",
@@ -820,11 +858,11 @@ __vue_render__$5._withStripped = true;
820
858
  /* style */
821
859
  const __vue_inject_styles__$5 = function (inject) {
822
860
  if (!inject) return
823
- inject("data-v-e76055ba_0", { source: "\n.frame-container > div[data-v-e76055ba] {\r\n max-height: 100%;\n}\n.frame-container[data-v-e76055ba] {\r\n background-color: black;\r\n display: flex;\r\n justify-content: center;\n}\n.frame-content[data-v-e76055ba],\r\n.dummy-frame[data-v-e76055ba] {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\n}\n.frame-content video[data-v-e76055ba] {\r\n flex-grow: 1;\r\n object-fit: fill;\r\n z-index: 0;\n}\n.overlay[data-v-e76055ba] {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\n}\n.active .overlay[data-v-e76055ba] {\r\n border-color: var(--visualization-primary);\n}\n.between-time .overlay[data-v-e76055ba] {\r\n border-top-color: var(--visualization-secondary);\n}\n.between-time.active .overlay[data-v-e76055ba] {\r\n border-color: var(--visualization-secondary);\n}\n.initial-time .overlay[data-v-e76055ba] {\r\n border-top-color: var(--visualization-start);\n}\n.initial-time.active .overlay[data-v-e76055ba] {\r\n border-color: var(--visualization-start);\n}\n.end-time .overlay[data-v-e76055ba] {\r\n border-top-color: var(--visualization-end);\n}\n.end-time.active .overlay[data-v-e76055ba] {\r\n border-color: var(--visualization-end);\n}\n.initial-time.end-time .overlay[data-v-e76055ba] {\r\n border-top-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\n}\n.initial-time.end-time.active .overlay[data-v-e76055ba] {\r\n border-top-color: var(--visualization-start);\r\n border-left-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n border-right-color: var(--visualization-end);\n}\n.div-frame[data-v-e76055ba] img {\r\n width: 90vh !important;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\components\\Frame.vue"],"names":[],"mappings":";AAyaA;EACA,gBAAA;AACA;AACA;EACA,uBAAA;EACA,aAAA;EACA,uBAAA;AACA;AACA;;EAEA,aAAA;EACA,mBAAA;EACA,uBAAA;AACA;AACA;EACA,YAAA;EACA,gBAAA;EACA,UAAA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,6BAAA;EACA,oBAAA;AACA;AACA;EACA,0CAAA;AACA;AACA;EACA,gDAAA;AACA;AACA;EACA,4CAAA;AACA;AACA;EACA,4CAAA;AACA;AACA;EACA,wCAAA;AACA;AACA;EACA,0CAAA;AACA;AACA;EACA,sCAAA;AACA;AACA;EACA,4CAAA;EACA,6CAAA;AACA;AACA;EACA,4CAAA;EACA,6CAAA;EACA,6CAAA;EACA,4CAAA;AACA;AACA;EACA,sBAAA;AACA","file":"Frame.vue","sourcesContent":["<template>\r\n <div\r\n :style=\"{\r\n maxHeight: `${maxHeight}px`,\r\n width: '100%',\r\n position: 'relative',\r\n }\"\r\n :class=\"{\r\n 'frame-container': true,\r\n 'initial-time': initialTime,\r\n 'end-time': endTime,\r\n 'between-time': betweenTime,\r\n active: active,\r\n }\">\r\n <GlobalEvents\r\n v-if=\"active && activeTab && parentComponent.settingsClosed\"\r\n @keydown.32.prevent=\"playOrPause\"\r\n @keydown.27.prevent=\"stop\"\r\n @keydown.79=\"toogleDetailFrame\"\r\n @keydown.13.prevent=\"jumpFrameToStart\" />\r\n <GlobalEvents\r\n v-if=\"showFrame\"\r\n @keydown.27.prevent=\"toogleDetailFrame\"\r\n @keydown.13.prevent=\"toogleDetailFrame\" />\r\n\r\n <vue-loading\r\n :active=\"isLoading\"\r\n spinner=\"ring\"\r\n color=\"var(--visualization-primary)\"\r\n background-color=\"#cacaca\"\r\n :style=\"{\r\n 'z-index': 0,\r\n minHeight: `${height}px`,\r\n minWidth: `${width}px`,\r\n }\"\r\n :text=\"videoIsLoading ? $t('infoBar.createVideo') : ''\" />\r\n <div style=\"background-color: black\">\r\n <div\r\n v-if=\"!isLoading\"\r\n :class=\"{\r\n 'frame-content': frame.title === -1 || videoStatus !== Status.stopped,\r\n }\"\r\n :style=\"{\r\n minHeight: `${height}px`,\r\n minWidth: `${width}px`,\r\n maxHeight: `${height}px`,\r\n maxWidth: `${width}px`,\r\n color: 'white',\r\n }\"\r\n @dblclick=\"playOrPause\">\r\n <div\r\n v-if=\"frame.image && videoStatus === Status.stopped\"\r\n :class=\"{ 'dummy-frame': frame.title === -1 }\"\r\n v-html=\"frame.image\"\r\n style=\"width: 100%; height: 100%\" />\r\n\r\n <video\r\n v-if=\"\r\n !videoOnModal && videoStatus !== Status.stopped && !videoIsLoading\r\n \"\r\n ref=\"videoPlayer\"\r\n :maxHeight=\"`${height}px`\"\r\n :maxWidth=\"`${width}px`\"\r\n :src=\"videoUrlString\"\r\n @timeupdate=\"updateTimeLabel\"\r\n @ended=\"videoEnded\"\r\n @click=\"playOrPause\"\r\n @canplay=\"canPlay\"\r\n @error=\"() => stop(false)\"\r\n :style=\"{ width: '100%', aspectRatio: aspectRatioFrac }\"></video>\r\n <div v-if=\"!loading\" class=\"overlay\"></div>\r\n \r\n </div>\r\n </div>\r\n\r\n <dialog\r\n ref=\"imageDetailsDialog\"\r\n style=\"\r\n top: 50%;\r\n left: 50%;\r\n transform: translateY(-50%) translateX(-50%);\r\n border: none;\r\n background: grey;\r\n width: 60%;\r\n \">\r\n <div\r\n v-if=\"videoStatus == Status.stopped\"\r\n style=\"justify-content: center; display: flex\"\r\n :class=\"{\r\n 'dummy-frame': frame.title === -1,\r\n 'div-frame': frame.title !== -1,\r\n }\"\r\n v-html=\"frame.image\"\r\n @dblclick=\"changeToVideo\"></div>\r\n <video\r\n v-if=\"videoOnModal && videoStatus !== Status.stopped && !videoIsLoading\"\r\n ref=\"videoPlayer\"\r\n :src=\"videoUrlString\"\r\n autoplay\r\n @ended=\"videoEnded\"\r\n style=\"width: 100%; aspect-ratio: 11/9\"\r\n controls=\"true\"\r\n width=\"200%\"></video>\r\n </dialog>\r\n </div>\r\n</template>\r\n<script>\r\nimport VueLoading from 'vue-loading-twa'\r\n\r\nconst Status = Object.freeze({\r\n stopped: 0,\r\n playing: 1,\r\n paused: 2,\r\n})\r\n\r\nexport default {\r\n components: {\r\n VueLoading,\r\n },\r\n name: 'frame-component',\r\n props: {\r\n frame: {\r\n type: [Object, Number],\r\n required: true,\r\n },\r\n index: {\r\n type: Number,\r\n required: true,\r\n },\r\n loading: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n gridSettings: {\r\n type: Object,\r\n required: true,\r\n },\r\n initialTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n endTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n betweenTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n active: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n activeTab: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n videoUrl: {\r\n type: [String, Promise],\r\n required: true,\r\n },\r\n playbackRate: {\r\n type: Number,\r\n default: 1,\r\n },\r\n videoControls: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n aspectRatio: {\r\n type: Number,\r\n default: 11 / 9,\r\n },\r\n },\r\n data() {\r\n return {\r\n Status,\r\n width: 0,\r\n height: 0,\r\n maxWidth: 0,\r\n fullMaxWidth: 0,\r\n maxHeight: 0,\r\n showFrame: false,\r\n videoStatus: Status.stopped,\r\n videoStartTime: null,\r\n videoCurrentTime: null,\r\n videoUrlString: '',\r\n parentComponent: null,\r\n videoIsLoading: false,\r\n currentBlock: null,\r\n lastTimeEnterPressed: null,\r\n videoOnModal: false,\r\n }\r\n },\r\n created() {\r\n this.parentComponent = this.$parent\r\n },\r\n watch: {\r\n playbackRate(val) {\r\n if (\r\n this.videoStatus === Status.playing ||\r\n this.videoStatus === Status.paused\r\n ) {\r\n this.$refs.videoPlayer.playbackRate = val\r\n }\r\n },\r\n },\r\n computed: {\r\n isLoading() {\r\n return (\r\n ((!this.frame.image || !this.frame.time) && this.frame.title !== -1) ||\r\n this.loading ||\r\n this.videoIsLoading\r\n )\r\n },\r\n aspectRatioFrac() {\r\n var gcd = function (a, b) {\r\n if (b < 0.0000001) return a\r\n\r\n return gcd(b, Math.floor(a % b))\r\n }\r\n\r\n var denominator = Math.pow(10, this.aspectRatio.toString().length - 2)\r\n var numerator = this.aspectRatio * denominator\r\n\r\n var divisor = gcd(numerator, denominator)\r\n\r\n return `${Math.floor(numerator / divisor)}/${Math.floor(\r\n denominator / divisor\r\n )}`\r\n },\r\n },\r\n methods: {\r\n canPlay() {\r\n this.$refs.videoPlayer.play()\r\n },\r\n changeToVideo() {\r\n this.videoOnModal = true\r\n this.playOrPause()\r\n },\r\n jumpFrameToStart() {\r\n if (this.active) {\r\n const currentTime = new Date().getTime()\r\n\r\n if (currentTime - this.lastTimeEnterPressed <= 500) {\r\n this.parentComponent.changeHour(\r\n this.parentComponent.convertToAudienceTime(this.frame.time)\r\n )\r\n }\r\n\r\n this.lastTimeEnterPressed = currentTime\r\n }\r\n },\r\n changeSettings(value) {\r\n this.videoCurrentTime = value\r\n },\r\n toogleDetailFrame() {\r\n this.stop()\r\n if (this.showFrame) {\r\n this.videoOnModal = false\r\n this.$refs.imageDetailsDialog.close()\r\n } else {\r\n this.$refs.imageDetailsDialog.showModal()\r\n }\r\n this.showFrame = !this.showFrame\r\n },\r\n getMaxWidth() {\r\n const commandBarSize = document.getElementById('command-bar')\r\n\r\n return commandBarSize?.clientWidth\r\n },\r\n resize(height) {\r\n const commandBarSize = document.getElementById('command-bar')\r\n const infoBarSize = document.getElementById('info-bar')\r\n\r\n this.fullMaxWidth = infoBarSize?.clientWidth\r\n this.maxWidth =\r\n (this.fullMaxWidth - this.gridSettings.framesPerRow * 10) /\r\n this.gridSettings.framesPerRow\r\n\r\n const rowSpacing = 29 * this.gridSettings.numberOfRows\r\n \r\n let heightAvailable =\r\n height -\r\n (commandBarSize?.offsetHeight || 0) -\r\n infoBarSize?.offsetHeight -\r\n rowSpacing -\r\n 2 // bottom padding\r\n\r\n if (this.gridSettings.numberOfRows > 1) {\r\n heightAvailable += 12\r\n }\r\n\r\n this.maxHeight = heightAvailable / this.gridSettings.numberOfRows\r\n const minHeightPerRow = this.gridSettings.numberOfRows > 2 ? 50 : 60\r\n this.maxHeight = Math.max(this.maxHeight, minHeightPerRow)\r\n\r\n if (this.maxWidth / this.aspectRatio > this.maxHeight) {\r\n this.height = this.maxHeight\r\n this.width = this.maxHeight * this.aspectRatio\r\n } else {\r\n this.width = this.maxWidth\r\n this.height = this.maxWidth / this.aspectRatio\r\n }\r\n\r\n this.maxHeight = this.height\r\n },\r\n\r\n async playOrPause() {\r\n switch (this.videoStatus) {\r\n case Status.stopped:\r\n this.videoIsLoading = true\r\n try {\r\n this.videoUrlString = await this.videoUrl\r\n const blockInfo =\r\n await this.parentComponent.fInterface?.getVideoStartTime(\r\n this.frame\r\n )\r\n\r\n this.videoStartTime = blockInfo.start\r\n this.videoUrlString =\r\n this.parentComponent.fInterface.getVideoRequestByUrl(\r\n blockInfo.url,\r\n this.frame.number + this.parentComponent.shiftFrames\r\n )\r\n } catch (error) {\r\n console.log(error)\r\n }\r\n this.videoIsLoading = false\r\n this.videoStatus = Status.playing\r\n this.$nextTick(() => {\r\n this.$refs.videoPlayer.onloaded = (e) => {\r\n this.$refs.videoPlayer.playbackRate = this.playbackRate\r\n // * atualizar slider\r\n this.$emit('updateSlider', this.videoStartTime, this.frame.time)\r\n //*\r\n this.$emit('startPlaying', this.frame, e.target.duration)\r\n this.$emit('playPauseStatus', true)\r\n }\r\n })\r\n break\r\n case Status.paused:\r\n this.$refs.videoPlayer.play()\r\n this.$refs.videoPlayer.playbackRate = this.playbackRate\r\n this.videoStatus = Status.playing\r\n this.$emit('playPauseStatus', true)\r\n break\r\n case Status.playing:\r\n this.$refs.videoPlayer.pause()\r\n\r\n this.videoStatus = Status.paused\r\n this.$emit('playPauseStatus', false)\r\n break\r\n }\r\n },\r\n stop(jump = true) {\r\n this.videoOnModal = false\r\n if (\r\n this.videoStatus === Status.playing ||\r\n this.videoStatus === Status.paused\r\n ) {\r\n if (jump) {\r\n this.parentComponent.changeHour(\r\n this.parentComponent.convertToAudienceTime(\r\n parseInt(this.videoCurrentTime)\r\n )\r\n )\r\n }\r\n this.videoStatus = Status.stopped\r\n this.videoUrlString = null\r\n this.videoCurrentTime = null\r\n this.videoStartTime = null\r\n }\r\n this.$emit('stopPlaying')\r\n },\r\n //eslint-disable-next-line\r\n videoJumpTo(time) {\r\n this.videoCurrentTime = this.videoStartTime + time\r\n this.$refs.videoPlayer.currentTime = time\r\n },\r\n async videoJumpToTimeStamp(time) {\r\n let frame = {\r\n time: time,\r\n }\r\n if (!time) return\r\n if (\r\n !(\r\n this.currentBlock &&\r\n time >= this.currentBlock.start &&\r\n time <= this.currentBlock.end\r\n )\r\n ) {\r\n this.currentBlock = await this.parentComponent.fInterface?.getBlockInfo(\r\n frame\r\n )\r\n this.videoStartTime = this.currentBlock.start\r\n this.videoUrlString =\r\n this.parentComponent.fInterface.getVideoUrlForTime(\r\n this.videoStartTime\r\n )\r\n }\r\n this.videoCurrentTime = time - this.videoStartTime\r\n this.$refs.videoPlayer.currentTime = this.videoCurrentTime\r\n },\r\n updateTimeLabel(e) {\r\n this.videoCurrentTime = this.videoStartTime + e.target.currentTime\r\n this.parentComponent.updateVideoTime(this.index, this.videoCurrentTime)\r\n this.parentComponent.updateVideoStatus(e.target.currentTime)\r\n },\r\n async videoEnded() {\r\n this.videoStartTime =\r\n await this.parentComponent.fInterface?.getNextVideoStartTime(\r\n this.frame.time - this.parentComponent.shiftFrames\r\n )\r\n this.videoUrlString = this.parentComponent.fInterface.getVideoUrlForTime(\r\n this.videoStartTime\r\n )\r\n // * Ao acabar o vídeo tenho de mandar atualizar slider\r\n // * aqui o video current time tambem vai ser o videoStartTime\r\n this.$emit('updateSlider', this.videoStartTime, this.videoStartTime)\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.frame-container > div {\r\n max-height: 100%;\r\n}\r\n.frame-container {\r\n background-color: black;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n.frame-content,\r\n.dummy-frame {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.frame-content video {\r\n flex-grow: 1;\r\n object-fit: fill;\r\n z-index: 0;\r\n}\r\n.overlay {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\r\n}\r\n.active .overlay {\r\n border-color: var(--visualization-primary);\r\n}\r\n.between-time .overlay {\r\n border-top-color: var(--visualization-secondary);\r\n}\r\n.between-time.active .overlay {\r\n border-color: var(--visualization-secondary);\r\n}\r\n.initial-time .overlay {\r\n border-top-color: var(--visualization-start);\r\n}\r\n.initial-time.active .overlay {\r\n border-color: var(--visualization-start);\r\n}\r\n.end-time .overlay {\r\n border-top-color: var(--visualization-end);\r\n}\r\n.end-time.active .overlay {\r\n border-color: var(--visualization-end);\r\n}\r\n.initial-time.end-time .overlay {\r\n border-top-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n}\r\n.initial-time.end-time.active .overlay {\r\n border-top-color: var(--visualization-start);\r\n border-left-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n border-right-color: var(--visualization-end);\r\n}\r\n.div-frame >>> img {\r\n width: 90vh !important;\r\n}\r\n</style>\r\n"]}, media: undefined });
861
+ inject("data-v-2297f9cd_0", { source: "\n.frame-container > div[data-v-2297f9cd] {\r\n max-height: 100%;\r\n height: 100%; /* Add this */\n}\n.frame-container[data-v-2297f9cd] {\r\n background-color: black;\r\n display: flex;\r\n justify-content: center;\n}\n.frame-content[data-v-2297f9cd],\r\n.dummy-frame[data-v-2297f9cd] {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\n}\n.frame-content video[data-v-2297f9cd] {\r\n flex-grow: 1;\r\n object-fit: fill;\r\n z-index: 0;\n}\n.overlay[data-v-2297f9cd] {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\n}\n.active .overlay[data-v-2297f9cd] {\r\n border-color: var(--visualization-primary);\n}\n.between-time .overlay[data-v-2297f9cd] {\r\n border-top-color: var(--visualization-secondary);\n}\n.between-time.active .overlay[data-v-2297f9cd] {\r\n border-color: var(--visualization-secondary);\n}\n.initial-time .overlay[data-v-2297f9cd] {\r\n border-top-color: var(--visualization-start);\n}\n.initial-time.active .overlay[data-v-2297f9cd] {\r\n border-color: var(--visualization-start);\n}\n.end-time .overlay[data-v-2297f9cd] {\r\n border-top-color: var(--visualization-end);\n}\n.end-time.active .overlay[data-v-2297f9cd] {\r\n border-color: var(--visualization-end);\n}\n.initial-time.end-time .overlay[data-v-2297f9cd] {\r\n border-top-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\n}\n.initial-time.end-time.active .overlay[data-v-2297f9cd] {\r\n border-top-color: var(--visualization-start);\r\n border-left-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n border-right-color: var(--visualization-end);\n}\r\n\r\n/* new styles */\n.frame-content[data-v-2297f9cd] img,\r\n.dummy-frame[data-v-2297f9cd] img {\r\n width: 100% !important;\r\n height: 100% !important;\r\n object-fit: fill !important;\r\n aspect-ratio: auto !important;\r\n display: block !important;\n}\n.frame-content[data-v-2297f9cd] div,\r\n.dummy-frame[data-v-2297f9cd] div {\r\n width: 100% !important;\r\n height: 100% !important;\n}\n.frame-content video[data-v-2297f9cd] {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: fill;\r\n z-index: 0;\n}\n.overlay[data-v-2297f9cd] {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\n}\r\n/* «««««««« */\n.div-frame[data-v-2297f9cd] img {\r\n width: 90vh !important;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\components\\Frame.vue"],"names":[],"mappings":";AAwcA;EACA,gBAAA;EACA,YAAA,EAAA,aAAA;AACA;AACA;EACA,uBAAA;EACA,aAAA;EACA,uBAAA;AACA;AACA;;EAEA,aAAA;EACA,mBAAA;EACA,uBAAA;AACA;AACA;EACA,YAAA;EACA,gBAAA;EACA,UAAA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,6BAAA;EACA,oBAAA;AACA;AACA;EACA,0CAAA;AACA;AACA;EACA,gDAAA;AACA;AACA;EACA,4CAAA;AACA;AACA;EACA,4CAAA;AACA;AACA;EACA,wCAAA;AACA;AACA;EACA,0CAAA;AACA;AACA;EACA,sCAAA;AACA;AACA;EACA,4CAAA;EACA,6CAAA;AACA;AACA;EACA,4CAAA;EACA,6CAAA;EACA,6CAAA;EACA,4CAAA;AACA;;AAEA,eAAA;AACA;;EAEA,sBAAA;EACA,uBAAA;EACA,2BAAA;EACA,6BAAA;EACA,yBAAA;AACA;AAEA;;EAEA,sBAAA;EACA,uBAAA;AACA;AAEA;EACA,WAAA;EACA,YAAA;EACA,gBAAA;EACA,UAAA;AACA;AAEA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,6BAAA;EACA,oBAAA;AACA;AACA,aAAA;AACA;EACA,sBAAA;AACA","file":"Frame.vue","sourcesContent":["<template>\r\n <div\r\n :style=\"{\r\n maxHeight: `${maxHeight}px`,\r\n width: '100%',\r\n position: 'relative',\r\n }\"\r\n :class=\"{\r\n 'frame-container': true,\r\n 'initial-time': initialTime,\r\n 'end-time': endTime,\r\n 'between-time': betweenTime,\r\n active: active,\r\n }\">\r\n <GlobalEvents\r\n v-if=\"active && activeTab && parentComponent.settingsClosed\"\r\n @keydown.32.prevent=\"playOrPause\"\r\n @keydown.27.prevent=\"stop\"\r\n @keydown.79=\"toogleDetailFrame\"\r\n @keydown.13.prevent=\"jumpFrameToStart\" />\r\n <GlobalEvents\r\n v-if=\"showFrame\"\r\n @keydown.27.prevent=\"toogleDetailFrame\"\r\n @keydown.13.prevent=\"toogleDetailFrame\" />\r\n\r\n <vue-loading\r\n :active=\"isLoading\"\r\n spinner=\"ring\"\r\n color=\"var(--visualization-primary)\"\r\n background-color=\"#cacaca\"\r\n :style=\"{\r\n 'z-index': 0,\r\n minHeight: `${height}px`,\r\n minWidth: `${width}px`,\r\n }\"\r\n :text=\"videoIsLoading ? $t('infoBar.createVideo') : ''\" />\r\n <div\r\n :style=\"{\r\n backgroundColor: 'black',\r\n width: stretchFrame ? '100%' : 'auto',\r\n height: stretchFrame ? '100%' : 'auto',\r\n }\">\r\n <div\r\n v-if=\"!isLoading\"\r\n :class=\"{\r\n 'frame-content': frame.title === -1 || videoStatus !== Status.stopped,\r\n }\"\r\n :style=\"\r\n stretchFrame\r\n ? {\r\n height: `${maxHeight}px`,\r\n width: '100%',\r\n color: 'white',\r\n }\r\n : {\r\n minHeight: `${height}px`,\r\n minWidth: `${width}px`,\r\n maxHeight: `${height}px`,\r\n maxWidth: `${width}px`,\r\n color: 'white',\r\n }\r\n \"\r\n @dblclick=\"playOrPause\">\r\n <div\r\n v-if=\"frame.image && videoStatus === Status.stopped\"\r\n :class=\"{ 'dummy-frame': frame.title === -1 }\"\r\n v-html=\"frame.image\"\r\n style=\"width: 100%; height: 100%\" />\r\n\r\n <video\r\n v-if=\"\r\n !videoOnModal && videoStatus !== Status.stopped && !videoIsLoading\r\n \"\r\n ref=\"videoPlayer\"\r\n :maxHeight=\"`${height}px`\"\r\n :maxWidth=\"`${width}px`\"\r\n :src=\"videoUrlString\"\r\n @timeupdate=\"updateTimeLabel\"\r\n @ended=\"videoEnded\"\r\n @click=\"playOrPause\"\r\n @canplay=\"canPlay\"\r\n @error=\"() => stop(false)\"\r\n :style=\"{ width: '100%', aspectRatio: aspectRatioFrac }\"></video>\r\n <div v-if=\"!loading\" class=\"overlay\"></div>\r\n \r\n </div>\r\n </div>\r\n\r\n <dialog\r\n ref=\"imageDetailsDialog\"\r\n style=\"\r\n top: 50%;\r\n left: 50%;\r\n transform: translateY(-50%) translateX(-50%);\r\n border: none;\r\n background: grey;\r\n width: 60%;\r\n \">\r\n <div\r\n v-if=\"videoStatus == Status.stopped\"\r\n style=\"justify-content: center; display: flex\"\r\n :class=\"{\r\n 'dummy-frame': frame.title === -1,\r\n 'div-frame': frame.title !== -1,\r\n }\"\r\n v-html=\"frame.image\"\r\n @dblclick=\"changeToVideo\"></div>\r\n <video\r\n v-if=\"videoOnModal && videoStatus !== Status.stopped && !videoIsLoading\"\r\n ref=\"videoPlayer\"\r\n :src=\"videoUrlString\"\r\n autoplay\r\n @ended=\"videoEnded\"\r\n style=\"width: 100%; aspect-ratio: 11/9\"\r\n controls=\"true\"\r\n width=\"200%\"></video>\r\n </dialog>\r\n </div>\r\n</template>\r\n<script>\r\nimport VueLoading from 'vue-loading-twa'\r\n\r\nconst Status = Object.freeze({\r\n stopped: 0,\r\n playing: 1,\r\n paused: 2,\r\n})\r\n\r\nexport default {\r\n components: {\r\n VueLoading,\r\n },\r\n name: 'frame-component',\r\n props: {\r\n frame: {\r\n type: [Object, Number],\r\n required: true,\r\n },\r\n index: {\r\n type: Number,\r\n required: true,\r\n },\r\n loading: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n gridSettings: {\r\n type: Object,\r\n required: true,\r\n },\r\n initialTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n endTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n betweenTime: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n active: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n activeTab: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n videoUrl: {\r\n type: [String, Promise],\r\n required: true,\r\n },\r\n playbackRate: {\r\n type: Number,\r\n default: 1,\r\n },\r\n videoControls: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n aspectRatio: {\r\n type: Number,\r\n default: 11 / 9,\r\n },\r\n stretchFrame: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n data() {\r\n return {\r\n Status,\r\n width: 0,\r\n height: 0,\r\n maxWidth: 0,\r\n fullMaxWidth: 0,\r\n maxHeight: 0,\r\n showFrame: false,\r\n videoStatus: Status.stopped,\r\n videoStartTime: null,\r\n videoCurrentTime: null,\r\n videoUrlString: '',\r\n parentComponent: null,\r\n videoIsLoading: false,\r\n currentBlock: null,\r\n lastTimeEnterPressed: null,\r\n videoOnModal: false,\r\n }\r\n },\r\n created() {\r\n this.parentComponent = this.$parent\r\n },\r\n watch: {\r\n playbackRate(val) {\r\n if (\r\n this.videoStatus === Status.playing ||\r\n this.videoStatus === Status.paused\r\n ) {\r\n this.$refs.videoPlayer.playbackRate = val\r\n }\r\n },\r\n },\r\n computed: {\r\n isLoading() {\r\n return (\r\n ((!this.frame.image || !this.frame.time) && this.frame.title !== -1) ||\r\n this.loading ||\r\n this.videoIsLoading\r\n )\r\n },\r\n aspectRatioFrac() {\r\n var gcd = function (a, b) {\r\n if (b < 0.0000001) return a\r\n\r\n return gcd(b, Math.floor(a % b))\r\n }\r\n\r\n var denominator = Math.pow(10, this.aspectRatio.toString().length - 2)\r\n var numerator = this.aspectRatio * denominator\r\n\r\n var divisor = gcd(numerator, denominator)\r\n\r\n return `${Math.floor(numerator / divisor)}/${Math.floor(\r\n denominator / divisor\r\n )}`\r\n },\r\n },\r\n methods: {\r\n canPlay() {\r\n this.$refs.videoPlayer.play()\r\n },\r\n changeToVideo() {\r\n this.videoOnModal = true\r\n this.playOrPause()\r\n },\r\n jumpFrameToStart() {\r\n if (this.active) {\r\n const currentTime = new Date().getTime()\r\n\r\n if (currentTime - this.lastTimeEnterPressed <= 500) {\r\n this.parentComponent.changeHour(\r\n this.parentComponent.convertToAudienceTime(this.frame.time)\r\n )\r\n }\r\n\r\n this.lastTimeEnterPressed = currentTime\r\n }\r\n },\r\n changeSettings(value) {\r\n this.videoCurrentTime = value\r\n },\r\n toogleDetailFrame() {\r\n this.stop()\r\n if (this.showFrame) {\r\n this.videoOnModal = false\r\n this.$refs.imageDetailsDialog.close()\r\n } else {\r\n this.$refs.imageDetailsDialog.showModal()\r\n }\r\n this.showFrame = !this.showFrame\r\n },\r\n getMaxWidth() {\r\n const commandBarSize = document.getElementById('command-bar')\r\n\r\n return commandBarSize?.clientWidth\r\n },\r\n resize(height) {\r\n const commandBarSize = document.getElementById('command-bar')\r\n const infoBarSize = document.getElementById('info-bar')\r\n\r\n this.fullMaxWidth = infoBarSize?.clientWidth\r\n this.maxWidth =\r\n (this.fullMaxWidth - this.gridSettings.framesPerRow * 10) /\r\n this.gridSettings.framesPerRow\r\n\r\n const rowSpacing = 29 * this.gridSettings.numberOfRows\r\n \r\n let heightAvailable =\r\n height -\r\n (commandBarSize?.offsetHeight || 0) -\r\n infoBarSize?.offsetHeight -\r\n rowSpacing -\r\n 2 // bottom padding\r\n\r\n if (this.gridSettings.numberOfRows > 1) {\r\n heightAvailable += 12\r\n }\r\n\r\n this.maxHeight = heightAvailable / this.gridSettings.numberOfRows\r\n const minHeightPerRow = this.gridSettings.numberOfRows > 2 ? 50 : 60\r\n this.maxHeight = Math.max(this.maxHeight, minHeightPerRow)\r\n\r\n if (this.maxWidth / this.aspectRatio > this.maxHeight) {\r\n this.height = this.maxHeight\r\n this.width = this.maxHeight * this.aspectRatio\r\n } else {\r\n this.width = this.maxWidth\r\n this.height = this.maxWidth / this.aspectRatio\r\n }\r\n this.applyImageStyles()\r\n this.maxHeight = this.height\r\n },\r\n applyImageStyles() {\r\n this.$nextTick(() => {\r\n const frameImages = this.$el.querySelectorAll(\r\n '.frame-container img, .dummy-frame img'\r\n )\r\n\r\n frameImages.forEach((img) => {\r\n img.style.width = '100%'\r\n img.style.height = '100%'\r\n img.style.objectFit = 'fill'\r\n img.style.aspectRatio = 'auto'\r\n img.style.display = 'block'\r\n })\r\n })\r\n },\r\n async playOrPause() {\r\n switch (this.videoStatus) {\r\n case Status.stopped:\r\n this.videoIsLoading = true\r\n try {\r\n this.videoUrlString = await this.videoUrl\r\n const blockInfo =\r\n await this.parentComponent.fInterface?.getVideoStartTime(\r\n this.frame\r\n )\r\n\r\n this.videoStartTime = blockInfo.start\r\n this.videoUrlString =\r\n this.parentComponent.fInterface.getVideoRequestByUrl(\r\n blockInfo.url,\r\n this.frame.number + this.parentComponent.shiftFrames\r\n )\r\n } catch (error) {\r\n console.log(error)\r\n }\r\n this.videoIsLoading = false\r\n this.videoStatus = Status.playing\r\n this.$nextTick(() => {\r\n this.$refs.videoPlayer.onloaded = (e) => {\r\n this.$refs.videoPlayer.playbackRate = this.playbackRate\r\n // * atualizar slider\r\n this.$emit('updateSlider', this.videoStartTime, this.frame.time)\r\n //*\r\n this.$emit('startPlaying', this.frame, e.target.duration)\r\n this.$emit('playPauseStatus', true)\r\n }\r\n })\r\n break\r\n case Status.paused:\r\n this.$refs.videoPlayer.play()\r\n this.$refs.videoPlayer.playbackRate = this.playbackRate\r\n this.videoStatus = Status.playing\r\n this.$emit('playPauseStatus', true)\r\n break\r\n case Status.playing:\r\n this.$refs.videoPlayer.pause()\r\n\r\n this.videoStatus = Status.paused\r\n this.$emit('playPauseStatus', false)\r\n break\r\n }\r\n },\r\n stop(jump = true) {\r\n this.videoOnModal = false\r\n if (\r\n this.videoStatus === Status.playing ||\r\n this.videoStatus === Status.paused\r\n ) {\r\n if (jump) {\r\n this.parentComponent.changeHour(\r\n this.parentComponent.convertToAudienceTime(\r\n parseInt(this.videoCurrentTime)\r\n )\r\n )\r\n }\r\n this.videoStatus = Status.stopped\r\n this.videoUrlString = null\r\n this.videoCurrentTime = null\r\n this.videoStartTime = null\r\n }\r\n this.$emit('stopPlaying')\r\n },\r\n //eslint-disable-next-line\r\n videoJumpTo(time) {\r\n this.videoCurrentTime = this.videoStartTime + time\r\n this.$refs.videoPlayer.currentTime = time\r\n },\r\n async videoJumpToTimeStamp(time) {\r\n let frame = {\r\n time: time,\r\n }\r\n if (!time) return\r\n if (\r\n !(\r\n this.currentBlock &&\r\n time >= this.currentBlock.start &&\r\n time <= this.currentBlock.end\r\n )\r\n ) {\r\n this.currentBlock = await this.parentComponent.fInterface?.getBlockInfo(\r\n frame\r\n )\r\n this.videoStartTime = this.currentBlock.start\r\n this.videoUrlString =\r\n this.parentComponent.fInterface.getVideoUrlForTime(\r\n this.videoStartTime\r\n )\r\n }\r\n this.videoCurrentTime = time - this.videoStartTime\r\n this.$refs.videoPlayer.currentTime = this.videoCurrentTime\r\n },\r\n updateTimeLabel(e) {\r\n this.videoCurrentTime = this.videoStartTime + e.target.currentTime\r\n this.parentComponent.updateVideoTime(this.index, this.videoCurrentTime)\r\n this.parentComponent.updateVideoStatus(e.target.currentTime)\r\n },\r\n async videoEnded() {\r\n this.videoStartTime =\r\n await this.parentComponent.fInterface?.getNextVideoStartTime(\r\n this.frame.time - this.parentComponent.shiftFrames\r\n )\r\n this.videoUrlString = this.parentComponent.fInterface.getVideoUrlForTime(\r\n this.videoStartTime\r\n )\r\n // * Ao acabar o vídeo tenho de mandar atualizar slider\r\n // * aqui o video current time tambem vai ser o videoStartTime\r\n this.$emit('updateSlider', this.videoStartTime, this.videoStartTime)\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.frame-container > div {\r\n max-height: 100%;\r\n height: 100%; /* Add this */\r\n}\r\n.frame-container {\r\n background-color: black;\r\n display: flex;\r\n justify-content: center;\r\n}\r\n.frame-content,\r\n.dummy-frame {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.frame-content video {\r\n flex-grow: 1;\r\n object-fit: fill;\r\n z-index: 0;\r\n}\r\n.overlay {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\r\n}\r\n.active .overlay {\r\n border-color: var(--visualization-primary);\r\n}\r\n.between-time .overlay {\r\n border-top-color: var(--visualization-secondary);\r\n}\r\n.between-time.active .overlay {\r\n border-color: var(--visualization-secondary);\r\n}\r\n.initial-time .overlay {\r\n border-top-color: var(--visualization-start);\r\n}\r\n.initial-time.active .overlay {\r\n border-color: var(--visualization-start);\r\n}\r\n.end-time .overlay {\r\n border-top-color: var(--visualization-end);\r\n}\r\n.end-time.active .overlay {\r\n border-color: var(--visualization-end);\r\n}\r\n.initial-time.end-time .overlay {\r\n border-top-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n}\r\n.initial-time.end-time.active .overlay {\r\n border-top-color: var(--visualization-start);\r\n border-left-color: var(--visualization-start);\r\n border-bottom-color: var(--visualization-end);\r\n border-right-color: var(--visualization-end);\r\n}\r\n\r\n/* new styles */\r\n.frame-content >>> img,\r\n.dummy-frame >>> img {\r\n width: 100% !important;\r\n height: 100% !important;\r\n object-fit: fill !important;\r\n aspect-ratio: auto !important;\r\n display: block !important;\r\n}\r\n\r\n.frame-content >>> div,\r\n.dummy-frame >>> div {\r\n width: 100% !important;\r\n height: 100% !important;\r\n}\r\n\r\n.frame-content video {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: fill;\r\n z-index: 0;\r\n}\r\n\r\n.overlay {\r\n width: 100%;\r\n height: 100%;\r\n z-index: 5;\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n border: 4px solid transparent;\r\n pointer-events: none;\r\n}\r\n/* «««««««« */\r\n.div-frame >>> img {\r\n width: 90vh !important;\r\n}\r\n</style>\r\n"]}, media: undefined });
824
862
 
825
863
  };
826
864
  /* scoped */
827
- const __vue_scope_id__$5 = "data-v-e76055ba";
865
+ const __vue_scope_id__$5 = "data-v-2297f9cd";
828
866
  /* module identifier */
829
867
  const __vue_module_identifier__$5 = undefined;
830
868
  /* functional template */
@@ -872,12 +910,14 @@ var FramesService = {
872
910
  direction,
873
911
  channel,
874
912
  split,
913
+ size,
875
914
  time,
876
915
  quality,
877
916
  factor,
878
917
  useCache = true,
879
918
  signal,
880
919
  } = {}) {
920
+ let fileSize = size > 180 ? '88x72' : '352x288';
881
921
  return API().get(`Get${direction}FramesBlockInFiles`, {
882
922
  params: {
883
923
  Channel: channel,
@@ -887,6 +927,7 @@ var FramesService = {
887
927
  Step: 0,
888
928
  JpegQuality: quality,
889
929
  JpegSizeFactor: factor,
930
+ FileSize: fileSize,
890
931
  },
891
932
  signal,
892
933
  })
@@ -902,6 +943,9 @@ var FramesService = {
902
943
  useCache = true,
903
944
  signal,
904
945
  } = {}) {
946
+ //console.log('Getting small block request', size)
947
+
948
+ let fileSize = size > 180 ? '88x72' : '352x288';
905
949
  return API().get('GetSmallFramesBlockInFiles', {
906
950
  params: {
907
951
  Channel: channel,
@@ -912,6 +956,7 @@ var FramesService = {
912
956
  JpegQuality: quality,
913
957
  JpegSizeFactor: factor,
914
958
  Size: size,
959
+ FileSize: fileSize,
915
960
  },
916
961
  signal,
917
962
  })
@@ -1306,6 +1351,7 @@ FramesManager.prototype.getBlock = async function (
1306
1351
  channel,
1307
1352
  split,
1308
1353
  time,
1354
+ size: this.size * 15,
1309
1355
  quality: ENUM.StepsQuality[this.currentStep],
1310
1356
  factor: ENUM.StepsFactor[this.currentStep],
1311
1357
  signal: this.requests[requestId].signal,
@@ -2286,6 +2332,13 @@ __vue_render__$4._withStripped = true;
2286
2332
  //
2287
2333
  //
2288
2334
  //
2335
+ //
2336
+ //
2337
+ //
2338
+ //
2339
+ //
2340
+ //
2341
+ //
2289
2342
 
2290
2343
  var script$3 = {
2291
2344
  props: {
@@ -2331,9 +2384,16 @@ var script$3 = {
2331
2384
  hourEnd: {
2332
2385
  type: [Number, Boolean],
2333
2386
  },
2387
+ showStretchFrame: {
2388
+ type: Boolean,
2389
+ default: false,
2390
+ },
2391
+
2334
2392
  },
2335
2393
  data() {
2336
- return {}
2394
+ return {
2395
+ stretchFrames: false,
2396
+ }
2337
2397
  },
2338
2398
  computed: {
2339
2399
  blockTotalTime() {
@@ -2502,6 +2562,34 @@ var __vue_render__$3 = function () {
2502
2562
  "div",
2503
2563
  { staticClass: "settings-container" },
2504
2564
  [
2565
+ _c("font-awesome-icon", {
2566
+ directives: [
2567
+ {
2568
+ name: "show",
2569
+ rawName: "v-show",
2570
+ value: _vm.showStretchFrame,
2571
+ expression: "showStretchFrame",
2572
+ },
2573
+ {
2574
+ name: "tooltip",
2575
+ rawName: "v-tooltip",
2576
+ value: _vm.$t("infoBar.stretchFrames"),
2577
+ expression: "$t('infoBar.stretchFrames')",
2578
+ },
2579
+ ],
2580
+ attrs: {
2581
+ icon: !_vm.stretchFrames
2582
+ ? ["fas", "fa-maximize"]
2583
+ : ["fas", "fa-minimize"],
2584
+ },
2585
+ on: {
2586
+ click: function ($event) {
2587
+ _vm.stretchFrames = !_vm.stretchFrames;
2588
+ _vm.$emit("update-stretch-frames", _vm.stretchFrames);
2589
+ },
2590
+ },
2591
+ }),
2592
+ _vm._v(" "),
2505
2593
  _c("font-awesome-icon", {
2506
2594
  directives: [
2507
2595
  {
@@ -2609,11 +2697,11 @@ __vue_render__$3._withStripped = true;
2609
2697
  /* style */
2610
2698
  const __vue_inject_styles__$3 = function (inject) {
2611
2699
  if (!inject) return
2612
- inject("data-v-848911da_0", { source: "\n.visualization-row[data-v-848911da] {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\n}\n.visualization-col[data-v-848911da] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\n}\n.visualization-divider[data-v-848911da] {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\n}\n.visualization-divider.vertical[data-v-848911da] {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\n}\n.visualization-card[data-v-848911da] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\n}\n.visualization-justify-center[data-v-848911da],[data-v-848911da] .visualization-justify-center {\r\n justify-content: center;\n}\n.visualization-align-center[data-v-848911da] {\r\n align-items: center;\n}\n#visualization-container[data-v-848911da] {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\n}\n#visualization-container > .card[data-v-848911da] {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\n}\n#command-bar[data-v-848911da],\r\n#info-bar[data-v-848911da] {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n#command-bar button[data-v-848911da] {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\n}\n#command-bar button[data-v-848911da]:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\n}\n#command-bar svg[data-v-848911da] {\r\n font-size: 16px;\n}\n#command-bar[data-v-848911da] {\r\n padding: 0 !important;\n}\n#info-bar[data-v-848911da] {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\n}\n.settings-container[data-v-848911da] {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\n}\n.settings-container > *[data-v-848911da] {\r\n margin: 0 2px;\r\n cursor: pointer;\n}\n#info-bar svg[data-v-848911da] {\r\n font-size: 16px;\n}\n#info-bar .divider[data-v-848911da] {\r\n margin: 0 8px;\n}\nsvg[data-v-848911da]:focus {\r\n border: none;\n}\n.visualization-card[data-v-848911da] {\r\n border-left: 8px solid #eee;\n}\n.active-tab[data-v-848911da] {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\n}\n[id^='frame-'][data-v-848911da] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\n}\n.tooltip[data-v-848911da] {\r\n display: block !important;\r\n z-index: 10000;\n}\n.tooltip .tooltip-inner[data-v-848911da] {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\n}\n.tooltip .tooltip-arrow[data-v-848911da] {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\n}\n.tooltip[x-placement^='top'][data-v-848911da] {\r\n margin-bottom: 5px;\n}\n.tooltip[x-placement^='top'] .tooltip-arrow[data-v-848911da] {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='bottom'][data-v-848911da] {\r\n margin-top: 5px;\n}\n.tooltip[x-placement^='bottom'] .tooltip-arrow[data-v-848911da] {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='right'][data-v-848911da] {\r\n margin-left: 5px;\n}\n.tooltip[x-placement^='right'] .tooltip-arrow[data-v-848911da] {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip[x-placement^='left'][data-v-848911da] {\r\n margin-right: 5px;\n}\n.tooltip[x-placement^='left'] .tooltip-arrow[data-v-848911da] {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip.popover .popover-inner[data-v-848911da] {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\n}\n.tooltip.popover .popover-arrow[data-v-848911da] {\r\n border-color: #f9f9f9;\n}\n.tooltip[aria-hidden='true'][data-v-848911da] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\n}\n.tooltip[aria-hidden='false'][data-v-848911da] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\components\\Infos.vue"],"names":[],"mappings":";AA+LA;EACA,aAAA;EACA,eAAA;EACA,cAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;AACA;AAEA;EACA,cAAA;EACA,cAAA;EACA,WAAA;EACA,eAAA;EACA,UAAA;EACA,mBAAA;EACA,mBAAA;EACA,wBAAA;EACA,iCAAA;EACA,SAAA;AACA;AAEA;EACA,mBAAA;EACA,wBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,cAAA;EACA,2BAAA;EACA,UAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;EACA,WAAA;EACA,4DAAA;EACA,yBAAA;EACA;qCACA;AACA;AAEA;EAEA,uBAAA;AACA;AAEA;EACA,mBAAA;AACA;AAEA;EACA,0BAAA;EACA,yBAAA;EACA,YAAA;EACA,mBAAA;AACA;AACA;EACA,2BAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;AACA;AAEA;;EAEA,yBAAA;EACA;mCACA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;EACA,+BAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,eAAA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,2BAAA;AACA;AAEA;EACA,aAAA;EACA,eAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,YAAA;AACA;AAEA;EACA,2BAAA;AACA;AAEA;EACA,8DAAA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;AACA;AAEA;EACA,yBAAA;EACA,cAAA;AACA;AAEA;EACA,wCAAA;EACA,YAAA;EACA,mBAAA;EACA,qBAAA;AACA;AAEA;EACA,QAAA;EACA,SAAA;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,0CAAA;EACA,UAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,2CAAA;EACA,YAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,wCAAA;EACA,SAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,wCAAA;EACA,2CAAA;EACA,UAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,iBAAA;AACA;AAEA;EACA,2BAAA;EACA,wCAAA;EACA,0CAAA;EACA,2CAAA;EACA,WAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,mBAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,uCAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,kBAAA;EACA,UAAA;EACA,2CAAA;AACA;AAEA;EACA,mBAAA;EACA,UAAA;EACA,yBAAA;AACA","file":"Infos.vue","sourcesContent":["<template>\r\n <div\r\n id=\"info-bar\"\r\n class=\"visualization-col\"\r\n :style=\"\r\n !commandsShow ? 'border-top-right-radius: 6px; padding: 0' : 'padding: 0'\r\n \"\r\n >\r\n <div\r\n class=\"visualization-row visualization-justify-center visualization-align-center\"\r\n style=\"position: relative; padding: 4px\"\r\n >\r\n <span> {{ playbackRate }}x </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.selected', {\r\n seconds: hourEnd && hourIni ? hourEnd - hourIni + 1 : 0,\r\n hour_ini: convertToAudienceTime(hourIni),\r\n hour_end: convertToAudienceTime(hourEnd),\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.interval', {\r\n seconds: secondsPerFrame,\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.block', {\r\n time1: convertToAudienceTime(blockStartTime),\r\n time2: convertToAudienceTime(blockTotalTime),\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n {{ framesPerRow * numberOfRows }}\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n {{ framesPerRow + '*' + numberOfRows }}\r\n <span\r\n class=\"visualization-divider vertical\"\r\n v-if=\"!cache\"\r\n style=\"margin: 0 8px\"\r\n />\r\n <span v-if=\"!cache\">\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-exclamation-circle\"\r\n style=\"margin: 0 4px\"\r\n />\r\n <strong>{{ $t('infoBar.notUsingCache') }}</strong>\r\n </span>\r\n <div class=\"settings-container\">\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-server\"\r\n @click=\"$emit('change-server')\"\r\n v-tooltip=\"\r\n alternativeServer\r\n ? $t('infoBar.changeServer')\r\n : $t('infoBar.changeServer')\r\n \"\r\n />\r\n <font-awesome-icon\r\n :icon=\"commandsShow ? 'fa-solid fa-eye' : 'fa-solid fa-eye-slash'\"\r\n @click=\"$emit('toogle-commands-visibility')\"\r\n v-tooltip=\"\r\n commandsShow\r\n ? $t('moduletelentry.showButtons')\r\n : $t('moduletelentry.hideButtons')\r\n \"\r\n />\r\n <font-awesome-icon\r\n :icon=\"cache ? 'fa-solid fa-ban' : 'fa-solid fa-sync'\"\r\n @click=\"$emit('toogle-cache')\"\r\n v-tooltip=\"\r\n cache ? $t('infoBar.disableCache') : $t('infoBar.activateCache')\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div\r\n v-if=\"alternativeServer\"\r\n class=\"visualization-row visualization-justify-center visualization-align-center\"\r\n style=\"\r\n color: white;\r\n background-color: orange;\r\n font-weight: bold;\r\n padding: 4px;\r\n \"\r\n >\r\n {{ $t('infoBar.alternativeServer') }}\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-exclamation-triangle\"\r\n style=\"margin: 0 4px\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n<script>\r\nexport default {\r\n props: {\r\n playbackRate: {\r\n type: Number,\r\n required: true,\r\n },\r\n secondsPerFrame: {\r\n type: Number,\r\n required: true,\r\n },\r\n commandsShow: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n cache: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n blockStartTime: {\r\n type: Number,\r\n required: true,\r\n },\r\n videoTotalDuration: {\r\n type: Number,\r\n required: true,\r\n },\r\n alternativeServer: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n framesPerRow: {\r\n type: Number,\r\n required: true,\r\n },\r\n numberOfRows: {\r\n type: Number,\r\n required: true,\r\n },\r\n hourIni: {\r\n type: [Number, Boolean],\r\n },\r\n hourEnd: {\r\n type: [Number, Boolean],\r\n },\r\n },\r\n data() {\r\n return {}\r\n },\r\n computed: {\r\n blockTotalTime() {\r\n return this.videoTotalDuration + this.blockStartTime\r\n },\r\n },\r\n methods: {\r\n convertToAudienceTime(time, separator = ':') {\r\n const limit = Date.UTC(null, null, null, 23, 59, 59) / 1000\r\n\r\n let hour = this.dateInUtc(time * 1000)\r\n .toTimeString()\r\n .split(' ')[0]\r\n .split(':')\r\n .map(Number)\r\n\r\n if (time > limit && time <= limit + this.startAudienceSeconds) {\r\n hour[0] = 24 + hour[0]\r\n }\r\n return hour\r\n .map((part) => (part > 9 ? part.toString() : '0' + part))\r\n .join(separator)\r\n },\r\n\r\n dateInUtc(miliSeconds) {\r\n var date = new Date(miliSeconds)\r\n var utc = new Date(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth(),\r\n date.getUTCDate(),\r\n date.getUTCHours(),\r\n date.getUTCMinutes(),\r\n date.getUTCSeconds()\r\n )\r\n return utc\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.visualization-row {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\r\n}\r\n\r\n.visualization-col {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n}\r\n\r\n.visualization-divider {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\r\n}\r\n\r\n.visualization-divider.vertical {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\r\n}\r\n\r\n.visualization-card {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\r\n}\r\n\r\n.visualization-justify-center,\r\n/deep/ .visualization-justify-center {\r\n justify-content: center;\r\n}\r\n\r\n.visualization-align-center {\r\n align-items: center;\r\n}\r\n\r\n#visualization-container {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\r\n}\r\n#visualization-container > .card {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\r\n}\r\n\r\n#command-bar,\r\n#info-bar {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\r\n}\r\n#command-bar button {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\r\n}\r\n\r\n#command-bar button:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n#command-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#command-bar {\r\n padding: 0 !important;\r\n}\r\n\r\n#info-bar {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\r\n}\r\n\r\n.settings-container {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n}\r\n\r\n.settings-container > * {\r\n margin: 0 2px;\r\n cursor: pointer;\r\n}\r\n\r\n#info-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#info-bar .divider {\r\n margin: 0 8px;\r\n}\r\n\r\nsvg:focus {\r\n border: none;\r\n}\r\n\r\n.visualization-card {\r\n border-left: 8px solid #eee;\r\n}\r\n\r\n.active-tab {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\r\n}\r\n\r\n[id^='frame-'] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\r\n}\r\n\r\n.tooltip {\r\n display: block !important;\r\n z-index: 10000;\r\n}\r\n\r\n.tooltip .tooltip-inner {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\r\n}\r\n\r\n.tooltip .tooltip-arrow {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\r\n}\r\n\r\n.tooltip[x-placement^='top'] {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='top'] .tooltip-arrow {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] {\r\n margin-top: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] .tooltip-arrow {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='right'] {\r\n margin-left: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='right'] .tooltip-arrow {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip[x-placement^='left'] {\r\n margin-right: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='left'] .tooltip-arrow {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip.popover .popover-inner {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\r\n}\r\n\r\n.tooltip.popover .popover-arrow {\r\n border-color: #f9f9f9;\r\n}\r\n\r\n.tooltip[aria-hidden='true'] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\r\n}\r\n\r\n.tooltip[aria-hidden='false'] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\r\n}\r\n</style>\r\n"]}, media: undefined });
2700
+ inject("data-v-25cfa24c_0", { source: "\n.visualization-row[data-v-25cfa24c] {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\n}\n.visualization-col[data-v-25cfa24c] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\n}\n.visualization-divider[data-v-25cfa24c] {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\n}\n.visualization-divider.vertical[data-v-25cfa24c] {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\n}\n.visualization-card[data-v-25cfa24c] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\n}\n.visualization-justify-center[data-v-25cfa24c],[data-v-25cfa24c] .visualization-justify-center {\r\n justify-content: center;\n}\n.visualization-align-center[data-v-25cfa24c] {\r\n align-items: center;\n}\n#visualization-container[data-v-25cfa24c] {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\n}\n#visualization-container > .card[data-v-25cfa24c] {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\n}\n#command-bar[data-v-25cfa24c],\r\n#info-bar[data-v-25cfa24c] {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n#command-bar button[data-v-25cfa24c] {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\n}\n#command-bar button[data-v-25cfa24c]:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\n}\n#command-bar svg[data-v-25cfa24c] {\r\n font-size: 16px;\n}\n#command-bar[data-v-25cfa24c] {\r\n padding: 0 !important;\n}\n#info-bar[data-v-25cfa24c] {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\n}\n.settings-container[data-v-25cfa24c] {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\n}\n.settings-container > *[data-v-25cfa24c] {\r\n margin: 0 2px;\r\n cursor: pointer;\n}\n#info-bar svg[data-v-25cfa24c] {\r\n font-size: 16px;\n}\n#info-bar .divider[data-v-25cfa24c] {\r\n margin: 0 8px;\n}\nsvg[data-v-25cfa24c]:focus {\r\n border: none;\n}\n.visualization-card[data-v-25cfa24c] {\r\n border-left: 8px solid #eee;\n}\n.active-tab[data-v-25cfa24c] {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\n}\n[id^='frame-'][data-v-25cfa24c] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\n}\n.tooltip[data-v-25cfa24c] {\r\n display: block !important;\r\n z-index: 10000;\n}\n.tooltip .tooltip-inner[data-v-25cfa24c] {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\n}\n.tooltip .tooltip-arrow[data-v-25cfa24c] {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\n}\n.tooltip[x-placement^='top'][data-v-25cfa24c] {\r\n margin-bottom: 5px;\n}\n.tooltip[x-placement^='top'] .tooltip-arrow[data-v-25cfa24c] {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='bottom'][data-v-25cfa24c] {\r\n margin-top: 5px;\n}\n.tooltip[x-placement^='bottom'] .tooltip-arrow[data-v-25cfa24c] {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='right'][data-v-25cfa24c] {\r\n margin-left: 5px;\n}\n.tooltip[x-placement^='right'] .tooltip-arrow[data-v-25cfa24c] {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip[x-placement^='left'][data-v-25cfa24c] {\r\n margin-right: 5px;\n}\n.tooltip[x-placement^='left'] .tooltip-arrow[data-v-25cfa24c] {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip.popover .popover-inner[data-v-25cfa24c] {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\n}\n.tooltip.popover .popover-arrow[data-v-25cfa24c] {\r\n border-color: #f9f9f9;\n}\n.tooltip[aria-hidden='true'][data-v-25cfa24c] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\n}\n.tooltip[aria-hidden='false'][data-v-25cfa24c] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\components\\Infos.vue"],"names":[],"mappings":";AA6MA;EACA,aAAA;EACA,eAAA;EACA,cAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;AACA;AAEA;EACA,cAAA;EACA,cAAA;EACA,WAAA;EACA,eAAA;EACA,UAAA;EACA,mBAAA;EACA,mBAAA;EACA,wBAAA;EACA,iCAAA;EACA,SAAA;AACA;AAEA;EACA,mBAAA;EACA,wBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,cAAA;EACA,2BAAA;EACA,UAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;EACA,WAAA;EACA,4DAAA;EACA,yBAAA;EACA;qCACA;AACA;AAEA;EAEA,uBAAA;AACA;AAEA;EACA,mBAAA;AACA;AAEA;EACA,0BAAA;EACA,yBAAA;EACA,YAAA;EACA,mBAAA;AACA;AACA;EACA,2BAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;AACA;AAEA;;EAEA,yBAAA;EACA;mCACA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;EACA,+BAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,eAAA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,2BAAA;AACA;AAEA;EACA,aAAA;EACA,eAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,YAAA;AACA;AAEA;EACA,2BAAA;AACA;AAEA;EACA,8DAAA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;AACA;AAEA;EACA,yBAAA;EACA,cAAA;AACA;AAEA;EACA,wCAAA;EACA,YAAA;EACA,mBAAA;EACA,qBAAA;AACA;AAEA;EACA,QAAA;EACA,SAAA;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,0CAAA;EACA,UAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,2CAAA;EACA,YAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,wCAAA;EACA,SAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,wCAAA;EACA,2CAAA;EACA,UAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,iBAAA;AACA;AAEA;EACA,2BAAA;EACA,wCAAA;EACA,0CAAA;EACA,2CAAA;EACA,WAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,mBAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,uCAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,kBAAA;EACA,UAAA;EACA,2CAAA;AACA;AAEA;EACA,mBAAA;EACA,UAAA;EACA,yBAAA;AACA","file":"Infos.vue","sourcesContent":["<template>\r\n <div\r\n id=\"info-bar\"\r\n class=\"visualization-col\"\r\n :style=\"\r\n !commandsShow ? 'border-top-right-radius: 6px; padding: 0' : 'padding: 0'\r\n \"\r\n >\r\n <div\r\n class=\"visualization-row visualization-justify-center visualization-align-center\"\r\n style=\"position: relative; padding: 4px\"\r\n >\r\n <span> {{ playbackRate }}x </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.selected', {\r\n seconds: hourEnd && hourIni ? hourEnd - hourIni + 1 : 0,\r\n hour_ini: convertToAudienceTime(hourIni),\r\n hour_end: convertToAudienceTime(hourEnd),\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.interval', {\r\n seconds: secondsPerFrame,\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n <span>\r\n {{\r\n $t('infoBar.block', {\r\n time1: convertToAudienceTime(blockStartTime),\r\n time2: convertToAudienceTime(blockTotalTime),\r\n })\r\n }}\r\n </span>\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n {{ framesPerRow * numberOfRows }}\r\n <hr class=\"visualization-divider vertical\" style=\"margin: 0 8px\" />\r\n {{ framesPerRow + '*' + numberOfRows }}\r\n <span\r\n class=\"visualization-divider vertical\"\r\n v-if=\"!cache\"\r\n style=\"margin: 0 8px\"\r\n />\r\n <span v-if=\"!cache\">\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-exclamation-circle\"\r\n style=\"margin: 0 4px\"\r\n />\r\n <strong>{{ $t('infoBar.notUsingCache') }}</strong>\r\n </span>\r\n \r\n <div class=\"settings-container\">\r\n <font-awesome-icon\r\n v-show=\"showStretchFrame\"\r\n :icon=\"!stretchFrames ? ['fas', 'fa-maximize'] : ['fas', 'fa-minimize']\"\r\n @click=\"stretchFrames = !stretchFrames; $emit('update-stretch-frames', stretchFrames)\"\r\n v-tooltip=\"$t('infoBar.stretchFrames')\"\r\n />\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-server\"\r\n @click=\"$emit('change-server')\"\r\n v-tooltip=\"\r\n alternativeServer\r\n ? $t('infoBar.changeServer')\r\n : $t('infoBar.changeServer')\r\n \"\r\n />\r\n <font-awesome-icon\r\n :icon=\"commandsShow ? 'fa-solid fa-eye' : 'fa-solid fa-eye-slash'\"\r\n @click=\"$emit('toogle-commands-visibility')\"\r\n v-tooltip=\"\r\n commandsShow\r\n ? $t('moduletelentry.showButtons')\r\n : $t('moduletelentry.hideButtons')\r\n \"\r\n />\r\n <font-awesome-icon\r\n :icon=\"cache ? 'fa-solid fa-ban' : 'fa-solid fa-sync'\"\r\n @click=\"$emit('toogle-cache')\"\r\n v-tooltip=\"\r\n cache ? $t('infoBar.disableCache') : $t('infoBar.activateCache')\r\n \"\r\n />\r\n </div>\r\n </div>\r\n\r\n <div\r\n v-if=\"alternativeServer\"\r\n class=\"visualization-row visualization-justify-center visualization-align-center\"\r\n style=\"\r\n color: white;\r\n background-color: orange;\r\n font-weight: bold;\r\n padding: 4px;\r\n \"\r\n >\r\n {{ $t('infoBar.alternativeServer') }}\r\n <font-awesome-icon\r\n icon=\"fa-solid fa-exclamation-triangle\"\r\n style=\"margin: 0 4px\"\r\n />\r\n </div>\r\n </div>\r\n</template>\r\n<script>\r\nexport default {\r\n props: {\r\n playbackRate: {\r\n type: Number,\r\n required: true,\r\n },\r\n secondsPerFrame: {\r\n type: Number,\r\n required: true,\r\n },\r\n commandsShow: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n cache: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n blockStartTime: {\r\n type: Number,\r\n required: true,\r\n },\r\n videoTotalDuration: {\r\n type: Number,\r\n required: true,\r\n },\r\n alternativeServer: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n framesPerRow: {\r\n type: Number,\r\n required: true,\r\n },\r\n numberOfRows: {\r\n type: Number,\r\n required: true,\r\n },\r\n hourIni: {\r\n type: [Number, Boolean],\r\n },\r\n hourEnd: {\r\n type: [Number, Boolean],\r\n },\r\n showStretchFrame: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n \r\n },\r\n data() {\r\n return {\r\n stretchFrames: false,\r\n }\r\n },\r\n computed: {\r\n blockTotalTime() {\r\n return this.videoTotalDuration + this.blockStartTime\r\n },\r\n },\r\n methods: {\r\n convertToAudienceTime(time, separator = ':') {\r\n const limit = Date.UTC(null, null, null, 23, 59, 59) / 1000\r\n\r\n let hour = this.dateInUtc(time * 1000)\r\n .toTimeString()\r\n .split(' ')[0]\r\n .split(':')\r\n .map(Number)\r\n\r\n if (time > limit && time <= limit + this.startAudienceSeconds) {\r\n hour[0] = 24 + hour[0]\r\n }\r\n return hour\r\n .map((part) => (part > 9 ? part.toString() : '0' + part))\r\n .join(separator)\r\n },\r\n\r\n dateInUtc(miliSeconds) {\r\n var date = new Date(miliSeconds)\r\n var utc = new Date(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth(),\r\n date.getUTCDate(),\r\n date.getUTCHours(),\r\n date.getUTCMinutes(),\r\n date.getUTCSeconds()\r\n )\r\n return utc\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.visualization-row {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\r\n}\r\n\r\n.visualization-col {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n}\r\n\r\n.visualization-divider {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\r\n}\r\n\r\n.visualization-divider.vertical {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\r\n}\r\n\r\n.visualization-card {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\r\n}\r\n\r\n.visualization-justify-center,\r\n/deep/ .visualization-justify-center {\r\n justify-content: center;\r\n}\r\n\r\n.visualization-align-center {\r\n align-items: center;\r\n}\r\n\r\n#visualization-container {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\r\n}\r\n#visualization-container > .card {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\r\n}\r\n\r\n#command-bar,\r\n#info-bar {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\r\n}\r\n#command-bar button {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\r\n}\r\n\r\n#command-bar button:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n#command-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#command-bar {\r\n padding: 0 !important;\r\n}\r\n\r\n#info-bar {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\r\n}\r\n\r\n.settings-container {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n}\r\n\r\n.settings-container > * {\r\n margin: 0 2px;\r\n cursor: pointer;\r\n}\r\n\r\n#info-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#info-bar .divider {\r\n margin: 0 8px;\r\n}\r\n\r\nsvg:focus {\r\n border: none;\r\n}\r\n\r\n.visualization-card {\r\n border-left: 8px solid #eee;\r\n}\r\n\r\n.active-tab {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\r\n}\r\n\r\n[id^='frame-'] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\r\n}\r\n\r\n.tooltip {\r\n display: block !important;\r\n z-index: 10000;\r\n}\r\n\r\n.tooltip .tooltip-inner {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\r\n}\r\n\r\n.tooltip .tooltip-arrow {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\r\n}\r\n\r\n.tooltip[x-placement^='top'] {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='top'] .tooltip-arrow {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] {\r\n margin-top: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] .tooltip-arrow {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='right'] {\r\n margin-left: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='right'] .tooltip-arrow {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip[x-placement^='left'] {\r\n margin-right: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='left'] .tooltip-arrow {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip.popover .popover-inner {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\r\n}\r\n\r\n.tooltip.popover .popover-arrow {\r\n border-color: #f9f9f9;\r\n}\r\n\r\n.tooltip[aria-hidden='true'] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\r\n}\r\n\r\n.tooltip[aria-hidden='false'] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\r\n}\r\n</style>\r\n"]}, media: undefined });
2613
2701
 
2614
2702
  };
2615
2703
  /* scoped */
2616
- const __vue_scope_id__$3 = "data-v-848911da";
2704
+ const __vue_scope_id__$3 = "data-v-25cfa24c";
2617
2705
  /* module identifier */
2618
2706
  const __vue_module_identifier__$3 = undefined;
2619
2707
  /* functional template */
@@ -4038,6 +4126,10 @@ var script = {
4038
4126
  type: Boolean,
4039
4127
  default: false,
4040
4128
  },
4129
+ showStretchFrame: {
4130
+ type: Boolean,
4131
+ default: false,
4132
+ },
4041
4133
  },
4042
4134
  components: {
4043
4135
  Frame: __vue_component__$5,
@@ -4098,6 +4190,7 @@ var script = {
4098
4190
  shiftFrames: 0,
4099
4191
  aspectRatio: 11 / 9,
4100
4192
  showCustomInputs: false,
4193
+ stretchFrame: false,
4101
4194
  }
4102
4195
  },
4103
4196
  async created() {
@@ -4569,7 +4662,6 @@ var script = {
4569
4662
  }
4570
4663
  },
4571
4664
  selectFrame(index, frame) {
4572
- console.log(index, frame);
4573
4665
  const d = this.getDateParts();
4574
4666
  const limit = Date.UTC(d.year, d.month, d.day, 23, 59, 59) / 1000;
4575
4667
  const frameTime = frame?.time;
@@ -4988,6 +5080,9 @@ var script = {
4988
5080
  }
4989
5081
  });
4990
5082
  },
5083
+ stretchFrame() {
5084
+ this.$nextTick(this.resize);
5085
+ },
4991
5086
  },
4992
5087
  };
4993
5088
 
@@ -5301,6 +5396,7 @@ var __vue_render__ = function () {
5301
5396
  "max-steps": _vm.maxSteps,
5302
5397
  "shift-frames": _vm.shiftFrames,
5303
5398
  customGridSize: _vm.customGridSize,
5399
+ stretchFrames: _vm.stretchFrame,
5304
5400
  },
5305
5401
  on: {
5306
5402
  "change-playback-rate": function (value) {
@@ -5402,6 +5498,7 @@ var __vue_render__ = function () {
5402
5498
  "number-of-rows": _vm.numberOfRows,
5403
5499
  "hour-ini": _vm.hourIniSelected,
5404
5500
  "hour-end": _vm.hourEndSelected,
5501
+ "show-stretch-frame": _vm.showStretchFrame,
5405
5502
  },
5406
5503
  on: {
5407
5504
  "toogle-commands-visibility": _vm.toogleCommandsVisibility,
@@ -5409,6 +5506,9 @@ var __vue_render__ = function () {
5409
5506
  _vm.useCache = !_vm.useCache;
5410
5507
  },
5411
5508
  "change-server": _vm.changeServerClick,
5509
+ "update-stretch-frames": function (value) {
5510
+ return (_vm.stretchFrame = value)
5511
+ },
5412
5512
  },
5413
5513
  }),
5414
5514
  _vm._v(" "),
@@ -5418,7 +5518,7 @@ var __vue_render__ = function () {
5418
5518
  {
5419
5519
  key: "row-" + rowNumber,
5420
5520
  staticClass: "visualization-row",
5421
- staticStyle: { padding: "1px 5px" },
5521
+ staticStyle: { padding: "0px 4px" },
5422
5522
  attrs: { id: "row-" + rowNumber },
5423
5523
  },
5424
5524
  [
@@ -5471,24 +5571,6 @@ var __vue_render__ = function () {
5471
5571
  return _c(
5472
5572
  "div",
5473
5573
  {
5474
- directives: [
5475
- {
5476
- name: "memo",
5477
- rawName: "v-memo",
5478
- value: [
5479
- frame.time,
5480
- _vm.getIndex(
5481
- rowNumber,
5482
- frameNumber,
5483
- _vm.Positions.current
5484
- ) === _vm.activeFrame,
5485
- frame.time === _vm.hourIniSelected,
5486
- frame.time === _vm.hourEndSelected,
5487
- ],
5488
- expression:
5489
- "[\n frame.time,\n getIndex(rowNumber, frameNumber, Positions.current) === activeFrame,\n frame.time === hourIniSelected,\n frame.time === hourEndSelected,\n ]",
5490
- },
5491
- ],
5492
5574
  key:
5493
5575
  "row-" +
5494
5576
  rowNumber +
@@ -5580,6 +5662,7 @@ var __vue_render__ = function () {
5580
5662
  videoControls: _vm.videoControls,
5581
5663
  "playback-rate": _vm.playbackRate,
5582
5664
  "aspect-ratio": _vm.aspectRatio,
5665
+ stretchFrame: _vm.stretchFrame,
5583
5666
  },
5584
5667
  on: {
5585
5668
  startPlaying: _vm.startPlaying,
@@ -5610,11 +5693,11 @@ __vue_render__._withStripped = true;
5610
5693
  /* style */
5611
5694
  const __vue_inject_styles__ = function (inject) {
5612
5695
  if (!inject) return
5613
- inject("data-v-11fd896a_0", { source: "\n.visualization-row[data-v-11fd896a] {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\n}\n.visualization-col[data-v-11fd896a] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 5px;\n}\n.visualization-divider[data-v-11fd896a] {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\n}\n.visualization-divider.vertical[data-v-11fd896a] {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\n}\n.visualization-card[data-v-11fd896a] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\n}\n.visualization-justify-center[data-v-11fd896a],\r\n*[data-v-11fd896a] .visualization-justify-center {\r\n justify-content: center;\n}\n.visualization-align-center[data-v-11fd896a] {\r\n align-items: center;\n}\n#visualization-container[data-v-11fd896a] {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\n}\n#visualization-container > .card[data-v-11fd896a] {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\n}\n#command-bar[data-v-11fd896a],\r\n#info-bar[data-v-11fd896a] {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n#command-bar button[data-v-11fd896a] {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\n}\n#command-bar button[data-v-11fd896a]:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\n}\n#command-bar svg[data-v-11fd896a] {\r\n font-size: 16px;\n}\n#command-bar[data-v-11fd896a] {\r\n padding: 0 !important;\n}\n#info-bar[data-v-11fd896a] {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\n}\n.settings-container[data-v-11fd896a] {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\n}\n.settings-container > *[data-v-11fd896a] {\r\n margin: 0 2px;\r\n cursor: pointer;\n}\n#info-bar svg[data-v-11fd896a] {\r\n font-size: 16px;\n}\n#info-bar .divider[data-v-11fd896a] {\r\n margin: 0 8px;\n}\nsvg[data-v-11fd896a]:focus {\r\n border: none;\n}\n.visualization-card[data-v-11fd896a] {\r\n border-left: 8px solid #eee;\n}\n.active-tab[data-v-11fd896a] {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\n}\n[id^='frame-'][data-v-11fd896a] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\n}\n.tooltip[data-v-11fd896a] {\r\n display: block !important;\r\n z-index: 10000;\n}\n.tooltip .tooltip-inner[data-v-11fd896a] {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\n}\n.tooltip .tooltip-arrow[data-v-11fd896a] {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\n}\n.tooltip[x-placement^='top'][data-v-11fd896a] {\r\n margin-bottom: 5px;\n}\n.tooltip[x-placement^='top'] .tooltip-arrow[data-v-11fd896a] {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='bottom'][data-v-11fd896a] {\r\n margin-top: 5px;\n}\n.tooltip[x-placement^='bottom'] .tooltip-arrow[data-v-11fd896a] {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='right'][data-v-11fd896a] {\r\n margin-left: 5px;\n}\n.tooltip[x-placement^='right'] .tooltip-arrow[data-v-11fd896a] {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip[x-placement^='left'][data-v-11fd896a] {\r\n margin-right: 5px;\n}\n.tooltip[x-placement^='left'] .tooltip-arrow[data-v-11fd896a] {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip.popover .popover-inner[data-v-11fd896a] {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\n}\n.tooltip.popover .popover-arrow[data-v-11fd896a] {\r\n border-color: #f9f9f9;\n}\n.tooltip[aria-hidden='true'][data-v-11fd896a] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\n}\n.tooltip[aria-hidden='false'][data-v-11fd896a] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\Visualization.vue"],"names":[],"mappings":";AA8wCA;EACA,aAAA;EACA,eAAA;EACA,cAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,YAAA;AACA;AAEA;EACA,cAAA;EACA,cAAA;EACA,WAAA;EACA,eAAA;EACA,UAAA;EACA,mBAAA;EACA,mBAAA;EACA,wBAAA;EACA,iCAAA;EACA,SAAA;AACA;AAEA;EACA,mBAAA;EACA,wBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,cAAA;EACA,2BAAA;EACA,UAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;EACA,WAAA;EACA,4DAAA;EACA,yBAAA;EACA;qCACA;AACA;AAEA;;EAEA,uBAAA;AACA;AAEA;EACA,mBAAA;AACA;AAEA;EACA,0BAAA;EACA,yBAAA;EACA,YAAA;EACA,mBAAA;AACA;AACA;EACA,2BAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;AACA;AAEA;;EAEA,yBAAA;EACA;mCACA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;EACA,+BAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,eAAA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,2BAAA;AACA;AAEA;EACA,aAAA;EACA,eAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,YAAA;AACA;AAEA;EACA,2BAAA;AACA;AAEA;EACA,8DAAA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;AACA;AAEA;EACA,yBAAA;EACA,cAAA;AACA;AAEA;EACA,wCAAA;EACA,YAAA;EACA,mBAAA;EACA,qBAAA;AACA;AAEA;EACA,QAAA;EACA,SAAA;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,0CAAA;EACA,UAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,2CAAA;EACA,YAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,wCAAA;EACA,SAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,wCAAA;EACA,2CAAA;EACA,UAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,iBAAA;AACA;AAEA;EACA,2BAAA;EACA,wCAAA;EACA,0CAAA;EACA,2CAAA;EACA,WAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,mBAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,uCAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,kBAAA;EACA,UAAA;EACA,2CAAA;AACA;AAEA;EACA,mBAAA;EACA,UAAA;EACA,yBAAA;AACA","file":"Visualization.vue","sourcesContent":["<template>\r\n <div\r\n class=\"visualization-row\"\r\n id=\"visualization-container\"\r\n @click=\"framesClicked\">\r\n <GlobalEvents\r\n v-if=\"!readOnly && canInsertTime && settingsClosed\"\r\n :filter=\"(event) => !event.shiftKey && !event.ctrlKey\"\r\n @keydown.45=\"insertTime\" />\r\n <GlobalEvents\r\n v-if=\"!readOnly && active && settingsClosed\"\r\n @keydown.83.prevent=\"setHourIni\"\r\n @keydown.69.prevent=\"setHourEnd\" />\r\n <GlobalEvents\r\n v-if=\"active && settingsClosed\"\r\n @keydown.left.prevent=\"arrowLeft\"\r\n @keydown.right.prevent=\"arrowRight\"\r\n @keydown.up.prevent=\"arrowUp\"\r\n @keydown.down.prevent=\"arrowDown\"\r\n @keydown.shift.page-down.prevent=\"nextLoopActivate\"\r\n @keydown.page-down.prevent=\"() => next()\"\r\n @keydown.page-up.prevent=\"() => prev()\"\r\n @keydown.shift.page-up.prevent=\"prevLoopActivate\"\r\n @keydown.36.prevent=\"goToFirstFrame\"\r\n @keydown.35.prevent=\"goToLastFrame\"\r\n @keydown.71.prevent=\"dialogs.goTo = true\"\r\n @keydown.73.prevent=\"dialogs.secondsPerFrame = true\"\r\n @keydown.76.prevent=\"dialogs.frames = true\"\r\n @keydown.49.97=\"() => (secondsPerFrame = 1)\"\r\n @keydown.50.98=\"() => (secondsPerFrame = 2)\"\r\n @keydown.51.99=\"() => (secondsPerFrame = 3)\"\r\n @keydown.52.100=\"() => (secondsPerFrame = 4)\"\r\n @keydown.53.101=\"() => (secondsPerFrame = 5)\" />\r\n <GlobalEvents\r\n v-if=\"prevLoop || nextLoop\"\r\n @keydown=\"breakLoop\"\r\n v-on:click=\"breakLoop\" />\r\n <settings\r\n v-if=\"active\"\r\n :dialogs-visibility=\"dialogs\"\r\n :playback-rate=\"playbackRate\"\r\n :seconds-per-frame=\"secondsPerFrame\"\r\n :frames-per-row=\"framesPerRow\"\r\n :number-of-rows=\"numberOfRows\"\r\n :max-steps=\"maxSteps\"\r\n :shift-frames=\"shiftFrames\"\r\n :customGridSize=\"customGridSize\"\r\n @change-playback-rate=\"(value) => (playbackRate = value)\"\r\n @change-go-to=\"changeHour\"\r\n @change-seconds-per-frame=\"(value) => (secondsPerFrame = value)\"\r\n @change-shift-frames=\"(value) => (shiftFrames = value)\"\r\n @set-frames-selection=\"setFrameSelection\"\r\n @set-custom-grid-values=\"setCustomGridValues\"\r\n @close=\"(dialog) => (dialogs[dialog] = false)\" />\r\n <div\r\n :class=\"{ 'visualization-card': true, 'active-tab': active }\"\r\n style=\"width: 100%; padding: 0\">\r\n <command-bar\r\n v-show=\"commandBarShow\"\r\n :read-only=\"readOnly\"\r\n :video-playing=\"videoPlaying\"\r\n :video-paused=\"paused\"\r\n :insert-time=\"canInsertTime\"\r\n :hour-ini-selected=\"!!hourIniSelected\"\r\n :hour-end-selected=\"!!hourEndSelected\"\r\n @prev-loop-activate=\"prevLoopActivate\"\r\n @next-loop-activate=\"nextLoopActivate\"\r\n @prev=\"prev\"\r\n @next=\"next\"\r\n @go-to=\"dialogs.goTo = true\"\r\n @open-frame-selection=\"dialogs.frames = true\"\r\n @open-frames-per-second=\"dialogs.secondsPerFrame = true\"\r\n @open-blocks=\"openBlocks\"\r\n @open-playback-rate=\"dialogs.playbackRate = true\"\r\n @play-or-pause=\"playOrPause\"\r\n @stop-playing=\"stopPlayingBar\"\r\n @set-hour-ini=\"setHourIni\"\r\n @set-hour-end=\"setHourEnd\"\r\n @insert-time=\"insertTime\"\r\n @shift-frames=\"dialogs.shiftFrames = true\" />\r\n <video-progress\r\n v-if=\"videoProgressBar\"\r\n v-show=\"videoPlaying\"\r\n :video-time=\"videoTime\" />\r\n <info-bar\r\n :playback-rate=\"playbackRate\"\r\n :seconds-per-frame=\"secondsPerFrame\"\r\n :commands-show=\"commandBarShow\"\r\n :cache=\"useCache\"\r\n :block-start-time=\"blockStartTime\"\r\n :video-total-duration=\"videoSliderTotalDuration\"\r\n :alternative-server=\"alternativeServer\"\r\n :frames-per-row=\"framesPerRow\"\r\n :number-of-rows=\"numberOfRows\"\r\n :hour-ini=\"hourIniSelected\"\r\n :hour-end=\"hourEndSelected\"\r\n @toogle-commands-visibility=\"toogleCommandsVisibility\"\r\n @toogle-cache=\"useCache = !useCache\"\r\n @change-server=\"changeServerClick\" />\r\n <div\r\n class=\"visualization-row\"\r\n v-for=\"rowNumber in numberOfRows\"\r\n :id=\"'row-' + rowNumber\"\r\n :key=\"'row-' + rowNumber\"\r\n style=\"padding: 1px 5px\">\r\n <div\r\n v-for=\"(frame, frameNumber) in previousFrames\"\r\n :key=\"\r\n numberOfRows +\r\n '-' +\r\n framesPerRow +\r\n '-' +\r\n getIndex(rowNumber, frameNumber, Positions.previous)\r\n \"\r\n style=\"display: none\">\r\n <span v-html=\"frame.img\" />\r\n </div>\r\n <div\r\n v-for=\"(frame, frameNumber) in nextFrames\"\r\n :key=\"\r\n numberOfRows +\r\n '-' +\r\n framesPerRow +\r\n '-' +\r\n getIndex(rowNumber, frameNumber, Positions.next)\r\n \"\r\n style=\"display: none\">\r\n <span v-html=\"frame.img\" />\r\n </div>\r\n <div\r\n class=\"visualization-col\"\r\n v-for=\"(frame, frameNumber) in frames.slice(\r\n framesPerRow * (rowNumber - 1),\r\n framesPerRow * rowNumber\r\n )\"\r\n v-memo=\"[\r\n frame.time,\r\n getIndex(rowNumber, frameNumber, Positions.current) === activeFrame,\r\n frame.time === hourIniSelected,\r\n frame.time === hourEndSelected,\r\n ]\"\r\n :key=\"'row-' + rowNumber + '-frame-' + frameNumber + '-' + frame.time\"\r\n :id=\"`frame-${getIndex(rowNumber, frameNumber, Positions.current)}`\"\r\n :class=\"{ loaderImg: !!frame.img }\"\r\n @click=\"\r\n frame.time\r\n ? selectFrame(\r\n getIndex(rowNumber, frameNumber, Positions.current),\r\n frame\r\n )\r\n : null\r\n \">\r\n <span :id=\"activeFrame ? 'aa' : 0\" style=\"text-align: center\">\r\n <b>\r\n {{\r\n getAudienceTime(\r\n frame.time,\r\n rowNumber,\r\n frameNumber,\r\n Positions.current\r\n )\r\n }}\r\n </b>\r\n </span>\r\n\r\n <frame\r\n ref=\"frames\"\r\n :frame=\"frame\"\r\n :index=\"getIndex(rowNumber, frameNumber, Positions.current)\"\r\n :grid-settings=\"{ numberOfRows, framesPerRow }\"\r\n :initialTime=\"frame.time === hourIniSelected\"\r\n :endTime=\"frame.time === hourEndSelected\"\r\n :betweenTime=\"\r\n frame.time > hourIniSelected && frame.time < hourEndSelected\r\n \"\r\n :active=\"\r\n getIndex(rowNumber, frameNumber, Positions.current) ===\r\n activeFrame\r\n \"\r\n :activeTab=\"active\"\r\n :videoUrl=\"fInterface ? fInterface.getVideoUrl(frame) : ''\"\r\n :videoControls=\"videoControls\"\r\n @startPlaying=\"startPlaying\"\r\n @stopPlaying=\"stopPlaying\"\r\n @playPauseStatus=\"changePlayPause\"\r\n @updateSlider=\"updateSlider\"\r\n :playback-rate=\"playbackRate\"\r\n :aspect-ratio=\"aspectRatio\"\r\n style=\"margin: 0 auto\"></frame>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- <settings\r\n ref=\"settings2\"\r\n :active=\"active\"\r\n @goToTime=\"changeHour\"\r\n @goToBlockInterval=\"changeBlockInterval\"\r\n @setSplitTime=\"setSplitTime\"\r\n @setFrameSelection=\"setFrameSelection\"\r\n @setPlaybackRate=\"\r\n (rate) => {\r\n playbackRate = rate\r\n }\r\n \"\r\n >\r\n </settings> -->\r\n <!-- <v-dialog v-model=\"dialog\" width=\"500\">\r\n <div class=\"card\">\r\n <div class=\"card\"-title class=\"text-h5 grey lighten-2\">\r\n {{ ' Último bloco disponível até: ' }}\r\n <v-btn\r\n @click=\"goToStartBlock\"\r\n class=\"ml-2\"\r\n dark\r\n color=\"success\"\r\n depressed\r\n >\r\n <v-icon left> fa-clock </v-icon>\r\n {{ timeLastBlock }}\r\n </v-btn>\r\n <v-spacer></v-spacer>\r\n <v-btn color=\"error\" fab small class=\"ml-5\" @click=\"dialog = false\">\r\n <v-icon dark> fa fa-xmark </v-icon>\r\n </v-btn>\r\n </div-title>\r\n </div>\r\n </v-dialog>\r\n <Help :media=\"media\" @close=\"media = null\" />\r\n <v-dialog\r\n v-if=\"userMultiTabsGrid\"\r\n v-model=\"userMultiTabsGridsModel\"\r\n persistent\r\n width=\"60%\"\r\n >\r\n <div class=\"card\">\r\n <div class=\"card\"-title class=\"warning text-h5\" primary-title>\r\n <div class=\"row\" class=\"ma-0\" justify=\"center\" align=\"center\">\r\n <v-icon dark left style=\"font-size: 24px !important\">\r\n fa fa-exclamation-triangle\r\n </v-icon>\r\n <div style=\"color: white\">{{ $t('form.alert') }}</div>\r\n </div>\r\n </div-title>\r\n <div class=\"card\"-text class=\"justify-center pa-6 grey lighten-2\">\r\n <h3>\r\n {{ $t('alerts.userMultiTabsGrid') }}\r\n </h3>\r\n </div-text>\r\n <hr class=\"divider\" class=\"grey lighten-1\"></span>\r\n <div class=\"card\"-actions class=\"grey lighten-2 justify-center\">\r\n <v-btn color=\"error\" ml-5 @click=\"userMultiTabsGrid = false\">\r\n <v-icon left color=\"white\">fa fa-times</v-icon>\r\n {{ $t('form.close') }}\r\n </v-btn>\r\n </div-actions>\r\n </div>\r\n </v-dialog> -->\r\n </div>\r\n</template>\r\n<script>\r\nimport Frame from './components/Frame.vue'\r\nimport FramesInterface from './utils/FramesInterface.js'\r\nimport FramesService from './services/FramesService.js'\r\n\r\nimport Commands from './components/Commands.vue'\r\nimport Infos from './components/Infos.vue'\r\nimport VideoProgress from './components/VideoProgress.vue'\r\nimport Settings from './components/Settings.vue'\r\n\r\nconst Positions = Object.freeze({\r\n previous: 0,\r\n current: 1,\r\n next: 2,\r\n})\r\n\r\nexport default {\r\n name: 'visualization-container',\r\n props: {\r\n value: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n date: {\r\n type: String,\r\n required: true,\r\n },\r\n channel: {\r\n type: Number,\r\n required: true,\r\n },\r\n startAudienceTime: {\r\n type: String,\r\n required: true,\r\n },\r\n endAudienceTime: {\r\n type: String,\r\n required: true,\r\n },\r\n videoProgressBar: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n jumpOnInsert: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n removeSelectionOnInsert: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n framesFormat: {\r\n type: [Number, String],\r\n default: 7,\r\n },\r\n maxSize: {\r\n type: Number,\r\n },\r\n videoControls: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n readOnly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n maxSteps: {\r\n type: Number,\r\n default: 1,\r\n },\r\n customGridSize: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n components: {\r\n Frame,\r\n CommandBar: Commands,\r\n InfoBar: Infos,\r\n VideoProgress,\r\n Settings,\r\n // Help,\r\n },\r\n data() {\r\n return {\r\n Positions,\r\n updatingChannel: null,\r\n dialog: false,\r\n timeLastBlock: null,\r\n alternativeServer: false,\r\n useCache: true,\r\n numberOfRows: 1,\r\n framesPerRow: 5,\r\n secondsPerFrame: 1,\r\n fInterface: null,\r\n velocity: 1,\r\n frames: [],\r\n previousFrames: [],\r\n nextFrames: [],\r\n channelCode: 0,\r\n videoPlaying: false,\r\n activeFrame: null,\r\n activeVideo: null,\r\n videoTime: 0,\r\n videoTotalTime: null,\r\n progressVideoDrag: false,\r\n hourIniSelected: false,\r\n hourEndSelected: false,\r\n canInsertTime: false,\r\n lastHeight: 0,\r\n loopInterval: null,\r\n nextLoop: false,\r\n prevLoop: false,\r\n videoSliderTotalDuration: 900,\r\n blockStartTime: null,\r\n media: null,\r\n changeServer: false,\r\n userMultiTabsGrid: false,\r\n userMultiTabsGridsModel: true,\r\n playbackRate: 1,\r\n paused: false,\r\n commandBarShow: true,\r\n dialogs: {\r\n playbackRate: false,\r\n goTo: false,\r\n secondsPerFrame: false,\r\n frames: false,\r\n shiftFrames: false,\r\n },\r\n lastNext: 0,\r\n lastPrev: 0,\r\n shiftFrames: 0,\r\n aspectRatio: 11 / 9,\r\n showCustomInputs: false,\r\n }\r\n },\r\n async created() {\r\n this.changeServer = this.serverOfFrames === 'alternative'\r\n this.alternativeServer = this.serverOfFrames === 'alternative'\r\n\r\n const settings = [\r\n {\r\n framesPerRow: 1,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 2,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 2,\r\n },\r\n {\r\n //Custom (item 11)\r\n framesPerRow: 7,\r\n numberOfRows: 3,\r\n },\r\n ]\r\n\r\n // Os valores custom são guardados no local storage e não na base de dados\r\n const customValues = JSON.parse(localStorage.getItem('customGridValues'))\r\n\r\n if (this.framesFormat == '11' && !!customValues) {\r\n this.numberOfRows = customValues[0]\r\n this.framesPerRow = customValues[1]\r\n } else {\r\n const storedOnDb = settings[parseInt(this.framesFormat) - 1]\r\n this.framesPerRow = storedOnDb.framesPerRow\r\n this.numberOfRows = storedOnDb.numberOfRows\r\n }\r\n\r\n await this.createFramesInterface()\r\n this.$nextTick(this.resize)\r\n },\r\n methods: {\r\n stopVideoPlaying(array) {\r\n for (const frame of array || this.$refs.frames) {\r\n if (\r\n frame.videoStatus === frame.Status.playing ||\r\n frame.videoStatus === frame.Status.paused\r\n ) {\r\n frame.stop(false)\r\n }\r\n }\r\n this.activeVideo = null\r\n },\r\n toogleCommandsVisibility() {\r\n this.commandBarShow = !this.commandBarShow\r\n this.$nextTick(this.resize)\r\n },\r\n framesClicked(e) {\r\n if (e.target.parentNode.id != 'insert') {\r\n this.active = true\r\n }\r\n },\r\n async goToStartBlock() {\r\n try {\r\n const d = new Date()\r\n let timestamp = Date.UTC(\r\n d.getFullYear(),\r\n d.getMonth(),\r\n d.getDate(),\r\n d.getHours(),\r\n d.getMinutes(),\r\n d.getSeconds()\r\n )\r\n\r\n const response = (\r\n await FramesService.getNextAvailableBlock({\r\n channel: this.channel,\r\n time: timestamp / 1000,\r\n })\r\n ).data\r\n\r\n this.dialog = false\r\n this.changeHour(this.convertToAudienceTime(response.data.start, ':'))\r\n } catch (err) {\r\n // console.error(err)\r\n }\r\n },\r\n async checkAvailableBlock() {\r\n try {\r\n const d = new Date()\r\n let timestamp = Date.UTC(\r\n d.getFullYear(),\r\n d.getMonth(),\r\n d.getDate(),\r\n d.getHours(),\r\n d.getMinutes(),\r\n d.getSeconds()\r\n )\r\n\r\n const response = (\r\n await FramesService.getNextAvailableBlock({\r\n channel: this.channel,\r\n time: timestamp / 1000,\r\n })\r\n ).data\r\n\r\n this.timeLastBlock = this.convertToAudienceTime(response.data.end, ':')\r\n this.dialog = true\r\n if (!response.status) {\r\n this.timeLastBlock = 'N/D'\r\n }\r\n } catch (err) {\r\n // console.error(err)\r\n }\r\n },\r\n updateSlider(videoStartTime, time) {\r\n // * atualizar slider se estiver fora do range definido previamente\r\n if (\r\n time < this.blockStartTime ||\r\n time > this.blockStartTime ||\r\n videoStartTime > this.blockStartTime + this.videoSliderTotalDuration\r\n ) {\r\n this.blockStartTime = videoStartTime\r\n this.videoSliderTotalDuration = 900\r\n }\r\n },\r\n nextLoopActivate() {\r\n this.breakLoop()\r\n this.loopInterval = setInterval(\r\n () => this.next({ ignoreTime: true }),\r\n this.swapImagesDelay\r\n )\r\n setTimeout(() => {\r\n this.nextLoop = true\r\n }, 0)\r\n },\r\n prevLoopActivate() {\r\n this.breakLoop()\r\n this.loopInterval = setInterval(\r\n () => this.prev({ ignoreTime: true }),\r\n this.swapImagesDelay\r\n )\r\n setTimeout(() => {\r\n this.prevLoop = true\r\n }, 0)\r\n },\r\n breakLoop() {\r\n clearInterval(this.loopInterval)\r\n this.loopInterval = null\r\n this.nextLoop = false\r\n this.prevLoop = false\r\n },\r\n changePlayPause(status) {\r\n this.paused = !status\r\n },\r\n resize(height = this.lastHeight) {\r\n this.lastHeight = height\r\n if (this.$refs.frames) {\r\n for (let frame of this.$refs.frames) {\r\n frame.resize(height)\r\n }\r\n }\r\n this.$emit('resized')\r\n },\r\n async goToFirstFrame() {\r\n let frames = this.$refs.frames\r\n\r\n let audienceTime = null\r\n if (frames.length > 0) {\r\n let frame = frames[0].frame\r\n audienceTime = this.getAudienceTime(frame.time, 0, 0, 0)\r\n }\r\n if (audienceTime) {\r\n const [hours, minutes, seconds] = audienceTime.split(':')\r\n const totalSeconds =\r\n parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds)\r\n if (totalSeconds >= 9000)\r\n this.changeHour(this.getLastFirtsBlockTime(audienceTime, true))\r\n else this.changeHour(this.getLastFirtsBlockTime('02:30:00', true))\r\n }\r\n },\r\n async goToLastFrame() {\r\n let frames = this.$refs.frames\r\n let audienceTime = null\r\n if (frames.length > 0) {\r\n let frame = frames[0].frame\r\n\r\n audienceTime = this.getAudienceTime(frame.time, 0, 0, 0)\r\n }\r\n if (audienceTime) {\r\n this.changeHour(this.getLastFirtsBlockTime(audienceTime))\r\n }\r\n },\r\n getLastFirtsBlockTime(time, first = false) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n let h, m, newTime\r\n const t = time.match(/.{1,2}/g)\r\n if (t[0] && t[1]) {\r\n h = parseInt(t[0])\r\n m = parseInt(t[1])\r\n }\r\n if (h < 26) {\r\n if (m < 15)\r\n if (first) newTime = t[0] + ':00:00'\r\n else newTime = t[0] + ':14:59'\r\n else if (m < 30)\r\n if (first) newTime = t[0] + ':15:00'\r\n else newTime = t[0] + ':29:59'\r\n else if (m < 45)\r\n if (first) newTime = t[0] + ':30:00'\r\n else newTime = t[0] + ':44:59'\r\n else if (first) newTime = t[0] + ':45:00'\r\n else newTime = t[0] + ':59:59'\r\n } else {\r\n if (m < 15)\r\n if (first) newTime = '26:00:00'\r\n else newTime = '26:14:59'\r\n else {\r\n if (first) newTime = '26:15:00'\r\n else newTime = '26:29:59'\r\n }\r\n }\r\n return newTime\r\n },\r\n openBlocks() {\r\n this.$refs.settings2?.openBlocks()\r\n },\r\n playOrPause() {\r\n const array = this.$refs.frames.filter((fc) => !!fc.active)\r\n if (array.length === 1) {\r\n const frame = array[0]\r\n frame.playOrPause(this.playbackRate)\r\n }\r\n },\r\n stopPlayingBar() {\r\n for (let ref of this.$refs.frames) {\r\n if (\r\n ref.videoStatus === ref.Status.playing ||\r\n ref.videoStatus === ref.Status.paused\r\n ) {\r\n ref.stop(false)\r\n }\r\n }\r\n },\r\n async setFrameSelection(selected) {\r\n this.frames = this.loadingArray\r\n const settings = [\r\n {\r\n framesPerRow: 1,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 2,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 2,\r\n },\r\n {\r\n //Custom (item 11)\r\n framesPerRow: 7,\r\n numberOfRows: 3,\r\n },\r\n ]\r\n\r\n const formatSelected = settings[selected - 1]\r\n this.framesPerRow = formatSelected.framesPerRow\r\n this.numberOfRows = formatSelected.numberOfRows\r\n\r\n await this.fInterface.changeSize(this.numberOfRows, this.framesPerRow)\r\n this.getFramesArray()\r\n this.$nextTick(this.resize)\r\n this.$emit('frames-format-changed', selected)\r\n },\r\n async setCustomGridValues(customValues) {\r\n this.numberOfRows = customValues[0]\r\n this.framesPerRow = customValues[1]\r\n localStorage.setItem('customGridValues', JSON.stringify(customValues))\r\n await this.fInterface.changeSize(this.numberOfRows, this.framesPerRow)\r\n this.getFramesArray()\r\n this.$nextTick(this.resize)\r\n this.$emit('frames-format-changed', 11)\r\n },\r\n getFramesArray() {\r\n this.frames = this.fInterface.getFrames(Positions.current)\r\n this.nextFrames = this.fInterface.getFrames(Positions.next)\r\n this.previousFrames = this.fInterface.getFrames(Positions.previous)\r\n\r\n const div = document.createElement('div')\r\n div.innerHTML = this.frames[0].image\r\n const newAspectRatio =\r\n div.getElementsByTagName('img')[0]?.naturalWidth /\r\n div.getElementsByTagName('img')[0]?.naturalHeight\r\n\r\n this.aspectRatio = isNaN(newAspectRatio)\r\n ? this.aspectRatio\r\n : newAspectRatio\r\n\r\n this.$nextTick(this.resize)\r\n\r\n const frame = this.frames.find((f) => f.blockStart)\r\n if (frame && this.alternativeServer) {\r\n this.$emit(\r\n 'new-block',\r\n frame.title?.match(/[0-9]{3}\\/(?:[0-9]+_?)+/)[0]\r\n )\r\n }\r\n },\r\n async createFramesInterface(startTime = this.startAudienceTime) {\r\n this.frames = this.loadingArray\r\n // let ch = this.channel\r\n // let associationTMP = {\r\n // 1735073: 1,\r\n // 1735074: 139,\r\n // 1735075: 3,\r\n // 1735076: 132,\r\n // }\r\n // //\r\n // this.channelCode = associationTMP[ch] ? associationTMP[ch] : ch\r\n\r\n const t = startTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const time = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n // * iniciar slider\r\n this.blockStartTime = time\r\n this.fInterface = await new FramesInterface(\r\n this.channel,\r\n this.numberOfRows,\r\n this.framesPerRow,\r\n time,\r\n this.startAudienceTime,\r\n this.useCache,\r\n this.shiftFrames\r\n )\r\n await this.fInterface.init()\r\n\r\n this.getFramesArray()\r\n\r\n const div = document.createElement('div')\r\n div.innerHTML = this.frames[0].image\r\n\r\n this.aspectRatio =\r\n div.getElementsByTagName('img')[0].naturalWidth /\r\n div.getElementsByTagName('img')[0].naturalHeight\r\n\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.activeVideo = null\r\n },\r\n getIndex(rowNumber, frameIndex, position) {\r\n const baseOffset = this.framesPerRow * this.numberOfRows * position\r\n const rowOffset = (rowNumber - 1) * this.framesPerRow\r\n return baseOffset + rowOffset + frameIndex\r\n },\r\n getAudienceTime(frameTime, rowNumber, frameNumber, position) {\r\n if (!frameTime) {\r\n return 'Loading...'\r\n } else if (\r\n this.getIndex(rowNumber, frameNumber, position) === this.activeVideo\r\n ) {\r\n return this.convertToAudienceTime(this.videoTime)\r\n } else {\r\n return this.convertToAudienceTime(frameTime)\r\n }\r\n },\r\n dateInUtc(miliSeconds) {\r\n var date = new Date(miliSeconds)\r\n var utc = new Date(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth(),\r\n date.getUTCDate(),\r\n date.getUTCHours(),\r\n date.getUTCMinutes(),\r\n date.getUTCSeconds()\r\n )\r\n return utc\r\n },\r\n convertToAudienceTime(time, separator = ':') {\r\n const d = this.getDateParts()\r\n const limit = Date.UTC(d.year, d.month, d.day, 23, 59, 59) / 1000\r\n\r\n let hour = this.dateInUtc(time * 1000)\r\n .toTimeString()\r\n .split(' ')[0]\r\n .split(':')\r\n .map(Number)\r\n\r\n if (time > limit && time <= limit + this.startAudienceSeconds) {\r\n hour[0] = 24 + hour[0]\r\n }\r\n return hour\r\n .map((part) => (part > 9 ? part.toString() : '0' + part))\r\n .join(separator)\r\n },\r\n getDateParts(date = this.date) {\r\n const data = /(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})/.exec(\r\n date\r\n )?.groups\r\n if (data) {\r\n return {\r\n year: parseInt(data.year),\r\n month: parseInt(data.month) - 1,\r\n day: parseInt(data.day),\r\n }\r\n }\r\n return {\r\n year: null,\r\n month: null,\r\n day: null,\r\n }\r\n },\r\n selectFrame(index, frame) {\r\n console.log(index, frame)\r\n const d = this.getDateParts()\r\n const limit = Date.UTC(d.year, d.month, d.day, 23, 59, 59) / 1000\r\n const frameTime = frame?.time\r\n\r\n if (frameTime - (this.startAudienceSeconds + limit) <= 0) {\r\n if (this.hourIniSelected === true) {\r\n this.hourIniSelected = frameTime\r\n\r\n if (\r\n this.hourEndSelected &&\r\n this.hourIniSelected > this.hourEndSelected\r\n ) {\r\n this.hourEndSelected = false\r\n }\r\n } else if (this.hourEndSelected === true) {\r\n if (frameTime > this.hourIniSelected) {\r\n this.hourEndSelected = frameTime\r\n this.canInsertTime = true\r\n } else {\r\n this.hourEndSelected = false\r\n }\r\n }\r\n }\r\n\r\n if (this.activeFrame !== index) {\r\n // ? Se clicar no frame diferente de onde está a dar play, faz pausa\r\n const array = this.$refs.frames.filter(\r\n (fc) => fc.videoStatus === fc.Status.playing\r\n )\r\n if (array.length === 1) {\r\n const frame = array[0]\r\n frame.playOrPause()\r\n }\r\n this.activeVideo = null\r\n this.activeFrame = index\r\n }\r\n },\r\n setHourIni() {\r\n this.canInsertTime = true\r\n this.hourIniSelected = true\r\n document.getElementById(`frame-${this.activeFrame}`).click()\r\n this.$emit('setHourIni', {\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n })\r\n },\r\n setHourEnd() {\r\n this.canInsertTime = true\r\n this.hourEndSelected = true\r\n document.getElementById(`frame-${this.activeFrame}`).click()\r\n },\r\n //* Navegação\r\n arrowRight() {\r\n if (this.checkLimitRight(false)) {\r\n if (\r\n this.activeFrame ===\r\n this.numberOfRows * this.framesPerRow * 2 - 1\r\n ) {\r\n this.next()\r\n } else {\r\n this.activeFrame++\r\n }\r\n }\r\n },\r\n arrowLeft() {\r\n if (this.checkLimitLeft(false)) {\r\n if (this.activeFrame === this.numberOfRows * this.framesPerRow) {\r\n this.prev({ stayOnLast: true })\r\n } else {\r\n this.activeFrame--\r\n }\r\n }\r\n },\r\n arrowUp() {\r\n const relativePosition =\r\n this.activeFrame - this.numberOfRows * this.framesPerRow\r\n const currentRow = Math.floor(relativePosition / this.framesPerRow)\r\n if (currentRow > 0) {\r\n this.activeFrame -= this.framesPerRow\r\n }\r\n },\r\n\r\n arrowDown() {\r\n const relativePosition =\r\n this.activeFrame - this.numberOfRows * this.framesPerRow\r\n const currentRow = Math.floor(relativePosition / this.framesPerRow)\r\n\r\n if (currentRow < this.numberOfRows - 1) {\r\n this.activeFrame += this.framesPerRow\r\n }\r\n },\r\n checkLimitRight(value) {\r\n const hours = this.endAudienceTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const high = Date.UTC(\r\n d.year,\r\n d.month,\r\n d.day,\r\n hours[0],\r\n parseInt(hours[1]) + 30,\r\n hours[2]\r\n )\r\n\r\n if (value) {\r\n return (\r\n high >\r\n (this.fInterface.getCurrentTime() +\r\n this.numberOfRows * this.framesPerRow -\r\n 1) *\r\n 1000\r\n )\r\n } else {\r\n return high > this.fInterface.getCurrentTime() * 1000\r\n }\r\n },\r\n checkLimitLeft(value) {\r\n const hours = this.startAudienceTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const low = Date.UTC(d.year, d.month, d.day, hours[0], hours[1], hours[2])\r\n\r\n if (value) {\r\n return low <= (this.fInterface.getCurrentTime() - 1) * 1000\r\n } else {\r\n return (\r\n low <\r\n (this.fInterface.getCurrentTime() +\r\n this.activeFrame -\r\n this.numberOfRows * this.framesPerRow) *\r\n 1000\r\n )\r\n }\r\n },\r\n async next(config = {}) {\r\n if (\r\n (config.ignoreTime ||\r\n Date.now() - this.lastNext > this.swapImagesDelay) &&\r\n this.checkLimitRight(true) &&\r\n !this.navigationPending\r\n ) {\r\n this.navigationPending = true\r\n this.stopVideoPlaying()\r\n\r\n this.navigationPending = await new Promise((resolve) => {\r\n this.fInterface\r\n .loadNextFrames()\r\n .then(() => {\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.getFramesArray()\r\n this.lastNext = Date.now()\r\n resolve(false)\r\n })\r\n .catch(() => {\r\n resolve(false)\r\n })\r\n })\r\n } else {\r\n // console.error('next blocked')\r\n }\r\n },\r\n async prev(config = {}) {\r\n if (\r\n (config.ignoreTime ||\r\n Date.now() - this.lastPrev > this.swapImagesDelay) &&\r\n this.checkLimitLeft(true) &&\r\n !this.navigationPending\r\n ) {\r\n this.navigationPending = true\r\n this.stopVideoPlaying()\r\n\r\n this.navigationPending = await new Promise((resolve) => {\r\n this.fInterface\r\n .loadPrevFrames()\r\n .then(() => {\r\n if (config.stayOnLast) {\r\n this.activeFrame = this.getIndex(\r\n this.numberOfRows,\r\n this.framesPerRow - 1,\r\n Positions.current\r\n )\r\n } else {\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n }\r\n\r\n this.getFramesArray()\r\n this.lastPrev = Date.now()\r\n resolve(false)\r\n })\r\n .catch(() => {\r\n resolve(false)\r\n })\r\n })\r\n } else {\r\n // console.error('prev blocked')\r\n }\r\n },\r\n async setStartTime(time) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n const t = time.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const setTime = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n // this.frames = this.loadingArray\r\n\r\n await this.fInterface.changeTime(setTime)\r\n\r\n this.getFramesArray()\r\n\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.activeVideo = null\r\n\r\n return true\r\n },\r\n hourToTimeStamp(time) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n const t = time.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const setTime = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n\r\n return setTime\r\n },\r\n changeHour(value) {\r\n if (value) {\r\n return new Promise((resolve) => {\r\n setTimeout(async () => {\r\n this.stopVideoPlaying()\r\n\r\n await this.setStartTime(value, true)\r\n resolve()\r\n }, 0)\r\n })\r\n }\r\n },\r\n changeBlockInterval(value) {\r\n this.changeHour(value.ini)\r\n let time_ini, time_end\r\n time_ini = this.hourToTimeStamp(value.ini)\r\n time_end = this.hourToTimeStamp(value.end)\r\n this.videoSliderTotalDuration = time_end - time_ini\r\n this.$refs.frames[0].changeSettings(time_ini)\r\n this.blockStartTime = time_ini\r\n },\r\n //eslint-disable-next-line\r\n async updateVideoTime(index, videoTime) {\r\n this.activeVideo = index\r\n this.videoTime = videoTime\r\n },\r\n //eslint-disable-next-line\r\n updateVideoStatus(currentTime) {\r\n if (!this.progressVideoDrag) {\r\n // ESTA FUNÇÃO PASSOU PARA DENTRO DOS COMMANDS\r\n // this.updateProgress(null, currentTime)\r\n }\r\n },\r\n async startPlaying(frame, totalTime) {\r\n const array = this.$refs.frames.filter(\r\n (fc) => fc.frame.time !== frame.time\r\n )\r\n this.stopVideoPlaying(array)\r\n\r\n this.videoTotalTime = totalTime\r\n this.videoPlaying = true\r\n },\r\n stopPlaying() {\r\n this.videoTotalTime = null\r\n this.videoPlaying = false\r\n this.paused = false\r\n },\r\n insertTime() {\r\n this.$emit('timeToInsert', {\r\n channel: this.channel,\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n hour_end: this.hourEndSelected\r\n ? this.convertToAudienceTime(this.hourEndSelected, '')\r\n : null,\r\n force: false,\r\n })\r\n\r\n if (this.jumpOnInsert) {\r\n this.changeHour(\r\n this.convertToAudienceTime(\r\n this.hourEndSelected || this.hourIniSelected\r\n )\r\n ).then(() => {\r\n this.activeFrame = this.getIndex(1, 1, Positions.current)\r\n })\r\n }\r\n\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = null\r\n this.hourEndSelected = null\r\n this.canInsertTime = false\r\n }\r\n },\r\n insertTimeForce() {\r\n this.$emit('timeToInsert', {\r\n channel: this.channel,\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n hour_end: this.hourEndSelected\r\n ? this.convertToAudienceTime(this.hourEndSelected, '')\r\n : null,\r\n force: true,\r\n })\r\n\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = null\r\n this.hourEndSelected = null\r\n this.canInsertTime = false\r\n }\r\n },\r\n async getChannelMedia() {\r\n // this.media = (await ChannelService.show(this.channel)).data.MEDIA\r\n },\r\n async changeServerClick() {\r\n this.changeServer = !this.changeServer\r\n this.alternativeServer = this.changeServer\r\n\r\n sessionStorage.setItem(\r\n 'server',\r\n this.changeServer ? 'alternative' : 'default'\r\n )\r\n\r\n await this.createFramesInterface(\r\n this.convertToAudienceTime(\r\n this.$refs.frames.find((frame) => frame.index === this.activeFrame)\r\n .frame.time,\r\n ''\r\n )\r\n )\r\n\r\n this.$nextTick(this.resize)\r\n },\r\n },\r\n computed: {\r\n swapImagesDelay() {\r\n return 0\r\n // return this.numberOfRows * this.framesPerRow * 15\r\n },\r\n active: {\r\n get() {\r\n return this.value\r\n },\r\n set(value) {\r\n this.$emit('input', value)\r\n },\r\n },\r\n settingsClosed() {\r\n return !Object.values(this.dialogs).find((v) => v)\r\n },\r\n startAudienceSeconds() {\r\n const t = this.startAudienceTime.match(/.{1,2}/g)\r\n return parseInt(t[0] * 3600 + t[1] * 60 + t[2])\r\n },\r\n loadingArray() {\r\n return Array.from(Array(this.numberOfRows * this.framesPerRow).keys())\r\n },\r\n serverOfFrames() {\r\n return sessionStorage.getItem('server')\r\n },\r\n },\r\n beforeDestroy() {\r\n sessionStorage.setItem('server', 'default')\r\n },\r\n watch: {\r\n async secondsPerFrame() {\r\n const activeF =\r\n this.frames[this.activeFrame - this.numberOfRows * this.framesPerRow]\r\n\r\n if (activeF) {\r\n this.changeHour(this.getAudienceTime(activeF.time, 0, 0, 0))\r\n this.fInterface.setCurrentStep(this.secondsPerFrame)\r\n await this.fInterface.loadFrames()\r\n this.getFramesArray()\r\n }\r\n },\r\n async shiftFrames() {\r\n this.createFramesInterface()\r\n },\r\n framesFormat(value) {\r\n this.setFrameSelection(value)\r\n },\r\n active() {\r\n // ? sempre que trocamos de tabs dar reset as horas selected\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = false\r\n this.hourEndSelected = false\r\n }\r\n },\r\n useCache() {\r\n this.createFramesInterface()\r\n },\r\n hourIniSelected(value) {\r\n if (value) {\r\n sessionStorage.setItem(\r\n 'currentTimeFrames',\r\n this.convertToAudienceTime(this.hourIniSelected, '')\r\n )\r\n } else {\r\n sessionStorage.removeItem('currentTimeFrames')\r\n }\r\n },\r\n activeFrame(value) {\r\n if (value) {\r\n this.stopPlayingBar()\r\n }\r\n },\r\n channel() {\r\n this.updatingChannel = new Promise((resolve, reject) => {\r\n try {\r\n this.createFramesInterface()\r\n resolve(true)\r\n } catch (err) {\r\n reject(err)\r\n }\r\n })\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.visualization-row {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\r\n}\r\n\r\n.visualization-col {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 5px;\r\n}\r\n\r\n.visualization-divider {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\r\n}\r\n\r\n.visualization-divider.vertical {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\r\n}\r\n\r\n.visualization-card {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\r\n}\r\n\r\n.visualization-justify-center,\r\n* >>> .visualization-justify-center {\r\n justify-content: center;\r\n}\r\n\r\n.visualization-align-center {\r\n align-items: center;\r\n}\r\n\r\n#visualization-container {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\r\n}\r\n#visualization-container > .card {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\r\n}\r\n\r\n#command-bar,\r\n#info-bar {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\r\n}\r\n#command-bar button {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\r\n}\r\n\r\n#command-bar button:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n#command-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#command-bar {\r\n padding: 0 !important;\r\n}\r\n\r\n#info-bar {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\r\n}\r\n\r\n.settings-container {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n}\r\n\r\n.settings-container > * {\r\n margin: 0 2px;\r\n cursor: pointer;\r\n}\r\n\r\n#info-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#info-bar .divider {\r\n margin: 0 8px;\r\n}\r\n\r\nsvg:focus {\r\n border: none;\r\n}\r\n\r\n.visualization-card {\r\n border-left: 8px solid #eee;\r\n}\r\n\r\n.active-tab {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\r\n}\r\n\r\n[id^='frame-'] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\r\n}\r\n\r\n.tooltip {\r\n display: block !important;\r\n z-index: 10000;\r\n}\r\n\r\n.tooltip .tooltip-inner {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\r\n}\r\n\r\n.tooltip .tooltip-arrow {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\r\n}\r\n\r\n.tooltip[x-placement^='top'] {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='top'] .tooltip-arrow {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] {\r\n margin-top: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] .tooltip-arrow {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='right'] {\r\n margin-left: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='right'] .tooltip-arrow {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip[x-placement^='left'] {\r\n margin-right: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='left'] .tooltip-arrow {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip.popover .popover-inner {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\r\n}\r\n\r\n.tooltip.popover .popover-arrow {\r\n border-color: #f9f9f9;\r\n}\r\n\r\n.tooltip[aria-hidden='true'] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\r\n}\r\n\r\n.tooltip[aria-hidden='false'] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\r\n}\r\n</style>\r\n"]}, media: undefined });
5696
+ inject("data-v-a861684a_0", { source: "\n.visualization-row[data-v-a861684a] {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\n}\n.visualization-col[data-v-a861684a] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 5px;\n}\n.visualization-divider[data-v-a861684a] {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\n}\n.visualization-divider.vertical[data-v-a861684a] {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\n}\n.visualization-card[data-v-a861684a] {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\n}\n.visualization-justify-center[data-v-a861684a],\r\n*[data-v-a861684a] .visualization-justify-center {\r\n justify-content: center;\n}\n.visualization-align-center[data-v-a861684a] {\r\n align-items: center;\n}\n#visualization-container[data-v-a861684a] {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\n}\n#visualization-container > .card[data-v-a861684a] {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\n}\n#command-bar[data-v-a861684a],\r\n#info-bar[data-v-a861684a] {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\n}\n#command-bar button[data-v-a861684a] {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\n}\n#command-bar button[data-v-a861684a]:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\n}\n#command-bar svg[data-v-a861684a] {\r\n font-size: 16px;\n}\n#command-bar[data-v-a861684a] {\r\n padding: 0 !important;\n}\n#info-bar[data-v-a861684a] {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\n}\n.settings-container[data-v-a861684a] {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\n}\n.settings-container > *[data-v-a861684a] {\r\n margin: 0 2px;\r\n cursor: pointer;\n}\n#info-bar svg[data-v-a861684a] {\r\n font-size: 16px;\n}\n#info-bar .divider[data-v-a861684a] {\r\n margin: 0 8px;\n}\nsvg[data-v-a861684a]:focus {\r\n border: none;\n}\n.visualization-card[data-v-a861684a] {\r\n border-left: 8px solid #eee;\n}\n.active-tab[data-v-a861684a] {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\n}\n[id^='frame-'][data-v-a861684a] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\n}\n.tooltip[data-v-a861684a] {\r\n display: block !important;\r\n z-index: 10000;\n}\n.tooltip .tooltip-inner[data-v-a861684a] {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\n}\n.tooltip .tooltip-arrow[data-v-a861684a] {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\n}\n.tooltip[x-placement^='top'][data-v-a861684a] {\r\n margin-bottom: 5px;\n}\n.tooltip[x-placement^='top'] .tooltip-arrow[data-v-a861684a] {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='bottom'][data-v-a861684a] {\r\n margin-top: 5px;\n}\n.tooltip[x-placement^='bottom'] .tooltip-arrow[data-v-a861684a] {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\n}\n.tooltip[x-placement^='right'][data-v-a861684a] {\r\n margin-left: 5px;\n}\n.tooltip[x-placement^='right'] .tooltip-arrow[data-v-a861684a] {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip[x-placement^='left'][data-v-a861684a] {\r\n margin-right: 5px;\n}\n.tooltip[x-placement^='left'] .tooltip-arrow[data-v-a861684a] {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\n}\n.tooltip.popover .popover-inner[data-v-a861684a] {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\n}\n.tooltip.popover .popover-arrow[data-v-a861684a] {\r\n border-color: #f9f9f9;\n}\n.tooltip[aria-hidden='true'][data-v-a861684a] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\n}\n.tooltip[aria-hidden='false'][data-v-a861684a] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\n}\n.custom-frametime[data-v-a861684a] {\r\n font-size: smaller;\n}\r\n", map: {"version":3,"sources":["C:\\Workspace\\visualization\\src\\Visualization.vue"],"names":[],"mappings":";AAmxCA;EACA,aAAA;EACA,eAAA;EACA,cAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,YAAA;AACA;AAEA;EACA,cAAA;EACA,cAAA;EACA,WAAA;EACA,eAAA;EACA,UAAA;EACA,mBAAA;EACA,mBAAA;EACA,wBAAA;EACA,iCAAA;EACA,SAAA;AACA;AAEA;EACA,mBAAA;EACA,wBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,cAAA;EACA,2BAAA;EACA,UAAA;AACA;AAEA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EACA,aAAA;EACA,WAAA;EACA,4DAAA;EACA,yBAAA;EACA;qCACA;AACA;AAEA;;EAEA,uBAAA;AACA;AAEA;EACA,mBAAA;AACA;AAEA;EACA,0BAAA;EACA,yBAAA;EACA,YAAA;EACA,mBAAA;AACA;AACA;EACA,2BAAA;EACA,eAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;AACA;AAEA;;EAEA,yBAAA;EACA;mCACA;AACA;AACA;EACA,WAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;EACA,+BAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,eAAA;EACA,kBAAA;AACA;AAEA;EACA,kBAAA;EACA,WAAA;EACA,QAAA;EACA,2BAAA;AACA;AAEA;EACA,aAAA;EACA,eAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,aAAA;AACA;AAEA;EACA,YAAA;AACA;AAEA;EACA,2BAAA;AACA;AAEA;EACA,8DAAA;EACA,qBAAA;AACA;AAEA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;AACA;AAEA;EACA,yBAAA;EACA,cAAA;AACA;AAEA;EACA,wCAAA;EACA,YAAA;EACA,mBAAA;EACA,qBAAA;AACA;AAEA;EACA,QAAA;EACA,SAAA;EACA,mBAAA;EACA,kBAAA;EACA,WAAA;EACA,0CAAA;EACA,UAAA;AACA;AAEA;EACA,kBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,2CAAA;EACA,YAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,eAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,0CAAA;EACA,wCAAA;EACA,SAAA;EACA,qBAAA;EACA,aAAA;EACA,gBAAA;AACA;AAEA;EACA,gBAAA;AACA;AAEA;EACA,2BAAA;EACA,yCAAA;EACA,wCAAA;EACA,2CAAA;EACA,UAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,iBAAA;AACA;AAEA;EACA,2BAAA;EACA,wCAAA;EACA,0CAAA;EACA,2CAAA;EACA,WAAA;EACA,oBAAA;EACA,cAAA;EACA,eAAA;AACA;AAEA;EACA,mBAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,uCAAA;AACA;AAEA;EACA,qBAAA;AACA;AAEA;EACA,kBAAA;EACA,UAAA;EACA,2CAAA;AACA;AAEA;EACA,mBAAA;EACA,UAAA;EACA,yBAAA;AACA;AAEA;EACA,kBAAA;AACA","file":"Visualization.vue","sourcesContent":["<template>\r\n <div\r\n class=\"visualization-row\"\r\n id=\"visualization-container\"\r\n @click=\"framesClicked\">\r\n <GlobalEvents\r\n v-if=\"!readOnly && canInsertTime && settingsClosed\"\r\n :filter=\"(event) => !event.shiftKey && !event.ctrlKey\"\r\n @keydown.45=\"insertTime\" />\r\n <GlobalEvents\r\n v-if=\"!readOnly && active && settingsClosed\"\r\n @keydown.83.prevent=\"setHourIni\"\r\n @keydown.69.prevent=\"setHourEnd\" />\r\n <GlobalEvents\r\n v-if=\"active && settingsClosed\"\r\n @keydown.left.prevent=\"arrowLeft\"\r\n @keydown.right.prevent=\"arrowRight\"\r\n @keydown.up.prevent=\"arrowUp\"\r\n @keydown.down.prevent=\"arrowDown\"\r\n @keydown.shift.page-down.prevent=\"nextLoopActivate\"\r\n @keydown.page-down.prevent=\"() => next()\"\r\n @keydown.page-up.prevent=\"() => prev()\"\r\n @keydown.shift.page-up.prevent=\"prevLoopActivate\"\r\n @keydown.36.prevent=\"goToFirstFrame\"\r\n @keydown.35.prevent=\"goToLastFrame\"\r\n @keydown.71.prevent=\"dialogs.goTo = true\"\r\n @keydown.73.prevent=\"dialogs.secondsPerFrame = true\"\r\n @keydown.76.prevent=\"dialogs.frames = true\"\r\n @keydown.49.97=\"() => (secondsPerFrame = 1)\"\r\n @keydown.50.98=\"() => (secondsPerFrame = 2)\"\r\n @keydown.51.99=\"() => (secondsPerFrame = 3)\"\r\n @keydown.52.100=\"() => (secondsPerFrame = 4)\"\r\n @keydown.53.101=\"() => (secondsPerFrame = 5)\" />\r\n <GlobalEvents\r\n v-if=\"prevLoop || nextLoop\"\r\n @keydown=\"breakLoop\"\r\n v-on:click=\"breakLoop\" />\r\n <settings\r\n v-if=\"active\"\r\n :dialogs-visibility=\"dialogs\"\r\n :playback-rate=\"playbackRate\"\r\n :seconds-per-frame=\"secondsPerFrame\"\r\n :frames-per-row=\"framesPerRow\"\r\n :number-of-rows=\"numberOfRows\"\r\n :max-steps=\"maxSteps\"\r\n :shift-frames=\"shiftFrames\"\r\n :customGridSize=\"customGridSize\"\r\n :stretchFrames=\"stretchFrame\"\r\n @change-playback-rate=\"(value) => (playbackRate = value)\"\r\n @change-go-to=\"changeHour\"\r\n @change-seconds-per-frame=\"(value) => (secondsPerFrame = value)\"\r\n @change-shift-frames=\"(value) => (shiftFrames = value)\"\r\n @set-frames-selection=\"setFrameSelection\"\r\n @set-custom-grid-values=\"setCustomGridValues\"\r\n @close=\"(dialog) => (dialogs[dialog] = false)\" />\r\n <div\r\n :class=\"{ 'visualization-card': true, 'active-tab': active }\"\r\n style=\"width: 100%; padding: 0\">\r\n <command-bar\r\n v-show=\"commandBarShow\"\r\n :read-only=\"readOnly\"\r\n :video-playing=\"videoPlaying\"\r\n :video-paused=\"paused\"\r\n :insert-time=\"canInsertTime\"\r\n :hour-ini-selected=\"!!hourIniSelected\"\r\n :hour-end-selected=\"!!hourEndSelected\"\r\n @prev-loop-activate=\"prevLoopActivate\"\r\n @next-loop-activate=\"nextLoopActivate\"\r\n @prev=\"prev\"\r\n @next=\"next\"\r\n @go-to=\"dialogs.goTo = true\"\r\n @open-frame-selection=\"dialogs.frames = true\"\r\n @open-frames-per-second=\"dialogs.secondsPerFrame = true\"\r\n @open-blocks=\"openBlocks\"\r\n @open-playback-rate=\"dialogs.playbackRate = true\"\r\n @play-or-pause=\"playOrPause\"\r\n @stop-playing=\"stopPlayingBar\"\r\n @set-hour-ini=\"setHourIni\"\r\n @set-hour-end=\"setHourEnd\"\r\n @insert-time=\"insertTime\"\r\n @shift-frames=\"dialogs.shiftFrames = true\" />\r\n <video-progress\r\n v-if=\"videoProgressBar\"\r\n v-show=\"videoPlaying\"\r\n :video-time=\"videoTime\" />\r\n <info-bar\r\n :playback-rate=\"playbackRate\"\r\n :seconds-per-frame=\"secondsPerFrame\"\r\n :commands-show=\"commandBarShow\"\r\n :cache=\"useCache\"\r\n :block-start-time=\"blockStartTime\"\r\n :video-total-duration=\"videoSliderTotalDuration\"\r\n :alternative-server=\"alternativeServer\"\r\n :frames-per-row=\"framesPerRow\"\r\n :number-of-rows=\"numberOfRows\"\r\n :hour-ini=\"hourIniSelected\"\r\n :hour-end=\"hourEndSelected\"\r\n :show-stretch-frame=\"showStretchFrame\"\r\n @toogle-commands-visibility=\"toogleCommandsVisibility\"\r\n @toogle-cache=\"useCache = !useCache\"\r\n @change-server=\"changeServerClick\"\r\n @update-stretch-frames=\"(value) => (stretchFrame = value)\" />\r\n <div\r\n class=\"visualization-row\"\r\n v-for=\"rowNumber in numberOfRows\"\r\n :id=\"'row-' + rowNumber\"\r\n :key=\"'row-' + rowNumber\"\r\n style=\"padding: 0px 4px\">\r\n <div\r\n v-for=\"(frame, frameNumber) in previousFrames\"\r\n :key=\"\r\n numberOfRows +\r\n '-' +\r\n framesPerRow +\r\n '-' +\r\n getIndex(rowNumber, frameNumber, Positions.previous)\r\n \"\r\n style=\"display: none\">\r\n <span v-html=\"frame.img\" />\r\n </div>\r\n <div\r\n v-for=\"(frame, frameNumber) in nextFrames\"\r\n :key=\"\r\n numberOfRows +\r\n '-' +\r\n framesPerRow +\r\n '-' +\r\n getIndex(rowNumber, frameNumber, Positions.next)\r\n \"\r\n style=\"display: none\">\r\n <span v-html=\"frame.img\" />\r\n </div>\r\n <div\r\n class=\"visualization-col\"\r\n v-for=\"(frame, frameNumber) in frames.slice(\r\n framesPerRow * (rowNumber - 1),\r\n framesPerRow * rowNumber\r\n )\"\r\n :key=\"'row-' + rowNumber + '-frame-' + frameNumber + '-' + frame.time\"\r\n :id=\"`frame-${getIndex(rowNumber, frameNumber, Positions.current)}`\"\r\n :class=\"{ loaderImg: !!frame.img }\"\r\n @click=\"\r\n frame.time\r\n ? selectFrame(\r\n getIndex(rowNumber, frameNumber, Positions.current),\r\n frame\r\n )\r\n : null\r\n \">\r\n <span :id=\"activeFrame ? 'aa' : 0\" style=\"text-align: center\">\r\n <b>\r\n {{\r\n getAudienceTime(\r\n frame.time,\r\n rowNumber,\r\n frameNumber,\r\n Positions.current\r\n )\r\n }}\r\n </b>\r\n </span>\r\n\r\n <frame\r\n ref=\"frames\"\r\n :frame=\"frame\"\r\n :index=\"getIndex(rowNumber, frameNumber, Positions.current)\"\r\n :grid-settings=\"{ numberOfRows, framesPerRow }\"\r\n :initialTime=\"frame.time === hourIniSelected\"\r\n :endTime=\"frame.time === hourEndSelected\"\r\n :betweenTime=\"\r\n frame.time > hourIniSelected && frame.time < hourEndSelected\r\n \"\r\n :active=\"\r\n getIndex(rowNumber, frameNumber, Positions.current) ===\r\n activeFrame\r\n \"\r\n :activeTab=\"active\"\r\n :videoUrl=\"fInterface ? fInterface.getVideoUrl(frame) : ''\"\r\n :videoControls=\"videoControls\"\r\n @startPlaying=\"startPlaying\"\r\n @stopPlaying=\"stopPlaying\"\r\n @playPauseStatus=\"changePlayPause\"\r\n @updateSlider=\"updateSlider\"\r\n :playback-rate=\"playbackRate\"\r\n :aspect-ratio=\"aspectRatio\"\r\n :stretchFrame=\"stretchFrame\"\r\n style=\"margin: 0 auto\"></frame>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- <settings\r\n ref=\"settings2\"\r\n :active=\"active\"\r\n @goToTime=\"changeHour\"\r\n @goToBlockInterval=\"changeBlockInterval\"\r\n @setSplitTime=\"setSplitTime\"\r\n @setFrameSelection=\"setFrameSelection\"\r\n @setPlaybackRate=\"\r\n (rate) => {\r\n playbackRate = rate\r\n }\r\n \"\r\n >\r\n </settings> -->\r\n <!-- <v-dialog v-model=\"dialog\" width=\"500\">\r\n <div class=\"card\">\r\n <div class=\"card\"-title class=\"text-h5 grey lighten-2\">\r\n {{ ' Último bloco disponível até: ' }}\r\n <v-btn\r\n @click=\"goToStartBlock\"\r\n class=\"ml-2\"\r\n dark\r\n color=\"success\"\r\n depressed\r\n >\r\n <v-icon left> fa-clock </v-icon>\r\n {{ timeLastBlock }}\r\n </v-btn>\r\n <v-spacer></v-spacer>\r\n <v-btn color=\"error\" fab small class=\"ml-5\" @click=\"dialog = false\">\r\n <v-icon dark> fa fa-xmark </v-icon>\r\n </v-btn>\r\n </div-title>\r\n </div>\r\n </v-dialog>\r\n <Help :media=\"media\" @close=\"media = null\" />\r\n <v-dialog\r\n v-if=\"userMultiTabsGrid\"\r\n v-model=\"userMultiTabsGridsModel\"\r\n persistent\r\n width=\"60%\"\r\n >\r\n <div class=\"card\">\r\n <div class=\"card\"-title class=\"warning text-h5\" primary-title>\r\n <div class=\"row\" class=\"ma-0\" justify=\"center\" align=\"center\">\r\n <v-icon dark left style=\"font-size: 24px !important\">\r\n fa fa-exclamation-triangle\r\n </v-icon>\r\n <div style=\"color: white\">{{ $t('form.alert') }}</div>\r\n </div>\r\n </div-title>\r\n <div class=\"card\"-text class=\"justify-center pa-6 grey lighten-2\">\r\n <h3>\r\n {{ $t('alerts.userMultiTabsGrid') }}\r\n </h3>\r\n </div-text>\r\n <hr class=\"divider\" class=\"grey lighten-1\"></span>\r\n <div class=\"card\"-actions class=\"grey lighten-2 justify-center\">\r\n <v-btn color=\"error\" ml-5 @click=\"userMultiTabsGrid = false\">\r\n <v-icon left color=\"white\">fa fa-times</v-icon>\r\n {{ $t('form.close') }}\r\n </v-btn>\r\n </div-actions>\r\n </div>\r\n </v-dialog> -->\r\n </div>\r\n</template>\r\n<script>\r\nimport Frame from './components/Frame.vue'\r\nimport FramesInterface from './utils/FramesInterface.js'\r\nimport FramesService from './services/FramesService.js'\r\n\r\nimport Commands from './components/Commands.vue'\r\nimport Infos from './components/Infos.vue'\r\nimport VideoProgress from './components/VideoProgress.vue'\r\nimport Settings from './components/Settings.vue'\r\n\r\nconst Positions = Object.freeze({\r\n previous: 0,\r\n current: 1,\r\n next: 2,\r\n})\r\n\r\nexport default {\r\n name: 'visualization-container',\r\n props: {\r\n value: {\r\n type: Boolean,\r\n required: true,\r\n },\r\n date: {\r\n type: String,\r\n required: true,\r\n },\r\n channel: {\r\n type: Number,\r\n required: true,\r\n },\r\n startAudienceTime: {\r\n type: String,\r\n required: true,\r\n },\r\n endAudienceTime: {\r\n type: String,\r\n required: true,\r\n },\r\n videoProgressBar: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n jumpOnInsert: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n removeSelectionOnInsert: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n framesFormat: {\r\n type: [Number, String],\r\n default: 7,\r\n },\r\n maxSize: {\r\n type: Number,\r\n },\r\n videoControls: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n readOnly: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n maxSteps: {\r\n type: Number,\r\n default: 1,\r\n },\r\n customGridSize: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n showStretchFrame: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n components: {\r\n Frame,\r\n CommandBar: Commands,\r\n InfoBar: Infos,\r\n VideoProgress,\r\n Settings,\r\n // Help,\r\n },\r\n data() {\r\n return {\r\n Positions,\r\n updatingChannel: null,\r\n dialog: false,\r\n timeLastBlock: null,\r\n alternativeServer: false,\r\n useCache: true,\r\n numberOfRows: 1,\r\n framesPerRow: 5,\r\n secondsPerFrame: 1,\r\n fInterface: null,\r\n velocity: 1,\r\n frames: [],\r\n previousFrames: [],\r\n nextFrames: [],\r\n channelCode: 0,\r\n videoPlaying: false,\r\n activeFrame: null,\r\n activeVideo: null,\r\n videoTime: 0,\r\n videoTotalTime: null,\r\n progressVideoDrag: false,\r\n hourIniSelected: false,\r\n hourEndSelected: false,\r\n canInsertTime: false,\r\n lastHeight: 0,\r\n loopInterval: null,\r\n nextLoop: false,\r\n prevLoop: false,\r\n videoSliderTotalDuration: 900,\r\n blockStartTime: null,\r\n media: null,\r\n changeServer: false,\r\n userMultiTabsGrid: false,\r\n userMultiTabsGridsModel: true,\r\n playbackRate: 1,\r\n paused: false,\r\n commandBarShow: true,\r\n dialogs: {\r\n playbackRate: false,\r\n goTo: false,\r\n secondsPerFrame: false,\r\n frames: false,\r\n shiftFrames: false,\r\n },\r\n lastNext: 0,\r\n lastPrev: 0,\r\n shiftFrames: 0,\r\n aspectRatio: 11 / 9,\r\n showCustomInputs: false,\r\n stretchFrame: false,\r\n }\r\n },\r\n async created() {\r\n this.changeServer = this.serverOfFrames === 'alternative'\r\n this.alternativeServer = this.serverOfFrames === 'alternative'\r\n\r\n const settings = [\r\n {\r\n framesPerRow: 1,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 2,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 2,\r\n },\r\n {\r\n //Custom (item 11)\r\n framesPerRow: 7,\r\n numberOfRows: 3,\r\n },\r\n ]\r\n\r\n // Os valores custom são guardados no local storage e não na base de dados\r\n const customValues = JSON.parse(localStorage.getItem('customGridValues'))\r\n\r\n if (this.framesFormat == '11' && !!customValues) {\r\n this.numberOfRows = customValues[0]\r\n this.framesPerRow = customValues[1]\r\n } else {\r\n const storedOnDb = settings[parseInt(this.framesFormat) - 1]\r\n this.framesPerRow = storedOnDb.framesPerRow\r\n this.numberOfRows = storedOnDb.numberOfRows\r\n }\r\n\r\n await this.createFramesInterface()\r\n this.$nextTick(this.resize)\r\n },\r\n methods: {\r\n stopVideoPlaying(array) {\r\n for (const frame of array || this.$refs.frames) {\r\n if (\r\n frame.videoStatus === frame.Status.playing ||\r\n frame.videoStatus === frame.Status.paused\r\n ) {\r\n frame.stop(false)\r\n }\r\n }\r\n this.activeVideo = null\r\n },\r\n toogleCommandsVisibility() {\r\n this.commandBarShow = !this.commandBarShow\r\n this.$nextTick(this.resize)\r\n },\r\n framesClicked(e) {\r\n if (e.target.parentNode.id != 'insert') {\r\n this.active = true\r\n }\r\n },\r\n async goToStartBlock() {\r\n try {\r\n const d = new Date()\r\n let timestamp = Date.UTC(\r\n d.getFullYear(),\r\n d.getMonth(),\r\n d.getDate(),\r\n d.getHours(),\r\n d.getMinutes(),\r\n d.getSeconds()\r\n )\r\n\r\n const response = (\r\n await FramesService.getNextAvailableBlock({\r\n channel: this.channel,\r\n time: timestamp / 1000,\r\n })\r\n ).data\r\n\r\n this.dialog = false\r\n this.changeHour(this.convertToAudienceTime(response.data.start, ':'))\r\n } catch (err) {\r\n // console.error(err)\r\n }\r\n },\r\n async checkAvailableBlock() {\r\n try {\r\n const d = new Date()\r\n let timestamp = Date.UTC(\r\n d.getFullYear(),\r\n d.getMonth(),\r\n d.getDate(),\r\n d.getHours(),\r\n d.getMinutes(),\r\n d.getSeconds()\r\n )\r\n\r\n const response = (\r\n await FramesService.getNextAvailableBlock({\r\n channel: this.channel,\r\n time: timestamp / 1000,\r\n })\r\n ).data\r\n\r\n this.timeLastBlock = this.convertToAudienceTime(response.data.end, ':')\r\n this.dialog = true\r\n if (!response.status) {\r\n this.timeLastBlock = 'N/D'\r\n }\r\n } catch (err) {\r\n // console.error(err)\r\n }\r\n },\r\n updateSlider(videoStartTime, time) {\r\n // * atualizar slider se estiver fora do range definido previamente\r\n if (\r\n time < this.blockStartTime ||\r\n time > this.blockStartTime ||\r\n videoStartTime > this.blockStartTime + this.videoSliderTotalDuration\r\n ) {\r\n this.blockStartTime = videoStartTime\r\n this.videoSliderTotalDuration = 900\r\n }\r\n },\r\n nextLoopActivate() {\r\n this.breakLoop()\r\n this.loopInterval = setInterval(\r\n () => this.next({ ignoreTime: true }),\r\n this.swapImagesDelay\r\n )\r\n setTimeout(() => {\r\n this.nextLoop = true\r\n }, 0)\r\n },\r\n prevLoopActivate() {\r\n this.breakLoop()\r\n this.loopInterval = setInterval(\r\n () => this.prev({ ignoreTime: true }),\r\n this.swapImagesDelay\r\n )\r\n setTimeout(() => {\r\n this.prevLoop = true\r\n }, 0)\r\n },\r\n breakLoop() {\r\n clearInterval(this.loopInterval)\r\n this.loopInterval = null\r\n this.nextLoop = false\r\n this.prevLoop = false\r\n },\r\n changePlayPause(status) {\r\n this.paused = !status\r\n },\r\n resize(height = this.lastHeight) {\r\n this.lastHeight = height\r\n if (this.$refs.frames) {\r\n for (let frame of this.$refs.frames) {\r\n frame.resize(height)\r\n }\r\n }\r\n this.$emit('resized')\r\n },\r\n async goToFirstFrame() {\r\n let frames = this.$refs.frames\r\n\r\n let audienceTime = null\r\n if (frames.length > 0) {\r\n let frame = frames[0].frame\r\n audienceTime = this.getAudienceTime(frame.time, 0, 0, 0)\r\n }\r\n if (audienceTime) {\r\n const [hours, minutes, seconds] = audienceTime.split(':')\r\n const totalSeconds =\r\n parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(seconds)\r\n if (totalSeconds >= 9000)\r\n this.changeHour(this.getLastFirtsBlockTime(audienceTime, true))\r\n else this.changeHour(this.getLastFirtsBlockTime('02:30:00', true))\r\n }\r\n },\r\n async goToLastFrame() {\r\n let frames = this.$refs.frames\r\n let audienceTime = null\r\n if (frames.length > 0) {\r\n let frame = frames[0].frame\r\n\r\n audienceTime = this.getAudienceTime(frame.time, 0, 0, 0)\r\n }\r\n if (audienceTime) {\r\n this.changeHour(this.getLastFirtsBlockTime(audienceTime))\r\n }\r\n },\r\n getLastFirtsBlockTime(time, first = false) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n let h, m, newTime\r\n const t = time.match(/.{1,2}/g)\r\n if (t[0] && t[1]) {\r\n h = parseInt(t[0])\r\n m = parseInt(t[1])\r\n }\r\n if (h < 26) {\r\n if (m < 15)\r\n if (first) newTime = t[0] + ':00:00'\r\n else newTime = t[0] + ':14:59'\r\n else if (m < 30)\r\n if (first) newTime = t[0] + ':15:00'\r\n else newTime = t[0] + ':29:59'\r\n else if (m < 45)\r\n if (first) newTime = t[0] + ':30:00'\r\n else newTime = t[0] + ':44:59'\r\n else if (first) newTime = t[0] + ':45:00'\r\n else newTime = t[0] + ':59:59'\r\n } else {\r\n if (m < 15)\r\n if (first) newTime = '26:00:00'\r\n else newTime = '26:14:59'\r\n else {\r\n if (first) newTime = '26:15:00'\r\n else newTime = '26:29:59'\r\n }\r\n }\r\n return newTime\r\n },\r\n openBlocks() {\r\n this.$refs.settings2?.openBlocks()\r\n },\r\n playOrPause() {\r\n const array = this.$refs.frames.filter((fc) => !!fc.active)\r\n if (array.length === 1) {\r\n const frame = array[0]\r\n frame.playOrPause(this.playbackRate)\r\n }\r\n },\r\n stopPlayingBar() {\r\n for (let ref of this.$refs.frames) {\r\n if (\r\n ref.videoStatus === ref.Status.playing ||\r\n ref.videoStatus === ref.Status.paused\r\n ) {\r\n ref.stop(false)\r\n }\r\n }\r\n },\r\n async setFrameSelection(selected) {\r\n this.frames = this.loadingArray\r\n const settings = [\r\n {\r\n framesPerRow: 1,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 2,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 3,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 4,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 5,\r\n numberOfRows: 2,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 1,\r\n },\r\n {\r\n framesPerRow: 6,\r\n numberOfRows: 2,\r\n },\r\n {\r\n //Custom (item 11)\r\n framesPerRow: 7,\r\n numberOfRows: 3,\r\n },\r\n ]\r\n\r\n const formatSelected = settings[selected - 1]\r\n this.framesPerRow = formatSelected.framesPerRow\r\n this.numberOfRows = formatSelected.numberOfRows\r\n\r\n await this.fInterface.changeSize(this.numberOfRows, this.framesPerRow)\r\n this.getFramesArray()\r\n this.$nextTick(this.resize)\r\n this.$emit('frames-format-changed', selected)\r\n },\r\n async setCustomGridValues(customValues) {\r\n this.numberOfRows = customValues[0]\r\n this.framesPerRow = customValues[1]\r\n localStorage.setItem('customGridValues', JSON.stringify(customValues))\r\n await this.fInterface.changeSize(this.numberOfRows, this.framesPerRow)\r\n this.getFramesArray()\r\n this.$nextTick(this.resize)\r\n this.$emit('frames-format-changed', 11)\r\n },\r\n getFramesArray() {\r\n this.frames = this.fInterface.getFrames(Positions.current)\r\n this.nextFrames = this.fInterface.getFrames(Positions.next)\r\n this.previousFrames = this.fInterface.getFrames(Positions.previous)\r\n\r\n const div = document.createElement('div')\r\n div.innerHTML = this.frames[0].image\r\n const newAspectRatio =\r\n div.getElementsByTagName('img')[0]?.naturalWidth /\r\n div.getElementsByTagName('img')[0]?.naturalHeight\r\n\r\n this.aspectRatio = isNaN(newAspectRatio)\r\n ? this.aspectRatio\r\n : newAspectRatio\r\n\r\n this.$nextTick(this.resize)\r\n\r\n const frame = this.frames.find((f) => f.blockStart)\r\n if (frame && this.alternativeServer) {\r\n this.$emit(\r\n 'new-block',\r\n frame.title?.match(/[0-9]{3}\\/(?:[0-9]+_?)+/)[0]\r\n )\r\n }\r\n },\r\n async createFramesInterface(startTime = this.startAudienceTime) {\r\n this.frames = this.loadingArray\r\n // let ch = this.channel\r\n // let associationTMP = {\r\n // 1735073: 1,\r\n // 1735074: 139,\r\n // 1735075: 3,\r\n // 1735076: 132,\r\n // }\r\n // //\r\n // this.channelCode = associationTMP[ch] ? associationTMP[ch] : ch\r\n\r\n const t = startTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const time = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n // * iniciar slider\r\n this.blockStartTime = time\r\n this.fInterface = await new FramesInterface(\r\n this.channel,\r\n this.numberOfRows,\r\n this.framesPerRow,\r\n time,\r\n this.startAudienceTime,\r\n this.useCache,\r\n this.shiftFrames\r\n )\r\n await this.fInterface.init()\r\n\r\n this.getFramesArray()\r\n\r\n const div = document.createElement('div')\r\n div.innerHTML = this.frames[0].image\r\n\r\n this.aspectRatio =\r\n div.getElementsByTagName('img')[0].naturalWidth /\r\n div.getElementsByTagName('img')[0].naturalHeight\r\n\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.activeVideo = null\r\n },\r\n getIndex(rowNumber, frameIndex, position) {\r\n const baseOffset = this.framesPerRow * this.numberOfRows * position\r\n const rowOffset = (rowNumber - 1) * this.framesPerRow\r\n return baseOffset + rowOffset + frameIndex\r\n },\r\n getAudienceTime(frameTime, rowNumber, frameNumber, position) {\r\n if (!frameTime) {\r\n return 'Loading...'\r\n } else if (\r\n this.getIndex(rowNumber, frameNumber, position) === this.activeVideo\r\n ) {\r\n return this.convertToAudienceTime(this.videoTime)\r\n } else {\r\n return this.convertToAudienceTime(frameTime)\r\n }\r\n },\r\n dateInUtc(miliSeconds) {\r\n var date = new Date(miliSeconds)\r\n var utc = new Date(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth(),\r\n date.getUTCDate(),\r\n date.getUTCHours(),\r\n date.getUTCMinutes(),\r\n date.getUTCSeconds()\r\n )\r\n return utc\r\n },\r\n convertToAudienceTime(time, separator = ':') {\r\n const d = this.getDateParts()\r\n const limit = Date.UTC(d.year, d.month, d.day, 23, 59, 59) / 1000\r\n\r\n let hour = this.dateInUtc(time * 1000)\r\n .toTimeString()\r\n .split(' ')[0]\r\n .split(':')\r\n .map(Number)\r\n\r\n if (time > limit && time <= limit + this.startAudienceSeconds) {\r\n hour[0] = 24 + hour[0]\r\n }\r\n return hour\r\n .map((part) => (part > 9 ? part.toString() : '0' + part))\r\n .join(separator)\r\n },\r\n getDateParts(date = this.date) {\r\n const data = /(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})/.exec(\r\n date\r\n )?.groups\r\n if (data) {\r\n return {\r\n year: parseInt(data.year),\r\n month: parseInt(data.month) - 1,\r\n day: parseInt(data.day),\r\n }\r\n }\r\n return {\r\n year: null,\r\n month: null,\r\n day: null,\r\n }\r\n },\r\n selectFrame(index, frame) {\r\n const d = this.getDateParts()\r\n const limit = Date.UTC(d.year, d.month, d.day, 23, 59, 59) / 1000\r\n const frameTime = frame?.time\r\n\r\n if (frameTime - (this.startAudienceSeconds + limit) <= 0) {\r\n if (this.hourIniSelected === true) {\r\n this.hourIniSelected = frameTime\r\n\r\n if (\r\n this.hourEndSelected &&\r\n this.hourIniSelected > this.hourEndSelected\r\n ) {\r\n this.hourEndSelected = false\r\n }\r\n } else if (this.hourEndSelected === true) {\r\n if (frameTime > this.hourIniSelected) {\r\n this.hourEndSelected = frameTime\r\n this.canInsertTime = true\r\n } else {\r\n this.hourEndSelected = false\r\n }\r\n }\r\n }\r\n\r\n if (this.activeFrame !== index) {\r\n // ? Se clicar no frame diferente de onde está a dar play, faz pausa\r\n const array = this.$refs.frames.filter(\r\n (fc) => fc.videoStatus === fc.Status.playing\r\n )\r\n if (array.length === 1) {\r\n const frame = array[0]\r\n frame.playOrPause()\r\n }\r\n this.activeVideo = null\r\n this.activeFrame = index\r\n }\r\n },\r\n setHourIni() {\r\n this.canInsertTime = true\r\n this.hourIniSelected = true\r\n document.getElementById(`frame-${this.activeFrame}`).click()\r\n this.$emit('setHourIni', {\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n })\r\n },\r\n setHourEnd() {\r\n this.canInsertTime = true\r\n this.hourEndSelected = true\r\n document.getElementById(`frame-${this.activeFrame}`).click()\r\n },\r\n //* Navegação\r\n arrowRight() {\r\n if (this.checkLimitRight(false)) {\r\n if (\r\n this.activeFrame ===\r\n this.numberOfRows * this.framesPerRow * 2 - 1\r\n ) {\r\n this.next()\r\n } else {\r\n this.activeFrame++\r\n }\r\n }\r\n },\r\n arrowLeft() {\r\n if (this.checkLimitLeft(false)) {\r\n if (this.activeFrame === this.numberOfRows * this.framesPerRow) {\r\n this.prev({ stayOnLast: true })\r\n } else {\r\n this.activeFrame--\r\n }\r\n }\r\n },\r\n arrowUp() {\r\n const relativePosition =\r\n this.activeFrame - this.numberOfRows * this.framesPerRow\r\n const currentRow = Math.floor(relativePosition / this.framesPerRow)\r\n if (currentRow > 0) {\r\n this.activeFrame -= this.framesPerRow\r\n }\r\n },\r\n\r\n arrowDown() {\r\n const relativePosition =\r\n this.activeFrame - this.numberOfRows * this.framesPerRow\r\n const currentRow = Math.floor(relativePosition / this.framesPerRow)\r\n\r\n if (currentRow < this.numberOfRows - 1) {\r\n this.activeFrame += this.framesPerRow\r\n }\r\n },\r\n checkLimitRight(value) {\r\n const hours = this.endAudienceTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const high = Date.UTC(\r\n d.year,\r\n d.month,\r\n d.day,\r\n hours[0],\r\n parseInt(hours[1]) + 30,\r\n hours[2]\r\n )\r\n\r\n if (value) {\r\n return (\r\n high >\r\n (this.fInterface.getCurrentTime() +\r\n this.numberOfRows * this.framesPerRow -\r\n 1) *\r\n 1000\r\n )\r\n } else {\r\n return high > this.fInterface.getCurrentTime() * 1000\r\n }\r\n },\r\n checkLimitLeft(value) {\r\n const hours = this.startAudienceTime.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const low = Date.UTC(d.year, d.month, d.day, hours[0], hours[1], hours[2])\r\n\r\n if (value) {\r\n return low <= (this.fInterface.getCurrentTime() - 1) * 1000\r\n } else {\r\n return (\r\n low <\r\n (this.fInterface.getCurrentTime() +\r\n this.activeFrame -\r\n this.numberOfRows * this.framesPerRow) *\r\n 1000\r\n )\r\n }\r\n },\r\n async next(config = {}) {\r\n if (\r\n (config.ignoreTime ||\r\n Date.now() - this.lastNext > this.swapImagesDelay) &&\r\n this.checkLimitRight(true) &&\r\n !this.navigationPending\r\n ) {\r\n this.navigationPending = true\r\n this.stopVideoPlaying()\r\n\r\n this.navigationPending = await new Promise((resolve) => {\r\n this.fInterface\r\n .loadNextFrames()\r\n .then(() => {\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.getFramesArray()\r\n this.lastNext = Date.now()\r\n resolve(false)\r\n })\r\n .catch(() => {\r\n resolve(false)\r\n })\r\n })\r\n } else {\r\n // console.error('next blocked')\r\n }\r\n },\r\n async prev(config = {}) {\r\n if (\r\n (config.ignoreTime ||\r\n Date.now() - this.lastPrev > this.swapImagesDelay) &&\r\n this.checkLimitLeft(true) &&\r\n !this.navigationPending\r\n ) {\r\n this.navigationPending = true\r\n this.stopVideoPlaying()\r\n\r\n this.navigationPending = await new Promise((resolve) => {\r\n this.fInterface\r\n .loadPrevFrames()\r\n .then(() => {\r\n if (config.stayOnLast) {\r\n this.activeFrame = this.getIndex(\r\n this.numberOfRows,\r\n this.framesPerRow - 1,\r\n Positions.current\r\n )\r\n } else {\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n }\r\n\r\n this.getFramesArray()\r\n this.lastPrev = Date.now()\r\n resolve(false)\r\n })\r\n .catch(() => {\r\n resolve(false)\r\n })\r\n })\r\n } else {\r\n // console.error('prev blocked')\r\n }\r\n },\r\n async setStartTime(time) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n const t = time.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const setTime = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n // this.frames = this.loadingArray\r\n\r\n await this.fInterface.changeTime(setTime)\r\n\r\n this.getFramesArray()\r\n\r\n this.activeFrame = this.getIndex(1, 0, Positions.current)\r\n\r\n this.activeVideo = null\r\n\r\n return true\r\n },\r\n hourToTimeStamp(time) {\r\n if (time.indexOf(':') !== -1) {\r\n time = time.replace(/:/g, '')\r\n }\r\n const t = time.match(/.{1,2}/g)\r\n const d = this.getDateParts()\r\n const setTime = Date.UTC(d.year, d.month, d.day, t[0], t[1], t[2]) / 1000\r\n\r\n return setTime\r\n },\r\n changeHour(value) {\r\n if (value) {\r\n return new Promise((resolve) => {\r\n setTimeout(async () => {\r\n this.stopVideoPlaying()\r\n\r\n await this.setStartTime(value, true)\r\n resolve()\r\n }, 0)\r\n })\r\n }\r\n },\r\n changeBlockInterval(value) {\r\n this.changeHour(value.ini)\r\n let time_ini, time_end\r\n time_ini = this.hourToTimeStamp(value.ini)\r\n time_end = this.hourToTimeStamp(value.end)\r\n this.videoSliderTotalDuration = time_end - time_ini\r\n this.$refs.frames[0].changeSettings(time_ini)\r\n this.blockStartTime = time_ini\r\n },\r\n //eslint-disable-next-line\r\n async updateVideoTime(index, videoTime) {\r\n this.activeVideo = index\r\n this.videoTime = videoTime\r\n },\r\n //eslint-disable-next-line\r\n updateVideoStatus(currentTime) {\r\n if (!this.progressVideoDrag) {\r\n // ESTA FUNÇÃO PASSOU PARA DENTRO DOS COMMANDS\r\n // this.updateProgress(null, currentTime)\r\n }\r\n },\r\n async startPlaying(frame, totalTime) {\r\n const array = this.$refs.frames.filter(\r\n (fc) => fc.frame.time !== frame.time\r\n )\r\n this.stopVideoPlaying(array)\r\n\r\n this.videoTotalTime = totalTime\r\n this.videoPlaying = true\r\n },\r\n stopPlaying() {\r\n this.videoTotalTime = null\r\n this.videoPlaying = false\r\n this.paused = false\r\n },\r\n insertTime() {\r\n this.$emit('timeToInsert', {\r\n channel: this.channel,\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n hour_end: this.hourEndSelected\r\n ? this.convertToAudienceTime(this.hourEndSelected, '')\r\n : null,\r\n force: false,\r\n })\r\n\r\n if (this.jumpOnInsert) {\r\n this.changeHour(\r\n this.convertToAudienceTime(\r\n this.hourEndSelected || this.hourIniSelected\r\n )\r\n ).then(() => {\r\n this.activeFrame = this.getIndex(1, 1, Positions.current)\r\n })\r\n }\r\n\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = null\r\n this.hourEndSelected = null\r\n this.canInsertTime = false\r\n }\r\n },\r\n insertTimeForce() {\r\n this.$emit('timeToInsert', {\r\n channel: this.channel,\r\n hour_ini: this.hourIniSelected\r\n ? this.convertToAudienceTime(this.hourIniSelected, '')\r\n : null,\r\n hour_end: this.hourEndSelected\r\n ? this.convertToAudienceTime(this.hourEndSelected, '')\r\n : null,\r\n force: true,\r\n })\r\n\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = null\r\n this.hourEndSelected = null\r\n this.canInsertTime = false\r\n }\r\n },\r\n async getChannelMedia() {\r\n // this.media = (await ChannelService.show(this.channel)).data.MEDIA\r\n },\r\n async changeServerClick() {\r\n this.changeServer = !this.changeServer\r\n this.alternativeServer = this.changeServer\r\n\r\n sessionStorage.setItem(\r\n 'server',\r\n this.changeServer ? 'alternative' : 'default'\r\n )\r\n\r\n await this.createFramesInterface(\r\n this.convertToAudienceTime(\r\n this.$refs.frames.find((frame) => frame.index === this.activeFrame)\r\n .frame.time,\r\n ''\r\n )\r\n )\r\n\r\n this.$nextTick(this.resize)\r\n },\r\n },\r\n computed: {\r\n swapImagesDelay() {\r\n return 0\r\n // return this.numberOfRows * this.framesPerRow * 15\r\n },\r\n active: {\r\n get() {\r\n return this.value\r\n },\r\n set(value) {\r\n this.$emit('input', value)\r\n },\r\n },\r\n settingsClosed() {\r\n return !Object.values(this.dialogs).find((v) => v)\r\n },\r\n startAudienceSeconds() {\r\n const t = this.startAudienceTime.match(/.{1,2}/g)\r\n return parseInt(t[0] * 3600 + t[1] * 60 + t[2])\r\n },\r\n loadingArray() {\r\n return Array.from(Array(this.numberOfRows * this.framesPerRow).keys())\r\n },\r\n serverOfFrames() {\r\n return sessionStorage.getItem('server')\r\n },\r\n },\r\n beforeDestroy() {\r\n sessionStorage.setItem('server', 'default')\r\n },\r\n watch: {\r\n async secondsPerFrame() {\r\n const activeF =\r\n this.frames[this.activeFrame - this.numberOfRows * this.framesPerRow]\r\n\r\n if (activeF) {\r\n this.changeHour(this.getAudienceTime(activeF.time, 0, 0, 0))\r\n this.fInterface.setCurrentStep(this.secondsPerFrame)\r\n await this.fInterface.loadFrames()\r\n this.getFramesArray()\r\n }\r\n },\r\n async shiftFrames() {\r\n this.createFramesInterface()\r\n },\r\n framesFormat(value) {\r\n this.setFrameSelection(value)\r\n },\r\n active() {\r\n // ? sempre que trocamos de tabs dar reset as horas selected\r\n if (this.removeSelectionOnInsert) {\r\n this.hourIniSelected = false\r\n this.hourEndSelected = false\r\n }\r\n },\r\n useCache() {\r\n this.createFramesInterface()\r\n },\r\n hourIniSelected(value) {\r\n if (value) {\r\n sessionStorage.setItem(\r\n 'currentTimeFrames',\r\n this.convertToAudienceTime(this.hourIniSelected, '')\r\n )\r\n } else {\r\n sessionStorage.removeItem('currentTimeFrames')\r\n }\r\n },\r\n activeFrame(value) {\r\n if (value) {\r\n this.stopPlayingBar()\r\n }\r\n },\r\n channel() {\r\n this.updatingChannel = new Promise((resolve, reject) => {\r\n try {\r\n this.createFramesInterface()\r\n resolve(true)\r\n } catch (err) {\r\n reject(err)\r\n }\r\n })\r\n },\r\n stretchFrame() {\r\n this.$nextTick(this.resize)\r\n },\r\n },\r\n}\r\n</script>\r\n<style scoped>\r\n.visualization-row {\r\n display: flex;\r\n flex-wrap: wrap;\r\n flex: 1 1 auto;\r\n}\r\n\r\n.visualization-col {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 5px;\r\n}\r\n\r\n.visualization-divider {\r\n display: block;\r\n flex: 1 1 100%;\r\n height: 0px;\r\n max-height: 0px;\r\n opacity: 1;\r\n transition: inherit;\r\n border-style: solid;\r\n border-width: thin 0 0 0;\r\n border-color: rgba(0, 0, 0, 0.12);\r\n margin: 0;\r\n}\r\n\r\n.visualization-divider.vertical {\r\n align-self: stretch;\r\n border-width: 0 thin 0 0;\r\n display: inline-flex;\r\n height: inherit;\r\n margin-left: -1px;\r\n max-height: 100%;\r\n max-width: 0px;\r\n vertical-align: text-bottom;\r\n width: 0px;\r\n}\r\n\r\n.visualization-card {\r\n flex-basis: 0;\r\n flex-grow: 1;\r\n max-width: 100%;\r\n padding: 12px;\r\n width: 100%;\r\n transition-property: box-shadow, opacity, -webkit-box-shadow;\r\n overflow-wrap: break-word;\r\n /*box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);*/\r\n}\r\n\r\n.visualization-justify-center,\r\n* >>> .visualization-justify-center {\r\n justify-content: center;\r\n}\r\n\r\n.visualization-align-center {\r\n align-items: center;\r\n}\r\n\r\n#visualization-container {\r\n max-width: 100% !important;\r\n margin: 0 auto !important;\r\n height: 100%;\r\n border-bottom: none;\r\n}\r\n#visualization-container > .card {\r\n border-radius: 0 !important;\r\n font-size: 12px;\r\n width: 100%;\r\n box-shadow: none;\r\n height: 100%;\r\n}\r\n\r\n#command-bar,\r\n#info-bar {\r\n background-color: #f5f5f5;\r\n box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14),\r\n 0 1px 5px 0 rgba(0, 0, 0, 0.12);\r\n}\r\n#command-bar button {\r\n width: 42px;\r\n height: 36px;\r\n border: none;\r\n background: none;\r\n}\r\n\r\n#command-bar button:hover {\r\n cursor: pointer;\r\n background: rgba(0, 0, 0, 0.12);\r\n}\r\n\r\n#command-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#command-bar {\r\n padding: 0 !important;\r\n}\r\n\r\n#info-bar {\r\n padding: 4px;\r\n font-size: 14px;\r\n position: relative;\r\n}\r\n\r\n.settings-container {\r\n position: absolute;\r\n right: 14px;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n}\r\n\r\n.settings-container > * {\r\n margin: 0 2px;\r\n cursor: pointer;\r\n}\r\n\r\n#info-bar svg {\r\n font-size: 16px;\r\n}\r\n\r\n#info-bar .divider {\r\n margin: 0 8px;\r\n}\r\n\r\nsvg:focus {\r\n border: none;\r\n}\r\n\r\n.visualization-card {\r\n border-left: 8px solid #eee;\r\n}\r\n\r\n.active-tab {\r\n border-left: 8px solid var(--visualization-primary) !important;\r\n border-image-slice: 1;\r\n}\r\n\r\n[id^='frame-'] {\r\n padding: 1px;\r\n display: flex;\r\n flex-flow: column;\r\n}\r\n\r\n.tooltip {\r\n display: block !important;\r\n z-index: 10000;\r\n}\r\n\r\n.tooltip .tooltip-inner {\r\n background: var(--visualization-primary);\r\n color: white;\r\n border-radius: 16px;\r\n padding: 5px 10px 4px;\r\n}\r\n\r\n.tooltip .tooltip-arrow {\r\n width: 0;\r\n height: 0;\r\n border-style: solid;\r\n position: absolute;\r\n margin: 5px;\r\n border-color: var(--visualization-primary);\r\n z-index: 1;\r\n}\r\n\r\n.tooltip[x-placement^='top'] {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='top'] .tooltip-arrow {\r\n border-width: 5px 5px 0 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n bottom: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] {\r\n margin-top: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='bottom'] .tooltip-arrow {\r\n border-width: 0 5px 5px 5px;\r\n border-left-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-top-color: transparent !important;\r\n top: -5px;\r\n left: calc(50% - 5px);\r\n margin-top: 0;\r\n margin-bottom: 0;\r\n}\r\n\r\n.tooltip[x-placement^='right'] {\r\n margin-left: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='right'] .tooltip-arrow {\r\n border-width: 5px 5px 5px 0;\r\n border-left-color: transparent !important;\r\n border-top-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n left: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip[x-placement^='left'] {\r\n margin-right: 5px;\r\n}\r\n\r\n.tooltip[x-placement^='left'] .tooltip-arrow {\r\n border-width: 5px 0 5px 5px;\r\n border-top-color: transparent !important;\r\n border-right-color: transparent !important;\r\n border-bottom-color: transparent !important;\r\n right: -5px;\r\n top: calc(50% - 5px);\r\n margin-left: 0;\r\n margin-right: 0;\r\n}\r\n\r\n.tooltip.popover .popover-inner {\r\n background: #f9f9f9;\r\n color: black;\r\n padding: 24px;\r\n border-radius: 5px;\r\n box-shadow: 0 5px 30px rgba(black, 0.1);\r\n}\r\n\r\n.tooltip.popover .popover-arrow {\r\n border-color: #f9f9f9;\r\n}\r\n\r\n.tooltip[aria-hidden='true'] {\r\n visibility: hidden;\r\n opacity: 0;\r\n transition: opacity 0.15s, visibility 0.15s;\r\n}\r\n\r\n.tooltip[aria-hidden='false'] {\r\n visibility: visible;\r\n opacity: 1;\r\n transition: opacity 0.15s;\r\n}\r\n\r\n.custom-frametime {\r\n font-size: smaller;\r\n}\r\n</style>\r\n"]}, media: undefined });
5614
5697
 
5615
5698
  };
5616
5699
  /* scoped */
5617
- const __vue_scope_id__ = "data-v-11fd896a";
5700
+ const __vue_scope_id__ = "data-v-a861684a";
5618
5701
  /* module identifier */
5619
5702
  const __vue_module_identifier__ = undefined;
5620
5703
  /* functional template */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twab/visualization",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "main": "dist/visualization.js",
5
5
  "files": [
6
6
  "dist"