mirror of
https://github.com/wekan/wekan.git
synced 2026-01-21 16:56:11 +01:00
Number of cards per list and sum of custom number field in list head.
Thanks to xet7 ! Fixes #3796
This commit is contained in:
parent
4292302c3c
commit
e569c2957e
29 changed files with 239 additions and 142 deletions
|
|
@ -368,6 +368,18 @@ body.list-resizing-active * {
|
|||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
/* Sum badge shown before list title */
|
||||
.list-header .list-sum-badge {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
background: transparent;
|
||||
color: #8c8c8c;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.list-rotated {
|
||||
width: 1.3vw;
|
||||
height: 35vh;
|
||||
|
|
@ -750,6 +762,9 @@ body.list-resizing-active * {
|
|||
grid-row: 2;
|
||||
grid-column: 2;
|
||||
align-self: start;
|
||||
text-align: left;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
font-size: 16px !important;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
|
@ -964,6 +979,9 @@ body.list-resizing-active * {
|
|||
grid-row: 2 !important;
|
||||
grid-column: 2 !important;
|
||||
align-self: start !important;
|
||||
text-align: left !important;
|
||||
padding-left: 0 !important;
|
||||
margin-left: 0 !important;
|
||||
font-size: 16px !important;
|
||||
line-height: 1.2 !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,50 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
|
||||
customFieldsSum() {
|
||||
const ret = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [Session.get('currentBoard')] },
|
||||
const list = Template.currentData();
|
||||
if (!list) return [];
|
||||
const boardId = Session.get('currentBoard');
|
||||
const fields = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [boardId] },
|
||||
showSumAtTopOfList: true,
|
||||
});
|
||||
return ret;
|
||||
|
||||
if (!fields || !fields.length) return [];
|
||||
|
||||
const cards = ReactiveCache.getCards({
|
||||
listId: list._id,
|
||||
archived: false,
|
||||
});
|
||||
|
||||
const result = fields.map(field => {
|
||||
let sum = 0;
|
||||
if (cards && cards.length) {
|
||||
cards.forEach(card => {
|
||||
const cfs = (card.customFields || []);
|
||||
const cf = cfs.find(f => f && f._id === field._id);
|
||||
if (!cf || cf.value === null || cf.value === undefined) return;
|
||||
let v = cf.value;
|
||||
if (typeof v === 'string') {
|
||||
// try to parse string numbers, accept comma decimal
|
||||
const parsed = parseFloat(v.replace(',', '.'));
|
||||
if (isNaN(parsed)) return;
|
||||
v = parsed;
|
||||
}
|
||||
if (typeof v === 'number' && isFinite(v)) {
|
||||
sum += v;
|
||||
}
|
||||
});
|
||||
}
|
||||
return {
|
||||
_id: field._id,
|
||||
name: field.name,
|
||||
type: field.type,
|
||||
settings: field.settings || {},
|
||||
value: sum,
|
||||
};
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
openForm(options) {
|
||||
|
|
@ -254,6 +293,22 @@ BlazeComponent.extendComponent({
|
|||
},
|
||||
}).register('listBody');
|
||||
|
||||
// Helpers for listBody template context
|
||||
Template.listBody.helpers({
|
||||
formattedCurrencyCustomFieldValue(val) {
|
||||
// `this` is the custom field sum object from customFieldsSum each-iteration
|
||||
const field = this || {};
|
||||
const code = (field.settings && field.settings.currencyCode) || 'USD';
|
||||
try {
|
||||
const n = typeof val === 'number' ? val : parseFloat(val);
|
||||
if (!isFinite(n)) return val;
|
||||
return new Intl.NumberFormat(undefined, { style: 'currency', currency: code }).format(n);
|
||||
} catch (e) {
|
||||
return `${code} ${val}`;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function toggleValueInReactiveArray(reactiveValue, value) {
|
||||
const array = reactiveValue.get();
|
||||
const valueIndex = array.indexOf(value);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ template(name="listHeader")
|
|||
|/#{wipLimit.value})
|
||||
if showCardsCountForList cards.length
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
|
||||
if hasNumberFieldsSum
|
||||
|
|
||||
span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}}
|
||||
else
|
||||
if collapsed
|
||||
a.js-collapse(title="{{_ 'uncollapse'}}")
|
||||
|
|
@ -44,6 +47,9 @@ template(name="listHeader")
|
|||
unless collapsed
|
||||
if showCardsCountForList cards.length
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
|
||||
if hasNumberFieldsSum
|
||||
|
|
||||
span.list-sum-badge(title="{{_ 'sum-of-number-fields'}}") ∑ {{numberFieldsSum}}
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
if isWatching
|
||||
|
|
|
|||
|
|
@ -142,7 +142,48 @@ BlazeComponent.extendComponent({
|
|||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
}
|
||||
},
|
||||
numberFieldsSum() {
|
||||
const list = Template.currentData();
|
||||
if (!list) return 0;
|
||||
const boardId = Session.get('currentBoard');
|
||||
const fields = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [boardId] },
|
||||
showSumAtTopOfList: true,
|
||||
type: 'number',
|
||||
});
|
||||
if (!fields || !fields.length) return 0;
|
||||
const cards = ReactiveCache.getCards({ listId: list._id, archived: false });
|
||||
let total = 0;
|
||||
if (cards && cards.length) {
|
||||
cards.forEach(card => {
|
||||
const cfs = (card.customFields || []);
|
||||
fields.forEach(field => {
|
||||
const cf = cfs.find(f => f && f._id === field._id);
|
||||
if (!cf || cf.value === null || cf.value === undefined) return;
|
||||
let v = cf.value;
|
||||
if (typeof v === 'string') {
|
||||
const parsed = parseFloat(v.replace(',', '.'));
|
||||
if (isNaN(parsed)) return;
|
||||
v = parsed;
|
||||
}
|
||||
if (typeof v === 'number' && isFinite(v)) {
|
||||
total += v;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return total;
|
||||
},
|
||||
hasNumberFieldsSum() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const fields = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [boardId] },
|
||||
showSumAtTopOfList: true,
|
||||
type: 'number',
|
||||
});
|
||||
return !!(fields && fields.length);
|
||||
},
|
||||
});
|
||||
|
||||
Template.listActionPopup.helpers({
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@ template(name="minilist")
|
|||
class="minicard-{{colorClass}}")
|
||||
.minicard-title
|
||||
.handle
|
||||
.fa.fa-arrows
|
||||
span.drag-handle(title="{{_ 'dragList'}}") ↕️
|
||||
+viewer
|
||||
= title
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue