Compare commits

...

10 Commits

Author SHA1 Message Date
MichaelYick 04dc38a944 Merge pull request 'Template Managment complete' (#27) from dev into master
Reviewed-on: #27
2023-05-23 01:46:47 +00:00
Tina_Azure 9e5f0a68ab Optimize template edit/creation requestbody parsing 2023-05-22 17:04:41 +02:00
Tina_Azure 549c98f673 implement freelancer alias creation 2023-05-19 18:10:52 +02:00
Tina_Azure bfddfd5271 implement freelancer alias deletion 2023-05-19 18:10:31 +02:00
Tina_Azure d83b427857 implement freelancer alias base management page
and minor fixes
2023-05-19 18:07:05 +02:00
Tina_Azure 1620967c45 implementation of the edit function for the template managment
+minor typo fixes
2023-05-17 18:39:32 +02:00
Tina_Azure d9f3fd711c implement base template operations with the corresponding templates
fully implement the delete operation
todo:edit operation
2023-05-15 19:32:21 +02:00
Tina_Azure bbf526f99f minor fix to avoid the creation of '' templates since crow is incapable of routing those to /<string> while trying to route them to / leading to a 404
obviously it's also possible to just give a general you have to name your template directive but as it stands i don't really see a need for it
2023-05-15 19:31:25 +02:00
Tina_Azure 383db248b7 Create new Template
+minor refactoring
2023-05-15 17:52:16 +02:00
Tina_Azure 09406b0852 Template for managment of templates + add button for creation of new template 2023-05-15 16:28:25 +02:00
17 changed files with 921 additions and 71 deletions

View File

@ -39,7 +39,7 @@ sudo -u postgres psql -c "CREATE TABLE freelancers(
sudo -u postgres psql -c "CREATE TABLE templates(
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
freelancerID int,
name text,
name text NOT NULL,
content text,
contactData text,
contactInformation text,

View File

@ -296,7 +296,7 @@ namespace Database {
/*
* Executes the prepared statement SELECT_FREELANCER_ID
* Takes an open pqxx::connection and the id to select by
* Takes an open pqxx::connection and the email to select by
*/
pqxx::result executePreparedStatement_SELECT_FREELANCER_ID(pqxx::connection &connection, const std::string& freelancerEmail) {
pqxx::work work(connection);
@ -305,10 +305,21 @@ namespace Database {
return result;
}
/*
* Executes the prepared statement SELECT_FREELANCER_NAME
* Takes an open pqxx::connection and the email to select by
*/
pqxx::result executePreparedStatement_SELECT_FREELANCER_NAME(pqxx::connection &connection, const std::string& freelancerEmail) {
pqxx::work work(connection);
pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER_NAME, freelancerEmail);
work.commit();
return result;
}
/*
* Executes the prepared statement SELECT_CHECK_EMAIL_EXISTS
* Takes an open pqxx::connection and the emailAddress to check
* Delivers count of emailaddress occurence 0 for none 1+ for more
* Delivers count of emailaddress occurrence 0 for none 1+ for more
*/
pqxx::result executePreparedStatement_SELECT_CHECK_EMAIL_EXISTS(pqxx::connection &connection, const std::string& freelancerEmail) {
pqxx::work work(connection);
@ -320,7 +331,7 @@ namespace Database {
/*
* Executes the prepared statement SELECT_CHECK_FREELANCER_LOGIN_STATE
* Takes an open pqxx::connection the loginKey and the id to check
* Delivers count of loginValidationKey occurence 0 for none 1+ for more
* Delivers count of loginValidationKey occurrence 0 for none 1+ for more
*/
pqxx::result executePreparedStatement_SELECT_CHECK_FREELANCER_LOGIN_STATE(pqxx::connection &connection, const std::string& freelancerEmail, const std::string& loginKey) {
pqxx::work work(connection);
@ -452,6 +463,68 @@ namespace Database {
return result;
}
/*
* Executes the prepared statement INSERT_FREELANCER_ALIAS
* Takes an open pqxx::connection and aliasname, freelanceremail, route, routeparameter, routevalue
* returns errorLevel
* 0 = no error
* 1 = query error
* 2 = critical error
*/
int executePreparedStatement_INSERT_FREELANCER_ALIAS(pqxx::connection &connection, const std::string& aliasname, const std::string& freelanceremail, const std::string& route, const std::string& routeparameter, const std::string& routevalue) {
try {
pqxx::work work(connection);
work.exec_prepared(PREPARED_STATEMENT_INSERT_FREELANCER_ALIAS, aliasname, freelanceremail, route, routeparameter, routevalue);
work.commit();
}
catch (pqxx::sql_error const &e) {
std::cerr
<< "Database error: " << e.what() << std::endl
<< "Query was: " << e.query() << std::endl;
return 1;
}
catch (std::exception const &e) {
std::cerr << e.what() << std::endl;
return 2;
}
return 0;
}
/*
* Executes the prepared statement SELECT_FREELANCER_ALIAS
* Takes an open pqxx::connection and the freelancer email to select by
*/
pqxx::result executePreparedStatement_SELECT_FREELANCER_ALIAS(pqxx::connection &connection, const std::string& freelancerEmail) {
pqxx::work work(connection);
pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER_ALIAS, freelancerEmail);
work.commit();
return result;
}
/*
* Executes the prepared statement DELETE_FREELANCER_ALIAS
* Deletes the entry for a reset key based on a freelancer email and the alias name
* Takes an open pqxx::connection and the freelancers email
*/
void executePreparedStatement_DELETE_FREELANCER_ALIAS(pqxx::connection &connection, const std::string& aliasName, const std::string& freelancerEmail) {
pqxx::work work(connection);
work.exec_prepared(PREPARED_STATEMENT_DELETE_FREELANCER_ALIAS, aliasName, freelancerEmail);
work.commit();
}
/*
* Executes the prepared statement SELECT_CHECK_FREELANCER_ALIAS
* Takes an open pqxx::connection and the alias name
* Delivers true if the alias is already used
*/
bool executePreparedStatement_SELECT_CHECK_FREELANCER_ALIAS(pqxx::connection &connection, const std::string& aliasName) {
pqxx::work work(connection);
pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS, aliasName);
work.commit();
std::string extractedResult = result.at(0).at(0).c_str();
return extractedResult == "t";
}
/*
* Executes the prepared statement UPDATE_LOGIN_VALIDATION_KEY
* Takes an open pqxx::connection, the freelancerID and the loginKey to update the entry
@ -548,6 +621,56 @@ namespace Database {
work.commit();
}
/*
* Executes the prepared statement INSERT_FREELANCER_TEMPLATE
* Takes an open pqxx::connection and the strings name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, freelancerEmail
* returns errorLevel
* 0 = no error
* 1 = query error
* 2 = critical error
*/
int executePreparedStatement_INSERT_FREELANCER_TEMPLATE(pqxx::connection &connection, const std::string& name, const std::string& content, const std::string& contactdata, const std::string& contactinformation, const std::string& currencypreference, const std::string& priceupfront, const std::string& priceondeliver, const std::string& freelancerEmail) {
try {
pqxx::work work(connection);
work.exec_prepared(PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, freelancerEmail);
work.commit();
}
catch (pqxx::sql_error const &e) {
std::cerr
<< "Database error: " << e.what() << std::endl
<< "Query was: " << e.query() << std::endl;
return 1;
}
catch (std::exception const &e) {
std::cerr << e.what() << std::endl;
return 2;
}
return 0;
}
/*
* Executes the prepared statement UPDATE_EDIT_FREELANCER_TEMPLATE
* Takes an open pqxx::connection name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, templateid and the freelancers email
* returns true if update occured
*/
bool executePreparedStatement_UPDATE_EDIT_FREELANCER_TEMPLATE(pqxx::connection &connection, const std::string& name, const std::string& content, const std::string& contactdata, const std::string& contactinformation, const std::string& currencypreference, const std::string& priceupfront, const std::string& priceondeliver, int templateid, const std::string& emailAddress) {
pqxx::work work(connection);
pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, templateid, emailAddress);
work.commit();
return result.affected_rows() != 0;
}
/*
* Executes the prepared statement DELETE_FREELANCER_TEMPLATE
* Deletes a templated based on the id and validated with the freelancer email
* Takes an open pqxx::connection the template id and the freelancers email
*/
void executePreparedStatement_DELETE_FREELANCER_TEMPLATE(pqxx::connection &connection, int templateID, const std::string& freelancerEmail) {
pqxx::work work(connection);
work.exec_prepared(PREPARED_STATEMENT_DELETE_FREELANCER_TEMPLATE, templateID, freelancerEmail);
work.commit();
}
/*
* Prepares a statement based on ID
* Takes an open pqxx::connection, the statement id

View File

@ -58,12 +58,19 @@ namespace DatabaseStatementConstCollection {
*/
const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_SALT = "selectFreelancerSalt";
const static std::string SQL_STATEMENT_SELECT_FREELANCER_SALT = "select salt from freelancers where emailaddress = $1;";
/*
* Name and Statement for prepared statement to get id using a given email
*/
const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_ID = "selectFreelancerID";
const static std::string SQL_STATEMENT_SELECT_FREELANCER_ID = "select id from freelancers where emailaddress = $1;";
/*
* Name and Statement for prepared statement to get name using a given email
*/
const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_NAME = "selectFreelancerName";
const static std::string SQL_STATEMENT_SELECT_FREELANCER_NAME = "select name from freelancers where emailaddress = $1;";
/*
* Name and Statement for prepared statement to check if hash is valid
*/
@ -100,6 +107,30 @@ namespace DatabaseStatementConstCollection {
const static std::string PREPARED_STATEMENT_SELECT_ALIAS = "selectAlias";
const static std::string SQL_STATEMENT_SELECT_ALIAS = "select aliasname, route, routeparameter, routevalue from aliasroutes where aliasname = $1;";
/*
* Name and Statement for prepared statement to select an alias and its route via the alias name
*/
const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_ALIAS = "selectFreelancerAlias";
const static std::string SQL_STATEMENT_SELECT_FREELANCER_ALIAS = "select aliasname, route from aliasroutes where freelancerid = (select freelancers.id from freelancers where emailaddress = $1);";
/*
* Name and Statement for prepared statement to select an alias and its route via the alias name
*/
const static std::string PREPARED_STATEMENT_DELETE_FREELANCER_ALIAS = "deleteFreelancerAlias";
const static std::string SQL_STATEMENT_DELETE_FREELANCER_ALIAS = "delete from aliasroutes where aliasname = $1 and freelancerid = (select freelancers.id from freelancers where emailaddress = $2);";
/*
* Name and Statement for prepared statement to select an alias and its route via the alias name
*/
const static std::string PREPARED_STATEMENT_INSERT_FREELANCER_ALIAS = "insertFreelancerAlias";
const static std::string SQL_STATEMENT_INSERT_FREELANCER_ALIAS = "insert into aliasroutes (aliasname, freelancerid, route, routeparameter, routevalue) VALUES($1, (select freelancers.id from freelancers where emailaddress = $2), $3, $4, $5);";
/*
* Name and Statement for prepared statement to try to check if an alias already exists
*/
const static std::string PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS = "selectCheckFreelancerAlias";
const static std::string SQL_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS = "select count(*) = 1 from aliasroutes where aliasname = $1;";
/*
* Name and Statement for prepared statement to update the loginvalidationkey of a freelancer via the freelancerID
*/
@ -125,7 +156,7 @@ namespace DatabaseStatementConstCollection {
const static std::string SQL_STATEMENT_SELECT_FREELANCER_EMAIL_FROM_PASSWORD_RESET_KEY = "select freelanceremail from passwordresetkeys where passwordresetkey = $1;";
/*
* Name and Statement for prepared statement to check if an reset key is expired
* Name and Statement for prepared statement to check if a reset key is expired
* returns 0 if key not expired
*/
const static std::string PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_RESET_KEY_EXPIRED = "checkFreelancerResetKeyExpired";
@ -186,6 +217,25 @@ namespace DatabaseStatementConstCollection {
const static std::string PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = "updateExpirationLoginLockOut";
const static std::string SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = "update loginlockout set (attempts, expiration) = (0, CURRENT_TIMESTAMP + make_interval(secs => $2)) where email = $1;";
/*
* Name and Statement for prepared statement to try to add a new template to a freelancer
* $1-8 -> name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver, emailaddress
*/
const static std::string PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE = "insertFreelancerTemplate";
const static std::string SQL_STATEMENT_INSERT_FREELANCER_TEMPLATE = "INSERT INTO templates(freelancerid, name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver) VALUES((select freelancers.id from freelancers where emailaddress = $8), $1, $2, $3, $4, $5, $6, $7);";
/*
* Name and Statement for prepared statement to update the template of a freelancer
*/
const static std::string PREPARED_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE = "updateEeditFreelancerTemplate";
const static std::string SQL_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE = "UPDATE templates SET (name, content, contactdata, contactinformation, currencypreference, priceupfront, priceondeliver) = ($1, $2, $3, $4, $5, $6, $7) WHERE id = $8 and freelancerid = (select freelancers.id from freelancers where emailaddress = $9);";
/*
* Name and Statement for prepared statement to delete a template with ownership validation
*/
const static std::string PREPARED_STATEMENT_DELETE_FREELANCER_TEMPLATE = "deleteFreelancerTemplate";
const static std::string SQL_STATEMENT_DELETE_FREELANCER_TEMPLATE = "delete from templates where id = $1 and freelancerid = (select freelancers.id from freelancers where emailaddress = $2);";
/*
* IDs of prepared statements
*/
@ -218,6 +268,14 @@ namespace DatabaseStatementConstCollection {
const static int ID_INSERT_LOGIN_LOCK_OUT = 26;
const static int ID_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS = 27;
const static int ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT = 28;
const static int ID_INSERT_FREELANCER_TEMPLATE = 29;
const static int ID_DELETE_FREELANCER_TEMPLATE = 30;
const static int ID_UPDATE_EDIT_FREELANCER_TEMPLATE = 31;
const static int ID_SELECT_FREELANCER_ALIAS = 32;
const static int ID_DELETE_FREELANCER_ALIAS = 33;
const static int ID_INSERT_FREELANCER_ALIAS = 34;
const static int ID_SELECT_CHECK_FREELANCER_ALIAS = 35;
const static int ID_SELECT_FREELANCER_NAME = 36;
/*
* Easy access to prepared statements via prepared statement name
@ -251,7 +309,15 @@ namespace DatabaseStatementConstCollection {
{PREPARED_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS, SQL_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS},
{PREPARED_STATEMENT_INSERT_LOGIN_LOCK_OUT, SQL_STATEMENT_INSERT_LOGIN_LOCK_OUT},
{PREPARED_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS, SQL_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS},
{PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT}
{PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, SQL_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT},
{PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE, SQL_STATEMENT_INSERT_FREELANCER_TEMPLATE},
{PREPARED_STATEMENT_DELETE_FREELANCER_TEMPLATE, SQL_STATEMENT_DELETE_FREELANCER_TEMPLATE},
{PREPARED_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE, SQL_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE},
{PREPARED_STATEMENT_SELECT_FREELANCER_ALIAS, SQL_STATEMENT_SELECT_FREELANCER_ALIAS},
{PREPARED_STATEMENT_DELETE_FREELANCER_ALIAS, SQL_STATEMENT_DELETE_FREELANCER_ALIAS},
{PREPARED_STATEMENT_INSERT_FREELANCER_ALIAS, SQL_STATEMENT_INSERT_FREELANCER_ALIAS},
{PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS, SQL_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS},
{PREPARED_STATEMENT_SELECT_FREELANCER_NAME, SQL_STATEMENT_SELECT_FREELANCER_NAME}
};
/*
* Easy access to prepared statement name via int
@ -285,7 +351,15 @@ namespace DatabaseStatementConstCollection {
{ID_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS, PREPARED_STATEMENT_UPDATE_INCREMENT_LOGIN_LOCK_OUT_ATTEMPTS},
{ID_INSERT_LOGIN_LOCK_OUT, PREPARED_STATEMENT_INSERT_LOGIN_LOCK_OUT},
{ID_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS, PREPARED_STATEMENT_SELECT_CHECK_LOGIN_LOCK_OUT_ATTEMPTS},
{ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT}
{ID_UPDATE_EXPIRATION_LOGIN_LOCK_OUT, PREPARED_STATEMENT_UPDATE_EXPIRATION_LOGIN_LOCK_OUT},
{ID_INSERT_FREELANCER_TEMPLATE, PREPARED_STATEMENT_INSERT_FREELANCER_TEMPLATE},
{ID_DELETE_FREELANCER_TEMPLATE, PREPARED_STATEMENT_DELETE_FREELANCER_TEMPLATE},
{ID_UPDATE_EDIT_FREELANCER_TEMPLATE, PREPARED_STATEMENT_UPDATE_EDIT_FREELANCER_TEMPLATE},
{ID_SELECT_FREELANCER_ALIAS, PREPARED_STATEMENT_SELECT_FREELANCER_ALIAS},
{ID_DELETE_FREELANCER_ALIAS, PREPARED_STATEMENT_DELETE_FREELANCER_ALIAS},
{ID_INSERT_FREELANCER_ALIAS, PREPARED_STATEMENT_INSERT_FREELANCER_ALIAS},
{ID_SELECT_CHECK_FREELANCER_ALIAS, PREPARED_STATEMENT_SELECT_CHECK_FREELANCER_ALIAS},
{ID_SELECT_FREELANCER_NAME, PREPARED_STATEMENT_SELECT_FREELANCER_NAME}
};
/*

View File

@ -1,7 +1,6 @@
#include <vector>
#include <string>
#include <thread>
#include <map>
#include <pqxx/pqxx>
@ -72,7 +71,7 @@ int main(int argc, char *argv[]) {
*/
CROW_ROUTE(app, "/@<string>")
([configuration](string alias) {
crow::mustache::context ctx(getAlias(configuration, alias));
crow::mustache::context ctx(Utilities::getAlias(configuration, alias));
auto page = crow::mustache::load(TEMPLATE_ALIAS_REDIRECT);
return page.render(ctx);
});
@ -144,7 +143,7 @@ int main(int argc, char *argv[]) {
if (!resultTemplate.empty()) {
//use freelancerID based on SQL_STATEMENT_SELECT_TEMPLATE
pqxx::result resultCommissionState = Database::executePreparedStatement_SELECT_FREELANCER_COMMISSION_STATE(databaseConnection, stoi(resultTemplate.at(0).at(2).c_str()));
//the commissionstate
//the commission-state
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1)
commissionState = true;
}
@ -230,7 +229,7 @@ int main(int argc, char *argv[]) {
pqxx::result resultCommissionState = Database::executePreparedStatement_SELECT_FREELANCER_COMMISSION_STATE(databaseConnection, newRequest.freelancerID);
//the commissionstate
//the commission-state
if (resultCommissionState.empty() || stoi(resultCommissionState.at(0).at(0).c_str()) == 1) {
ctx[MUSTACHE_ERROR_COMMISSIONS_CLOSED] = true;
}
@ -639,7 +638,7 @@ int main(int argc, char *argv[]) {
});
/*
* Page for freelancer to create/delete/edit Templates
* Page for freelancer to create/select Templates
*/
CROW_ROUTE(app, "/freelancer/templateManagement")
([&, configuration](const crow::request& getRequest ) {
@ -655,7 +654,60 @@ int main(int argc, char *argv[]) {
});
/*
* Page for freelancer to create/delete/edit Templates
* Page for freelancer to create new Template
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/new")
([&, configuration](const crow::request& getRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(getRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW);
return page.render(ctx);
});
/*
* Page for freelancer to create new Template fulfilment
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/new/fulfilment").methods("POST"_method)
([&, configuration](const crow::request& postRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
Utilities::templateItem newTemplate;
string postRequestBody = postRequest.body;
Utilities::decodeString(postRequestBody);
newTemplate.parseRequestBodyIntoItem(postRequestBody);
newTemplate.outputItem();
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_INSERT_FREELANCER_TEMPLATE);
int errorLevel = Database::executePreparedStatement_INSERT_FREELANCER_TEMPLATE(
databaseConnection, newTemplate.name, newTemplate.content, newTemplate.contactdata, newTemplate.contactinformation,
newTemplate.currencypreference, newTemplate.priceupfront, newTemplate.priceondeliver, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
if (errorLevel == 0) {
ctx["templatename"] = newTemplate.name;
ctx["contactdata"] = newTemplate.contactdata;
ctx["contactinformation"] = newTemplate.contactinformation;
ctx["currencypreference"] = newTemplate.currencypreference;
ctx["priceupfront"] = newTemplate.priceupfront;
ctx["priceondeliver"] = newTemplate.priceondeliver;
ctx["content"] = newTemplate.content;
}
else {
ctx[MUSTACHE_FREELANCER_TEMPLATE_CREATION_ERROR] = true;
}
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW_FULFILMENT);
return page.render(ctx);
});
/*
* Page for freelancer to view/delete/edit a Template
*/
CROW_ROUTE(app, "/freelancer/templateManagement/template/<string>").methods("POST"_method)
([&, configuration](const crow::request& postRequest, string templateName ) {
@ -691,11 +743,203 @@ int main(int argc, char *argv[]) {
}
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT);
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT_STAGE_CONFIRMATION);
return page.render(ctx);
});
/*
* Execute Template Operation
*/
CROW_ROUTE(app, "/freelancer/templateManagement/fulfilment/<string>").methods("POST"_method)
([&, configuration](const crow::request& postRequest, string operation ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
crow::mustache::context ctx;
bool operationEdit = false;
bool operationDelete = false;
bool error = false;
if (operation == MUSTACHE_FREELANCER_TEMPLATE_OPERATION_EDIT) {
operationEdit = true;
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_EDIT] = true;
}
else if (operation == MUSTACHE_FREELANCER_TEMPLATE_OPERATION_DELETE) {
operationDelete = true;
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_DELETE] = true;
}
else {
error = true;
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_ERROR] = true;
}
if (!error) {
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
string freelancerEmail = cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL);
string postRequestBody = postRequest.body;
Utilities::decodeString(postRequestBody);
int templateid;
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
for (const string& item : splitPostRequestBody) {
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem[0] == "templateid") {
templateid = stoi(splitItem[1]);
break;
}
}
pqxx::connection databaseConnection(configuration.databaseConnectionString);
if (operationEdit) {
Utilities::templateItem toEditTemplate;
Database::prepareStatement(databaseConnection, ID_UPDATE_EDIT_FREELANCER_TEMPLATE);
toEditTemplate.parseRequestBodyIntoItem(postRequestBody);
toEditTemplate.outputItem();
bool updateSuccess = Database::executePreparedStatement_UPDATE_EDIT_FREELANCER_TEMPLATE(
databaseConnection, toEditTemplate.name, toEditTemplate.content, toEditTemplate.contactdata, toEditTemplate.contactinformation,
toEditTemplate.currencypreference, toEditTemplate.priceupfront, toEditTemplate.priceondeliver, templateid, freelancerEmail);
if (updateSuccess) {
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_COMPLETE] = true;
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_EDIT] = true;
}
else {
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_ERROR] = true;
}
} else if (operationDelete) {
Database::prepareStatement(databaseConnection, ID_DELETE_FREELANCER_TEMPLATE);
Database::executePreparedStatement_DELETE_FREELANCER_TEMPLATE(databaseConnection, templateid, freelancerEmail);
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_COMPLETE] = true;
ctx[MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_DELETE] = true;
}
}
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT_STAGE_EXECUTION);
return page.render(ctx);
});
/*
* Page for freelancer to create/delete Alias
*/
CROW_ROUTE(app, "/freelancer/aliasManagement")
([&, configuration](const crow::request& getRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(getRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx = Utilities::getFreelancerAlias(configuration, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
ctx["freelanceremail"] = cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL);
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_ALIAS_MANAGEMENT);
return page.render(ctx);
});
/*
* Execute Alias deletion
*/
CROW_ROUTE(app, "/freelancer/aliasManagement/delete").methods("POST"_method)
([&, configuration](const crow::request& postRequest) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
string postRequestBody = postRequest.body;
Utilities::decodeString(postRequestBody);
string aliasName;
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
for (const string& item : splitPostRequestBody) {
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem.at(0) == "alias")
aliasName = splitItem.at(1);
}
Utilities::deleteFreelancerAlias(configuration, aliasName, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
ctx["freelanceremail"] = cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL);
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_DELETE);
return page.render(ctx);
});
/*
* Page for freelancer to create alias
*/
CROW_ROUTE(app, "/freelancer/aliasManagement/new")
([&, configuration](const crow::request& getRequest ) {
auto& cookieCtx = app.get_context<crow::CookieParser>(getRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
ctx = Utilities::getFreelancerTemplates(configuration, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
ctx["freelanceremail"] = cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL);
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_NEW);
return page.render(ctx);
});
/*
* Execute alias creation
*/
CROW_ROUTE(app, "/freelancer/aliasManagement/new/fulfilment").methods("POST"_method)
([&, configuration](const crow::request& postRequest) {
auto& cookieCtx = app.get_context<crow::CookieParser>(postRequest);
crow::mustache::context ctx;
if (Utilities::checkCookieLoginState(configuration, cookieCtx)) {
bool error = false;
ctx[MUSTACHE_COOKIE_LOGGED_IN] = true;
string postRequestBody = postRequest.body;
Utilities::decodeString(postRequestBody);
vector<string> splitPostRequestBody = Utilities::splitStringIntoVector(postRequestBody, '&');
string aliasname, templateNameID, templateName;
for (const string& item : splitPostRequestBody) {
vector<string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem.at(0) == "freelanceralias")
aliasname = splitItem.at(1);
if (splitItem.at(0) == "aliasroute")
templateNameID = splitItem.at(1);
}
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatements(databaseConnection, {
ID_SELECT_CHECK_FREELANCER_ALIAS,
ID_INSERT_FREELANCER_ALIAS,
ID_SELECT_FREELANCER_ID,
ID_SELECT_FREELANCER_NAME
});
bool aliasAlreadyUsed = false;
if (aliasname.empty()) {
error = true;
ctx[MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR] = true;
ctx[MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR_UNNAMED] = true;
} else {
ctx["aliasname"] = aliasname;
aliasAlreadyUsed = Database::executePreparedStatement_SELECT_CHECK_FREELANCER_ALIAS(databaseConnection, aliasname);
}
if (aliasAlreadyUsed) {
error = true;
ctx[MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR] = true;
ctx[MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR_DUPLICATE] = true;
}
if (!error) {
string route, routeparameter, routevalue;
pqxx::result freelancerNameResult = Database::executePreparedStatement_SELECT_FREELANCER_NAME(databaseConnection, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
if (templateNameID.empty()) {
routeparameter = "freelancerID";
pqxx::result freelancerIDResult = Database::executePreparedStatement_SELECT_FREELANCER_ID(databaseConnection, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL));
routevalue = freelancerIDResult.at(0).at(0).c_str();
route = Utilities::generateAliasRouteFreelancer(freelancerNameResult.at(0).at(0).c_str());
} else {
routeparameter = "templateID";
vector<string> splitValues = Utilities::splitStringIntoVector(templateNameID, '|');
routevalue = splitValues.at(1);
route = Utilities::generateAliasRouteFreelancerTemplate(freelancerNameResult.at(0).at(0).c_str(), splitValues.at(0));
}
int errorLevel = Database::executePreparedStatement_INSERT_FREELANCER_ALIAS(databaseConnection, aliasname, cookieCtx.get_cookie(COOKIE_FREELANCER_EMAIL), route, routeparameter, routevalue);
ctx["aliasname"] = aliasname;
if (errorLevel != 0)
ctx[MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR] = true;
}
}
auto page = crow::mustache::load(TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_NEW_FULFILMENT);
return page.render(ctx);
});

View File

@ -25,7 +25,14 @@ namespace TemplateConstCollection {
const static std::string TEMPLATE_FREELANCER_REDIRECT_PROFILE = "freelancer_Redirect_Profile.html";
const static std::string TEMPLATE_FREELANCER_PROFILE = "freelancer_Profile.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT = "freelancer_Template_Management.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT = "freelancer_Template_Management_Fulfilment.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT_STAGE_CONFIRMATION = "freelancer_Template_Management_Fulfilment_Stage_Confirmation.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_FULFILMENT_STAGE_EXECUTION = "freelancer_Template_Management_Fulfilment_Stage_Execution.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW = "freelancer_Template_Management_Create_New.html";
const static std::string TEMPLATE_FREELANCER_TEMPLATE_MANAGEMENT_CREATE_NEW_FULFILMENT = "freelancer_Template_Management_Create_New_Fulfilment.html";
const static std::string TEMPLATE_FREELANCER_ALIAS_MANAGEMENT = "freelancer_Alias_Management.html";
const static std::string TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_DELETE = "freelancer_Alias_Management_Delete.html";
const static std::string TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_NEW = "freelancer_Alias_Management_New.html";
const static std::string TEMPLATE_FREELANCER_ALIAS_MANAGEMENT_NEW_FULFILMENT = "freelancer_Alias_Management_New_Fulfilment.html";
//Mustache Error/Success variable names
const static std::string MUSTACHE_ERROR_COMMISSIONS_CLOSED = "ERROR_COMMISSIONS_CLOSED";
@ -54,6 +61,12 @@ namespace TemplateConstCollection {
const static std::string MUSTACHE_RESET_SUCCESS = "RESET_SUCCESS";
const static std::string MUSTACHE_LOGIN_SUCCESS = "LOGIN_SUCCESS";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_ERROR_NO_TEMPLATE = "TEMPLATE_OPERATION_ERROR_NO_TEMPLATE";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_COMPLETE = "TEMPLATE_OPERATION_COMPLETE";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_CREATION_ERROR = "TEMPLATE_CREATION_ERROR";
const static std::string MUSTACHE_FREELANCER_TEMPLATE_OPERATION_FULFILMENT_ERROR = "OPERATION_ERROR";
const static std::string MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR = "ALIAS_CREATION_ERROR";
const static std::string MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR_DUPLICATE = "ALIAS_CREATION_ERROR_DUPLICATE";
const static std::string MUSTACHE_FREELANCER_ALIAS_CREATION_ERROR_UNNAMED = "ALIAS_CREATION_ERROR_UNNAMED";
//Mustache Cookie variable names
const static std::string MUSTACHE_COOKIE_LOGGED_IN = "COOKIE_LOGGED_IN";

View File

@ -59,6 +59,19 @@ namespace Utilities {
return stringToTrim;
}
/*
* Checks if a given string is a valid number
*/
bool checkIfStrIsNumber(const std::string& numberString) {
try {
std::stod(numberString);
}
catch (const std::invalid_argument& ia) {
return false;
}
return true;
}
/*
* Struct representing the configuration file
*/
@ -227,6 +240,54 @@ namespace Utilities {
}
};
/*
* Struct representing a freelancers template
*/
struct templateItem {
std::string name;
std::string content;
std::string contactdata;
std::string contactinformation;
std::string currencypreference;
std::string priceupfront;
std::string priceondeliver;
/*
* Parses a decoded request body string and fills the struct
*/
void parseRequestBodyIntoItem(const std::string& requestBody) {
std::vector<std::string> splitPostRequestBody = Utilities::splitStringIntoVector(requestBody, '&');
for (const std::string& item : splitPostRequestBody) {
std::vector<std::string> splitItem = Utilities::splitStringIntoVector(item, '=');
if (splitItem[0] == "templatename")
name = splitItem[1];
if (splitItem[0] == "templatecontent")
content = splitItem[1];
if (splitItem[0] == "templatecontactdata")
contactdata = splitItem[1];
if (splitItem[0] == "templatecontactinformation")
contactinformation = splitItem[1];
if (splitItem[0] == "templatecurrencypreference")
currencypreference = splitItem[1];
if (splitItem[0] == "templatepriceupfront")
priceupfront = splitItem[1];
if (splitItem[0] == "templatepriceondeliver")
priceondeliver = splitItem[1];
}
if (name.empty())
name = "unnamed";
if (!checkIfStrIsNumber(priceupfront))
priceupfront = "0";
if (!checkIfStrIsNumber(priceondeliver))
priceondeliver = "0";
}
void outputItem() {
std::cout << name << " " << content << " " << contactdata << " " << contactinformation << " " << currencypreference
<< " " << priceupfront << "-" << priceondeliver << " " << std::endl;
}
};
/*
* Takes String and cuts from the start-up to the length of valueName
*/
@ -359,9 +420,11 @@ namespace Utilities {
* returns crow::json::wvalue with the Alias
*/
crow::json::wvalue getAlias(const Utilities::config& configuration, const std::string& alias) {
std::string decodedAlias = alias;
decodeString(decodedAlias);
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_SELECT_ALIAS);
pqxx::result resultAlias = Database::executePreparedStatement_SELECT_ALIAS(databaseConnection, alias);
pqxx::result resultAlias = Database::executePreparedStatement_SELECT_ALIAS(databaseConnection, decodedAlias);
crow::json::wvalue resultJsonAlias;
if (!resultAlias.empty())
resultJsonAlias = Database::convertResultRowToJSON(resultAlias);
@ -505,6 +568,10 @@ namespace Utilities {
}
}
/*
* Gets the freelancer templates and converts them into a wvalue JSON under the name "templates"
* takes config and freelancer email
*/
crow::json::wvalue getFreelancerTemplates(const Utilities::config& configuration, const std::string& emailAddress) {
crow::json::wvalue resultJsonFreelancerTemplate;
@ -522,5 +589,44 @@ namespace Utilities {
}
return resultJsonFreelancerTemplate;
}
/*
* Gets the freelancer alias and converts them into a wvalue JSON under the name "alias"
* takes config and freelancer email
*/
crow::json::wvalue getFreelancerAlias(const Utilities::config& configuration, const std::string& emailAddress) {
crow::json::wvalue resultJsonFreelancerAlias;
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_SELECT_FREELANCER_ALIAS);
pqxx::result aliasResult = Database::executePreparedStatement_SELECT_FREELANCER_ALIAS(databaseConnection, emailAddress);
resultJsonFreelancerAlias = Database::convertResultToJSON(aliasResult, "alias");
return resultJsonFreelancerAlias;
}
/*
* Deletes a freelancers alias
* takes config the alias name and the freelancers email
*/
void deleteFreelancerAlias(const Utilities::config& configuration, const std::string& aliasName, const std::string& emailAddress) {
pqxx::connection databaseConnection(configuration.databaseConnectionString);
Database::prepareStatement(databaseConnection, ID_DELETE_FREELANCER_ALIAS);
Database::executePreparedStatement_DELETE_FREELANCER_ALIAS(databaseConnection, aliasName, emailAddress);
}
/*
* Generates an alias route to the freelancers profile
* takes a freelancers name
*/
std::string generateAliasRouteFreelancer(const std::string& freelancerName) {
return "/customer/" + freelancerName;
}
/*
* Generates an alias route to the freelancers template
* takes a freelancers and a templates name
*/
std::string generateAliasRouteFreelancerTemplate(const std::string& freelancerName, const std::string& templateName) {
return "/customer/" + freelancerName + "/template/" + templateName;
}
}
#endif

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
<h2>Freelancer: {{freelanceremail}}</h2>
<br>
<br>
<table>
{{#alias}}
<tr>
<th>@{{aliasname}}</th>
<th>{{route}}</th>
<th>
<form action="/freelancer/aliasManagement/delete" method="post">
<button type="submit" name="alias" value="{{aliasname}}" class="button">Delete</button>
</form>
</th>
</tr>
{{/alias}}
</table>
<form action="/freelancer/aliasManagement/new" method="get">
<button type="submit" class="button">Create New Alias Route</button>
</form>
{{/COOKIE_LOGGED_IN}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
Operation concluded:
<br>
<form action="/freelancer/aliasManagement" method="get">
<button type="submit" class="button">Return to Alias Managment</button>
</form>
<form action="/freelancer/aliasManagement/new" method="get">
<button type="submit" class="button">Create New Alias Route</button>
</form>
{{/COOKIE_LOGGED_IN}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
<h2>Freelancer: {{freelanceremail}}</h2>
<br>
<form action="/freelancer/aliasManagement/new/fulfilment" method="post">
<label for="freelanceralias">Alias Name: @</label> <input type="text" id="freelanceralias" name="freelanceralias" value=""><br>
<select name="aliasroute">
<option value="">Profile</option>
{{#templates}}
<option value="{{name}}|{{id}}">Template: {{name}}</option>
{{/templates}}
</select><br>
<button type="submit" class="button">Create new Alias</button>
</form>
{{/COOKIE_LOGGED_IN}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
{{^ALIAS_CREATION_ERROR}}
Alias has been created:
<form action="/@{{aliasname}}" method="get">
<button type="submit" class="button">Open @{{aliasname}}</button>
</form>
{{/ALIAS_CREATION_ERROR}}
{{#ALIAS_CREATION_ERROR}}
Alias has not been created:
{{#ALIAS_CREATION_ERROR_DUPLICATE}}
Alias with the chosen name (@{{aliasname}}) already exists.
{{/ALIAS_CREATION_ERROR_DUPLICATE}}
{{#ALIAS_CREATION_ERROR_UNNAMED}}
Alias can not be created without a name.
{{/ALIAS_CREATION_ERROR_UNNAMED}}
{{/ALIAS_CREATION_ERROR}}
<form action="/freelancer/aliasManagement" method="get">
<button type="submit" class="button">Return to Alias Management</button>
</form>
<form action="/freelancer/aliasManagement/new" method="get">
<button type="submit" class="button">Create New Alias Route</button>
</form>
{{/COOKIE_LOGGED_IN}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -28,7 +28,7 @@
<form action="/freelancer/settings" method="get">
<button type="submit" class="button">Change Account Settings</button>
</form>
<form action="/freelancer/aliasSetup" method="get">
<form action="/freelancer/aliasManagement" method="get">
<button type="submit" class="button">Create/Remove Alias</button>
</form>
</div>

View File

@ -8,23 +8,26 @@
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
<h2>Freelancer: {{freelanceremail}}</h2>
<br>
<br>
<table>
{{#templates}}
<tr>
<th>{{name}}</th>
<th>
<form action="/freelancer/templateManagement/template/{{name}}" method="post">
<button type="submit" name="templateaction" value="view|{{id}}" class="button">View</button>
<button type="submit" name="templateaction" value="edit|{{id}}" class="button">Edit</button>
<button type="submit" name="templateaction" value="delete|{{id}}" class="button">Delete</button>
</form>
</th>
</tr>
{{/templates}}
</table>
<h2>Freelancer: {{freelanceremail}}</h2>
<br>
<br>
<table>
{{#templates}}
<tr>
<th>{{name}}</th>
<th>
<form action="/freelancer/templateManagement/template/{{name}}" method="post">
<button type="submit" name="templateaction" value="view|{{id}}" class="button">View</button>
<button type="submit" name="templateaction" value="edit|{{id}}" class="button">Edit</button>
<button type="submit" name="templateaction" value="delete|{{id}}" class="button">Delete</button>
</form>
</th>
</tr>
{{/templates}}
</table>
<form action="/freelancer/templateManagement/template/new" method="get">
<button type="submit" class="button">Create New Template</button>
</form>
{{/COOKIE_LOGGED_IN}}
{{> templateIncludes/freelancerLoginSignupProfileLogoutInterface.html.html}}
<br>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/templateManagement/template/new/fulfilment" method="post">
<label for="templatename">Template Name:</label> <input type="text" id="templatename" name="templatename" value=""><br>
<label for="templatecontactdata">Contact Data:</label> <input type="text" id="templatecontactdata" name="templatecontactdata" value=""><br>
<label for="templatecontactinformation">Contact Information: </label> <input type="text" id="templatecontactinformation" name="templatecontactinformation" value=""><br>
<label for="templatecurrencypreference">Prefered Currency: </label> <input type="text" id="templatecurrencypreference" name="templatecurrencypreference" value=""><br>
<label for="templatepriceupfront">Upfront payment: </label> <input type="text" id="templatepriceupfront" name="templatepriceupfront" value=""><br>
<label for="templatepriceondeliver">On Delivery Payment: </label> <input type="text" id="templatepriceondeliver" name="templatepriceondeliver" value=""><br>
<label for="templatecontent">Description: </label> <textarea id="templatecontent" name="templatecontent" value=""></textarea><br>
<button type="submit" class="button">Create new Template</button>
</form>
<br>
{{/COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{^COOKIE_LOGGED_IN}}
Please Log in.
{{/COOKIE_LOGGED_IN}}
{{#COOKIE_LOGGED_IN}}
{{^TEMPLATE_CREATION_ERROR}}
<h2>Template Successfully Created</h2>
<h3>Template: {{templatename}}</h3>
<div>Contact Information:</div>
<div>
{{contactdata}}<br>
{{contactinformation}}
</div>
<br>
<div>Payment Information:</div>
<div>
Prefered Currency: {{currencypreference}}<br>
Price: Upfront: {{priceupfront}} - On Delivery: {{priceondeliver}}<br>
</div>
<br>
<div>Description:</div>
<div>{{content}}</div>
{{/TEMPLATE_CREATION_ERROR}}
{{#TEMPLATE_CREATION_ERROR}}
Unable to create Template
<form action="/freelancer/templateManagement/template/new" method="get">
<button type="submit" class="button">Create New Template</button>
</form>
{{/TEMPLATE_CREATION_ERROR}}
{{/COOKIE_LOGGED_IN}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -1,37 +0,0 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
<h2>Freelancer: {{freelancername}}</h2>
<h3>Template: {{templatename}}</h3>
<div>Contact Information:</div>
<div>
{{contactdata}}<br>
{{contactinformation}}
</div>
<br>
<div>Payment Information:</div>
<div>
Prefered Currency: {{currencypreference}}<br>
Price: {{pricetotal}} - Upfront: {{priceupfront}} - On Delivery: {{priceondeliver}}<br>
</div>
<br>
<div>Description:</div>
<div>{{content}}</div>
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
<h2>Freelancer: {{freelancername}}</h2>
{{^OPERATION_EDIT}}
<h3>Template: {{templatename}}</h3>
<div>Contact Information:</div>
<div>
{{contactdata}}<br>
{{contactinformation}}
</div>
<br>
<div>Payment Information:</div>
<div>
Prefered Currency: {{currencypreference}}<br>
Price: {{pricetotal}} - Upfront: {{priceupfront}} - On Delivery: {{priceondeliver}}<br>
</div>
<br>
<div>Description:</div>
<div>{{content}}</div>
{{/OPERATION_EDIT}}
{{#OPERATION_EDIT}}
<br>
<form action="/freelancer/templateManagement/fulfilment/edit" method="post">
<label for="templatename">Template Name:</label> <input type="text" id="templatename" name="templatename" value="{{templatename}}"><br>
<label for="templatecontactdata">Contact Data:</label> <input type="text" id="templatecontactdata" name="templatecontactdata" value="{{contactdata}}"><br>
<label for="templatecontactinformation">Contact Information: </label> <input type="text" id="templatecontactinformation" name="templatecontactinformation" value="{{contactinformation}}"><br>
<label for="templatecurrencypreference">Prefered Currency: </label> <input type="text" id="templatecurrencypreference" name="templatecurrencypreference" value="{{currencypreference}}"><br>
<label for="templatepriceupfront">Upfront payment: </label> <input type="text" id="templatepriceupfront" name="templatepriceupfront" value="{{priceupfront}}"><br>
<label for="templatepriceondeliver">On Delivery Payment: </label> <input type="text" id="templatepriceondeliver" name="templatepriceondeliver" value="{{priceondeliver}}"><br>
<label for="templatecontent">Description: </label> <textarea id="templatecontent" name="templatecontent" value="">{{content}}</textarea><br>
<button type="submit" name="templateid" value="{{templateid}}" class="button">Confirm change of Template</button>
</form>
<br>
{{/OPERATION_EDIT}}
{{#OPERATION_DELETE}}
<br>
<form action="/freelancer/templateManagement/fulfilment/delete" method="post">
<button type="submit" name="templateid" value="{{templateid}}" class="button">Confirm Template Deletion</button>
</form>
<br>
{{/OPERATION_DELETE}}
{{#TEMPLATE_OPERATION_ERROR_NO_TEMPLATE}}
<div>
Template could not be found
</div>
{{/TEMPLATE_OPERATION_ERROR_NO_TEMPLATE}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
{{> templateIncludes/style.css.html}}
</head>
<body>
{{#TEMPLATE_OPERATION_COMPLETE}}
The
{{#OPERATION_EDIT}}Edit{{/OPERATION_EDIT}}
{{#OPERATION_DELETE}}Delete{{/OPERATION_DELETE}}
Operation has been completed.
{{/TEMPLATE_OPERATION_COMPLETE}}
{{#OPERATION_ERROR}}
The Operation has not been completed
{{/OPERATION_ERROR}}
<br>
<form action="/freelancer/profile" method="get">
<button type="submit" class="button">Return to profile</button>
</form>
<form action="/freelancer/templateManagement" method="get">
<button type="submit" class="button">Return to Template Management</button>
</form>
<br>
{{> templateIncludes/returnToIndexButton.html.html}}
</body>
</html>