diff --git a/package-lock.json b/package-lock.json index daec580127..e4c8caa547 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@fullcalendar/vue3": "6.1.21", "@google/model-viewer": "4.3.1", "@sentry/vue": "10.63.0", + "@tanstack/vue-virtual": "^3.13.31", "@unhead/vue": "3.1.7", "@vuepic/vue-datepicker": "14.0.0", "bowser": "2.14.1", @@ -2771,6 +2772,32 @@ "dev": true, "license": "MIT" }, + "node_modules/@tanstack/virtual-core": { + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.17.3.tgz", + "integrity": "sha512-8Np/TFELpI0ySuJoVmjvOrQYXH/8sTX0Biv9szhFhY39xOdAAY+smrMxjxOum/ux3eM8MUJQsEJ0/R0UpvC8dw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/vue-virtual": { + "version": "3.13.31", + "resolved": "https://registry.npmjs.org/@tanstack/vue-virtual/-/vue-virtual-3.13.31.tgz", + "integrity": "sha512-wZMEoSf852jQqaf3Ika1J7PiBae6341LNy/2CxmIyn0XKDQXMuK41wVX+xp6G0yx8jyR95Ef+Tdr13DK7mbJtQ==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.17.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.0.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", diff --git a/package.json b/package.json index d3f42f9f66..508efdbe9f 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "@fullcalendar/vue3": "6.1.21", "@google/model-viewer": "4.3.1", "@sentry/vue": "10.63.0", + "@tanstack/vue-virtual": "^3.13.31", "@unhead/vue": "3.1.7", "@vuepic/vue-datepicker": "14.0.0", "bowser": "2.14.1", diff --git a/src/components/cells/ValidationCell.vue b/src/components/cells/ValidationCell.vue index c6f29d99e2..61bf15956b 100644 --- a/src/components/cells/ValidationCell.vue +++ b/src/components/cells/ValidationCell.vue @@ -16,6 +16,7 @@
@@ -64,7 +65,7 @@ 'font-weight': isDarkTheme ? 'bold' : 'normal' }" :key="`avatar-${person.id}`" - v-for="person in assignees" + v-for="person in visibleAssignees" > + + +{{ extraAssigneesCount }} + @@ -111,6 +119,12 @@ const props = defineProps({ isBorder: { type: Boolean, default: true }, isCastingReady: { type: Boolean, default: false }, left: { type: String, default: '0px' }, + // Opt-in (0 = no cap, keeps the historical wrapping behavior): show at + // most this many assignee avatars and collapse the rest into a "+N" + // count on a single non-wrapping line. Virtualized lists (EditList) use + // it so a heavily-assigned task can never wrap the avatar stack and + // change the row height. + maxAssignees: { type: Number, default: 0 }, minimized: { type: Boolean, default: false }, rowX: { type: Number, default: 0 }, selectable: { type: Boolean, default: true }, @@ -151,6 +165,23 @@ const assignees = computed(() => ) ) +const visibleAssignees = computed(() => + props.maxAssignees > 0 + ? assignees.value.slice(0, props.maxAssignees) + : assignees.value +) + +const extraAssigneesCount = computed( + () => assignees.value.length - visibleAssignees.value.length +) + +const extraAssigneesTitle = computed(() => + assignees.value + .slice(props.maxAssignees) + .map(person => person.full_name) + .join('\n') +) + const priority = computed(() => formatPrioritySymbol(task.value.priority)) const cellStyle = computed(() => { @@ -276,6 +307,25 @@ defineExpose({ width: 100%; } +// Opt-in via the maxAssignees prop: the cell content stays on one line and +// clips instead of wrapping, so the cell height is constant whatever the +// status name length or assignee count. +.status-wrapper.single-line { + flex-wrap: nowrap; + overflow: hidden; + + > * { + flex-shrink: 0; + } +} + +.avatar.more-assignees { + background: var(--background-alt); + color: var(--text); + font-size: 9px; + font-weight: bold; +} + .full-wrapper { flex: 1; } diff --git a/src/components/lists/AssetList.vue b/src/components/lists/AssetList.vue index e31d8f36c5..e17bbfe1ae 100644 --- a/src/components/lists/AssetList.vue +++ b/src/components/lists/AssetList.vue @@ -240,15 +240,45 @@ - + + + +