-
-
Notifications
You must be signed in to change notification settings - Fork 95
Update MetricsDetails to add Save button to save both Test and Baseline Tables #1178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c3373a6
ea7a3cd
15120a5
cb3ede3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| const { TestResultsDB } = require('../Database'); | ||
| const ObjectID = require('mongodb').ObjectID; | ||
|
|
||
| module.exports = async (req, res) => { | ||
| const db = new TestResultsDB(); | ||
|
|
||
| const { | ||
| testId, | ||
| baselineId, | ||
| benchmarkName, | ||
| testStats, | ||
| baselineStats, | ||
| testDisabledIterations, | ||
| baselineDisabledIterations | ||
| } = req.body; | ||
|
|
||
| console.log('Received update request:', { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we remove the console.log before merging this into production? |
||
| testId, | ||
| baselineId, | ||
| benchmarkName, | ||
| testDisabledIterations, | ||
| baselineDisabledIterations | ||
| }); | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding validation for |
||
| try { | ||
| // Helper function to update a document | ||
| const updateDocument = async (docId, stats, disabledIterations, buildType) => { | ||
| // Find the document | ||
| const doc = await db.findOne({ _id: new ObjectID(docId) }); | ||
|
|
||
| if (!doc) { | ||
| console.error(`Document not found: ${docId}`); | ||
| return { success: false, error: `Document ${docId} not found` }; | ||
| } | ||
|
|
||
| if (!doc.aggregateInfo) { | ||
| console.error(`No aggregateInfo in document: ${docId}`); | ||
| return { success: false, error: `No aggregateInfo in document` }; | ||
| } | ||
|
|
||
| // Find and update the matching aggregateInfo entry | ||
| let updated = false; | ||
| for (const key in doc.aggregateInfo) { | ||
| const item = doc.aggregateInfo[key]; | ||
| if (item.benchmarkName === benchmarkName && | ||
| item.buildName && | ||
| item.buildName.includes(buildType)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| if (item.metrics) { | ||
| // Update each metric in this aggregateInfo | ||
| item.metrics = item.metrics.map(metric => { | ||
| return { | ||
| ...metric, | ||
|
|
||
| // original rawValues | ||
| rawValues: metric.rawValues, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant |
||
|
|
||
| //original statValues | ||
| statValues: metric.statValues, | ||
|
|
||
| // new field - filteredStatValues | ||
| filteredStatValues: { | ||
| mean: stats.mean, | ||
| max: stats.max, | ||
| min: stats.min, | ||
| median: stats.median, | ||
| std: stats.std, | ||
| CI: stats.CI | ||
| }, | ||
|
|
||
| // disablediterations | ||
| disabledIterations: disabledIterations || [] | ||
| }; | ||
| }); | ||
|
|
||
| updated = true; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (!updated) { | ||
| console.error(`Benchmark ${benchmarkName} with type ${buildType} not found`); | ||
| return { success: false, error: `Benchmark not found` }; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Misleading error message |
||
| } | ||
|
|
||
| // Update the document in database | ||
| await db.update( | ||
| { _id: new ObjectID(docId) }, | ||
| { $set: { aggregateInfo: doc.aggregateInfo } } | ||
| ); | ||
|
|
||
| console.log(`Successfully updated document: ${docId}`); | ||
| return { success: true }; | ||
| }; | ||
|
|
||
| // Update test document | ||
| const testResult = await updateDocument( | ||
| testId, | ||
| testStats, | ||
| testDisabledIterations, | ||
| 'test' | ||
| ); | ||
|
|
||
| if (!testResult.success) { | ||
| return res.status(400).json(testResult); | ||
| } | ||
|
|
||
| // Update baseline document | ||
| const baselineResult = await updateDocument( | ||
| baselineId, | ||
| baselineStats, | ||
| baselineDisabledIterations, | ||
| 'baseline' | ||
| ); | ||
|
|
||
| if (!baselineResult.success) { | ||
| return res.status(400).json(baselineResult); | ||
| } | ||
|
|
||
| res.json({ | ||
| success: true, | ||
| message: 'Statistics updated successfully' | ||
| }); | ||
|
|
||
| } catch (error) { | ||
| console.error('Error updating stats:', error); | ||
| res.status(500).json({ | ||
| success: false, | ||
| error: error.message | ||
| }); | ||
| } | ||
| }; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a newline |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,126 @@ | ||
| import { Divider } from 'antd'; | ||
| import React, { useState } from 'react'; | ||
| import { Divider, Button, message } from 'antd'; | ||
| import MetricsTable from './MetricsTable'; | ||
| import { getParams } from '../utils/query'; | ||
|
|
||
| function MetricsDetails() { | ||
| const { testId, baselineId, benchmarkName } = getParams(location.search); | ||
|
|
||
| // State to track data from both tables | ||
| const [testData, setTestData] = useState(null); | ||
| const [baselineData, setBaselineData] = useState(null); | ||
| const [testStats, setTestStats] = useState(null); | ||
| const [baselineStats, setBaselineStats] = useState(null); | ||
| const [saving, setSaving] = useState(false); | ||
|
|
||
| // Save handler for both tables | ||
| const handleSave = async () => { | ||
| if (!testData || !baselineData || !testStats || !baselineStats) { | ||
| message.warning('Please wait for data to load'); | ||
| return; | ||
| } | ||
|
|
||
| setSaving(true); | ||
|
|
||
| try { | ||
| // Calculate which iterations are disabled for TEST | ||
| const testDisabledIterations = testData | ||
| .filter(item => !item.enabled) | ||
| .map(item => item.iteration); | ||
|
|
||
| // Calculate which iterations are disabled for BASELINE | ||
| const baselineDisabledIterations = baselineData | ||
| .filter(item => !item.enabled) | ||
| .map(item => item.iteration); | ||
|
|
||
| console.log('Saving BOTH test and baseline:', { | ||
| testDisabledIterations, | ||
| baselineDisabledIterations, | ||
| testStats, | ||
| baselineStats | ||
| }); | ||
|
|
||
| // One API call saves both TEST and BASELINE stats together | ||
| const response = await fetch('/api/updateStats', { | ||
| method: 'PUT', | ||
| headers: { | ||
| 'Content-Type': 'application/json' | ||
| }, | ||
| body: JSON.stringify({ | ||
| testId, | ||
| baselineId, | ||
| benchmarkName, | ||
| testStats, | ||
| baselineStats, | ||
| testDisabledIterations, | ||
| baselineDisabledIterations, | ||
| }) | ||
| }); | ||
|
|
||
| const result = await response.json(); | ||
|
|
||
| if (result.success) { | ||
| message.success('✓ Both TEST and BASELINE statistics saved successfully!'); | ||
| } else { | ||
| message.error('Failed to save: ' + (result.error || 'Unknown error')); | ||
| } | ||
| } catch (error) { | ||
| message.error('Error saving: ' + error.message); | ||
| console.error('Save error:', error); | ||
| } finally { | ||
| setSaving(false); | ||
| } | ||
| }; | ||
|
|
||
| return ( | ||
| <div> | ||
| {/* One Save Button for bothH tables */} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix typo in comment: |
||
| <div style={{ | ||
| marginBottom: 16, | ||
| padding: 16, | ||
| background: '#f5f5f5', | ||
| borderRadius: 8, | ||
| display: 'flex', | ||
| justifyContent: 'space-between', | ||
| alignItems: 'center' | ||
| }}> | ||
| <div> | ||
| <div style={{ margin: 0, fontSize: 20, fontWeight: 'bold' }}> | ||
| Metrics Details - {benchmarkName} | ||
| </div> | ||
| <div style={{ margin: 0, fontSize: 12, color: 'rgba(0, 0, 0, 1)' }}> | ||
| Annotate bad runs for both test and baseline, then SAVE | ||
| </div> | ||
| </div> | ||
| <Button | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding a Tooltip to the Save button to explain why it is disabled. For example, show |
||
| type="primary" | ||
| size="large" | ||
| onClick={handleSave} | ||
| loading={saving} | ||
| disabled={!testStats || !baselineStats} | ||
| > | ||
| Save Both Statistics | ||
| </Button> | ||
| </div> | ||
|
|
||
|
|
||
| <MetricsTable | ||
| type="test" | ||
| id={testId} | ||
| benchmarkName={benchmarkName} | ||
| onDataChange={setTestData} | ||
| onStatsChange={setTestStats} | ||
| /> | ||
| <Divider /> | ||
| <MetricsTable | ||
| type="baseline" | ||
| id={baselineId} | ||
| benchmarkName={benchmarkName} | ||
| onDataChange={setBaselineData} | ||
| onStatsChange={setBaselineStats} | ||
| /> | ||
| </div> | ||
| ); | ||
| } | ||
| export default MetricsDetails; | ||
|
|
||
| export default MetricsDetails; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a newline here |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ObjectIDis deprecated , useObjectIdfrom mongodb