@@ -22,6 +22,7 @@ import {
2222 StyleManager , TrackFilterControls , GroupFilterControls ,
2323 ConfigurationManager ,
2424} from ' vue-media-annotator/index' ;
25+ import VisualMaskManager from ' vue-media-annotator/visualMasks' ;
2526import { provideAnnotator } from ' vue-media-annotator/provides' ;
2627
2728import {
@@ -66,6 +67,7 @@ import { useRoute } from 'vue-router/composables';
6667import AttributeShortcutToggle from ' ./Attributes/AttributeShortcutToggle.vue' ;
6768import GroupSidebarVue from ' ./GroupSidebar.vue' ;
6869import MultiCamToolsVue from ' ./MultiCamTools.vue' ;
70+ import VisualMaskSidebarVue from ' ./VisualMaskSidebar.vue' ;
6971import PrevNext from ' ./PrevNext.vue' ;
7072import AttributesSideBarVue from ' ./Attributes/AttributesSideBar.vue' ;
7173import TypeThresholdVue from ' ./TypeThreshold.vue' ;
@@ -172,6 +174,14 @@ export default defineComponent({
172174 });
173175
174176 const store = useStore ();
177+ const isConfigOwnerAdmin = computed (() => {
178+ const currentUser = store .state .User .user as ({
179+ admin? : boolean ;
180+ _id? : string ;
181+ groups? : string [];
182+ } | null );
183+ return configurationManager .isConfigOwnerAdmin (currentUser );
184+ });
175185
176186 const {
177187 save : saveToServer,
@@ -208,12 +218,32 @@ export default defineComponent({
208218 const vuetify = inject (' vuetify' ) as Vuetify ;
209219 const trackStyleManager = new StyleManager ({ markChangesPending , vuetify });
210220 const groupStyleManager = new StyleManager ({ markChangesPending , vuetify });
221+ const visualMaskStyleManager = new StyleManager ({ markChangesPending , vuetify });
211222
212223 const cameraStore = new CameraStore ({ markChangesPending });
213224 // eslint-disable-next-line max-len
214225 const configurationManager = new ConfigurationManager ({
215226 configurationId , setConfigurationId , saveConfiguration , transferConfiguration ,
216227 });
228+ const visualMaskManager = new VisualMaskManager ({
229+ markChangesPending ,
230+ styleManager: visualMaskStyleManager ,
231+ syncConfiguration : (visualMasks ) => {
232+ if (! configurationManager .configuration .value ) {
233+ if (! Object .keys (visualMasks ).length ) {
234+ return ;
235+ }
236+ configurationManager .setConfiguration ({});
237+ }
238+ if (configurationManager .configuration .value ) {
239+ if (Object .keys (visualMasks ).length ) {
240+ configurationManager .configuration .value .visualMasks = visualMasks ;
241+ } else {
242+ delete configurationManager .configuration .value .visualMasks ;
243+ }
244+ }
245+ },
246+ });
217247
218248 // This context for removal
219249 const removeGroups = (id : AnnotationId ) => {
@@ -507,6 +537,10 @@ export default defineComponent({
507537 handler .trackSelect (selectedTrackId .value , false );
508538 }
509539 try {
540+ await configurationManager .saveConfiguration (
541+ configurationId .value ,
542+ { visualMasks: visualMaskManager .serialize () },
543+ );
510544 await saveToServer ({
511545 customTypeStyling: trackStyleManager .getTypeStyles (trackFilters .allTypes ),
512546 customGroupStyling: groupStyleManager .getTypeStyles (groupFilters .allTypes ),
@@ -526,7 +560,8 @@ export default defineComponent({
526560 }
527561 } catch (err ) {
528562 let text = ' Unable to Save Data' ;
529- if (err .response && err .response .status === 403 ) {
563+ const errorResponse = err as { response? : { status? : number } };
564+ if (errorResponse .response && errorResponse .response .status === 403 ) {
530565 text = ' You do not have permission to Save Data to this Folder.' ;
531566 }
532567 await prompt ({
@@ -635,6 +670,7 @@ export default defineComponent({
635670 configurationManager .setConfiguration (
636671 config .diveConfig .metadata .configuration ,
637672 );
673+ visualMaskManager .load (config .diveConfig .metadata .configuration .visualMasks );
638674
639675 if (config .diveConfig .metadata .configuration .general ?.baseConfiguration ) {
640676 configurationManager .setConfigurationId (
@@ -644,6 +680,8 @@ export default defineComponent({
644680 if (config .diveConfig .metadata .configuration .filterTimelines ) {
645681 useTimelineFilters .loadFilterTimelines (config .diveConfig .metadata .configuration .filterTimelines );
646682 }
683+ } else {
684+ visualMaskManager .load ();
647685 }
648686 const flatUIMap = configurationManager .getFlatUISettingMap ();
649687 ctx .emit (' get-ui-settings' , flatUIMap );
@@ -836,6 +874,18 @@ export default defineComponent({
836874 component: DatasetInfo ,
837875 });
838876 }
877+ if (! configurationManager .getUISetting (' UIVisualMasks' ) || ! isConfigOwnerAdmin .value ) {
878+ context .unregister ({
879+ description: ' Visual Masks' ,
880+ component: VisualMaskSidebarVue ,
881+ });
882+ } else {
883+ context .register ({
884+ description: ' Visual Masks' ,
885+ component: VisualMaskSidebarVue ,
886+ width: 340 ,
887+ });
888+ }
839889
840890 if (! configurationManager .getUISetting (' UIThresholdControls' )) {
841891 context .unregister ({
@@ -861,7 +911,7 @@ export default defineComponent({
861911 progress .loaded = false ;
862912 console .error (err );
863913 const errorEl = document .createElement (' div' );
864- errorEl .innerHTML = getResponseError (err );
914+ errorEl .innerHTML = getResponseError (err as never );
865915 loadError .value = errorEl .innerText
866916 .concat (" . If you don't know how to resolve this, please contact the server administrator." );
867917 throw err ;
@@ -979,6 +1029,8 @@ export default defineComponent({
9791029 editingMode ,
9801030 groupFilters ,
9811031 groupStyleManager ,
1032+ visualMaskManager ,
1033+ visualMaskStyleManager ,
9821034 multiSelectList ,
9831035 pendingSaveCount ,
9841036 progress ,
@@ -1063,6 +1115,7 @@ export default defineComponent({
10631115 selectedTrackId ,
10641116 editingGroupId ,
10651117 selectedKey ,
1118+ visualMaskManager ,
10661119 trackFilters ,
10671120 videoUrl ,
10681121 overlays ,
@@ -1168,7 +1221,7 @@ export default defineComponent({
11681221 recipes,
11691222 multiSelectActive,
11701223 editingDetails,
1171- overlays,
1224+ overlays: overlays ? [...overlays] : [] ,
11721225 groupEditActive: editingGroupId !== null,
11731226 }"
11741227 :get-u-i-setting =" getUISetting"
@@ -1303,7 +1356,7 @@ export default defineComponent({
13031356 v-mousetrap =" [
13041357 { bind: 'n', handler: () => !readonlyState && handler.trackAdd() },
13051358 { bind: 'r', handler: () => aggregateController.resetZoom() },
1306- { bind: 'esc', handler: () => getUISetting('UISelection') && handler.trackAbort() },
1359+ { bind: 'esc', handler: () => (visualMaskManager.editingMaskId !== null ? visualMaskManager.stopEditing() : ( getUISetting('UISelection') && handler.trackAbort()) ) },
13071360 ]"
13081361 class =" d-flex flex-column grow"
13091362 >
@@ -1337,7 +1390,7 @@ export default defineComponent({
13371390 <LayerManager
13381391 v-if =" progress.loaded"
13391392 :camera =" camera"
1340- :overlays =" overlays"
1393+ :overlays =" overlays ? [...overlays] : [] "
13411394 />
13421395 </component >
13431396 </div >
0 commit comments