From be2b2416293dabbe702414766eec607a2a250d95 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 10 Oct 2017 12:20:48 -0700 Subject: [PATCH] Lots of progress; don't yet have some things --- .../InspectionCertificate.qml | 77 ++++++++++++++----- .../hifi/commerce/purchases/PurchasedItem.qml | 5 +- .../qml/hifi/commerce/purchases/Purchases.qml | 3 +- interface/src/commerce/Ledger.cpp | 20 +++-- interface/src/commerce/Ledger.h | 7 +- interface/src/commerce/QmlCommerce.cpp | 6 ++ interface/src/commerce/QmlCommerce.h | 3 + scripts/system/marketplaces/marketplaces.js | 20 ++--- 8 files changed, 93 insertions(+), 48 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml index 19728daa82..2a20f7fa9b 100644 --- a/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml +++ b/interface/resources/qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml @@ -25,7 +25,8 @@ Rectangle { HifiConstants { id: hifi; } id: root; - property string marketplaceId: ""; + property string marketplaceUrl; + property string certificateId; property string itemName: "--"; property string itemOwner: "--"; property string itemEdition: "--"; @@ -35,6 +36,26 @@ Rectangle { color: hifi.colors.faintGray; Hifi.QmlCommerce { id: commerce; + + onCertificateInfoResult: { + if (result.status !== 'success') { + console.log("Failed to get certificate info", result.message); + } else { + root.marketplaceUrl = result.data.marketplace_item_url; + root.itemOwner = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"; + root.itemEdition = result.data.edition_number + "/" + (result.data.limited_run === -1 ? "\u221e" : result.data.limited_run); + root.dateOfPurchase = getFormattedDate(result.data.transfer_created_at * 1000); + + if (result.data.invalid_reason) { + errorText.text = "Here we will display some text if there's an error with the certificate " + + "(DMCA takedown, invalid cert, location of item updated)"; + } + } + } + } + + onCertificateIdChanged: { + commerce.certificateInfo(certificateId); } // This object is always used in a popup. @@ -126,7 +147,7 @@ Rectangle { anchors.fill: parent; hoverEnabled: enabled; onClicked: { - sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplaceId}); + sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl}); } onEntered: itemName.color = hifi.colors.blueHighlight; onExited: itemName.color = hifi.colors.blueAccent; @@ -199,11 +220,10 @@ Rectangle { RalewayRegular { id: dateOfPurchaseHeader; text: "DATE OF PURCHASE"; - visible: root.dateOfPurchase !== ""; // Text size size: 16; // Anchors - anchors.top: ownedBy.bottom; + anchors.top: edition.bottom; anchors.topMargin: 20; anchors.left: parent.left; anchors.leftMargin: 45; @@ -216,14 +236,13 @@ Rectangle { AnonymousProRegular { id: dateOfPurchase; text: root.dateOfPurchase; - visible: root.dateOfPurchase !== ""; // Text size size: 22; // Anchors - anchors.top: editionHeader.bottom; + anchors.top: dateOfPurchaseHeader.bottom; anchors.topMargin: 4; - anchors.left: editionHeader.left; - anchors.right: editionHeader.right; + anchors.left: dateOfPurchaseHeader.left; + anchors.right: dateOfPurchaseHeader.right; height: paintedHeight; // Style color: hifi.colors.darkGray; @@ -231,15 +250,13 @@ Rectangle { RalewayRegular { id: errorText; - text: "Here we will display some text if there's an error with the certificate " + - "(DMCA takedown, invalid cert, location of item updated)"; // Text size size: 20; // Anchors - anchors.top: root.dateOfPurchase !== "" ? dateOfPurchase.bottom : edition.bottom; + anchors.top: dateOfPurchase.bottom; anchors.topMargin: 40; - anchors.left: root.dateOfPurchase !== "" ? dateOfPurchase.left : edition.left; - anchors.right: root.dateOfPurchase !== "" ? dateOfPurchase.right : edition.right; + anchors.left: dateOfPurchase.left; + anchors.right: dateOfPurchase.right; anchors.bottom: parent.bottom; // Style wrapMode: Text.WordWrap; @@ -290,7 +307,7 @@ Rectangle { height: 50; text: "View In Market" onClicked: { - sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', itemId: root.marketplaceId}); + sendToScript({method: 'inspectionCertificate_showInMarketplaceClicked', marketplaceUrl: root.marketplaceUrl}); } } } @@ -313,19 +330,37 @@ Rectangle { // function fromScript(message) { switch (message.method) { - case 'inspectionCertificate_setMarketplaceId': - root.marketplaceId = message.marketplaceId; - break; - case 'inspectionCertificate_setItemInfo': - root.itemName = message.itemName; - root.itemOwner = message.itemOwner; - root.itemEdition = message.itemEdition; + case 'inspectionCertificate_setCertificateId': + root.certificateId = message.certificateId; break; default: console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message)); } } signal sendToScript(var message); + + function getFormattedDate(timestamp) { + var a = new Date(timestamp); + var year = a.getFullYear(); + var month = a.getMonth(); + var day = a.getDate(); + var hour = a.getHours(); + var drawnHour = hour; + if (hour === 0) { + drawnHour = 12; + } else if (hour > 12) { + drawnHour -= 12; + } + + var amOrPm = "AM"; + if (hour >= 12) { + amOrPm = "PM"; + } + + var min = a.getMinutes(); + var sec = a.getSeconds(); + return year + '-' + month + '-' + day + ' ' + drawnHour + ':' + min + amOrPm; + } // // FUNCTION DEFINITIONS END // diff --git a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml index 5eb5516519..e7e16668fe 100644 --- a/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml +++ b/interface/resources/qml/hifi/commerce/purchases/PurchasedItem.qml @@ -34,6 +34,7 @@ Item { property string itemId; property string itemPreviewImageUrl; property string itemHref; + property string certificateId; property int displayedItemCount; property int itemEdition; property int numberSold; @@ -168,7 +169,7 @@ Item { anchors.fill: parent; hoverEnabled: enabled; onClicked: { - sendToPurchases({method: 'purchases_itemCertificateClicked', itemMarketplaceId: root.itemId}); + sendToPurchases({method: 'purchases_itemCertificateClicked', itemCertificateId: root.certificateId}); } onEntered: { certificateIcon.color = hifi.colors.black; @@ -225,7 +226,7 @@ Item { } else if (root.purchaseStatus === "invalidated") { "INVALIDATED" } else if (root.numberSold !== -1) { - ("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "INFTY" : root.limitedRun)) + ("Sales: " + root.numberSold + "/" + (root.limitedRun === -1 ? "\u221e" : root.limitedRun)) } else { "" } diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index ea32c139d4..54abe2d5fc 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -684,8 +684,7 @@ Rectangle { titleBarContainer.referrerURL = message.referrerURL; filterBar.text = message.filterText ? message.filterText : ""; break; - case 'inspectionCertificate_setMarketplaceId': - case 'inspectionCertificate_setItemInfo': + case 'inspectionCertificate_setCertificateId': inspectionCertificate.fromScript(message); break; case 'purchases_showMyItems': diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index a68a6fe929..9a6840c76a 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -13,7 +13,6 @@ #include #include #include -#include "AccountManager.h" #include "Wallet.h" #include "Ledger.h" #include "CommerceLogging.h" @@ -47,14 +46,15 @@ Handler(buy) Handler(receiveAt) Handler(balance) Handler(inventory) +Handler(certificateInfo) -void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request) { +void Ledger::send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request) { auto accountManager = DependencyManager::get(); const QString URL = "/api/v1/commerce/"; JSONCallbackParameters callbackParams(this, success, this, fail); qCInfo(commerce) << "Sending" << endpoint << QJsonDocument(request).toJson(QJsonDocument::Compact); accountManager->sendRequest(URL + endpoint, - AccountManagerAuth::Required, + authType, method, callbackParams, QJsonDocument(request).toJson()); @@ -70,14 +70,14 @@ void Ledger::signedSend(const QString& propertyName, const QByteArray& text, con } else { request["signature"] = QString("controlled failure!"); } - send(endpoint, success, fail, QNetworkAccessManager::PutOperation, request); + send(endpoint, success, fail, QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, request); } void Ledger::keysQuery(const QString& endpoint, const QString& success, const QString& fail) { auto wallet = DependencyManager::get(); QJsonObject request; request["public_keys"] = QJsonArray::fromStringList(wallet->listPublicKeys()); - send(endpoint, success, fail, QNetworkAccessManager::PostOperation, request); + send(endpoint, success, fail, QNetworkAccessManager::PostOperation, AccountManagerAuth::Required, request); } void Ledger::buy(const QString& hfc_key, int cost, const QString& asset_id, const QString& inventory_key, const bool controlled_failure) { @@ -192,7 +192,7 @@ void Ledger::history(const QStringList& keys) { void Ledger::resetSuccess(QNetworkReply& reply) { apiResponse("reset", reply); } void Ledger::resetFailure(QNetworkReply& reply) { failResponse("reset", reply); } void Ledger::reset() { - send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, QJsonObject()); + send("reset_user_hfc_account", "resetSuccess", "resetFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, QJsonObject()); } void Ledger::accountSuccess(QNetworkReply& reply) { @@ -217,7 +217,7 @@ void Ledger::accountFailure(QNetworkReply& reply) { failResponse("account", reply); } void Ledger::account() { - send("hfc_account", "accountSuccess", "accountFailure", QNetworkAccessManager::PutOperation, QJsonObject()); + send("hfc_account", "accountSuccess", "accountFailure", QNetworkAccessManager::PutOperation, AccountManagerAuth::Required, QJsonObject()); } // The api/failResponse is called just for the side effect of logging. @@ -234,3 +234,9 @@ void Ledger::updateLocation(const QString& asset_id, const QString location, con auto transactionString = transactionDoc.toJson(QJsonDocument::Compact); signedSend("transaction", transactionString, key, "location", "updateLocationSuccess", "updateLocationFailure", controlledFailure); } + +void Ledger::certificateInfo(const QString& certificateId) { + QString endpoint = "proof_of_purchase_status/transfer/" + certificateId; + QJsonObject request; + send(endpoint, "certificateInfoSuccess", "certificateInfoFailure", QNetworkAccessManager::GetOperation, AccountManagerAuth::None, request); +} diff --git a/interface/src/commerce/Ledger.h b/interface/src/commerce/Ledger.h index da6c67224f..ae001010f0 100644 --- a/interface/src/commerce/Ledger.h +++ b/interface/src/commerce/Ledger.h @@ -17,6 +17,7 @@ #include #include #include +#include "AccountManager.h" class Ledger : public QObject, public Dependency { @@ -32,6 +33,7 @@ public: void account(); void reset(); void updateLocation(const QString& asset_id, const QString location, const bool controlledFailure = false); + void certificateInfo(const QString& certificateId); signals: void buyResult(QJsonObject result); @@ -41,6 +43,7 @@ signals: void historyResult(QJsonObject result); void accountResult(QJsonObject result); void locationUpdateResult(QJsonObject result); + void certificateInfoResult(QJsonObject result); public slots: void buySuccess(QNetworkReply& reply); @@ -59,11 +62,13 @@ public slots: void accountFailure(QNetworkReply& reply); void updateLocationSuccess(QNetworkReply& reply); void updateLocationFailure(QNetworkReply& reply); + void certificateInfoSuccess(QNetworkReply& reply); + void certificateInfoFailure(QNetworkReply& reply); private: QJsonObject apiResponse(const QString& label, QNetworkReply& reply); QJsonObject failResponse(const QString& label, QNetworkReply& reply); - void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, QJsonObject request); + void send(const QString& endpoint, const QString& success, const QString& fail, QNetworkAccessManager::Operation method, AccountManagerAuth::Type authType, QJsonObject request); void keysQuery(const QString& endpoint, const QString& success, const QString& fail); void signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure = false); }; diff --git a/interface/src/commerce/QmlCommerce.cpp b/interface/src/commerce/QmlCommerce.cpp index ee75bc59e3..803264fa9f 100644 --- a/interface/src/commerce/QmlCommerce.cpp +++ b/interface/src/commerce/QmlCommerce.cpp @@ -29,6 +29,7 @@ QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) { connect(wallet.data(), &Wallet::keyFilePathIfExistsResult, this, &QmlCommerce::keyFilePathIfExistsResult); connect(ledger.data(), &Ledger::accountResult, this, &QmlCommerce::accountResult); connect(wallet.data(), &Wallet::walletStatusResult, this, &QmlCommerce::walletStatusResult); + connect(ledger.data(), &Ledger::certificateInfoResult, this, &QmlCommerce::certificateInfoResult); } void QmlCommerce::getWalletStatus() { @@ -125,3 +126,8 @@ void QmlCommerce::account() { auto ledger = DependencyManager::get(); ledger->account(); } + +void QmlCommerce::certificateInfo(const QString& certificateId) { + auto ledger = DependencyManager::get(); + ledger->certificateInfo(certificateId); +} diff --git a/interface/src/commerce/QmlCommerce.h b/interface/src/commerce/QmlCommerce.h index 45a5360680..ae63133425 100644 --- a/interface/src/commerce/QmlCommerce.h +++ b/interface/src/commerce/QmlCommerce.h @@ -43,6 +43,7 @@ signals: void inventoryResult(QJsonObject result); void historyResult(QJsonObject result); void accountResult(QJsonObject result); + void certificateInfoResult(QJsonObject result); protected: Q_INVOKABLE void getWalletStatus(); @@ -63,6 +64,8 @@ protected: Q_INVOKABLE void generateKeyPair(); Q_INVOKABLE void reset(); Q_INVOKABLE void account(); + + Q_INVOKABLE void certificateInfo(const QString& certificateId); }; #endif // hifi_QmlCommerce_h diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index bf9822ba19..6880d10c18 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -134,22 +134,12 @@ tablet.pushOntoStack(MARKETPLACE_WALLET_QML_PATH); } - function setCertificateInfo(currentEntityWithContextOverlay, itemMarketplaceId) { + function setCertificateInfo(currentEntityWithContextOverlay, itemCertificateId) { wireEventBridge(true); tablet.sendToQml({ - method: 'inspectionCertificate_setMarketplaceId', - marketplaceId: itemMarketplaceId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['marketplaceID']).marketplaceID + method: 'inspectionCertificate_setCertificateId', + certificateId: itemCertificateId || Entities.getEntityProperties(currentEntityWithContextOverlay, ['certificateID']).certificateID }); - // ZRF FIXME! Make a call to the endpoint to get item info instead of this silliness - Script.setTimeout(function () { - var randomNumber = Math.floor((Math.random() * 150) + 1); - tablet.sendToQml({ - method: 'inspectionCertificate_setItemInfo', - itemName: "The Greatest Item", - itemOwner: "ABCDEFG1234567", - itemEdition: (Math.floor(Math.random() * randomNumber) + " / " + randomNumber) - }); - }, 500); } function onUsernameChanged() { @@ -358,13 +348,13 @@ tablet.loadQMLSource("TabletAddressDialog.qml"); break; case 'purchases_itemCertificateClicked': - setCertificateInfo("", message.itemMarketplaceId); + setCertificateInfo("", message.itemCertificateId); break; case 'inspectionCertificate_closeClicked': tablet.gotoHomeScreen(); break; case 'inspectionCertificate_showInMarketplaceClicked': - tablet.gotoWebScreen(MARKETPLACE_URL + '/items/' + message.itemId, MARKETPLACES_INJECT_SCRIPT_URL); + tablet.gotoWebScreen(message.marketplaceUrl, MARKETPLACES_INJECT_SCRIPT_URL); break; case 'header_myItemsClicked': referrerURL = MARKETPLACE_URL_INITIAL;