44-->
55
66<template >
7- <tr
8- class =" files-list__row files-list__row--image-group"
9- :class =" {
10- 'files-list__row--image-group-expanded': source.expanded,
11- 'files-list__row--active': isSelected,
12- }" >
13- <td class =" files-list__row-checkbox" @click.stop >
14- <NcCheckboxRadioSwitch
15- :aria-label =" t('files', 'Toggle selection for image group')"
16- :modelValue =" isSelected"
17- :indeterminate =" isPartiallySelected"
18- @update:modelValue =" onSelectionChange" />
19- </td >
20-
21- <td class =" files-list__row-name" @click =" $ emit('toggle', source.source)" >
22- <span class =" files-list__row-icon" >
23- <ImageMultipleIcon :size =" 20" />
24- </span >
25-
26- <span class =" files-list__row-image-group-chevron" >
27- <NcIconSvgWrapper
28- :path =" mdiChevronDown"
29- :size =" 20"
30- :class =" { 'files-list__row-image-group-chevron--expanded': source.expanded }" />
31- </span >
32-
33- <span class =" files-list__row-name-text" >
34- {{ n('files', '{count} image', '{count} images', source.images.length, { count: source.images.length }) }}
35- </span >
36- </td >
37-
38- <td v-if =" isMimeAvailable" class =" files-list__row-mime" />
39- <td v-if =" isSizeAvailable" class =" files-list__row-size" />
40- <td v-if =" isMtimeAvailable" class =" files-list__row-mtime" />
41- </tr >
7+ <tr
8+ class =" files-list__row files-list__row--image-group"
9+ :class =" {
10+ 'files-list__row--image-group-expanded': source.expanded,
11+ 'files-list__row--active': isSelected,
12+ }" >
13+ <td class =" files-list__row-checkbox" @click.stop >
14+ <NcCheckboxRadioSwitch
15+ :aria-label =" t('files', 'Toggle selection for image group')"
16+ :modelValue =" isSelected"
17+ :indeterminate =" isPartiallySelected"
18+ @update:modelValue =" onSelectionChange" />
19+ </td >
20+
21+ <td class =" files-list__row-name" @click =" emit('toggle', source.source)" >
22+ <span class =" files-list__row-icon" >
23+ <ImageMultipleIcon :size =" 20" />
24+ </span >
25+
26+ <span class =" files-list__row-image-group-chevron" >
27+ <NcIconSvgWrapper
28+ :path =" mdiChevronDown"
29+ :size =" 20"
30+ :class =" { 'files-list__row-image-group-chevron--expanded': source.expanded }" />
31+ </span >
32+
33+ <span class =" files-list__row-name-text" >
34+ {{ n('files', '{count} image', '{count} images', source.images.length, { count: source.images.length }) }}
35+ </span >
36+ </td >
37+
38+ <td v-if =" isMimeAvailable" class =" files-list__row-mime" />
39+ <td v-if =" isSizeAvailable" class =" files-list__row-size" />
40+ <td v-if =" isMtimeAvailable" class =" files-list__row-mtime" />
41+ </tr >
4242</template >
4343
44- <script lang="ts">
45- import type { PropType } from ' vue'
44+ <script lang="ts" setup>
4645import type { ImageGroupNode } from ' ../composables/useImageGrouping.ts'
4746
4847import { mdiChevronDown } from ' @mdi/js'
4948import { n , t } from ' @nextcloud/l10n'
50- import { defineComponent } from ' vue'
49+ import { computed } from ' vue'
5150import NcCheckboxRadioSwitch from ' @nextcloud/vue/components/NcCheckboxRadioSwitch'
5251import NcIconSvgWrapper from ' @nextcloud/vue/components/NcIconSvgWrapper'
5352import ImageMultipleIcon from ' vue-material-design-icons/ImageMultiple.vue'
5453import { useSelectionStore } from ' ../store/selection.ts'
5554
56- export default defineComponent ({
57- name: ' FileEntryImageGroup' ,
58-
59- components: {
60- ImageMultipleIcon ,
61- NcCheckboxRadioSwitch ,
62- NcIconSvgWrapper ,
63- },
64-
65- props: {
66- source: {
67- type: Object as PropType <ImageGroupNode >,
68- required: true ,
69- },
70-
71- isMimeAvailable: {
72- type: Boolean ,
73- default: false ,
74- },
75-
76- isSizeAvailable: {
77- type: Boolean ,
78- default: false ,
79- },
80-
81- isMtimeAvailable: {
82- type: Boolean ,
83- default: false ,
84- },
85- },
86-
87- emits: [' toggle' ],
88-
89- setup() {
90- const selectionStore = useSelectionStore ()
91- return { selectionStore , n , t , mdiChevronDown }
92- },
93-
94- computed: {
95- childSources() {
96- return this .source .images .map ((img ) => img .source )
97- },
98-
99- isSelected() {
100- return this .childSources .every ((src ) => this .selectionStore .selected .includes (src ))
101- },
102-
103- isPartiallySelected() {
104- return ! this .isSelected && this .childSources .some ((src ) => this .selectionStore .selected .includes (src ))
105- },
106- },
107-
108- methods: {
109- onSelectionChange(selected : boolean ) {
110- const current = this .selectionStore .selected
111- if (selected ) {
112- // select all children
113- this .selectionStore .set ([... new Set ([... current , ... this .childSources ])])
114- } else {
115- // unselect all children
116- this .selectionStore .set (current .filter ((src ) => ! this .childSources .includes (src )))
117- }
118- },
119-
120- onRowClick() {
121- this .onSelectionChange (! this .isSelected )
122- },
123- },
124- })
55+ const props = defineProps <{
56+ source: ImageGroupNode
57+ isMimeAvailable? : boolean
58+ isSizeAvailable? : boolean
59+ isMtimeAvailable? : boolean
60+ }>()
61+
62+ const emit = defineEmits <{
63+ (e : ' toggle' , key : string ): void
64+ }>()
65+
66+ const selectionStore = useSelectionStore ()
67+
68+ const childSources = computed (() => props .source .images .map ((img ) => img .source ))
69+
70+ const isSelected = computed (() => childSources .value .every ((src ) => selectionStore .selected .includes (src )))
71+
72+ const isPartiallySelected = computed (() => ! isSelected .value && childSources .value .some ((src ) => selectionStore .selected .includes (src )))
73+
74+ /**
75+ * Handle selection change for the image group
76+ *
77+ * @param selected - Whether the group should be selected or deselected
78+ */
79+ async function onSelectionChange(selected : boolean ) {
80+ const current = selectionStore .selected
81+ if (selected ) {
82+ // select all children
83+ selectionStore .set ([... new Set ([... current , ... childSources .value ])])
84+ } else {
85+ // unselect all children
86+ selectionStore .set (current .filter ((src ) => ! childSources .value .includes (src )))
87+ }
88+ }
12589 </script >
12690
12791<style scoped lang="scss">
@@ -133,14 +97,14 @@ export default defineComponent({
13397 }
13498 }
13599
136- .files-list__row-image-group-chevron {
137- display : flex ;
138- align-items : center ;
139- color : var (--color-text-maxcontrast );
140- & --expanded {
141- transform : rotate (180deg );
142- }
143- }
100+ .files-list__row-image-group-chevron {
101+ display : flex ;
102+ align-items : center ;
103+ color : var (--color-text-maxcontrast );
104+ & --expanded {
105+ transform : rotate (180deg );
106+ }
107+ }
144108
145109 .files-list__row-name-text {
146110 color : var (--color-main-text );
0 commit comments