@geode/opengeodeweb-front 10.41.0-rc.1 → 10.41.0-rc.3

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 (26) hide show
  1. package/app/components/HybridRenderingView.vue +2 -0
  2. package/app/components/RemoteRenderingView.vue +2 -0
  3. package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +0 -1
  4. package/app/components/Viewer/Generic/Model/ComponentPointsOptions.vue +245 -0
  5. package/app/components/Viewer/Generic/Model/ModelPointsCard.vue +141 -0
  6. package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +7 -67
  7. package/app/components/Viewer/Generic/Model/PointsOptions.vue +2 -40
  8. package/app/components/Viewer/Options/ColormapQuickPicker.vue +11 -2
  9. package/app/composables/attribute_coloring_style.ts +182 -0
  10. package/app/composables/global_attribute_style.ts +55 -366
  11. package/app/composables/model_attribute_style.ts +79 -0
  12. package/app/composables/model_menu_context.ts +101 -0
  13. package/app/composables/use_quick_colormap.ts +4 -1
  14. package/app/stores/data.ts +12 -0
  15. package/app/utils/attribute_range.ts +15 -15
  16. package/internal/stores/data_style/model/blocks/index.ts +4 -0
  17. package/internal/stores/data_style/model/blocks/points.ts +51 -0
  18. package/internal/stores/data_style/model/index.ts +6 -0
  19. package/internal/stores/data_style/model/lines/index.ts +4 -0
  20. package/internal/stores/data_style/model/lines/points.ts +51 -0
  21. package/internal/stores/data_style/model/points/component.ts +423 -0
  22. package/internal/stores/data_style/model/points/size.ts +13 -1
  23. package/internal/stores/data_style/model/points/visibility.ts +13 -3
  24. package/internal/stores/data_style/model/surfaces/index.ts +4 -0
  25. package/internal/stores/data_style/model/surfaces/points.ts +51 -0
  26. package/package.json +1 -1
@@ -98,10 +98,12 @@ async function handleClick(event: PointerEvent): Promise<void> {
98
98
  <ClientOnly>
99
99
  <div data-testid="hybridViewer" class="fill-height" style="position: relative; height: 100%">
100
100
  <ColormapQuickPicker
101
+ :key="quickColormap.data_id"
101
102
  v-model:show="quickColormap.show"
102
103
  :x="quickColormap.x"
103
104
  :y="quickColormap.y"
104
105
  :data-id="quickColormap.data_id"
106
+ :block-ids="quickColormap.block_ids"
105
107
  />
106
108
  <ZoomBoxOverlay v-if="hybridViewerStore.is_zoom_box_active" />
107
109
  <ViewToolbar />
@@ -116,10 +116,12 @@ onMounted(async () => {
116
116
  <ClientOnly>
117
117
  <div style="position: relative; width: 100%; height: 100%">
118
118
  <ColormapQuickPicker
119
+ :key="quickColormap.data_id"
119
120
  v-model:show="quickColormap.show"
120
121
  :x="quickColormap.x"
121
122
  :y="quickColormap.y"
122
123
  :data-id="quickColormap.data_id"
124
+ :block-ids="quickColormap.block_ids"
123
125
  />
124
126
  <ViewToolbar />
125
127
  <slot name="ui"></slot>
@@ -172,7 +172,6 @@ async function setVertexAttributeRangesPerData(ranges: RangesPerData): Promise<v
172
172
  v-model:vertex_attribute_color_map="vertex_attribute_color_map"
173
173
  v-model:vertex_attribute_no_data_color="vertex_attribute_no_data_color"
174
174
  v-model:vertex_attribute_time_step="vertex_attribute_time_step"
175
- :capabilities="{ vertex: { available: false } }"
176
175
  />
177
176
  </template>
178
177
  </template>
@@ -0,0 +1,245 @@
1
+ <script setup lang="ts">
2
+ import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
3
+ import ViewerOptionsColoringTypeSelector from "@ogw_front/components/Viewer/Options/ColoringTypeSelector.vue";
4
+ import ViewerOptionsSizeSlider from "@ogw_front/components/Viewer/Options/Sliders/Size.vue";
5
+ import VisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
6
+ import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_typed_schemas.js";
7
+ import { useDataStyleStore } from "@ogw_front/stores/data_style";
8
+ import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
9
+
10
+ interface PointsTarget {
11
+ componentType: "Surface" | "Line" | "Block";
12
+ componentIds: string[];
13
+ }
14
+
15
+ interface Props {
16
+ modelId: string;
17
+ targets: PointsTarget[];
18
+ referenceComponentId?: string;
19
+ }
20
+
21
+ const { modelId, targets, referenceComponentId = undefined } = defineProps<Props>();
22
+
23
+ const dataStyleStore = useDataStyleStore();
24
+ const hybridViewerStore = useHybridViewerStore();
25
+
26
+ // Each component type exposes its own points functions in the data style store
27
+ const POINTS_STYLES = {
28
+ Surface: {
29
+ visibility: dataStyleStore.modelSurfacePointsVisibility,
30
+ size: dataStyleStore.modelSurfacePointsSize,
31
+ color: dataStyleStore.modelSurfacePointsColor,
32
+ activeColoring: dataStyleStore.modelSurfacePointsActiveColoring,
33
+ vertexAttributeName: dataStyleStore.modelSurfacePointsVertexAttributeName,
34
+ vertexAttributeItem: dataStyleStore.modelSurfacePointsVertexAttributeItem,
35
+ vertexAttributeRange: dataStyleStore.modelSurfacePointsVertexAttributeRange,
36
+ vertexAttributeColorMap: dataStyleStore.modelSurfacePointsVertexAttributeColorMap,
37
+ vertexAttributeNoDataColor: dataStyleStore.modelSurfacePointsVertexAttributeNoDataColor,
38
+ setVisibility: dataStyleStore.setModelSurfacesPointsVisibility,
39
+ setSize: dataStyleStore.setModelSurfacesPointsSize,
40
+ setColor: dataStyleStore.setModelSurfacesPointsColor,
41
+ setActiveColoring: dataStyleStore.setModelSurfacesPointsActiveColoring,
42
+ setVertexAttributeName: dataStyleStore.setModelSurfacesPointsVertexAttributeName,
43
+ setVertexAttributeItem: dataStyleStore.setModelSurfacesPointsVertexAttributeItem,
44
+ setVertexAttributeRange: dataStyleStore.setModelSurfacesPointsVertexAttributeRange,
45
+ setVertexAttributeColorMap: dataStyleStore.setModelSurfacesPointsVertexAttributeColorMap,
46
+ setVertexAttributeNoDataColor: dataStyleStore.setModelSurfacesPointsVertexAttributeNoDataColor,
47
+ },
48
+ Line: {
49
+ visibility: dataStyleStore.modelLinePointsVisibility,
50
+ size: dataStyleStore.modelLinePointsSize,
51
+ color: dataStyleStore.modelLinePointsColor,
52
+ activeColoring: dataStyleStore.modelLinePointsActiveColoring,
53
+ vertexAttributeName: dataStyleStore.modelLinePointsVertexAttributeName,
54
+ vertexAttributeItem: dataStyleStore.modelLinePointsVertexAttributeItem,
55
+ vertexAttributeRange: dataStyleStore.modelLinePointsVertexAttributeRange,
56
+ vertexAttributeColorMap: dataStyleStore.modelLinePointsVertexAttributeColorMap,
57
+ vertexAttributeNoDataColor: dataStyleStore.modelLinePointsVertexAttributeNoDataColor,
58
+ setVisibility: dataStyleStore.setModelLinesPointsVisibility,
59
+ setSize: dataStyleStore.setModelLinesPointsSize,
60
+ setColor: dataStyleStore.setModelLinesPointsColor,
61
+ setActiveColoring: dataStyleStore.setModelLinesPointsActiveColoring,
62
+ setVertexAttributeName: dataStyleStore.setModelLinesPointsVertexAttributeName,
63
+ setVertexAttributeItem: dataStyleStore.setModelLinesPointsVertexAttributeItem,
64
+ setVertexAttributeRange: dataStyleStore.setModelLinesPointsVertexAttributeRange,
65
+ setVertexAttributeColorMap: dataStyleStore.setModelLinesPointsVertexAttributeColorMap,
66
+ setVertexAttributeNoDataColor: dataStyleStore.setModelLinesPointsVertexAttributeNoDataColor,
67
+ },
68
+ Block: {
69
+ visibility: dataStyleStore.modelBlockPointsVisibility,
70
+ size: dataStyleStore.modelBlockPointsSize,
71
+ color: dataStyleStore.modelBlockPointsColor,
72
+ activeColoring: dataStyleStore.modelBlockPointsActiveColoring,
73
+ vertexAttributeName: dataStyleStore.modelBlockPointsVertexAttributeName,
74
+ vertexAttributeItem: dataStyleStore.modelBlockPointsVertexAttributeItem,
75
+ vertexAttributeRange: dataStyleStore.modelBlockPointsVertexAttributeRange,
76
+ vertexAttributeColorMap: dataStyleStore.modelBlockPointsVertexAttributeColorMap,
77
+ vertexAttributeNoDataColor: dataStyleStore.modelBlockPointsVertexAttributeNoDataColor,
78
+ setVisibility: dataStyleStore.setModelBlocksPointsVisibility,
79
+ setSize: dataStyleStore.setModelBlocksPointsSize,
80
+ setColor: dataStyleStore.setModelBlocksPointsColor,
81
+ setActiveColoring: dataStyleStore.setModelBlocksPointsActiveColoring,
82
+ setVertexAttributeName: dataStyleStore.setModelBlocksPointsVertexAttributeName,
83
+ setVertexAttributeItem: dataStyleStore.setModelBlocksPointsVertexAttributeItem,
84
+ setVertexAttributeRange: dataStyleStore.setModelBlocksPointsVertexAttributeRange,
85
+ setVertexAttributeColorMap: dataStyleStore.setModelBlocksPointsVertexAttributeColorMap,
86
+ setVertexAttributeNoDataColor: dataStyleStore.setModelBlocksPointsVertexAttributeNoDataColor,
87
+ },
88
+ };
89
+ type PointsStyle = (typeof POINTS_STYLES)[PointsTarget["componentType"]];
90
+
91
+ // Values are read from the first target, changes are applied to every target
92
+ const pointsStyle = computed<PointsStyle | undefined>(() => {
93
+ const [reference] = targets;
94
+ return reference === undefined ? undefined : POINTS_STYLES[reference.componentType];
95
+ });
96
+ const allComponentIds = computed<string[]>(() => targets.flatMap((target) => target.componentIds));
97
+
98
+ async function applyPointsStyle(
99
+ setter: (style: PointsStyle, componentIds: string[]) => Promise<unknown>,
100
+ ): Promise<void> {
101
+ await Promise.all(
102
+ targets.map(async (target) => {
103
+ await setter(POINTS_STYLES[target.componentType], target.componentIds);
104
+ }),
105
+ );
106
+ hybridViewerStore.remoteRender();
107
+ }
108
+
109
+ const visibility = computed<boolean | undefined>({
110
+ get: () => pointsStyle.value?.visibility(modelId, referenceComponentId),
111
+ set: async (newValue) => {
112
+ if (newValue === undefined) {
113
+ return;
114
+ }
115
+ await applyPointsStyle((style, ids) => style.setVisibility(modelId, ids, newValue));
116
+ },
117
+ });
118
+
119
+ const size = computed<number | undefined>({
120
+ get: () => pointsStyle.value?.size(modelId, referenceComponentId),
121
+ set: async (newValue) => {
122
+ if (newValue === undefined) {
123
+ return;
124
+ }
125
+ await applyPointsStyle((style, ids) => style.setSize(modelId, ids, newValue));
126
+ },
127
+ });
128
+
129
+ const activeColoring = computed<string | undefined>({
130
+ get: () => pointsStyle.value?.activeColoring(modelId, referenceComponentId),
131
+ set: async (newValue) => {
132
+ if (newValue === undefined) {
133
+ return;
134
+ }
135
+ await applyPointsStyle((style, ids) => style.setActiveColoring(modelId, ids, newValue));
136
+ },
137
+ });
138
+
139
+ const color = computed<RGBAColor | undefined>({
140
+ get: () => pointsStyle.value?.color(modelId, referenceComponentId),
141
+ set: async (newValue) => {
142
+ if (newValue === undefined) {
143
+ return;
144
+ }
145
+ await applyPointsStyle((style, ids) => style.setColor(modelId, ids, newValue));
146
+ },
147
+ });
148
+
149
+ const vertexAttributeName = computed<string | undefined>({
150
+ get: () => pointsStyle.value?.vertexAttributeName(modelId, referenceComponentId),
151
+ set: async (newValue) => {
152
+ if (newValue === undefined) {
153
+ return;
154
+ }
155
+ await applyPointsStyle((style, ids) => style.setVertexAttributeName(modelId, ids, newValue));
156
+ },
157
+ });
158
+
159
+ const vertexAttributeItem = computed<number | undefined>({
160
+ get: () => pointsStyle.value?.vertexAttributeItem(modelId, referenceComponentId),
161
+ set: async (newValue) => {
162
+ if (newValue === undefined) {
163
+ return;
164
+ }
165
+ await applyPointsStyle((style, ids) => style.setVertexAttributeItem(modelId, ids, newValue));
166
+ },
167
+ });
168
+
169
+ const vertexAttributeRange = computed<(number | undefined)[] | undefined>({
170
+ get: () => pointsStyle.value?.vertexAttributeRange(modelId, referenceComponentId),
171
+ set: async (newValue) => {
172
+ if (newValue === undefined) {
173
+ return;
174
+ }
175
+ const [minimum, maximum] = newValue;
176
+ if (minimum === undefined || maximum === undefined) {
177
+ return;
178
+ }
179
+ await applyPointsStyle((style, ids) =>
180
+ style.setVertexAttributeRange(modelId, ids, minimum, maximum),
181
+ );
182
+ },
183
+ });
184
+
185
+ const vertexAttributeColorMap = computed<string | undefined>({
186
+ get: () => pointsStyle.value?.vertexAttributeColorMap(modelId, referenceComponentId),
187
+ set: async (newValue) => {
188
+ await applyPointsStyle((style, ids) =>
189
+ style.setVertexAttributeColorMap(modelId, ids, newValue),
190
+ );
191
+ },
192
+ });
193
+
194
+ const vertexAttributeNoDataColor = computed<RGBAColor | undefined>({
195
+ get: () => pointsStyle.value?.vertexAttributeNoDataColor(modelId, referenceComponentId),
196
+ set: async (newValue) => {
197
+ if (newValue === undefined) {
198
+ return;
199
+ }
200
+ await applyPointsStyle((style, ids) =>
201
+ style.setVertexAttributeNoDataColor(modelId, ids, newValue),
202
+ );
203
+ },
204
+ });
205
+
206
+ const capabilities = {
207
+ color: { available: true },
208
+ textures: { available: false },
209
+ vertex: { available: true },
210
+ edge: { available: false },
211
+ cell: { available: false },
212
+ polygon: { available: false },
213
+ polyhedron: { available: false },
214
+ };
215
+
216
+ const backSchemas = back_schemas.opengeodeweb_back;
217
+ const attributeSchemas = {
218
+ vertex: {
219
+ names: backSchemas.model_component_vertex_attribute_names,
220
+ range: backSchemas.model_component_vertex_attribute_range,
221
+ },
222
+ };
223
+ </script>
224
+
225
+ <template>
226
+ <div class="mt-2" data-testid="modelComponentPointsOptions">
227
+ <VisibilitySwitch data-testid="modelComponentPointsVisibilitySwitch" v-model="visibility" />
228
+ <template v-if="visibility">
229
+ <ViewerOptionsSizeSlider data-testid="modelComponentPointsSizeSlider" v-model="size" />
230
+ <ViewerOptionsColoringTypeSelector
231
+ :id="modelId"
232
+ :componentIds="allComponentIds"
233
+ v-model:coloring_style_key="activeColoring"
234
+ v-model:color="color"
235
+ v-model:vertex_attribute_name="vertexAttributeName"
236
+ v-model:vertex_attribute_item="vertexAttributeItem"
237
+ v-model:vertex_attribute_range="vertexAttributeRange"
238
+ v-model:vertex_attribute_color_map="vertexAttributeColorMap"
239
+ v-model:vertex_attribute_no_data_color="vertexAttributeNoDataColor"
240
+ :capabilities="capabilities"
241
+ :schemas="attributeSchemas"
242
+ />
243
+ </template>
244
+ </div>
245
+ </template>
@@ -0,0 +1,141 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ type ModelMenuItemProps,
4
+ useModelMenuContext,
5
+ } from "@ogw_front/composables/model_menu_context";
6
+ import OptionsSection from "@ogw_front/components/Viewer/Options/OptionsSection.vue";
7
+ import ViewerGenericModelComponentPointsOptions from "@ogw_front/components/Viewer/Generic/Model/ComponentPointsOptions.vue";
8
+ import VisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
9
+ import { useBatchStyle } from "@ogw_front/composables/batch_style";
10
+ import { useDataStore } from "@ogw_front/stores/data";
11
+ import { useDataStyleStore } from "@ogw_front/stores/data_style";
12
+ import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
13
+
14
+ // Corners have no points options: their points are the corners themselves
15
+ const POINTS_TYPE_TITLES = {
16
+ Surface: "Surfaces Points Options",
17
+ Line: "Lines Points Options",
18
+ Block: "Blocks Points Options",
19
+ } as const;
20
+ type PointsComponentType = keyof typeof POINTS_TYPE_TITLES;
21
+ const POINTS_COMPONENT_TYPES: PointsComponentType[] = ["Surface", "Line", "Block"];
22
+
23
+ function isPointsComponentType(type: string | undefined): type is PointsComponentType {
24
+ return type !== undefined && type in POINTS_TYPE_TITLES;
25
+ }
26
+
27
+ interface Props {
28
+ itemProps: ModelMenuItemProps;
29
+ }
30
+
31
+ const { itemProps } = defineProps<Props>();
32
+
33
+ const dataStore = useDataStore();
34
+ const dataStyleStore = useDataStyleStore();
35
+ const hybridViewerStore = useHybridViewerStore();
36
+ const { applyBatchStyle } = useBatchStyle();
37
+
38
+ const { modelId, componentId, componentType, collections, targetComponentIds } =
39
+ useModelMenuContext(() => itemProps);
40
+
41
+ const modelPointsVisibility = computed<boolean>({
42
+ get: () => dataStyleStore.modelPointsVisibility(modelId.value),
43
+ set: async (newValue) => {
44
+ await applyBatchStyle(modelId.value, (targetId: string) =>
45
+ dataStyleStore.setModelPointsVisibility(targetId, newValue),
46
+ );
47
+ hybridViewerStore.remoteRender();
48
+ },
49
+ });
50
+
51
+ const pointsComponentType = computed<PointsComponentType | undefined>(() =>
52
+ isPointsComponentType(componentType.value) ? componentType.value : undefined,
53
+ );
54
+
55
+ const allComponentsTargets = ref<{ componentType: PointsComponentType; componentIds: string[] }[]>(
56
+ [],
57
+ );
58
+ watch(
59
+ modelId,
60
+ async (currentModelId) => {
61
+ const targets = await Promise.all(
62
+ POINTS_COMPONENT_TYPES.map(async (type) => ({
63
+ componentType: type,
64
+ componentIds: await dataStore.getMeshComponentGeodeIds(currentModelId, type),
65
+ })),
66
+ );
67
+ if (modelId.value === currentModelId) {
68
+ allComponentsTargets.value = targets.filter((target) => target.componentIds.length > 0);
69
+ }
70
+ },
71
+ { immediate: true },
72
+ );
73
+
74
+ const typeTargets = computed(() =>
75
+ pointsComponentType.value === undefined
76
+ ? []
77
+ : [{ componentType: pointsComponentType.value, componentIds: targetComponentIds.value }],
78
+ );
79
+ const typeReferenceId = computed<string | undefined>(() =>
80
+ collections.value ? targetComponentIds.value[0] : undefined,
81
+ );
82
+
83
+ const componentTargets = computed(() =>
84
+ pointsComponentType.value === undefined || componentId.value === undefined
85
+ ? []
86
+ : [{ componentType: pointsComponentType.value, componentIds: [componentId.value] }],
87
+ );
88
+ </script>
89
+
90
+ <template>
91
+ <v-sheet class="model-points-card" color="transparent">
92
+ <OptionsSection title="Model Points Options">
93
+ <VisibilitySwitch data-testid="modelPointsVisibilitySwitch" v-model="modelPointsVisibility" />
94
+ </OptionsSection>
95
+
96
+ <OptionsSection
97
+ v-if="!componentType && !componentId && allComponentsTargets.length > 0"
98
+ title="Components Points Options"
99
+ data-testid="modelPointsComponentsOptions"
100
+ class="mt-4"
101
+ >
102
+ <ViewerGenericModelComponentPointsOptions
103
+ :modelId="modelId"
104
+ :targets="allComponentsTargets"
105
+ />
106
+ </OptionsSection>
107
+
108
+ <OptionsSection
109
+ v-if="pointsComponentType"
110
+ :title="POINTS_TYPE_TITLES[pointsComponentType]"
111
+ data-testid="modelPointsComponentTypeOptions"
112
+ class="mt-4"
113
+ >
114
+ <ViewerGenericModelComponentPointsOptions
115
+ :modelId="modelId"
116
+ :targets="typeTargets"
117
+ :referenceComponentId="typeReferenceId"
118
+ />
119
+ </OptionsSection>
120
+
121
+ <OptionsSection
122
+ v-if="pointsComponentType && componentId"
123
+ title="Component Points Options"
124
+ data-testid="modelPointsComponentOptions"
125
+ class="mt-4"
126
+ >
127
+ <ViewerGenericModelComponentPointsOptions
128
+ :modelId="modelId"
129
+ :targets="componentTargets"
130
+ :referenceComponentId="componentId"
131
+ />
132
+ </OptionsSection>
133
+ </v-sheet>
134
+ </template>
135
+
136
+ <style scoped>
137
+ .model-points-card {
138
+ padding-top: 12px;
139
+ overflow-x: hidden;
140
+ }
141
+ </style>
@@ -1,95 +1,35 @@
1
1
  <script setup lang="ts">
2
+ import {
3
+ type ModelMenuItemProps,
4
+ useModelMenuContext,
5
+ } from "@ogw_front/composables/model_menu_context";
2
6
  import BlocksOptions from "./BlocksOptions.vue";
3
- import type { CollectionComponent } from "@ogw_front/stores/data_helpers/collections";
4
7
  import CornersOptions from "./CornersOptions.vue";
5
8
  import LinesOptions from "./LinesOptions.vue";
6
- import { MESH_COMPONENT_TYPES } from "@ogw_front/utils/default_styles";
7
9
  import OptionsSection from "@ogw_front/components/Viewer/Options/OptionsSection.vue";
8
10
  import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
9
11
  import SurfacesOptions from "./SurfacesOptions.vue";
10
12
  import ViewerOptionsColoringTypeSelector from "@ogw_front/components/Viewer/Options/ColoringTypeSelector.vue";
11
13
  import VisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
12
14
  import { useBatchStyle } from "@ogw_front/composables/batch_style";
13
- import { useDataStore } from "@ogw_front/stores/data";
14
15
  import { useDataStyleStore } from "@ogw_front/stores/data_style";
15
16
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
16
17
 
17
18
  const dataStyleStore = useDataStyleStore();
18
19
  const hybridViewerStore = useHybridViewerStore();
19
- const dataStore = useDataStore();
20
20
  const { applyBatchStyle } = useBatchStyle();
21
21
 
22
22
  interface Props {
23
- itemProps: Record<string, unknown>;
23
+ itemProps: ModelMenuItemProps;
24
24
  }
25
25
 
26
26
  const { itemProps } = defineProps<Props>();
27
27
 
28
- const modelId = computed<string>(() => itemProps.meta_data.modelId || itemProps.id);
29
- const componentId = computed<string | undefined>(() => itemProps.meta_data.pickedComponentId);
28
+ const { modelId, componentId, componentType, collections, targetComponentIds } =
29
+ useModelMenuContext(() => itemProps);
30
30
  function visibleComponents(targetId: string): string[] {
31
31
  return dataStyleStore.visibleMeshComponents(targetId).value || [];
32
32
  }
33
- const componentType = ref<string | undefined>(undefined);
34
- const collections = ref<CollectionComponent[] | undefined>(undefined);
35
-
36
- watch(
37
- () => [
38
- modelId.value,
39
- componentId.value,
40
- itemProps.meta_data.viewer_type,
41
- itemProps.meta_data.modelComponentType,
42
- ],
43
- async () => {
44
- componentType.value = undefined;
45
- collections.value = undefined;
46
- if (itemProps.meta_data.viewer_type === "model_component_type") {
47
- const { modelComponentType, targetComponentIds: ids } = itemProps.meta_data;
48
- if (MESH_COMPONENT_TYPES.includes(modelComponentType)) {
49
- componentType.value = modelComponentType;
50
- } else {
51
- const collectionsByType = await dataStore.fetchAllCollectionComponents(modelId.value);
52
- collections.value = collectionsByType[modelComponentType].filter((collection) =>
53
- collection.children.every((child) => ids.includes(child.id)),
54
- );
55
- componentType.value = collections.value[0].children[0].category;
56
- }
57
- } else if (componentId.value && modelId.value) {
58
- const currentModelId = modelId.value;
59
- const currentCompId = componentId.value;
60
- const type = await dataStore.meshComponentType(currentModelId, currentCompId);
61
- if (
62
- modelId.value === currentModelId &&
63
- componentId.value === currentCompId &&
64
- itemProps.meta_data.viewer_type !== "model_component_type"
65
- ) {
66
- componentType.value = type;
67
- }
68
- }
69
- },
70
- { immediate: true },
71
- );
72
-
73
- const targetComponentIds = ref<string[]>([]);
74
- watch(
75
- () => [modelId.value, componentType.value, itemProps.meta_data.targetComponentIds],
76
- async () => {
77
- targetComponentIds.value = [];
78
- if (itemProps.meta_data.targetComponentIds) {
79
- targetComponentIds.value = itemProps.meta_data.targetComponentIds;
80
- return;
81
- }
82
- if (componentType.value && modelId.value) {
83
- const currentModelId = modelId.value;
84
- const currentType = componentType.value;
85
- const ids = await dataStore.getMeshComponentGeodeIds(currentModelId, currentType);
86
- if (modelId.value === currentModelId && componentType.value === currentType) {
87
- targetComponentIds.value = ids;
88
- }
89
- }
90
- },
91
- { immediate: true },
92
- );
93
33
 
94
34
  const modelVisibility = computed<boolean | undefined>({
95
35
  get: () => dataStyleStore.modelVisibility(modelId.value),
@@ -2,45 +2,14 @@
2
2
  import ViewerContextMenuItem, {
3
3
  type ItemProps,
4
4
  } from "@ogw_front/components/Viewer/ContextMenu/ContextMenuItem.vue";
5
+ import ModelPointsCard from "./ModelPointsCard.vue";
5
6
  import SurfacePoints from "@ogw_front/assets/viewer_svgs/surface_points.svg";
6
- import ViewerOptionsSizeSlider from "@ogw_front/components/Viewer/Options/Sliders/Size.vue";
7
- import ViewerOptionsVisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
8
- import { useBatchStyle } from "@ogw_front/composables/batch_style";
9
- import { useDataStyleStore } from "@ogw_front/stores/data_style";
10
- import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
11
-
12
- const dataStyleStore = useDataStyleStore();
13
- const hybridViewerStore = useHybridViewerStore();
14
- const { applyBatchStyle } = useBatchStyle();
15
7
 
16
8
  interface Props {
17
9
  itemProps: ItemProps & { index: number };
18
10
  }
19
11
 
20
12
  const { itemProps } = defineProps<Props>();
21
-
22
- const id = computed<string>(
23
- () => (itemProps.meta_data.modelId as string | undefined) || itemProps.id,
24
- );
25
-
26
- const visibility = computed<boolean>({
27
- get: () => dataStyleStore.modelPointsVisibility(id.value),
28
- set: async (newValue) => {
29
- await applyBatchStyle(id.value, (targetId: string) =>
30
- dataStyleStore.setModelPointsVisibility(targetId, newValue),
31
- );
32
- hybridViewerStore.remoteRender();
33
- },
34
- });
35
- const size = computed<number>({
36
- get: () => dataStyleStore.modelPointsSize(id.value),
37
- set: async (newValue) => {
38
- await applyBatchStyle(id.value, (targetId: string) =>
39
- dataStyleStore.setModelPointsSize(targetId, newValue),
40
- );
41
- hybridViewerStore.remoteRender();
42
- },
43
- });
44
13
  </script>
45
14
 
46
15
  <template>
@@ -52,14 +21,7 @@ const size = computed<number>({
52
21
  :btnImage="SurfacePoints"
53
22
  >
54
23
  <template #options>
55
- <ViewerOptionsVisibilitySwitch
56
- data-testid="modelPointsVisibilitySwitch"
57
- v-model="visibility"
58
- />
59
- <template v-if="visibility">
60
- <v-divider class="my-2" />
61
- <ViewerOptionsSizeSlider data-testid="modelPointsSizeSlider" v-model="size" />
62
- </template>
24
+ <ModelPointsCard :itemProps="itemProps" />
63
25
  </template>
64
26
  </ViewerContextMenuItem>
65
27
  </template>
@@ -5,18 +5,21 @@ import TimeStepSlider from "@ogw_front/components/Viewer/Options/TimeStepSlider.
5
5
 
6
6
  import { getPresetsWithCurrentAtTop } from "@ogw_front/utils/colormap";
7
7
  import { useGlobalAttributeStyle } from "@ogw_front/composables/global_attribute_style";
8
+ import { useModelAttributeStyle } from "@ogw_front/composables/model_attribute_style";
8
9
 
9
10
  interface Props {
10
11
  dataId?: string;
12
+ blockIds?: number[];
11
13
  x: number;
12
14
  y: number;
13
15
  }
14
16
 
15
- const { dataId = undefined, x, y } = defineProps<Props>();
17
+ const { dataId = undefined, blockIds = undefined, x, y } = defineProps<Props>();
16
18
 
17
19
  const show = defineModel<boolean>("show", { default: false });
18
20
 
19
21
  const dataIdRef = computed<string>(() => dataId);
22
+ // The parent keys this picker on the picked data: a mesh or a model, so the style is chosen once here
20
23
  const {
21
24
  currentColormap,
22
25
  currentRange,
@@ -25,7 +28,13 @@ const {
25
28
  currentTimeSteps,
26
29
  currentTimeStep,
27
30
  loadTimeSteps,
28
- } = useGlobalAttributeStyle(dataIdRef);
31
+ } =
32
+ blockIds === undefined
33
+ ? useGlobalAttributeStyle(dataIdRef)
34
+ : useModelAttributeStyle(
35
+ dataIdRef,
36
+ computed<number[]>(() => blockIds),
37
+ );
29
38
 
30
39
  watch(show, async (isShown) => {
31
40
  if (isShown) {