mirror of
https://github.com/OPM/ResInsight.git
synced 2026-10-24 22:27:55 -05:00
Workflows: Take missing-value warnings from the displayed job
Describe only sees literal input values, so object references such as cases were always reported as missing, and the warning did not update when a value was edited. Compute these warnings from the job's bindings and refresh them when a binding changes.
This commit is contained in:
1 parent
3650b4fbfd
commit
a47a871fea
7 files changed
+118
-1
No files matched your search
@@ -91,7 +91,7 @@ RimWorkflowValidationTools::Result RimWorkflowValidationTools::issuesFromDescrib
|
||||
result.issues.push_back( { .task = task.value( "name" ).toString(),
|
||||
.field = field.toString(),
|
||||
.severity = RimWorkflowIssue::Severity::Warning,
|
||||
.message = QString( "Input '%1' has no value" ).arg( field.toString() ) } );
|
||||
.message = missingValueMessage( field.toString() ) } );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -110,3 +110,40 @@ QString RimWorkflowValidationTools::taskFromMessage( const QString& message, con
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QString RimWorkflowValidationTools::missingValueMessage( const QString& fieldName )
|
||||
{
|
||||
return QString( "Input '%1' has no value" ).arg( fieldName );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// The saved definition only carries literal values, so describe reports object references (cases,
|
||||
/// well paths, views) as missing, and the result goes stale when the user edits a value. The job's
|
||||
/// own bindings are the source of truth for the fields they cover.
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
QJsonArray RimWorkflowValidationTools::issuesWithJobValues( const QString& taskName,
|
||||
const QJsonArray& taskIssues,
|
||||
const std::map<QString, bool>& fieldHasValue )
|
||||
{
|
||||
QJsonArray result;
|
||||
for ( const QJsonValue& value : taskIssues )
|
||||
{
|
||||
const QJsonObject issue = value.toObject();
|
||||
const QString field = issue.value( "field" ).toString();
|
||||
const bool isMissingValueWarning = issue.value( "severity" ).toString() == "warning" &&
|
||||
issue.value( "message" ).toString() == missingValueMessage( field );
|
||||
if ( isMissingValueWarning && fieldHasValue.contains( field ) ) continue;
|
||||
result.append( issue );
|
||||
}
|
||||
|
||||
for ( const auto& [field, hasValue] : fieldHasValue )
|
||||
{
|
||||
if ( hasValue ) continue;
|
||||
result.append(
|
||||
QJsonObject{ { "task", taskName }, { "field", field }, { "severity", "warning" }, { "message", missingValueMessage( field ) } } );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -20,9 +20,11 @@
|
||||
|
||||
#include "RimWorkflowDefinition.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
//==================================================================================================
|
||||
@@ -40,4 +42,9 @@ struct Result
|
||||
Result issuesFromHelperResult( const QJsonObject& helperResult, const QStringList& nodeNames );
|
||||
Result issuesFromDescribe( const QJsonObject& describe, const QJsonObject& describeError, const QStringList& nodeNames );
|
||||
QString taskFromMessage( const QString& message, const QStringList& nodeNames );
|
||||
QString missingValueMessage( const QString& fieldName );
|
||||
|
||||
// Replace the missing-value warnings of a task with warnings derived from the values of a job.
|
||||
// `fieldHasValue` maps the task's bound input fields to whether the job gives them a value.
|
||||
QJsonArray issuesWithJobValues( const QString& taskName, const QJsonArray& taskIssues, const std::map<QString, bool>& fieldHasValue );
|
||||
} // namespace RimWorkflowValidationTools
|
||||
@@ -241,3 +241,30 @@ TEST( RimWorkflowValidationTools, issuesFromHelperResult )
|
||||
EXPECT_EQ( RimWorkflowIssue::Severity::Warning, result.issues[0].severity );
|
||||
EXPECT_EQ( "paths", result.issues[0].field );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
///
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
TEST( RimWorkflowValidationTools, issuesWithJobValues )
|
||||
{
|
||||
const QJsonObject missingCase{ { "task", "select" },
|
||||
{ "field", "case" },
|
||||
{ "severity", "warning" },
|
||||
{ "message", RimWorkflowValidationTools::missingValueMessage( "case" ) } };
|
||||
const QJsonObject otherIssue{ { "task", "select" }, { "field", "" }, { "severity", "error" }, { "message", "Broken" } };
|
||||
|
||||
// A value in the job removes the stale warning from describe
|
||||
QJsonArray issues = RimWorkflowValidationTools::issuesWithJobValues( "select", { missingCase, otherIssue }, { { "case", true } } );
|
||||
ASSERT_EQ( 1, issues.size() );
|
||||
EXPECT_EQ( "Broken", issues[0].toObject().value( "message" ).toString() );
|
||||
|
||||
// A missing value in the job gives one warning, even if describe also reported it
|
||||
issues = RimWorkflowValidationTools::issuesWithJobValues( "select", { missingCase }, { { "case", false } } );
|
||||
ASSERT_EQ( 1, issues.size() );
|
||||
EXPECT_EQ( "case", issues[0].toObject().value( "field" ).toString() );
|
||||
EXPECT_EQ( "warning", issues[0].toObject().value( "severity" ).toString() );
|
||||
|
||||
// Fields the job does not bind keep the warnings from describe
|
||||
issues = RimWorkflowValidationTools::issuesWithJobValues( "select", { missingCase }, {} );
|
||||
EXPECT_EQ( 1, issues.size() );
|
||||
}
|
||||
@@ -1621,6 +1621,7 @@ void RiuMainWindow::workflowBindingChanged( const RimWorkflowFieldBinding* bindi
|
||||
{
|
||||
m_workflowEditor->graphView()->setTaskInputValue( task->taskName(), binding->fieldName(), binding->displayValue() );
|
||||
}
|
||||
m_workflowEditor->updateTaskIssues();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "Workflow/RimWorkflowPortCompatibility.h"
|
||||
#include "Workflow/RimWorkflowTaskCatalog.h"
|
||||
#include "Workflow/RimWorkflowTaskInput.h"
|
||||
#include "Workflow/RimWorkflowValidationTools.h"
|
||||
|
||||
#include "cafCmdFeature.h"
|
||||
#include "cafCmdFeatureManager.h"
|
||||
@@ -260,6 +261,43 @@ void RiuWorkflowEditorWidget::updateTaskInputValues()
|
||||
if ( binding ) m_graphView->setTaskInputValue( task->taskName(), binding->fieldName(), binding->displayValue() );
|
||||
}
|
||||
}
|
||||
updateTaskIssues();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// Show the issues of the workflow, with missing-value warnings taken from the displayed job
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
void RiuWorkflowEditorWidget::updateTaskIssues()
|
||||
{
|
||||
if ( !m_workflow || !m_job ) return;
|
||||
|
||||
for ( const QJsonValue& value : m_workflow->graph().value( "tasks" ).toArray() )
|
||||
{
|
||||
const QJsonObject graphTask = value.toObject();
|
||||
const QString taskName = graphTask.value( "name" ).toString();
|
||||
RimWorkflowTaskInput* taskInput = m_job->taskInput( taskName );
|
||||
|
||||
std::map<QString, bool> fieldHasValue;
|
||||
for ( const QJsonValue& field : graphTask.value( "config_fields" ).toArray() )
|
||||
{
|
||||
const QJsonObject schema = field.toObject();
|
||||
const QString fieldName = schema.value( "name" ).toString();
|
||||
bool hasValue = false;
|
||||
if ( taskInput )
|
||||
{
|
||||
for ( const RimWorkflowFieldBinding* binding : taskInput->items() )
|
||||
{
|
||||
if ( binding && binding->fieldName() == fieldName ) hasValue = !binding->toJsonValue().isNull();
|
||||
}
|
||||
}
|
||||
fieldHasValue[fieldName] = hasValue || !schema.value( "required" ).toBool();
|
||||
}
|
||||
|
||||
m_graphView->setTaskIssues( taskName,
|
||||
RimWorkflowValidationTools::issuesWithJobValues( taskName,
|
||||
graphTask.value( "issues" ).toArray(),
|
||||
fieldHasValue ) );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -57,6 +57,7 @@ public:
|
||||
void refresh();
|
||||
void updateJobState();
|
||||
void updateTaskInputValues();
|
||||
void updateTaskIssues();
|
||||
|
||||
RiuWorkflowGraphView* graphView() const;
|
||||
RiuWorkflowTaskPalette* palette() const;
|
||||
|
||||
@@ -192,6 +192,12 @@ Two layers of validation run:
|
||||
dropped, and a 30 s watchdog stops hung processes.
|
||||
`RimWorkflowValidationTools::issuesFromHelperResult` maps the errors to
|
||||
tasks; anything left over goes to the status line.
|
||||
- **Missing values** come from the displayed job, not from describe. The saved
|
||||
definition only carries literal values, so describe would report cases, well
|
||||
paths and views as missing. The editor replaces describe's "has no value"
|
||||
warnings with ones computed from the job's bindings
|
||||
(`RimWorkflowValidationTools::issuesWithJobValues`). They update as soon as
|
||||
a value is edited.
|
||||
|
||||
Running a workflow whose last validation failed asks for confirmation first.
|
||||
|
||||
|
||||
Reference in new issue
Block a user