-
-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
958 additions
and
253 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from conan import ConanFile | ||
|
||
|
||
class KemaiConan(ConanFile): | ||
settings = "os", "compiler", "build_type", "arch" | ||
generators = "cmake_find_package" | ||
requires = ("spdlog/1.11.0", "magic_enum/0.8.2") | ||
|
||
def requirements(self): | ||
if self.settings.os == "Macos": | ||
self.requires("range-v3/0.12.0") |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
#include "kimaiCache.h" | ||
|
||
/* | ||
* TODO: Removes when std::views is available on MacOS/clang | ||
*/ | ||
#ifdef Q_OS_MACOS | ||
# include <range/v3/all.hpp> | ||
#else | ||
# include <ranges> | ||
namespace ranges = std; | ||
#endif | ||
|
||
#include <magic_enum.hpp> | ||
#include <spdlog/spdlog.h> | ||
|
||
using namespace kemai; | ||
|
||
void KimaiCache::synchronize(const std::shared_ptr<KimaiClient>& client, const std::set<Category>& categories) | ||
{ | ||
if (!mSyncSemaphore.try_acquire()) | ||
{ | ||
spdlog::error("Sync already in progress"); | ||
return; | ||
} | ||
|
||
mStatus = KimaiCache::Status::SyncPending; | ||
|
||
// Fill what to sync | ||
if (categories.empty()) | ||
{ | ||
auto categoryArray = magic_enum::enum_values<Category>(); | ||
mPendingSync = {categoryArray.begin(), categoryArray.end()}; | ||
} | ||
else | ||
{ | ||
mPendingSync = categories; | ||
} | ||
|
||
// Notify before running sync requests | ||
emit synchronizeStarted(); | ||
|
||
for (const auto& category : mPendingSync) | ||
{ | ||
switch (category) | ||
{ | ||
case Category::Customers: { | ||
mCustomers.clear(); | ||
auto customersResult = client->requestCustomers(); | ||
connect(customersResult, &KimaiApiBaseResult::ready, this, [this, customersResult] { processCustomersResult(customersResult); }); | ||
connect(customersResult, &KimaiApiBaseResult::error, this, [this, customersResult] { processCustomersResult(customersResult); }); | ||
} | ||
break; | ||
|
||
case Category::Projects: { | ||
mProjects.clear(); | ||
auto projectsResult = client->requestProjects(); | ||
connect(projectsResult, &KimaiApiBaseResult::ready, this, [this, projectsResult] { processProjectsResult(projectsResult); }); | ||
connect(projectsResult, &KimaiApiBaseResult::error, this, [this, projectsResult] { processProjectsResult(projectsResult); }); | ||
} | ||
break; | ||
|
||
case Category::Activities: { | ||
mActivities.clear(); | ||
auto activitiesResult = client->requestActivities(); | ||
connect(activitiesResult, &KimaiApiBaseResult::ready, this, [this, activitiesResult] { processActivitiesResult(activitiesResult); }); | ||
connect(activitiesResult, &KimaiApiBaseResult::error, this, [this, activitiesResult] { processActivitiesResult(activitiesResult); }); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
|
||
KimaiCache::Status KimaiCache::status() const | ||
{ | ||
return mStatus; | ||
} | ||
|
||
Customers KimaiCache::customers() const | ||
{ | ||
return mCustomers; | ||
} | ||
|
||
Projects KimaiCache::projects(std::optional<int> customerId) const | ||
{ | ||
if (customerId.has_value()) | ||
{ | ||
auto its = mProjects | ranges::views::filter([id = customerId.value()](auto const& project) { return project.customer.id == id; }); | ||
return {its.begin(), its.end()}; | ||
} | ||
return mProjects; | ||
} | ||
|
||
Activities KimaiCache::activities(std::optional<int> projectId) const | ||
{ | ||
if (projectId.has_value()) | ||
{ | ||
auto its = mActivities | ranges::views::filter([id = projectId.value()](auto const& activity) { | ||
if (!activity.project.has_value()) | ||
{ | ||
return true; | ||
} | ||
return activity.project->id == id; | ||
}); | ||
return {its.begin(), its.end()}; | ||
} | ||
return mActivities; | ||
} | ||
|
||
void KimaiCache::updateSyncProgress(Category finishedCategory) | ||
{ | ||
const std::lock_guard<std::mutex> lockGuard(mProgressMutex); | ||
|
||
mPendingSync.erase(finishedCategory); | ||
|
||
if (mPendingSync.empty()) | ||
{ | ||
mStatus = KimaiCache::Status::Ready; | ||
mSyncSemaphore.release(); | ||
emit synchronizeFinished(); | ||
} | ||
} | ||
|
||
void KimaiCache::processCustomersResult(CustomersResult customersResult) | ||
{ | ||
if (!customersResult->hasError()) | ||
{ | ||
mCustomers = customersResult->takeResult(); | ||
} | ||
customersResult->deleteLater(); | ||
updateSyncProgress(Category::Customers); | ||
} | ||
|
||
void KimaiCache::processProjectsResult(ProjectsResult projectsResult) | ||
{ | ||
if (!projectsResult->hasError()) | ||
{ | ||
mProjects = projectsResult->takeResult(); | ||
} | ||
projectsResult->deleteLater(); | ||
updateSyncProgress(Category::Projects); | ||
} | ||
|
||
void KimaiCache::processActivitiesResult(ActivitiesResult activitiesResult) | ||
{ | ||
if (!activitiesResult->hasError()) | ||
{ | ||
mActivities = activitiesResult->takeResult(); | ||
} | ||
activitiesResult->deleteLater(); | ||
updateSyncProgress(Category::Activities); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#pragma once | ||
|
||
#include <memory> | ||
#include <mutex> | ||
#include <semaphore> | ||
#include <set> | ||
|
||
#include <QObject> | ||
|
||
#include "client/kimaiclient.h" | ||
|
||
namespace kemai { | ||
|
||
class KimaiCache : public QObject | ||
{ | ||
Q_OBJECT | ||
|
||
public: | ||
enum class Category | ||
{ | ||
Customers, | ||
Projects, | ||
Activities | ||
}; | ||
|
||
enum class Status | ||
{ | ||
Empty, | ||
SyncPending, | ||
Ready | ||
}; | ||
|
||
void synchronize(const std::shared_ptr<KimaiClient>& client, const std::set<Category>& categories = {}); | ||
Status status() const; | ||
|
||
Customers customers() const; | ||
Projects projects(std::optional<int> customerId = std::nullopt) const; | ||
Activities activities(std::optional<int> projectId = std::nullopt) const; | ||
|
||
signals: | ||
void synchronizeStarted(); | ||
void synchronizeFinished(); | ||
|
||
private: | ||
void updateSyncProgress(Category finishedCategory); | ||
void processCustomersResult(CustomersResult customersResult); | ||
void processProjectsResult(ProjectsResult projectsResult); | ||
void processActivitiesResult(ActivitiesResult activitiesResult); | ||
|
||
std::set<Category> mPendingSync; | ||
|
||
Customers mCustomers; | ||
Projects mProjects; | ||
Activities mActivities; | ||
|
||
kemai::KimaiCache::Status mStatus = kemai::KimaiCache::Status::Empty; | ||
std::binary_semaphore mSyncSemaphore{1}; | ||
std::mutex mProgressMutex; | ||
}; | ||
|
||
} // namespace kemai |
Oops, something went wrong.