minor refactoring in config

implement pagination
This commit is contained in:
Tina_Azure
2023-05-04 22:22:21 +02:00
parent 4720ffdad5
commit 8d2033b316
8 changed files with 132 additions and 19 deletions

View File

@ -195,6 +195,30 @@ namespace Database {
return result;
}
/*
* Executes the SELECT_FREELANCERS_WITHCOMMISSIONSSTATE statement
* Takes an open pqxx::connection
*/
pqxx::result executeStatement_SELECT_FREELANCERS_COUNT(pqxx::connection &connection) {
pqxx::work work(connection);
pqxx::result result = work.exec(SQL_Statement_SELECT_FREELANCERS_COUNT);
work.commit();
return result;
}
/*
* Executes the SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET statement
* Takes an open pqxx::connection the limit and the offset
*/
pqxx::result executePreparedStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET(pqxx::connection &connection, int limit, int offset) {
if (offset < 0)
offset = 0;
pqxx::work work(connection);
pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET, limit, offset);
work.commit();
return result;
}
/*
* Executes the PURGE_EXPIRED_FREELANCER_RESET_KEYS statement
* Takes an open pqxx::connection

View File

@ -144,6 +144,12 @@ namespace DatabaseStatementConstCollection {
const static std::string PREPARED_STATEMENT_DELETE_FREELANCER_RESET_KEY = "deleteFreelancerResetKey";
const static std::string SQL_STATEMENT_DELETE_FREELANCER_RESET_KEY = "delete from passwordresetkeys where freelanceremail = $1;";
/*
* Name and Statement for prepared statement to delete specific reset key of a freelancer
*/
const static std::string PREPARED_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET = "selectFreelancersWithCommissionstateLimitedAndOffset";
const static std::string SQL_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET = "select id, name, basicInformation , (case when (commissionlimit <= (select count(*) as requestCount from requests where requests.accepted = true and requests.completed = false and requests.freelancerid = freelancers.id group by freelancers.id)) then 'Closed' else 'Open' end) as commissionsclosed from freelancers order by name limit $1 offset $2;";
/*
* IDs of prepared statements
*/
@ -169,6 +175,7 @@ namespace DatabaseStatementConstCollection {
const static int ID_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED = 19;
const static int ID_INSERT_FREELANCER_RESET_KEY = 20;
const static int ID_DELETE_FREELANCER_RESET_KEY = 21;
const static int ID_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET = 22;
/*
* Easy access to prepared statements via prepared statement name
@ -195,7 +202,8 @@ namespace DatabaseStatementConstCollection {
{PREPARED_STATEMENT_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY, SQL_STATEMENT_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY},
{PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED, SQL_STATEMENT_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED},
{PREPARED_STATEMENT_INSERT_FREELANCER_RESET_KEY, SQL_STATEMENT_INSERT_FREELANCER_RESET_KEY},
{PREPARED_STATEMENT_DELETE_FREELANCER_RESET_KEY, SQL_STATEMENT_DELETE_FREELANCER_RESET_KEY}
{PREPARED_STATEMENT_DELETE_FREELANCER_RESET_KEY, SQL_STATEMENT_DELETE_FREELANCER_RESET_KEY},
{PREPARED_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET, SQL_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET}
};
/*
* Easy access to prepared statement name via int
@ -222,7 +230,8 @@ namespace DatabaseStatementConstCollection {
{ID_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY, PREPARED_STATEMENT_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY},
{ID_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED, PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED},
{ID_INSERT_FREELANCER_RESET_KEY, PREPARED_STATEMENT_INSERT_FREELANCER_RESET_KEY},
{ID_DELETE_FREELANCER_RESET_KEY, PREPARED_STATEMENT_DELETE_FREELANCER_RESET_KEY}
{ID_DELETE_FREELANCER_RESET_KEY, PREPARED_STATEMENT_DELETE_FREELANCER_RESET_KEY},
{ID_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET, PREPARED_STATEMENT_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET}
};
/*
@ -235,5 +244,11 @@ namespace DatabaseStatementConstCollection {
* Delivers if the commission limit has been reached and if the commissions are closed based on the accepted/completed state of the freelancers requests
*/
const static std::string SQL_Statement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE = "select id, name, basicInformation , (case when (commissionlimit <= (select count(*) as requestCount from requests where requests.accepted = true and requests.completed = false and requests.freelancerid = freelancers.id group by freelancers.id)) then 'Closed' else 'Open' end) as commissionsclosed from freelancers order by name;";
/*
* Selects freelancer count
*/
const static std::string SQL_Statement_SELECT_FREELANCERS_COUNT = "select count(*) from freelancers;";
}
#endif

View File

@ -15,6 +15,7 @@
# regularTaskExecution={false}
# regularTaskExecutionIntervalSeconds={900} 15min
# regularTaskExecutionModules={} # options separated by "|": reeeprint|counter
# itemsPerPage{0} #0 == no pagination
@ -41,6 +42,8 @@ regularTaskExecution=true;
regularTaskExecutionIntervalSeconds=2;
regularTaskExecutionModules=reeeprint|counter;
regularTaskExecutionModules=;
itemsPerPage=5;
#configend#

View File

@ -1,6 +1,7 @@
#include <vector>
#include <string>
#include <thread>
#include <map>
#include <pqxx/pqxx>
@ -36,9 +37,28 @@ int main(int argc, char *argv[]) {
* Freelancer Profile listing for customers
*/
CROW_ROUTE(app, "/").methods("POST"_method, "GET"_method)
([configuration]() {
([configuration](const crow::request& request) {
int selectedPage = 1;
if (!request.url_params.keys().empty()) {
string selectedPageString = request.url_params.get("page");
if (!selectedPageString.empty())
selectedPage = stoi(selectedPageString);
}
auto page = crow::mustache::load(TEMPLATE_CUSTOMER_INDEX_FREELANCER_LISTING);
crow::mustache::context ctx(Utilities::getFreelancerListing(configuration));
crow::mustache::context ctx(Utilities::getFreelancerListing(configuration, selectedPage));
if (configuration.itemsPerPage > 0) {
ctx[MUSTACHE_PAGINATION] = true;
vector<int> pages = Utilities::getFreelancerIndexPagination(configuration);
ctx[MUSTACHE_PAGINATION_NUMBERS] = pages;
if (selectedPage <= 1)
ctx[MUSTACHE_PAGINATION_PREVIOUS] = 1;
else
ctx[MUSTACHE_PAGINATION_PREVIOUS] = selectedPage - 1;
if (selectedPage >= pages.size())
ctx[MUSTACHE_PAGINATION_NEXT] = pages.size();
else
ctx[MUSTACHE_PAGINATION_NEXT] = selectedPage + 1;
}
return page.render(ctx);
});

View File

@ -52,5 +52,11 @@ namespace TemplateConstCollection {
//Mustache Cookie variable names
const static std::string MUSTACHE_COOKIE_LOGGED_IN = "COOKIE_LOGGED_IN";
//Mustache variable names
const static std::string MUSTACHE_PAGINATION = "PAGINATION";
const static std::string MUSTACHE_PAGINATION_NUMBERS = "PAGINATION_NUMBERS";
const static std::string MUSTACHE_PAGINATION_PREVIOUS = "PAGINATION_PREVIOUS";
const static std::string MUSTACHE_PAGINATION_NEXT = "PAGINATION_NEXT";
}
#endif

View File

@ -11,6 +11,7 @@
#include <stdexcept>
#include <chrono>
#include <thread>
#include <math.h>
#include <openssl/sha.h>
#include <pqxx/pqxx>
@ -78,6 +79,7 @@ namespace Utilities {
{MODULE_NAME_REEE_PRINT, false},
{MODULE_NAME_COUNTER_PRINT, false}
};
int itemsPerPage = 20;
/*
* validates existence of mandatory variables in config
@ -142,57 +144,64 @@ namespace Utilities {
if (lineVector.size() == 2) {
std::cout << lineVector.at(0) << " - " << lineVector.at(1) << std::endl;
std::string lineString = trimFromDelimiter(lineVector.at(1), ';');
if (lineString.empty())
continue;
if (lineVector.at(0) == "emailAddress") {
emailAddress = trimFromDelimiter(lineVector.at(1), ';');
emailAddress = lineString;
continue;
}
if (lineVector.at(0) == "emailPassword") {
emailPassword = trimFromDelimiter(lineVector.at(1), ';');
emailPassword = lineString;
continue;
}
if (lineVector.at(0) == "emailServerAddress") {
emailServerAddress = trimFromDelimiter(lineVector.at(1), ';');
emailServerAddress = lineString;
continue;
}
if (lineVector.at(0) == "emailServerPort") {
emailServerPort = std::stoi(trimFromDelimiter(lineVector.at(1), ';'));
emailServerPort = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "emailAddressDisplay") {
emailAddressDisplay = trimFromDelimiter(lineVector.at(1), ';');
emailAddressDisplay = lineString;
continue;
}
if (lineVector.at(0) == "databaseConnectionString") {
databaseConnectionString = trimFromDelimiter(lineVector.at(1), ';');
databaseConnectionString = lineString;
continue;
}
if (lineVector.at(0) == "sslCrtPath") {
sslCrtPath = trimFromDelimiter(lineVector.at(1), ';');
sslCrtPath = lineString;
continue;
}
if (lineVector.at(0) == "sslKeyPath") {
sslKeyPath = trimFromDelimiter(lineVector.at(1), ';');
sslKeyPath = lineString;
continue;
}
if (lineVector.at(0) == "domain") {
domain = trimFromDelimiter(lineVector.at(1), ';');
domain = lineString;
continue;
}
if (lineVector.at(0) == "regularTaskExecution") {
regularTaskExecution = (trimFromDelimiter(lineVector.at(1), ';') == "true");
regularTaskExecution = (lineString == "true");
continue;
}
if (lineVector.at(0) == "regularTaskExecutionIntervalSeconds") {
regularTaskExecutionIntervalSeconds = std::stoi(trimFromDelimiter(lineVector.at(1), ';'));
regularTaskExecutionIntervalSeconds = std::stoi(lineString);
continue;
}
if (lineVector.at(0) == "regularTaskExecutionModules") {
std::vector<std::string> modules = Utilities::splitStringIntoVector(trimFromDelimiter(lineVector.at(1), ';'), '|');
std::vector<std::string> modules = Utilities::splitStringIntoVector(lineString, '|');
for (const std::string& module : modules) {
regularTaskExecutionModules.at(module) = true;
}
continue;
}
if (lineVector.at(0) == "itemsPerPage") {
itemsPerPage = std::stoi(lineString);
continue;
}
}
}
}
@ -356,12 +365,36 @@ namespace Utilities {
* takes configuration
* returns crow::json::wvalue with the Freelancer profile listing
*/
crow::json::wvalue getFreelancerListing(const Utilities::config& configuration) {
crow::json::wvalue getFreelancerListing(const Utilities::config& configuration, int page) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
pqxx::result result = Database::executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(databaseConnection);
pqxx::result result;
if (configuration.itemsPerPage == 0)
result = Database::executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(databaseConnection);
else {
Database::prepareStatement(databaseConnection, ID_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET);
result = Database::executePreparedStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE_LIMITED_AND_OFFSET(databaseConnection, configuration.itemsPerPage, configuration.itemsPerPage * (page - 1));
}
return Database::convertResultToJSON(result, "freelancerProfiles");
}
/*
* Gets a vector<int> with the appropriate pagination for the configuration.itemsPerPage
* takes configuration
* returns vector<int>
*/
std::vector<int> getFreelancerIndexPagination(const Utilities::config& configuration) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
pqxx::result freelancerCountResult = Database::executeStatement_SELECT_FREELANCERS_COUNT(databaseConnection);
double freelancerCount = std::stoi(freelancerCountResult.at(0).at(0).c_str());
int pageCount = ceil(freelancerCount / configuration.itemsPerPage);
std::vector<int> pagination;
for (int i = 1; i <= pageCount; ++i) {
pagination.push_back(i);
}
return pagination;
}
/*
* Checks if freelancer is logged in
* Takes config, the loginkey and freelancerid taken from the secure cookie

View File

@ -23,6 +23,7 @@
</tr>
{{/freelancerProfiles}}
</table>
{{> templateIncludes/pagination.html.html}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
</body>
</html>

View File

@ -0,0 +1,11 @@
{{#PAGINATION}}
<div>
<a href="/?page={{PAGINATION_PREVIOUS}}">&laquo;</a> -
<a href="/?page={{PAGINATION_NEXT}}">&raquo;</a> |
<br>
{{#PAGINATION_NUMBERS}}
<a href="/?page={{.}}">{{.}}</a>
{{/PAGINATION_NUMBERS}}
</div>
<br>
{{/PAGINATION}}