Add Cards report

This commit is contained in:
John R. Supplee 2021-04-17 10:27:16 +02:00
parent ef584e2826
commit 661e80084c
7 changed files with 124 additions and 55 deletions

View file

@ -1,5 +1,5 @@
template(name="adminReports") template(name="adminReports")
.setting-content .setting-content.admin-reports-content
unless currentUser.isAdmin unless currentUser.isAdmin
| {{_ 'error-notAuthorized'}} | {{_ 'error-notAuthorized'}}
else else
@ -26,6 +26,11 @@ template(name="adminReports")
i.fa.fa-magic i.fa.fa-magic
| {{_ 'rulesReportTitle'}} | {{_ 'rulesReportTitle'}}
li
a.js-report-cards(data-id="report-cards")
i.fa.fa-magic
| {{_ 'cardsReportTitle'}}
.main-body .main-body
if loading.get if loading.get
+spinner +spinner
@ -37,6 +42,8 @@ template(name="adminReports")
+orphanedFilesReport +orphanedFilesReport
else if showRulesReport.get else if showRulesReport.get
+rulesReport +rulesReport
else if showCardsReport.get
+cardsReport
template(name="brokenCardsReport") template(name="brokenCardsReport")
@ -57,7 +64,7 @@ template(name="rulesReport")
th actionType th actionType
th activityType th activityType
each rule in rows each rule in results
tr tr
td {{ rule.title }} td {{ rule.title }}
td {{ rule.boardTitle }} td {{ rule.boardTitle }}
@ -78,7 +85,7 @@ template(name="filesReport")
th MD5 Sum th MD5 Sum
th ID th ID
each att in attachmentFiles each att in results
tr tr
td {{ att.filename }} td {{ att.filename }}
td.right {{fileSize att.length }} td.right {{fileSize att.length }}
@ -100,7 +107,7 @@ template(name="orphanedFilesReport")
th MD5 Sum th MD5 Sum
th ID th ID
each att in attachmentFiles each att in results
tr tr
td {{ att.filename }} td {{ att.filename }}
td.right {{fileSize att.length }} td.right {{fileSize att.length }}
@ -109,3 +116,26 @@ template(name="orphanedFilesReport")
td {{ att._id.toHexString }} td {{ att._id.toHexString }}
else else
div {{_ 'no-results' }} div {{_ 'no-results' }}
template(name="cardsReport")
h1 {{_ 'cardsReportTitle'}}
if resultsCount
table.table
tr
th Card Title
th Board
th Swimlane
th List
th Members
th Assignees
each card in results
tr
td {{abbreviate card.title }}
td {{abbreviate card.board.title }}
td {{abbreviate card.swimlane.title }}
td {{abbreviate card.list.title }}
td {{userNames card.members }}
td {{userNames card.assignees }}
else
div {{_ 'no-results' }}

View file

@ -1,6 +1,8 @@
import { AttachmentStorage } from '/models/attachments'; import { AttachmentStorage } from '/models/attachments';
import { CardSearchPagedComponent } from '/client/lib/cardSearch'; import { CardSearchPagedComponent } from '/client/lib/cardSearch';
import SessionData from '/models/usersessiondata'; import SessionData from '/models/usersessiondata';
import { QueryParams } from '/config/query-classes';
import { OPERATOR_LIMIT } from '/config/search-const';
BlazeComponent.extendComponent({ BlazeComponent.extendComponent({
subscription: null, subscription: null,
@ -8,10 +10,13 @@ BlazeComponent.extendComponent({
showBrokenCardsReport: new ReactiveVar(false), showBrokenCardsReport: new ReactiveVar(false),
showOrphanedFilesReport: new ReactiveVar(false), showOrphanedFilesReport: new ReactiveVar(false),
showRulesReport: new ReactiveVar(false), showRulesReport: new ReactiveVar(false),
showCardsReport: new ReactiveVar(false),
sessionId: null,
onCreated() { onCreated() {
this.error = new ReactiveVar(''); this.error = new ReactiveVar('');
this.loading = new ReactiveVar(false); this.loading = new ReactiveVar(false);
this.sessionId = SessionData.getSessionId();
}, },
events() { events() {
@ -21,6 +26,7 @@ BlazeComponent.extendComponent({
'click a.js-report-files': this.switchMenu, 'click a.js-report-files': this.switchMenu,
'click a.js-report-orphaned-files': this.switchMenu, 'click a.js-report-orphaned-files': this.switchMenu,
'click a.js-report-rules': this.switchMenu, 'click a.js-report-rules': this.switchMenu,
'click a.js-report-cards': this.switchMenu,
}, },
]; ];
}, },
@ -64,68 +70,66 @@ BlazeComponent.extendComponent({
this.showRulesReport.set(true); this.showRulesReport.set(true);
this.loading.set(false); this.loading.set(false);
}); });
} else if ('report-cards' === targetID) {
const qp = new QueryParams();
qp.addPredicate(OPERATOR_LIMIT, 300);
this.subscription = Meteor.subscribe(
'globalSearch',
this.sessionId,
qp.getParams(),
qp.text,
() => {
this.showCardsReport.set(true);
this.loading.set(false);
},
);
} }
} }
}, },
}).register('adminReports'); }).register('adminReports');
Template.filesReport.helpers({ class AdminReport extends BlazeComponent {
attachmentFiles() { collection;
results() {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
// console.log('attachments:', AttachmentStorage.find()); // console.log('attachments:', AttachmentStorage.find());
// console.log('attachments.count:', AttachmentStorage.find().count()); // console.log('attachments.count:', AttachmentStorage.find().count());
return AttachmentStorage.find(); return this.collection.find();
}, }
rulesReport() {
const rules = [];
Rules.find().forEach(rule => {
rules.push({
_id: rule._id,
title: rule.title,
boardId: rule.boardId,
boardTitle: rule.board().title,
action: rule.action().fetch(),
trigger: rule.trigger().fetch(),
});
});
return rules;
},
resultsCount() { resultsCount() {
return AttachmentStorage.find().count(); return this.collection.find().count();
}, }
fileSize(size) { fileSize(size) {
return Math.round(size / 1024); return Math.round(size / 1024);
}, }
usageCount(key) { usageCount(key) {
return Attachments.find({ 'copies.attachments.key': key }).count(); return Attachments.find({ 'copies.attachments.key': key }).count();
}, }
});
Template.orphanedFilesReport.helpers({ abbreviate(text) {
attachmentFiles() { if (text.length > 30) {
// eslint-disable-next-line no-console return `${text.substr(0, 29)}...`;
// console.log('attachments:', AttachmentStorage.find()); }
// console.log('attachments.count:', AttachmentStorage.find().count()); return text;
return AttachmentStorage.find(); }
}, }
resultsCount() { (class extends AdminReport {
return AttachmentStorage.find().count(); collection = AttachmentStorage;
}, }.register('filesReport'));
fileSize(size) { (class extends AdminReport {
return Math.round(size / 1024); collection = AttachmentStorage;
}, }.register('orphanedFilesReport'));
});
Template.rulesReport.helpers({ (class extends AdminReport {
rows() { collection = Rules;
results() {
const rules = []; const rules = [];
Rules.find().forEach(rule => { Rules.find().forEach(rule => {
@ -139,14 +143,25 @@ Template.rulesReport.helpers({
}); });
}); });
// eslint-disable-next-line no-console
console.log('rows:', rules); console.log('rows:', rules);
return rules; return rules;
}, }
}.register('rulesReport'));
resultsCount() { (class extends AdminReport {
return Rules.find().count(); collection = Cards;
},
}); userNames(userIds) {
let text = '';
userIds.forEach(userId => {
const user = Users.findOne(userId);
text += text ? ', ' : '';
text += user.username;
});
return text;
}
}.register('cardsReport'));
class BrokenCardsComponent extends CardSearchPagedComponent { class BrokenCardsComponent extends CardSearchPagedComponent {
onCreated() { onCreated() {

View file

@ -0,0 +1,3 @@
.admin-reports-content
height: auto !important

View file

@ -49,3 +49,11 @@ export const TYPE_LINKED_BOARD = 'cardType-linkedBoard';
export const TYPE_LINKED_CARD = 'cardType-linkedCard'; export const TYPE_LINKED_CARD = 'cardType-linkedCard';
export const TYPE_TEMPLATE_BOARD = 'template-board'; export const TYPE_TEMPLATE_BOARD = 'template-board';
export const TYPE_TEMPLATE_CONTAINER = 'template-container'; export const TYPE_TEMPLATE_CONTAINER = 'template-container';
export const TYPE_TEMPLATE_CARD = 'template-card';
export const TYPE_TEMPLATE_LIST = 'template-list';
export const CARD_TYPES = [
TYPE_CARD,
TYPE_LINKED_CARD,
TYPE_LINKED_BOARD,
TYPE_TEMPLATE_CARD,
];

View file

@ -999,5 +999,6 @@
"filesReportTitle": "Files Report", "filesReportTitle": "Files Report",
"orphanedFilesReportTitle": "Orphaned Files Report", "orphanedFilesReportTitle": "Orphaned Files Report",
"reports": "Reports", "reports": "Reports",
"rulesReportTitle": "Rules Report" "rulesReportTitle": "Rules Report",
"cardsReportTitle": "Cards Report"
} }

View file

@ -1294,7 +1294,12 @@ Boards.userSearch = (
return Boards.find(selector, projection); return Boards.find(selector, projection);
}; };
Boards.userBoards = (userId, archived = false, selector = {}) => { Boards.userBoards = (
userId,
archived = false,
selector = {},
projection = {},
) => {
if (typeof archived === 'boolean') { if (typeof archived === 'boolean') {
selector.archived = archived; selector.archived = archived;
} }
@ -1304,13 +1309,18 @@ Boards.userBoards = (userId, archived = false, selector = {}) => {
selector.$or = [{ permission: 'public' }]; selector.$or = [{ permission: 'public' }];
if (userId) { if (userId) {
selector.$or.push({ members: { $elemMatch: { userId, isActive: true } } }); selector.$or.push(
{ members: { $elemMatch: { userId, isActive: true } } },
projection,
);
} }
return Boards.find(selector); return Boards.find(selector);
}; };
Boards.userBoardIds = (userId, archived = false, selector = {}) => { Boards.userBoardIds = (userId, archived = false, selector = {}) => {
return Boards.userBoards(userId, archived, selector).map(board => { return Boards.userBoards(userId, archived, selector, {
fields: { _id: 1 },
}).map(board => {
return board._id; return board._id;
}); });
}; };

View file

@ -47,6 +47,7 @@ import {
PREDICATE_SYSTEM, PREDICATE_SYSTEM,
} from '/config/search-const'; } from '/config/search-const';
import { QueryErrors, QueryParams, Query } from '/config/query-classes'; import { QueryErrors, QueryParams, Query } from '/config/query-classes';
import { CARD_TYPES } from '../../config/const';
const escapeForRegex = require('escape-string-regexp'); const escapeForRegex = require('escape-string-regexp');
@ -577,6 +578,7 @@ Meteor.publish('brokenCards', function(sessionId) {
{ boardId: { $in: [null, ''] } }, { boardId: { $in: [null, ''] } },
{ swimlaneId: { $in: [null, ''] } }, { swimlaneId: { $in: [null, ''] } },
{ listId: { $in: [null, ''] } }, { listId: { $in: [null, ''] } },
{ type: { $nin: CARD_TYPES } },
]; ];
// console.log('brokenCards selector:', query.selector); // console.log('brokenCards selector:', query.selector);