@3cr/viewer-browser 0.0.62 → 0.0.92

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 (81) hide show
  1. package/components.d.ts +0 -2
  2. package/coverage/3cr-viewer-browser/index.html +116 -0
  3. package/coverage/3cr-viewer-browser/index.ts.html +199 -0
  4. package/coverage/3cr-viewer-browser/src/App.vue.html +316 -0
  5. package/coverage/3cr-viewer-browser/src/components/WebGL3DR.vue.html +442 -0
  6. package/coverage/3cr-viewer-browser/src/components/icons/index.html +116 -0
  7. package/coverage/3cr-viewer-browser/src/components/icons/liver.vue.html +148 -0
  8. package/coverage/3cr-viewer-browser/src/components/index.html +116 -0
  9. package/coverage/3cr-viewer-browser/src/components/loading/LoadingSpinner.vue.html +622 -0
  10. package/coverage/3cr-viewer-browser/src/components/loading/index.html +116 -0
  11. package/coverage/3cr-viewer-browser/src/components/modal/MftpWebGL3DRModal.vue.html +3118 -0
  12. package/coverage/3cr-viewer-browser/src/components/modal/index.html +116 -0
  13. package/coverage/3cr-viewer-browser/src/components/selectors/ValueSelector.vue.html +358 -0
  14. package/coverage/3cr-viewer-browser/src/components/selectors/index.html +116 -0
  15. package/coverage/3cr-viewer-browser/src/components/sliders/DoubleSliderSelector.vue.html +487 -0
  16. package/coverage/3cr-viewer-browser/src/components/sliders/VerticalSliderSelector.vue.html +358 -0
  17. package/coverage/3cr-viewer-browser/src/components/sliders/index.html +131 -0
  18. package/coverage/3cr-viewer-browser/src/dataLayer/iconData.ts.html +118 -0
  19. package/coverage/3cr-viewer-browser/src/dataLayer/index.html +146 -0
  20. package/coverage/3cr-viewer-browser/src/dataLayer/payloadHandler.ts.html +463 -0
  21. package/coverage/3cr-viewer-browser/src/dataLayer/scanState.ts.html +598 -0
  22. package/coverage/3cr-viewer-browser/src/helpers/index.html +146 -0
  23. package/coverage/3cr-viewer-browser/src/helpers/layoutOverlayStyle.ts.html +406 -0
  24. package/coverage/3cr-viewer-browser/src/helpers/modelHelper.ts.html +412 -0
  25. package/coverage/3cr-viewer-browser/src/helpers/utils.ts.html +133 -0
  26. package/coverage/3cr-viewer-browser/src/index.html +131 -0
  27. package/coverage/3cr-viewer-browser/src/main.ts.html +124 -0
  28. package/coverage/3cr-viewer-browser/src/models/LoadViewerOptions.ts.html +166 -0
  29. package/coverage/3cr-viewer-browser/src/models/index.html +116 -0
  30. package/coverage/3cr-viewer-browser/src/notifications/index.html +116 -0
  31. package/coverage/3cr-viewer-browser/src/notifications/notification.ts.html +238 -0
  32. package/coverage/3cr-viewer-browser/src/plugins/index.html +131 -0
  33. package/coverage/3cr-viewer-browser/src/plugins/index.ts.html +136 -0
  34. package/coverage/3cr-viewer-browser/src/plugins/vuetify.ts.html +220 -0
  35. package/coverage/base.css +224 -0
  36. package/coverage/block-navigation.js +87 -0
  37. package/coverage/favicon.png +0 -0
  38. package/coverage/index.html +296 -0
  39. package/coverage/prettify.css +1 -0
  40. package/coverage/prettify.js +2 -0
  41. package/coverage/sort-arrow-sprite.png +0 -0
  42. package/coverage/sorter.js +196 -0
  43. package/dist/Viewer3CR.js +12 -12
  44. package/dist/Viewer3CR.mjs +10142 -10179
  45. package/dist/Viewer3CR.umd.js +12 -12
  46. package/index.ts +7 -42
  47. package/package.json +1 -1
  48. package/src/App.vue +6 -2
  49. package/src/components/modal/MftpWebGL3DRModal.vue +149 -552
  50. package/src/components/modal/__tests__/mftp-webgl-3dr-modal.spec.ts +146 -199
  51. package/src/components/selectors/ValueSelector.vue +4 -0
  52. package/src/components/selectors/__tests__/value-selector.spec.ts +18 -0
  53. package/src/components/sliders/DoubleSliderSelector.vue +10 -4
  54. package/src/components/sliders/__tests__/double-slider-selector.spec.ts +32 -0
  55. package/src/dataLayer/__tests__/payload-handler.spec.ts +214 -0
  56. package/src/dataLayer/iconData.ts +11 -0
  57. package/src/dataLayer/payloadHandler.ts +126 -0
  58. package/src/dataLayer/scanState.ts +171 -0
  59. package/src/demo/options.ts +93 -0
  60. package/src/models/Callbacks.ts +2 -0
  61. package/src/models/LoadViewerOptions.ts +27 -0
  62. package/src/models/LoadViewerPayload.ts +8 -0
  63. package/src/models/__tests__/load-viewer-options.spec.ts +22 -0
  64. package/src/notifications/__tests__/notification.spec.ts +120 -0
  65. package/src/notifications/notification.ts +51 -0
  66. package/vitest.config.mts +1 -0
  67. package/coverage/.tmp/coverage-100.json +0 -1
  68. package/coverage/.tmp/coverage-101.json +0 -1
  69. package/coverage/.tmp/coverage-102.json +0 -1
  70. package/coverage/.tmp/coverage-103.json +0 -1
  71. package/coverage/.tmp/coverage-104.json +0 -1
  72. package/coverage/.tmp/coverage-105.json +0 -1
  73. package/coverage/.tmp/coverage-106.json +0 -1
  74. package/coverage/.tmp/coverage-107.json +0 -1
  75. package/coverage/.tmp/coverage-108.json +0 -1
  76. package/coverage/.tmp/coverage-109.json +0 -1
  77. package/coverage/.tmp/coverage-110.json +0 -1
  78. package/coverage/.tmp/coverage-98.json +0 -1
  79. package/coverage/.tmp/coverage-99.json +0 -1
  80. /package/src/{components/modal → demo}/DemoModal.vue +0 -0
  81. /package/src/{components/modal → demo}/DemoPatientModal.vue +0 -0
@@ -172,7 +172,7 @@
172
172
  height="36"
173
173
  style="min-width: 36px !important"
174
174
  :color="isLayout2x2 ? 'secondary' : 'primary'"
175
- @click="layouts('lo_02')"
175
+ @click="payloadHandler.layouts(LayoutActions.lo02)"
176
176
  ><v-icon>grid_view</v-icon></v-btn
177
177
  >
178
178
  <v-btn
@@ -180,7 +180,7 @@
180
180
  height="36"
181
181
  style="min-width: 36px !important"
182
182
  :color="isLayout1x3 ? 'secondary' : 'primary'"
183
- @click="layouts('lo_03')"
183
+ @click="payloadHandler.layouts(LayoutActions.lo03)"
184
184
  ><v-icon style="rotate: -90deg">view_comfy</v-icon></v-btn
185
185
  >
186
186
  <v-btn class="" variant="flat" color="red" @click="alterValue(false)"
@@ -202,7 +202,6 @@
202
202
  <div
203
203
  class="d-flex align-center pb-1"
204
204
  :class="drawerCollapsed ? 'py-2' : 'pa-2'"
205
- @click="snap"
206
205
  >
207
206
  <img
208
207
  v-if="!drawerCollapsed"
@@ -224,7 +223,6 @@
224
223
  <div
225
224
  class="text-center mx-auto pa-0 text-white sub-type"
226
225
  :style="drawerCollapsed ? 'font-size: 100%' : 'font-size: 140%'"
227
- @click="snap"
228
226
  >
229
227
  Online Viewer
230
228
  </div>
@@ -329,7 +327,7 @@
329
327
  />
330
328
  <v-card-actions class="py-3">
331
329
  <v-select
332
- :value="getCurrentGreyscalePreset()"
330
+ :value="currentGreyscalePreset"
333
331
  :items="initialScanState.GreyscalePresets"
334
332
  label="Greyscale Preset"
335
333
  item-text="Name"
@@ -343,7 +341,9 @@
343
341
  closeOnContentClick: true,
344
342
  }"
345
343
  placeholder="Select a Density Preset"
346
- @change="setPreset(PresetsActions.pr01, $event)"
344
+ @change="
345
+ payloadHandler.setPreset(PresetsActions.pr01, $event)
346
+ "
347
347
  >
348
348
  <template #item="{ props, item }">
349
349
  <v-list-item
@@ -352,7 +352,9 @@
352
352
  :title="item.raw.Name"
353
353
  lines="three"
354
354
  @mousedown.prevent
355
- @click="setPreset(PresetsActions.pr01, item.raw)"
355
+ @click="
356
+ payloadHandler.setPreset(PresetsActions.pr01, item.raw)
357
+ "
356
358
  >
357
359
  <template v-slot:prepend>
358
360
  <v-icon
@@ -390,7 +392,9 @@
390
392
  }"
391
393
  placeholder="Select a Colour Preset"
392
394
  return-object
393
- @update:modelValue="setPreset(PresetsActions.pr02, $event)"
395
+ @update:modelValue="
396
+ payloadHandler.setPreset(PresetsActions.pr02, $event)
397
+ "
394
398
  ></v-select>
395
399
  </v-card-actions>
396
400
  </v-expansion-panel-text>
@@ -431,7 +435,7 @@
431
435
  id="webgl-container"
432
436
  @on_payload="handleOnPayload"
433
437
  @instance_loaded="load"
434
- @hover="hoverOverCanvas"
438
+ @hover="payloadHandler.hoverOverCanvas($event)"
435
439
  >
436
440
  <div
437
441
  class="bordered-event-window"
@@ -471,7 +475,7 @@
471
475
  <div v-if="scanState.Layout.PositionData.length === 1">
472
476
  <v-btn
473
477
  color="transparent"
474
- @click="layouts(previousLayout)"
478
+ @click="payloadHandler.layouts(previousLayout)"
475
479
  :icon="true"
476
480
  >
477
481
  <v-icon color="white">fullscreen_exit</v-icon>
@@ -491,8 +495,12 @@
491
495
  color="transparent"
492
496
  :icon="true"
493
497
  @click="
494
- viewSelection('vs_05');
495
- viewSelection('vs_06');
498
+ payloadHandler.viewSelection(
499
+ ViewSelectionActions.vs06
500
+ );
501
+ payloadHandler.viewSelection(
502
+ ViewSelectionActions.vs05
503
+ );
496
504
  "
497
505
  ><v-icon color="white">home</v-icon></v-btn
498
506
  >
@@ -590,7 +598,7 @@
590
598
  <v-btn
591
599
  color="primary"
592
600
  @click="
593
- rotateByDeg(
601
+ payloadHandler.rotateByDeg(
594
602
  getCurrentActiveView(layout),
595
603
  rotationDeg
596
604
  )
@@ -667,49 +675,67 @@ import VerticalSliderSelector from "@/components/sliders/VerticalSliderSelector.
667
675
  import { generateDivStyleForLayout } from "@/helpers/layoutOverlayStyle";
668
676
 
669
677
  import {
670
- inflateInitialScanState,
671
- inflateScanState,
672
- } from "@/helpers/modelHelper";
673
- import {
674
- SlidersActions,
675
- PresetsActions,
676
- ScanMovementActions,
677
- ScanOrientationActions,
678
678
  FileManagementActions,
679
679
  FrontEndInterfaces,
680
- AnchorPoint,
681
- ColourPresetData,
682
- CurrentScanState,
683
- InitialScanState,
680
+ LayoutActions,
681
+ NotificationsActions,
684
682
  PositionData,
683
+ PresetsActions,
684
+ ScanMovementActions,
685
685
  ScanView,
686
- InteractivityActions,
687
- NotificationsActions,
688
- NotificationPayload,
686
+ SlidersActions,
687
+ ViewSelectionActions,
689
688
  } from "@3cr/types-ts";
689
+ import { defineEmits, nextTick, ref, unref, watch, WatchSource } from "vue";
690
690
 
691
- import { toNumber } from "@/helpers/utils";
692
- import { computed, ref, unref, watch, defineEmits, nextTick } from "vue";
693
691
  import {
694
- defaultOptions,
692
+ checkIsDemo,
693
+ demoType,
694
+ executeDemoOption,
695
+ isDemo,
696
+ m_demo,
697
+ m_demoPatient,
698
+ } from "@/demo/options";
699
+ import { handleNotification } from "@/notifications/notification";
700
+ import DemoPatientModal from "@/demo/DemoPatientModal.vue";
701
+ import DemoModal from "@/demo/DemoModal.vue";
702
+ import { LoadViewerPayload } from "@/models/LoadViewerPayload";
703
+ import {
704
+ defaultLoadViewerOptions,
695
705
  LoadViewerOptions,
696
- LoadViewerPayload,
697
- } from "../../../index";
698
-
699
- import { useNotification } from "@kyvg/vue3-notification";
700
-
701
- const { notify } = useNotification();
702
-
703
- const emit = defineEmits<{
704
- instanceLoaded: [void];
705
- snap: [void];
706
- }>();
706
+ } from "@/models/LoadViewerOptions";
707
+ import { PayloadHandler, sendPayload } from "@/dataLayer/payloadHandler";
708
+ import {
709
+ cMinMax,
710
+ cSlider,
711
+ currentColourPreset,
712
+ currentGreyscalePreset,
713
+ huMinMax,
714
+ initialScanState,
715
+ isLayout1x3,
716
+ isLayout2x2,
717
+ previousLayout,
718
+ scanState,
719
+ setInitialScanStateFromPayload,
720
+ setScanStateFromPayload,
721
+ sMinMax,
722
+ sSlider,
723
+ thresholdSlider,
724
+ tMinMax,
725
+ transactionStarted,
726
+ tSlider,
727
+ windowSlider,
728
+ } from "@/dataLayer/scanState";
729
+ import { getIconForPreset } from "@/dataLayer/iconData";
707
730
 
708
731
  export interface Props {
709
732
  payload?: LoadViewerPayload;
710
733
  options?: LoadViewerOptions;
711
734
  }
712
735
 
736
+ const emit = defineEmits<{
737
+ instanceLoaded: [void];
738
+ }>();
713
739
  const props = withDefaults(defineProps<Props>(), {
714
740
  payload: () => ({
715
741
  Url: "https://webgl-3dr.singular.health/test_scans/8bdddee1-e581-485d-827d-6aa12eef2fc8/Head+Axial+Axial.3vxl",
@@ -718,121 +744,25 @@ const props = withDefaults(defineProps<Props>(), {
718
744
  Key: "OWjSMiL/ewUV1V6fGybhKcTyiysTPsIMp2DjdVoOUGI=",
719
745
  },
720
746
  }),
721
- options: () => defaultOptions,
747
+ options: () => defaultLoadViewerOptions,
722
748
  });
723
- const isDemo = ref<boolean>(false);
724
- let m_demo = ref<boolean>(false);
725
- let m_demoPatient = ref<boolean>(false);
726
-
727
- const demoLicenceOptions: LoadViewerOptions = {
728
- OnClosePopup: () => Promise.resolve(),
729
- OnExitViewer: () => {
730
- m_demo.value = true;
731
- },
732
- OnLoadNewDicomSeries: () => {
733
- m_demo.value = true;
734
- },
735
- OnDownloadDicomSeries: () => {
736
- m_demo.value = true;
737
- },
738
- OnLoadSavedSession: () => {
739
- m_demo.value = true;
740
- },
741
- OnSaveSession: () => {
742
- m_demo.value = true;
743
- },
744
- OnSendTo3rdParty: () => {
745
- m_demo.value = true;
746
- },
747
- OnShareToMobile: () => {
748
- m_demo.value = true;
749
- },
750
- OnShare: () => {
751
- m_demo.value = true;
752
- },
753
- OnScreenshot: () => {
754
- m_demo.value = true;
755
- },
756
- };
757
-
758
- const demoPatientOptions: LoadViewerOptions = {
759
- OnClosePopup: () => Promise.resolve(),
760
- OnExitViewer: () => {
761
- m_demoPatient.value = true;
762
- },
763
- OnLoadNewDicomSeries: () => {
764
- m_demoPatient.value = true;
765
- },
766
- OnDownloadDicomSeries: () => {
767
- m_demoPatient.value = true;
768
- },
769
- OnLoadSavedSession: () => {
770
- m_demoPatient.value = true;
771
- },
772
- OnSaveSession: () => {
773
- m_demoPatient.value = true;
774
- },
775
- OnSendTo3rdParty: () => {
776
- m_demoPatient.value = true;
777
- },
778
- OnShareToMobile: () => {
779
- m_demoPatient.value = true;
780
- },
781
- OnShare: () => {
782
- m_demoPatient.value = true;
783
- },
784
- OnScreenshot: () => {
785
- m_demoPatient.value = true;
786
- },
787
- };
788
-
789
- const demoType = computed(() => {
790
- const urlParams = new URLSearchParams(window.location.search);
791
- return urlParams.get("demoType") || "licence";
792
- });
793
-
794
- function executeOption(key: keyof LoadViewerOptions) {
795
- if (unref(isDemo)) {
796
- if (unref(demoType) === "licence") {
797
- const functionToExecute = demoLicenceOptions[key];
798
- if (functionToExecute !== undefined) {
799
- functionToExecute();
800
- }
801
- } else if (unref(demoType) === "patient") {
802
- const functionToExecute = demoPatientOptions[key];
803
- if (functionToExecute !== undefined) {
804
- functionToExecute();
805
- }
806
- }
807
- } else {
808
- const functionToExecute = unref(props.options)[key];
809
- if (functionToExecute !== undefined) {
810
- functionToExecute();
811
- }
812
- }
813
- }
814
-
815
- const emptyPayload = { Version: "1.1.0" };
816
749
 
750
+ const web_gl = ref<typeof WebGL3DR | null>(null);
751
+ const payloadHandler = new PayloadHandler(web_gl);
817
752
  const value = ref<boolean>(false);
818
753
  const drawer = ref<boolean>(true);
819
754
  const drawerCollapsed = ref<boolean>(true);
820
755
  const scanLoading = ref<boolean>(true);
821
756
  const instanceLoaded = ref<boolean>(true);
822
- const scanState = ref<CurrentScanState>(inflateScanState());
823
- const initialScanState = ref<InitialScanState>(inflateInitialScanState());
824
- const currentColourPreset = ref<ColourPresetData | undefined>(undefined);
825
757
  const openPanels = ref<number>(0);
826
- const previousLayout = ref<string>("lo_02");
827
758
  const footerItems = ref([
828
759
  {
829
760
  text: "Reset Scan",
830
761
  icon: "refresh",
831
762
  color: "red",
832
763
  click: async () => {
833
- console.log("Reset Scan");
834
- await viewSelection("vs_05");
835
- await viewSelection("vs_06");
764
+ await payloadHandler.viewSelection(ViewSelectionActions.vs05);
765
+ await payloadHandler.viewSelection(ViewSelectionActions.vs06);
836
766
  },
837
767
  },
838
768
  {
@@ -854,7 +784,6 @@ const footerItems = ref([
854
784
  click: async () => executeOption("OnScreenshot"),
855
785
  },
856
786
  ]);
857
-
858
787
  const miniMenu = ref([
859
788
  {
860
789
  icon: "display_settings",
@@ -862,238 +791,79 @@ const miniMenu = ref([
862
791
  tooltip:
863
792
  "Tissue Density - Change the view of density within the scan, allowing you to see through a certain density of particles",
864
793
  },
865
- // { icon: 'display_settings', text: 'Display', tooltip: 'Display - Alter the view of the current scan' },
866
794
  ]);
867
-
868
- const huMinMax = ref({
869
- min: -999999,
870
- max: 999999,
871
- });
872
-
873
- const tMinMax = ref({
874
- min: 0,
875
- max: 999999,
876
- });
877
- const sMinMax = ref({
878
- min: 0,
879
- max: 999999,
880
- });
881
- const cMinMax = ref({
882
- min: 0,
883
- max: 999999,
884
- });
885
795
  const rotationDeg = ref<number>(0);
886
- const scanStateIncoming = ref<string>("");
887
- const transactionStarted = ref<boolean>(false);
888
796
  const stateOverlay = ref<boolean>(false);
889
797
  const m_closeDialog = ref<boolean>(false);
890
798
 
891
- const windowSlider = computed({
892
- get() {
893
- return [
894
- unref(scanState).Display.WindowLower,
895
- unref(scanState).Display.WindowUpper,
896
- ];
897
- },
898
- set(value: Array<number>) {
899
- scanState.value.Display.WindowLower = value[0];
900
- scanState.value.Display.WindowUpper = value[1];
901
- },
902
- });
903
- const thresholdSlider = computed({
904
- get() {
905
- return [
906
- Math.trunc(unref(scanState).Display.ThresholdLower),
907
- Math.trunc(unref(scanState).Display.ThresholdUpper),
908
- ];
909
- },
910
- set(value: Array<number>) {
911
- scanState.value.Display.ThresholdLower = value[0];
912
- scanState.value.Display.ThresholdUpper = value[1];
913
- },
914
- });
915
- const tSlider = computed({
916
- get() {
917
- return [
918
- Math.trunc(unref(scanState).Slice.TransverseLower),
919
- Math.trunc(unref(scanState).Slice.TransverseUpper),
920
- ];
921
- },
922
- set(value: Array<number>) {
923
- scanState.value.Slice.TransverseLower = value[0];
924
- scanState.value.Slice.TransverseLower = value[1];
925
- },
926
- });
927
- const sSlider = computed({
928
- get() {
929
- return [
930
- Math.trunc(unref(scanState).Slice.SagittalLower),
931
- Math.trunc(unref(scanState).Slice.SagittalUpper),
932
- ];
933
- },
934
- set(value: Array<number>) {
935
- scanState.value.Slice.SagittalLower = value[0];
936
- scanState.value.Slice.SagittalUpper = value[1];
937
- },
938
- });
939
-
940
- const cSlider = computed({
941
- get() {
942
- return [
943
- Math.trunc(unref(scanState).Slice.CoronalLower),
944
- Math.trunc(unref(scanState).Slice.CoronalUpper),
945
- ];
946
- },
947
- set(value: Array<number>) {
948
- scanState.value.Slice.CoronalLower = value[0];
949
- scanState.value.Slice.CoronalUpper = value[1];
950
- },
951
- });
952
- const web_gl = ref<typeof WebGL3DR | null>(null);
953
-
954
- watch(
955
- () => scanState.value.Display.Brightness,
956
- async (value: number) => {
957
- await sliderHandler(SlidersActions.sl01, value);
958
- }
959
- );
960
- watch(
961
- () => scanState.value.Display.Contrast,
962
- async (value: number) => {
963
- await sliderHandler(SlidersActions.sl02, value);
964
- }
965
- );
966
- watch(
967
- () => scanState.value.Display.Opacity,
968
- async (value: number) => {
969
- await sliderHandler(SlidersActions.sl03, value);
970
- }
971
- );
972
- watch(
973
- () => scanState.value.Display.WindowLower,
974
- async (value: number) => {
975
- await sliderHandler(SlidersActions.sl04, value);
976
- }
977
- );
978
- watch(
979
- () => scanState.value.Display.WindowUpper,
980
- async (value: number) => {
981
- await sliderHandler(SlidersActions.sl05, value);
982
- }
983
- );
984
- watch(
985
- () => scanState.value.Display.ThresholdLower,
986
- async (value: number) => {
987
- await sliderHandler(SlidersActions.sl06, value);
988
- }
989
- );
990
- watch(
991
- () => scanState.value.Display.ThresholdUpper,
992
- async (value: number) => {
993
- await sliderHandler(SlidersActions.sl07, value);
994
- }
995
- );
996
- watch(
997
- () => scanState.value.Slice.TransverseLower,
998
- async (value: number) => {
999
- await sliderHandler(SlidersActions.sl08, value);
1000
- }
1001
- );
1002
- watch(
1003
- () => scanState.value.Orientations.Transverse.Slice,
1004
- async (value: number) => {
1005
- await sliderHandler(SlidersActions.sl09, value);
1006
- }
1007
- );
1008
- watch(
1009
- () => scanState.value.Slice.TransverseUpper,
1010
- async (value: number) => {
1011
- await sliderHandler(SlidersActions.sl10, value);
1012
- }
1013
- );
1014
- watch(
1015
- () => scanState.value.Slice.SagittalLower,
1016
- async (value: number) => {
1017
- await sliderHandler(SlidersActions.sl11, value);
1018
- }
1019
- );
1020
- watch(
1021
- () => scanState.value.Orientations.Sagittal.Slice,
1022
- async (value: number) => {
1023
- await sliderHandler(SlidersActions.sl12, value);
1024
- }
1025
- );
1026
- watch(
1027
- () => scanState.value.Slice.SagittalUpper,
1028
- async (value: number) => {
1029
- await sliderHandler(SlidersActions.sl13, value);
1030
- }
1031
- );
1032
- watch(
1033
- () => scanState.value.Slice.CoronalLower,
1034
- async (value: number) => {
1035
- await sliderHandler(SlidersActions.sl14, value);
1036
- }
1037
- );
1038
- watch(
1039
- () => scanState.value.Orientations.Coronal.Slice,
1040
- async (value: number) => {
1041
- await sliderHandler(SlidersActions.sl15, value);
1042
- }
1043
- );
1044
- watch(
1045
- () => scanState.value.Slice.CoronalUpper,
1046
- async (value: number) => {
1047
- await sliderHandler(SlidersActions.sl16, value);
1048
- }
1049
- );
1050
- watch(
1051
- () => scanState.value.InteractionSettings.PanSensivitity,
1052
- async (value: number) => {
1053
- await scanMovementHandler(ScanMovementActions.sm05, value);
1054
- }
1055
- );
1056
- watch(
1057
- () => scanState.value.InteractionSettings.ZoomSensitivity,
1058
- async (value: number) => {
1059
- await scanMovementHandler(ScanMovementActions.sm08, value);
1060
- }
1061
- );
1062
- watch(
1063
- () => scanState.value.InteractionSettings.RotateSensitivity,
1064
- async (value: number) => {
1065
- await scanMovementHandler(ScanMovementActions.sm10, value);
1066
- }
1067
- );
1068
- watch(
1069
- () => scanState.value.InteractionSettings.CameraRotateSensitivity,
1070
- async (value: number) => {
1071
- await scanMovementHandler(ScanMovementActions.sm12, value);
799
+ function executeOption(key: keyof LoadViewerOptions) {
800
+ if (unref(isDemo)) {
801
+ executeDemoOption(key);
802
+ } else {
803
+ const functionToExecute = unref(props.options)[key];
804
+ if (functionToExecute !== undefined) {
805
+ functionToExecute();
806
+ }
1072
807
  }
1073
- );
808
+ }
1074
809
 
1075
- function getIconForPreset(presetName: string): string | undefined {
1076
- if (presetName === "Bone") return "fa:fas fa-bone";
1077
- if (presetName === "Brain") return "fa:fas fa-brain";
1078
- if (presetName === "Liver") return "custom:liver_icon";
1079
- if (presetName === "Lungs") return "fa:fas fa-lungs";
1080
- if (presetName === "Muscle") return "custom:muscle_icon";
1081
- if (presetName === "Temporal Bones") return "custom:temporal_bones_icon";
1082
- if (presetName === "Soft Tissue") return "custom:torso_icon";
1083
- if (presetName === "Skin") return "custom:skin_icon";
1084
- return undefined;
810
+ type WatchSlidersType = { [key in SlidersActions]: WatchSource<number> };
811
+ const watchSliders: WatchSlidersType = {
812
+ [SlidersActions.sl01]: () => scanState.value.Display.Brightness,
813
+ [SlidersActions.sl02]: () => scanState.value.Display.Contrast,
814
+ [SlidersActions.sl03]: () => scanState.value.Display.Opacity,
815
+ [SlidersActions.sl04]: () => scanState.value.Display.WindowLower,
816
+ [SlidersActions.sl05]: () => scanState.value.Display.WindowUpper,
817
+ [SlidersActions.sl06]: () => scanState.value.Display.ThresholdLower,
818
+ [SlidersActions.sl07]: () => scanState.value.Display.ThresholdUpper,
819
+ [SlidersActions.sl08]: () => scanState.value.Slice.TransverseLower,
820
+ [SlidersActions.sl09]: () => scanState.value.Orientations.Transverse.Slice,
821
+ [SlidersActions.sl10]: () => scanState.value.Slice.TransverseUpper,
822
+ [SlidersActions.sl11]: () => scanState.value.Slice.SagittalLower,
823
+ [SlidersActions.sl12]: () => scanState.value.Orientations.Sagittal.Slice,
824
+ [SlidersActions.sl13]: () => scanState.value.Slice.SagittalUpper,
825
+ [SlidersActions.sl14]: () => scanState.value.Slice.CoronalLower,
826
+ [SlidersActions.sl15]: () => scanState.value.Orientations.Coronal.Slice,
827
+ [SlidersActions.sl16]: () => scanState.value.Slice.CoronalUpper,
828
+ };
829
+
830
+ for (const slider of Object.keys(watchSliders)) {
831
+ watch(
832
+ watchSliders[slider as keyof WatchSlidersType],
833
+ async (value: number) => {
834
+ await payloadHandler.sliderHandler(slider as SlidersActions, value);
835
+ }
836
+ );
1085
837
  }
1086
- async function rotateByDeg(view: ScanView, deg: number) {
1087
- await sendPayload(
1088
- FrontEndInterfaces.scan_orientation,
1089
- ScanOrientationActions.so01,
1090
- {
1091
- Version: "0.0.1",
1092
- View: view,
1093
- Angle: deg,
838
+
839
+ type WatchScanMovementType = {
840
+ [key in ScanMovementActions]: WatchSource<number>;
841
+ };
842
+
843
+ //@ts-ignore
844
+ const watchScanMovement: WatchScanMovementType = {
845
+ [ScanMovementActions.sm05]: () =>
846
+ scanState.value.InteractionSettings.PanSensivitity,
847
+ [ScanMovementActions.sm08]: () =>
848
+ scanState.value.InteractionSettings.ZoomSensitivity,
849
+ [ScanMovementActions.sm10]: () =>
850
+ scanState.value.InteractionSettings.RotateSensitivity,
851
+ [ScanMovementActions.sm12]: () =>
852
+ scanState.value.InteractionSettings.CameraRotateSensitivity,
853
+ };
854
+
855
+ for (const scanMovement of Object.keys(watchScanMovement)) {
856
+ watch(
857
+ watchScanMovement[scanMovement as keyof typeof watchScanMovement],
858
+ async (value: number) => {
859
+ await payloadHandler.scanMovementHandler(
860
+ scanMovement as ScanMovementActions,
861
+ value
862
+ );
1094
863
  }
1095
864
  );
1096
865
  }
866
+
1097
867
  function getCurrentActiveView(position: PositionData): ScanView {
1098
868
  return unref(scanState).Layout.PositionData.length !== 1
1099
869
  ? position.DefaultView
@@ -1108,16 +878,8 @@ function getViewName(index: number) {
1108
878
  })[index];
1109
879
  }
1110
880
  async function fullscreenLayout(view: ScanView) {
1111
- await layouts("lo_01");
1112
- await viewSelection(`vs_0${view + 1}`);
1113
- }
1114
- async function scanMovementHandler(action: string, value: number) {
1115
- if (unref(transactionStarted)) return;
1116
- await scanMovement(action, value);
1117
- }
1118
- async function sliderHandler(action: string, value: number) {
1119
- if (unref(transactionStarted)) return;
1120
- await slider(action, value);
881
+ await payloadHandler.layouts(LayoutActions.lo01);
882
+ await payloadHandler.viewSelection(`vs_0${view + 1}` as ViewSelectionActions);
1121
883
  }
1122
884
 
1123
885
  function closeModal() {
@@ -1130,181 +892,27 @@ function alterValue(val: boolean) {
1130
892
  m_closeDialog.value = true;
1131
893
  return;
1132
894
  } else {
1133
- isDemo.value =
1134
- props.payload.Url ===
1135
- "https://webgl-3dr.singular.health/test_scans/01440d4e-8b04-4b90-bb2c-698535ce16d6/CHEST.3vxl";
895
+ checkIsDemo(props.payload);
1136
896
  }
1137
897
 
1138
898
  value.value = val;
1139
899
  }
1140
- async function sendPayload(
1141
- interfaceType: string,
1142
- actionType: string,
1143
- message: any
1144
- ) {
1145
- await unref(web_gl)?.sendPayload(
1146
- JSON.stringify({
1147
- Version: "0.0.1",
1148
- Interface: interfaceType,
1149
- Action: actionType,
1150
- Message: JSON.stringify(message),
1151
- })
1152
- );
1153
- }
1154
900
  async function load() {
1155
901
  instanceLoaded.value = true;
1156
902
  scanLoading.value = true;
1157
- await sendPayload("file_management", "fm_01", props.payload);
1158
- }
1159
- async function viewSelection(action: string) {
1160
- await sendPayload(FrontEndInterfaces.view_selection, action, emptyPayload);
1161
- }
1162
- async function layouts(action: string) {
1163
- if (action !== "lo_01") previousLayout.value = action;
1164
- await sendPayload(FrontEndInterfaces.layout, action, emptyPayload);
1165
- }
1166
- async function snap() {
1167
- emit("snap");
1168
- }
1169
-
1170
- async function setPreset(action: PresetsActions, preset: any) {
1171
- await sendPayload("presets", action, preset);
1172
- if (action === PresetsActions.pr02) {
1173
- currentColourPreset.value = preset;
1174
- }
1175
- }
1176
- async function slider(action: string, value: number) {
1177
- await sendPayload("sliders", action, {
1178
- Version: "0.0.1",
1179
- Value: toNumber(value),
1180
- });
903
+ await sendPayload(web_gl, "file_management", "fm_01", props.payload);
1181
904
  }
1182
- async function scanMovement(action: string, value: number) {
1183
- await sendPayload(FrontEndInterfaces.scan_movement, action, {
1184
- Version: "0.0.1",
1185
- Value: toNumber(value),
1186
- });
1187
- }
1188
- async function hoverOverCanvas(isHovering: boolean) {
1189
- await sendPayload("interactivity", "in_01", {
1190
- Version: "0.0.1",
1191
- Value: isHovering,
1192
- });
1193
- await sendPayload("interactivity", "in_02", {
1194
- Version: "0.0.1",
1195
- Value: isHovering,
1196
- });
1197
- }
1198
- async function i_scanState(_: string, message: string) {
1199
- transactionStarted.value = true;
1200
- scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2);
1201
905
 
1202
- setScanState(message);
1203
- await nextTick();
1204
- transactionStarted.value = false;
1205
- }
1206
906
  async function i_fileManagement(action: string, message: string) {
1207
- if (action !== FileManagementActions.fm02) return;
1208
- transactionStarted.value = true;
1209
-
1210
- scanStateIncoming.value = JSON.stringify(JSON.parse(message), null, 2);
1211
- const obj = JSON.parse(unref(scanStateIncoming)) as InitialScanState;
1212
-
1213
- setScanState(JSON.stringify(obj.DefaultDisplaySettings, null, 2));
1214
- initialScanState.value = obj;
1215
- huMinMax.value.max = obj.HuUpper;
1216
- huMinMax.value.min = obj.HuLower;
1217
- sMinMax.value.max = obj.XSlices;
1218
- cMinMax.value.max = obj.YSlices;
1219
- tMinMax.value.max = obj.ZSlices;
1220
- currentColourPreset.value = obj.ColourPresets[0];
1221
-
1222
- await nextTick();
1223
- transactionStarted.value = false;
1224
- scanLoading.value = false;
1225
- drawerCollapsed.value = false;
1226
- await hoverOverCanvas(false);
1227
- }
1228
-
1229
- async function i_notifications(action: string, message: string) {
1230
- const notification = JSON.parse(message) as NotificationPayload;
1231
-
1232
- switch (notification.Action) {
1233
- case InteractivityActions.in01:
1234
- case InteractivityActions.in02:
1235
- case InteractivityActions.in03:
1236
- case InteractivityActions.in04:
1237
- return;
1238
- default:
1239
- }
1240
- if (notification.Action.startsWith("sl")) return;
1241
-
1242
- let type = "success";
1243
- switch (action) {
1244
- // Muting no01
1245
- case NotificationsActions.no01:
1246
- type = "success";
1247
- return;
1248
-
1249
- case NotificationsActions.no02:
1250
- type = "warn";
1251
- break;
1252
-
1253
- case NotificationsActions.no03:
1254
- type = "error";
1255
- break;
1256
-
1257
- // Muting no04
1258
- case NotificationsActions.no04:
1259
- type = "info";
1260
- return;
907
+ if (action === FileManagementActions.fm02) {
908
+ await setInitialScanStateFromPayload(action, message);
909
+
910
+ await nextTick();
911
+ transactionStarted.value = false;
912
+ scanLoading.value = false;
913
+ drawerCollapsed.value = false;
914
+ await payloadHandler.hoverOverCanvas(false);
1261
915
  }
1262
-
1263
- notify({
1264
- title: notification.Code,
1265
- text: notification.Action,
1266
- type,
1267
- });
1268
- }
1269
- const isLayout2x2 = computed(() => {
1270
- return (
1271
- unref(scanState).Layout.PositionData.length > 1 &&
1272
- unref(scanState).Layout.PositionData[0].Anchor === AnchorPoint.TOP_LEFT &&
1273
- unref(scanState).Layout.PositionData[1].Anchor === AnchorPoint.TOP_RIGHT &&
1274
- unref(scanState).Layout.PositionData[2].Anchor ===
1275
- AnchorPoint.BOTTOM_LEFT &&
1276
- unref(scanState).Layout.PositionData[3].Anchor === AnchorPoint.BOTTOM_RIGHT
1277
- );
1278
- });
1279
- const isLayout1x3 = computed(() => {
1280
- return (
1281
- unref(scanState).Layout.PositionData.length > 1 &&
1282
- unref(scanState).Layout.PositionData[0].Anchor === AnchorPoint.CENTER &&
1283
- unref(scanState).Layout.PositionData[1].Anchor === AnchorPoint.TOP_RIGHT &&
1284
- unref(scanState).Layout.PositionData[2].Anchor === AnchorPoint.RIGHT &&
1285
- unref(scanState).Layout.PositionData[3].Anchor === AnchorPoint.BOTTOM_RIGHT
1286
- );
1287
- });
1288
-
1289
- function getCurrentGreyscalePreset() {
1290
- for (const preset of unref(initialScanState).GreyscalePresets) {
1291
- if (
1292
- (unref(scanState).Display.WindowLower === preset.Lower ||
1293
- (preset.Lower < unref(initialScanState).HuLower &&
1294
- unref(scanState).Display.WindowLower ===
1295
- unref(initialScanState).HuLower)) &&
1296
- (unref(scanState).Display.WindowUpper === preset.Upper ||
1297
- (preset.Upper > unref(initialScanState).HuUpper &&
1298
- unref(scanState).Display.WindowUpper ===
1299
- unref(initialScanState).HuUpper))
1300
- ) {
1301
- return preset.Name;
1302
- }
1303
- }
1304
- return undefined;
1305
- }
1306
- function setScanState(message: string) {
1307
- scanState.value = JSON.parse(message) as CurrentScanState;
1308
916
  }
1309
917
 
1310
918
  function handleOnPayload(
@@ -1313,13 +921,13 @@ function handleOnPayload(
1313
921
  message: string
1314
922
  ) {
1315
923
  if (interfaceSet === FrontEndInterfaces.scan_state) {
1316
- i_scanState(actionSet, message);
924
+ setScanStateFromPayload(actionSet, message);
1317
925
  }
1318
926
  if (interfaceSet === FrontEndInterfaces.file_management) {
1319
927
  i_fileManagement(actionSet, message);
1320
928
  }
1321
929
  if (interfaceSet === FrontEndInterfaces.notifications) {
1322
- i_notifications(actionSet, message);
930
+ handleNotification(actionSet as NotificationsActions, message);
1323
931
  }
1324
932
  }
1325
933
 
@@ -1327,29 +935,18 @@ defineExpose({
1327
935
  alterValue,
1328
936
  load,
1329
937
  handleOnPayload,
1330
- setScanState,
1331
938
  sendPayload,
1332
939
  getIconForPreset,
1333
- cSlider,
1334
- sSlider,
1335
- tSlider,
1336
940
  thresholdSlider,
1337
941
  windowSlider,
1338
- isLayout2x2,
1339
- isLayout1x3,
1340
942
  m_closeDialog,
1341
- getCurrentGreyscalePreset,
1342
943
  closeModal,
1343
- snap,
1344
944
  scanState,
1345
945
  initialScanState,
1346
946
  footerItems,
1347
- rotateByDeg,
1348
947
  getCurrentActiveView,
1349
948
  getViewName,
1350
949
  fullscreenLayout,
1351
- layouts,
1352
- setPreset,
1353
950
  value,
1354
951
  transactionStarted,
1355
952
  });