diff --git a/tempo/integrationplugintempo.cpp b/tempo/integrationplugintempo.cpp index fa163975..06378a46 100644 --- a/tempo/integrationplugintempo.cpp +++ b/tempo/integrationplugintempo.cpp @@ -49,20 +49,17 @@ void IntegrationPluginTempo::startPairing(ThingPairingInfo *info) if (info->thingClassId() == tempoConnectionThingClassId) { - - QString jiraCloudInstanceName = info->params().paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); - qCDebug(dcTempo()) << "Checking if the Tempo server is reachable: https://api.tempo.io/core/3"; QNetworkReply *reply = hardwareManager()->networkManager()->get(QNetworkRequest(QUrl("https://api.tempo.io/core/3"))); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); - connect(reply, &QNetworkReply::finished, info, [reply, info, this] { + connect(reply, &QNetworkReply::finished, info, [reply, info] { if (reply->error() != QNetworkReply::NetworkError::HostNotFoundError) { qCDebug(dcTempo()) << "Tempo server is reachable"; - info->finish(Thing::ThingErrorNoError); + info->finish(Thing::ThingErrorNoError, QT_TR_NOOP("Please enter your Tempo API integration token.")); } else { qCWarning(dcTempo()) << "Got online check error" << reply->error() << reply->errorString(); - info->finish(Thing::ThingErrorSetupFailed, tr("Tempo server not reachable, please check the internet connection")); + info->finish(Thing::ThingErrorSetupFailed, tr("Tempo server not reachable, please check the internet connection.")); } }); } else { @@ -81,8 +78,7 @@ void IntegrationPluginTempo::confirmPairing(ThingPairingInfo *info, const QStrin qCWarning(dcTempo()) << "No authorization code received."; return info->finish(Thing::ThingErrorAuthenticationFailure); } - QString atlassianAccountName = info->params().paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); - Tempo *tempo = new Tempo(hardwareManager()->networkManager(), atlassianAccountName, secret, this); + Tempo *tempo = new Tempo(hardwareManager()->networkManager(), secret, this); tempo->getAccounts(); connect(info, &ThingPairingInfo::aborted, tempo, &Tempo::deleteLater); connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, secret, this] (bool authenticated){ @@ -155,7 +151,7 @@ void IntegrationPluginTempo::discoverThings(ThingDiscoveryInfo *info) void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); - qCDebug(dcTempo()) << "Setup thing"; + qCDebug(dcTempo()) << "Setup thing" << thing->name(); if (thing->thingClassId() == tempoConnectionThingClassId) { @@ -172,6 +168,12 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) qCWarning(dcTempo()) << "Tempo connection object not found for thing" << thing->name(); } m_tempoConnections.insert(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); } else { //device loaded from the device database, needs a new access token; @@ -182,8 +184,7 @@ void IntegrationPluginTempo::setupThing(ThingSetupInfo *info) info->finish(Thing::ThingErrorAuthenticationFailure, tr("Token is not available.")); return; } - QString jiraInstanceName = thing->paramValue(tempoConnectionThingAtlassianAccountNameParamTypeId).toString(); - Tempo *tempo = new Tempo(hardwareManager()->networkManager(), jiraInstanceName, token, this); + Tempo *tempo = new Tempo(hardwareManager()->networkManager(), token, this); connect(info, &ThingSetupInfo::aborted, tempo, &Tempo::deleteLater); connect(tempo, &Tempo::authenticationStatusChanged, info, [info, tempo, this] (bool authenticated){ if (authenticated) { @@ -236,12 +237,10 @@ void IntegrationPluginTempo::postSetupThing(Thing *thing) Q_FOREACH (Thing *childThing, myThings().filterByParentId(thing->id())) { if (childThing->thingClassId() == accountThingClassId) { QString key = childThing->paramValue(accountThingKeyParamTypeId).toString(); - QDate from(1970, 1, 1); - tempo->getWorkloadByAccount(key, from, QDate::currentDate()); + tempo->getWorkloadByAccount(key, QDate(1970, 1, 1), QDate::currentDate(), 0, 1000); } else if (childThing->thingClassId() == teamThingClassId) { int id = childThing->paramValue(teamThingIdParamTypeId).toInt(); - QDate from(1970, 1, 1); - tempo->getWorkloadByTeam(id, from, QDate::currentDate()); + tempo->getWorkloadByTeam(id, QDate(1970, 1, 1), QDate::currentDate(), 0, 1000); } } } @@ -260,13 +259,13 @@ void IntegrationPluginTempo::postSetupThing(Thing *thing) 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->getWorkloadByAccount(key, from, QDate::currentDate(), 0, 1000); tempo->getAccounts(); } else if (thing->thingClassId() == teamThingClassId) { 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->getWorkloadByTeam(id, from, QDate::currentDate(), 0, 1000); tempo->getTeams(); } } @@ -276,7 +275,11 @@ void IntegrationPluginTempo::thingRemoved(Thing *thing) qCDebug(dcTempo()) << "Thing removed" << thing->name(); if (thing->thingClassId() == tempoConnectionThingClassId) { m_tempoConnections.take(thing->id())->deleteLater(); + } else if (thing->thingClassId() == teamThingClassId || + thing->thingClassId() == accountThingClassId) { + m_worklogBuffer.remove(thing->id()); } + if (myThings().isEmpty()) { qCDebug(dcTempo()) << "Stopping plugin timer"; hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer15min); @@ -315,20 +318,20 @@ void IntegrationPluginTempo::onAccountsReceived(const QList acco 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; + // 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) { @@ -368,7 +371,7 @@ void IntegrationPluginTempo::onTeamsReceived(const QList teams) } } -void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList workloads) +void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &accountKey, QList workloads, int limit, int offset) { qCDebug(dcTempo()) << "Account workload received, account key:" << accountKey << "Worklog etries: "<< workloads.count(); Thing *thing = myThings().findByParams(ParamList() << Param(accountThingKeyParamTypeId, accountKey)); @@ -377,32 +380,87 @@ void IntegrationPluginTempo::onAccountWorkloadReceived(const QString &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; + if (offset == 0) { + m_worklogBuffer.remove(thing->id()); + } + if (workloads.count() >= limit) { + //limit is reached + if (m_worklogBuffer.contains(thing->id())) { + m_worklogBuffer[thing->id()].append(workloads); + } else { + m_worklogBuffer.insert(thing->id(), workloads); + } + Tempo *tempo = m_tempoConnections.value(thing->parentId()); + if (tempo) { + tempo->getWorkloadByAccount(accountKey, QDate(1970, 1, 1), QDate::currentDate(), offset+workloads.count(), limit); + } + + } else { + uint totalTimeSpentSeconds = 0; + uint thisMonthTimeSpentSeconds = 0; + QDate today = QDate::currentDate(); + Q_FOREACH(Tempo::Worklog workload, workloads) { + if ((workload.startDate.month() == today.month()) && (workload.startDate.year() == today.year())) { + thisMonthTimeSpentSeconds += workload.timeSpentSeconds; + } + totalTimeSpentSeconds += workload.timeSpentSeconds; + } + if (m_worklogBuffer.contains(thing->id())) { + Q_FOREACH(Tempo::Worklog workload, m_worklogBuffer.take(thing->id())) { + if ((workload.startDate.month() == today.month()) && (workload.startDate.year() == today.year())) { + thisMonthTimeSpentSeconds += workload.timeSpentSeconds; + } + totalTimeSpentSeconds += workload.timeSpentSeconds; + } + } + thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); + thing->setStateValue(accountMonthTimeSpentStateTypeId, thisMonthTimeSpentSeconds/3600.00); } - thing->setStateValue(accountTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); - thing->setStateValue(accountMonthTimeSpentStateTypeId, thisMonthTimeSpentSeconds/3600.00); } -void IntegrationPluginTempo::onTeamWorkloadReceived(int teamId, QList workloads) +void IntegrationPluginTempo::onTeamWorkloadReceived(int teamId, QList workloads, int limit, int offset) { - qCDebug(dcTempo()) << "Team workload received, team ID:" << teamId << "Worklog etries: "<< workloads.count(); + qCDebug(dcTempo()) << "Team workload received, team ID:" << teamId << "Worklog entries: "<< 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; + if (offset == 0) { + m_worklogBuffer.remove(thing->id()); + } + if (workloads.count() >= limit) { + //limit is reached# + if (m_worklogBuffer.contains(thing->id())) { + m_worklogBuffer[thing->id()].append(workloads); + } else { + m_worklogBuffer.insert(thing->id(), workloads); + } + Tempo *tempo = m_tempoConnections.value(thing->parentId()); + if (tempo) { + tempo->getWorkloadByTeam(teamId, QDate(1970, 1, 1), QDate::currentDate(), offset+workloads.count(), limit); + } + + } else { + uint totalTimeSpentSeconds = 0; + uint thisMonthTimeSpentSeconds = 0; + QDate today = QDate::currentDate(); + Q_FOREACH(Tempo::Worklog workload, workloads) { + if ((workload.startDate.month() == today.month()) && (workload.startDate.year() == today.year())) { + thisMonthTimeSpentSeconds += workload.timeSpentSeconds; + } + totalTimeSpentSeconds += workload.timeSpentSeconds; + } + if (m_worklogBuffer.contains(thing->id())) { + Q_FOREACH(Tempo::Worklog workload, m_worklogBuffer.take(thing->id())) { + if ((workload.startDate.month() == today.month()) && (workload.startDate.year() == today.year())) { + thisMonthTimeSpentSeconds += workload.timeSpentSeconds; + } + totalTimeSpentSeconds += workload.timeSpentSeconds; + } + } + thing->setStateValue(teamTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); + thing->setStateValue(teamMonthTimeSpentStateTypeId, thisMonthTimeSpentSeconds/3600.00); } - thing->setStateValue(teamTotalTimeSpentStateTypeId, totalTimeSpentSeconds/3600.00); } diff --git a/tempo/integrationplugintempo.h b/tempo/integrationplugintempo.h index 2be13f5a..17d73b22 100644 --- a/tempo/integrationplugintempo.h +++ b/tempo/integrationplugintempo.h @@ -57,6 +57,7 @@ public: private: PluginTimer *m_pluginTimer15min = nullptr; + QHash> m_worklogBuffer; QHash m_setupTempoConnections; QHash m_tempoConnections; @@ -67,7 +68,7 @@ private slots: void onAccountsReceived(const QList accounts); void onTeamsReceived(const QList teams); - void onAccountWorkloadReceived(const QString &accountKey, QList workloads); - void onTeamWorkloadReceived(int teamId, QList workloads); + void onAccountWorkloadReceived(const QString &accountKey, QList workloads, int limit, int offset); + void onTeamWorkloadReceived(int teamId, QList workloads, int limit, int offset); }; #endif // INTEGRATIONPLUGINTEMPO_H diff --git a/tempo/integrationplugintempo.json b/tempo/integrationplugintempo.json index 4999dacd..4040a3df 100644 --- a/tempo/integrationplugintempo.json +++ b/tempo/integrationplugintempo.json @@ -15,15 +15,6 @@ "interfaces": ["account"], "createMethods": ["user"], "setupMethod": "displayPin", - "paramTypes": [ - { - "id": "b4110c37-8331-4057-8e9f-12f34c2623fe", - "name": "atlassianAccountName", - "displayName": "Atlassian account name", - "type": "QString", - "defaultValue": "" - } - ], "stateTypes": [ { "id": "15f45315-5419-4e1b-ace3-fc21503d3b70", @@ -50,6 +41,15 @@ "displayName": "Account", "interfaces": ["connectable"], "createMethods": ["discovery"], + "settingsTypes": [ + { + "id": "56c460b2-37d8-453a-b4f4-8e58be348f85", + "name": "startDate", + "displayName": "Start date", + "defaultValue": "", + "type": "QDate" + } + ], "paramTypes": [ { "id": "c6aeddae-56af-496d-a419-1635ff9bae50", @@ -193,6 +193,15 @@ "defaultValue": 0, "type": "double", "unit": "Hours" + }, + { + "id": "f5ec7b30-3074-41e9-b1fc-62b6307ddbe1", + "name": "monthTimeSpent", + "displayName": "This month time spent", + "displayNameEvent": "This month time spent changed", + "defaultValue": 0, + "type": "double", + "unit": "Hours" } ] } diff --git a/tempo/tempo.cpp b/tempo/tempo.cpp index eaa95a48..93f40062 100644 --- a/tempo/tempo.cpp +++ b/tempo/tempo.cpp @@ -34,18 +34,17 @@ #include "tempo.h" #include "extern-plugininfo.h" -Tempo::Tempo(NetworkAccessManager *networkmanager, const QString &jiraCloudInstanceName, const QString &token, QObject *parent) : +Tempo::Tempo(NetworkAccessManager *networkmanager, const QString &token, QObject *parent) : QObject(parent), m_token(token), - m_jiraCloudInstanceName(jiraCloudInstanceName), m_networkManager(networkmanager) { - qCDebug(dcTempo()) << "Creating tempo connection to" << m_jiraCloudInstanceName; + qCDebug(dcTempo()) << "Creating tempo connection"; } Tempo::~Tempo() { - qCDebug(dcTempo()) << "Deleting tempo connection to" << m_jiraCloudInstanceName; + qCDebug(dcTempo()) << "Deleting tempo connection"; } QString Tempo::token() const @@ -185,9 +184,11 @@ void Tempo::getWorkloadByAccount(const QString &accountKey, QDate from, QDate to return; } QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap(); + int offset = dataMap.value("metadata").toMap().value("offset").toInt(); + int limit = dataMap.value("metadata").toMap().value("limit").toInt(); QList worklogs = parseJsonForWorklog(dataMap); if (!worklogs.isEmpty()) - emit accountWorklogsReceived(accountKey, worklogs); + emit accountWorklogsReceived(accountKey, worklogs, limit, offset); }); } @@ -214,9 +215,11 @@ void Tempo::getWorkloadByTeam(int teamId, QDate from, QDate to, int offset, int return; } QVariantMap dataMap = QJsonDocument::fromJson(rawData).toVariant().toMap(); + int offset = dataMap.value("metadata").toMap().value("offset").toInt(); + int limit = dataMap.value("metadata").toMap().value("limit").toInt(); QList worklogs = parseJsonForWorklog(dataMap); if (!worklogs.isEmpty()) - emit teamWorklogsReceived(teamId, worklogs); + emit teamWorklogsReceived(teamId, worklogs, limit, offset); }); } @@ -239,6 +242,11 @@ void Tempo::setConnected(bool state) QList Tempo::parseJsonForWorklog(const QVariantMap &data) { QVariantList worklogList = data.value("results").toList(); + qCDebug(dcTempo()) << "Worklog received"; + qCDebug(dcTempo()) << " - Count:" << data.value("metadata").toMap().value("count"); + qCDebug(dcTempo()) << " - Offset:" << data.value("metadata").toMap().value("offset"); + qCDebug(dcTempo()) << " - Limit:" << data.value("metadata").toMap().value("limit"); + QList worklogs; Q_FOREACH(QVariant var, worklogList) { QVariantMap map = var.toMap(); @@ -248,8 +256,8 @@ QList Tempo::parseJsonForWorklog(const QVariantMap &data) 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.startDate = QDate::fromString(map["startDate"].toString(), Qt::ISODate); + worklog.startTime = QTime::fromString(map["startTime"].toString(), Qt::ISODate); worklog.description = map["description"].toString(); worklog.createdAt = QDateTime::fromString(map["createdAt"].toString(), Qt::ISODate); worklog.updatedAt = QDateTime::fromString(map["updatedAt"].toString(), Qt::ISODate); diff --git a/tempo/tempo.h b/tempo/tempo.h index 71a431ae..f3a24a02 100644 --- a/tempo/tempo.h +++ b/tempo/tempo.h @@ -95,7 +95,8 @@ public: int jiraWorklogId; QString issue; int timeSpentSeconds; - QDateTime startedAt; + QDate startDate; + QTime startTime; QString description; QDateTime createdAt; QDateTime updatedAt; @@ -111,7 +112,7 @@ public: Lead lead; }; - explicit Tempo(NetworkAccessManager *networkmanager, const QString &jiraCloudInstanceName, const QString &token, QObject *parent = nullptr); + explicit Tempo(NetworkAccessManager *networkmanager, const QString &token, QObject *parent = nullptr); ~Tempo() override; QString token() const; @@ -123,7 +124,6 @@ public: private: QByteArray m_baseControlUrl = "https://api.tempo.io/core/3"; QString m_token; - QString m_jiraCloudInstanceName; NetworkAccessManager *m_networkManager = nullptr; @@ -144,8 +144,8 @@ signals: void teamsReceived(const QList teams); void accountsReceived(const QList accounts); - void accountWorklogsReceived(const QString &accountKey, QList worklogs); - void teamWorklogsReceived(int teamId, QList worklogs); + void accountWorklogsReceived(const QString &accountKey, QList worklogs, int limit, int offset); + void teamWorklogsReceived(int teamId, QList worklogs, int limit, int offset); }; #endif // TEMPO_H diff --git a/tempo/translations/809bc4ca-d1cd-4279-9e0d-7324537ccb5a-en_US.ts b/tempo/translations/809bc4ca-d1cd-4279-9e0d-7324537ccb5a-en_US.ts new file mode 100644 index 00000000..6e5bf7fd --- /dev/null +++ b/tempo/translations/809bc4ca-d1cd-4279-9e0d-7324537ccb5a-en_US.ts @@ -0,0 +1,285 @@ + + + + + IntegrationPluginTempo + + + Please enter your Tempo API integration token. + + + + + Tempo server not reachable, please check the internet connection. + + + + + Create a Tempo connection first + + + + + Token is not available. + + + + + tempo + + + Account + The name of the ThingClass ({8be71352-bdfd-450b-903e-79a4ed203701}) + + + + + + Category + The name of the ParamType (ThingClass: account, EventType: category, ID: {3af6d1c0-bb0a-406f-809b-2c367e1a16bb}) +---------- +The name of the StateType ({3af6d1c0-bb0a-406f-809b-2c367e1a16bb}) of ThingClass account + + + + + Category changed + The name of the EventType ({3af6d1c0-bb0a-406f-809b-2c367e1a16bb}) of ThingClass account + + + + + + + + + + Connected + The name of the ParamType (ThingClass: team, EventType: connected, ID: {a125d3b5-676f-49eb-bb93-feae233c2e91}) +---------- +The name of the StateType ({a125d3b5-676f-49eb-bb93-feae233c2e91}) of ThingClass team +---------- +The name of the ParamType (ThingClass: account, EventType: connected, ID: {0b776bc1-9e56-4205-9bc3-b356026f5b64}) +---------- +The name of the StateType ({0b776bc1-9e56-4205-9bc3-b356026f5b64}) of ThingClass account +---------- +The name of the ParamType (ThingClass: tempoConnection, EventType: connected, ID: {15f45315-5419-4e1b-ace3-fc21503d3b70}) +---------- +The name of the StateType ({15f45315-5419-4e1b-ace3-fc21503d3b70}) of ThingClass tempoConnection + + + + + + + Connected changed + The name of the EventType ({a125d3b5-676f-49eb-bb93-feae233c2e91}) of ThingClass team +---------- +The name of the EventType ({0b776bc1-9e56-4205-9bc3-b356026f5b64}) of ThingClass account +---------- +The name of the EventType ({15f45315-5419-4e1b-ace3-fc21503d3b70}) of ThingClass tempoConnection + + + + + + Contact + The name of the ParamType (ThingClass: account, EventType: contact, ID: {ece43b12-4a0d-4e25-b811-b1aca610bea8}) +---------- +The name of the StateType ({ece43b12-4a0d-4e25-b811-b1aca610bea8}) of ThingClass account + + + + + Contact changed + The name of the EventType ({ece43b12-4a0d-4e25-b811-b1aca610bea8}) of ThingClass account + + + + + + Customer + The name of the ParamType (ThingClass: account, EventType: Customer, ID: {3dcc1426-51f8-46fa-9967-5a93d7bb2633}) +---------- +The name of the StateType ({3dcc1426-51f8-46fa-9967-5a93d7bb2633}) of ThingClass account + + + + + Customer changed + The name of the EventType ({3dcc1426-51f8-46fa-9967-5a93d7bb2633}) of ThingClass account + + + + + + Global + The name of the ParamType (ThingClass: account, EventType: global, ID: {abd55ea0-ad4e-413e-bc77-3e8b7f0a9be4}) +---------- +The name of the StateType ({abd55ea0-ad4e-413e-bc77-3e8b7f0a9be4}) of ThingClass account + + + + + Global changed + The name of the EventType ({abd55ea0-ad4e-413e-bc77-3e8b7f0a9be4}) of ThingClass account + + + + + Id + The name of the ParamType (ThingClass: team, Type: thing, ID: {bb90e986-fcfa-47e8-8783-f2b5a887314a}) + + + + + Key + The name of the ParamType (ThingClass: account, Type: thing, ID: {c6aeddae-56af-496d-a419-1635ff9bae50}) + + + + + + + + Lead + The name of the ParamType (ThingClass: team, EventType: lead, ID: {667a9d8d-4e80-4c7c-938c-d698853fa4b1}) +---------- +The name of the StateType ({667a9d8d-4e80-4c7c-938c-d698853fa4b1}) of ThingClass team +---------- +The name of the ParamType (ThingClass: account, EventType: lead, ID: {f1f2af66-d09a-4242-9058-401145f662c4}) +---------- +The name of the StateType ({f1f2af66-d09a-4242-9058-401145f662c4}) of ThingClass account + + + + + + Lead changed + The name of the EventType ({667a9d8d-4e80-4c7c-938c-d698853fa4b1}) of ThingClass team +---------- +The name of the EventType ({f1f2af66-d09a-4242-9058-401145f662c4}) of ThingClass account + + + + + + Logged in + The name of the ParamType (ThingClass: tempoConnection, EventType: loggedIn, ID: {e4b5be87-dbc9-481e-88da-608c71be8bda}) +---------- +The name of the StateType ({e4b5be87-dbc9-481e-88da-608c71be8bda}) of ThingClass tempoConnection + + + + + Logged in changed + The name of the EventType ({e4b5be87-dbc9-481e-88da-608c71be8bda}) of ThingClass tempoConnection + + + + + + Monthly budget + The name of the ParamType (ThingClass: account, EventType: monthlyBudget, ID: {44ebbc18-7511-48c0-860b-c4de5f634ed6}) +---------- +The name of the StateType ({44ebbc18-7511-48c0-860b-c4de5f634ed6}) of ThingClass account + + + + + Monthly budget changed + The name of the EventType ({44ebbc18-7511-48c0-860b-c4de5f634ed6}) of ThingClass account + + + + + Start date + The name of the ParamType (ThingClass: account, Type: settings, ID: {56c460b2-37d8-453a-b4f4-8e58be348f85}) + + + + + + Status + The name of the ParamType (ThingClass: account, EventType: status, ID: {7948f15b-7243-404e-9e67-18e915e8b328}) +---------- +The name of the StateType ({7948f15b-7243-404e-9e67-18e915e8b328}) of ThingClass account + + + + + Status changed + The name of the EventType ({7948f15b-7243-404e-9e67-18e915e8b328}) of ThingClass account + + + + + Team + The name of the ThingClass ({11c85176-e7fe-44b4-995a-24757273f3af}) + + + + + + Tempo + The name of the vendor ({58fc1ab7-b8b5-4e52-8388-72957ce5852d}) +---------- +The name of the plugin tempo ({809bc4ca-d1cd-4279-9e0d-7324537ccb5a}) + + + + + Tempo connection + The name of the ThingClass ({878eae0a-6217-4b36-bd46-72c911e52e73}) + + + + + + + + This month time spent + The name of the ParamType (ThingClass: team, EventType: monthTimeSpent, ID: {f5ec7b30-3074-41e9-b1fc-62b6307ddbe1}) +---------- +The name of the StateType ({f5ec7b30-3074-41e9-b1fc-62b6307ddbe1}) of ThingClass team +---------- +The name of the ParamType (ThingClass: account, EventType: monthTimeSpent, ID: {81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb}) +---------- +The name of the StateType ({81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb}) of ThingClass account + + + + + + This month time spent changed + The name of the EventType ({f5ec7b30-3074-41e9-b1fc-62b6307ddbe1}) of ThingClass team +---------- +The name of the EventType ({81bec4e8-9fd3-43d1-b339-2a7fdd83e8cb}) of ThingClass account + + + + + + + + Total time spent + The name of the ParamType (ThingClass: team, EventType: totalTimeSpent, ID: {a694682e-3c2a-4146-aa56-9e75fd82bcab}) +---------- +The name of the StateType ({a694682e-3c2a-4146-aa56-9e75fd82bcab}) of ThingClass team +---------- +The name of the ParamType (ThingClass: account, EventType: totalTimeSpent, ID: {1ac39002-56a1-4911-aa68-9d14e142edae}) +---------- +The name of the StateType ({1ac39002-56a1-4911-aa68-9d14e142edae}) of ThingClass account + + + + + + Total time spent changed + The name of the EventType ({a694682e-3c2a-4146-aa56-9e75fd82bcab}) of ThingClass team +---------- +The name of the EventType ({1ac39002-56a1-4911-aa68-9d14e142edae}) of ThingClass account + + + +