diff --git a/tempo/integrationplugintempo.cpp b/tempo/integrationplugintempo.cpp index 9eb16918..fa163975 100644 --- a/tempo/integrationplugintempo.cpp +++ b/tempo/integrationplugintempo.cpp @@ -109,17 +109,17 @@ void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info) if (info->thingClassId() == accountThingClassId) { Q_FOREACH(Tempo *tempo, m_tempoConnections) { tempo->getAccounts(); - Thing *parentThing = m_tempoConnections.key(tempo); - if (!parentThing) { + ThingId parentThingId = m_tempoConnections.key(tempo); + if (parentThingId.isNull()) { qCWarning(dcTempo()) << "Parent not found"; return; } - connect(tempo, &Tempo::accountsReceived, info, [info, parentThing, this, tempo] (const QList &accounts) { + connect(tempo, &Tempo::accountsReceived, info, [info, parentThingId] (const QList &accounts) { Q_FOREACH(Tempo::Account account, accounts) { if (account.status == Tempo::Status::Archived) continue; - ThingDescriptor descriptor(accountThingClassId, account.name, account.customer.name, parentThing->id()); + ThingDescriptor descriptor(accountThingClassId, account.name, account.customer.name, parentThingId); ParamList params; params << Param(accountThingKeyParamTypeId, account.key); descriptor.setParams(params); @@ -130,15 +130,15 @@ void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info) } else if (info->thingClassId() == teamThingClassId) { Q_FOREACH(Tempo *tempo, m_tempoConnections) { tempo->getTeams(); - Thing *parentThing = m_tempoConnections.key(tempo); - if (!parentThing) { + ThingId parentThingId = m_tempoConnections.key(tempo); + if (parentThingId.isNull()) { qCWarning(dcTempo()) << "Parent not found"; return; } - connect(tempo, &Tempo::teamsReceived, info, [info, parentThing, this, tempo] (const QList &teams) { + connect(tempo, &Tempo::teamsReceived, info, [info, parentThingId] (const QList &teams) { Q_FOREACH(Tempo::Team team, teams) { - ThingDescriptor descriptor(teamThingClassId, team.name, team.summary, parentThing->id()); + ThingDescriptor descriptor(teamThingClassId, team.name, team.summary, parentThingId); ParamList params; params << Param(teamThingIdParamTypeId, team.id); descriptor.setParams(params); @@ -160,9 +160,9 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) if (thing->thingClassId() == tempoConnectionThingClassId) { Tempo *tempo; - if (m_tempoConnections.contains(thing)) { + if (m_tempoConnections.contains(thing->id())) { qCDebug(dcTempo()) << "Setup after reconfiguration, cleaning up"; - m_tempoConnections.take(thing)->deleteLater(); + m_tempoConnections.take(thing->id())->deleteLater(); } if (m_setupTempoConnections.keys().contains(thing->id())) { // This thing setup is after a pairing process @@ -171,7 +171,7 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) if (!tempo) { qCWarning(dcTempo()) << "Tempo connection object not found for thing" << thing->name(); } - m_tempoConnections.insert(thing, tempo); + m_tempoConnections.insert(thing->id(), tempo); info->finish(Thing::ThingErrorNoError); } else { //device loaded from the device database, needs a new access token; @@ -187,15 +187,18 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) connect(info, &ThingSetupInfo::aborted, tempo, &Tempo::deleteLater); connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){ if (authenticated) { - m_tempoConnections.insert(info->thing(), tempo); + m_tempoConnections.insert(info->thing()->id(), tempo); + connect(tempo, &Tempo::connectionChanged, this, &IntegrationPluginTempo::onConnectionChanged); + connect(tempo, &Tempo::authenticationStatusChanged, this, &IntegrationPluginTempo::onAuthenticationStatusChanged); + connect(tempo, &Tempo::accountsReceived, this, &IntegrationPluginTempo::onAccountsReceived); + connect(tempo, &Tempo::teamsReceived, this, &IntegrationPluginTempo::onTeamsReceived); + connect(tempo, &Tempo::accountWorklogsReceived, this, &IntegrationPluginTempo::onAccountWorkloadReceived); + connect(tempo, &Tempo::teamWorklogsReceived, this, &IntegrationPluginTempo::onTeamWorkloadReceived); info->finish(Thing::ThingErrorNoError); } }); tempo->getAccounts(); } - connect(tempo, &Tempo::connectionChanged, this, &IntegrationPluginTempo::onConnectionChanged); - connect(tempo, &Tempo::authenticationStatusChanged, this, &IntegrationPluginTempo::onAuthenticationStatusChanged); - connect(tempo, &Tempo::accountsReceived, this, &IntegrationPluginTempo::onReceivedAccounts); } else if (thing->thingClassId() == accountThingClassId || thing->thingClassId() == teamThingClassId){ @@ -223,53 +226,68 @@ void IntegrationPluginTempo::postSetupThing(Thing *thing) connect(m_pluginTimer15min, &PluginTimer::timeout, this, [this]() { qCDebug(dcTempo()) << "Refresh timer timout, polling all Tempo accounts."; Q_FOREACH (Thing *thing, myThings().filterByThingClassId(tempoConnectionThingClassId)) { - Tempo *tempo = m_tempoConnections.value(thing); + Tempo *tempo = m_tempoConnections.value(thing->id()); if (!tempo) { qWarning(dcTempo()) << "No Tempo connection found for" << thing->name(); continue; } tempo->getAccounts(); + tempo->getTeams(); Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) { - QString key = childThing->paramValue(accountThingKeyParamTypeId).toString(); - QDate from(1970, 1, 1); - tempo->getWorkloadByAccount(key, from, QDate::currentDate()); + if (childThing->thingClassId() == accountThingClassId) { + QString key = childThing->paramValue(accountThingKeyParamTypeId).toString(); + QDate from(1970, 1, 1); + tempo->getWorkloadByAccount(key, from, QDate::currentDate()); + } else if (childThing->thingClassId() == teamThingClassId) { + int id = childThing->paramValue(teamThingIdParamTypeId).toInt(); + QDate from(1970, 1, 1); + tempo->getWorkloadByTeam(id, from, QDate::currentDate()); + } } } }); } if (thing->thingClassId() == tempoConnectionThingClassId) { - Tempo *tempo = m_tempoConnections.value(thing); + Tempo *tempo = m_tempoConnections.value(thing->id()); + if (!tempo) { + qCWarning(dcTempo()) << "Tempo connection not found for" << thing->name(); + return; + } tempo->getAccounts(); } else if (thing->thingClassId() == accountThingClassId) { - + Tempo *tempo = m_tempoConnections.value(thing->parentId()); + QString key = thing->paramValue(accountThingKeyParamTypeId).toString(); + QDate from(1970, 1, 1); + tempo->getWorkloadByAccount(key, from, QDate::currentDate()); + tempo->getAccounts(); } else if (thing->thingClassId() == teamThingClassId) { - - } -} - -void IntegrationPluginTempo::executeAction(ThingActionInfo *info) -{ - Thing *thing = info->thing(); - Action action = info->action(); - - if (thing->thingClassId() == tempoConnectionThingClassId) { - - } else if (thing->thingClassId() == accountThingClassId) { - + Tempo *tempo = m_tempoConnections.value(thing->parentId()); + int id = thing->paramValue(teamThingIdParamTypeId).toInt(); + QDate from(1970, 1, 1); + tempo->getWorkloadByTeam(id, from, QDate::currentDate()); + tempo->getTeams(); } } void IntegrationPluginTempo::thingRemoved(Thing *thing) { qCDebug(dcTempo()) << "Thing removed" << thing->name(); + if (thing->thingClassId() == tempoConnectionThingClassId) { + m_tempoConnections.take(thing->id())->deleteLater(); + } + if (myThings().isEmpty()) { + qCDebug(dcTempo()) << "Stopping plugin timer"; + hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer15min); + m_pluginTimer15min = nullptr; + } } void IntegrationPluginTempo::onConnectionChanged(bool connected) { Tempo *tempo = static_cast(sender()); - Thing *thing = m_tempoConnections.key(tempo); + Thing *thing = myThings().findById(m_tempoConnections.key(tempo)); if (!thing) return; thing->setStateValue(tempoConnectionConnectedStateTypeId, connected); @@ -284,31 +302,107 @@ void IntegrationPluginTempo::onAuthenticationStatusChanged(bool authenticated) { qCDebug(dcTempo()) << "Authentication changed" << authenticated; - Tempo *tempoConnection = static_cast(sender()); - - Thing *thing = m_tempoConnections.key(tempoConnection); + Tempo *tempo = static_cast(sender()); + Thing *thing = myThings().findById(m_tempoConnections.key(tempo)); if (!thing) return; thing->setStateValue(tempoConnectionLoggedInStateTypeId, authenticated); } - -void IntegrationPluginTempo::onReceivedAccounts(const QList &accounts) +void IntegrationPluginTempo::onAccountsReceived(const QList accounts) { - qCDebug(dcTempo()) << "Received" << accounts.count() << "accounts"; + qCDebug(dcTempo()) << "Accounts received"; + + Q_FOREACH(Tempo::Account account, accounts) { + qCDebug(dcTempo()) << " - Account" << account.name; + qCDebug(dcTempo()) << " - Key" << account.key; + qCDebug(dcTempo()) << " - Monthly budget" << account.monthlyBudget; + qCDebug(dcTempo()) << " - Lead" << account.lead.displayName; + qCDebug(dcTempo()) << " - Is Global" << account.global; + qCDebug(dcTempo()) << " - Contact type" << account.contact.type; + qCDebug(dcTempo()) << " - Contact account id" << account.contact.accountId; + qCDebug(dcTempo()) << " - Contact" << account.contact.displayName; + qCDebug(dcTempo()) << " - Category Id" << account.category.id; + qCDebug(dcTempo()) << " - Category name" << account.category.name; + qCDebug(dcTempo()) << " - Category key" << account.category.key; + qCDebug(dcTempo()) << " - Customer id" << account.customer.id; + qCDebug(dcTempo()) << " - Customer key" << account.customer.key; + qCDebug(dcTempo()) << " - Customer name" << account.customer.name; + + Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, account.key)); + if (!thing) { + continue; + } + thing->setName(account.name); + thing->setStateValue(accountConnectedStateTypeId, (account.status != Tempo::Status::Archived)); + thing->setStateValue(accountLeadStateTypeId, account.lead.displayName); + thing->setStateValue(accountGlobalStateTypeId, account.global); + thing->setStateValue(accountCategoryStateTypeId, account.category.name); + thing->setStateValue(accountCustomerStateTypeId, account.customer.name); + thing->setStateValue(accountContactStateTypeId, account.contact.displayName); + thing->setStateValue(accountMonthlyBudgetStateTypeId, account.monthlyBudget); + + if (account.status == Tempo::Status::Open) { + thing->setStateValue(accountStatusStateTypeId, "Open"); + } else if (account.status == Tempo::Status::Closed) { + thing->setStateValue(accountStatusStateTypeId, "Closed"); + } else if (account.status == Tempo::Status::Archived) { + thing->setStateValue(accountStatusStateTypeId, "Archived"); + } + } +} + +void IntegrationPluginTempo::onTeamsReceived(const QList teams) +{ + qCDebug(dcTempo()) << "Teams received"; + + Q_FOREACH(Tempo::Team team, teams) { + Thing *thing = myThings().findByParams(ParamList() << Param(teamThingIdParamTypeId, team.id)); + if (!thing) { + continue; + } + thing->setName(team.name); + thing->setStateValue(teamConnectedStateTypeId, true); + thing->setStateValue(teamLeadStateTypeId, team.lead.displayName); + } } void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList workloads) { + qCDebug(dcTempo()) << "Account workload received, account key:" << accountKey << "Worklog etries: "<< workloads.count(); Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, accountKey)); - if (!thing) + if (!thing) { + qCWarning(dcTempo()) << "Could not find account thing for account key" << accountKey; return; + } + + uint totalTimeSpentSeconds = 0; + uint thisMonthTimeSpentSeconds = 0; + QDate today = QDate::currentDate(); + Q_FOREACH(Tempo::Worklog workload, workloads) { + if (workload.createdAt.date().month() == today.month()) { + thisMonthTimeSpentSeconds += workload.timeSpentSeconds; + } + totalTimeSpentSeconds += workload.timeSpentSeconds; + } + thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); + thing->setStateValue(accountMonthTimeSpentStateTypeId, thisMonthTimeSpentSeconds/3600.00); +} + +void IntegrationPluginTempo::onTeamWorkloadReceived(int teamId, QList workloads) +{ + qCDebug(dcTempo()) << "Team workload received, team ID:" << teamId << "Worklog etries: "<< workloads.count(); + Thing *thing = myThings().findByParams(ParamList() << Param(teamThingIdParamTypeId, teamId)); + if (!thing) { + qCWarning(dcTempo()) << "Could not find team thing for account key" << teamId; + return; + } uint totalTimeSpentSeconds = 0; Q_FOREACH(Tempo::Worklog workload, workloads) { totalTimeSpentSeconds += workload.timeSpentSeconds; } - thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/60); + thing->setStateValue(teamTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); } diff --git a/tempo/integrationplugintempo.h b/tempo/integrationplugintempo.h index b1ee298c..2be13f5a 100644 --- a/tempo/integrationplugintempo.h +++ b/tempo/integrationplugintempo.h @@ -52,20 +52,22 @@ public: void discoverThings(ThingDiscoveryInfo *info) override; void setupThing(ThingSetupInfo *info) override; void postSetupThing(Thing *thing) override; - void executeAction(ThingActionInfo *info) override; void thingRemoved(Thing *thing) override; private: PluginTimer *m_pluginTimer15min = nullptr; QHash m_setupTempoConnections; - QHash m_tempoConnections; + QHash m_tempoConnections; private slots: void onConnectionChanged(bool connected); void onAuthenticationStatusChanged(bool authenticated); - void onReceivedAccounts(const QList &accounts); + + void onAccountsReceived(const QList accounts); + void onTeamsReceived(const QList teams); void onAccountWorkloadReceived(const QString &accountKey, QList workloads); + void onTeamWorkloadReceived(int teamId, QList workloads); }; #endif // INTEGRATIONPLUGINTEMPO_H diff --git a/tempo/integrationplugintempo.json b/tempo/integrationplugintempo.json index ea56685c..4999dacd 100644 --- a/tempo/integrationplugintempo.json +++ b/tempo/integrationplugintempo.json @@ -41,22 +41,6 @@ "displayNameEvent": "Logged in changed", "defaultValue": true, "type": "bool" - }, - { - "id": "f3b9581b-7828-4fbe-be5f-3e8aad78a71e", - "name": "userDisplayName", - "displayName": "User name", - "displayNameEvent": "User name changed", - "defaultValue": "", - "type": "QString" - }, - { - "id": "db70444d-bf67-4133-b2de-54aefbdd7149", - "name": "autoAddAccounts", - "displayName": "Auto add accounts", - "displayNameEvent": "Auto add accounts", - "defaultValue": true, - "type": "bool" } ] }, @@ -72,7 +56,8 @@ "name": "key", "displayName": "Key", "defaultValue": "", - "type": "QString" + "type": "QString", + "readOnly": true } ], "stateTypes": [ @@ -90,11 +75,11 @@ "name": "status", "displayName": "Status", "displayNameEvent": "Status changed", - "defaultValue": "OPEN", + "defaultValue": "Open", "possibleValues": [ - "OPEN", - "CLOSED", - "ARCHIVED" + "Open", + "Closed", + "Archived" ], "type": "QString" }, @@ -152,8 +137,8 @@ "displayName": "Total time spent", "displayNameEvent": "Total time spent changed", "defaultValue": 0, - "type": "uint", - "unit": "Minutes" + "type": "double", + "unit": "Hours" }, { "id": "81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb", @@ -161,8 +146,8 @@ "displayName": "This month time spent", "displayNameEvent": "This month time spent changed", "defaultValue": 0, - "type": "uint", - "unit": "Minutes" + "type": "double", + "unit": "Hours" } ] }, @@ -178,7 +163,8 @@ "name": "id", "displayName": "Id", "defaultValue": 0, - "type": "int" + "type": "int", + "readOnly": true } ], "stateTypes": [ @@ -190,6 +176,23 @@ "defaultValue": true, "cached": false, "type": "bool" + }, + { + "id": "667a9d8d-4e80-4c7c-938c-d698853fa4b1", + "name": "lead", + "displayName": "Lead", + "displayNameEvent": "Lead changed", + "defaultValue": "", + "type": "QString" + }, + { + "id": "a694682e-3c2a-4146-aa56-9e75fd82bcab", + "name": "totalTimeSpent", + "displayName": "Total time spent", + "displayNameEvent": "Total time spent changed", + "defaultValue": 0, + "type": "double", + "unit": "Hours" } ] } diff --git a/tempo/tempo.cpp b/tempo/tempo.cpp index 7f042070..eaa95a48 100644 --- a/tempo/tempo.cpp +++ b/tempo/tempo.cpp @@ -134,15 +134,24 @@ void Tempo::getAccounts() account.lead.self = lead["self"].toString(); account.lead.accountId = lead["accountId"].toString(); account.lead.displayName = lead["displayName"].toString(); - //TODO Customer + QVariantMap customer = map["customer"].toMap(); - account.customer.self = lead["self"].toString(); - //TODO Category + account.customer.self = customer["self"].toString(); + account.customer.key = customer["key"].toString(); + account.customer.id = customer["id"].toInt(); + account.customer.name = customer["name"].toString(); + QVariantMap category = map["category"].toMap(); - account.category.self = lead["self"].toString(); - //TODO Contact + account.category.self = category["self"].toString(); + account.category.key = category["key"].toString(); + account.category.name = category["name"].toString(); + account.category.id = category["id"].toInt(); + QVariantMap contact = map["contact"].toMap(); - account.contact.self = lead["self"].toString(); + account.contact.self = contact["self"].toString(); + account.contact.type = contact["type"].toString(); + account.contact.accountId = contact["accountId"].toString(); + account.contact.displayName = contact["displayName"].toString(); accounts.append(account); } @@ -152,12 +161,14 @@ void Tempo::getAccounts() }); } -void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to) +void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to, int offset, int limit) { QUrl url = QUrl(m_baseControlUrl+"/worklogs/account/"+accountKey); QUrlQuery query; query.addQueryItem("from", from.toString(Qt::DateFormat::ISODate)); query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate)); + query.addQueryItem("offset", QString::number(offset)); + query.addQueryItem("limit", QString::number(limit)); url.setQuery(query); qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString(); @@ -174,30 +185,41 @@ void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to return; } QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap(); - QVariantList worklogList = dataMap.value("results").toList(); - QList worklogs; - Q_FOREACH(QVariant var, worklogList) { - QVariantMap map = var.toMap(); - Worklog worklog; - worklog.self = map["self"].toString(); - worklog.tempoWorklogId = map["tempoWorklogId"].toInt(); - worklog.jiraWorklogId = map["jiraWorklogId"].toInt(); - worklog.issue = map["issue"].toMap().value("key").toString(); - worklog.timeSpentSeconds = map["timeSpentSeconds"].toInt(); - //TODO startDate: required (date-only) - //TODO startTime: required (time-only) - worklog.description = map["description"].toString(); - //TODO createdAt: required (datetime) - //TODO updatedAt: required (datetime) - worklog.authorAccountId = map["author"].toMap().value("accountId").toString(); - worklog.authorDisplayName = map["author"].toMap().value("displayName").toString(); - worklogs.append(worklog); - } + QList worklogs = parseJsonForWorklog(dataMap); if (!worklogs.isEmpty()) emit accountWorklogsReceived(accountKey, worklogs); }); } +void Tempo::getWorkloadByTeam(int teamId, QDate from, QDate to, int offset, int limit) +{ + QUrl url = QUrl(m_baseControlUrl+"/worklogs/team/"+QString::number(teamId)); + QUrlQuery query; + query.addQueryItem("from", from.toString(Qt::DateFormat::ISODate)); + query.addQueryItem("to", to.toString(Qt::DateFormat::ISODate)); + query.addQueryItem("offset", QString::number(offset)); + query.addQueryItem("limit", QString::number(limit)); + url.setQuery(query); + + qCDebug(dcTempo()) << "Get workload by account. Url" << url.toString(); + + QNetworkRequest request(url); + request.setRawHeader("Authorization", "Bearer "+m_token.toUtf8()); + + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + connect(reply, &QNetworkReply::finished, this, [this, teamId, reply]{ + QByteArray rawData = reply->readAll(); + if (!checkStatusCode(reply, rawData)) { + return; + } + QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap(); + QList worklogs = parseJsonForWorklog(dataMap); + if (!worklogs.isEmpty()) + emit teamWorklogsReceived(teamId, worklogs); + }); +} + void Tempo::setAuthenticated(bool state) { if (state != m_authenticated) { @@ -214,6 +236,30 @@ void Tempo::setConnected(bool state) } } +QList Tempo::parseJsonForWorklog(const QVariantMap &data) +{ + QVariantList worklogList = data.value("results").toList(); + QList worklogs; + Q_FOREACH(QVariant var, worklogList) { + QVariantMap map = var.toMap(); + Worklog worklog; + worklog.self = map["self"].toString(); + worklog.tempoWorklogId = map["tempoWorklogId"].toInt(); + worklog.jiraWorklogId = map["jiraWorklogId"].toInt(); + worklog.issue = map["issue"].toMap().value("key").toString(); + worklog.timeSpentSeconds = map["timeSpentSeconds"].toInt(); + //TODO startDate: required (date-only) + //TODO startTime: required (time-only) + worklog.description = map["description"].toString(); + worklog.createdAt = QDateTime::fromString(map["createdAt"].toString(), Qt::ISODate); + worklog.updatedAt = QDateTime::fromString(map["updatedAt"].toString(), Qt::ISODate); + worklog.authorAccountId = map["author"].toMap().value("accountId").toString(); + worklog.authorDisplayName = map["author"].toMap().value("displayName").toString(); + worklogs.append(worklog); + } + return worklogs; +} + bool Tempo::checkStatusCode(QNetworkReply *reply, const QByteArray &rawData) { // Check for the internet connection diff --git a/tempo/tempo.h b/tempo/tempo.h index 1492ec87..71a431ae 100644 --- a/tempo/tempo.h +++ b/tempo/tempo.h @@ -63,8 +63,9 @@ public: struct Category { QUrl self; - QString accountId; - QString displayName; + QString key; + int id; + QString name; }; struct Customer { @@ -116,11 +117,11 @@ public: void getTeams(); void getAccounts(); - void getWorkloadByAccount(const QString &accountKey, QDate from, QDate to); + void getWorkloadByAccount(const QString &accountKey, QDate from, QDate to, int offset = 0, int limit = 50); + void getWorkloadByTeam(int teamId, QDate from, QDate to, int offset = 0, int limit = 50); private: - QByteArray m_baseTokenUrl = "https://api.tempo.io/oauth/token/"; - QByteArray m_baseControlUrl = "https://api.tempo.io/core/3/"; + QByteArray m_baseControlUrl = "https://api.tempo.io/core/3"; QString m_token; QString m_jiraCloudInstanceName; @@ -132,6 +133,7 @@ private: bool m_authenticated = false; bool m_connected = false; + QList parseJsonForWorklog(const QVariantMap &data); bool checkStatusCode(QNetworkReply *reply, const QByteArray &rawData); private slots: @@ -143,6 +145,7 @@ signals: void teamsReceived(const QList teams); void accountsReceived(const QList accounts); void accountWorklogsReceived(const QString &accountKey, QList worklogs); + void teamWorklogsReceived(int teamId, QList worklogs); }; #endif // TEMPO_H