diff --git a/UIs/BeetRoundWidgets/dialogs/edititemdialog.cpp b/UIs/BeetRoundWidgets/dialogs/edititemdialog.cpp index 488919b..1565f5f 100644 --- a/UIs/BeetRoundWidgets/dialogs/edititemdialog.cpp +++ b/UIs/BeetRoundWidgets/dialogs/edititemdialog.cpp @@ -26,6 +26,10 @@ void EditItemDialog::createContent() { innerLayout->addWidget(m_detailMapper); m_outerLayout->insertWidget(0, m_contentContainer); + + /// online user stuff + connect(m_detailMapper, &ItemDetailMapper::createOnlineAccountTriggered, this, + &EditItemDialog::createOnlineAccountTriggered); } void EditItemDialog::accept() { diff --git a/UIs/BeetRoundWidgets/dialogs/edititemdialog.h b/UIs/BeetRoundWidgets/dialogs/edititemdialog.h index 67bf01e..ad28bfb 100644 --- a/UIs/BeetRoundWidgets/dialogs/edititemdialog.h +++ b/UIs/BeetRoundWidgets/dialogs/edititemdialog.h @@ -19,6 +19,8 @@ class EditItemDialog : public AbstractDialog { /// AbstractDialog interface void createContent() override; + signals: + void createOnlineAccountTriggered(const QString& mailAddress); public slots: void accept() override; void reject() override; diff --git a/UIs/BeetRoundWidgets/mainwindow.cpp b/UIs/BeetRoundWidgets/mainwindow.cpp index a042a03..ba3c9cb 100644 --- a/UIs/BeetRoundWidgets/mainwindow.cpp +++ b/UIs/BeetRoundWidgets/mainwindow.cpp @@ -16,7 +16,6 @@ #include "genericcore.h" #include "model/generalsortfiltermodel.h" #include "model/metadata.h" -#include "model/modelsummary.h" #include "model/tablemodel.h" #include "widgets/biddingroundcontrol.h" #include "widgets/comboboxdelegate.h" @@ -75,6 +74,10 @@ MainWindow::MainWindow(QWidget* parent) onCurrentChanged(QModelIndex(), QModelIndex()); setupEventTab(); + + // #ifndef QT_DEBUG + initServerConnection(); + // #endif } MainWindow::~MainWindow() { delete ui; } @@ -563,3 +566,8 @@ void MainWindow::setupEventTab() { ui->tabWidget->insertTab(0, containerWidget, "Event (&1)"); } + +void MainWindow::initServerConnection() { + connect(m_editItemDialog.get(), &EditItemDialog::createOnlineAccountTriggered, m_core.get(), + &GenericCore::onCreateOnlineAccountTriggered); +} diff --git a/UIs/BeetRoundWidgets/mainwindow.h b/UIs/BeetRoundWidgets/mainwindow.h index 2d081a7..f89c15f 100644 --- a/UIs/BeetRoundWidgets/mainwindow.h +++ b/UIs/BeetRoundWidgets/mainwindow.h @@ -120,5 +120,7 @@ class MainWindow : public QMainWindow { void createGuiDialogs(); void setupEventTab(); + + void initServerConnection(); }; #endif // MAINWINDOW_H diff --git a/UIs/BeetRoundWidgets/views/itemdetailmapper.cpp b/UIs/BeetRoundWidgets/views/itemdetailmapper.cpp index 11a7e95..6f7f3f1 100644 --- a/UIs/BeetRoundWidgets/views/itemdetailmapper.cpp +++ b/UIs/BeetRoundWidgets/views/itemdetailmapper.cpp @@ -156,6 +156,15 @@ ItemDetailMapper::ItemDetailMapper(QWidget* parent) outerLayout->addLayout(leftLayout); outerLayout->addLayout(rightLayout); setLayout(outerLayout); + + /// online user account + connect(m_mailEdit, &QLineEdit::textChanged, this, &ItemDetailMapper::onMailEditChanged); + connect(m_onlineIdDisplay, &QLineEdit::textChanged, this, &ItemDetailMapper::onOnlineIDChanged); + connect(m_accessCodeDisplay, &QLineEdit::textChanged, this, + &ItemDetailMapper::onAccessCodeChanged); + + connect(m_createOnlineAccountButton, &QAbstractButton::clicked, this, + &ItemDetailMapper::onCreateOnlineAccountTriggered); } void ItemDetailMapper::setModelMappings(QTableView* tableView) { @@ -265,3 +274,40 @@ void ItemDetailMapper::updateQRCode(const QString text) { m_qrCodeDisplay->setPixmap(QPixmap::fromImage(image)); m_qrCodeDisplay->setToolTip(text); } + +void ItemDetailMapper::onMailEditChanged(const QString& text) { + if (text.isEmpty()) { + m_createOnlineAccountButton->setEnabled(false); + m_sendInviteMailButton->setEnabled(false); + } else { + onOnlineIDChanged(m_onlineIdDisplay->text()); + onAccessCodeChanged(m_accessCodeDisplay->text()); + } +} + +void ItemDetailMapper::onOnlineIDChanged(const QString& text) { + if (text.isEmpty()) { + m_createOnlineAccountButton->setEnabled(true); + m_sendInviteMailButton->setEnabled(false); + } else { + m_createOnlineAccountButton->setEnabled(false); + m_sendInviteMailButton->setEnabled(true); + } +} + +void ItemDetailMapper::onAccessCodeChanged(const QString& text) { + if (text.isEmpty()) { + m_sendInviteMailButton->setEnabled(false); + m_accessUrlDisplay->setText(""); + updateQRCode(""); + } else { + m_sendInviteMailButton->setEnabled(true); + const QString accessUrl = "http://127.0.0.1:4000/api/users/" + text; + m_accessUrlDisplay->setText(accessUrl); + updateQRCode(accessUrl); + } +} + +void ItemDetailMapper::onCreateOnlineAccountTriggered() { + emit createOnlineAccountTriggered(m_mailEdit->text()); +} diff --git a/UIs/BeetRoundWidgets/views/itemdetailmapper.h b/UIs/BeetRoundWidgets/views/itemdetailmapper.h index 5443690..9aa802e 100644 --- a/UIs/BeetRoundWidgets/views/itemdetailmapper.h +++ b/UIs/BeetRoundWidgets/views/itemdetailmapper.h @@ -30,6 +30,8 @@ class ItemDetailMapper : public QWidget { signals: void contentChanged(const QString text); + void createOnlineAccountTriggered(const QString& mailAddress); + private slots: void rowsInserted(const QModelIndex& parent, int start, int end); void rowsRemoved(const QModelIndex& parent, int start, int end); @@ -38,7 +40,12 @@ class ItemDetailMapper : public QWidget { void updateButtons(int row); void emitContentChanged(const QModelIndex& currentIndex); void onCurrentIndexChanged(const QModelIndex& current, const QModelIndex& previous); + void updateQRCode(const QString text = ""); + void onMailEditChanged(const QString& text); + void onOnlineIDChanged(const QString& text); + void onAccessCodeChanged(const QString& text); + void onCreateOnlineAccountTriggered(); private: /// *** members *** diff --git a/libs/BeetRoundCore/genericcore.cpp b/libs/BeetRoundCore/genericcore.cpp index 015705a..e4ef5b1 100644 --- a/libs/BeetRoundCore/genericcore.cpp +++ b/libs/BeetRoundCore/genericcore.cpp @@ -160,6 +160,17 @@ void GenericCore::onBiddingsChanged(int round, QList biddings) { // NEXT merge biddings into model } +void GenericCore::onCreateOnlineAccountTriggered(const QString& mailAddress) { + qInfo() << "Creating online account for:" << mailAddress; + // QJsonDocument onlineCredentialsDoc = m_mainModel->getOnlineCredentialsAsJsonDoc(mailAddress); + // emit createOnlineUser(onlineCredentialsDoc.toJson()); + emit sendPostRequest(RegisterUser, mailAddress); +} + +// void GenericCore::onOnlineUserCreatedReceived(const QJsonDocument& jsonDoc) {} + +// void GenericCore::onOnlineUserExistedReceived(const QJsonDocument jsonDoc) {} + void GenericCore::setupModels() { m_mainModel = make_shared(m_modelUndoStack); m_sortFilterModel = make_shared(m_mainModel); diff --git a/libs/BeetRoundCore/genericcore.h b/libs/BeetRoundCore/genericcore.h index 8751648..b87be80 100644 --- a/libs/BeetRoundCore/genericcore.h +++ b/libs/BeetRoundCore/genericcore.h @@ -49,12 +49,17 @@ class GenericCore : public QObject { public slots: void onBiddingsChanged(int round, QList biddings); + void onCreateOnlineAccountTriggered(const QString& mailAddress); + // void onOnlineUserCreatedReceived(const QJsonDocument& jsonDoc); + // void onOnlineUserExistedReceived(const QJsonDocument jsonDoc); + signals: void displayStatusMessage(QString message); /// *** server communication *** /// request signals void sendGetRequest(GetRequestTypes type, QVariant data = QVariant()); + void sendPostRequest(PostRequestTypes type, QVariant data = QVariant()); /// response signals void currentBiddingRoundChanged(int round, bool isRunning); diff --git a/libs/BeetRoundCore/model/metadata.h b/libs/BeetRoundCore/model/metadata.h index dbbe9c0..83ffdb9 100644 --- a/libs/BeetRoundCore/model/metadata.h +++ b/libs/BeetRoundCore/model/metadata.h @@ -91,6 +91,7 @@ enum GetRequestTypes { GetBiddingsOfSpecificRound, GetBiddingsOfHighestRound }; +enum PostRequestTypes { RegisterUser }; /// functions static UserRoles GET_ROLE_FOR_COLUMN(const int column) { diff --git a/libs/BeetRoundCore/network/apiroutes.h b/libs/BeetRoundCore/network/apiroutes.h index 5422772..a89c9f5 100644 --- a/libs/BeetRoundCore/network/apiroutes.h +++ b/libs/BeetRoundCore/network/apiroutes.h @@ -9,6 +9,8 @@ static const QString apiPrefix = "/api/"; static const QString ROUTE_ITEMS = apiPrefix + "items"; +static const QString ROUTE_REGISTER_USER = apiPrefix + "users"; + static const QString ROUTE_BIDDINGROUNDS = apiPrefix + "bidding_rounds"; static const QString ROUTE_CURRENT_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/get_current"; static const QString ROUTE_START_BIDDINGROUND = ROUTE_BIDDINGROUNDS + "/start_new"; diff --git a/libs/BeetRoundCore/network/servercommunicator.cpp b/libs/BeetRoundCore/network/servercommunicator.cpp index 0c42fb6..f3db0f5 100644 --- a/libs/BeetRoundCore/network/servercommunicator.cpp +++ b/libs/BeetRoundCore/network/servercommunicator.cpp @@ -20,6 +20,8 @@ ServerCommunicator::ServerCommunicator(GenericCore* core) connect(m_core, &GenericCore::sendGetRequest, this, &ServerCommunicator::onSendGetRequestTriggered); + connect(m_core, &GenericCore::sendPostRequest, this, + &ServerCommunicator::onSendPostRequestTriggered); connect(this, &ServerCommunicator::biddingsChanged, m_core, &GenericCore::onBiddingsChanged); } @@ -44,66 +46,6 @@ void ServerCommunicator::setUrl(const QUrl& url) { emit urlChanged(); } -void ServerCommunicator::fetchItems() { - /// Set up a GET request - m_restManager->get(m_serviceApi->createRequest(ROUTE_ITEMS), this, [this](QRestReply& reply) { - if (reply.isSuccess()) { - qInfo() << "Fetching items successful."; - const QJsonDocument doc = reply.readJson().value(); - emit itemsFetched(doc.toJson()); - - } else { - if (reply.hasError()) { - const QString errorString = reply.errorString(); - qCritical() << "ERROR:" << errorString; - emit itemsFetchFailure(errorString); - } else { - int statusCode = reply.httpStatus(); - qCritical() << "ERROR:" << statusCode; - emit itemsFetchFailure(QString::number(statusCode)); - emit itemsFetchFailure(QString("HTTP status code: %1").arg(statusCode)); - } - } - }); -} - -void ServerCommunicator::postItems(const QByteArray& jsonData) { - QNetworkReply* reply = m_restManager->post(m_serviceApi->createRequest(ROUTE_ITEMS), jsonData); - - QObject::connect(reply, &QNetworkReply::finished, [=]() { - if (reply->error() == QNetworkReply::NoError) { - QByteArray responseData = reply->readAll(); - const QString message = QString("POST successful! Response: %1").arg(responseData); - qInfo() << message; - emit postRequestSuccessful(responseData); - } else { - const QString message = QString("Error: %1").arg(reply->errorString()); - qDebug() << message; - emit postRequestFailure(message); - } - reply->deleteLater(); - }); -} - -void ServerCommunicator::deleteItem(const QString& id) { - const QString deleteRoute = QString("%1/%2").arg(ROUTE_ITEMS, id); - QNetworkReply* reply = m_restManager->deleteResource(m_serviceApi->createRequest(deleteRoute)); - - QObject::connect(reply, &QNetworkReply::finished, [=]() { - if (reply->error() == QNetworkReply::NoError) { - QByteArray responseData = reply->readAll(); - const QString message = QString("DELETE successful! Response: %1").arg(responseData); - qInfo() << message; - emit deleteRequestSuccessful(responseData); - } else { - const QString message = QString("Error: %1").arg(reply->errorString()); - qDebug() << message; - emit deleteRequestFailure(message); - } - reply->deleteLater(); - }); -} - void ServerCommunicator::setServerConfiguration(const QString url, const QString email, const QString password) { @@ -191,6 +133,75 @@ void ServerCommunicator::onGetReplyFailure(const GetRequestTypes type, const QSt m_core->displayStatusMessage(message); } +void ServerCommunicator::onSendPostRequestTriggered(const PostRequestTypes type, QVariant data) { + QString path; + switch (type) { + case RegisterUser: + path = ROUTE_REGISTER_USER; + break; + default: + qWarning() << "No route found for PostRequestType:" << type; + break; + } + + // TODO move into default case of switch statement? + if (path.isEmpty()) { + qDebug() << "Empty path -> Not sending a request."; + return; + } + + const QNetworkRequest request = m_serviceApi->createRequest(path); + + QJsonDocument doc = QJsonDocument(); + QJsonObject rootObject; + + QJsonObject itemObject; + itemObject.insert("email", data.toString()); + rootObject.insert("user", itemObject); + + doc.setObject(rootObject); + + m_restManager->post(request, doc, this, [this, type](QRestReply& reply) { + if (reply.isSuccess()) { + int statusCode = reply.httpStatus(); + qInfo() << "Request successful. Status code:" << statusCode; + const QJsonDocument doc = reply.readJson().value(); + onPostReplySuccessful(type, doc); + } else { + if (reply.hasError()) { + const QString errorString = reply.errorString(); + qWarning() << "Network error:" << errorString; + onPostReplyFailure(type, errorString); + } else { + int statusCode = reply.httpStatus(); + qWarning() << "Request not successful:" << statusCode; + qCritical() << "Content:" << reply.readJson(); + onPostReplyFailure(type, QString("HTTP status code: %1").arg(statusCode)); + } + } + }); +} + +void ServerCommunicator::onPostReplySuccessful(const PostRequestTypes type, + const QJsonDocument doc) { + switch (type) { + case RegisterUser: + qInfo() << "Register user successful:" << type; + m_core->displayStatusMessage(doc.toJson()); + break; + default: + qWarning() << "Can't match request type:" << type; + break; + } +} + +void ServerCommunicator::onPostReplyFailure(const PostRequestTypes type, + const QString errorString) { + const QString message = + QString("Request of type %1 returned: %2").arg(QString::number(type), errorString); + m_core->displayStatusMessage(message); +} + void ServerCommunicator::currentBiddingRoundChangedReply(const QJsonDocument jsonDoc) { qInfo() << "Current bidding round received."; const QJsonObject rootObject = jsonDoc["data"].toObject(); diff --git a/libs/BeetRoundCore/network/servercommunicator.h b/libs/BeetRoundCore/network/servercommunicator.h index 0f6b3df..f69275d 100644 --- a/libs/BeetRoundCore/network/servercommunicator.h +++ b/libs/BeetRoundCore/network/servercommunicator.h @@ -29,9 +29,9 @@ class ServerCommunicator : public QObject { void onGetReplySuccessful(const GetRequestTypes type, const QJsonDocument doc); void onGetReplyFailure(const GetRequestTypes type, const QString errorString); - void fetchItems(); - void postItems(const QByteArray& jsonData); - void deleteItem(const QString& id); + void onSendPostRequestTriggered(const PostRequestTypes type, QVariant data); + void onPostReplySuccessful(const PostRequestTypes type, const QJsonDocument doc); + void onPostReplyFailure(const PostRequestTypes type, const QString errorString); signals: void urlChanged();