@@ -10,16 +10,19 @@ import {
1010 useCameraStore ,
1111 useTime ,
1212 useReadOnlyMode ,
13+ useAttributesFilters ,
1314} from ' vue-media-annotator/provides' ;
14- import { Attribute } from ' vue-media-annotator/use/useAttributes' ;
15+ import type { Attribute , AttributeFilter } from ' vue-media-annotator/use/useAttributes' ;
1516import AttributeInput from ' dive-common/components/AttributeInput.vue' ;
1617import PanelSubsection from ' dive-common/components/PanelSubsection.vue' ;
17-
18+ import TooltipBtn from ' vue-media-annotator/components/TooltipButton.vue' ;
19+ import context from ' dive-common/store/context' ;
1820
1921export default defineComponent ({
2022 components: {
2123 AttributeInput ,
2224 PanelSubsection ,
25+ TooltipBtn ,
2326 },
2427 props: {
2528 attributes: {
@@ -39,8 +42,12 @@ export default defineComponent({
3942 const readOnlyMode = useReadOnlyMode ();
4043 const { frame : frameRef } = useTime ();
4144 const selectedTrackIdRef = useSelectedTrackId ();
45+ const { attributeFilters, sortAndFilterAttributes, timelineEnabled } = useAttributesFilters ();
4246 const cameraStore = useCameraStore ();
4347 const activeSettings = ref (true );
48+ const sortingMethods = [' a-z' , ' 1-0' ];
49+ const sortingMethodIcons = [' mdi-sort-alphabetical-ascending' , ' mdi-sort-numeric-ascending' ];
50+ const sortingMode = ref (0 );
4451
4552 const selectedTrack = computed (() => {
4653 if (selectedTrackIdRef .value !== null ) {
@@ -66,9 +73,23 @@ export default defineComponent({
6673 return null ;
6774 });
6875
69- const filteredFullAttributes = computed (() => Object .values (props .attributes ).filter (
70- (attribute : Attribute ) => attribute .belongs === props .mode .toLowerCase (),
71- ));
76+ const filteredFullAttributes = computed (() => {
77+ let additionFilters: AttributeFilter [] = [];
78+ let mode: ' track' | ' detection' = ' track' ;
79+ if (props .mode === ' Track' ) {
80+ additionFilters = attributeFilters .value .track ;
81+ } else {
82+ additionFilters = attributeFilters .value .detection ;
83+ mode = ' detection' ;
84+ }
85+ let attributeVals = {};
86+ if (selectedAttributes .value && selectedAttributes .value .attributes ) {
87+ attributeVals = selectedAttributes .value .attributes ;
88+ }
89+ return sortAndFilterAttributes (
90+ props .attributes , mode , attributeVals , sortingMode .value , additionFilters ,
91+ );
92+ });
7293
7394 const activeAttributesCount = computed (
7495 () => props .attributes .filter (
@@ -106,6 +127,27 @@ export default defineComponent({
106127 function addAttribute() {
107128 emit (' add-attribute' , props .mode );
108129 }
130+ function clickSortToggle() {
131+ sortingMode .value = (sortingMode .value + 1 ) % sortingMethods .length ;
132+ }
133+
134+ const filtersActive = computed (() => {
135+ let additionFilters: AttributeFilter [] = [];
136+ if (props .mode === ' Track' ) {
137+ additionFilters = attributeFilters .value .track ;
138+ } else {
139+ additionFilters = attributeFilters .value .detection ;
140+ }
141+ return !! additionFilters .find ((filter ) => filter .filterData .active === true );
142+ });
143+
144+ function openFilter() {
145+ context .openClose (' AttributesSideBar' , true , ' Filtering' );
146+ }
147+ function openTimeline() {
148+ context .openClose (' AttributesSideBar' , true , ' Timeline' );
149+ }
150+
109151
110152 return {
111153 frameRef ,
@@ -120,6 +162,14 @@ export default defineComponent({
120162 editAttribute ,
121163 addAttribute ,
122164 setEditIndividual ,
165+ // Sorting & Filters
166+ sortingMethodIcons ,
167+ sortingMode ,
168+ clickSortToggle ,
169+ openFilter ,
170+ openTimeline ,
171+ timelineEnabled ,
172+ filtersActive ,
123173 };
124174 },
125175});
@@ -134,25 +184,32 @@ export default defineComponent({
134184 class =" align-center"
135185 no-gutters
136186 >
137- <b >{{ mode }} Attributes:</b >
138- <v-spacer />
187+ <v-col dense >
188+ <b class =" attribute-header" >{{ mode }} Attributes</b >
189+ <div
190+ v-if =" mode === 'Detection'"
191+ no-gutters
192+ class =" text-caption"
193+ >
194+ {{ `Frame: ${frameRef}` }}
195+ </div >
196+ </v-col >
139197 <v-tooltip
140198 open-delay =" 200"
141199 bottom
142200 max-width =" 200"
143201 >
144202 <template #activator =" { on } " >
145203 <v-btn
146- outlined
147- x-small
204+ small
205+ icon
148206 :disabled =" readOnlyMode"
149207 v-on =" on"
150208 @click =" addAttribute"
151209 >
152210 <v-icon small >
153211 mdi-plus
154212 </v-icon >
155- Attribute
156213 </v-btn >
157214 </template >
158215 <span >Add a new {{ mode }} Attribute</span >
@@ -178,13 +235,29 @@ export default defineComponent({
178235 </template >
179236 <span >Show/Hide un-used</span >
180237 </v-tooltip >
181- </v-row >
182- <v-row
183- v-if =" mode === 'Detection'"
184- no-gutters
185- class =" text-caption"
186- >
187- {{ `Frame: ${frameRef}` }}
238+ <tooltip-btn
239+ :icon =" sortingMethodIcons[sortingMode]"
240+ tooltip-text =" Sort types by value or alphabetically"
241+ @click =" clickSortToggle"
242+ />
243+ <tooltip-btn
244+ icon =" mdi-filter"
245+ :color =" filtersActive ? 'primary' : 'default'"
246+ :tooltip-text =" filtersActive
247+ ? 'Filters are active, click to view': 'No filters are active, click to edit'"
248+ @click =" openFilter"
249+ />
250+ <tooltip-btn
251+ v-if =" mode === 'Detection'"
252+ icon =" mdi-chart-line-variant"
253+ :color =" timelineEnabled ? 'primary' : 'default'"
254+ tooltip-text =" Timeline Settings for Attributes"
255+ @click =" openTimeline"
256+ />
257+ <div
258+ v-else
259+ class =" blank-spacer"
260+ />
188261 </v-row >
189262 </template >
190263
@@ -199,8 +272,8 @@ export default defineComponent({
199272 class =" pa-0"
200273 >
201274 <span
202- v-for =" (attribute, i ) of filteredFullAttributes"
203- :key =" i "
275+ v-for =" (attribute) of filteredFullAttributes"
276+ :key =" attribute.name "
204277 >
205278 <v-row
206279 v-if ="
@@ -211,7 +284,14 @@ export default defineComponent({
211284 dense
212285 align =" center"
213286 >
214- <v-col class =" attribute-name" > {{ attribute.name }}: </v-col >
287+ <v-col class =" attribute-name" > <div
288+ class =" type-color-box"
289+ :style =" {
290+ backgroundColor: attribute.color,
291+ }"
292+ /><span >{{ attribute.name }}:
293+ </span >
294+ </v-col >
215295 <v-col class =" px-1" >
216296 <AttributeInput
217297 v-if =" activeSettings "
@@ -277,6 +357,9 @@ export default defineComponent({
277357</template >
278358
279359<style scoped lang="scss">
360+ .attribute-header {
361+ font-size : 12px ;
362+ }
280363.attribute-item-value {
281364 max-width : 80% ;
282365 margin : 0px ;
@@ -290,4 +373,19 @@ export default defineComponent({
290373 max-width : 50% ;
291374 min-width : 50% ;
292375}
376+ .type-color-box {
377+ display : inline-block ;
378+ margin-right : 5px ;
379+ min-width : 8px ;
380+ max-width : 8px ;
381+ min-height : 8px ;
382+ max-height : 8px ;
383+ }
384+ .blank-spacer {
385+ min-width : 28px ;
386+ min-height : 28px ;
387+ max-width : 28px ;
388+ max-height : 28px ;
389+ }
390+
293391 </style >
0 commit comments