WIP Group contributions by URL

This commit is contained in:
2026-07-26 14:08:02 +02:00
parent 606f5c9383
commit a7e017971a
6 changed files with 218 additions and 4 deletions
+68
View File
@@ -227,6 +227,74 @@ export default Service.extend({
return kreditsByContributor;
}),
// Groups contributions that were created together for the same
// issue/pull request (one contribution per contributor). The grouping key
// is the contribution's `url` (see utils/contribution-grouping-key).
// Manual contributions without a URL each form their own single-item group
// (they are never collapsed together, since `null` is not a real key).
//
// Each group is an EmberObject with: groupId, items, contributors,
// contributorIds, totalAmount, kind, description, url, date, isGrouped
// (true when more than one contribution shares the key).
contributionsGrouped: computed('contributions.[]', function() {
const groupsMap = new Map();
const singletons = [];
this.contributions.forEach(c => {
const groupId = c.groupId;
if (isEmpty(groupId)) {
singletons.push(c);
} else if (groupsMap.has(groupId)) {
groupsMap.get(groupId).items.push(c);
} else {
groupsMap.set(groupId, { groupId, items: [c] });
}
});
const groups = [
...groupsMap.values(),
...singletons.map(c => ({ groupId: null, items: [c] }))
];
return groups.map(group => {
const items = group.items;
const first = items.firstObject;
const contributorIds = items.mapBy('contributorId').uniq();
const contributors = contributorIds
.map(id => this.contributors.findBy('id', id))
.filter(Boolean);
const totalAmount = items
.mapBy('amount')
.reduce((a, b) => a + (b || 0), 0);
return EmberObject.create({
groupId: group.groupId,
items,
contributors,
contributorIds,
totalAmount,
kind: first ? first.kind : null,
description: first ? first.description : null,
url: first ? first.url : null,
date: first ? first.date : null,
isGrouped: items.length > 1
});
});
}),
// Returns the other contributions that share a grouping key with the given
// contribution (i.e. the co-contributors' contributions). Returns an empty
// array when the contribution has no group (manual, no URL) or has no
// siblings.
siblingContributions (contribution) {
if (!contribution) return [];
const groupId = contribution.groupId;
if (isEmpty(groupId)) return [];
const group = this.contributionsGrouped.findBy('groupId', groupId);
if (!group) return [];
return group.items.filter(c => c !== contribution);
},
contributionsUnconfirmed: computed('contributions.[]', 'currentBlock', function() {
return this.contributions
.filter(c => c.confirmedAt > this.currentBlock);