ui: cache derived usage views
This commit is contained in:
+40
-13
@@ -3,6 +3,12 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
period: '7d',
|
period: '7d',
|
||||||
workspaceId: null,
|
workspaceId: null,
|
||||||
usage: null,
|
usage: null,
|
||||||
|
derived: {
|
||||||
|
localizedOperations: [],
|
||||||
|
normalizedTimeline: [],
|
||||||
|
timelineMaxValue: 0,
|
||||||
|
totalCalls: 0,
|
||||||
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
loadError: '',
|
loadError: '',
|
||||||
};
|
};
|
||||||
@@ -203,6 +209,29 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recomputeDerivedState() {
|
||||||
|
var operations = state.usage ? (state.usage.operations || []) : [];
|
||||||
|
var timeline = state.usage ? normalizeTimeline(state.usage.timeline || [], state.period) : [];
|
||||||
|
var totalCalls = operations.reduce(function (sum, operation) {
|
||||||
|
return sum + operation.calls_total;
|
||||||
|
}, 0);
|
||||||
|
var timelineMaxValue = timeline.reduce(function (maxValue, point) {
|
||||||
|
return Math.max(maxValue, point.calls_ok + point.calls_error);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
state.derived = {
|
||||||
|
localizedOperations: operations.map(function (operation) {
|
||||||
|
return {
|
||||||
|
operation: operation,
|
||||||
|
localized: localizedUsageOperation(operation),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
normalizedTimeline: timeline,
|
||||||
|
timelineMaxValue: timelineMaxValue,
|
||||||
|
totalCalls: totalCalls,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function buildEmptyState(title, message, compact) {
|
function buildEmptyState(title, message, compact) {
|
||||||
var empty = element('div', 'empty-state');
|
var empty = element('div', 'empty-state');
|
||||||
if (compact) {
|
if (compact) {
|
||||||
@@ -263,7 +292,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderChart() {
|
function renderChart() {
|
||||||
var timeline = state.usage ? normalizeTimeline(state.usage.timeline || [], state.period) : [];
|
var timeline = state.derived.normalizedTimeline;
|
||||||
chartWrap.innerHTML = '';
|
chartWrap.innerHTML = '';
|
||||||
|
|
||||||
if (!timeline.length) {
|
if (!timeline.length) {
|
||||||
@@ -277,9 +306,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxValue = Math.max.apply(null, timeline.map(function (point) {
|
var maxValue = state.derived.timelineMaxValue;
|
||||||
return point.calls_ok + point.calls_error;
|
|
||||||
}));
|
|
||||||
|
|
||||||
timeline.forEach(function (point, index) {
|
timeline.forEach(function (point, index) {
|
||||||
var node = chartTemplate.content.cloneNode(true);
|
var node = chartTemplate.content.cloneNode(true);
|
||||||
@@ -301,7 +328,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderTable() {
|
function renderTable() {
|
||||||
var operations = state.usage ? state.usage.operations : [];
|
var operations = state.derived.localizedOperations;
|
||||||
tableBody.innerHTML = '';
|
tableBody.innerHTML = '';
|
||||||
|
|
||||||
if (!operations.length) {
|
if (!operations.length) {
|
||||||
@@ -321,19 +348,16 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalCalls = operations.reduce(function (sum, operation) {
|
operations.forEach(function (entry) {
|
||||||
return sum + operation.calls_total;
|
var operation = entry.operation;
|
||||||
}, 0);
|
var localizedOperation = entry.localized;
|
||||||
|
|
||||||
operations.forEach(function (operation) {
|
|
||||||
var localizedOperation = localizedUsageOperation(operation);
|
|
||||||
var node = rowTemplate.content.cloneNode(true);
|
var node = rowTemplate.content.cloneNode(true);
|
||||||
var errorRate = operation.calls_total === 0
|
var errorRate = operation.calls_total === 0
|
||||||
? 0
|
? 0
|
||||||
: ((operation.calls_error / operation.calls_total) * 100);
|
: ((operation.calls_error / operation.calls_total) * 100);
|
||||||
var share = totalCalls === 0
|
var share = state.derived.totalCalls === 0
|
||||||
? 0
|
? 0
|
||||||
: ((operation.calls_total / totalCalls) * 100);
|
: ((operation.calls_total / state.derived.totalCalls) * 100);
|
||||||
|
|
||||||
node.querySelector('.col-name').textContent = localizedOperation.operation_display_name || operation.operation_display_name;
|
node.querySelector('.col-name').textContent = localizedOperation.operation_display_name || operation.operation_display_name;
|
||||||
node.querySelector('.col-op-slug').textContent = operation.operation_name;
|
node.querySelector('.col-op-slug').textContent = operation.operation_name;
|
||||||
@@ -404,8 +428,11 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
state.usage = await window.CrankApi.getUsageOverview(state.workspaceId, { period: state.period });
|
state.usage = await window.CrankApi.getUsageOverview(state.workspaceId, { period: state.period });
|
||||||
|
recomputeDerivedState();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
state.loadError = error.message || tKey('usage.error.load');
|
state.loadError = error.message || tKey('usage.error.load');
|
||||||
|
state.usage = null;
|
||||||
|
recomputeDerivedState();
|
||||||
} finally {
|
} finally {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
renderUsage();
|
renderUsage();
|
||||||
|
|||||||
Reference in New Issue
Block a user