forked from qt-creator/qt-creator
Axivion: Fetch the DashboardData via task tree
Enrich the DashboardInfo structure. Use dashboardInfoRecipe() for fetching the project list. Change-Id: Ibbc14d0fae31a8930cec6051e412af15bec71fea Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -268,7 +268,7 @@ void IssuesWidget::updateUi()
|
||||
return;
|
||||
|
||||
// for now just a start..
|
||||
const Dto::AnalysisVersionDto &last = info.versions.back();
|
||||
// const Dto::AnalysisVersionDto &last = info.versions.back();
|
||||
|
||||
const std::vector<Dto::IssueKindInfoDto> &issueKinds = info.issueKinds;
|
||||
for (const Dto::IssueKindInfoDto &kind : issueKinds) {
|
||||
|
@@ -33,13 +33,11 @@
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/async.h>
|
||||
#include <utils/expected.h>
|
||||
#include <utils/networkaccessmanager.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QFutureWatcher>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
@@ -97,6 +95,7 @@ public:
|
||||
|
||||
NetworkAccessManager m_networkAccessManager;
|
||||
AxivionOutputPane m_axivionOutputPane;
|
||||
std::optional<DashboardInfo> m_dashboardInfo;
|
||||
std::optional<Dto::ProjectInfoDto> m_currentProjectInfo;
|
||||
bool m_runningQuery = false;
|
||||
TaskTreeRunner m_taskTreeRunner;
|
||||
@@ -324,6 +323,54 @@ static Group fetchDataRecipe(const QUrl &url,
|
||||
return recipe;
|
||||
}
|
||||
|
||||
static DashboardInfo toDashboardInfo(const QUrl &source, const Dto::DashboardInfoDto &infoDto)
|
||||
{
|
||||
const QVersionNumber versionNumber = infoDto.dashboardVersionNumber
|
||||
? QVersionNumber::fromString(*infoDto.dashboardVersionNumber) : QVersionNumber();
|
||||
|
||||
QStringList projects;
|
||||
QHash<QString, QUrl> projectUrls;
|
||||
|
||||
if (infoDto.projects) {
|
||||
for (const Dto::ProjectReferenceDto &project : *infoDto.projects) {
|
||||
projects.push_back(project.name);
|
||||
projectUrls.insert(project.name, project.url);
|
||||
}
|
||||
}
|
||||
return {source, versionNumber, projects, projectUrls, infoDto.checkCredentialsUrl};
|
||||
}
|
||||
|
||||
Group dashboardInfoRecipe(const DashboardInfoHandler &handler)
|
||||
{
|
||||
const auto onSetup = [handler] {
|
||||
if (dd->m_dashboardInfo) {
|
||||
if (handler)
|
||||
handler(*dd->m_dashboardInfo);
|
||||
return SetupResult::StopWithSuccess;
|
||||
}
|
||||
return SetupResult::Continue;
|
||||
};
|
||||
const auto onDone = [handler](DoneWith result) {
|
||||
if (result == DoneWith::Error && handler)
|
||||
handler(make_unexpected(QString("Error"))); // TODO: Collect error message in the storage.
|
||||
};
|
||||
|
||||
const QUrl url(settings().server.dashboard);
|
||||
|
||||
const auto resultHandler = [handler, url](const Dto::DashboardInfoDto &data) {
|
||||
dd->m_dashboardInfo = toDashboardInfo(url, data);
|
||||
if (handler)
|
||||
handler(*dd->m_dashboardInfo);
|
||||
};
|
||||
|
||||
const Group root {
|
||||
onGroupSetup(onSetup), // Stops if cache exists.
|
||||
fetchDataRecipe<Dto::DashboardInfoDto>(url, resultHandler),
|
||||
onGroupDone(onDone) // TODO: Pass CallDoneIf::Error, write task tree autotest.
|
||||
};
|
||||
return root;
|
||||
}
|
||||
|
||||
void AxivionPluginPrivate::fetchProjectInfo(const QString &projectName)
|
||||
{
|
||||
if (m_taskTreeRunner.isRunning()) { // TODO: cache in queue and run when task tree finished
|
||||
|
@@ -5,6 +5,12 @@
|
||||
|
||||
#include "dashboard/dto.h"
|
||||
|
||||
#include <utils/expected.h>
|
||||
|
||||
#include <QHash>
|
||||
#include <QUrl>
|
||||
#include <QVersionNumber>
|
||||
|
||||
#include <memory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -13,6 +19,8 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace ProjectExplorer { class Project; }
|
||||
|
||||
namespace Tasking { class Group; }
|
||||
|
||||
namespace Axivion::Internal {
|
||||
|
||||
struct IssueListSearch
|
||||
@@ -29,6 +37,19 @@ struct IssueListSearch
|
||||
QString toQuery() const;
|
||||
};
|
||||
|
||||
class DashboardInfo
|
||||
{
|
||||
public:
|
||||
QUrl source;
|
||||
QVersionNumber versionNumber;
|
||||
QStringList projects;
|
||||
QHash<QString, QUrl> projectUrls;
|
||||
std::optional<QUrl> checkCredentialsUrl;
|
||||
};
|
||||
|
||||
using DashboardInfoHandler = std::function<void(const Utils::expected_str<DashboardInfo> &)>;
|
||||
Tasking::Group dashboardInfoRecipe(const DashboardInfoHandler &handler = {});
|
||||
|
||||
void fetchProjectInfo(const QString &projectName);
|
||||
std::optional<Dto::ProjectInfoDto> projectInfo();
|
||||
void fetchIssueTableLayout(const QString &prefix);
|
||||
|
@@ -4,8 +4,6 @@
|
||||
#include "axivionprojectsettings.h"
|
||||
|
||||
#include "axivionplugin.h"
|
||||
#include "axivionquery.h"
|
||||
#include "axivionresultparser.h"
|
||||
#include "axivionsettings.h"
|
||||
#include "axiviontr.h"
|
||||
|
||||
@@ -13,6 +11,8 @@
|
||||
#include <projectexplorer/projectpanelfactory.h>
|
||||
#include <projectexplorer/projectsettingswidget.h>
|
||||
|
||||
#include <solutions/tasking/tasktreerunner.h>
|
||||
|
||||
#include <utils/infolabel.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Tasking;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Axivion::Internal {
|
||||
@@ -96,7 +97,6 @@ public:
|
||||
|
||||
private:
|
||||
void fetchProjects();
|
||||
void onDashboardInfoReceived(const DashboardInfo &info);
|
||||
void onSettingsChanged();
|
||||
void linkProject();
|
||||
void unlinkProject();
|
||||
@@ -110,6 +110,7 @@ private:
|
||||
QPushButton *m_link = nullptr;
|
||||
QPushButton *m_unlink = nullptr;
|
||||
Utils::InfoLabel *m_infoLabel = nullptr;
|
||||
TaskTreeRunner m_taskTreeRunner;
|
||||
};
|
||||
|
||||
AxivionProjectSettingsWidget::AxivionProjectSettingsWidget(ProjectExplorer::Project *project)
|
||||
@@ -166,30 +167,20 @@ void AxivionProjectSettingsWidget::fetchProjects()
|
||||
m_dashboardProjects->clear();
|
||||
m_fetchProjects->setEnabled(false);
|
||||
m_infoLabel->setVisible(false);
|
||||
// TODO perform query and populate m_dashboardProjects
|
||||
const AxivionQuery query(AxivionQuery::DashboardInfo);
|
||||
AxivionQueryRunner *runner = new AxivionQueryRunner(query, this);
|
||||
connect(runner, &AxivionQueryRunner::resultRetrieved,
|
||||
this, [this](const QByteArray &result){
|
||||
onDashboardInfoReceived(ResultParser::parseDashboardInfo(result));
|
||||
});
|
||||
connect(runner, &AxivionQueryRunner::finished, this, [runner]{ runner->deleteLater(); });
|
||||
runner->start();
|
||||
}
|
||||
|
||||
void AxivionProjectSettingsWidget::onDashboardInfoReceived(const DashboardInfo &info)
|
||||
{
|
||||
if (!info.error.isEmpty()) {
|
||||
m_infoLabel->setText(info.error);
|
||||
m_infoLabel->setType(Utils::InfoLabel::Error);
|
||||
m_infoLabel->setVisible(true);
|
||||
const auto onDashboardInfo = [this](const expected_str<DashboardInfo> &info) {
|
||||
if (!info) {
|
||||
m_infoLabel->setText(info.error());
|
||||
m_infoLabel->setType(Utils::InfoLabel::Error);
|
||||
m_infoLabel->setVisible(true);
|
||||
} else {
|
||||
for (const QString &project : info->projects)
|
||||
new QTreeWidgetItem(m_dashboardProjects, {project});
|
||||
}
|
||||
updateEnabledStates();
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for (const Project &project : info.projects)
|
||||
new QTreeWidgetItem(m_dashboardProjects, {project.name});
|
||||
updateEnabledStates();
|
||||
m_taskTreeRunner.start(dashboardInfoRecipe(onDashboardInfo));
|
||||
}
|
||||
|
||||
void AxivionProjectSettingsWidget::onSettingsChanged()
|
||||
|
@@ -5,14 +5,8 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace Axivion::Internal {
|
||||
|
||||
static std::pair<QByteArray, QByteArray> splitHeaderAndBody(const QByteArray &input)
|
||||
@@ -58,67 +52,8 @@ static BaseResult prehandleHeader(const QByteArray &header, const QByteArray &bo
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::pair<BaseResult, QJsonDocument> prehandleHeaderAndBody(const QByteArray &header,
|
||||
const QByteArray &body)
|
||||
{
|
||||
BaseResult result = prehandleHeader(header, body);
|
||||
if (!result.error.isEmpty())
|
||||
return {result, {}};
|
||||
|
||||
QJsonParseError error;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(body, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
result.error = error.errorString();
|
||||
return {result, doc};
|
||||
}
|
||||
|
||||
if (!doc.isObject()) {
|
||||
result.error = "Not an object.";
|
||||
return {result, {}};
|
||||
}
|
||||
|
||||
return {result, doc};
|
||||
}
|
||||
|
||||
namespace ResultParser {
|
||||
|
||||
DashboardInfo parseDashboardInfo(const QByteArray &input)
|
||||
{
|
||||
DashboardInfo result;
|
||||
|
||||
auto [header, body] = splitHeaderAndBody(input);
|
||||
auto [error, doc] = prehandleHeaderAndBody(header, body);
|
||||
if (!error.error.isEmpty()) {
|
||||
result.error = error.error;
|
||||
return result;
|
||||
}
|
||||
const QJsonObject object = doc.object();
|
||||
result.mainUrl = object.value("mainUrl").toString();
|
||||
|
||||
if (!object.contains("projects")) {
|
||||
result.error = "Missing projects information.";
|
||||
return result;
|
||||
}
|
||||
const QJsonValue projects = object.value("projects");
|
||||
if (!projects.isArray()) {
|
||||
result.error = "Projects information not an array.";
|
||||
return result;
|
||||
}
|
||||
const QJsonArray array = projects.toArray();
|
||||
for (const QJsonValue &val : array) {
|
||||
if (!val.isObject())
|
||||
continue;
|
||||
const QJsonObject projectObject = val.toObject();
|
||||
Project project;
|
||||
project.name = projectObject.value("name").toString();
|
||||
project.url = projectObject.value("url").toString();
|
||||
if (project.name.isEmpty() || project.url.isEmpty())
|
||||
continue;
|
||||
result.projects.append(project);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static QRegularExpression issueCsvLineRegex(const QByteArray &firstCsvLine)
|
||||
{
|
||||
QString pattern = "^";
|
||||
|
@@ -22,13 +22,6 @@ public:
|
||||
QString url;
|
||||
};
|
||||
|
||||
class DashboardInfo : public BaseResult
|
||||
{
|
||||
public:
|
||||
QString mainUrl;
|
||||
QList<Project> projects;
|
||||
};
|
||||
|
||||
class ShortIssue : public BaseResult
|
||||
{
|
||||
public:
|
||||
@@ -50,7 +43,6 @@ public:
|
||||
|
||||
namespace ResultParser {
|
||||
|
||||
DashboardInfo parseDashboardInfo(const QByteArray &input);
|
||||
IssuesList parseIssuesList(const QByteArray &input);
|
||||
QString parseRuleInfo(const QByteArray &input);
|
||||
|
||||
|
Reference in New Issue
Block a user