diff --git a/src/plugins/axivion/axivionoutputpane.cpp b/src/plugins/axivion/axivionoutputpane.cpp index 41a445a4074..909ef153711 100644 --- a/src/plugins/axivion/axivionoutputpane.cpp +++ b/src/plugins/axivion/axivionoutputpane.cpp @@ -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 &issueKinds = info.issueKinds; for (const Dto::IssueKindInfoDto &kind : issueKinds) { diff --git a/src/plugins/axivion/axivionplugin.cpp b/src/plugins/axivion/axivionplugin.cpp index 505536c8bbb..56b9be3df33 100644 --- a/src/plugins/axivion/axivionplugin.cpp +++ b/src/plugins/axivion/axivionplugin.cpp @@ -33,13 +33,11 @@ #include #include -#include #include #include #include #include -#include #include #include #include @@ -97,6 +95,7 @@ public: NetworkAccessManager m_networkAccessManager; AxivionOutputPane m_axivionOutputPane; + std::optional m_dashboardInfo; std::optional 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 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(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 diff --git a/src/plugins/axivion/axivionplugin.h b/src/plugins/axivion/axivionplugin.h index 29b3c307323..a82b62b9f81 100644 --- a/src/plugins/axivion/axivionplugin.h +++ b/src/plugins/axivion/axivionplugin.h @@ -5,6 +5,12 @@ #include "dashboard/dto.h" +#include + +#include +#include +#include + #include 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 projectUrls; + std::optional checkCredentialsUrl; +}; + +using DashboardInfoHandler = std::function &)>; +Tasking::Group dashboardInfoRecipe(const DashboardInfoHandler &handler = {}); + void fetchProjectInfo(const QString &projectName); std::optional projectInfo(); void fetchIssueTableLayout(const QString &prefix); diff --git a/src/plugins/axivion/axivionprojectsettings.cpp b/src/plugins/axivion/axivionprojectsettings.cpp index 706da8023e1..591072d962a 100644 --- a/src/plugins/axivion/axivionprojectsettings.cpp +++ b/src/plugins/axivion/axivionprojectsettings.cpp @@ -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 #include +#include + #include #include @@ -21,6 +21,7 @@ #include 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 &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() diff --git a/src/plugins/axivion/axivionresultparser.cpp b/src/plugins/axivion/axivionresultparser.cpp index cd4ec0b11c6..b2823e62f7c 100644 --- a/src/plugins/axivion/axivionresultparser.cpp +++ b/src/plugins/axivion/axivionresultparser.cpp @@ -5,14 +5,8 @@ #include -#include -#include -#include #include -#include -#include - namespace Axivion::Internal { static std::pair splitHeaderAndBody(const QByteArray &input) @@ -58,67 +52,8 @@ static BaseResult prehandleHeader(const QByteArray &header, const QByteArray &bo return result; } -static std::pair 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 = "^"; diff --git a/src/plugins/axivion/axivionresultparser.h b/src/plugins/axivion/axivionresultparser.h index 9ae4ede7761..9302af8082b 100644 --- a/src/plugins/axivion/axivionresultparser.h +++ b/src/plugins/axivion/axivionresultparser.h @@ -22,13 +22,6 @@ public: QString url; }; -class DashboardInfo : public BaseResult -{ -public: - QString mainUrl; - QList 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);