add groups page for listing and add groups (only for admins)

This commit is contained in:
Dario 2020-08-27 08:35:18 +02:00
parent db87207bc0
commit f817374c46
12 changed files with 510 additions and 6 deletions

View File

@ -2,6 +2,7 @@ CREATE TABLE `groups` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`alias` varchar(190) NOT NULL,
`name` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`description` text,
PRIMARY KEY (`id`),
UNIQUE KEY `alias` (`alias`)

View File

@ -6,7 +6,7 @@ CREATE TABLE `hedera_topics` (
`group_id` int unsigned NOT NULL,
`admin_key_id` int unsigned DEFAULT NULL,
`submit_key_id` int unsigned DEFAULT NULL,
`current_timeout` timestamp NOT NULL DEFAULT '0',
`current_timeout` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00',
`sequence_number` bigint unsigned DEFAULT '0',
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),

View File

@ -0,0 +1,212 @@
#include "AdminGroupsPage.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/DeflatingStream.h"
#line 7 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
#include "../controller/Group.h"
#line 1 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
#include "../ServerConfig.h"
AdminGroupsPage::AdminGroupsPage(Session* arg):
SessionHTTPRequestHandler(arg)
{
}
void AdminGroupsPage::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
bool _compressResponse(request.hasToken("Accept-Encoding", "gzip"));
if (_compressResponse) response.set("Content-Encoding", "gzip");
Poco::Net::HTMLForm form(request, request.stream());
#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
const char* pageName = "Gruppen";
// add
if(!form.empty()) {
auto alias = form.get("group-alias");
if(alias == "")
{
addError(new Error("Add Group", "Alias is empty!"));
}
else
{
auto newGroup = controller::Group::create(
alias,
form.get("group-name", ""),
form.get("group-url", ""),
form.get("group-desc", "")
);
newGroup->getModel()->insertIntoDB(false);
}
}
// select all
auto groups = controller::Group::listAll();
//auto groups = controller::Group::load("gdd1");
//std::vector<Poco::SharedPtr<controller::Group>> groups;
#line 3 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
bool withMaterialIcons = false;
std::ostream& _responseStream = response.send();
Poco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, 1);
std::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;
responseStream << "\n";
// begin include header.cpsp
responseStream << "\n";
responseStream << "<!DOCTYPE html>\n";
responseStream << "<html>\n";
responseStream << "<head>\n";
responseStream << "<meta charset=\"UTF-8\">\n";
responseStream << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n";
responseStream << "<title>Gradido Login Server: ";
#line 11 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( pageName );
responseStream << "</title>\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 12 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/main.css\">\n";
#line 13 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
if(withMaterialIcons) { responseStream << "\n";
responseStream << "<link rel=\"stylesheet\" type=\"text/css\" href=\"";
#line 14 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "css/materialdesignicons.min.css\">\n";
#line 15 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
} responseStream << "\n";
responseStream << "</head>\n";
responseStream << "<body>\n";
responseStream << " <div class=\"layout\">\n";
responseStream << " <div class=\"center-form-single\">\n";
responseStream << " <div class=\"center-form-header\">\n";
responseStream << " <a href=\"";
#line 21 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "\" class=\"center-logo\">\n";
responseStream << " <picture>\n";
responseStream << " <source srcset=\"";
#line 23 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.webp\" type=\"image/webp\">\n";
responseStream << " <source srcset=\"";
#line 24 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" type=\"image/png\">\n";
responseStream << " <img src=\"";
#line 25 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\header.cpsp"
responseStream << ( ServerConfig::g_php_serverPath );
responseStream << "img/logo_schrift.png\" alt=\"logo\" />\n";
responseStream << " </picture>\n";
responseStream << " </a>\n";
responseStream << " </div>";
// end include header.cpsp
responseStream << "\n";
#line 38 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( getErrorsHtml() );
responseStream << "\n";
responseStream << "<div class=\"center-form-container\">\n";
responseStream << "\t<div class=\"content-list\">\n";
responseStream << "\t\t<div class=\"content-list-title\">\n";
responseStream << "\t\t\t<h2>Alle Gruppen</h2>\n";
responseStream << "\t\t</div>\t\n";
responseStream << "\t\t<div class=\"content-list-table\">\n";
responseStream << "\t\t\t<div class=\"row\">\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell\">ID</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell\">Name</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell\">Alias</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell\">Url</div>\n";
responseStream << "\t\t\t\t<div class=\"cell header-cell\">";
#line 50 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( gettext("Description") );
responseStream << "</div>\n";
responseStream << "\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 52 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
for(auto it = groups.begin(); it != groups.end(); it++) {
auto group_model = (*it)->getModel(); responseStream << "\n";
responseStream << "\t\t\t\t<div class=\"row\">\n";
responseStream << "\t\t\t\t\t<div class=\"cell\">";
#line 55 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( group_model->getID() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell\">";
#line 56 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( group_model->getName() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell\">";
#line 57 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( group_model->getAlias() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"cell\">";
#line 58 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( group_model->getUrl() );
responseStream << "</div>\n";
responseStream << "\t\t\t\t\t<div class=\"celL\">";
#line 59 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( group_model->getDescription());
responseStream << "</div>\n";
responseStream << "\t\t\t\t</div>\n";
responseStream << "\t\t\t";
#line 61 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
} responseStream << "\n";
responseStream << "\t\t</div>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-title\">\n";
responseStream << "\t <h3>Eine neue Gruppe anlegen</h3>\n";
responseStream << "\t</div>\n";
responseStream << "\t<div class=\"center-form-form\">\n";
responseStream << "\t\t<form method=\"POST\">\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"group-name\">Name</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"group-name\" type=\"text\" name=\"group-name\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"group-alias\">Alias</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"group-alias\" type=\"text\" name=\"group-alias\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"group-url\">Url</label>\n";
responseStream << "\t\t\t<input class=\"form-control\" id=\"group-url\" type=\"text\" name=\"group-url\"/>\n";
responseStream << "\t\t\t<label class=\"form-label\" for=\"group-desc\">";
#line 75 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( gettext("Description"));
responseStream << "</label>\n";
responseStream << "\t\t\t<textarea class=\"form-control\" name=\"group-desc\" rows=\"3\" maxlength=\"150\" id=\"group-desc\"></textarea>\n";
responseStream << "\t\t\t<input class=\"center-form-submit form-button\" type=\"submit\" name=\"submit\" value=\"";
#line 77 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\adminGroups.cpsp"
responseStream << ( gettext("Add Group") );
responseStream << "\">\n";
responseStream << "\t</form>\n";
responseStream << "</div>\n";
// begin include footer.cpsp
responseStream << " <div class=\"center-bottom\">\n";
responseStream << " <p>Copyright © Gradido 2020</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomleft\">\n";
responseStream << " ";
#line 6 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( mTimeProfiler.string() );
responseStream << "\n";
responseStream << " </div>\n";
responseStream << " <div class=\"bottomright\">\n";
responseStream << " <p>Login Server in Entwicklung</p>\n";
responseStream << " <p>Alpha ";
#line 10 "F:\\Gradido\\gradido_login_server\\src\\cpsp\\footer.cpsp"
responseStream << ( ServerConfig::g_versionString );
responseStream << "</p>\n";
responseStream << " </div>\n";
responseStream << " </div>\n";
responseStream << "</body>\n";
responseStream << "\n";
responseStream << "</html>";
// end include footer.cpsp
responseStream << "\n";
if (_compressResponse) _gzipStream.close();
}

View File

@ -0,0 +1,20 @@
#ifndef AdminGroupsPage_INCLUDED
#define AdminGroupsPage_INCLUDED
#include "Poco/Net/HTTPRequestHandler.h"
#include "SessionHTTPRequestHandler.h"
class AdminGroupsPage: public SessionHTTPRequestHandler
{
public:
AdminGroupsPage(Session*);
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);
};
#endif // AdminGroupsPage_INCLUDED

View File

@ -27,6 +27,7 @@
#include "PassphrasedTransaction.h"
#include "AdminUserPasswordReset.h"
#include "RegisterDirectPage.h"
#include "AdminGroupsPage.h"
#include "DecodeTransactionPage.h"
#include "RepairDefectPassphrase.h"
@ -206,6 +207,11 @@ Poco::Net::HTTPRequestHandler* PageRequestHandlerFactory::createRequestHandler(c
pageRequestHandler->setProfiler(timeUsed);
return pageRequestHandler;
}
if (url_first_part == "/groups") {
auto pageRequestHandler = new AdminGroupsPage(s);
pageRequestHandler->setProfiler(timeUsed);
return pageRequestHandler;
}
}
if(url_first_part == "/logout") {

View File

@ -0,0 +1,69 @@
#include "Group.h"
namespace controller {
Group::Group(model::table::Group* dbModel)
{
mDBModel = dbModel;
}
Group::~Group()
{
}
Poco::AutoPtr<Group> Group::create(const std::string& alias, const std::string& name, const std::string& url, const std::string& description)
{
auto db = new model::table::Group(alias, name, url, description);
auto group = new Group(db);
return Poco::AutoPtr<Group>(group);
}
std::vector<Poco::AutoPtr<Group>> Group::load(const std::string& alias)
{
auto db = new model::table::Group();
auto group_list = db->loadFromDB<std::string, model::table::GroupTuple>("alias", alias, 0);
std::vector<Poco::AutoPtr<Group>> resultVector;
resultVector.reserve(group_list.size());
for (auto it = group_list.begin(); it != group_list.end(); it++) {
resultVector.push_back(new Group(new model::table::Group(*it)));
}
return resultVector;
}
std::vector<Poco::AutoPtr<Group>> Group::listAll()
{
auto db = new model::table::Group();
std::vector<model::table::GroupTuple> group_list;
// throw an unresolved external symbol error
//group_list = db->loadAllFromDB<model::table::GroupTuple>();
// work around for not working call to loadAllFromDB
auto cm = ConnectionManager::getInstance();
Poco::Data::Statement select(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER));
select << "SELECT id, alias, name, url, description FROM " << db->getTableName()
, Poco::Data::Keywords::into(group_list);
size_t resultCount = 0;
try {
resultCount = select.execute();
}
catch (Poco::Exception& ex) {
printf("[Group::listAll] poco exception: %s\n", ex.displayText().data());
}
// work around end
std::vector<Poco::AutoPtr<Group>> resultVector;
resultVector.reserve(group_list.size());
for (auto it = group_list.begin(); it != group_list.end(); it++) {
Poco::AutoPtr<Group> group_ptr(new Group(new model::table::Group(*it)));
resultVector.push_back(group_ptr);
}
return resultVector;
}
}

View File

@ -0,0 +1,33 @@
#ifndef GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE
#define GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE
#include "../model/table/Group.h"
#include "Poco/SharedPtr.h"
#include "TableControllerBase.h"
namespace controller {
class Group : public TableControllerBase
{
public:
~Group();
static Poco::AutoPtr<Group> create(const std::string& alias, const std::string& name, const std::string& url, const std::string& description);
static std::vector<Poco::AutoPtr<Group>> load(const std::string& alias);
static std::vector<Poco::AutoPtr<Group>> listAll();
inline bool deleteFromDB() { return mDBModel->deleteFromDB(); }
inline Poco::AutoPtr<model::table::Group> getModel() { return _getModel<model::table::Group>(); }
protected:
Group(model::table::Group* dbModel);
};
}
#endif //GRADIDO_LOGIN_SERVER_CONTROLLER_GROUP_INCLUDE

View File

@ -8,6 +8,19 @@ namespace model {
{
}
Group::Group(const std::string& alias, const std::string& name, const std::string& url, const std::string& description)
: mAlias(alias), mName(name), mUrl(url), mDescription(description)
{
}
Group::Group(GroupTuple tuple)
: ModelBase(tuple.get<0>()),
mAlias(tuple.get<1>()), mName(tuple.get<2>()), mUrl(tuple.get<3>()), mDescription(tuple.get<4>())
{
}
Group::~Group()
{
@ -18,6 +31,7 @@ namespace model {
std::stringstream ss;
ss << "Alias: " << mAlias << std::endl;
ss << "Name: " << mName << std::endl;
ss << "Url: " << mUrl << std::endl;
ss << "Description:" << mDescription << std::endl;
return ss.str();
}
@ -26,9 +40,28 @@ namespace model {
{
Poco::Data::Statement select(session);
select << "SELECT id, alias, name, description FROM " << getTableName()
select << "SELECT id, alias, name, url, description FROM " << getTableName()
<< " where " << fieldName << " = ?"
, into(mID), into(mAlias), into(mName), into(mDescription);
, into(mID), into(mAlias), into(mName), into(mUrl), into(mDescription);
return select;
}
Poco::Data::Statement Group::_loadAllFromDB(Poco::Data::Session session)
{
Poco::Data::Statement select(session);
select << "SELECT id, alias, name, url, description FROM " << getTableName();
return select;
}
Poco::Data::Statement Group::_loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName)
{
Poco::Data::Statement select(session);
// typedef Poco::Tuple<std::string, std::string, std::string, Poco::Nullable<Poco::Data::BLOB>, int> UserTuple;
select << "SELECT id, alias, name, url, description FROM " << getTableName()
<< " where " << fieldName << " LIKE ?";
return select;
}
@ -48,8 +81,8 @@ namespace model {
Poco::Data::Statement insert(session);
lock();
insert << "INSERT INTO " << getTableName()
<< " (alias, name, description) VALUES(?,?,?)"
, use(mAlias), use(mName), use(mDescription);
<< " (alias, name, url, description) VALUES(?,?,?,?)"
, use(mAlias), use(mName), use(mUrl), use(mDescription);
unlock();
return insert;
}

View File

@ -2,30 +2,47 @@
#define GRADIDO_LOGIN_SERVER_MODEL_TABLE_GROUPS_INCLUDE
#include "ModelBase.h"
#include "Poco/Tuple.h"
namespace model {
namespace table {
typedef Poco::Tuple<int, std::string, std::string, std::string, std::string> GroupTuple;
class Group : public ModelBase
{
public:
Group();
Group(const std::string& alias, const std::string& name, const std::string& url, const std::string& description);
Group(GroupTuple userTuple);
~Group();
// generic db operations
const char* getTableName() const { return "groups"; }
std::string toString();
inline const std::string& getAlias() const { return mAlias; }
inline const std::string& getName() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mName; }
inline const std::string& getDescription() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mDescription; }
inline const std::string& getUrl() const { std::shared_lock<std::shared_mutex> _lock(mSharedMutex); return mUrl; }
inline void setName(const std::string& name) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mName = name; }
inline void setDescription(const std::string& desc) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mDescription = desc; }
inline void setUrl(const std::string& url) { std::unique_lock<std::shared_mutex> _lock(mSharedMutex); mUrl = url; }
protected:
Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _loadAllFromDB(Poco::Data::Session session);
Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName);
Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session);
Poco::Data::Statement _insertIntoDB(Poco::Data::Session session);
std::string mAlias;
std::string mName;
std::string mUrl;
std::string mDescription;
mutable std::shared_mutex mSharedMutex;
};
}

View File

@ -137,6 +137,13 @@ namespace model {
throw Poco::Exception(message);
}
Poco::Data::Statement ModelBase::_loadAllFromDB(Poco::Data::Session session)
{
std::string message = getTableName();
message += "::_loadAllFromDB not implemented";
throw Poco::Exception(message);
}
Poco::DateTime ModelBase::parseElopageDate(std::string dateString)
{
std::string decodedDateString = "";

View File

@ -42,6 +42,8 @@ namespace model {
bool isExistInDB(const std::string& fieldName, const T& fieldValue);
template<class WhereFieldType, class Tuple>
std::vector<Tuple> loadFromDB(const std::string& fieldName, const WhereFieldType& fieldValue, int expectedResults = 0);
template<class Tuple>
std::vector<Tuple> loadAllFromDB();
template<class T1, class T2>
size_t loadFromDB(const std::vector<std::string>& fieldNames, const T1& field1Value, const T2& field2Value, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
template<class WhereFieldType, class Tuple>
@ -62,6 +64,7 @@ namespace model {
virtual Poco::Data::Statement _loadIdFromDB(Poco::Data::Session session) = 0;
virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::string& fieldName) = 0;
virtual Poco::Data::Statement _loadFromDB(Poco::Data::Session session, const std::vector<std::string>& fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
virtual Poco::Data::Statement _loadAllFromDB(Poco::Data::Session session);
virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::string& fieldName);
virtual Poco::Data::Statement _loadMultipleFromDB(Poco::Data::Session session, const std::vector<std::string> fieldNames, MysqlConditionType conditionType = MYSQL_CONDITION_AND);
virtual Poco::Data::Statement _insertIntoDB(Poco::Data::Session session) = 0;
@ -145,6 +148,29 @@ namespace model {
return results;
}
template<class Tuple>
std::vector<Tuple> loadAllFromDB()
{
std::vector<Tuple> results;
Poco::ScopedLock<Poco::Mutex> _lock(mWorkMutex);
auto cm = ConnectionManager::getInstance();
Poco::Data::Statement select = _loadAllFromDB(cm->getConnection(CONNECTION_MYSQL_LOGIN_SERVER));
select, Poco::Data::Keywords::into(results);
size_t resultCount = 0;
try {
resultCount = select.execute();
}
catch (Poco::Exception& ex) {
lock();
addError(new ParamError(getTableName(), "mysql error by selecting all", ex.displayText().data()));
unlock();
}
return results;
}
template<class WhereFieldType, class Tuple>
std::vector<Tuple> ModelBase::loadFromDB(const std::vector<std::string>& fieldNames, const std::vector<WhereFieldType>& fieldValues, MysqlConditionType conditionType/* = MYSQL_CONDITION_AND*/, int expectedResults/* = 0*/)
{

80
src/cpsp/adminGroups.cpsp Normal file
View File

@ -0,0 +1,80 @@
<%@ page class="AdminGroupsPage" %>
<%@ page form="true" %>
<%@ page compressed="true" %>
<%@ page baseClass="SessionHTTPRequestHandler" %>
<%@ page ctorArg="Session*" %>
<%@ header include="SessionHTTPRequestHandler.h" %>
<%!
#include "../controller/Group.h"
%>
<%%
const char* pageName = "Gruppen";
// add
if(!form.empty()) {
auto alias = form.get("group-alias");
if(alias == "")
{
addError(new Error("Add Group", "Alias is empty!"));
}
else
{
auto newGroup = controller::Group::create(
alias,
form.get("group-name", ""),
form.get("group-url", ""),
form.get("group-desc", "")
);
newGroup->getModel()->insertIntoDB(false);
}
}
// select all
auto groups = controller::Group::listAll();
//auto groups = controller::Group::load("gdd1");
//std::vector<Poco::SharedPtr<controller::Group>> groups;
%><%@ include file="header.cpsp" %>
<%= getErrorsHtml() %>
<div class="center-form-container">
<div class="content-list">
<div class="content-list-title">
<h2>Alle Gruppen</h2>
</div>
<div class="content-list-table">
<div class="row">
<div class="cell header-cell">ID</div>
<div class="cell header-cell">Name</div>
<div class="cell header-cell">Alias</div>
<div class="cell header-cell">Url</div>
<div class="cell header-cell"><%= gettext("Description") %></div>
</div>
<% for(auto it = groups.begin(); it != groups.end(); it++) {
auto group_model = (*it)->getModel(); %>
<div class="row">
<div class="cell"><%= group_model->getID() %></div>
<div class="cell"><%= group_model->getName() %></div>
<div class="cell"><%= group_model->getAlias() %></div>
<div class="cell"><%= group_model->getUrl() %></div>
<div class="celL"><%= group_model->getDescription()%></div>
</div>
<% } %>
</div>
</div>
<div class="center-form-title">
<h3>Eine neue Gruppe anlegen</h3>
</div>
<div class="center-form-form">
<form method="POST">
<label class="form-label" for="group-name">Name</label>
<input class="form-control" id="group-name" type="text" name="group-name"/>
<label class="form-label" for="group-alias">Alias</label>
<input class="form-control" id="group-alias" type="text" name="group-alias"/>
<label class="form-label" for="group-url">Url</label>
<input class="form-control" id="group-url" type="text" name="group-url"/>
<label class="form-label" for="group-desc"><%= gettext("Description")%></label>
<textarea class="form-control" name="group-desc" rows="3" maxlength="150" id="group-desc"></textarea>
<input class="center-form-submit form-button" type="submit" name="submit" value="<%= gettext("Add Group") %>">
</form>
</div>
<%@ include file="footer.cpsp" %>