fix: code review — security, dead code, performance, consistency
Critical fixes: - XSS: escapeHtml() on all user-supplied text in email notifications - Budget PATCH: added mutex lock + availability validation (prevents corruption) - batchResolveNames: fixed wrong signature for budget request earmark names Dead code cleanup: - Deleted 8 unused PostComposition* files (replaced by PostDetail full page) Performance: - budget-helpers: single-fetch with computeFromEntries(), optional prefetch param - post-composition: parallelized text + thumbnail fetches with Promise.all Consistency: - PostDetail.jsx: native <select> → PortalSelect (matches all panels) - Finance.jsx: 11 hardcoded English table headers → t() with i18n keys - PostCalendar.jsx: day names, Month/Week labels → t() with i18n keys - App.jsx Suspense: "Loading..." → brand spinner (can't use i18n in fallback) - UploadZone: proper useRef pattern, no vanilla JS document.createElement - All file inputs: className="hidden" → absolute w-0 h-0 opacity-0 - ArtefactDetailPanel: removed campaign/project selects (inherited from post) - TranslationDetailPanel: removed brand/linked post selects (inherited from post) - ApproverMultiSelect: portal-based dropdown (fixes clipping in modals) - Thumbnail fix: post-composition constructs URL from filename (was undefined) - Upload fix: UploadZone with drag-and-drop for design + video artefacts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
+18
-16
@@ -3,27 +3,23 @@
|
||||
|
||||
const nocodb = require('./nocodb');
|
||||
|
||||
async function getMainAvailable() {
|
||||
const entries = await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
function computeFromEntries(entries) {
|
||||
const income = entries.filter(e => (e.type || 'income') === 'income');
|
||||
const expenses = entries.filter(e => e.type === 'expense');
|
||||
|
||||
const totalReceived = income.reduce((s, e) => s + (e.amount || 0), 0);
|
||||
const totalExpenses = expenses.reduce((s, e) => s + (e.amount || 0), 0);
|
||||
const totalCampaignBudget = income.filter(e => e.campaign_id).reduce((s, e) => s + (e.amount || 0), 0);
|
||||
const totalProjectBudget = income.filter(e => e.project_id).reduce((s, e) => s + (e.amount || 0), 0);
|
||||
|
||||
return {
|
||||
totalReceived,
|
||||
totalExpenses,
|
||||
totalCampaignBudget,
|
||||
totalProjectBudget,
|
||||
available: totalReceived - totalExpenses - totalCampaignBudget - totalProjectBudget,
|
||||
};
|
||||
return { totalReceived, totalExpenses, totalCampaignBudget, totalProjectBudget, available: totalReceived - totalExpenses - totalCampaignBudget - totalProjectBudget };
|
||||
}
|
||||
|
||||
async function getCampaignAvailable(campaignId) {
|
||||
const entries = await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
async function getMainAvailable(prefetchedEntries) {
|
||||
const entries = prefetchedEntries || await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
return computeFromEntries(entries);
|
||||
}
|
||||
|
||||
async function getCampaignAvailable(campaignId, prefetchedEntries) {
|
||||
const entries = prefetchedEntries || await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
const campaignIncome = entries.filter(e =>
|
||||
e.campaign_id && Number(e.campaign_id) === Number(campaignId) && (e.type || 'income') === 'income'
|
||||
);
|
||||
@@ -38,11 +34,17 @@ async function getCampaignAvailable(campaignId) {
|
||||
return { allocated, trackAllocated, available: allocated - trackAllocated };
|
||||
}
|
||||
|
||||
async function getCampaignAllocatedFromEntries(campaignId) {
|
||||
const entries = await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
async function getCampaignAllocatedFromEntries(campaignId, prefetchedEntries) {
|
||||
const entries = prefetchedEntries || await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
return entries
|
||||
.filter(e => e.campaign_id && Number(e.campaign_id) === Number(campaignId) && (e.type || 'income') === 'income')
|
||||
.reduce((s, e) => s + (e.amount || 0), 0);
|
||||
}
|
||||
|
||||
module.exports = { getMainAvailable, getCampaignAvailable, getCampaignAllocatedFromEntries };
|
||||
async function getAllBudgetData() {
|
||||
const entries = await nocodb.list('BudgetEntries', { limit: 10000 });
|
||||
const main = computeFromEntries(entries);
|
||||
return { entries, ...main };
|
||||
}
|
||||
|
||||
module.exports = { getMainAvailable, getCampaignAvailable, getCampaignAllocatedFromEntries, getAllBudgetData, computeFromEntries };
|
||||
|
||||
Reference in New Issue
Block a user