diff --git a/CHANGELOG.md b/CHANGELOG.md index 6277c7425..13a3dc8a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable, unreleased changes to this project will be documented in this file. - Move fragments to separate directory to avoid circular imports - #592 by @dominik-zeglen - Add order invoices management - #570 by @orzechdev - Add Cypress e2e runner - #584 by @krzysztofwolski +- create Apps - #599 by @AlicjaSzu ## 2.10.1 diff --git a/assets/images/activate-icon.svg b/assets/images/activate-icon.svg new file mode 100644 index 000000000..8ac7d076a --- /dev/null +++ b/assets/images/activate-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/app-install-error.svg b/assets/images/app-install-error.svg new file mode 100644 index 000000000..44d68cafe --- /dev/null +++ b/assets/images/app-install-error.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/error-icon.svg b/assets/images/error-icon.svg index 0918ec675..5f42eef60 100644 --- a/assets/images/error-icon.svg +++ b/assets/images/error-icon.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/assets/images/menu-apps-icon.svg b/assets/images/menu-apps-icon.svg new file mode 100644 index 000000000..3033691d1 --- /dev/null +++ b/assets/images/menu-apps-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/plus-icon.svg b/assets/images/plus-icon.svg new file mode 100644 index 000000000..8a0ed5ebd --- /dev/null +++ b/assets/images/plus-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/settings-icon.svg b/assets/images/settings-icon.svg new file mode 100644 index 000000000..452240eb0 --- /dev/null +++ b/assets/images/settings-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/support-icon.svg b/assets/images/support-icon.svg new file mode 100644 index 000000000..71b29d507 --- /dev/null +++ b/assets/images/support-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index a03c34aa4..2a20074d3 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -298,6 +298,357 @@ "context": "button", "string": "Accept" }, + "src_dot_apps": { + "context": "apps section name", + "string": "Apps" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_1499521723": { + "context": "dialog header", + "string": "Activate App" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3356885734": { + "context": "activate app", + "string": "Are you sure you want to activate {name}? Activating will start gathering events." + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3761045983": { + "context": "activate app", + "string": "Are you sure you want to activate this app? Activating will start gathering events" + }, + "src_dot_apps_dot_components_dot_AppActivateDialog_dot_3865193889": { + "context": "button label", + "string": "Activate" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_1782042241": { + "context": "button label", + "string": "Deactivate" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_2031792590": { + "context": "dialog header", + "string": "Dectivate App" + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_2955925498": { + "context": "deactivate app", + "string": "Are you sure you want to disable this app? Your data will be kept until you reactivate the app. You will be still billed for the app." + }, + "src_dot_apps_dot_components_dot_AppDeactivateDialog_dot_329373780": { + "context": "deactivate app", + "string": "Are you sure you want to disable {name}? Your data will be kept until you reactivate the app. You will be still billed for the app." + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_1347203024": { + "context": "delete custom app", + "string": "Deleting {name}, you will delete all the data and webhooks regarding this app. Are you sure you want to do that?" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_1462011531": { + "context": "dialog header", + "string": "Delete App" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_330001535": { + "context": "delete app", + "string": "Are you sure you want to delete this app?" + }, + "src_dot_apps_dot_components_dot_AppDeleteDialog_dot_3817179919": { + "context": "delete app", + "string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_1782042241": { + "context": "link", + "string": "Deactivate" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_2432433023": { + "context": "app privacy policy link", + "string": "View this app’s privacy policy" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_2973480575": { + "context": "link", + "string": "Edit settings" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3744068622": { + "context": "section header", + "string": "Data privacy" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3768793197": { + "context": "link", + "string": "Get Support" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3817397882": { + "context": "button", + "string": "Open App" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3865193889": { + "context": "link", + "string": "Activate" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_3916538164": { + "context": "section header", + "string": "App permissions" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_846582072": { + "context": "apps about permissions", + "string": "This app has permissions to:" + }, + "src_dot_apps_dot_components_dot_AppDetailsPage_dot_85811128": { + "context": "section header", + "string": "About this app" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_198187074": { + "context": "button", + "string": "Support/FAQ" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_3302125406": { + "context": "button", + "string": "My App" + }, + "src_dot_apps_dot_components_dot_AppDetailsSettingsPage_dot_3662390044": { + "context": "button", + "string": "Dashboard" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_1462011531": { + "context": "dialog header", + "string": "Delete App" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_330001535": { + "context": "delete app", + "string": "Are you sure you want to delete this app?" + }, + "src_dot_apps_dot_components_dot_AppInProgressDeleteDialog_dot_3817179919": { + "context": "delete app", + "string": "Deleting {name}, you will remove installation of the app. If you are paying for app subscription, remember to unsubscribe from the app in Saleor Marketplace. Are you sure you want to delete the app?" + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_1152717819": { + "context": "title", + "string": "There’s a problem with app." + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_1261716527": { + "context": "content", + "string": "Saleor couldn’t fetch crucial information regarding installation. Without those System can’t install the app in your Saleor. Please use the button below to get back to system’s dashboard." + }, + "src_dot_apps_dot_components_dot_AppInstallErrorPage_dot_3375237564": { + "context": "button", + "string": "Back to homepage" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_127674832": { + "context": "app data privacy link", + "string": "Learn more about data privacy" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_2538706256": { + "context": "install button", + "string": "Install App" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_2936990163": { + "context": "install app permissions", + "string": "Installing this app will give it following permissions:" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3436300370": { + "context": "install app privacy", + "string": "Uninstalling the app will remove all your customer’s personal data stored by {name}. " + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3688014441": { + "context": "section header", + "string": "You are about to install {name}" + }, + "src_dot_apps_dot_components_dot_AppInstallPage_dot_3916538164": { + "context": "section header", + "string": "App permissions" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_1675189051": { + "context": "section header", + "string": "Ongoing Installations" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_2398081356": { + "context": "retry installation", + "string": "Retry" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_2868351060": { + "context": "app installation error", + "string": "There was a problem during installation" + }, + "src_dot_apps_dot_components_dot_AppsInProgress_dot_3733091754": { + "context": "app installation", + "string": "Installing app..." + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_1414896555": { + "context": "checkbox label", + "string": "Grant this app full access to the store" + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_3076071936": { + "context": "card description", + "string": "Expand or restrict app permissions to access certain part of Saleor system." + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_3189779214": { + "context": "header", + "string": "Create New App" + }, + "src_dot_apps_dot_components_dot_CustomAppCreatePage_dot_570656367": { + "context": "checkbox label", + "string": "App is active" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_1336855942": { + "string": "Generated Token" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_2080322626": { + "string": "This token gives you access to your shop's API, which you'll find here: {url}" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_2864204643": { + "context": "button", + "string": "Copied" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_3406541221": { + "context": "button", + "string": "Copy token" + }, + "src_dot_apps_dot_components_dot_CustomAppDefaultToken_dot_4189999598": { + "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_1414896555": { + "context": "checkbox label", + "string": "Grant this app full access to the store" + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_3076071936": { + "context": "card description", + "string": "Expand or restrict app permissions to access certain part of Saleor system." + }, + "src_dot_apps_dot_components_dot_CustomAppDetailsPage_dot_570656367": { + "context": "checkbox label", + "string": "App is active" + }, + "src_dot_apps_dot_components_dot_CustomAppInformation_dot_2860466085": { + "context": "header", + "string": "App Information" + }, + "src_dot_apps_dot_components_dot_CustomAppInformation_dot_3001692357": { + "context": "custom app name", + "string": "App Name" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_2446088470": { + "context": "custom app token key", + "string": "Key" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_2639089057": { + "string": "No tokens found" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_3209034045": { + "context": "header", + "string": "Tokens" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_3875340101": { + "context": "button", + "string": "Create Token" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_4017491013": { + "string": "Token Note" + }, + "src_dot_apps_dot_components_dot_CustomAppTokens_dot_4190792473": { + "context": "table actions", + "string": "Actions" + }, + "src_dot_apps_dot_components_dot_CustomApps_dot_3152347892": { + "context": "custom apps content", + "string": "Your custom created apps will be shown here." + }, + "src_dot_apps_dot_components_dot_CustomApps_dot_3230241731": { + "context": "create app button", + "string": "Create App" + }, + "src_dot_apps_dot_components_dot_DeactivatedText_dot_3064552173": { + "context": "app deactivated", + "string": "Deactivated" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_1636202177": { + "context": "about app", + "string": "About" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_186286611": { + "context": "apps content", + "string": "You don’t have any installed apps in your dashboard" + }, + "src_dot_apps_dot_components_dot_InstalledApps_dot_2008086393": { + "context": "section header", + "string": "Thirdparty Apps" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_2932910073": { + "context": "section header", + "string": "Saleor Marketplace" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_3259214524": { + "context": "marketplace content", + "string": "Marketplace is coming soon" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_3910026447": { + "context": "marketplace button", + "string": "Visit Marketplace" + }, + "src_dot_apps_dot_components_dot_Marketplace_dot_52985091": { + "context": "marketplace content", + "string": "Discover great free and paid apps in our Saleor Marketplace." + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_1336855942": { + "string": "Generated Token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_2530792168": { + "string": "Access token is used to authenticate service accounts" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3009959880": { + "string": "We’ve created your token. Make sure to copy your new personal access token now. You won’t be able to see it again." + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3406541221": { + "context": "button", + "string": "Copy token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_3875340101": { + "context": "header", + "string": "Create Token" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_4017491013": { + "string": "Token Note" + }, + "src_dot_apps_dot_components_dot_TokenCreateDialog_dot_4120989039": { + "context": "create service token, button", + "string": "Create" + }, + "src_dot_apps_dot_components_dot_TokenDeleteDialog_dot_2164262076": { + "context": "dialog title", + "string": "Delete Token" + }, + "src_dot_apps_dot_components_dot_TokenDeleteDialog_dot_981802752": { + "context": "delete token", + "string": "Are you sure you want to delete token {token}?" + }, + "src_dot_apps_dot_views_dot_AppDetailsSettings_dot_2140018198": { + "context": "app settings error", + "string": "Failed to fetch app settings" + }, + "src_dot_apps_dot_views_dot_AppDetails_dot_2021043385": { + "context": "snackbar text", + "string": "App activated" + }, + "src_dot_apps_dot_views_dot_AppDetails_dot_3791371350": { + "context": "snackbar text", + "string": "App deactivated" + }, + "src_dot_apps_dot_views_dot_AppInstall_dot_2538706256": { + "context": "window title", + "string": "Install App" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_1180774955": { + "context": "app has been installed", + "string": "{name} is ready to be used" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_3076215778": { + "context": "app has been removed", + "string": "App successfully removed" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_539268521": { + "context": "message title", + "string": "Couldn’t Install {name}" + }, + "src_dot_apps_dot_views_dot_AppsList_dot_966773578": { + "context": "message title", + "string": "App installed" + }, + "src_dot_apps_dot_views_dot_CustomAppCreate_dot_3230241731": { + "context": "window title", + "string": "Create App" + }, "src_dot_attributes": { "context": "attributes section name", "string": "Attributes" @@ -931,13 +1282,6 @@ "context": "permission list item description", "string": "This group is last source of that permission" }, - "src_dot_components_dot_AccountStatus_dot_2183517419": { - "context": "section header", - "string": "Account Status" - }, - "src_dot_components_dot_AccountStatus_dot_2683780981": { - "string": "If you want to disable this account uncheck the box below" - }, "src_dot_components_dot_AddressEdit_dot_1139500589": { "string": "Country" }, @@ -970,6 +1314,13 @@ "context": "button", "string": "Account Settings" }, + "src_dot_components_dot_AppStatus_dot_1624959454": { + "string": "If you want to disable this App please uncheck the box below." + }, + "src_dot_components_dot_AppStatus_dot_1750277107": { + "context": "section header", + "string": "App Status" + }, "src_dot_components_dot_AssignCategoryDialog_dot_1305061437": { "string": "Search Categories" }, @@ -1442,15 +1793,9 @@ "src_dot_configuration_dot_1440737903": { "string": "Shipping Settings" }, - "src_dot_configuration_dot_1639245766": { - "string": "View and update your webhook and their settings" - }, "src_dot_configuration_dot_1742602794": { "string": "Attributes and Product Types" }, - "src_dot_configuration_dot_2387898569": { - "string": "Manage external integrations accounts" - }, "src_dot_configuration_dot_3140151600": { "string": "Staff Settings" }, @@ -1476,6 +1821,9 @@ "context": "button", "string": "Create" }, + "src_dot_customApps": { + "string": "Local Apps" + }, "src_dot_customers": { "context": "customers section name", "string": "Customers" @@ -4090,159 +4438,6 @@ "context": "service accounts section name", "string": "Service Accounts" }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_1848599267": { - "context": "checkbox label", - "string": "User has full access to the store" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_248507553": { - "context": "header", - "string": "Create New Account" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_27827485": { - "context": "checkbox label", - "string": "Service account is active" - }, - "src_dot_services_dot_components_dot_ServiceCreatePage_dot_3639008725": { - "context": "card description", - "string": "Expand or restrict user's permissions to access certain part of saleor system." - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_1336855942": { - "string": "Generated Token" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2080322626": { - "string": "This token gives you access to your shop's API, which you'll find here: {url}" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_2864204643": { - "context": "button", - "string": "Copied" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_3406541221": { - "context": "button", - "string": "Copy token" - }, - "src_dot_services_dot_components_dot_ServiceDefaultToken_dot_4189999598": { - "string": "We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again." - }, - "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_1534767622": { - "context": "dialog header", - "string": "Delete Service Account" - }, - "src_dot_services_dot_components_dot_ServiceDeleteDialog_dot_2297471173": { - "context": "delete service account", - "string": "Are you sure you want to delete {name}?" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_1848599267": { - "context": "checkbox label", - "string": "User has full access to the store" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_27827485": { - "context": "checkbox label", - "string": "Service account is active" - }, - "src_dot_services_dot_components_dot_ServiceDetailsPage_dot_3639008725": { - "context": "card description", - "string": "Expand or restrict user's permissions to access certain part of saleor system." - }, - "src_dot_services_dot_components_dot_ServiceInfo_dot_3789449123": { - "context": "service account", - "string": "Account Name" - }, - "src_dot_services_dot_components_dot_ServiceInfo_dot_426959482": { - "context": "header", - "string": "Service Account Information" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_1895355592": { - "string": "Search Service Accounts" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_4040605455": { - "context": "tab name", - "string": "All Service Accounts" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_624280156": { - "context": "button", - "string": "Create account" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_active": { - "context": "service account", - "string": "Active" - }, - "src_dot_services_dot_components_dot_ServiceListPage_dot_deactivated": { - "context": "service account", - "string": "Inactive" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_1342308051": { - "string": "No service accounts found" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_31853942": { - "context": "account status", - "string": "active" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_3239722049": { - "context": "account status", - "string": "inactive" - }, - "src_dot_services_dot_components_dot_ServiceList_dot_636461959": { - "context": "service name", - "string": "Name" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_1336855942": { - "string": "Generated Token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_2530792168": { - "string": "Access token is used to authenticate service accounts" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3009959880": { - "string": "We’ve created your token. Make sure to copy your new personal access token now. You won’t be able to see it again." - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3406541221": { - "context": "button", - "string": "Copy token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_3875340101": { - "context": "header", - "string": "Create Token" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4017491013": { - "string": "Token Note" - }, - "src_dot_services_dot_components_dot_ServiceTokenCreateDialog_dot_4120989039": { - "context": "create service token, button", - "string": "Create" - }, - "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_1534767622": { - "context": "dialog title", - "string": "Delete Service Account" - }, - "src_dot_services_dot_components_dot_ServiceTokenDeleteDialog_dot_981802752": { - "context": "delete token", - "string": "Are you sure you want to delete token {token}?" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_2446088470": { - "context": "service account key", - "string": "Key" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_2639089057": { - "string": "No tokens found" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_3875340101": { - "context": "button", - "string": "Create Token" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_4017491013": { - "string": "Token Note" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_4190792473": { - "context": "table actions", - "string": "Actions" - }, - "src_dot_services_dot_components_dot_ServiceTokens_dot_426959482": { - "context": "header", - "string": "Service Account Information" - }, - "src_dot_services_dot_views_dot_ServiceCreate_dot_3167211165": { - "context": "window title", - "string": "Create Service Account" - }, "src_dot_sessionExpired": { "string": "Your session has expired. Please log in again to continue." }, @@ -5189,12 +5384,21 @@ "src_dot_utils_dot_errors_dot_invalid": { "string": "Invalid value" }, + "src_dot_utils_dot_errors_dot_invalidManifestFormat": { + "string": "Invalid manifest format" + }, "src_dot_utils_dot_errors_dot_invalidPassword": { "string": "Invalid password" }, + "src_dot_utils_dot_errors_dot_invalidPermission": { + "string": "Permission is invalid" + }, "src_dot_utils_dot_errors_dot_invalidStatus": { "context": "error message", - "string": "Cannot request an invoice for draft order" + "string": "Status is invalid" + }, + "src_dot_utils_dot_errors_dot_invalidUrlFormat": { + "string": "Url has invalid format" }, "src_dot_utils_dot_errors_dot_noShippingAddress": { "context": "error message", @@ -5216,9 +5420,15 @@ "context": "error message", "string": "Number not set for an invoice" }, + "src_dot_utils_dot_errors_dot_outOfScopeApp": { + "string": "App is out of your permissions scope" + }, "src_dot_utils_dot_errors_dot_outOfScopeGroup": { "string": "Group is out of your permission scope" }, + "src_dot_utils_dot_errors_dot_outOfScopePermission": { + "string": "Permission is out of your scope" + }, "src_dot_utils_dot_errors_dot_outOfScopeUser": { "string": "User is out of your permissions scope" }, @@ -5448,9 +5658,6 @@ "context": "webhook specific information", "string": "Webhook specific information" }, - "src_dot_webhooks_dot_components_dot_WebhookInfo_dot_819389696": { - "string": "Assign to Service Account" - }, "src_dot_webhooks_dot_components_dot_WebhookStatus_dot_2772025990": { "context": "webhooks active", "string": "Webhook is active" @@ -5471,31 +5678,16 @@ "context": "header", "string": "{webhookName} Details" }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_1432828311": { - "string": "Search Webhooks" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_2295583901": { - "context": "button", - "string": "Create webhook" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_3300314452": { - "context": "tab name", - "string": "All Webhooks" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_active": { - "context": "webhook", - "string": "Active" - }, - "src_dot_webhooks_dot_components_dot_WebhooksListPage_dot_inactive": { - "context": "webhook", - "string": "Inactive" - }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_1153324159": { "string": "No webhooks found" }, - "src_dot_webhooks_dot_components_dot_WebhooksList_dot_2487865635": { - "context": "webhook service account", - "string": "Service Account" + "src_dot_webhooks_dot_components_dot_WebhooksList_dot_3493926696": { + "context": "button", + "string": "Create Webhook" + }, + "src_dot_webhooks_dot_components_dot_WebhooksList_dot_3861572549": { + "context": "header", + "string": "Webhooks" }, "src_dot_webhooks_dot_components_dot_WebhooksList_dot_4120604650": { "context": "user action bar", diff --git a/package-lock.json b/package-lock.json index 187d509cb..630e34467 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2735,6 +2735,31 @@ "warning": "^3.0.0" } }, + "@saleor/macaw-ui": { + "version": "0.1.1-9", + "resolved": "https://registry.npmjs.org/@saleor/macaw-ui/-/macaw-ui-0.1.1-9.tgz", + "integrity": "sha512-ryftb0jBs1ghIm4ILwJZ7vfQt90Kab9XlNcEUh4JFDV4+HEABrGpwstLKyCtIjFDzxQf/z9L4vbW25o1m6klmg==", + "requires": { + "@types/react-inlinesvg": "^0.8.1", + "classnames": "^2.2.6", + "downshift": "^1.31.16", + "lodash-es": "^4.17.15", + "react-helmet": "^5.2.1", + "react-inlinesvg": "^1.1.2", + "string-similarity": "^1.2.2" + }, + "dependencies": { + "react-inlinesvg": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/react-inlinesvg/-/react-inlinesvg-1.2.0.tgz", + "integrity": "sha512-IsznU+UzpUwDGzBWbf0bfSRA5Jbqz87xeoqLM/nSIDPkoHksInF1wCGybTSn4sIui+30TqboRQP1wAelNTkdog==", + "requires": { + "exenv": "^1.2.2", + "react-from-dom": "^0.3.0" + } + } + } + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", @@ -3793,6 +3818,14 @@ "@types/react": "*" } }, + "@types/react-inlinesvg": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@types/react-inlinesvg/-/react-inlinesvg-0.8.1.tgz", + "integrity": "sha512-pONmeCNqot4diXLhxb+jajDWX57rH/JmMu9H4NQWNMl5WUHAHmcrOfDfB05IgYBfRUX1Cvyjl9EZzKHxSxZpAA==", + "requires": { + "@types/react": "*" + } + }, "@types/react-router": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.2.tgz", @@ -6533,6 +6566,11 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -7147,20 +7185,17 @@ "character-entities": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.3.tgz", - "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==", - "dev": true + "integrity": "sha512-yB4oYSAa9yLcGyTbB4ItFwHw43QHdH129IJ5R+WvxOkWlyFnR5FAaBNnUq4mcxsTVZGh28bHoeTHMKXH1wZf3w==" }, "character-entities-legacy": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.3.tgz", - "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==", - "dev": true + "integrity": "sha512-YAxUpPoPwxYFsslbdKkhrGnXAtXoHNgYjlBM3WMXkWGTl5RsY3QmOyhwAgL8Nxm9l5LBThXGawxKPn68y6/fww==" }, "character-reference-invalid": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.3.tgz", - "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==", - "dev": true + "integrity": "sha512-VOq6PRzQBam/8Jm6XBGk2fNEnHXAdGd6go0rtd4weAGECBamHDwwCQSOT12TACIYUZegUXnV6xBXqUssijtxIg==" }, "chardet": { "version": "0.7.0", @@ -7529,6 +7564,11 @@ "urlgrey": "0.4.4" } }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -8791,7 +8831,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz", "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==", - "dev": true, "requires": { "domelementtype": "^2.0.1", "entities": "^2.0.0" @@ -8800,14 +8839,12 @@ "domelementtype": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" }, "entities": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", - "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", - "dev": true + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==" } } }, @@ -10098,6 +10135,11 @@ } } }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -10321,8 +10363,7 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -12270,6 +12311,63 @@ "uglify-js": "^3.5.1" } }, + "html-to-react": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/html-to-react/-/html-to-react-1.4.3.tgz", + "integrity": "sha512-txe09A3vxW8yEZGJXJ1is5gGDfBEVACmZDSgwDyH5EsfRdOubBwBCg63ZThZP0xBn0UE4FyvMXZXmohusCxDcg==", + "requires": { + "domhandler": "^3.0", + "htmlparser2": "^4.1.0", + "lodash.camelcase": "^4.3.0", + "ramda": "^0.27" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" + }, + "domhandler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz", + "integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==", + "requires": { + "domelementtype": "^2.0.1" + } + }, + "domutils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.1.0.tgz", + "integrity": "sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg==", + "requires": { + "dom-serializer": "^0.2.1", + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0" + } + }, + "entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.2.tgz", + "integrity": "sha512-dmD3AvJQBUjKpcNkoqr+x+IF0SdRtPz9Vk0uTy4yWqga9ibB6s4v++QFWNohjiUGoMlF552ZvNyXDxz5iW0qmw==" + }, + "htmlparser2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", + "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^3.0.0", + "domutils": "^2.0.0", + "entities": "^2.0.0" + } + }, + "ramda": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.0.tgz", + "integrity": "sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==" + } + } + }, "html-webpack-plugin": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", @@ -12896,14 +12994,12 @@ "is-alphabetical": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.3.tgz", - "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==", - "dev": true + "integrity": "sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA==" }, "is-alphanumerical": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.3.tgz", "integrity": "sha512-A1IGAPO5AW9vSh7omxIlOGwIqEvpW/TA+DksVOPM5ODuxKlZS09+TEM1E3275lJqO2oJ38vDpeAL3DCIiHE6eA==", - "dev": true, "requires": { "is-alphabetical": "^1.0.0", "is-decimal": "^1.0.0" @@ -12938,8 +13034,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { "version": "1.1.4", @@ -12983,8 +13078,7 @@ "is-decimal": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.3.tgz", - "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==", - "dev": true + "integrity": "sha512-bvLSwoDg2q6Gf+E2LEPiklHZxxiSi3XAh4Mav65mKqTfCO1HM3uBs24TjEH8iJX3bbDdLXKJXBTmGzuTUuAEjQ==" }, "is-descriptor": { "version": "0.1.6", @@ -13075,8 +13169,7 @@ "is-hexadecimal": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.3.tgz", - "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==", - "dev": true + "integrity": "sha512-zxQ9//Q3D/34poZf8fiy3m3XVpbQc7ren15iKqrTtLPwkPD/t3Scy9Imp63FujULGxuK0ZlCwoo5xNpktFgbOA==" }, "is-in-browser": { "version": "1.1.3", @@ -13156,8 +13249,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-plain-object": { "version": "2.0.4", @@ -13260,12 +13352,22 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==" + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==" + }, "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", @@ -14861,6 +14963,11 @@ "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -14872,11 +14979,20 @@ "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", "dev": true }, + "lodash.every": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.every/-/lodash.every-4.6.0.tgz", + "integrity": "sha1-64mYS+vENkJ5uzrvu9HKGb+mxqc=" + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" }, "lodash.get": { "version": "4.4.2", @@ -14893,6 +15009,16 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.maxby": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.maxby/-/lodash.maxby-4.6.0.tgz", + "integrity": "sha1-CCJABo88eiJ6oAqDgOTzjPB4bj0=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -15131,6 +15257,11 @@ "object-visit": "^1.0.0" } }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==" + }, "markdown-to-jsx": { "version": "6.11.4", "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz", @@ -15158,6 +15289,14 @@ "safe-buffer": "^5.1.2" } }, + "mdast-add-list-metadata": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz", + "integrity": "sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA==", + "requires": { + "unist-util-visit-parents": "1.1.2" + } + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -16192,7 +16331,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-1.2.2.tgz", "integrity": "sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg==", - "dev": true, "requires": { "character-entities": "^1.0.0", "character-entities-legacy": "^1.0.0", @@ -17356,6 +17494,11 @@ "react-clientside-effect": "^1.2.0" } }, + "react-from-dom": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/react-from-dom/-/react-from-dom-0.3.1.tgz", + "integrity": "sha512-PeNBa8iuzoD7qHA9O7YpGnXFvC+XFFwStmFh2/r2zJAvEIaRg6EwOj+EPcDIFwyYBhqPIItxIx/dGdeWiFivjQ==" + }, "react-gtm-module": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.8.tgz", @@ -17495,6 +17638,28 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-markdown": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-4.3.1.tgz", + "integrity": "sha512-HQlWFTbDxTtNY6bjgp3C3uv1h2xcjCSi1zAEzfBW9OwJJvENSYiLXWNXN5hHLsoqai7RnZiiHzcnWdXk2Splzw==", + "requires": { + "html-to-react": "^1.3.4", + "mdast-add-list-metadata": "1.0.1", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "remark-parse": "^5.0.0", + "unified": "^6.1.5", + "unist-util-visit": "^1.3.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "react-moment": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz", @@ -18043,6 +18208,35 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, + "remark-parse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-5.0.0.tgz", + "integrity": "sha512-b3iXszZLH1TLoyUzrATcTQUZrwNl1rE70rVdSruJFlDaJ9z5aMkhrG43Pp68OgfHndL/ADz6V69Zow8cTQu+JA==", + "requires": { + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^1.1.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^1.0.0", + "vfile-location": "^2.0.0", + "xtend": "^4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -18088,8 +18282,7 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -18100,6 +18293,11 @@ "is-finite": "^1.0.0" } }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -19308,6 +19506,11 @@ } } }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -19451,6 +19654,18 @@ } } }, + "string-similarity": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.2.tgz", + "integrity": "sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==", + "requires": { + "lodash.every": "^4.6.0", + "lodash.flattendeep": "^4.4.0", + "lodash.foreach": "^4.5.0", + "lodash.map": "^4.6.0", + "lodash.maxby": "^4.6.0" + } + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -20163,12 +20378,27 @@ "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", "dev": true }, + "trim-trailing-lines": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz", + "integrity": "sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA==" + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==" + }, "ts-dedent": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-1.1.0.tgz", @@ -20379,6 +20609,22 @@ "integrity": "sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg==", "dev": true }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -20407,6 +20653,19 @@ "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", "dev": true }, + "unified": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-6.2.0.tgz", + "integrity": "sha512-1k+KPhlVtqmG99RaTbAv/usu85fcSRu3wY8X+vnsEhIxNP5VbVIDiXnLqyKIG+UMdyTg0ZX9EI6k2AfjJkHPtA==", + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^1.1.0", + "trough": "^1.0.0", + "vfile": "^2.0.0", + "x-is-string": "^0.1.0" + } + }, "union-class-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-class-names/-/union-class-names-1.0.0.tgz", @@ -20448,6 +20707,47 @@ "imurmurhash": "^0.1.4" } }, + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + }, + "unist-util-remove-position": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz", + "integrity": "sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A==", + "requires": { + "unist-util-visit": "^1.1.0" + } + }, + "unist-util-stringify-position": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz", + "integrity": "sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ==" + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + }, + "dependencies": { + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "requires": { + "unist-util-is": "^3.0.0" + } + } + } + }, + "unist-util-visit-parents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz", + "integrity": "sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q==" + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -20740,6 +21040,30 @@ "extsprintf": "^1.2.0" } }, + "vfile": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-2.3.0.tgz", + "integrity": "sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w==", + "requires": { + "is-buffer": "^1.1.4", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^1.0.0", + "vfile-message": "^1.0.0" + } + }, + "vfile-location": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-2.0.6.tgz", + "integrity": "sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA==" + }, + "vfile-message": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-1.1.1.tgz", + "integrity": "sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA==", + "requires": { + "unist-util-stringify-position": "^1.1.1" + } + }, "vm-browserify": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", @@ -21544,6 +21868,11 @@ "async-limiter": "~1.0.0" } }, + "x-is-string": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz", + "integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=" + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index 843fed0b7..8b0b9273d 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@material-ui/core": "^4.5.1", "@material-ui/icons": "^4.5.1", "@material-ui/styles": "^4.5.2", + "@saleor/macaw-ui": "^0.1.1-9", "apollo": "^2.21.2", "apollo-cache-inmemory": "^1.6.5", "apollo-client": "^2.6.8", @@ -58,6 +59,7 @@ "react-inlinesvg": "^0.8.4", "react-intl": "^3.1.8", "react-jss": "^10.0.0", + "react-markdown": "^4.3.1", "react-moment": "^0.9.7", "react-router": "^5.0.1", "react-router-dom": "^5.0.1", @@ -166,7 +168,7 @@ "moduleNameMapper": { "@assets(.*)$": "/assets/$1", "@locale(.*)$": "/locale/$1", - "@saleor(.*)$": "/src/$1", + "@saleor(?!.*macaw)(.*)$": "/src/$1", "@test/(.*)$": "/testUtils/$1", "^lodash-es(.*)$": "lodash/$1" } diff --git a/schema.graphql b/schema.graphql index 8be671a96..4a3aa7ce0 100644 --- a/schema.graphql +++ b/schema.graphql @@ -4,28 +4,40 @@ schema { } type AccountAddressCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address } type AccountAddressDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address } type AccountAddressUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address } type AccountDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -77,7 +89,10 @@ input AccountInput { } type AccountRegister { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) requiresConfirmation: Boolean accountErrors: [AccountError!]! user: User @@ -90,24 +105,36 @@ input AccountRegisterInput { } type AccountRequestDeletion { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! } type AccountSetDefaultAddress { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } type AccountUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } type AccountUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -130,14 +157,20 @@ type Address implements Node { } type AddressCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address } type AddressDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address @@ -158,7 +191,10 @@ input AddressInput { } type AddressSetDefault { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } @@ -169,7 +205,10 @@ enum AddressTypeEnum { } type AddressUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! address: Address @@ -204,9 +243,34 @@ type App implements Node & ObjectWithMetadata { tokens: [AppToken] privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + type: AppTypeEnum webhooks: [Webhook] + aboutApp: String + dataPrivacy: String + dataPrivacyUrl: String + homepageUrl: String + supportUrl: String + configurationUrl: String + appUrl: String + version: String + accessToken: String +} + +type AppActivate { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + appErrors: [AppError!]! + app: App } type AppCountableConnection { @@ -221,18 +285,42 @@ type AppCountableEdge { } type AppCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authToken: String appErrors: [AppError!]! app: App } -type AppDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") +type AppDeactivate { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) appErrors: [AppError!]! app: App } +type AppDelete { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + appErrors: [AppError!]! + app: App +} + +type AppDeleteFailedInstallation { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + appErrors: [AppError!]! + appInstallation: AppInstallation +} + type AppError { field: String message: String @@ -241,8 +329,14 @@ type AppError { } enum AppErrorCode { + FORBIDDEN GRAPHQL_ERROR INVALID + INVALID_STATUS + INVALID_PERMISSION + INVALID_URL_FORMAT + INVALID_MANIFEST_FORMAT + MANIFEST_URL_CANT_CONNECT NOT_FOUND REQUIRED UNIQUE @@ -250,9 +344,19 @@ enum AppErrorCode { OUT_OF_SCOPE_PERMISSION } +type AppFetchManifest { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + manifest: Manifest + appErrors: [AppError!]! +} + input AppFilterInput { search: String isActive: Boolean + type: AppTypeEnum } input AppInput { @@ -261,6 +365,41 @@ input AppInput { permissions: [PermissionEnum] } +type AppInstall { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + appErrors: [AppError!]! + appInstallation: AppInstallation +} + +input AppInstallInput { + appName: String + manifestUrl: String + activateAfterInstallation: Boolean = true + permissions: [PermissionEnum] +} + +type AppInstallation implements Node & Job { + status: JobStatusEnum! + message: String + createdAt: DateTime! + updatedAt: DateTime! + appName: String! + manifestUrl: String! + id: ID! +} + +type AppRetryInstall { + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) + appErrors: [AppError!]! + appInstallation: AppInstallation +} + enum AppSortField { NAME CREATION_DATE @@ -278,14 +417,20 @@ type AppToken implements Node { } type AppTokenCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authToken: String appErrors: [AppError!]! appToken: AppToken } type AppTokenDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) appErrors: [AppError!]! appToken: AppToken } @@ -296,31 +441,61 @@ input AppTokenInput { } type AppTokenVerify { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) valid: Boolean! appErrors: [AppError!]! } +enum AppTypeEnum { + LOCAL + THIRDPARTY +} + type AppUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) appErrors: [AppError!]! app: App } type AssignNavigation { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menu: Menu menuErrors: [MenuError!]! } type Attribute implements Node & ObjectWithMetadata { id: ID! - productTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection! - productVariantTypes(before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection! + productTypes( + before: String + after: String + first: Int + last: Int + ): ProductTypeCountableConnection! + productVariantTypes( + before: String + after: String + first: Int + last: Int + ): ProductTypeCountableConnection! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) inputType: AttributeInputTypeEnum name: String slug: String @@ -335,7 +510,10 @@ type Attribute implements Node & ObjectWithMetadata { } type AttributeAssign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productType: ProductType productErrors: [ProductAttributeError!]! } @@ -346,19 +524,28 @@ input AttributeAssignInput { } type AttributeBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type AttributeClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! attribute: Attribute } type AttributeClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! attribute: Attribute } @@ -375,7 +562,10 @@ type AttributeCountableEdge { } type AttributeCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! } @@ -395,7 +585,10 @@ input AttributeCreateInput { } type AttributeDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! attribute: Attribute } @@ -425,7 +618,10 @@ enum AttributeInputTypeEnum { } type AttributeReorderValues { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! } @@ -455,7 +651,10 @@ type AttributeTranslatableContent implements Node { } type AttributeTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! attribute: Attribute } @@ -472,13 +671,19 @@ enum AttributeTypeEnum { } type AttributeUnassign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productType: ProductType productErrors: [ProductError!]! } type AttributeUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! } @@ -498,13 +703,19 @@ input AttributeUpdateInput { } type AttributeUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! attribute: Attribute } type AttributeUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! attribute: Attribute } @@ -513,19 +724,28 @@ type AttributeValue implements Node { id: ID! name: String slug: String - type: AttributeValueType @deprecated(reason: "Use the `inputType` field to determine the type of attribute's value. This field will be removed after 2020-07-31.") + type: AttributeValueType + @deprecated( + reason: "Use the `inputType` field to determine the type of attribute's value. This field will be removed after 2020-07-31." + ) translation(languageCode: LanguageCodeEnum!): AttributeValueTranslation inputType: AttributeInputTypeEnum } type AttributeValueBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type AttributeValueCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! attributeValue: AttributeValue @@ -536,7 +756,10 @@ input AttributeValueCreateInput { } type AttributeValueDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! attributeValue: AttributeValue @@ -555,7 +778,10 @@ type AttributeValueTranslatableContent implements Node { } type AttributeValueTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! attributeValue: AttributeValue } @@ -574,7 +800,10 @@ enum AttributeValueType { } type AttributeValueUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) attribute: Attribute productErrors: [ProductError!]! attributeValue: AttributeValue @@ -586,14 +815,20 @@ type AuthorizationKey { } type AuthorizationKeyAdd { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authorizationKey: AuthorizationKey shop: Shop shopErrors: [ShopError!]! } type AuthorizationKeyDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authorizationKey: AuthorizationKey shop: Shop shopErrors: [ShopError!]! @@ -642,30 +877,61 @@ type Category implements Node & ObjectWithMetadata { level: Int! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - ancestors(before: String, after: String, first: Int, last: Int): CategoryCountableConnection - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection - url: String @deprecated(reason: "This field will be removed after 2020-07-31.") - children(before: String, after: String, first: Int, last: Int): CategoryCountableConnection + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + ancestors( + before: String + after: String + first: Int + last: Int + ): CategoryCountableConnection + products( + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection + url: String + @deprecated(reason: "This field will be removed after 2020-07-31.") + children( + before: String + after: String + first: Int + last: Int + ): CategoryCountableConnection backgroundImage(size: Int): Image translation(languageCode: LanguageCodeEnum!): CategoryTranslation } type CategoryBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type CategoryClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } type CategoryClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } @@ -682,13 +948,19 @@ type CategoryCountableEdge { } type CategoryCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } type CategoryDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } @@ -731,7 +1003,10 @@ type CategoryTranslatableContent implements Node { } type CategoryTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! category: Category } @@ -747,19 +1022,28 @@ type CategoryTranslation implements Node { } type CategoryUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } type CategoryUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } type CategoryUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! category: Category } @@ -781,8 +1065,14 @@ type Checkout implements Node & ObjectWithMetadata { id: ID! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) availableShippingMethods: [ShippingMethod]! availablePaymentGateways: [PaymentGateway!]! email: String! @@ -795,31 +1085,46 @@ type Checkout implements Node & ObjectWithMetadata { } type CheckoutAddPromoCode { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutBillingAddressUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkoutErrors: [CheckoutError!]! checkout: Checkout } type CheckoutClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkoutErrors: [CheckoutError!]! checkout: Checkout } type CheckoutComplete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order confirmationNeeded: Boolean! checkoutErrors: [CheckoutError!]! @@ -837,7 +1142,10 @@ type CheckoutCountableEdge { } type CheckoutCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) created: Boolean checkoutErrors: [CheckoutError!]! checkout: Checkout @@ -851,19 +1159,28 @@ input CheckoutCreateInput { } type CheckoutCustomerAttach { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutCustomerDetach { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutEmailUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } @@ -916,7 +1233,10 @@ type CheckoutLineCountableEdge { } type CheckoutLineDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } @@ -927,50 +1247,74 @@ input CheckoutLineInput { } type CheckoutLinesAdd { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutLinesUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutPaymentCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout payment: Payment paymentErrors: [PaymentError!]! } type CheckoutRemovePromoCode { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutShippingAddressUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutShippingMethodUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkout: Checkout checkoutErrors: [CheckoutError!]! } type CheckoutUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkoutErrors: [CheckoutError!]! checkout: Checkout } type CheckoutUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) checkoutErrors: [CheckoutError!]! checkout: Checkout } @@ -992,39 +1336,65 @@ type Collection implements Node & ObjectWithMetadata { slug: String! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + products( + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection backgroundImage(size: Int): Image translation(languageCode: LanguageCodeEnum!): CollectionTranslation } type CollectionAddProducts { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) collection: Collection productErrors: [ProductError!]! } type CollectionBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type CollectionBulkPublish { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type CollectionClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } type CollectionClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } @@ -1041,7 +1411,10 @@ type CollectionCountableEdge { } type CollectionCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } @@ -1060,7 +1433,10 @@ input CollectionCreateInput { } type CollectionDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } @@ -1089,13 +1465,19 @@ enum CollectionPublished { } type CollectionRemoveProducts { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) collection: Collection productErrors: [ProductError!]! } type CollectionReorderProducts { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) collection: Collection productErrors: [ProductError!]! } @@ -1123,7 +1505,10 @@ type CollectionTranslatableContent implements Node { } type CollectionTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! collection: Collection } @@ -1139,19 +1524,28 @@ type CollectionTranslation implements Node { } type CollectionUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } type CollectionUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } type CollectionUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! collection: Collection } @@ -1177,13 +1571,19 @@ enum ConfigurationTypeFieldEnum { } type ConfirmAccount { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } type ConfirmEmailChange { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } @@ -1448,7 +1848,10 @@ type CountryDisplay { } type CreateToken { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) token: String refreshToken: String csrfToken: String @@ -1465,19 +1868,28 @@ type CreditCard { } type CustomerBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! accountErrors: [AccountError!]! } type CustomerCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } type CustomerDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -1528,7 +1940,10 @@ input CustomerInput { } type CustomerUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -1548,20 +1963,29 @@ input DateTimeRangeInput { } type DeactivateAllUserTokens { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! } scalar Decimal type DeleteMetadata { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) metadataErrors: [MetadataError!]! item: ObjectWithMetadata } type DeletePrivateMetadata { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) metadataErrors: [MetadataError!]! item: ObjectWithMetadata } @@ -1577,8 +2001,14 @@ type DigitalContent implements Node & ObjectWithMetadata { id: ID! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) } type DigitalContentCountableConnection { @@ -1593,14 +2023,20 @@ type DigitalContentCountableEdge { } type DigitalContentCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) variant: ProductVariant content: DigitalContent productErrors: [ProductError!]! } type DigitalContentDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) variant: ProductVariant productErrors: [ProductError!]! } @@ -1613,7 +2049,10 @@ input DigitalContentInput { } type DigitalContentUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) variant: ProductVariant content: DigitalContent productErrors: [ProductError!]! @@ -1637,7 +2076,10 @@ type DigitalContentUrl implements Node { } type DigitalContentUrlCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! digitalContentUrl: DigitalContentUrl } @@ -1679,19 +2121,28 @@ type Domain { } type DraftOrderBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! orderErrors: [OrderError!]! } type DraftOrderComplete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } type DraftOrderCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) orderErrors: [OrderError!]! order: Order } @@ -1709,7 +2160,10 @@ input DraftOrderCreateInput { } type DraftOrderDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) orderErrors: [OrderError!]! order: Order } @@ -1726,34 +2180,49 @@ input DraftOrderInput { } type DraftOrderLineDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderLine: OrderLine orderErrors: [OrderError!]! } type DraftOrderLineUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! orderLine: OrderLine } type DraftOrderLinesBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! orderErrors: [OrderError!]! } type DraftOrderLinesCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderLines: [OrderLine!] orderErrors: [OrderError!]! } type DraftOrderUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) orderErrors: [OrderError!]! order: Order } @@ -1771,15 +2240,24 @@ type Fulfillment implements Node & ObjectWithMetadata { created: DateTime! privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) lines: [FulfillmentLine] statusDisplay: String warehouse: Warehouse } type FulfillmentCancel { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment order: Order orderErrors: [OrderError!]! @@ -1790,12 +2268,18 @@ input FulfillmentCancelInput { } type FulfillmentClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment } type FulfillmentClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment } @@ -1811,17 +2295,26 @@ enum FulfillmentStatus { } type FulfillmentUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment } type FulfillmentUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment } type FulfillmentUpdateTracking { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillment: Fulfillment order: Order orderErrors: [OrderError!]! @@ -1858,7 +2351,10 @@ type GiftCard implements Node { } type GiftCardActivate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) giftCard: GiftCard giftCardErrors: [GiftCardError!]! } @@ -1875,7 +2371,10 @@ type GiftCardCountableEdge { } type GiftCardCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) giftCardErrors: [GiftCardError!]! giftCard: GiftCard } @@ -1889,7 +2388,10 @@ input GiftCardCreateInput { } type GiftCardDeactivate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) giftCard: GiftCard giftCardErrors: [GiftCardError!]! } @@ -1910,7 +2412,10 @@ enum GiftCardErrorCode { } type GiftCardUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) giftCardErrors: [GiftCardError!]! giftCard: GiftCard } @@ -1942,7 +2447,10 @@ type GroupCountableEdge { } type HomepageCollectionUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop shopErrors: [ShopError!]! } @@ -1964,15 +2472,24 @@ type Invoice implements ObjectWithMetadata & Job & Node { number: String externalUrl: String privateMetadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) createdAt: DateTime! updatedAt: DateTime! url: String } type InvoiceCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) invoiceErrors: [InvoiceError!]! invoice: Invoice } @@ -1983,7 +2500,10 @@ input InvoiceCreateInput { } type InvoiceDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) invoiceErrors: [InvoiceError!]! invoice: Invoice } @@ -2005,26 +2525,38 @@ enum InvoiceErrorCode { } type InvoiceRequest { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order invoiceErrors: [InvoiceError!]! invoice: Invoice } type InvoiceRequestDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) invoiceErrors: [InvoiceError!]! invoice: Invoice } type InvoiceSendEmail { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) invoiceErrors: [InvoiceError!]! invoice: Invoice } type InvoiceUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) invoiceErrors: [InvoiceError!]! invoice: Invoice } @@ -2098,6 +2630,21 @@ type LanguageDisplay { language: String! } +type Manifest { + identifier: String! + version: String! + name: String! + about: String + permissions: [Permission] + appUrl: String + configurationUrl: String + tokenTargetUrl: String + dataPrivacy: String + dataPrivacyUrl: String + homepageUrl: String + supportUrl: String +} + type Margin { start: Int stop: Int @@ -2110,7 +2657,10 @@ type Menu implements Node { } type MenuBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! menuErrors: [MenuError!]! } @@ -2127,7 +2677,10 @@ type MenuCountableEdge { } type MenuCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menu: Menu } @@ -2138,7 +2691,10 @@ input MenuCreateInput { } type MenuDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menu: Menu } @@ -2184,7 +2740,10 @@ type MenuItem implements Node { } type MenuItemBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! menuErrors: [MenuError!]! } @@ -2201,7 +2760,10 @@ type MenuItemCountableEdge { } type MenuItemCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menuItem: MenuItem } @@ -2217,7 +2779,10 @@ input MenuItemCreateInput { } type MenuItemDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menuItem: MenuItem } @@ -2235,7 +2800,10 @@ input MenuItemInput { } type MenuItemMove { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menu: Menu menuErrors: [MenuError!]! } @@ -2259,7 +2827,10 @@ type MenuItemTranslatableContent implements Node { } type MenuItemTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! menuItem: MenuItem } @@ -2271,7 +2842,10 @@ type MenuItemTranslation implements Node { } type MenuItemUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menuItem: MenuItem } @@ -2291,7 +2865,10 @@ input MenuSortingInput { } type MenuUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) menuErrors: [MenuError!]! menu: Menu } @@ -2349,7 +2926,10 @@ type MetadataItem { type Money { currency: String! amount: Float! - localized: String! @deprecated(reason: "Price formatting according to the current locale should be handled by the frontend client. This field will be removed after 2020-07-31.") + localized: String! + @deprecated( + reason: "Price formatting according to the current locale should be handled by the frontend client. This field will be removed after 2020-07-31." + ) } type MoneyRange { @@ -2369,108 +2949,324 @@ type Mutation { createWarehouse(input: WarehouseCreateInput!): WarehouseCreate updateWarehouse(id: ID!, input: WarehouseUpdateInput!): WarehouseUpdate deleteWarehouse(id: ID!): WarehouseDelete - assignWarehouseShippingZone(id: ID!, shippingZoneIds: [ID!]!): WarehouseShippingZoneAssign - unassignWarehouseShippingZone(id: ID!, shippingZoneIds: [ID!]!): WarehouseShippingZoneUnassign - authorizationKeyAdd(input: AuthorizationKeyInput!, keyType: AuthorizationKeyType!): AuthorizationKeyAdd + assignWarehouseShippingZone( + id: ID! + shippingZoneIds: [ID!]! + ): WarehouseShippingZoneAssign + unassignWarehouseShippingZone( + id: ID! + shippingZoneIds: [ID!]! + ): WarehouseShippingZoneUnassign + authorizationKeyAdd( + input: AuthorizationKeyInput! + keyType: AuthorizationKeyType! + ): AuthorizationKeyAdd authorizationKeyDelete(keyType: AuthorizationKeyType!): AuthorizationKeyDelete - staffNotificationRecipientCreate(input: StaffNotificationRecipientInput!): StaffNotificationRecipientCreate - staffNotificationRecipientUpdate(id: ID!, input: StaffNotificationRecipientInput!): StaffNotificationRecipientUpdate + staffNotificationRecipientCreate( + input: StaffNotificationRecipientInput! + ): StaffNotificationRecipientCreate + staffNotificationRecipientUpdate( + id: ID! + input: StaffNotificationRecipientInput! + ): StaffNotificationRecipientUpdate staffNotificationRecipientDelete(id: ID!): StaffNotificationRecipientDelete homepageCollectionUpdate(collection: ID): HomepageCollectionUpdate shopDomainUpdate(input: SiteDomainInput): ShopDomainUpdate shopSettingsUpdate(input: ShopSettingsInput!): ShopSettingsUpdate shopFetchTaxRates: ShopFetchTaxRates - shopSettingsTranslate(input: ShopSettingsTranslationInput!, languageCode: LanguageCodeEnum!): ShopSettingsTranslate + shopSettingsTranslate( + input: ShopSettingsTranslationInput! + languageCode: LanguageCodeEnum! + ): ShopSettingsTranslate shopAddressUpdate(input: AddressInput): ShopAddressUpdate shippingPriceCreate(input: ShippingPriceInput!): ShippingPriceCreate shippingPriceDelete(id: ID!): ShippingPriceDelete shippingPriceBulkDelete(ids: [ID]!): ShippingPriceBulkDelete shippingPriceUpdate(id: ID!, input: ShippingPriceInput!): ShippingPriceUpdate - shippingPriceTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): ShippingPriceTranslate + shippingPriceTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): ShippingPriceTranslate shippingZoneCreate(input: ShippingZoneCreateInput!): ShippingZoneCreate shippingZoneDelete(id: ID!): ShippingZoneDelete shippingZoneBulkDelete(ids: [ID]!): ShippingZoneBulkDelete - shippingZoneUpdate(id: ID!, input: ShippingZoneUpdateInput!): ShippingZoneUpdate + shippingZoneUpdate( + id: ID! + input: ShippingZoneUpdateInput! + ): ShippingZoneUpdate attributeCreate(input: AttributeCreateInput!): AttributeCreate attributeDelete(id: ID!): AttributeDelete attributeBulkDelete(ids: [ID]!): AttributeBulkDelete - attributeAssign(operations: [AttributeAssignInput]!, productTypeId: ID!): AttributeAssign + attributeAssign( + operations: [AttributeAssignInput]! + productTypeId: ID! + ): AttributeAssign attributeUnassign(attributeIds: [ID]!, productTypeId: ID!): AttributeUnassign attributeUpdate(id: ID!, input: AttributeUpdateInput!): AttributeUpdate - attributeTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): AttributeTranslate - attributeUpdateMetadata(id: ID!, input: MetaInput!): AttributeUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - attributeClearMetadata(id: ID!, input: MetaPath!): AttributeClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - attributeUpdatePrivateMetadata(id: ID!, input: MetaInput!): AttributeUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - attributeClearPrivateMetadata(id: ID!, input: MetaPath!): AttributeClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - attributeValueCreate(attribute: ID!, input: AttributeValueCreateInput!): AttributeValueCreate + attributeTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): AttributeTranslate + attributeUpdateMetadata(id: ID!, input: MetaInput!): AttributeUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + attributeClearMetadata(id: ID!, input: MetaPath!): AttributeClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + attributeUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): AttributeUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + attributeClearPrivateMetadata( + id: ID! + input: MetaPath! + ): AttributeClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + attributeValueCreate( + attribute: ID! + input: AttributeValueCreateInput! + ): AttributeValueCreate attributeValueDelete(id: ID!): AttributeValueDelete attributeValueBulkDelete(ids: [ID]!): AttributeValueBulkDelete - attributeValueUpdate(id: ID!, input: AttributeValueCreateInput!): AttributeValueUpdate - attributeValueTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): AttributeValueTranslate - attributeReorderValues(attributeId: ID!, moves: [ReorderInput]!): AttributeReorderValues + attributeValueUpdate( + id: ID! + input: AttributeValueCreateInput! + ): AttributeValueUpdate + attributeValueTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): AttributeValueTranslate + attributeReorderValues( + attributeId: ID! + moves: [ReorderInput]! + ): AttributeReorderValues categoryCreate(input: CategoryInput!, parent: ID): CategoryCreate categoryDelete(id: ID!): CategoryDelete categoryBulkDelete(ids: [ID]!): CategoryBulkDelete categoryUpdate(id: ID!, input: CategoryInput!): CategoryUpdate - categoryTranslate(id: ID!, input: TranslationInput!, languageCode: LanguageCodeEnum!): CategoryTranslate - categoryUpdateMetadata(id: ID!, input: MetaInput!): CategoryUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - categoryClearMetadata(id: ID!, input: MetaPath!): CategoryClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - categoryUpdatePrivateMetadata(id: ID!, input: MetaInput!): CategoryUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - categoryClearPrivateMetadata(id: ID!, input: MetaPath!): CategoryClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - collectionAddProducts(collectionId: ID!, products: [ID]!): CollectionAddProducts + categoryTranslate( + id: ID! + input: TranslationInput! + languageCode: LanguageCodeEnum! + ): CategoryTranslate + categoryUpdateMetadata(id: ID!, input: MetaInput!): CategoryUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + categoryClearMetadata(id: ID!, input: MetaPath!): CategoryClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + categoryUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): CategoryUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + categoryClearPrivateMetadata( + id: ID! + input: MetaPath! + ): CategoryClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + collectionAddProducts( + collectionId: ID! + products: [ID]! + ): CollectionAddProducts collectionCreate(input: CollectionCreateInput!): CollectionCreate collectionDelete(id: ID!): CollectionDelete - collectionReorderProducts(collectionId: ID!, moves: [MoveProductInput]!): CollectionReorderProducts + collectionReorderProducts( + collectionId: ID! + moves: [MoveProductInput]! + ): CollectionReorderProducts collectionBulkDelete(ids: [ID]!): CollectionBulkDelete - collectionBulkPublish(ids: [ID]!, isPublished: Boolean!): CollectionBulkPublish - collectionRemoveProducts(collectionId: ID!, products: [ID]!): CollectionRemoveProducts + collectionBulkPublish( + ids: [ID]! + isPublished: Boolean! + ): CollectionBulkPublish + collectionRemoveProducts( + collectionId: ID! + products: [ID]! + ): CollectionRemoveProducts collectionUpdate(id: ID!, input: CollectionInput!): CollectionUpdate - collectionTranslate(id: ID!, input: TranslationInput!, languageCode: LanguageCodeEnum!): CollectionTranslate - collectionUpdateMetadata(id: ID!, input: MetaInput!): CollectionUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - collectionClearMetadata(id: ID!, input: MetaPath!): CollectionClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - collectionUpdatePrivateMetadata(id: ID!, input: MetaInput!): CollectionUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - collectionClearPrivateMetadata(id: ID!, input: MetaPath!): CollectionClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") + collectionTranslate( + id: ID! + input: TranslationInput! + languageCode: LanguageCodeEnum! + ): CollectionTranslate + collectionUpdateMetadata(id: ID!, input: MetaInput!): CollectionUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + collectionClearMetadata(id: ID!, input: MetaPath!): CollectionClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + collectionUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): CollectionUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + collectionClearPrivateMetadata( + id: ID! + input: MetaPath! + ): CollectionClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) productCreate(input: ProductCreateInput!): ProductCreate productDelete(id: ID!): ProductDelete productBulkDelete(ids: [ID]!): ProductBulkDelete productBulkPublish(ids: [ID]!, isPublished: Boolean!): ProductBulkPublish productUpdate(id: ID!, input: ProductInput!): ProductUpdate - productTranslate(id: ID!, input: TranslationInput!, languageCode: LanguageCodeEnum!): ProductTranslate - productUpdateMetadata(id: ID!, input: MetaInput!): ProductUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productClearMetadata(id: ID!, input: MetaPath!): ProductClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - productUpdatePrivateMetadata(id: ID!, input: MetaInput!): ProductUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productClearPrivateMetadata(id: ID!, input: MetaPath!): ProductClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") + productTranslate( + id: ID! + input: TranslationInput! + languageCode: LanguageCodeEnum! + ): ProductTranslate + productUpdateMetadata(id: ID!, input: MetaInput!): ProductUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productClearMetadata(id: ID!, input: MetaPath!): ProductClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): ProductUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productClearPrivateMetadata( + id: ID! + input: MetaPath! + ): ProductClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) productImageCreate(input: ProductImageCreateInput!): ProductImageCreate productImageDelete(id: ID!): ProductImageDelete productImageBulkDelete(ids: [ID]!): ProductImageBulkDelete productImageReorder(imagesIds: [ID]!, productId: ID!): ProductImageReorder - productImageUpdate(id: ID!, input: ProductImageUpdateInput!): ProductImageUpdate + productImageUpdate( + id: ID! + input: ProductImageUpdateInput! + ): ProductImageUpdate productTypeCreate(input: ProductTypeInput!): ProductTypeCreate productTypeDelete(id: ID!): ProductTypeDelete productTypeBulkDelete(ids: [ID]!): ProductTypeBulkDelete productTypeUpdate(id: ID!, input: ProductTypeInput!): ProductTypeUpdate - productTypeReorderAttributes(moves: [ReorderInput]!, productTypeId: ID!, type: AttributeTypeEnum!): ProductTypeReorderAttributes - productTypeUpdateMetadata(id: ID!, input: MetaInput!): ProductTypeUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productTypeClearMetadata(id: ID!, input: MetaPath!): ProductTypeClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - productTypeUpdatePrivateMetadata(id: ID!, input: MetaInput!): ProductTypeUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productTypeClearPrivateMetadata(id: ID!, input: MetaPath!): ProductTypeClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - digitalContentCreate(input: DigitalContentUploadInput!, variantId: ID!): DigitalContentCreate + productTypeReorderAttributes( + moves: [ReorderInput]! + productTypeId: ID! + type: AttributeTypeEnum! + ): ProductTypeReorderAttributes + productTypeUpdateMetadata(id: ID!, input: MetaInput!): ProductTypeUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productTypeClearMetadata(id: ID!, input: MetaPath!): ProductTypeClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productTypeUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): ProductTypeUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productTypeClearPrivateMetadata( + id: ID! + input: MetaPath! + ): ProductTypeClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + digitalContentCreate( + input: DigitalContentUploadInput! + variantId: ID! + ): DigitalContentCreate digitalContentDelete(variantId: ID!): DigitalContentDelete - digitalContentUpdate(input: DigitalContentInput!, variantId: ID!): DigitalContentUpdate - digitalContentUrlCreate(input: DigitalContentUrlCreateInput!): DigitalContentUrlCreate + digitalContentUpdate( + input: DigitalContentInput! + variantId: ID! + ): DigitalContentUpdate + digitalContentUrlCreate( + input: DigitalContentUrlCreateInput! + ): DigitalContentUrlCreate productVariantCreate(input: ProductVariantCreateInput!): ProductVariantCreate productVariantDelete(id: ID!): ProductVariantDelete - productVariantBulkCreate(product: ID!, variants: [ProductVariantBulkCreateInput]!): ProductVariantBulkCreate + productVariantBulkCreate( + product: ID! + variants: [ProductVariantBulkCreateInput]! + ): ProductVariantBulkCreate productVariantBulkDelete(ids: [ID]!): ProductVariantBulkDelete - productVariantStocksCreate(stocks: [StockInput!]!, variantId: ID!): ProductVariantStocksCreate - productVariantStocksDelete(variantId: ID!, warehouseIds: [ID!]): ProductVariantStocksDelete - productVariantStocksUpdate(stocks: [StockInput!]!, variantId: ID!): ProductVariantStocksUpdate - productVariantUpdate(id: ID!, input: ProductVariantInput!): ProductVariantUpdate - productVariantTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): ProductVariantTranslate - productVariantUpdateMetadata(id: ID!, input: MetaInput!): ProductVariantUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productVariantClearMetadata(id: ID!, input: MetaPath!): ProductVariantClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - productVariantUpdatePrivateMetadata(id: ID!, input: MetaInput!): ProductVariantUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - productVariantClearPrivateMetadata(id: ID!, input: MetaPath!): ProductVariantClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") + productVariantStocksCreate( + stocks: [StockInput!]! + variantId: ID! + ): ProductVariantStocksCreate + productVariantStocksDelete( + variantId: ID! + warehouseIds: [ID!] + ): ProductVariantStocksDelete + productVariantStocksUpdate( + stocks: [StockInput!]! + variantId: ID! + ): ProductVariantStocksUpdate + productVariantUpdate( + id: ID! + input: ProductVariantInput! + ): ProductVariantUpdate + productVariantTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): ProductVariantTranslate + productVariantUpdateMetadata( + id: ID! + input: MetaInput! + ): ProductVariantUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productVariantClearMetadata( + id: ID! + input: MetaPath! + ): ProductVariantClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productVariantUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): ProductVariantUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + productVariantClearPrivateMetadata( + id: ID! + input: MetaPath! + ): ProductVariantClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) variantImageAssign(imageId: ID!, variantId: ID!): VariantImageAssign variantImageUnassign(imageId: ID!, variantId: ID!): VariantImageUnassign paymentCapture(amount: Decimal, paymentId: ID!): PaymentCapture @@ -2482,40 +3278,89 @@ type Mutation { pageBulkDelete(ids: [ID]!): PageBulkDelete pageBulkPublish(ids: [ID]!, isPublished: Boolean!): PageBulkPublish pageUpdate(id: ID!, input: PageInput!): PageUpdate - pageTranslate(id: ID!, input: PageTranslationInput!, languageCode: LanguageCodeEnum!): PageTranslate + pageTranslate( + id: ID! + input: PageTranslationInput! + languageCode: LanguageCodeEnum! + ): PageTranslate draftOrderComplete(id: ID!): DraftOrderComplete draftOrderCreate(input: DraftOrderCreateInput!): DraftOrderCreate draftOrderDelete(id: ID!): DraftOrderDelete draftOrderBulkDelete(ids: [ID]!): DraftOrderBulkDelete draftOrderLinesBulkDelete(ids: [ID]!): DraftOrderLinesBulkDelete - draftOrderLinesCreate(id: ID!, input: [OrderLineCreateInput]!): DraftOrderLinesCreate + draftOrderLinesCreate( + id: ID! + input: [OrderLineCreateInput]! + ): DraftOrderLinesCreate draftOrderLineDelete(id: ID!): DraftOrderLineDelete draftOrderLineUpdate(id: ID!, input: OrderLineInput!): DraftOrderLineUpdate draftOrderUpdate(id: ID!, input: DraftOrderInput!): DraftOrderUpdate orderAddNote(order: ID!, input: OrderAddNoteInput!): OrderAddNote orderCancel(id: ID!): OrderCancel orderCapture(amount: Decimal!, id: ID!): OrderCapture - orderClearPrivateMeta(id: ID!, input: MetaPath!): OrderClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderClearMeta(input: MetaPath!, token: UUID!): OrderClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") + orderClearPrivateMeta(id: ID!, input: MetaPath!): OrderClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderClearMeta(input: MetaPath!, token: UUID!): OrderClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) orderFulfill(input: OrderFulfillInput!, order: ID): OrderFulfill - orderFulfillmentCancel(id: ID!, input: FulfillmentCancelInput!): FulfillmentCancel - orderFulfillmentUpdateTracking(id: ID!, input: FulfillmentUpdateTrackingInput!): FulfillmentUpdateTracking - orderFulfillmentClearMeta(id: ID!, input: MetaPath!): FulfillmentClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderFulfillmentClearPrivateMeta(id: ID!, input: MetaPath!): FulfillmentClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderFulfillmentUpdateMeta(id: ID!, input: MetaInput!): FulfillmentUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderFulfillmentUpdatePrivateMeta(id: ID!, input: MetaInput!): FulfillmentUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") + orderFulfillmentCancel( + id: ID! + input: FulfillmentCancelInput! + ): FulfillmentCancel + orderFulfillmentUpdateTracking( + id: ID! + input: FulfillmentUpdateTrackingInput! + ): FulfillmentUpdateTracking + orderFulfillmentClearMeta(id: ID!, input: MetaPath!): FulfillmentClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderFulfillmentClearPrivateMeta( + id: ID! + input: MetaPath! + ): FulfillmentClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderFulfillmentUpdateMeta(id: ID!, input: MetaInput!): FulfillmentUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderFulfillmentUpdatePrivateMeta( + id: ID! + input: MetaInput! + ): FulfillmentUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) orderMarkAsPaid(id: ID!): OrderMarkAsPaid orderRefund(amount: Decimal!, id: ID!): OrderRefund orderUpdate(id: ID!, input: OrderUpdateInput!): OrderUpdate - orderUpdateMeta(input: MetaInput!, token: UUID!): OrderUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderUpdatePrivateMeta(id: ID!, input: MetaInput!): OrderUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31.") - orderUpdateShipping(order: ID!, input: OrderUpdateShippingInput): OrderUpdateShipping + orderUpdateMeta(input: MetaInput!, token: UUID!): OrderUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderUpdatePrivateMeta(id: ID!, input: MetaInput!): OrderUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation instead. This field will be removed after 2020-07-31." + ) + orderUpdateShipping( + order: ID! + input: OrderUpdateShippingInput + ): OrderUpdateShipping orderVoid(id: ID!): OrderVoid orderBulkCancel(ids: [ID]!): OrderBulkCancel deleteMetadata(id: ID!, keys: [String!]!): DeleteMetadata deletePrivateMetadata(id: ID!, keys: [String!]!): DeletePrivateMetadata updateMetadata(id: ID!, input: [MetadataInput!]!): UpdateMetadata - updatePrivateMetadata(id: ID!, input: [MetadataInput!]!): UpdatePrivateMetadata + updatePrivateMetadata( + id: ID! + input: [MetadataInput!]! + ): UpdatePrivateMetadata assignNavigation(menu: ID, navigationType: NavigationType!): AssignNavigation menuCreate(input: MenuCreateInput!): MenuCreate menuDelete(id: ID!): MenuDelete @@ -2525,7 +3370,11 @@ type Mutation { menuItemDelete(id: ID!): MenuItemDelete menuItemBulkDelete(ids: [ID]!): MenuItemBulkDelete menuItemUpdate(id: ID!, input: MenuItemInput!): MenuItemUpdate - menuItemTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): MenuItemTranslate + menuItemTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): MenuItemTranslate menuItemMove(menu: ID!, moves: [MenuItemMoveInput]!): MenuItemMove invoiceRequest(number: String, orderId: ID!): InvoiceRequest invoiceRequestDelete(id: ID!): InvoiceRequestDelete @@ -2544,32 +3393,92 @@ type Mutation { saleUpdate(id: ID!, input: SaleInput!): SaleUpdate saleCataloguesAdd(id: ID!, input: CatalogueInput!): SaleAddCatalogues saleCataloguesRemove(id: ID!, input: CatalogueInput!): SaleRemoveCatalogues - saleTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): SaleTranslate + saleTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): SaleTranslate voucherCreate(input: VoucherInput!): VoucherCreate voucherDelete(id: ID!): VoucherDelete voucherBulkDelete(ids: [ID]!): VoucherBulkDelete voucherUpdate(id: ID!, input: VoucherInput!): VoucherUpdate voucherCataloguesAdd(id: ID!, input: CatalogueInput!): VoucherAddCatalogues - voucherCataloguesRemove(id: ID!, input: CatalogueInput!): VoucherRemoveCatalogues - voucherTranslate(id: ID!, input: NameTranslationInput!, languageCode: LanguageCodeEnum!): VoucherTranslate - checkoutAddPromoCode(checkoutId: ID!, promoCode: String!): CheckoutAddPromoCode - checkoutBillingAddressUpdate(billingAddress: AddressInput!, checkoutId: ID!): CheckoutBillingAddressUpdate - checkoutComplete(checkoutId: ID!, redirectUrl: String, storeSource: Boolean = false): CheckoutComplete + voucherCataloguesRemove( + id: ID! + input: CatalogueInput! + ): VoucherRemoveCatalogues + voucherTranslate( + id: ID! + input: NameTranslationInput! + languageCode: LanguageCodeEnum! + ): VoucherTranslate + checkoutAddPromoCode( + checkoutId: ID! + promoCode: String! + ): CheckoutAddPromoCode + checkoutBillingAddressUpdate( + billingAddress: AddressInput! + checkoutId: ID! + ): CheckoutBillingAddressUpdate + checkoutComplete( + checkoutId: ID! + redirectUrl: String + storeSource: Boolean = false + ): CheckoutComplete checkoutCreate(input: CheckoutCreateInput!): CheckoutCreate - checkoutCustomerAttach(checkoutId: ID!, customerId: ID): CheckoutCustomerAttach + checkoutCustomerAttach( + checkoutId: ID! + customerId: ID + ): CheckoutCustomerAttach checkoutCustomerDetach(checkoutId: ID!): CheckoutCustomerDetach checkoutEmailUpdate(checkoutId: ID, email: String!): CheckoutEmailUpdate checkoutLineDelete(checkoutId: ID!, lineId: ID): CheckoutLineDelete - checkoutLinesAdd(checkoutId: ID!, lines: [CheckoutLineInput]!): CheckoutLinesAdd - checkoutLinesUpdate(checkoutId: ID!, lines: [CheckoutLineInput]!): CheckoutLinesUpdate - checkoutRemovePromoCode(checkoutId: ID!, promoCode: String!): CheckoutRemovePromoCode - checkoutPaymentCreate(checkoutId: ID!, input: PaymentInput!): CheckoutPaymentCreate - checkoutShippingAddressUpdate(checkoutId: ID!, shippingAddress: AddressInput!): CheckoutShippingAddressUpdate - checkoutShippingMethodUpdate(checkoutId: ID, shippingMethodId: ID!): CheckoutShippingMethodUpdate - checkoutUpdateMetadata(id: ID!, input: MetaInput!): CheckoutUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31.") - checkoutClearMetadata(id: ID!, input: MetaPath!): CheckoutClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation. This field will be removed after 2020-07-31.") - checkoutUpdatePrivateMetadata(id: ID!, input: MetaInput!): CheckoutUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation. This field will be removed after 2020-07-31.") - checkoutClearPrivateMetadata(id: ID!, input: MetaPath!): CheckoutClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation. This field will be removed after 2020-07-31.") + checkoutLinesAdd( + checkoutId: ID! + lines: [CheckoutLineInput]! + ): CheckoutLinesAdd + checkoutLinesUpdate( + checkoutId: ID! + lines: [CheckoutLineInput]! + ): CheckoutLinesUpdate + checkoutRemovePromoCode( + checkoutId: ID! + promoCode: String! + ): CheckoutRemovePromoCode + checkoutPaymentCreate( + checkoutId: ID! + input: PaymentInput! + ): CheckoutPaymentCreate + checkoutShippingAddressUpdate( + checkoutId: ID! + shippingAddress: AddressInput! + ): CheckoutShippingAddressUpdate + checkoutShippingMethodUpdate( + checkoutId: ID + shippingMethodId: ID! + ): CheckoutShippingMethodUpdate + checkoutUpdateMetadata(id: ID!, input: MetaInput!): CheckoutUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31." + ) + checkoutClearMetadata(id: ID!, input: MetaPath!): CheckoutClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation. This field will be removed after 2020-07-31." + ) + checkoutUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): CheckoutUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation. This field will be removed after 2020-07-31." + ) + checkoutClearPrivateMetadata( + id: ID! + input: MetaPath! + ): CheckoutClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation. This field will be removed after 2020-07-31." + ) appCreate(input: AppInput!): AppCreate appUpdate(id: ID!, input: AppInput!): AppUpdate appDelete(id: ID!): AppDelete @@ -2580,25 +3489,54 @@ type Mutation { tokenRefresh(csrfToken: String, refreshToken: String): RefreshToken tokenVerify(token: String!): VerifyToken tokensDeactivateAll: DeactivateAllUserTokens - requestPasswordReset(email: String!, redirectUrl: String!): RequestPasswordReset + appInstall(input: AppInstallInput!): AppInstall + appRetryInstall( + activateAfterInstallation: Boolean = true + id: ID! + ): AppRetryInstall + appDeleteFailedInstallation(id: ID!): AppDeleteFailedInstallation + appFetchManifest(manifestUrl: String!): AppFetchManifest + appActivate(id: ID!): AppActivate + appDeactivate(id: ID!): AppDeactivate + requestPasswordReset( + email: String! + redirectUrl: String! + ): RequestPasswordReset confirmAccount(email: String!, token: String!): ConfirmAccount setPassword(email: String!, password: String!, token: String!): SetPassword passwordChange(newPassword: String!, oldPassword: String!): PasswordChange - requestEmailChange(newEmail: String!, password: String!, redirectUrl: String!): RequestEmailChange + requestEmailChange( + newEmail: String! + password: String! + redirectUrl: String! + ): RequestEmailChange confirmEmailChange(token: String!): ConfirmEmailChange - accountAddressCreate(input: AddressInput!, type: AddressTypeEnum): AccountAddressCreate + accountAddressCreate( + input: AddressInput! + type: AddressTypeEnum + ): AccountAddressCreate accountAddressUpdate(id: ID!, input: AddressInput!): AccountAddressUpdate accountAddressDelete(id: ID!): AccountAddressDelete - accountSetDefaultAddress(id: ID!, type: AddressTypeEnum!): AccountSetDefaultAddress + accountSetDefaultAddress( + id: ID! + type: AddressTypeEnum! + ): AccountSetDefaultAddress accountRegister(input: AccountRegisterInput!): AccountRegister accountUpdate(input: AccountInput!): AccountUpdate accountRequestDeletion(redirectUrl: String!): AccountRequestDeletion accountDelete(token: String!): AccountDelete - accountUpdateMeta(input: MetaInput!): AccountUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31.") + accountUpdateMeta(input: MetaInput!): AccountUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31." + ) addressCreate(input: AddressInput!, userId: ID!): AddressCreate addressUpdate(id: ID!, input: AddressInput!): AddressUpdate addressDelete(id: ID!): AddressDelete - addressSetDefault(addressId: ID!, type: AddressTypeEnum!, userId: ID!): AddressSetDefault + addressSetDefault( + addressId: ID! + type: AddressTypeEnum! + userId: ID! + ): AddressSetDefault customerCreate(input: UserCreateInput!): CustomerCreate customerUpdate(id: ID!, input: CustomerInput!): CustomerUpdate customerDelete(id: ID!): CustomerDelete @@ -2610,19 +3548,68 @@ type Mutation { userAvatarUpdate(image: Upload!): UserAvatarUpdate userAvatarDelete: UserAvatarDelete userBulkSetActive(ids: [ID]!, isActive: Boolean!): UserBulkSetActive - userUpdateMetadata(id: ID!, input: MetaInput!): UserUpdateMeta @deprecated(reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31.") - userClearMetadata(id: ID!, input: MetaPath!): UserClearMeta @deprecated(reason: "Use the `deleteMetadata` mutation. This field will be removed after 2020-07-31.") - userUpdatePrivateMetadata(id: ID!, input: MetaInput!): UserUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation. This field will be removed after 2020-07-31.") - userClearPrivateMetadata(id: ID!, input: MetaPath!): UserClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation. This field will be removed after 2020-07-31.") - serviceAccountCreate(input: ServiceAccountInput!): ServiceAccountCreate @deprecated(reason: "Use the `appCreate` mutation instead. This field will be removed after 2020-07-31.") - serviceAccountUpdate(id: ID!, input: ServiceAccountInput!): ServiceAccountUpdate @deprecated(reason: "Use the `appUpdate` mutation instead. This field will be removed after 2020-07-31.") - serviceAccountDelete(id: ID!): ServiceAccountDelete @deprecated(reason: "Use the `appDelete` mutation instead. This field will be removed after 2020-07-31.") - serviceAccountUpdatePrivateMetadata(id: ID!, input: MetaInput!): ServiceAccountUpdatePrivateMeta @deprecated(reason: "Use the `updatePrivateMetadata` mutation with App instead.This field will be removed after 2020-07-31.") - serviceAccountClearPrivateMetadata(id: ID!, input: MetaPath!): ServiceAccountClearPrivateMeta @deprecated(reason: "Use the `deletePrivateMetadata` mutation with App instead.This field will be removed after 2020-07-31.") - serviceAccountTokenCreate(input: ServiceAccountTokenInput!): ServiceAccountTokenCreate @deprecated(reason: "Use the `appTokenCreate` mutation instead. This field will be removed after 2020-07-31.") - serviceAccountTokenDelete(id: ID!): ServiceAccountTokenDelete @deprecated(reason: "Use the `appTokenDelete` mutation instead. This field will be removed after 2020-07-31.") - permissionGroupCreate(input: PermissionGroupCreateInput!): PermissionGroupCreate - permissionGroupUpdate(id: ID!, input: PermissionGroupUpdateInput!): PermissionGroupUpdate + userUpdateMetadata(id: ID!, input: MetaInput!): UserUpdateMeta + @deprecated( + reason: "Use the `updateMetadata` mutation. This field will be removed after 2020-07-31." + ) + userClearMetadata(id: ID!, input: MetaPath!): UserClearMeta + @deprecated( + reason: "Use the `deleteMetadata` mutation. This field will be removed after 2020-07-31." + ) + userUpdatePrivateMetadata(id: ID!, input: MetaInput!): UserUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation. This field will be removed after 2020-07-31." + ) + userClearPrivateMetadata(id: ID!, input: MetaPath!): UserClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation. This field will be removed after 2020-07-31." + ) + serviceAccountCreate(input: ServiceAccountInput!): ServiceAccountCreate + @deprecated( + reason: "Use the `appCreate` mutation instead. This field will be removed after 2020-07-31." + ) + serviceAccountUpdate( + id: ID! + input: ServiceAccountInput! + ): ServiceAccountUpdate + @deprecated( + reason: "Use the `appUpdate` mutation instead. This field will be removed after 2020-07-31." + ) + serviceAccountDelete(id: ID!): ServiceAccountDelete + @deprecated( + reason: "Use the `appDelete` mutation instead. This field will be removed after 2020-07-31." + ) + serviceAccountUpdatePrivateMetadata( + id: ID! + input: MetaInput! + ): ServiceAccountUpdatePrivateMeta + @deprecated( + reason: "Use the `updatePrivateMetadata` mutation with App instead.This field will be removed after 2020-07-31." + ) + serviceAccountClearPrivateMetadata( + id: ID! + input: MetaPath! + ): ServiceAccountClearPrivateMeta + @deprecated( + reason: "Use the `deletePrivateMetadata` mutation with App instead.This field will be removed after 2020-07-31." + ) + serviceAccountTokenCreate( + input: ServiceAccountTokenInput! + ): ServiceAccountTokenCreate + @deprecated( + reason: "Use the `appTokenCreate` mutation instead. This field will be removed after 2020-07-31." + ) + serviceAccountTokenDelete(id: ID!): ServiceAccountTokenDelete + @deprecated( + reason: "Use the `appTokenDelete` mutation instead. This field will be removed after 2020-07-31." + ) + permissionGroupCreate( + input: PermissionGroupCreateInput! + ): PermissionGroupCreate + permissionGroupUpdate( + id: ID! + input: PermissionGroupUpdateInput! + ): PermissionGroupUpdate permissionGroupDelete(id: ID!): PermissionGroupDelete } @@ -2647,8 +3634,14 @@ interface Node { interface ObjectWithMetadata { privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) } type Order implements Node & ObjectWithMetadata { @@ -2674,8 +3667,14 @@ type Order implements Node & ObjectWithMetadata { weight: Weight privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) fulfillments: [Fulfillment]! lines: [OrderLine]! actions: [OrderAction]! @@ -2706,7 +3705,10 @@ enum OrderAction { } type OrderAddNote { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order event: OrderEvent orderErrors: [OrderError!]! @@ -2717,30 +3719,45 @@ input OrderAddNoteInput { } type OrderBulkCancel { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! orderErrors: [OrderError!]! } type OrderCancel { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } type OrderCapture { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } type OrderClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order } type OrderClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order } @@ -2885,7 +3902,10 @@ input OrderFilterInput { } type OrderFulfill { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) fulfillments: [Fulfillment] order: Order orderErrors: [OrderError!]! @@ -2933,13 +3953,19 @@ input OrderLineInput { } type OrderMarkAsPaid { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } type OrderRefund { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } @@ -2976,7 +4002,10 @@ enum OrderStatusFilter { } type OrderUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) orderErrors: [OrderError!]! order: Order } @@ -2988,17 +4017,26 @@ input OrderUpdateInput { } type OrderUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order } type OrderUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order } type OrderUpdateShipping { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } @@ -3008,7 +4046,10 @@ input OrderUpdateShippingInput { } type OrderVoid { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) order: Order orderErrors: [OrderError!]! } @@ -3028,13 +4069,19 @@ type Page implements Node { } type PageBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! pageErrors: [PageError!]! } type PageBulkPublish { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! pageErrors: [PageError!]! } @@ -3051,13 +4098,19 @@ type PageCountableEdge { } type PageCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) pageErrors: [PageError!]! page: Page } type PageDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) pageErrors: [PageError!]! page: Page } @@ -3122,7 +4175,10 @@ type PageTranslatableContent implements Node { } type PageTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! page: PageTranslatableContent } @@ -3146,13 +4202,19 @@ input PageTranslationInput { } type PageUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) pageErrors: [PageError!]! page: Page } type PasswordChange { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } @@ -3181,7 +4243,10 @@ type Payment implements Node { } type PaymentCapture { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) payment: Payment paymentErrors: [PaymentError!]! } @@ -3241,13 +4306,19 @@ input PaymentInput { } type PaymentRefund { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) payment: Payment paymentErrors: [PaymentError!]! } type PaymentSecureConfirm { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) payment: Payment paymentErrors: [PaymentError!]! } @@ -3258,7 +4329,10 @@ type PaymentSource { } type PaymentVoid { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) payment: Payment paymentErrors: [PaymentError!]! } @@ -3283,12 +4357,14 @@ enum PermissionEnum { MANAGE_SHIPPING MANAGE_SETTINGS MANAGE_TRANSLATIONS - MANAGE_WEBHOOKS MANAGE_CHECKOUTS } type PermissionGroupCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) permissionGroupErrors: [PermissionGroupError!]! group: Group } @@ -3300,7 +4376,10 @@ input PermissionGroupCreateInput { } type PermissionGroupDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) permissionGroupErrors: [PermissionGroupError!]! group: Group } @@ -3338,7 +4417,10 @@ input PermissionGroupSortingInput { } type PermissionGroupUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) permissionGroupErrors: [PermissionGroupError!]! group: Group } @@ -3401,7 +4483,10 @@ input PluginSortingInput { } type PluginUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) plugin: Plugin pluginsErrors: [PluginError!]! } @@ -3433,9 +4518,16 @@ type Product implements Node & ObjectWithMetadata { weight: Weight privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - url: String! @deprecated(reason: "This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + url: String! + @deprecated(reason: "This field will be removed after 2020-07-31.") thumbnail(size: Int): Image pricing: ProductPricingInfo isAvailable: Boolean @@ -3459,25 +4551,37 @@ type ProductAttributeError { } type ProductBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type ProductBulkPublish { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type ProductClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } type ProductClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } @@ -3494,7 +4598,10 @@ type ProductCountableEdge { } type ProductCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } @@ -3521,7 +4628,10 @@ input ProductCreateInput { } type ProductDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } @@ -3570,13 +4680,19 @@ type ProductImage implements Node { } type ProductImageBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type ProductImageCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) product: Product image: ProductImage productErrors: [ProductError!]! @@ -3589,21 +4705,30 @@ input ProductImageCreateInput { } type ProductImageDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) product: Product image: ProductImage productErrors: [ProductError!]! } type ProductImageReorder { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) product: Product images: [ProductImage] productErrors: [ProductError!]! } type ProductImageUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) product: Product image: ProductImage productErrors: [ProductError!]! @@ -3673,7 +4798,10 @@ type ProductTranslatableContent implements Node { } type ProductTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! product: Product } @@ -3698,30 +4826,56 @@ type ProductType implements Node & ObjectWithMetadata { weight: Weight privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + products( + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection taxRate: TaxRateType taxType: TaxType variantAttributes: [Attribute] productAttributes: [Attribute] - availableAttributes(filter: AttributeFilterInput, before: String, after: String, first: Int, last: Int): AttributeCountableConnection + availableAttributes( + filter: AttributeFilterInput + before: String + after: String + first: Int + last: Int + ): AttributeCountableConnection } type ProductTypeBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type ProductTypeClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } type ProductTypeClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } @@ -3743,13 +4897,19 @@ type ProductTypeCountableEdge { } type ProductTypeCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } type ProductTypeDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } @@ -3779,7 +4939,10 @@ input ProductTypeInput { } type ProductTypeReorderAttributes { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productType: ProductType productErrors: [ProductError!]! } @@ -3796,37 +4959,55 @@ input ProductTypeSortingInput { } type ProductTypeUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } type ProductTypeUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } type ProductTypeUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productType: ProductType } type ProductUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } type ProductUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } type ProductUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! product: Product } @@ -3840,14 +5021,32 @@ type ProductVariant implements Node & ObjectWithMetadata { weight: Weight privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") - quantity: Int! @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") - quantityAllocated: Int @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") - stockQuantity: Int! @deprecated(reason: "Use the quantityAvailable field instead. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) + quantity: Int! + @deprecated( + reason: "Use the stock field instead. This field will be removed after 2020-07-31." + ) + quantityAllocated: Int + @deprecated( + reason: "Use the stock field instead. This field will be removed after 2020-07-31." + ) + stockQuantity: Int! + @deprecated( + reason: "Use the quantityAvailable field instead. This field will be removed after 2020-07-31." + ) price: Money pricing: VariantPricingInfo - isAvailable: Boolean @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.") + isAvailable: Boolean + @deprecated( + reason: "Use the stock field instead. This field will be removed after 2020-07-31." + ) attributes: [SelectedAttribute!]! costPrice: Money margin: Int @@ -3861,7 +5060,10 @@ type ProductVariant implements Node & ObjectWithMetadata { } type ProductVariantBulkCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productVariants: [ProductVariant!]! bulkProductErrors: [BulkProductError!]! @@ -3878,19 +5080,28 @@ input ProductVariantBulkCreateInput { } type ProductVariantBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! productErrors: [ProductError!]! } type ProductVariantClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } type ProductVariantClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } @@ -3907,7 +5118,10 @@ type ProductVariantCountableEdge { } type ProductVariantCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } @@ -3924,7 +5138,10 @@ input ProductVariantCreateInput { } type ProductVariantDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } @@ -3939,19 +5156,28 @@ input ProductVariantInput { } type ProductVariantStocksCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productVariant: ProductVariant bulkStockErrors: [BulkStockError!]! } type ProductVariantStocksDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productVariant: ProductVariant stockErrors: [StockError!]! } type ProductVariantStocksUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productVariant: ProductVariant bulkStockErrors: [BulkStockError!]! } @@ -3964,7 +5190,10 @@ type ProductVariantTranslatableContent implements Node { } type ProductVariantTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! productVariant: ProductVariant } @@ -3976,90 +5205,320 @@ type ProductVariantTranslation implements Node { } type ProductVariantUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } type ProductVariantUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } type ProductVariantUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productErrors: [ProductError!]! productVariant: ProductVariant } type Query { webhook(id: ID!): Webhook - webhooks(sortBy: WebhookSortingInput, filter: WebhookFilterInput, before: String, after: String, first: Int, last: Int): WebhookCountableConnection @deprecated(reason: "Use webhooks field on app(s) query instead. This field will be removed after 2020-07-31.") + webhooks( + sortBy: WebhookSortingInput + filter: WebhookFilterInput + before: String + after: String + first: Int + last: Int + ): WebhookCountableConnection + @deprecated( + reason: "Use webhooks field on app(s) query instead. This field will be removed after 2020-07-31." + ) webhookEvents: [WebhookEvent] webhookSamplePayload(eventType: WebhookSampleEventTypeEnum!): JSONString warehouse(id: ID!): Warehouse - warehouses(filter: WarehouseFilterInput, sortBy: WarehouseSortingInput, before: String, after: String, first: Int, last: Int): WarehouseCountableConnection - translations(kind: TranslatableKinds!, before: String, after: String, first: Int, last: Int): TranslatableItemConnection + warehouses( + filter: WarehouseFilterInput + sortBy: WarehouseSortingInput + before: String + after: String + first: Int + last: Int + ): WarehouseCountableConnection + translations( + kind: TranslatableKinds! + before: String + after: String + first: Int + last: Int + ): TranslatableItemConnection translation(id: ID!, kind: TranslatableKinds!): TranslatableItem stock(id: ID!): Stock - stocks(filter: StockFilterInput, before: String, after: String, first: Int, last: Int): StockCountableConnection + stocks( + filter: StockFilterInput + before: String + after: String + first: Int + last: Int + ): StockCountableConnection shop: Shop! shippingZone(id: ID!): ShippingZone - shippingZones(before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection + shippingZones( + before: String + after: String + first: Int + last: Int + ): ShippingZoneCountableConnection digitalContent(id: ID!): DigitalContent - digitalContents(before: String, after: String, first: Int, last: Int): DigitalContentCountableConnection - attributes(filter: AttributeFilterInput, sortBy: AttributeSortingInput, before: String, after: String, first: Int, last: Int): AttributeCountableConnection + digitalContents( + before: String + after: String + first: Int + last: Int + ): DigitalContentCountableConnection + attributes( + filter: AttributeFilterInput + sortBy: AttributeSortingInput + before: String + after: String + first: Int + last: Int + ): AttributeCountableConnection attribute(id: ID!): Attribute - categories(filter: CategoryFilterInput, sortBy: CategorySortingInput, level: Int, before: String, after: String, first: Int, last: Int): CategoryCountableConnection + categories( + filter: CategoryFilterInput + sortBy: CategorySortingInput + level: Int + before: String + after: String + first: Int + last: Int + ): CategoryCountableConnection category(id: ID, slug: String): Category collection(id: ID, slug: String): Collection - collections(filter: CollectionFilterInput, sortBy: CollectionSortingInput, before: String, after: String, first: Int, last: Int): CollectionCountableConnection + collections( + filter: CollectionFilterInput + sortBy: CollectionSortingInput + before: String + after: String + first: Int + last: Int + ): CollectionCountableConnection product(id: ID, slug: String): Product - products(filter: ProductFilterInput, sortBy: ProductOrder, stockAvailability: StockAvailability, before: String, after: String, first: Int, last: Int): ProductCountableConnection + products( + filter: ProductFilterInput + sortBy: ProductOrder + stockAvailability: StockAvailability + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection productType(id: ID!): ProductType - productTypes(filter: ProductTypeFilterInput, sortBy: ProductTypeSortingInput, before: String, after: String, first: Int, last: Int): ProductTypeCountableConnection + productTypes( + filter: ProductTypeFilterInput + sortBy: ProductTypeSortingInput + before: String + after: String + first: Int + last: Int + ): ProductTypeCountableConnection productVariant(id: ID!): ProductVariant - productVariants(ids: [ID], before: String, after: String, first: Int, last: Int): ProductVariantCountableConnection - reportProductSales(period: ReportingPeriod!, before: String, after: String, first: Int, last: Int): ProductVariantCountableConnection + productVariants( + ids: [ID] + before: String + after: String + first: Int + last: Int + ): ProductVariantCountableConnection + reportProductSales( + period: ReportingPeriod! + before: String + after: String + first: Int + last: Int + ): ProductVariantCountableConnection payment(id: ID!): Payment - payments(before: String, after: String, first: Int, last: Int): PaymentCountableConnection + payments( + before: String + after: String + first: Int + last: Int + ): PaymentCountableConnection page(id: ID, slug: String): Page - pages(sortBy: PageSortingInput, filter: PageFilterInput, before: String, after: String, first: Int, last: Int): PageCountableConnection - homepageEvents(before: String, after: String, first: Int, last: Int): OrderEventCountableConnection + pages( + sortBy: PageSortingInput + filter: PageFilterInput + before: String + after: String + first: Int + last: Int + ): PageCountableConnection + homepageEvents( + before: String + after: String + first: Int + last: Int + ): OrderEventCountableConnection order(id: ID!): Order - orders(sortBy: OrderSortingInput, filter: OrderFilterInput, created: ReportingPeriod, status: OrderStatusFilter, before: String, after: String, first: Int, last: Int): OrderCountableConnection - draftOrders(sortBy: OrderSortingInput, filter: OrderDraftFilterInput, created: ReportingPeriod, before: String, after: String, first: Int, last: Int): OrderCountableConnection + orders( + sortBy: OrderSortingInput + filter: OrderFilterInput + created: ReportingPeriod + status: OrderStatusFilter + before: String + after: String + first: Int + last: Int + ): OrderCountableConnection + draftOrders( + sortBy: OrderSortingInput + filter: OrderDraftFilterInput + created: ReportingPeriod + before: String + after: String + first: Int + last: Int + ): OrderCountableConnection ordersTotal(period: ReportingPeriod): TaxedMoney orderByToken(token: UUID!): Order menu(id: ID, name: String): Menu - menus(sortBy: MenuSortingInput, filter: MenuFilterInput, before: String, after: String, first: Int, last: Int): MenuCountableConnection + menus( + sortBy: MenuSortingInput + filter: MenuFilterInput + before: String + after: String + first: Int + last: Int + ): MenuCountableConnection menuItem(id: ID!): MenuItem - menuItems(sortBy: MenuItemSortingInput, filter: MenuItemFilterInput, before: String, after: String, first: Int, last: Int): MenuItemCountableConnection + menuItems( + sortBy: MenuItemSortingInput + filter: MenuItemFilterInput + before: String + after: String + first: Int + last: Int + ): MenuItemCountableConnection giftCard(id: ID!): GiftCard - giftCards(before: String, after: String, first: Int, last: Int): GiftCardCountableConnection + giftCards( + before: String + after: String + first: Int + last: Int + ): GiftCardCountableConnection plugin(id: ID!): Plugin - plugins(filter: PluginFilterInput, sortBy: PluginSortingInput, before: String, after: String, first: Int, last: Int): PluginCountableConnection + plugins( + filter: PluginFilterInput + sortBy: PluginSortingInput + before: String + after: String + first: Int + last: Int + ): PluginCountableConnection sale(id: ID!): Sale - sales(filter: SaleFilterInput, sortBy: SaleSortingInput, query: String, before: String, after: String, first: Int, last: Int): SaleCountableConnection + sales( + filter: SaleFilterInput + sortBy: SaleSortingInput + query: String + before: String + after: String + first: Int + last: Int + ): SaleCountableConnection voucher(id: ID!): Voucher - vouchers(filter: VoucherFilterInput, sortBy: VoucherSortingInput, query: String, before: String, after: String, first: Int, last: Int): VoucherCountableConnection + vouchers( + filter: VoucherFilterInput + sortBy: VoucherSortingInput + query: String + before: String + after: String + first: Int + last: Int + ): VoucherCountableConnection taxTypes: [TaxType] checkout(token: UUID): Checkout - checkouts(before: String, after: String, first: Int, last: Int): CheckoutCountableConnection + checkouts( + before: String + after: String + first: Int + last: Int + ): CheckoutCountableConnection checkoutLine(id: ID): CheckoutLine - checkoutLines(before: String, after: String, first: Int, last: Int): CheckoutLineCountableConnection - apps(filter: AppFilterInput, sortBy: AppSortingInput, before: String, after: String, first: Int, last: Int): AppCountableConnection + checkoutLines( + before: String + after: String + first: Int + last: Int + ): CheckoutLineCountableConnection + appsInstallations: [AppInstallation!]! + apps( + filter: AppFilterInput + sortBy: AppSortingInput + before: String + after: String + first: Int + last: Int + ): AppCountableConnection app(id: ID!): App - addressValidationRules(countryCode: CountryCode!, countryArea: String, city: String, cityArea: String): AddressValidationData + addressValidationRules( + countryCode: CountryCode! + countryArea: String + city: String + cityArea: String + ): AddressValidationData address(id: ID!): Address - customers(filter: CustomerFilterInput, sortBy: UserSortingInput, before: String, after: String, first: Int, last: Int): UserCountableConnection - permissionGroups(filter: PermissionGroupFilterInput, sortBy: PermissionGroupSortingInput, before: String, after: String, first: Int, last: Int): GroupCountableConnection + customers( + filter: CustomerFilterInput + sortBy: UserSortingInput + before: String + after: String + first: Int + last: Int + ): UserCountableConnection + permissionGroups( + filter: PermissionGroupFilterInput + sortBy: PermissionGroupSortingInput + before: String + after: String + first: Int + last: Int + ): GroupCountableConnection permissionGroup(id: ID!): Group me: User - staffUsers(filter: StaffUserInput, sortBy: UserSortingInput, before: String, after: String, first: Int, last: Int): UserCountableConnection - serviceAccounts(filter: ServiceAccountFilterInput, sortBy: ServiceAccountSortingInput, before: String, after: String, first: Int, last: Int): ServiceAccountCountableConnection @deprecated(reason: "Use the `apps` query instead. This field will be removed after 2020-07-31.") - serviceAccount(id: ID!): ServiceAccount @deprecated(reason: "Use the `app` query instead. This field will be removed after 2020-07-31.") + staffUsers( + filter: StaffUserInput + sortBy: UserSortingInput + before: String + after: String + first: Int + last: Int + ): UserCountableConnection + serviceAccounts( + filter: ServiceAccountFilterInput + sortBy: ServiceAccountSortingInput + before: String + after: String + first: Int + last: Int + ): ServiceAccountCountableConnection + @deprecated( + reason: "Use the `apps` query instead. This field will be removed after 2020-07-31." + ) + serviceAccount(id: ID!): ServiceAccount + @deprecated( + reason: "Use the `app` query instead. This field will be removed after 2020-07-31." + ) user(id: ID!): User _entities(representations: [_Any]): [_Entity] _service: _Service @@ -4071,7 +5530,10 @@ type ReducedRate { } type RefreshToken { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) token: String user: User accountErrors: [AccountError!]! @@ -4088,13 +5550,19 @@ enum ReportingPeriod { } type RequestEmailChange { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } type RequestPasswordReset { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! } @@ -4105,20 +5573,41 @@ type Sale implements Node { value: Float! startDate: DateTime! endDate: DateTime - categories(before: String, after: String, first: Int, last: Int): CategoryCountableConnection - collections(before: String, after: String, first: Int, last: Int): CollectionCountableConnection - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection + categories( + before: String + after: String + first: Int + last: Int + ): CategoryCountableConnection + collections( + before: String + after: String + first: Int + last: Int + ): CollectionCountableConnection + products( + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection translation(languageCode: LanguageCodeEnum!): SaleTranslation } type SaleAddCatalogues { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) sale: Sale discountErrors: [DiscountError!]! } type SaleBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! discountErrors: [DiscountError!]! } @@ -4135,13 +5624,19 @@ type SaleCountableEdge { } type SaleCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! sale: Sale } type SaleDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! sale: Sale } @@ -4165,7 +5660,10 @@ input SaleInput { } type SaleRemoveCatalogues { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) sale: Sale discountErrors: [DiscountError!]! } @@ -4191,7 +5689,10 @@ type SaleTranslatableContent implements Node { } type SaleTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! sale: Sale } @@ -4208,7 +5709,10 @@ enum SaleType { } type SaleUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! sale: Sale } @@ -4232,12 +5736,21 @@ type ServiceAccount implements Node & ObjectWithMetadata { tokens: [ServiceAccountToken] privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) } type ServiceAccountClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! serviceAccount: ServiceAccount } @@ -4254,14 +5767,20 @@ type ServiceAccountCountableEdge { } type ServiceAccountCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authToken: String accountErrors: [AccountError!]! serviceAccount: ServiceAccount } type ServiceAccountDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! serviceAccount: ServiceAccount } @@ -4294,14 +5813,20 @@ type ServiceAccountToken implements Node { } type ServiceAccountTokenCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) authToken: String accountErrors: [AccountError!]! serviceAccountToken: ServiceAccountToken } type ServiceAccountTokenDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! serviceAccountToken: ServiceAccountToken } @@ -4312,19 +5837,28 @@ input ServiceAccountTokenInput { } type ServiceAccountUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! serviceAccount: ServiceAccount } type ServiceAccountUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! serviceAccount: ServiceAccount } type SetPassword { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) token: String refreshToken: String csrfToken: String @@ -4381,20 +5915,29 @@ enum ShippingMethodTypeEnum { } type ShippingPriceBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! shippingErrors: [ShippingError!]! } type ShippingPriceCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingZone: ShippingZone shippingErrors: [ShippingError!]! shippingMethod: ShippingMethod } type ShippingPriceDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingMethod: ShippingMethod shippingZone: ShippingZone shippingErrors: [ShippingError!]! @@ -4412,13 +5955,19 @@ input ShippingPriceInput { } type ShippingPriceTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! shippingMethod: ShippingMethod } type ShippingPriceUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingZone: ShippingZone shippingErrors: [ShippingError!]! shippingMethod: ShippingMethod @@ -4435,7 +5984,10 @@ type ShippingZone implements Node { } type ShippingZoneBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! shippingErrors: [ShippingError!]! } @@ -4452,7 +6004,10 @@ type ShippingZoneCountableEdge { } type ShippingZoneCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingErrors: [ShippingError!]! shippingZone: ShippingZone } @@ -4465,13 +6020,19 @@ input ShippingZoneCreateInput { } type ShippingZoneDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingErrors: [ShippingError!]! shippingZone: ShippingZone } type ShippingZoneUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shippingErrors: [ShippingError!]! shippingZone: ShippingZone } @@ -4518,13 +6079,19 @@ type Shop { } type ShopAddressUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop shopErrors: [ShopError!]! } type ShopDomainUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop shopErrors: [ShopError!]! } @@ -4546,7 +6113,10 @@ enum ShopErrorCode { } type ShopFetchTaxRates { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop shopErrors: [ShopError!]! } @@ -4568,7 +6138,10 @@ input ShopSettingsInput { } type ShopSettingsTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop translationErrors: [TranslationError!]! } @@ -4579,7 +6152,10 @@ input ShopSettingsTranslationInput { } type ShopSettingsUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shop: Shop shopErrors: [ShopError!]! } @@ -4597,13 +6173,19 @@ input SiteDomainInput { } type StaffBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! staffErrors: [StaffError!]! } type StaffCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) staffErrors: [StaffError!]! user: User } @@ -4619,7 +6201,10 @@ input StaffCreateInput { } type StaffDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) staffErrors: [StaffError!]! user: User } @@ -4646,13 +6231,19 @@ type StaffNotificationRecipient implements Node { } type StaffNotificationRecipientCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shopErrors: [ShopError!]! staffNotificationRecipient: StaffNotificationRecipient } type StaffNotificationRecipientDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shopErrors: [ShopError!]! staffNotificationRecipient: StaffNotificationRecipient } @@ -4664,13 +6255,19 @@ input StaffNotificationRecipientInput { } type StaffNotificationRecipientUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) shopErrors: [ShopError!]! staffNotificationRecipient: StaffNotificationRecipient } type StaffUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) staffErrors: [StaffError!]! user: User } @@ -4817,7 +6414,18 @@ enum TransactionKind { CONFIRM } -union TranslatableItem = ProductTranslatableContent | CollectionTranslatableContent | CategoryTranslatableContent | AttributeTranslatableContent | AttributeValueTranslatableContent | ProductVariantTranslatableContent | PageTranslatableContent | ShippingMethodTranslatableContent | SaleTranslatableContent | VoucherTranslatableContent | MenuItemTranslatableContent +union TranslatableItem = + ProductTranslatableContent + | CollectionTranslatableContent + | CategoryTranslatableContent + | AttributeTranslatableContent + | AttributeValueTranslatableContent + | ProductVariantTranslatableContent + | PageTranslatableContent + | ShippingMethodTranslatableContent + | SaleTranslatableContent + | VoucherTranslatableContent + | MenuItemTranslatableContent type TranslatableItemConnection { pageInfo: PageInfo! @@ -4872,13 +6480,19 @@ input UpdateInvoiceInput { } type UpdateMetadata { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) metadataErrors: [MetadataError!]! item: ObjectWithMetadata } type UpdatePrivateMetadata { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) metadataErrors: [MetadataError!]! item: ObjectWithMetadata } @@ -4899,13 +6513,32 @@ type User implements Node & ObjectWithMetadata { defaultBillingAddress: Address privateMetadata: [MetadataItem]! metadata: [MetadataItem]! - privateMeta: [MetaStore]! @deprecated(reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31.") - meta: [MetaStore]! @deprecated(reason: "Use the `metadata` field. This field will be removed after 2020-07-31.") + privateMeta: [MetaStore]! + @deprecated( + reason: "Use the `privetaMetadata` field. This field will be removed after 2020-07-31." + ) + meta: [MetaStore]! + @deprecated( + reason: "Use the `metadata` field. This field will be removed after 2020-07-31." + ) addresses: [Address] checkout: Checkout - giftCards(before: String, after: String, first: Int, last: Int): GiftCardCountableConnection - orders(before: String, after: String, first: Int, last: Int): OrderCountableConnection - permissions: [Permission] @deprecated(reason: "Will be removed in Saleor 2.11.Use the `userPermissions` instead.") + giftCards( + before: String + after: String + first: Int + last: Int + ): GiftCardCountableConnection + orders( + before: String + after: String + first: Int + last: Int + ): OrderCountableConnection + permissions: [Permission] + @deprecated( + reason: "Will be removed in Saleor 2.11.Use the `userPermissions` instead." + ) userPermissions: [UserPermission] permissionGroups: [Group] editableGroups: [Group] @@ -4915,31 +6548,46 @@ type User implements Node & ObjectWithMetadata { } type UserAvatarDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } type UserAvatarUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User accountErrors: [AccountError!]! } type UserBulkSetActive { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! accountErrors: [AccountError!]! } type UserClearMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } type UserClearPrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -4985,13 +6633,19 @@ input UserSortingInput { } type UserUpdateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } type UserUpdatePrivateMeta { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) accountErrors: [AccountError!]! user: User } @@ -5003,14 +6657,20 @@ type VAT { } type VariantImageAssign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productVariant: ProductVariant image: ProductImage productErrors: [ProductError!]! } type VariantImageUnassign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) productVariant: ProductVariant image: ProductImage productErrors: [ProductError!]! @@ -5026,7 +6686,10 @@ type VariantPricingInfo { } type VerifyToken { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) user: User isValid: Boolean! payload: GenericScalar @@ -5048,21 +6711,42 @@ type Voucher implements Node { discountValue: Float! minSpent: Money minCheckoutItemsQuantity: Int - categories(before: String, after: String, first: Int, last: Int): CategoryCountableConnection - collections(before: String, after: String, first: Int, last: Int): CollectionCountableConnection - products(before: String, after: String, first: Int, last: Int): ProductCountableConnection + categories( + before: String + after: String + first: Int + last: Int + ): CategoryCountableConnection + collections( + before: String + after: String + first: Int + last: Int + ): CollectionCountableConnection + products( + before: String + after: String + first: Int + last: Int + ): ProductCountableConnection countries: [CountryDisplay] translation(languageCode: LanguageCodeEnum!): VoucherTranslation } type VoucherAddCatalogues { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) voucher: Voucher discountErrors: [DiscountError!]! } type VoucherBulkDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) count: Int! discountErrors: [DiscountError!]! } @@ -5079,13 +6763,19 @@ type VoucherCountableEdge { } type VoucherCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! voucher: Voucher } type VoucherDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! voucher: Voucher } @@ -5124,7 +6814,10 @@ input VoucherInput { } type VoucherRemoveCatalogues { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) voucher: Voucher discountErrors: [DiscountError!]! } @@ -5152,7 +6845,10 @@ type VoucherTranslatableContent implements Node { } type VoucherTranslate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) translationErrors: [TranslationError!]! voucher: Voucher } @@ -5170,7 +6866,10 @@ enum VoucherTypeEnum { } type VoucherUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) discountErrors: [DiscountError!]! voucher: Voucher } @@ -5180,7 +6879,12 @@ type Warehouse implements Node { name: String! slug: String! companyName: String! - shippingZones(before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection! + shippingZones( + before: String + after: String + first: Int + last: Int + ): ShippingZoneCountableConnection! address: Address! email: String! } @@ -5208,7 +6912,10 @@ type WarehouseCountableEdge { } type WarehouseCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) warehouseErrors: [WarehouseError!]! warehouse: Warehouse } @@ -5223,7 +6930,10 @@ input WarehouseCreateInput { } type WarehouseDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) warehouseErrors: [WarehouseError!]! warehouse: Warehouse } @@ -5249,13 +6959,19 @@ input WarehouseFilterInput { } type WarehouseShippingZoneAssign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) warehouseErrors: [WarehouseError!]! warehouse: Warehouse } type WarehouseShippingZoneUnassign { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) warehouseErrors: [WarehouseError!]! warehouse: Warehouse } @@ -5270,7 +6986,10 @@ input WarehouseSortingInput { } type WarehouseUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) warehouseErrors: [WarehouseError!]! warehouse: Warehouse } @@ -5290,7 +7009,10 @@ type Webhook implements Node { secretKey: String id: ID! events: [WebhookEvent!]! - serviceAccount: ServiceAccount! @deprecated(reason: "Use the `app` field instead. This field will be removed after 2020-07-31.") + serviceAccount: ServiceAccount! + @deprecated( + reason: "Use the `app` field instead. This field will be removed after 2020-07-31." + ) app: App! } @@ -5306,7 +7028,10 @@ type WebhookCountableEdge { } type WebhookCreate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) webhookErrors: [WebhookError!]! webhook: Webhook } @@ -5322,7 +7047,10 @@ input WebhookCreateInput { } type WebhookDelete { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) webhookErrors: [WebhookError!]! webhook: Webhook } @@ -5395,7 +7123,10 @@ input WebhookSortingInput { } type WebhookUpdate { - errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") + errors: [Error!]! + @deprecated( + reason: "Use typed errors with error codes. This field will be removed after 2020-07-31." + ) webhookErrors: [WebhookError!]! webhook: Webhook } @@ -5426,7 +7157,18 @@ enum WeightUnitsEnum { scalar _Any -union _Entity = Address | User | Group | ServiceAccount | App | ProductVariant | Product | ProductType | Collection | Category | ProductImage +union _Entity = + Address + | User + | Group + | ServiceAccount + | App + | ProductVariant + | Product + | ProductType + | Collection + | Category + | ProductImage type _Service { sdl: String diff --git a/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx b/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx new file mode 100644 index 000000000..cd54d8776 --- /dev/null +++ b/src/apps/components/AppActivateDialog/AppActivateDialog.stories.tsx @@ -0,0 +1,18 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppActivateDialog, { AppActivateDialogProps } from "./AppActivateDialog"; + +const props: AppActivateDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Activate app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppActivateDialog/AppActivateDialog.tsx b/src/apps/components/AppActivateDialog/AppActivateDialog.tsx new file mode 100644 index 000000000..f447d2402 --- /dev/null +++ b/src/apps/components/AppActivateDialog/AppActivateDialog.tsx @@ -0,0 +1,61 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppActivateDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppActivateDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppActivateDialog.displayName = "AppActivateDialog"; +export default AppActivateDialog; diff --git a/src/apps/components/AppActivateDialog/index.ts b/src/apps/components/AppActivateDialog/index.ts new file mode 100644 index 000000000..7b7d24553 --- /dev/null +++ b/src/apps/components/AppActivateDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppActivateDialog"; +export { default } from "./AppActivateDialog"; diff --git a/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx new file mode 100644 index 000000000..00cb9a903 --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppDeactivateDialog, { + AppDeactivateDialogProps +} from "./AppDeactivateDialog"; + +const props: AppDeactivateDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Deactivate app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx new file mode 100644 index 000000000..9cc84e6cb --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/AppDeactivateDialog.tsx @@ -0,0 +1,61 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppDeactivateDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppDeactivateDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppDeactivateDialog.displayName = "AppDeactivateDialog"; +export default AppDeactivateDialog; diff --git a/src/apps/components/AppDeactivateDialog/index.ts b/src/apps/components/AppDeactivateDialog/index.ts new file mode 100644 index 000000000..d58865cf1 --- /dev/null +++ b/src/apps/components/AppDeactivateDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDeactivateDialog"; +export { default } from "./AppDeactivateDialog"; diff --git a/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx b/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx new file mode 100644 index 000000000..43f19486a --- /dev/null +++ b/src/apps/components/AppDeleteDialog/AppDeleteDialog.stories.tsx @@ -0,0 +1,19 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppDeleteDialog, { AppDeleteDialogProps } from "./AppDeleteDialog"; + +const props: AppDeleteDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true, + type: "EXTERNAL" +}; + +storiesOf("Views / Apps / Delete app", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ); diff --git a/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx b/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx new file mode 100644 index 000000000..fa5708368 --- /dev/null +++ b/src/apps/components/AppDeleteDialog/AppDeleteDialog.tsx @@ -0,0 +1,67 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppDeleteDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; + type: "CUSTOM" | "EXTERNAL"; +} + +const AppDeleteDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm, + type +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : type === "EXTERNAL" ? ( + {getStringOrPlaceholder(name)} + }} + /> + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppDeleteDialog.displayName = "AppDeleteDialog"; +export default AppDeleteDialog; diff --git a/src/apps/components/AppDeleteDialog/index.ts b/src/apps/components/AppDeleteDialog/index.ts new file mode 100644 index 000000000..06d0e0693 --- /dev/null +++ b/src/apps/components/AppDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDeleteDialog"; +export { default } from "./AppDeleteDialog"; diff --git a/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx b/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx new file mode 100644 index 000000000..20cf82e41 --- /dev/null +++ b/src/apps/components/AppDetailsPage/AppDetailsPage.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appDetails } from "../../fixtures"; +import AppDetailsPage, { AppDetailsPageProps } from "./AppDetailsPage"; + +const props: AppDetailsPageProps = { + data: appDetails, + loading: false, + navigateToAppSettings: () => undefined, + onAppActivateOpen: () => undefined, + onAppDeactivateOpen: () => undefined, + onBack: () => undefined +}; + +storiesOf("Views / Apps / App details", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ); diff --git a/src/apps/components/AppDetailsPage/AppDetailsPage.tsx b/src/apps/components/AppDetailsPage/AppDetailsPage.tsx new file mode 100644 index 000000000..a01299701 --- /dev/null +++ b/src/apps/components/AppDetailsPage/AppDetailsPage.tsx @@ -0,0 +1,195 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Container from "@saleor/components/Container"; +import ExternalLink from "@saleor/components/ExternalLink"; +import PageHeader from "@saleor/components/PageHeader"; +import Skeleton from "@saleor/components/Skeleton"; +import { sectionNames } from "@saleor/intl"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; +import ReactMarkdown from "react-markdown"; + +import activateIcon from "../../../../assets/images/activate-icon.svg"; +import settingsIcon from "../../../../assets/images/settings-icon.svg"; +import supportIcon from "../../../../assets/images/support-icon.svg"; +import { useStyles } from "../../styles"; +import { App_app } from "../../types/App"; +import DeactivatedText from "../DeactivatedText"; + +export interface AppDetailsPageProps { + loading: boolean; + data: App_app; + navigateToAppSettings: () => void; + onAppActivateOpen: () => void; + onAppDeactivateOpen: () => void; + onBack: () => void; +} + +export const AppDetailsPage: React.FC = ({ + data, + loading, + navigateToAppSettings, + onAppActivateOpen, + onAppDeactivateOpen, + onBack +}) => { + const intl = useIntl(); + const classes = useStyles({}); + + return ( + + + {intl.formatMessage(sectionNames.apps)} + + + {data?.name} {!data?.isActive && } + + } + > + + +
+ {data ? ( +
+ + + + + + +
+ ) : ( + + )} +
+
+ + + + + {!loading ? : } + + + + + + + {!loading ? ( + <> + + + + {!!data?.permissions?.length && ( +
    + {data?.permissions?.map(perm => ( +
  • {perm.name}
  • + ))} +
+ )} + + ) : ( + + )} +
+
+ + + + + + {!loading ? ( + <> + {data?.dataPrivacy} + + + + + ) : ( + + )} + + + + + ); +}; + +AppDetailsPage.displayName = "AppDetailsPage"; +export default AppDetailsPage; diff --git a/src/apps/components/AppDetailsPage/index.ts b/src/apps/components/AppDetailsPage/index.ts new file mode 100644 index 000000000..1e11990da --- /dev/null +++ b/src/apps/components/AppDetailsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsPage"; +export { default } from "./AppDetailsPage"; diff --git a/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx new file mode 100644 index 000000000..8665d545e --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.stories.tsx @@ -0,0 +1,20 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appDetails } from "../../fixtures"; +import AppDetailsSettingsPage, { + AppDetailsSettingsPageProps +} from "./AppDetailsSettingsPage"; + +const props: AppDetailsSettingsPageProps = { + backendHost: "host", + data: appDetails, + navigateToDashboard: () => undefined, + onBack: () => undefined, + onError: () => undefined +}; + +storiesOf("Views / Apps / App details settings", module) + .addDecorator(Decorator) + .add("default", () => ); diff --git a/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx new file mode 100644 index 000000000..86672606e --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/AppDetailsSettingsPage.tsx @@ -0,0 +1,146 @@ +import Button from "@material-ui/core/Button"; +import Typography from "@material-ui/core/Typography"; +import AppHeader from "@saleor/components/AppHeader"; +import CardSpacer from "@saleor/components/CardSpacer"; +import Container from "@saleor/components/Container"; +import Grid from "@saleor/components/Grid"; +import Hr from "@saleor/components/Hr"; +import useTheme from "@saleor/hooks/useTheme"; +import { sectionNames } from "@saleor/intl"; +import classNames from "classnames"; +import React, { useEffect, useRef } from "react"; +import { FormattedMessage, useIntl } from "react-intl"; +import urlJoin from "url-join"; + +import { App_app } from "../../types/App"; +import { useStyles } from "./styles"; +import useSettingsBreadcrumbs from "./useSettingsBreadcrumbs"; + +export interface AppDetailsSettingsPageProps { + backendHost: string; + data: App_app; + navigateToDashboard: () => void; + onBack: () => void; + onError: () => void; +} + +export const AppDetailsSettingsPage: React.FC = ({ + backendHost, + data, + navigateToDashboard, + onBack, + onError +}) => { + const iframeRef = useRef(null); + const intl = useIntl(); + const classes = useStyles({}); + const { sendThemeToExtension } = useTheme(); + const [breadcrumbs, onBreadcrumbClick] = useSettingsBreadcrumbs(); + + useEffect(() => { + if (!iframeRef.current?.innerHTML && data?.configurationUrl) { + fetch(data?.configurationUrl, { + headers: { + "x-saleor-domain": backendHost, + "x-saleor-token": data.accessToken + }, + method: "GET" + }) + .then(async response => { + const url = new URL(response.url); + const text = await response.text(); + const content = new DOMParser().parseFromString(text, "text/html"); + + const iFrame = document.createElement("iframe"); + iFrame.src = "about:blank"; + iFrame.id = "extension-app"; + iframeRef.current.innerHTML = ""; + iframeRef.current.appendChild(iFrame); + const iFrameDoc = + iFrame.contentWindow && iFrame.contentWindow.document; + + const documentElement = content.documentElement; + const formScript = documentElement.querySelector("script"); + const formURL = new URL(documentElement.querySelector("script").src); + formScript.src = `${urlJoin(url.origin, formURL.pathname)}`; + iFrameDoc.write(content.documentElement.innerHTML); + iFrameDoc.close(); + iFrame.contentWindow.onload = sendThemeToExtension; + }) + .catch(() => onError()); + } + }, [data]); + + return ( + + + {intl.formatMessage(sectionNames.apps)} + + +
+
+ + {data?.name} + + {breadcrumbs.map(b => ( + onBreadcrumbClick(b.value)} + key={b.label} + > + {b.label} + + ))} +
+
+
+ + + +
+
+ + +
+ + +
+ + + ); +}; + +AppDetailsSettingsPage.displayName = "AppDetailsSettingsPage"; +export default AppDetailsSettingsPage; diff --git a/src/apps/components/AppDetailsSettingsPage/index.ts b/src/apps/components/AppDetailsSettingsPage/index.ts new file mode 100644 index 000000000..b492e446b --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsSettingsPage"; +export { default } from "./AppDetailsSettingsPage"; diff --git a/src/apps/components/AppDetailsSettingsPage/styles.ts b/src/apps/components/AppDetailsSettingsPage/styles.ts new file mode 100644 index 000000000..cf6f42e4d --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/styles.ts @@ -0,0 +1,62 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + appSettingsHeader: { + "& > button, & > a": { + "&:last-child": { + marginRight: 0 + }, + marginRight: theme.spacing(2) + }, + display: "flex", + justifyContent: "flex-end" + }, + breadcrumb: { + "&:not(:last-child)": { + "&:after": { + content: "'/'", + display: "block", + position: "absolute", + right: -theme.spacing(2), + top: 0 + }, + "&:not(:first-child):hover": { + cursor: "pointer", + textDecoration: "underline" + } + }, + marginRight: theme.spacing(3), + position: "relative" + }, + breadcrumbContainer: { + alignItems: "center", + display: "flex" + }, + breadcrumbDisabled: { + "&:hover": { + textDecoration: "none" + }, + color: theme.palette.text.disabled + }, + breadcrumbs: { + display: "flex" + }, + hr: { + border: "none", + borderTop: `1px solid ${theme.palette.divider}`, + height: 0, + marginBottom: 0, + marginTop: 0, + width: "100%" + }, + iframeContainer: { + "& > iframe": { + border: "none", + minHeight: "75vh", + width: "100%" + } + } + }), + { name: "AppDetailsSettingsPage" } +); diff --git a/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts b/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts new file mode 100644 index 000000000..3edcc45ec --- /dev/null +++ b/src/apps/components/AppDetailsSettingsPage/useSettingsBreadcrumbs.ts @@ -0,0 +1,38 @@ +import { + Breadcrumb, + BreadcrumbChangeMessage, + BreadcrumbClickMessage, + ExtensionMessageEvent, + ExtensionMessageType, + sendMessageToExtension, + useExtensionMessage +} from "@saleor/macaw-ui/extensions"; +import { useState } from "react"; + +type UseSettingsBreadcrumbs = [Breadcrumb[], (value: string) => void]; +function useSettingsBreadcrumbs(): UseSettingsBreadcrumbs { + const [breadcrumbs, setBreadcrumbs] = useState([]); + + const handleBreadcrumbSet = ( + event: ExtensionMessageEvent + ) => { + if (event.data.type === ExtensionMessageType.BREADCRUMB_SET) { + setBreadcrumbs(event.data.breadcrumbs); + } + }; + + useExtensionMessage(handleBreadcrumbSet); + + const handleBreadcrumbClick = (value: string) => + sendMessageToExtension( + { + breadcrumb: value, + type: ExtensionMessageType.BREADCRUMB_CLICK + }, + "*" + ); + + return [breadcrumbs, handleBreadcrumbClick]; +} + +export default useSettingsBreadcrumbs; diff --git a/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx new file mode 100644 index 000000000..fc8598add --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.stories.tsx @@ -0,0 +1,22 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import AppInProgressDeleteDialog, { + AppInProgressDeleteDialogProps +} from "./AppInProgressDeleteDialog"; + +const props: AppInProgressDeleteDialogProps = { + confirmButtonState: "default", + name: "App", + onClose: () => undefined, + onConfirm: () => undefined, + open: true +}; + +storiesOf("Views / Apps / Delete app failed installation", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("unnamed app", () => ( + + )); diff --git a/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx new file mode 100644 index 000000000..272a4fac8 --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/AppInProgressDeleteDialog.tsx @@ -0,0 +1,57 @@ +import DialogContentText from "@material-ui/core/DialogContentText"; +import ActionDialog from "@saleor/components/ActionDialog"; +import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +export interface AppInProgressDeleteDialogProps { + confirmButtonState: ConfirmButtonTransitionState; + open: boolean; + name: string; + onClose: () => void; + onConfirm: () => void; +} + +const AppInProgressDeleteDialog: React.FC = ({ + confirmButtonState, + open, + name, + onClose, + onConfirm +}) => { + const intl = useIntl(); + + return ( + + + {["", null].includes(name) ? ( + + ) : ( + {getStringOrPlaceholder(name)} + }} + /> + )} + + + ); +}; +AppInProgressDeleteDialog.displayName = "AppInProgressDeleteDialog"; +export default AppInProgressDeleteDialog; diff --git a/src/apps/components/AppInProgressDeleteDialog/index.ts b/src/apps/components/AppInProgressDeleteDialog/index.ts new file mode 100644 index 000000000..64c241dd2 --- /dev/null +++ b/src/apps/components/AppInProgressDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInProgressDeleteDialog"; +export { default } from "./AppInProgressDeleteDialog"; diff --git a/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx b/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx new file mode 100644 index 000000000..ef26b4f0a --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/AppInstallErrorPage.tsx @@ -0,0 +1,56 @@ +import errorImg from "@assets/images/app-install-error.svg"; +import Button from "@material-ui/core/Button"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import Container from "@saleor/components/Container"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "./styles"; + +interface AppInstallErrorPageProps { + onBack: () => void; +} + +export const AppInstallErrorPage: React.FC = ({ + onBack +}) => { + const classes = useStyles({}); + + return ( + + + + + + + + + + + + + + + + + ); +}; + +export default AppInstallErrorPage; diff --git a/src/apps/components/AppInstallErrorPage/index.ts b/src/apps/components/AppInstallErrorPage/index.ts new file mode 100644 index 000000000..c49180823 --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstallErrorPage"; +export { default } from "./AppInstallErrorPage"; diff --git a/src/apps/components/AppInstallErrorPage/styles.ts b/src/apps/components/AppInstallErrorPage/styles.ts new file mode 100644 index 000000000..6232b920f --- /dev/null +++ b/src/apps/components/AppInstallErrorPage/styles.ts @@ -0,0 +1,26 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + button: { + marginTop: theme.spacing(2), + padding: theme.spacing(1.5, 2) + }, + root: { + "& > div": { + minHeight: "80vh" + }, + "& h3": { + fontWeight: 600, + marginBottom: theme.spacing(3), + maxWidth: theme.spacing(60) + }, + "& img": { + maxWidth: "100%" + } + } + }), + { + name: "AppInstallErrorPage" + } +); diff --git a/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx b/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx new file mode 100644 index 000000000..4847c70b0 --- /dev/null +++ b/src/apps/components/AppInstallPage/AppInstallPage.stories.tsx @@ -0,0 +1,18 @@ +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { installApp } from "../../fixtures"; +import AppInstallPage, { AppInstallPageProps } from "./AppInstallPage"; + +const props: AppInstallPageProps = { + data: installApp, + loading: false, + navigateToAppsList: () => undefined, + onSubmit: () => undefined +}; + +storiesOf("Views / Apps / Install App", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ); diff --git a/src/apps/components/AppInstallPage/AppInstallPage.tsx b/src/apps/components/AppInstallPage/AppInstallPage.tsx new file mode 100644 index 000000000..b6ca74f80 --- /dev/null +++ b/src/apps/components/AppInstallPage/AppInstallPage.tsx @@ -0,0 +1,160 @@ +import saleorDarkLogoSmall from "@assets/images/logo-dark-small.svg"; +import plusIcon from "@assets/images/plus-icon.svg"; +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Grid from "@material-ui/core/Grid"; +import Typography from "@material-ui/core/Typography"; +import CardSpacer from "@saleor/components/CardSpacer"; +import CardTitle from "@saleor/components/CardTitle"; +import Container from "@saleor/components/Container"; +import Hr from "@saleor/components/Hr"; +import Skeleton from "@saleor/components/Skeleton"; +import { buttonMessages } from "@saleor/intl"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppFetch_appFetchManifest_manifest } from "../../types/AppFetch"; + +export interface AppInstallPageProps { + data: AppFetch_appFetchManifest_manifest; + loading: boolean; + navigateToAppsList: () => void; + onSubmit: () => void; +} + +export const AppInstallPage: React.FC = ({ + data, + loading, + navigateToAppsList, + onSubmit +}) => { + const intl = useIntl(); + const classes = useStyles({}); + + const name = data?.name || ""; + + return ( + + + + + ) : ( + intl.formatMessage( + { + defaultMessage: `You are about to install {name}`, + description: "section header" + }, + { name } + ) + ) + } + /> + + {loading ? ( + + ) : ( +
+
+ +
+ +
+

{name?.charAt(0).toUpperCase()}

+
+
+ )} +
+
+ + + + + {loading ? ( + + ) : ( + <> + + + + {!!data?.permissions?.length && ( +
    + {data?.permissions?.map(perm => ( +
  • {perm.name}
  • + ))} +
+ )} +
+ + + + + + + + + )} +
+
+ + + + + + + + + +
+ ); +}; + +AppInstallPage.displayName = "AppInstallPage"; +export default AppInstallPage; diff --git a/src/apps/components/AppInstallPage/index.ts b/src/apps/components/AppInstallPage/index.ts new file mode 100644 index 000000000..6cdc3393b --- /dev/null +++ b/src/apps/components/AppInstallPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstallPage"; +export { default } from "./AppInstallPage"; diff --git a/src/apps/components/AppsInProgress/AppsInProgress.tsx b/src/apps/components/AppsInProgress/AppsInProgress.tsx new file mode 100644 index 000000000..0d1ed27df --- /dev/null +++ b/src/apps/components/AppsInProgress/AppsInProgress.tsx @@ -0,0 +1,117 @@ +import Button from "@material-ui/core/Button"; +import Progress from "@material-ui/core/CircularProgress"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Tooltip from "@material-ui/core/Tooltip"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import ErrorIcon from "@material-ui/icons/Error"; +import CardTitle from "@saleor/components/CardTitle"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import classNames from "classnames"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { JobStatusEnum } from "../../../types/globalTypes"; +import { useStyles } from "../../styles"; +import { AppsInstallations_appsInstallations } from "../../types/AppsInstallations"; +import CardContainer from "../CardContainer"; + +export interface AppsInProgressProps { + appsList: AppsInstallations_appsInstallations[]; + disabled: boolean; + onAppInstallRetry: (id: string) => void; + onRemove: (id: string) => void; +} + +const AppsInProgress: React.FC = ({ + appsList, + disabled, + onAppInstallRetry, + onRemove, + ...props +}) => { + const intl = useIntl(); + const classes = useStyles(props); + + return ( + + } + > + + {renderCollection(appsList, ({ status, appName, id, message }) => ( + + + {appName} + + {status === JobStatusEnum.PENDING && ( + + + + +
+ +
+
+ )} + {status === JobStatusEnum.FAILED && ( + + + + {message}} + classes={{ + tooltip: classes.customTooltip + }} + > + + + + + onRemove(id))} + > + + + + )} +
+ ))} +
+
+ ); +}; + +AppsInProgress.displayName = "AppsInProgress"; +export default AppsInProgress; diff --git a/src/apps/components/AppsInProgress/index.ts b/src/apps/components/AppsInProgress/index.ts new file mode 100644 index 000000000..a18fc1160 --- /dev/null +++ b/src/apps/components/AppsInProgress/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsInProgress"; +export { default } from "./AppsInProgress"; diff --git a/src/apps/components/AppsListPage/AppListPage.stories.tsx b/src/apps/components/AppsListPage/AppListPage.stories.tsx new file mode 100644 index 000000000..dded8b172 --- /dev/null +++ b/src/apps/components/AppsListPage/AppListPage.stories.tsx @@ -0,0 +1,58 @@ +import { + listActionsProps, + pageListProps, + searchPageProps, + sortPageProps, + tabPageProps +} from "@saleor/fixtures"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import React from "react"; + +import { appsInProgress, appsList, customAppsList } from "../../fixtures"; +import AppsListPage, { AppsListPageProps } from "./AppsListPage"; + +const props: AppsListPageProps = { + ...listActionsProps, + ...pageListProps.default, + ...searchPageProps, + ...sortPageProps, + ...tabPageProps, + appsInProgressList: { appsInstallations: appsInProgress }, + customAppsList, + disabled: false, + installedAppsList: appsList, + loadingAppsInProgress: false, + navigateToCustomApp: () => undefined, + navigateToCustomAppCreate: () => undefined, + onAppInProgressRemove: () => undefined, + onAppInstallRetry: () => undefined, + onCustomAppRemove: () => undefined, + onInstalledAppRemove: () => undefined, + onNextPage: () => undefined, + onPreviousPage: () => undefined, + onRowClick: () => undefined, + onSettingsRowClick: () => undefined +}; + +storiesOf("Views / Apps / Apps list", module) + .addDecorator(Decorator) + .add("default", () => ) + .add("loading", () => ( + + )) + .add("no data", () => ( + + )); diff --git a/src/apps/components/AppsListPage/AppsListPage.tsx b/src/apps/components/AppsListPage/AppsListPage.tsx new file mode 100644 index 000000000..6b17f4f01 --- /dev/null +++ b/src/apps/components/AppsListPage/AppsListPage.tsx @@ -0,0 +1,76 @@ +import Container from "@saleor/components/Container"; +import PageHeader from "@saleor/components/PageHeader"; +import { sectionNames } from "@saleor/intl"; +import { ListProps } from "@saleor/types"; +import React from "react"; +import { useIntl } from "react-intl"; + +import { AppsInstallations } from "../../types/AppsInstallations"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsInProgress from "../AppsInProgress/AppsInProgress"; +import CustomApps from "../CustomApps/CustomApps"; +import InstalledApps from "../InstalledApps/InstalledApps"; +import Marketplace from "../Marketplace"; + +export interface AppsListPageProps extends ListProps { + installedAppsList: AppsList_apps_edges[]; + customAppsList: AppsList_apps_edges[]; + appsInProgressList?: AppsInstallations; + loadingAppsInProgress: boolean; + navigateToCustomApp: (id: string) => () => void; + navigateToCustomAppCreate: () => void; + onInstalledAppRemove: (id: string) => void; + onCustomAppRemove: (id: string) => void; + onAppInProgressRemove: (id: string) => void; + onAppInstallRetry: (id: string) => void; + onSettingsRowClick: (id: string) => () => void; +} + +const AppsListPage: React.FC = ({ + appsInProgressList, + customAppsList, + installedAppsList, + loadingAppsInProgress, + navigateToCustomApp, + navigateToCustomAppCreate, + onInstalledAppRemove, + onCustomAppRemove, + onAppInProgressRemove, + onAppInstallRetry, + onSettingsRowClick, + ...listProps +}) => { + const intl = useIntl(); + + const appsInProgress = appsInProgressList?.appsInstallations; + + return ( + + + {!!appsInProgress?.length && ( + + )} + + + + + ); +}; + +AppsListPage.displayName = "AppsListPage"; +export default AppsListPage; diff --git a/src/apps/components/AppsListPage/index.ts b/src/apps/components/AppsListPage/index.ts new file mode 100644 index 000000000..4fb8fb6a4 --- /dev/null +++ b/src/apps/components/AppsListPage/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsListPage"; +export { default } from "./AppsListPage"; diff --git a/src/apps/components/AppsSkeleton/AppsSkeleton.tsx b/src/apps/components/AppsSkeleton/AppsSkeleton.tsx new file mode 100644 index 000000000..21fdb5ba2 --- /dev/null +++ b/src/apps/components/AppsSkeleton/AppsSkeleton.tsx @@ -0,0 +1,21 @@ +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Skeleton from "@saleor/components/Skeleton"; +import React from "react"; + +import { useStyles } from "../../styles"; + +export const AppsSkeleton = () => { + const classes = useStyles({}); + + return ( + + + + + + ); +}; + +AppsSkeleton.displayName = "AppsSkeleton"; +export default AppsSkeleton; diff --git a/src/apps/components/AppsSkeleton/index.ts b/src/apps/components/AppsSkeleton/index.ts new file mode 100644 index 000000000..a91325e46 --- /dev/null +++ b/src/apps/components/AppsSkeleton/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsSkeleton"; +export { default } from "./AppsSkeleton"; diff --git a/src/apps/components/CardContainer/CardContainer.tsx b/src/apps/components/CardContainer/CardContainer.tsx new file mode 100644 index 000000000..81444808e --- /dev/null +++ b/src/apps/components/CardContainer/CardContainer.tsx @@ -0,0 +1,29 @@ +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import ResponsiveTable from "@saleor/components/ResponsiveTable"; +import React from "react"; + +import { useStyles } from "../../styles"; + +export interface CardContainerProps { + children: React.ReactNode; + header: React.ReactNode; +} + +const CardContainer: React.FC = ({ children, header }) => { + const classes = useStyles({}); + + return ( +
+ + {header} + + {children} + + +
+ ); +}; + +CardContainer.displayName = "CardContainer"; +export default CardContainer; diff --git a/src/apps/components/CardContainer/index.ts b/src/apps/components/CardContainer/index.ts new file mode 100644 index 000000000..3cca607ae --- /dev/null +++ b/src/apps/components/CardContainer/index.ts @@ -0,0 +1,2 @@ +export * from "./CardContainer"; +export { default } from "./CardContainer"; diff --git a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx b/src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx similarity index 72% rename from src/services/components/ServiceCreatePage/ServiceCreatePage.tsx rename to src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx index d1c87ed8a..1c948a2be 100644 --- a/src/services/components/ServiceCreatePage/ServiceCreatePage.tsx +++ b/src/apps/components/CustomAppCreatePage/CustomAppCreatePage.tsx @@ -1,6 +1,7 @@ +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; import AccountPermissions from "@saleor/components/AccountPermissions"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AppStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; @@ -9,32 +10,31 @@ import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; -import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { sectionNames } from "@saleor/intl"; import { PermissionEnum } from "@saleor/types/globalTypes"; import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; +import getAppErrorMessage from "@saleor/utils/errors/app"; import React from "react"; import { useIntl } from "react-intl"; -import ServiceInfo from "../ServiceInfo"; +import CustomAppInformation from "../CustomAppInformation"; -export interface ServiceCreatePageFormData { +export interface CustomAppCreatePageFormData { hasFullAccess: boolean; isActive: boolean; name: string; permissions: PermissionEnum[]; } -export interface ServiceCreatePageProps { +export interface CustomAppCreatePageProps { disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; onBack: () => void; - onSubmit: (data: ServiceCreatePageFormData) => void; + onSubmit: (data: CustomAppCreatePageFormData) => void; } -const ServiceCreatePage: React.FC = props => { +const CustomAppCreatePage: React.FC = props => { const { disabled, errors, @@ -45,7 +45,7 @@ const ServiceCreatePage: React.FC = props => { } = props; const intl = useIntl(); - const initialForm: ServiceCreatePageFormData = { + const initialForm: CustomAppCreatePageFormData = { hasFullAccess: false, isActive: false, name: "", @@ -53,24 +53,24 @@ const ServiceCreatePage: React.FC = props => { }; const formErrors = getFormErrors(["permissions"], errors || []); - const permissionsError = getAccountErrorMessage(formErrors.permissions, intl); + const permissionsError = getAppErrorMessage(formErrors.permissions, intl); return (
{({ data, change, hasChanged, submit }) => ( - {intl.formatMessage(sectionNames.serviceAccounts)} + {intl.formatMessage(sectionNames.apps)}
- = props => { permissionsExceeded={false} onChange={change} fullAccessLabel={intl.formatMessage({ - defaultMessage: "User has full access to the store", + defaultMessage: "Grant this app full access to the store", description: "checkbox label" })} description={intl.formatMessage({ defaultMessage: - "Expand or restrict user's permissions to access certain part of saleor system.", + "Expand or restrict app permissions to access certain part of Saleor system.", description: "card description" })} /> - = props => { ); }; -ServiceCreatePage.displayName = "ServiceCreatePage"; -export default ServiceCreatePage; +CustomAppCreatePage.displayName = "CustomAppCreatePage"; +export default CustomAppCreatePage; diff --git a/src/apps/components/CustomAppCreatePage/index.ts b/src/apps/components/CustomAppCreatePage/index.ts new file mode 100644 index 000000000..3f24a8549 --- /dev/null +++ b/src/apps/components/CustomAppCreatePage/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppCreatePage"; +export { default } from "./CustomAppCreatePage"; diff --git a/src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx b/src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx similarity index 68% rename from src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx rename to src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx index bcbe7f1fb..38b7433fd 100644 --- a/src/services/components/ServiceDefaultToken/ServiceDefaultToken.tsx +++ b/src/apps/components/CustomAppDefaultToken/CustomAppDefaultToken.tsx @@ -3,8 +3,6 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import IconButton from "@material-ui/core/IconButton"; import Paper from "@material-ui/core/Paper"; -import { makeStyles } from "@material-ui/core/styles"; -import { fade } from "@material-ui/core/styles/colorManipulator"; import Typography from "@material-ui/core/Typography"; import CloseIcon from "@material-ui/icons/Close"; import Link from "@saleor/components/Link"; @@ -12,50 +10,16 @@ import useClipboard from "@saleor/hooks/useClipboard"; import React from "react"; import { FormattedMessage } from "react-intl"; -export interface ServiceDefaultTokenProps { +import { useStyles } from "./styles"; + +export interface CustomAppDefaultTokenProps { apiUri: string; token: string; onApiUriClick: () => void; onTokenClose: () => void; } -const useStyles = makeStyles( - theme => ({ - cancel: { - marginRight: theme.spacing(1) - }, - closeContainer: { - display: "flex", - justifyContent: "flex-end", - position: "relative", - right: -theme.spacing(), - top: -theme.spacing(1) - }, - content: { - display: "grid", - gridColumnGap: theme.spacing(3), - gridTemplateColumns: "1fr 60px", - marginBottom: theme.spacing(3) - }, - copy: { - marginTop: theme.spacing(), - position: "relative", - right: theme.spacing(1) - }, - paper: { - background: fade(theme.palette.primary.main, 0.05), - padding: theme.spacing(2, 3) - }, - root: { - boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)" - } - }), - { - name: "ServiceTokenCreateDialog" - } -); - -const ServiceDefaultToken: React.FC = props => { +const CustomAppDefaultToken: React.FC = props => { const { apiUri, token, onApiUriClick, onTokenClose } = props; const classes = useStyles(props); const [copied, copy] = useClipboard(); @@ -112,5 +76,5 @@ const ServiceDefaultToken: React.FC = props => { ); }; -ServiceDefaultToken.displayName = "ServiceDefaultToken"; -export default ServiceDefaultToken; +CustomAppDefaultToken.displayName = "CustomAppDefaultToken"; +export default CustomAppDefaultToken; diff --git a/src/apps/components/CustomAppDefaultToken/index.ts b/src/apps/components/CustomAppDefaultToken/index.ts new file mode 100644 index 000000000..2d086352c --- /dev/null +++ b/src/apps/components/CustomAppDefaultToken/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDefaultToken"; +export { default } from "./CustomAppDefaultToken"; diff --git a/src/apps/components/CustomAppDefaultToken/styles.ts b/src/apps/components/CustomAppDefaultToken/styles.ts new file mode 100644 index 000000000..1f63c79ef --- /dev/null +++ b/src/apps/components/CustomAppDefaultToken/styles.ts @@ -0,0 +1,38 @@ +import { makeStyles } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; + +export const useStyles = makeStyles( + theme => ({ + cancel: { + marginRight: theme.spacing(1) + }, + closeContainer: { + display: "flex", + justifyContent: "flex-end", + position: "relative", + right: -theme.spacing(), + top: -theme.spacing(1) + }, + content: { + display: "grid", + gridColumnGap: theme.spacing(3), + gridTemplateColumns: "1fr 60px", + marginBottom: theme.spacing(3) + }, + copy: { + marginTop: theme.spacing(), + position: "relative", + right: theme.spacing(1) + }, + paper: { + background: fade(theme.palette.primary.main, 0.05), + padding: theme.spacing(2, 3) + }, + root: { + boxShadow: "0px 5px 10px rgba(0, 0, 0, 0.05)" + } + }), + { + name: "CustomAppTokenCreateDialog" + } +); diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx similarity index 59% rename from src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx rename to src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx index a56ab8d8c..f452257e2 100644 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.tsx +++ b/src/apps/components/CustomAppDetailsPage/CustomAppDetailsPage.tsx @@ -1,6 +1,7 @@ +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; import AccountPermissions from "@saleor/components/AccountPermissions"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AppStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import Container from "@saleor/components/Container"; @@ -9,93 +10,95 @@ import Grid from "@saleor/components/Grid"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; import { ShopInfo_shop_permissions } from "@saleor/components/Shop/types/ShopInfo"; -import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { sectionNames } from "@saleor/intl"; -import { maybe } from "@saleor/misc"; -import { ServiceDetails_serviceAccount } from "@saleor/services/types/ServiceDetails"; import { PermissionEnum } from "@saleor/types/globalTypes"; import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import WebhooksList from "@saleor/webhooks/components/WebhooksList"; import React from "react"; import { useIntl } from "react-intl"; -import ServiceDefaultToken from "../ServiceDefaultToken"; -import ServiceInfo from "../ServiceInfo"; -import ServiceTokens from "../ServiceTokens"; +import { AppUpdate_appUpdate_app } from "../../types/AppUpdate"; +import CustomAppDefaultToken from "../CustomAppDefaultToken"; +import CustomAppInformation from "../CustomAppInformation"; +import CustomAppTokens from "../CustomAppTokens"; -export interface ServiceDetailsPageFormData { +export interface CustomAppDetailsPageFormData { hasFullAccess: boolean; isActive: boolean; name: string; permissions: PermissionEnum[]; } -export interface ServiceDetailsPageProps { +export interface CustomAppDetailsPageProps { apiUri: string; disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; permissions: ShopInfo_shop_permissions[]; saveButtonBarState: ConfirmButtonTransitionState; - service: ServiceDetails_serviceAccount; + app: AppUpdate_appUpdate_app; token: string; onApiUriClick: () => void; onBack: () => void; onTokenDelete: (id: string) => void; - onDelete: () => void; onTokenClose: () => void; onTokenCreate: () => void; - onSubmit: (data: ServiceDetailsPageFormData) => void; + onSubmit: (data: CustomAppDetailsPageFormData) => void; + onWebhookCreate: () => void; + onWebhookRemove: (id: string) => void; + navigateToWebhookDetails: (id: string) => () => void; } -const ServiceDetailsPage: React.FC = props => { +const CustomAppDetailsPage: React.FC = props => { const { apiUri, disabled, errors, permissions, saveButtonBarState, - service, + app, + navigateToWebhookDetails, token, onApiUriClick, onBack, - onDelete, onTokenClose, onTokenCreate, onTokenDelete, - onSubmit + onSubmit, + onWebhookCreate, + onWebhookRemove } = props; const intl = useIntl(); - const formErrors = getFormErrors(["permissions"], errors || []); - const permissionsError = getAccountErrorMessage(formErrors.permissions, intl); + const webhooks = app?.webhooks; - const initialForm: ServiceDetailsPageFormData = { - hasFullAccess: maybe( - () => - permissions.filter( - perm => - maybe(() => service.permissions, []).filter( - userPerm => userPerm.code === perm.code - ).length === 0 - ).length === 0, - false - ), - isActive: maybe(() => service.isActive, false), - name: maybe(() => service.name, ""), - permissions: maybe(() => service.permissions, []).map(perm => perm.code) + const formErrors = getFormErrors(["permissions"], errors || []); + const permissionsError = getAppErrorMessage(formErrors.permissions, intl); + + const initialForm: CustomAppDetailsPageFormData = { + hasFullAccess: + permissions?.filter( + perm => + app?.permissions?.filter(userPerm => userPerm.code === perm.code) + .length === 0 + ).length === 0 || false, + isActive: !!app?.isActive, + name: app?.name || "", + permissions: app?.permissions?.map(perm => perm.code) || [] }; + return ( {({ data, change, hasChanged, submit }) => ( - {intl.formatMessage(sectionNames.serviceAccounts)} + {intl.formatMessage(sectionNames.apps)} - service.name)} /> +
{token && ( <> - = props => { )} - - + +
= props => { permissionsExceeded={false} onChange={change} fullAccessLabel={intl.formatMessage({ - defaultMessage: "User has full access to the store", + defaultMessage: "Grant this app full access to the store", description: "checkbox label" })} description={intl.formatMessage({ defaultMessage: - "Expand or restrict user's permissions to access certain part of saleor system.", + "Expand or restrict app permissions to access certain part of Saleor system.", description: "card description" })} /> - = props => { state={saveButtonBarState} onCancel={onBack} onSave={submit} - onDelete={onDelete} /> )} @@ -160,5 +169,5 @@ const ServiceDetailsPage: React.FC = props => { ); }; -ServiceDetailsPage.displayName = "ServiceDetailsPage"; -export default ServiceDetailsPage; +CustomAppDetailsPage.displayName = "CustomAppDetailsPage"; +export default CustomAppDetailsPage; diff --git a/src/apps/components/CustomAppDetailsPage/index.ts b/src/apps/components/CustomAppDetailsPage/index.ts new file mode 100644 index 000000000..fc3198f13 --- /dev/null +++ b/src/apps/components/CustomAppDetailsPage/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDetailsPage"; +export { default } from "./CustomAppDetailsPage"; diff --git a/src/services/components/ServiceInfo/ServiceInfo.tsx b/src/apps/components/CustomAppInformation/CustomAppInformation.tsx similarity index 64% rename from src/services/components/ServiceInfo/ServiceInfo.tsx rename to src/apps/components/CustomAppInformation/CustomAppInformation.tsx index df2b7c807..207a0d3c4 100644 --- a/src/services/components/ServiceInfo/ServiceInfo.tsx +++ b/src/apps/components/CustomAppInformation/CustomAppInformation.tsx @@ -1,24 +1,24 @@ import Card from "@material-ui/core/Card"; import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; +import { AppErrorFragment } from "@saleor/apps/types/AppErrorFragment"; import CardTitle from "@saleor/components/CardTitle"; -import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment"; import { FormChange } from "@saleor/hooks/useForm"; import { getFormErrors } from "@saleor/utils/errors"; -import getAccountErrorMessage from "@saleor/utils/errors/account"; +import getAppErrorMessage from "@saleor/utils/errors/app"; import React from "react"; import { useIntl } from "react-intl"; -export interface ServiceInfoProps { +export interface CustomAppInfoProps { data: { name: string; }; disabled: boolean; - errors: AccountErrorFragment[]; + errors: AppErrorFragment[]; onChange: FormChange; } -const ServiceInfo: React.FC = ({ +const CustomAppInformation: React.FC = ({ data, disabled, errors, @@ -32,7 +32,7 @@ const ServiceInfo: React.FC = ({ @@ -41,10 +41,10 @@ const ServiceInfo: React.FC = ({ disabled={disabled} error={!!formErrors.name} label={intl.formatMessage({ - defaultMessage: "Account Name", - description: "service account" + defaultMessage: "App Name", + description: "custom app name" })} - helperText={getAccountErrorMessage(formErrors.name, intl)} + helperText={getAppErrorMessage(formErrors.name, intl)} fullWidth name="name" value={data.name} @@ -55,5 +55,5 @@ const ServiceInfo: React.FC = ({ ); }; -ServiceInfo.displayName = "ServiceInfo"; -export default ServiceInfo; +CustomAppInformation.displayName = "CustomAppInformation"; +export default CustomAppInformation; diff --git a/src/apps/components/CustomAppInformation/index.ts b/src/apps/components/CustomAppInformation/index.ts new file mode 100644 index 000000000..2ecb5c14b --- /dev/null +++ b/src/apps/components/CustomAppInformation/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppInformation"; +export { default } from "./CustomAppInformation"; diff --git a/src/services/components/ServiceTokens/ServiceTokens.tsx b/src/apps/components/CustomAppTokens/CustomAppTokens.tsx similarity index 71% rename from src/services/components/ServiceTokens/ServiceTokens.tsx rename to src/apps/components/CustomAppTokens/CustomAppTokens.tsx index 1e6c183c2..9f96dcfc0 100644 --- a/src/services/components/ServiceTokens/ServiceTokens.tsx +++ b/src/apps/components/CustomAppTokens/CustomAppTokens.tsx @@ -1,7 +1,6 @@ import Button from "@material-ui/core/Button"; import Card from "@material-ui/core/Card"; import IconButton from "@material-ui/core/IconButton"; -import makeStyles from "@material-ui/core/styles/makeStyles"; import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableHead from "@material-ui/core/TableHead"; @@ -10,42 +9,22 @@ import DeleteIcon from "@material-ui/icons/Delete"; import CardTitle from "@saleor/components/CardTitle"; import ResponsiveTable from "@saleor/components/ResponsiveTable"; import Skeleton from "@saleor/components/Skeleton"; -import { ServiceDetailsFragment_tokens } from "@saleor/fragments/types/ServiceDetailsFragment"; -import { maybe, renderCollection } from "@saleor/misc"; +import { renderCollection } from "@saleor/misc"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -export interface ServiceTokensProps { - tokens: ServiceDetailsFragment_tokens[]; +import { AppUpdate_appUpdate_app_tokens } from "../../types/AppUpdate"; +import { useStyles } from "./styles"; + +export interface CustomAppTokensProps { + tokens: Array | null; onCreate: () => void; onDelete: (id: string) => void; } -const useStyles = makeStyles( - theme => ({ - [theme.breakpoints.down("md")]: { - colNote: { - width: 200 - } - }, - colActions: { - textAlign: "right", - width: 100 - }, - colKey: { - width: 200 - }, - colNote: {}, - table: { - tableLayout: "fixed" - } - }), - { name: "ServiceTokens" } -); - const numberOfColumns = 3; -const ServiceTokens: React.FC = props => { +const CustomAppTokens: React.FC = props => { const { tokens, onCreate, onDelete } = props; const classes = useStyles(props); const intl = useIntl(); @@ -54,7 +33,7 @@ const ServiceTokens: React.FC = props => { = props => { @@ -92,13 +71,10 @@ const ServiceTokens: React.FC = props => { token => ( - {maybe(() => token.name, )} + {token?.name || } - {maybe( - () => `**** ${token.authToken}`, - - )} + {token?.authToken ? `**** ${token.authToken}` : } = props => { ); }; -ServiceTokens.displayName = "ServiceTokens"; -export default ServiceTokens; +CustomAppTokens.displayName = "CustomAppTokens"; +export default CustomAppTokens; diff --git a/src/apps/components/CustomAppTokens/index.ts b/src/apps/components/CustomAppTokens/index.ts new file mode 100644 index 000000000..c88f1f2cf --- /dev/null +++ b/src/apps/components/CustomAppTokens/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppTokens"; +export { default } from "./CustomAppTokens"; diff --git a/src/apps/components/CustomAppTokens/styles.ts b/src/apps/components/CustomAppTokens/styles.ts new file mode 100644 index 000000000..42231fff0 --- /dev/null +++ b/src/apps/components/CustomAppTokens/styles.ts @@ -0,0 +1,23 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; + +export const useStyles = makeStyles( + theme => ({ + [theme.breakpoints.down("md")]: { + colNote: { + width: 200 + } + }, + colActions: { + textAlign: "right", + width: 100 + }, + colKey: { + width: 200 + }, + colNote: {}, + table: { + tableLayout: "fixed" + } + }), + { name: "CustomAppTokens" } +); diff --git a/src/apps/components/CustomApps/CustomApps.tsx b/src/apps/components/CustomApps/CustomApps.tsx new file mode 100644 index 000000000..cb564600f --- /dev/null +++ b/src/apps/components/CustomApps/CustomApps.tsx @@ -0,0 +1,116 @@ +import Button from "@material-ui/core/Button"; +import CardHeader from "@material-ui/core/CardHeader"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import { commonMessages } from "@saleor/intl"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsSkeleton from "../AppsSkeleton"; +import CardContainer from "../CardContainer"; +import DeactivatedText from "../DeactivatedText"; + +export interface CustomAppsProps { + appsList: AppsList_apps_edges[]; + navigateToCustomApp: (id: string) => () => void; + navigateToCustomAppCreate?: () => void; + onRemove: (id: string) => void; +} + +const CustomApps: React.FC = ({ + appsList, + navigateToCustomAppCreate, + onRemove, + navigateToCustomApp +}) => { + const classes = useStyles({}); + + return ( + + + + + ) + } + title={ + + + + } + /> +
+ + } + > + + {renderCollection( + appsList, + (app, index) => + app ? ( + + + + {app.node.name} + + {!app.node.isActive && ( +
+ +
+ )} +
+ + onRemove(app.node.id))} + > + + + +
+ ) : ( + + ), + () => ( + + + + + + + + ) + )} +
+
+ ); +}; + +CustomApps.displayName = "CustomApps"; +export default CustomApps; diff --git a/src/apps/components/CustomApps/index.ts b/src/apps/components/CustomApps/index.ts new file mode 100644 index 000000000..4c43c395b --- /dev/null +++ b/src/apps/components/CustomApps/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomApps"; +export { default } from "./CustomApps"; diff --git a/src/apps/components/DeactivatedText/DeactivatedText.tsx b/src/apps/components/DeactivatedText/DeactivatedText.tsx new file mode 100644 index 000000000..4327fb911 --- /dev/null +++ b/src/apps/components/DeactivatedText/DeactivatedText.tsx @@ -0,0 +1,19 @@ +import Typography from "@material-ui/core/Typography"; +import React from "react"; +import { FormattedMessage } from "react-intl"; + +import { useStyles } from "./styles"; + +export const DeactivatedText: React.FC<{}> = () => { + const classes = useStyles({}); + return ( + + + + ); +}; + +export default DeactivatedText; diff --git a/src/apps/components/DeactivatedText/index.ts b/src/apps/components/DeactivatedText/index.ts new file mode 100644 index 000000000..6eb43119d --- /dev/null +++ b/src/apps/components/DeactivatedText/index.ts @@ -0,0 +1,2 @@ +export * from "./DeactivatedText"; +export { default } from "./DeactivatedText"; diff --git a/src/apps/components/DeactivatedText/styles.ts b/src/apps/components/DeactivatedText/styles.ts new file mode 100644 index 000000000..0c1e03ef2 --- /dev/null +++ b/src/apps/components/DeactivatedText/styles.ts @@ -0,0 +1,26 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + root: { + "&:before": { + backgroundColor: theme.palette.error.main, + borderRadius: "50%", + content: "''", + display: "block", + height: 8, + left: 0, + position: "absolute", + top: "50%", + transform: "translateY(-50%)", + width: 8 + }, + color: theme.palette.error.main, + display: "inline-block", + marginLeft: theme.spacing(1.5), + paddingLeft: theme.spacing(2), + position: "relative" + } + }), + { name: "DeactivatedText" } +); diff --git a/src/apps/components/InstalledApps/InstalledApps.tsx b/src/apps/components/InstalledApps/InstalledApps.tsx new file mode 100644 index 000000000..b84d620db --- /dev/null +++ b/src/apps/components/InstalledApps/InstalledApps.tsx @@ -0,0 +1,133 @@ +import Button from "@material-ui/core/Button"; +import IconButton from "@material-ui/core/IconButton"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableFooter from "@material-ui/core/TableFooter"; +import TableRow from "@material-ui/core/TableRow"; +import Typography from "@material-ui/core/Typography"; +import DeleteIcon from "@material-ui/icons/Delete"; +import CardTitle from "@saleor/components/CardTitle"; +import TablePagination from "@saleor/components/TablePagination"; +import { renderCollection, stopPropagation } from "@saleor/misc"; +import { ListProps } from "@saleor/types"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import AppsSkeleton from "../AppsSkeleton"; +import CardContainer from "../CardContainer"; +import DeactivatedText from "../DeactivatedText"; + +export interface InstalledAppsProps extends ListProps { + appsList: AppsList_apps_edges[]; + onRemove: (id: string) => void; + onSettingsRowClick: (id: string) => () => void; +} +const numberOfColumns = 2; + +const InstalledApps: React.FC = ({ + appsList, + onRemove, + settings, + disabled, + onNextPage, + onPreviousPage, + onRowClick, + onUpdateListSettings, + onSettingsRowClick, + pageInfo, + ...props +}) => { + const intl = useIntl(); + const classes = useStyles(props); + + return ( + + } + > + <> + + + + + + + {renderCollection( + appsList, + (app, index) => + app ? ( + + + + {app.node.name} + + {!app.node.isActive && ( +
+ +
+ )} +
+ + + onRemove(app.node.id))} + > + + + +
+ ) : ( + + ), + () => ( + + + + + + + + ) + )} +
+ +
+ ); +}; + +InstalledApps.displayName = "InstalledApps"; +export default InstalledApps; diff --git a/src/apps/components/InstalledApps/index.ts b/src/apps/components/InstalledApps/index.ts new file mode 100644 index 000000000..03a42dc2f --- /dev/null +++ b/src/apps/components/InstalledApps/index.ts @@ -0,0 +1,2 @@ +export * from "./InstalledApps"; +export { default } from "./InstalledApps"; diff --git a/src/apps/components/Marketplace/Marketplace.tsx b/src/apps/components/Marketplace/Marketplace.tsx new file mode 100644 index 000000000..7ad75851d --- /dev/null +++ b/src/apps/components/Marketplace/Marketplace.tsx @@ -0,0 +1,59 @@ +import Button from "@material-ui/core/Button"; +import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; +import Typography from "@material-ui/core/Typography"; +import CardTitle from "@saleor/components/CardTitle"; +import React from "react"; +import { FormattedMessage, useIntl } from "react-intl"; + +import { useStyles } from "../../styles"; + +interface MarketplaceProps { + link?: () => void; +} + +const Marketplace: React.FC = ({ link }) => { + const intl = useIntl(); + const classes = useStyles({}); + + return ( +
+ + + + {!!link ? ( + <> + + + + + + ) : ( + + + + )} + + +
+ ); +}; + +Marketplace.displayName = "Marketplace"; +export default Marketplace; diff --git a/src/apps/components/Marketplace/index.ts b/src/apps/components/Marketplace/index.ts new file mode 100644 index 000000000..ce958567a --- /dev/null +++ b/src/apps/components/Marketplace/index.ts @@ -0,0 +1,2 @@ +export * from "./Marketplace"; +export { default } from "./Marketplace"; diff --git a/src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx b/src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx similarity index 83% rename from src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx rename to src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx index e8e4e707b..f7a571eed 100644 --- a/src/services/components/ServiceTokenCreateDialog/ServiceTokenCreateDialog.tsx +++ b/src/apps/components/TokenCreateDialog/TokenCreateDialog.tsx @@ -4,8 +4,6 @@ import DialogActions from "@material-ui/core/DialogActions"; import DialogContent from "@material-ui/core/DialogContent"; import DialogTitle from "@material-ui/core/DialogTitle"; import Paper from "@material-ui/core/Paper"; -import { makeStyles } from "@material-ui/core/styles"; -import { fade } from "@material-ui/core/styles/colorManipulator"; import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import CardSpacer from "@saleor/components/CardSpacer"; @@ -19,7 +17,9 @@ import { buttonMessages } from "@saleor/intl"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -export interface ServiceTokenCreateDialogProps { +import { useStyles } from "./styles"; + +export interface TokenCreateDialogProps { confirmButtonState: ConfirmButtonTransitionState; open: boolean; token: string | undefined; @@ -27,35 +27,15 @@ export interface ServiceTokenCreateDialogProps { onCreate: (name: string) => void; } -type ServiceTokenCreateStep = "form" | "summary"; - -const useStyles = makeStyles( - theme => ({ - cancel: { - marginRight: theme.spacing(1) - }, - copy: { - marginTop: theme.spacing(), - position: "relative", - right: theme.spacing(1) - }, - paper: { - background: fade(theme.palette.primary.main, 0.05), - padding: theme.spacing(2, 3) - } - }), - { - name: "ServiceTokenCreateDialog" - } -); +type TokenCreateStep = "form" | "summary"; function handleCopy(token: string) { navigator.clipboard.writeText(token); } -const ServiceTokenCreateDialog: React.FC = props => { +const TokenCreateDialog: React.FC = props => { const { confirmButtonState, open, token, onClose, onCreate } = props; - const [step, setStep] = React.useState("form"); + const [step, setStep] = React.useState("form"); const intl = useIntl(); const classes = useStyles(props); @@ -155,5 +135,5 @@ const ServiceTokenCreateDialog: React.FC = props ); }; -ServiceTokenCreateDialog.displayName = "ServiceTokenCreateDialog"; -export default ServiceTokenCreateDialog; +TokenCreateDialog.displayName = "TokenCreateDialog"; +export default TokenCreateDialog; diff --git a/src/apps/components/TokenCreateDialog/index.ts b/src/apps/components/TokenCreateDialog/index.ts new file mode 100644 index 000000000..0ad4789c2 --- /dev/null +++ b/src/apps/components/TokenCreateDialog/index.ts @@ -0,0 +1,2 @@ +export { default } from "./TokenCreateDialog"; +export * from "./TokenCreateDialog"; diff --git a/src/apps/components/TokenCreateDialog/styles.ts b/src/apps/components/TokenCreateDialog/styles.ts new file mode 100644 index 000000000..4ba0e9333 --- /dev/null +++ b/src/apps/components/TokenCreateDialog/styles.ts @@ -0,0 +1,22 @@ +import { makeStyles } from "@material-ui/core/styles"; +import { fade } from "@material-ui/core/styles/colorManipulator"; + +export const useStyles = makeStyles( + theme => ({ + cancel: { + marginRight: theme.spacing(1) + }, + copy: { + marginTop: theme.spacing(), + position: "relative", + right: theme.spacing(1) + }, + paper: { + background: fade(theme.palette.primary.main, 0.05), + padding: theme.spacing(2, 3) + } + }), + { + name: "TokenCreateDialog" + } +); diff --git a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx similarity index 50% rename from src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx rename to src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx index f1a9ad0f7..b639c5f72 100644 --- a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.stories.tsx +++ b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.stories.tsx @@ -2,11 +2,9 @@ import Decorator from "@saleor/storybook/Decorator"; import { storiesOf } from "@storybook/react"; import React from "react"; -import ServiceTokenDeleteDialog, { - ServiceTokenDeleteDialogProps -} from "./ServiceTokenDeleteDialog"; +import TokenDeleteDialog, { TokenDeleteDialogProps } from "./TokenDeleteDialog"; -const props: ServiceTokenDeleteDialogProps = { +const props: TokenDeleteDialogProps = { confirmButtonState: "default", name: "Slack", onClose: () => undefined, @@ -14,6 +12,6 @@ const props: ServiceTokenDeleteDialogProps = { open: true }; -storiesOf("Views / Services / Token delete", module) +storiesOf("Views / Apps / Custom app details / Token delete", module) .addDecorator(Decorator) - .add("default", () => ); + .add("default", () => ); diff --git a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx similarity index 79% rename from src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx rename to src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx index 099aedaa6..422b2f759 100644 --- a/src/services/components/ServiceTokenDeleteDialog/ServiceTokenDeleteDialog.tsx +++ b/src/apps/components/TokenDeleteDialog/TokenDeleteDialog.tsx @@ -4,7 +4,7 @@ import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -export interface ServiceTokenDeleteDialogProps { +export interface TokenDeleteDialogProps { confirmButtonState: ConfirmButtonTransitionState; open: boolean; onConfirm: () => void; @@ -12,7 +12,7 @@ export interface ServiceTokenDeleteDialogProps { name: string; } -const ServiceTokenDeleteDialog: React.FC = ({ +const TokenDeleteDialog: React.FC = ({ name, confirmButtonState, onClose, @@ -29,7 +29,7 @@ const ServiceTokenDeleteDialog: React.FC = ({ onConfirm={onConfirm} variant="delete" title={intl.formatMessage({ - defaultMessage: "Delete Service Account", + defaultMessage: "Delete Token", description: "dialog title" })} > @@ -46,5 +46,5 @@ const ServiceTokenDeleteDialog: React.FC = ({ ); }; -ServiceTokenDeleteDialog.displayName = "ServiceTokenDeleteDialog"; -export default ServiceTokenDeleteDialog; +TokenDeleteDialog.displayName = "TokenDeleteDialog"; +export default TokenDeleteDialog; diff --git a/src/apps/components/TokenDeleteDialog/index.ts b/src/apps/components/TokenDeleteDialog/index.ts new file mode 100644 index 000000000..536bbc3a4 --- /dev/null +++ b/src/apps/components/TokenDeleteDialog/index.ts @@ -0,0 +1,2 @@ +export * from "./TokenDeleteDialog"; +export { default } from "./TokenDeleteDialog"; diff --git a/src/apps/fixtures.ts b/src/apps/fixtures.ts new file mode 100644 index 000000000..eee4f6c2b --- /dev/null +++ b/src/apps/fixtures.ts @@ -0,0 +1,134 @@ +import { + AppTypeEnum, + JobStatusEnum, + PermissionEnum +} from "../types/globalTypes"; +import { App_app } from "./types/App"; +import { AppFetch_appFetchManifest_manifest } from "./types/AppFetch"; +import { AppsInstallations_appsInstallations } from "./types/AppsInstallations"; +import { AppsList_apps_edges } from "./types/AppsList"; + +export const appsList: AppsList_apps_edges[] = [ + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: true, + name: "app", + type: AppTypeEnum.THIRDPARTY + } + }, + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: false, + name: "app1", + type: AppTypeEnum.THIRDPARTY + } + } +]; + +export const customAppsList: AppsList_apps_edges[] = [ + { + __typename: "AppCountableEdge", + node: { + __typename: "App", + id: "QXBwOjE3Ng==", + isActive: true, + name: "app custom", + type: AppTypeEnum.LOCAL + } + } +]; + +export const appsInProgress: AppsInstallations_appsInstallations[] = [ + { + __typename: "AppInstallation", + appName: "app", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Failed to connect to app. Try later or contact with app support.", + status: JobStatusEnum.FAILED + }, + { + __typename: "AppInstallation", + appName: "app pending", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Pending.", + status: JobStatusEnum.PENDING + }, + { + __typename: "AppInstallation", + appName: "app success", + id: "QXBwSW5zdGFsbGF0aW9uOjk2", + manifestUrl: "http://localhost:3000/manifest", + message: "Success.", + status: JobStatusEnum.SUCCESS + } +]; + +export const appDetails: App_app = { + __typename: "App", + aboutApp: "Lorem ipsum", + accessToken: "token", + appUrl: "http://localhost:8888/app", + configurationUrl: "htpp://localhost:8888/configuration", + created: "2020-06-02T12:24:26.818138+00:00", + dataPrivacy: "Lorem ipsum", + dataPrivacyUrl: "http://localhost:8888/app-data-privacy", + homepageUrl: "http://localhost:8888/homepage", + id: "QXBwOjE4MQ==", + isActive: true, + metadata: [], + name: "app1", + permissions: [ + { + __typename: "Permission", + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders." + }, + { + __typename: "Permission", + code: PermissionEnum.MANAGE_USERS, + name: "Manage customers." + } + ], + privateMetadata: [], + supportUrl: "http://localhost:8888/support", + tokens: [], + type: AppTypeEnum.THIRDPARTY, + version: "1.0.0", + webhooks: [] +}; + +export const installApp: AppFetch_appFetchManifest_manifest = { + __typename: "Manifest", + + about: "Lorem ipsum", + appUrl: null, + configurationUrl: null, + dataPrivacy: null, + dataPrivacyUrl: null, + homepageUrl: null, + identifier: "app", + name: "app", + permissions: [ + { + __typename: "Permission", + code: PermissionEnum.MANAGE_USERS, + name: "Manage users" + }, + { + __typename: "Permission", + code: PermissionEnum.MANAGE_ORDERS, + name: "Manage orders" + } + ], + supportUrl: null, + tokenTargetUrl: null, + version: "1.0" +}; diff --git a/src/apps/index.tsx b/src/apps/index.tsx new file mode 100644 index 000000000..79156da07 --- /dev/null +++ b/src/apps/index.tsx @@ -0,0 +1,118 @@ +import { sectionNames } from "@saleor/intl"; +import WebhooksRoutes from "@saleor/webhooks"; +import { parse as parseQs } from "qs"; +import React from "react"; +import { useIntl } from "react-intl"; +import { Route, RouteComponentProps, Switch } from "react-router-dom"; + +import { WindowTitle } from "../components/WindowTitle"; +import { + AppDetailsUrlQueryParams, + appInstallPath, + AppInstallUrlQueryParams, + AppListUrlQueryParams, + appPath, + appSettingsPath, + appsListPath, + customAppAddPath, + customAppPath, + CustomAppUrlQueryParams +} from "./urls"; +import AppDetailsView from "./views/AppDetails"; +import AppDetailsSettingsView from "./views/AppDetailsSettings"; +import AppInstallView from "./views/AppInstall"; +import AppsListView from "./views/AppsList"; +import CustomAppCreateView from "./views/CustomAppCreate"; +import CustomAppDetailsView from "./views/CustomAppDetails"; + +const AppDetails: React.FC> = ({ + match +}) => { + const qs = parseQs(location.search.substr(1)); + const params: AppDetailsUrlQueryParams = qs; + + return ( + + ); +}; + +const AppDetailsSettings: React.FC> = ({ + match +}) => ; + +const AppInstall: React.FC = props => { + const qs = parseQs(location.search.substr(1)); + const params: AppInstallUrlQueryParams = qs; + + return ; +}; + +interface CustomAppDetailsProps extends RouteComponentProps<{ id: string }> { + token: string; + onTokenClose: () => void; +} + +const CustomAppDetails: React.FC = ({ + match, + token, + onTokenClose +}) => { + const qs = parseQs(location.search.substr(1)); + const params: CustomAppUrlQueryParams = qs; + + return ( + + ); +}; + +const AppsList: React.FC = () => { + const qs = parseQs(location.search.substr(1)); + const params: AppListUrlQueryParams = qs; + + return ; +}; +const Component = () => { + const intl = useIntl(); + const [token, setToken] = React.useState(null); + + return ( + <> + + + + } + /> + + + + ( + setToken(null)} + /> + )} + /> + + + + + ); +}; + +export default Component; diff --git a/src/apps/mutations.ts b/src/apps/mutations.ts new file mode 100644 index 000000000..cc2f79976 --- /dev/null +++ b/src/apps/mutations.ts @@ -0,0 +1,269 @@ +import { appFragment } from "@saleor/fragments/apps"; +import { appErrorFragment } from "@saleor/fragments/errors"; +import { webhooksFragment } from "@saleor/fragments/webhooks"; +import makeMutation from "@saleor/hooks/makeMutation"; +import gql from "graphql-tag"; + +import { AppActivate, AppActivateVariables } from "./types/AppActivate"; +import { AppCreate, AppCreateVariables } from "./types/AppCreate"; +import { AppDeactivate, AppDeactivateVariables } from "./types/AppDeactivate"; +import { AppDelete, AppDeleteVariables } from "./types/AppDelete"; +import { + AppDeleteFailedInstallation, + AppDeleteFailedInstallationVariables +} from "./types/AppDeleteFailedInstallation"; +import { AppFetch, AppFetchVariables } from "./types/AppFetch"; +import { AppInstall, AppInstallVariables } from "./types/AppInstall"; +import { + AppRetryInstall, + AppRetryInstallVariables +} from "./types/AppRetryInstall"; +import { + AppTokenCreate, + AppTokenCreateVariables +} from "./types/AppTokenCreate"; +import { + AppTokenDelete, + AppTokenDeleteVariables +} from "./types/AppTokenDelete"; +import { AppUpdate, AppUpdateVariables } from "./types/AppUpdate"; + +export const appCreateMutation = gql` + ${appFragment} + ${webhooksFragment} + ${appErrorFragment} + mutation AppCreate($input: AppInput!) { + appCreate(input: $input) { + authToken + app { + ...AppFragment + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeleteMutation = gql` + ${appFragment} + ${webhooksFragment} + ${appErrorFragment} + mutation AppDelete($id: ID!) { + appDelete(id: $id) { + app { + ...AppFragment + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeleteFailedInstallationMutation = gql` + ${appErrorFragment} + mutation AppDeleteFailedInstallation($id: ID!) { + appDeleteFailedInstallation(id: $id) { + appInstallation { + id + status + appName + message + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appFetchMutation = gql` + mutation AppFetch($manifestUrl: String!) { + appFetchManifest(manifestUrl: $manifestUrl) { + manifest { + identifier + version + about + name + appUrl + configurationUrl + tokenTargetUrl + dataPrivacy + dataPrivacyUrl + homepageUrl + supportUrl + permissions { + code + name + } + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appInstallMutation = gql` + ${appErrorFragment} + mutation AppInstall($input: AppInstallInput!) { + appInstall(input: $input) { + appInstallation { + id + status + appName + manifestUrl + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appRetryInstallMutation = gql` + ${appErrorFragment} + mutation AppRetryInstall($id: ID!) { + appRetryInstall(id: $id) { + appInstallation { + id + status + appName + manifestUrl + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appActivateMutation = gql` + ${appErrorFragment} + mutation AppActivate($id: ID!) { + appActivate(id: $id) { + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appDeactivateMutation = gql` + ${appErrorFragment} + mutation AppDeactivate($id: ID!) { + appDeactivate(id: $id) { + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appUpdateMutation = gql` + ${appErrorFragment} + ${appFragment} + ${webhooksFragment} + mutation AppUpdate($id: ID!, $input: AppInput!) { + appUpdate(id: $id, input: $input) { + app { + ...AppFragment + permissions { + code + name + } + } + errors: appErrors { + ...AppErrorFragment + message + permissions + } + } + } +`; + +export const appTokenCreateMutation = gql` + ${appErrorFragment} + mutation AppTokenCreate($input: AppTokenInput!) { + appTokenCreate(input: $input) { + appToken { + name + authToken + id + } + authToken + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const appTokenDeleteMutation = gql` + ${appErrorFragment} + mutation AppTokenDelete($id: ID!) { + appTokenDelete(id: $id) { + appToken { + name + authToken + id + } + errors: appErrors { + ...AppErrorFragment + } + } + } +`; + +export const useAppCreateMutation = makeMutation( + appCreateMutation +); + +export const useAppDeleteMutation = makeMutation( + appDeleteMutation +); + +export const useAppDeleteFailedInstallationMutation = makeMutation< + AppDeleteFailedInstallation, + AppDeleteFailedInstallationVariables +>(appDeleteFailedInstallationMutation); + +export const useAppInstallMutation = makeMutation< + AppInstall, + AppInstallVariables +>(appInstallMutation); + +export const useAppRetryInstallMutation = makeMutation< + AppRetryInstall, + AppRetryInstallVariables +>(appRetryInstallMutation); + +export const useAppManifestFetchMutation = makeMutation< + AppFetch, + AppFetchVariables +>(appFetchMutation); + +export const useAppActivateMutation = makeMutation< + AppActivate, + AppActivateVariables +>(appActivateMutation); + +export const useAppDeactivateMutation = makeMutation< + AppDeactivate, + AppDeactivateVariables +>(appDeactivateMutation); + +export const useAppUpdateMutation = makeMutation( + appUpdateMutation +); + +export const useAppTokenCreateMutation = makeMutation< + AppTokenCreate, + AppTokenCreateVariables +>(appTokenCreateMutation); + +export const useAppTokenDeleteMutation = makeMutation< + AppTokenDelete, + AppTokenDeleteVariables +>(appTokenDeleteMutation); diff --git a/src/apps/queries.ts b/src/apps/queries.ts new file mode 100644 index 000000000..38fde017e --- /dev/null +++ b/src/apps/queries.ts @@ -0,0 +1,83 @@ +import { appFragment } from "@saleor/fragments/apps"; +import { webhooksFragment } from "@saleor/fragments/webhooks"; +import makeQuery from "@saleor/hooks/makeQuery"; +import gql from "graphql-tag"; + +import { App, AppVariables } from "./types/App"; +import { AppsInstallations } from "./types/AppsInstallations"; +import { AppsList, AppsListVariables } from "./types/AppsList"; + +const appsList = gql` + query AppsList( + $before: String + $after: String + $first: Int + $last: Int + $sort: AppSortingInput + $filter: AppFilterInput + ) { + apps( + before: $before + after: $after + first: $first + last: $last + sortBy: $sort + filter: $filter + ) { + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + totalCount + edges { + node { + id + name + isActive + type + } + } + } + } +`; + +const appsInProgressList = gql` + query AppsInstallations { + appsInstallations { + status + message + appName + manifestUrl + id + } + } +`; + +const appDetails = gql` + ${appFragment} + ${webhooksFragment} + query App($id: ID!) { + app(id: $id) { + ...AppFragment + aboutApp + permissions { + code + name + } + dataPrivacy + dataPrivacyUrl + } + } +`; + +export const useAppsListQuery = makeQuery( + appsList +); + +export const useAppsInProgressListQuery = makeQuery( + appsInProgressList +); + +export const useAppDetails = makeQuery(appDetails); diff --git a/src/apps/styles.ts b/src/apps/styles.ts new file mode 100644 index 000000000..9d6e83224 --- /dev/null +++ b/src/apps/styles.ts @@ -0,0 +1,204 @@ +import { makeStyles } from "@material-ui/core/styles"; + +export const useStyles = makeStyles( + theme => ({ + [theme.breakpoints.up("lg")]: { + colName: { + "&&": { + width: "auto" + } + } + }, + alignRight: { + textAlign: "right" + }, + appContainer: { + marginBottom: theme.spacing(3) + }, + appContent: { + "&:last-child": { + padding: "0!important" + }, + padding: 0 + }, + appHeader: { + marginBottom: theme.spacing(3) + }, + appHeaderLinks: { + "& img": { + marginRight: theme.spacing(1) + }, + alignItems: "center", + display: "flex", + padding: theme.spacing(2, 0) + }, + appName: { + color: theme.palette.primary.main + }, + colAction: { + "&&": { + paddingRight: theme.spacing(1), + textAlign: "right" + }, + textAlign: "right" + }, + colInstallAction: { + "& > *": { + display: "inline-flex" + } + }, + colName: { + paddingLeft: 0, + width: theme.spacing(30) + }, + colSpinner: { + "& svg": { + textAlign: "right" + }, + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(2) + }, + customTooltip: { + "& > div": { + backgroundColor: theme.palette.error.main, + borderRadius: theme.spacing(1), + color: theme.palette.primary.contrastText, + padding: theme.spacing(2) + }, + padding: "0!important" + }, + error: { + "& svg": { + bottom: theme.spacing(0.2), + marginLeft: theme.spacing(0.6), + position: "relative" + }, + color: theme.palette.error.main, + margin: theme.spacing(0, 1, 0.7, 0) + }, + headerLinkContainer: { + "& span": { + fontWeight: 500 + }, + alignItems: "center", + display: "flex", + fontSize: theme.spacing(2), + fontWeight: 500, + lineHeight: 1.2, + marginRight: theme.spacing(3), + padding: 0, + textTransform: "none" + }, + hr: { + border: "none", + borderTop: `1px solid ${theme.palette.divider}`, + height: 0, + marginBottom: 0, + marginTop: 0, + width: "100%" + }, + installAppContainer: { + "& > div": { + position: "relative" + }, + "& img": { + position: "relative" + }, + display: "flex", + justifyContent: "space-between", + padding: theme.spacing(2, 0), + position: "relative", + width: theme.spacing(35) + }, + installCard: { + "&:before": { + backgroundColor: theme.palette.divider, + content: "''", + height: 2, + position: "absolute", + top: "50%", + transform: "translateY(-50%)", + width: theme.spacing(30) + }, + display: "flex", + justifyContent: "center", + position: "relative" + }, + installIcon: { + alignItems: "center", + backgroundColor: theme.palette.divider, + border: `1px solid ${theme.palette.divider}`, + borderRadius: "50%", + display: "flex", + height: theme.spacing(9), + justifyContent: "center", + overflow: "hidden", + width: theme.spacing(9) + }, + installPermissionTitle: { + fontWeight: 500 + }, + installPrivacyText: { + "& a": { + color: theme.palette.primary.main, + textDecoration: "none" + }, + color: theme.palette.text.hint + }, + installSaleorIcon: { + backgroundColor: theme.palette.secondary.main, + border: "none" + }, + installSpacer: { + margin: theme.spacing(2, 0) + }, + installText: { + color: theme.palette.primary.contrastText + }, + linkContainer: { + fontWeight: 500, + marginTop: theme.spacing(1.5) + }, + marketplaceContent: { + "& button": { + marginTop: theme.spacing(1) + }, + "&:last-child": { + padding: theme.spacing(2, 3, 2, 3) + }, + padding: theme.spacing(1) + }, + permissionsContainer: { + "& li": { + "&:last-child": { + marginBottom: 0 + }, + marginBottom: theme.spacing(1) + }, + paddingLeft: theme.spacing(2) + }, + retryBtnCol: { + paddingRight: theme.spacing(1), + width: theme.spacing(14) + }, + statusWrapper: { + display: "inline-block", + marginLeft: theme.spacing(2.5) + }, + table: { + tableLayout: "fixed" + }, + tableRow: { + cursor: "pointer" + }, + text: { + color: theme.palette.text.secondary + }, + title: { + flex: 1, + fontWeight: 500, + lineHeight: 1 + } + }), + { name: "AppList" } +); diff --git a/src/apps/types/App.ts b/src/apps/types/App.ts new file mode 100644 index 000000000..833e8d218 --- /dev/null +++ b/src/apps/types/App.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: App +// ==================================================== + +export interface App_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface App_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface App_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface App_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface App_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: App_app_webhooks_app; +} + +export interface App_app_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface App_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (App_app_privateMetadata | null)[]; + metadata: (App_app_metadata | null)[]; + tokens: (App_app_tokens | null)[] | null; + webhooks: (App_app_webhooks | null)[] | null; + aboutApp: string | null; + permissions: (App_app_permissions | null)[] | null; + dataPrivacy: string | null; + dataPrivacyUrl: string | null; +} + +export interface App { + app: App_app | null; +} + +export interface AppVariables { + id: string; +} diff --git a/src/apps/types/AppActivate.ts b/src/apps/types/AppActivate.ts new file mode 100644 index 000000000..d4bae0f7a --- /dev/null +++ b/src/apps/types/AppActivate.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppActivate +// ==================================================== + +export interface AppActivate_appActivate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppActivate_appActivate { + __typename: "AppActivate"; + errors: AppActivate_appActivate_errors[]; +} + +export interface AppActivate { + appActivate: AppActivate_appActivate | null; +} + +export interface AppActivateVariables { + id: string; +} diff --git a/src/apps/types/AppCreate.ts b/src/apps/types/AppCreate.ts new file mode 100644 index 000000000..a3cb7cb0f --- /dev/null +++ b/src/apps/types/AppCreate.ts @@ -0,0 +1,84 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInput, AppTypeEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppCreate +// ==================================================== + +export interface AppCreate_appCreate_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppCreate_appCreate_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppCreate_appCreate_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppCreate_appCreate_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppCreate_appCreate_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppCreate_appCreate_app_webhooks_app; +} + +export interface AppCreate_appCreate_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppCreate_appCreate_app_privateMetadata | null)[]; + metadata: (AppCreate_appCreate_app_metadata | null)[]; + tokens: (AppCreate_appCreate_app_tokens | null)[] | null; + webhooks: (AppCreate_appCreate_app_webhooks | null)[] | null; +} + +export interface AppCreate_appCreate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppCreate_appCreate { + __typename: "AppCreate"; + authToken: string | null; + app: AppCreate_appCreate_app | null; + errors: AppCreate_appCreate_errors[]; +} + +export interface AppCreate { + appCreate: AppCreate_appCreate | null; +} + +export interface AppCreateVariables { + input: AppInput; +} diff --git a/src/apps/types/AppDeactivate.ts b/src/apps/types/AppDeactivate.ts new file mode 100644 index 000000000..f391ecb2a --- /dev/null +++ b/src/apps/types/AppDeactivate.ts @@ -0,0 +1,30 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDeactivate +// ==================================================== + +export interface AppDeactivate_appDeactivate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDeactivate_appDeactivate { + __typename: "AppDeactivate"; + errors: AppDeactivate_appDeactivate_errors[]; +} + +export interface AppDeactivate { + appDeactivate: AppDeactivate_appDeactivate | null; +} + +export interface AppDeactivateVariables { + id: string; +} diff --git a/src/apps/types/AppDelete.ts b/src/apps/types/AppDelete.ts new file mode 100644 index 000000000..af2a28456 --- /dev/null +++ b/src/apps/types/AppDelete.ts @@ -0,0 +1,83 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDelete +// ==================================================== + +export interface AppDelete_appDelete_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppDelete_appDelete_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppDelete_appDelete_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppDelete_appDelete_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppDelete_appDelete_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppDelete_appDelete_app_webhooks_app; +} + +export interface AppDelete_appDelete_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppDelete_appDelete_app_privateMetadata | null)[]; + metadata: (AppDelete_appDelete_app_metadata | null)[]; + tokens: (AppDelete_appDelete_app_tokens | null)[] | null; + webhooks: (AppDelete_appDelete_app_webhooks | null)[] | null; +} + +export interface AppDelete_appDelete_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDelete_appDelete { + __typename: "AppDelete"; + app: AppDelete_appDelete_app | null; + errors: AppDelete_appDelete_errors[]; +} + +export interface AppDelete { + appDelete: AppDelete_appDelete | null; +} + +export interface AppDeleteVariables { + id: string; +} diff --git a/src/apps/types/AppDeleteFailedInstallation.ts b/src/apps/types/AppDeleteFailedInstallation.ts new file mode 100644 index 000000000..70dd4860f --- /dev/null +++ b/src/apps/types/AppDeleteFailedInstallation.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppDeleteFailedInstallation +// ==================================================== + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + message: string | null; +} + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppDeleteFailedInstallation_appDeleteFailedInstallation { + __typename: "AppDeleteFailedInstallation"; + appInstallation: AppDeleteFailedInstallation_appDeleteFailedInstallation_appInstallation | null; + errors: AppDeleteFailedInstallation_appDeleteFailedInstallation_errors[]; +} + +export interface AppDeleteFailedInstallation { + appDeleteFailedInstallation: AppDeleteFailedInstallation_appDeleteFailedInstallation | null; +} + +export interface AppDeleteFailedInstallationVariables { + id: string; +} diff --git a/src/apps/types/AppErrorFragment.ts b/src/apps/types/AppErrorFragment.ts new file mode 100644 index 000000000..2dca654b1 --- /dev/null +++ b/src/apps/types/AppErrorFragment.ts @@ -0,0 +1,17 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppErrorFragment +// ==================================================== + +export interface AppErrorFragment { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} diff --git a/src/apps/types/AppFetch.ts b/src/apps/types/AppFetch.ts new file mode 100644 index 000000000..3b09b98c4 --- /dev/null +++ b/src/apps/types/AppFetch.ts @@ -0,0 +1,53 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { PermissionEnum, AppErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppFetch +// ==================================================== + +export interface AppFetch_appFetchManifest_manifest_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface AppFetch_appFetchManifest_manifest { + __typename: "Manifest"; + identifier: string; + version: string; + about: string | null; + name: string; + appUrl: string | null; + configurationUrl: string | null; + tokenTargetUrl: string | null; + dataPrivacy: string | null; + dataPrivacyUrl: string | null; + homepageUrl: string | null; + supportUrl: string | null; + permissions: (AppFetch_appFetchManifest_manifest_permissions | null)[] | null; +} + +export interface AppFetch_appFetchManifest_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppFetch_appFetchManifest { + __typename: "AppFetchManifest"; + manifest: AppFetch_appFetchManifest_manifest | null; + errors: AppFetch_appFetchManifest_errors[]; +} + +export interface AppFetch { + appFetchManifest: AppFetch_appFetchManifest | null; +} + +export interface AppFetchVariables { + manifestUrl: string; +} diff --git a/src/apps/types/AppFragment.ts b/src/apps/types/AppFragment.ts new file mode 100644 index 000000000..ef2f53128 --- /dev/null +++ b/src/apps/types/AppFragment.ts @@ -0,0 +1,61 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppFragment +// ==================================================== + +export interface AppFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppFragment_webhooks_app; +} + +export interface AppFragment { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppFragment_privateMetadata | null)[]; + metadata: (AppFragment_metadata | null)[]; + tokens: (AppFragment_tokens | null)[] | null; + webhooks: (AppFragment_webhooks | null)[] | null; +} diff --git a/src/apps/types/AppInstall.ts b/src/apps/types/AppInstall.ts new file mode 100644 index 000000000..4952ab004 --- /dev/null +++ b/src/apps/types/AppInstall.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInstallInput, JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppInstall +// ==================================================== + +export interface AppInstall_appInstall_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + manifestUrl: string; +} + +export interface AppInstall_appInstall_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppInstall_appInstall { + __typename: "AppInstall"; + appInstallation: AppInstall_appInstall_appInstallation | null; + errors: AppInstall_appInstall_errors[]; +} + +export interface AppInstall { + appInstall: AppInstall_appInstall | null; +} + +export interface AppInstallVariables { + input: AppInstallInput; +} diff --git a/src/apps/types/AppRetryInstall.ts b/src/apps/types/AppRetryInstall.ts new file mode 100644 index 000000000..31b8dd049 --- /dev/null +++ b/src/apps/types/AppRetryInstall.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppRetryInstall +// ==================================================== + +export interface AppRetryInstall_appRetryInstall_appInstallation { + __typename: "AppInstallation"; + id: string; + status: JobStatusEnum; + appName: string; + manifestUrl: string; +} + +export interface AppRetryInstall_appRetryInstall_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppRetryInstall_appRetryInstall { + __typename: "AppRetryInstall"; + appInstallation: AppRetryInstall_appRetryInstall_appInstallation | null; + errors: AppRetryInstall_appRetryInstall_errors[]; +} + +export interface AppRetryInstall { + appRetryInstall: AppRetryInstall_appRetryInstall | null; +} + +export interface AppRetryInstallVariables { + id: string; +} diff --git a/src/apps/types/AppTokenCreate.ts b/src/apps/types/AppTokenCreate.ts new file mode 100644 index 000000000..008e74772 --- /dev/null +++ b/src/apps/types/AppTokenCreate.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTokenInput, AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppTokenCreate +// ==================================================== + +export interface AppTokenCreate_appTokenCreate_appToken { + __typename: "AppToken"; + name: string | null; + authToken: string | null; + id: string; +} + +export interface AppTokenCreate_appTokenCreate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppTokenCreate_appTokenCreate { + __typename: "AppTokenCreate"; + appToken: AppTokenCreate_appTokenCreate_appToken | null; + authToken: string | null; + errors: AppTokenCreate_appTokenCreate_errors[]; +} + +export interface AppTokenCreate { + appTokenCreate: AppTokenCreate_appTokenCreate | null; +} + +export interface AppTokenCreateVariables { + input: AppTokenInput; +} diff --git a/src/apps/types/AppTokenDelete.ts b/src/apps/types/AppTokenDelete.ts new file mode 100644 index 000000000..53bc8e02b --- /dev/null +++ b/src/apps/types/AppTokenDelete.ts @@ -0,0 +1,38 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppTokenDelete +// ==================================================== + +export interface AppTokenDelete_appTokenDelete_appToken { + __typename: "AppToken"; + name: string | null; + authToken: string | null; + id: string; +} + +export interface AppTokenDelete_appTokenDelete_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppTokenDelete_appTokenDelete { + __typename: "AppTokenDelete"; + appToken: AppTokenDelete_appTokenDelete_appToken | null; + errors: AppTokenDelete_appTokenDelete_errors[]; +} + +export interface AppTokenDelete { + appTokenDelete: AppTokenDelete_appTokenDelete | null; +} + +export interface AppTokenDeleteVariables { + id: string; +} diff --git a/src/apps/types/AppUpdate.ts b/src/apps/types/AppUpdate.ts new file mode 100644 index 000000000..a27a4f3c3 --- /dev/null +++ b/src/apps/types/AppUpdate.ts @@ -0,0 +1,91 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppInput, AppTypeEnum, PermissionEnum, AppErrorCode } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL mutation operation: AppUpdate +// ==================================================== + +export interface AppUpdate_appUpdate_app_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppUpdate_appUpdate_app_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppUpdate_appUpdate_app_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppUpdate_appUpdate_app_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppUpdate_appUpdate_app_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppUpdate_appUpdate_app_webhooks_app; +} + +export interface AppUpdate_appUpdate_app_permissions { + __typename: "Permission"; + code: PermissionEnum; + name: string; +} + +export interface AppUpdate_appUpdate_app { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppUpdate_appUpdate_app_privateMetadata | null)[]; + metadata: (AppUpdate_appUpdate_app_metadata | null)[]; + tokens: (AppUpdate_appUpdate_app_tokens | null)[] | null; + webhooks: (AppUpdate_appUpdate_app_webhooks | null)[] | null; + permissions: (AppUpdate_appUpdate_app_permissions | null)[] | null; +} + +export interface AppUpdate_appUpdate_errors { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} + +export interface AppUpdate_appUpdate { + __typename: "AppUpdate"; + app: AppUpdate_appUpdate_app | null; + errors: AppUpdate_appUpdate_errors[]; +} + +export interface AppUpdate { + appUpdate: AppUpdate_appUpdate | null; +} + +export interface AppUpdateVariables { + id: string; + input: AppInput; +} diff --git a/src/apps/types/AppsInstallations.ts b/src/apps/types/AppsInstallations.ts new file mode 100644 index 000000000..93c0aff2d --- /dev/null +++ b/src/apps/types/AppsInstallations.ts @@ -0,0 +1,22 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { JobStatusEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: AppsInstallations +// ==================================================== + +export interface AppsInstallations_appsInstallations { + __typename: "AppInstallation"; + status: JobStatusEnum; + message: string | null; + appName: string; + manifestUrl: string; + id: string; +} + +export interface AppsInstallations { + appsInstallations: AppsInstallations_appsInstallations[]; +} diff --git a/src/apps/types/AppsList.ts b/src/apps/types/AppsList.ts new file mode 100644 index 000000000..00a127bae --- /dev/null +++ b/src/apps/types/AppsList.ts @@ -0,0 +1,50 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppSortingInput, AppFilterInput, AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: AppsList +// ==================================================== + +export interface AppsList_apps_pageInfo { + __typename: "PageInfo"; + hasNextPage: boolean; + hasPreviousPage: boolean; + startCursor: string | null; + endCursor: string | null; +} + +export interface AppsList_apps_edges_node { + __typename: "App"; + id: string; + name: string | null; + isActive: boolean | null; + type: AppTypeEnum | null; +} + +export interface AppsList_apps_edges { + __typename: "AppCountableEdge"; + node: AppsList_apps_edges_node; +} + +export interface AppsList_apps { + __typename: "AppCountableConnection"; + pageInfo: AppsList_apps_pageInfo; + totalCount: number | null; + edges: AppsList_apps_edges[]; +} + +export interface AppsList { + apps: AppsList_apps | null; +} + +export interface AppsListVariables { + before?: string | null; + after?: string | null; + first?: number | null; + last?: number | null; + sort?: AppSortingInput | null; + filter?: AppFilterInput | null; +} diff --git a/src/apps/urls.ts b/src/apps/urls.ts new file mode 100644 index 000000000..7e5613dbe --- /dev/null +++ b/src/apps/urls.ts @@ -0,0 +1,59 @@ +import { stringify as stringifyQs } from "qs"; +import urlJoin from "url-join"; + +import { ActiveTab, Dialog, Pagination, SingleAction } from "../types"; + +export const MANIFEST_ATTR = "manifestUrl"; + +export type AppListUrlDialog = "remove" | "remove-app" | "remove-custom-app"; + +export type AppDetailsUrlDialog = "app-activate" | "app-deactivate"; + +export type AppListUrlQueryParams = ActiveTab & + Dialog & + SingleAction & + Pagination; + +export type AppDetailsUrlQueryParams = Dialog & + SingleAction; + +export type AppInstallUrlQueryParams = Partial<{ [MANIFEST_ATTR]: string }>; + +export enum AppListUrlSortField { + name = "name", + active = "active" +} + +export type CustomAppUrlDialog = + | "create-token" + | "remove-webhook" + | "remove-token"; +export type CustomAppUrlQueryParams = Dialog & SingleAction; + +export const appsSection = "/apps/"; +export const appsListPath = appsSection; + +export const customAppListPath = "/apps/custom/"; + +export const appPath = (id: string) => urlJoin(appsSection, id); +export const appSettingsPath = (id: string) => + urlJoin(appsSection, id, "settings"); +export const customAppPath = (id: string) => urlJoin(customAppListPath, id); +export const appInstallPath = urlJoin(appsSection, "install"); +export const appInstallUrl = appInstallPath; + +export const appUrl = (id: string, params?: AppDetailsUrlQueryParams) => + appPath(encodeURIComponent(id)) + "?" + stringifyQs(params); + +export const appSettingsUrl = (id: string, params?: AppDetailsUrlQueryParams) => + urlJoin(appPath(encodeURIComponent(id)), "settings") + + "?" + + stringifyQs(params); + +export const customAppUrl = (id: string, params?: CustomAppUrlQueryParams) => + customAppPath(encodeURIComponent(id)) + "?" + stringifyQs(params); +export const customAppAddPath = urlJoin(customAppListPath, "add"); +export const customAppAddUrl = customAppAddPath; + +export const appsListUrl = (params?: AppListUrlQueryParams) => + appsListPath + "?" + stringifyQs(params); diff --git a/src/apps/views/AppDetails/AppDetails.tsx b/src/apps/views/AppDetails/AppDetails.tsx new file mode 100644 index 000000000..6ab1138ec --- /dev/null +++ b/src/apps/views/AppDetails/AppDetails.tsx @@ -0,0 +1,125 @@ +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React from "react"; +import { useIntl } from "react-intl"; + +import AppActivateDialog from "../../components/AppActivateDialog"; +import AppDeactivateDialog from "../../components/AppDeactivateDialog"; +import AppDetailsPage from "../../components/AppDetailsPage"; +import { + useAppActivateMutation, + useAppDeactivateMutation +} from "../../mutations"; +import { useAppDetails } from "../../queries"; +import { + AppDetailsUrlDialog, + AppDetailsUrlQueryParams, + appSettingsUrl, + appsListPath, + appUrl +} from "../../urls"; + +interface AppDetailsProps { + id: string; + params: AppDetailsUrlQueryParams; +} + +export const AppDetails: React.FC = ({ id, params }) => { + const { data, loading, refetch } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const mutationOpts = { variables: { id } }; + const [activateApp, activateAppResult] = useAppActivateMutation({ + onCompleted: data => { + const errors = data?.appActivate?.errors; + if (errors?.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App activated", + description: "snackbar text" + }) + }); + refetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + } + }); + const [deactivateApp, deactivateAppResult] = useAppDeactivateMutation({ + onCompleted: data => { + const errors = data?.appDeactivate?.errors; + if (errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App deactivated", + description: "snackbar text" + }) + }); + refetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + } + }); + + const [openModal, closeModal] = createDialogActionHandlers< + AppDetailsUrlDialog, + AppDetailsUrlQueryParams + >(navigate, params => appUrl(id, params), params); + + const handleActivateConfirm = () => { + activateApp(mutationOpts); + }; + const handleDeactivateConfirm = () => { + deactivateApp(mutationOpts); + }; + + return ( + <> + + + navigate(appSettingsUrl(id))} + onAppActivateOpen={() => openModal("app-activate")} + onAppDeactivateOpen={() => openModal("app-deactivate")} + onBack={() => navigate(appsListPath)} + /> + + ); +}; + +export default AppDetails; diff --git a/src/apps/views/AppDetails/index.ts b/src/apps/views/AppDetails/index.ts new file mode 100644 index 000000000..d320b2453 --- /dev/null +++ b/src/apps/views/AppDetails/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetails"; +export { default } from "./AppDetails"; diff --git a/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx b/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx new file mode 100644 index 000000000..4044821a3 --- /dev/null +++ b/src/apps/views/AppDetailsSettings/AppDetailsSettings.tsx @@ -0,0 +1,46 @@ +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import React from "react"; +import { useIntl } from "react-intl"; + +import AppDetailsSettingsPage from "../../components/AppDetailsSettingsPage"; +import { useAppDetails } from "../../queries"; +import { appsListPath, appUrl } from "../../urls"; + +interface AppDetailsSetttingsProps { + id: string; +} + +export const AppDetailsSettings: React.FC = ({ + id +}) => { + const shop = useShop(); + const { data } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + + return ( + navigate(appUrl(id))} + onBack={() => navigate(appsListPath)} + onError={() => + notify({ + status: "error", + text: intl.formatMessage({ + defaultMessage: "Failed to fetch app settings", + description: "app settings error" + }) + }) + } + /> + ); +}; + +export default AppDetailsSettings; diff --git a/src/apps/views/AppDetailsSettings/index.ts b/src/apps/views/AppDetailsSettings/index.ts new file mode 100644 index 000000000..69a4896c3 --- /dev/null +++ b/src/apps/views/AppDetailsSettings/index.ts @@ -0,0 +1,2 @@ +export * from "./AppDetailsSettings"; +export { default } from "./AppDetailsSettings"; diff --git a/src/apps/views/AppInstall/AppInstall.tsx b/src/apps/views/AppInstall/AppInstall.tsx new file mode 100644 index 000000000..7f2042fb4 --- /dev/null +++ b/src/apps/views/AppInstall/AppInstall.tsx @@ -0,0 +1,112 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import React, { useEffect } from "react"; +import { useIntl } from "react-intl"; +import { RouteComponentProps } from "react-router-dom"; + +import AppInstallErrorPage from "../../components/AppInstallErrorPage"; +import AppInstallPage from "../../components/AppInstallPage"; +import { + useAppInstallMutation, + useAppManifestFetchMutation +} from "../../mutations"; +import { + AppInstallUrlQueryParams, + appsListUrl, + MANIFEST_ATTR +} from "../../urls"; + +interface InstallAppCreateProps extends RouteComponentProps { + params: AppInstallUrlQueryParams; +} +export const InstallAppCreate: React.FC = ({ + params +}) => { + const [, setActiveInstallations] = useLocalStorage("activeInstallations", []); + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const manifestUrl = params[MANIFEST_ATTR]; + + const [fetchManifest, fetchManifestOpts] = useAppManifestFetchMutation({ + onCompleted: data => { + if (data.appFetchManifest.errors.length) { + data.appFetchManifest.errors.forEach(error => { + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }); + }); + } + } + }); + const [installApp] = useAppInstallMutation({ + onCompleted: data => { + const installationData = data.appInstall.appInstallation; + if (data.appInstall.errors.length === 0) { + setActiveInstallations(activeInstallations => [ + ...activeInstallations, + { id: installationData.id, name: installationData.appName } + ]); + navigateToAppsList(); + } else { + data.appInstall.errors.forEach(error => { + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }); + }); + } + } + }); + + const navigateToAppsList = () => navigate(appsListUrl()); + + const handleSubmit = () => { + const manifest = fetchManifestOpts?.data?.appFetchManifest?.manifest; + installApp({ + variables: { + input: { + appName: manifest?.name, + manifestUrl, + permissions: manifest?.permissions.map(permission => permission.code) + } + } + }); + }; + + useEffect(() => { + if (manifestUrl) { + fetchManifest({ variables: { manifestUrl } }); + } else { + navigate(appsListUrl()); + } + }, []); + + return ( + <> + + {!!fetchManifestOpts.data?.appFetchManifest?.errors?.length || + !!fetchManifestOpts.error ? ( + navigate("/")} /> + ) : ( + + )} + + ); +}; + +export default InstallAppCreate; diff --git a/src/apps/views/AppInstall/index.ts b/src/apps/views/AppInstall/index.ts new file mode 100644 index 000000000..bbf79f50b --- /dev/null +++ b/src/apps/views/AppInstall/index.ts @@ -0,0 +1,2 @@ +export * from "./AppInstall"; +export { default } from "./AppInstall"; diff --git a/src/apps/views/AppsList/AppsList.tsx b/src/apps/views/AppsList/AppsList.tsx new file mode 100644 index 000000000..40c91f855 --- /dev/null +++ b/src/apps/views/AppsList/AppsList.tsx @@ -0,0 +1,341 @@ +import useListSettings from "@saleor/hooks/useListSettings"; +import useLocalStorage from "@saleor/hooks/useLocalStorage"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import usePaginator, { + createPaginationState +} from "@saleor/hooks/usePaginator"; +import { ListViews } from "@saleor/types"; +import getAppErrorMessage from "@saleor/utils/errors/app"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import React, { useEffect, useRef } from "react"; +import { useIntl } from "react-intl"; + +import { + AppSortField, + AppTypeEnum, + JobStatusEnum, + OrderDirection +} from "../../../types/globalTypes"; +import AppDeleteDialog from "../../components/AppDeleteDialog"; +import AppInProgressDeleteDialog from "../../components/AppInProgressDeleteDialog"; +import AppsListPage from "../../components/AppsListPage"; +import { + useAppDeleteFailedInstallationMutation, + useAppDeleteMutation, + useAppRetryInstallMutation +} from "../../mutations"; +import { useAppsInProgressListQuery, useAppsListQuery } from "../../queries"; +import { AppDelete } from "../../types/AppDelete"; +import { AppDeleteFailedInstallation } from "../../types/AppDeleteFailedInstallation"; +import { AppsInstallations_appsInstallations } from "../../types/AppsInstallations"; +import { AppsList_apps_edges } from "../../types/AppsList"; +import { + AppListUrlDialog, + AppListUrlQueryParams, + appSettingsUrl, + appsListUrl, + appUrl, + customAppAddUrl, + customAppUrl +} from "../../urls"; + +const getCurrentAppName = (id: string, collection?: AppsList_apps_edges[]) => + collection?.find(edge => edge.node.id === id)?.node?.name; + +const getAppInProgressName = ( + id: string, + collection?: AppsInstallations_appsInstallations[] +) => collection?.find(app => app.id === id)?.appName; +interface AppsListProps { + params: AppListUrlQueryParams; +} + +export const AppsList: React.FC = ({ params }) => { + const { action } = params; + const [activeInstallations, setActiveInstallations] = useLocalStorage( + "activeInstallations", + [] + ); + const notify = useNotifier(); + const intl = useIntl(); + const navigate = useNavigator(); + const { updateListSettings, settings } = useListSettings(ListViews.APPS_LIST); + const paginate = usePaginator(); + const paginationState = createPaginationState(settings.rowNumber, params); + const queryVariables = { + sort: { + direction: OrderDirection.DESC, + field: AppSortField.CREATION_DATE + } + }; + const intervalId = useRef(null); + + const removeInstallation = (id: string) => + setActiveInstallations(installations => + installations.filter(item => item.id !== id) + ); + + const { + data: appsInProgressData, + loading: loadingAppsInProgress, + refetch: appsInProgressRefetch + } = useAppsInProgressListQuery({ + displayLoader: false + }); + const { data, loading, refetch } = useAppsListQuery({ + displayLoader: true, + variables: { + ...paginationState, + ...queryVariables, + filter: { + type: AppTypeEnum.THIRDPARTY + } + } + }); + + const { loadNextPage, loadPreviousPage, pageInfo } = paginate( + data?.apps?.pageInfo, + paginationState, + params + ); + + const { + data: customAppsData, + loading: customAppsLoading, + refetch: customAppsRefetch + } = useAppsListQuery({ + displayLoader: true, + variables: { + first: 100, + ...queryVariables, + filter: { + type: AppTypeEnum.LOCAL + } + } + }); + + const installedAppNotify = (name: string) => { + notify({ + status: "success", + text: intl.formatMessage( + { + defaultMessage: "{name} is ready to be used", + description: "app has been installed" + }, + { name } + ), + title: intl.formatMessage({ + defaultMessage: "App installed", + description: "message title" + }) + }); + }; + const [retryInstallApp] = useAppRetryInstallMutation({ + onCompleted: data => { + const errors = data.appRetryInstall.errors; + if (!errors.length) { + const appInstallation = data.appRetryInstall.appInstallation; + setActiveInstallations(installations => [ + ...installations, + { id: appInstallation.id, name: appInstallation.appName } + ]); + } else { + errors.forEach(error => + notify({ status: "error", text: getAppErrorMessage(error, intl) }) + ); + } + } + }); + const [openModal, closeModal] = createDialogActionHandlers< + AppListUrlDialog, + AppListUrlQueryParams + >(navigate, appsListUrl, params); + + const onAppRemove = (data: AppDelete) => { + const errors = data.appDelete.errors; + if (errors.length === 0) { + if (data.appDelete.app.type === AppTypeEnum.LOCAL) { + customAppsRefetch(); + } else { + refetch(); + } + closeModal(); + removeAppNotify(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + }; + + const [deleteApp, deleteAppOpts] = useAppDeleteMutation({ + onCompleted: data => { + onAppRemove(data); + } + }); + const [ + deleteInProgressApp, + deleteInProgressAppOpts + ] = useAppDeleteFailedInstallationMutation({ + onCompleted: data => { + onAppInProgressRemove(data); + } + }); + + useEffect(() => { + const appsInProgress = appsInProgressData?.appsInstallations || []; + if (activeInstallations.length && !!appsInProgressData) { + if (!intervalId.current) { + intervalId.current = window.setInterval( + () => appsInProgressRefetch(), + 2000 + ); + } + activeInstallations.forEach(installation => { + const item = appsInProgress?.find(app => app.id === installation.id); + if (!item) { + removeInstallation(installation.id); + installedAppNotify(installation.name); + appsInProgressRefetch(); + } else if (item.status === JobStatusEnum.SUCCESS) { + removeInstallation(installation.id); + installedAppNotify(item.appName); + refetch(); + } else if (item.status === JobStatusEnum.FAILED) { + removeInstallation(installation.id); + notify({ + status: "error", + text: item.message, + title: intl.formatMessage( + { + defaultMessage: "Couldn’t Install {name}", + description: "message title" + }, + { name: item.appName } + ) + }); + } + }); + } + if (!activeInstallations.length && intervalId.current) { + clearInterval(intervalId.current); + intervalId.current = null; + } + + return () => { + if (intervalId.current) { + clearInterval(intervalId.current); + intervalId.current = null; + } + }; + }, [activeInstallations.length, appsInProgressData]); + + const handleRemoveInProgressConfirm = () => + deleteInProgressApp({ + variables: { + id: params.id + } + }); + + const handleRemoveConfirm = () => + deleteApp({ + variables: { + id: params.id + } + }); + + const removeAppNotify = () => { + notify({ + status: "success", + text: intl.formatMessage({ + defaultMessage: "App successfully removed", + description: "app has been removed" + }) + }); + }; + + const onAppInProgressRemove = (data: AppDeleteFailedInstallation) => { + const errors = data.appDeleteFailedInstallation.errors; + if (errors.length === 0) { + removeAppNotify(); + appsInProgressRefetch(); + closeModal(); + } else { + errors.forEach(error => + notify({ + status: "error", + text: getAppErrorMessage(error, intl) + }) + ); + } + }; + const onAppInstallRetry = (id: string) => + retryInstallApp({ variables: { id } }); + + const installedApps = data?.apps?.edges; + const customApps = customAppsData?.apps?.edges; + + return ( + <> + + + () => navigate(appUrl(id))} + onSettingsRowClick={id => () => navigate(appSettingsUrl(id))} + onAppInstallRetry={onAppInstallRetry} + navigateToCustomApp={id => () => navigate(customAppUrl(id))} + navigateToCustomAppCreate={() => navigate(customAppAddUrl)} + onInstalledAppRemove={id => + openModal("remove-app", { + id + }) + } + onCustomAppRemove={id => + openModal("remove-custom-app", { + id + }) + } + onAppInProgressRemove={id => + openModal("remove", { + id + }) + } + /> + + ); +}; + +export default AppsList; diff --git a/src/apps/views/AppsList/index.ts b/src/apps/views/AppsList/index.ts new file mode 100644 index 000000000..571192ed9 --- /dev/null +++ b/src/apps/views/AppsList/index.ts @@ -0,0 +1,2 @@ +export * from "./AppsList"; +export { default } from "./AppsList"; diff --git a/src/apps/views/CustomAppCreate/CustomAppCreate.tsx b/src/apps/views/CustomAppCreate/CustomAppCreate.tsx new file mode 100644 index 000000000..8aacf4730 --- /dev/null +++ b/src/apps/views/CustomAppCreate/CustomAppCreate.tsx @@ -0,0 +1,77 @@ +import { WindowTitle } from "@saleor/components/WindowTitle"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import React from "react"; +import { useIntl } from "react-intl"; + +import CustomAppCreatePage, { + CustomAppCreatePageFormData +} from "../../components/CustomAppCreatePage"; +import { useAppCreateMutation } from "../../mutations"; +import { AppCreate } from "../../types/AppCreate"; +import { appsListUrl, customAppUrl } from "../../urls"; + +interface CustomAppCreateProps { + setToken: (token: string) => void; +} +export const CustomAppCreate: React.FC = ({ + setToken +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const shop = useShop(); + + const onSubmit = (data: AppCreate) => { + if (data.appCreate.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(customAppUrl(data.appCreate.app.id)); + setToken(data.appCreate.authToken); + } + }; + + const handleBack = () => navigate(appsListUrl()); + + const [createApp, createAppOpts] = useAppCreateMutation({ + onCompleted: onSubmit + }); + + const handleSubmit = (data: CustomAppCreatePageFormData) => + createApp({ + variables: { + input: { + isActive: data.isActive, + name: data.name, + permissions: data.hasFullAccess + ? shop.permissions.map(permission => permission.code) + : data.permissions + } + } + }); + + return ( + <> + + + + ); +}; + +export default CustomAppCreate; diff --git a/src/apps/views/CustomAppCreate/index.ts b/src/apps/views/CustomAppCreate/index.ts new file mode 100644 index 000000000..0fc349041 --- /dev/null +++ b/src/apps/views/CustomAppCreate/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppCreate"; +export { default } from "./CustomAppCreate"; diff --git a/src/apps/views/CustomAppDetails/CustomAppDetails.tsx b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx new file mode 100644 index 000000000..da7111e6d --- /dev/null +++ b/src/apps/views/CustomAppDetails/CustomAppDetails.tsx @@ -0,0 +1,226 @@ +import TokenCreateDialog from "@saleor/apps/components/TokenCreateDialog"; +import TokenDeleteDialog from "@saleor/apps/components/TokenDeleteDialog"; +import NotFoundPage from "@saleor/components/NotFoundPage"; +import { WindowTitle } from "@saleor/components/WindowTitle"; +import { API_URI } from "@saleor/config"; +import useNavigator from "@saleor/hooks/useNavigator"; +import useNotifier from "@saleor/hooks/useNotifier"; +import useShop from "@saleor/hooks/useShop"; +import { commonMessages } from "@saleor/intl"; +import { getStringOrPlaceholder } from "@saleor/misc"; +import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import WebhookDeleteDialog from "@saleor/webhooks/components/WebhookDeleteDialog"; +import { useWebhookDeleteMutation } from "@saleor/webhooks/mutations"; +import { WebhookDelete } from "@saleor/webhooks/types/WebhookDelete"; +import { webhookAddPath, webhookPath } from "@saleor/webhooks/urls"; +import React from "react"; +import { useIntl } from "react-intl"; + +import CustomAppDetailsPage, { + CustomAppDetailsPageFormData +} from "../../components/CustomAppDetailsPage"; +import { + useAppTokenCreateMutation, + useAppTokenDeleteMutation, + useAppUpdateMutation +} from "../../mutations"; +import { useAppDetails } from "../../queries"; +import { AppTokenCreate } from "../../types/AppTokenCreate"; +import { AppTokenDelete } from "../../types/AppTokenDelete"; +import { AppUpdate } from "../../types/AppUpdate"; +import { + appsListUrl, + customAppUrl, + CustomAppUrlDialog, + CustomAppUrlQueryParams +} from "../../urls"; + +interface OrderListProps { + id: string; + params: CustomAppUrlQueryParams; + token: string; + onTokenClose: () => void; +} + +export const CustomAppDetails: React.FC = ({ + id, + params, + token, + onTokenClose +}) => { + const navigate = useNavigator(); + const notify = useNotifier(); + const intl = useIntl(); + const shop = useShop(); + + React.useEffect(() => onTokenClose, []); + + const [openModal, closeModal] = createDialogActionHandlers< + CustomAppUrlDialog, + CustomAppUrlQueryParams + >(navigate, params => customAppUrl(id, params), params); + + const { data, loading, refetch } = useAppDetails({ + displayLoader: true, + variables: { id } + }); + + const onWebhookDelete = (data: WebhookDelete) => { + if (data.webhookDelete.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + navigate(customAppUrl(id)); + closeModal(); + refetch(); + } + }; + + const [webhookDelete, webhookDeleteOpts] = useWebhookDeleteMutation({ + onCompleted: onWebhookDelete + }); + + const handleRemoveWebhookConfirm = () => { + webhookDelete({ + variables: { + id: params.id + } + }); + }; + + const onAppUpdate = (data: AppUpdate) => { + if (data?.appUpdate?.errors?.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + } + }; + const handleBack = () => navigate(appsListUrl()); + const customApp = data?.app; + + if (customApp === null) { + return ; + } + + const onTokenCreate = (data: AppTokenCreate) => { + if (data?.appTokenCreate?.errors.length === 0) { + refetch(); + } + }; + const onTokenDelete = (data: AppTokenDelete) => { + if (data?.appTokenDelete?.errors.length === 0) { + notify({ + status: "success", + text: intl.formatMessage(commonMessages.savedChanges) + }); + refetch(); + closeModal(); + } + }; + + const [updateApp, updateAppOpts] = useAppUpdateMutation({ + onCompleted: onAppUpdate + }); + const [createToken, createTokenOpts] = useAppTokenCreateMutation({ + onCompleted: onTokenCreate + }); + const [deleteToken, deleteTokenOpts] = useAppTokenDeleteMutation({ + onCompleted: onTokenDelete + }); + + const handleSubmit = (data: CustomAppDetailsPageFormData) => + updateApp({ + variables: { + id, + input: { + isActive: data.isActive, + name: data.name, + permissions: data.hasFullAccess + ? shop.permissions.map(permission => permission.code) + : data.permissions + } + } + }); + + const handleTokenCreate = (name: string) => + createToken({ + variables: { + input: { + app: id, + name + } + } + }); + + const handleTokenDelete = () => + deleteToken({ + variables: { + id: params.id + } + }); + + const currentToken = data?.app?.tokens?.find(token => token.id === params.id); + + return ( + <> + + () => navigate(webhookPath(id))} + onApiUriClick={() => open(API_URI, "blank")} + onBack={handleBack} + onSubmit={handleSubmit} + onTokenClose={onTokenClose} + onTokenCreate={() => openModal("create-token")} + onTokenDelete={id => + openModal("remove-token", { + id + }) + } + onWebhookCreate={() => navigate(webhookAddPath(id))} + onWebhookRemove={id => + openModal("remove-webhook", { + id + }) + } + permissions={shop?.permissions} + app={data?.app} + saveButtonBarState={updateAppOpts.status} + /> + + + webhook.id === params.id)?.name + } + onClose={closeModal} + onConfirm={handleRemoveWebhookConfirm} + open={params.action === "remove-webhook"} + /> + + ); +}; + +export default CustomAppDetails; diff --git a/src/apps/views/CustomAppDetails/index.ts b/src/apps/views/CustomAppDetails/index.ts new file mode 100644 index 000000000..2461dd3f6 --- /dev/null +++ b/src/apps/views/CustomAppDetails/index.ts @@ -0,0 +1,2 @@ +export * from "./CustomAppDetails"; +export { default } from "./CustomAppDetails"; diff --git a/src/components/AccountPermissions/AccountPermissions.tsx b/src/components/AccountPermissions/AccountPermissions.tsx index 739161f5e..6a2a18562 100644 --- a/src/components/AccountPermissions/AccountPermissions.tsx +++ b/src/components/AccountPermissions/AccountPermissions.tsx @@ -98,7 +98,7 @@ const AccountPermissions: React.FC = props => { {permissionsExceeded && ( <> - + {intl.formatMessage({ defaultMessage: "This groups permissions exceeds your own. You are able only to manage permissions that you have.", @@ -108,7 +108,7 @@ const AccountPermissions: React.FC = props => {
- + {intl.formatMessage({ defaultMessage: "Available permissions", description: "card section description" @@ -127,7 +127,7 @@ const AccountPermissions: React.FC = props => { {!permissionsExceeded && ( <> - {description} + {description} = props => { > = props => { > = props => { <>
- {errorMessage} + + {errorMessage} + )} diff --git a/src/components/AccountStatus/index.ts b/src/components/AccountStatus/index.ts deleted file mode 100644 index eb103372d..000000000 --- a/src/components/AccountStatus/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./AccountStatus"; -export * from "./AccountStatus"; diff --git a/src/components/AppLayout/menuStructure.ts b/src/components/AppLayout/menuStructure.ts index 1785de889..177c3b433 100644 --- a/src/components/AppLayout/menuStructure.ts +++ b/src/components/AppLayout/menuStructure.ts @@ -1,3 +1,4 @@ +import appsIcon from "@assets/images/menu-apps-icon.svg"; import catalogIcon from "@assets/images/menu-catalog-icon.svg"; import customerIcon from "@assets/images/menu-customers-icon.svg"; import discountsIcon from "@assets/images/menu-discounts-icon.svg"; @@ -7,6 +8,7 @@ import translationIcon from "@assets/images/menu-translation-icon.svg"; import { commonMessages, sectionNames } from "@saleor/intl"; import { IntlShape } from "react-intl"; +import { appsListPath } from "../../apps/urls"; import { categoryListUrl } from "../../categories/urls"; import { collectionListUrl } from "../../collections/urls"; import { customerListUrl } from "../../customers/urls"; @@ -102,6 +104,13 @@ function createMenuStructure(intl: IntlShape): IMenuItem[] { label: intl.formatMessage(commonMessages.discounts), permission: PermissionEnum.MANAGE_DISCOUNTS }, + { + ariaLabel: "apps", + icon: appsIcon, + label: intl.formatMessage(sectionNames.apps), + permission: PermissionEnum.MANAGE_APPS, + url: appsListPath + }, { ariaLabel: "translations", icon: translationIcon, diff --git a/src/components/AccountStatus/AccountStatus.tsx b/src/components/AppStatus/AppStatus.tsx similarity index 80% rename from src/components/AccountStatus/AccountStatus.tsx rename to src/components/AppStatus/AppStatus.tsx index d78ad8eaf..9e989a9a2 100644 --- a/src/components/AccountStatus/AccountStatus.tsx +++ b/src/components/AppStatus/AppStatus.tsx @@ -6,7 +6,7 @@ import { ControlledCheckbox } from "@saleor/components/ControlledCheckbox"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; -interface StaffStatusProps { +interface AppStatusProps { data: { isActive: boolean; }; @@ -15,7 +15,7 @@ interface StaffStatusProps { onChange: (event: React.ChangeEvent) => void; } -const StaffStatus: React.FC = ({ +const AppStatus: React.FC = ({ data, disabled, label, @@ -27,13 +27,13 @@ const StaffStatus: React.FC = ({ - - + + = ({ ); }; -StaffStatus.displayName = "StaffStatus"; -export default StaffStatus; +AppStatus.displayName = "AppStatus"; +export default AppStatus; diff --git a/src/components/AppStatus/index.ts b/src/components/AppStatus/index.ts new file mode 100644 index 000000000..567fca42a --- /dev/null +++ b/src/components/AppStatus/index.ts @@ -0,0 +1,2 @@ +export { default } from "./AppStatus"; +export * from "./AppStatus"; diff --git a/src/components/Navigator/modes/default/views.ts b/src/components/Navigator/modes/default/views.ts index 60dee6617..4e0c4c90b 100644 --- a/src/components/Navigator/modes/default/views.ts +++ b/src/components/Navigator/modes/default/views.ts @@ -11,14 +11,12 @@ import { pageListUrl } from "@saleor/pages/urls"; import { pluginListUrl } from "@saleor/plugins/urls"; import { productListUrl } from "@saleor/products/urls"; import { productTypeListUrl } from "@saleor/productTypes/urls"; -import { serviceListUrl } from "@saleor/services/urls"; import { shippingZonesListUrl } from "@saleor/shipping/urls"; import { siteSettingsUrl } from "@saleor/siteSettings/urls"; import { staffListUrl } from "@saleor/staff/urls"; import { countryListUrl } from "@saleor/taxes/urls"; import { languageListUrl } from "@saleor/translations/urls"; import { warehouseListUrl } from "@saleor/warehouses/urls"; -import { webhookListUrl } from "@saleor/webhooks/urls"; import { score } from "fuzzaldrin"; import { IntlShape } from "react-intl"; @@ -86,10 +84,6 @@ function searchInViews( label: intl.formatMessage(sectionNames.sales), url: saleListUrl() }, - { - label: intl.formatMessage(sectionNames.serviceAccounts), - url: serviceListUrl() - }, { label: intl.formatMessage(sectionNames.shipping), url: shippingZonesListUrl() @@ -114,10 +108,6 @@ function searchInViews( label: intl.formatMessage(sectionNames.vouchers), url: voucherListUrl() }, - { - label: intl.formatMessage(sectionNames.webhooks), - url: webhookListUrl() - }, { label: intl.formatMessage(sectionNames.warehouses), url: warehouseListUrl() diff --git a/src/components/TablePagination/TablePagination.tsx b/src/components/TablePagination/TablePagination.tsx index 4961a7b1c..af5f09e5c 100644 --- a/src/components/TablePagination/TablePagination.tsx +++ b/src/components/TablePagination/TablePagination.tsx @@ -94,7 +94,7 @@ const TablePagination: React.FC = props => {
{maybe(() => settings.rowNumber) && ( diff --git a/src/components/Theme/ThemeProvider.tsx b/src/components/Theme/ThemeProvider.tsx index 591358b2b..e4db1eb4e 100644 --- a/src/components/Theme/ThemeProvider.tsx +++ b/src/components/Theme/ThemeProvider.tsx @@ -1,5 +1,10 @@ import { MuiThemeProvider } from "@material-ui/core/styles"; -import React from "react"; +import { + ExtensionMessageType, + sendMessageToExtension, + ThemeChangeMessage +} from "@saleor/macaw-ui/extensions"; +import React, { useEffect } from "react"; import Helmet from "react-helmet"; import Baseline from "../../Baseline"; @@ -8,10 +13,12 @@ import { dark, light } from "./themes"; interface IThemeContext { isDark: boolean; + sendThemeToExtension: () => void; toggleTheme: () => void; } export const ThemeContext = React.createContext({ isDark: false, + sendThemeToExtension: () => undefined, toggleTheme: () => undefined }); @@ -23,17 +30,31 @@ const ThemeProvider: React.FC = ({ isDefaultDark }) => { const [isDark, setDark] = React.useState(isDefaultDark); + const sendThemeToExtension = () => + sendMessageToExtension( + { + theme: isDark ? "dark" : "light", + type: ExtensionMessageType.THEME + }, + "*" + ); + const toggleTheme = () => { setDark(!isDark); localStorage.setItem("theme", (!isDark).toString()); }; + useEffect(() => { + sendThemeToExtension(); + }, [isDark]); + const theme = createTheme(isDark ? dark : light); return ( diff --git a/src/config.ts b/src/config.ts index 6dee3beb2..7a9e4ef0c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -20,6 +20,7 @@ export const PAGINATE_BY = 20; export type ProductListColumns = "productType" | "isPublished" | "price"; export interface AppListViewSettings { + [ListViews.APPS_LIST]: ListSettings; [ListViews.CATEGORY_LIST]: ListSettings; [ListViews.COLLECTION_LIST]: ListSettings; [ListViews.CUSTOMER_LIST]: ListSettings; @@ -38,6 +39,9 @@ export interface AppListViewSettings { [ListViews.WEBHOOK_LIST]: ListSettings; } export const defaultListSettings: AppListViewSettings = { + [ListViews.APPS_LIST]: { + rowNumber: 10 + }, [ListViews.CATEGORY_LIST]: { rowNumber: PAGINATE_BY }, diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx index 87dcfc982..9b434deab 100644 --- a/src/configuration/index.tsx +++ b/src/configuration/index.tsx @@ -3,7 +3,6 @@ import { WindowTitle } from "@saleor/components/WindowTitle"; import useNavigator from "@saleor/hooks/useNavigator"; import useUser from "@saleor/hooks/useUser"; import Attributes from "@saleor/icons/Attributes"; -import Bot from "@saleor/icons/Bot"; import Navigation from "@saleor/icons/Navigation"; import Pages from "@saleor/icons/Pages"; import PermissionGroups from "@saleor/icons/PermissionGroups"; @@ -14,7 +13,6 @@ import SiteSettings from "@saleor/icons/SiteSettings"; import StaffMembers from "@saleor/icons/StaffMembers"; import Taxes from "@saleor/icons/Taxes"; import Warehouses from "@saleor/icons/Warehouses"; -import Webhooks from "@saleor/icons/Webhooks"; import { sectionNames } from "@saleor/intl"; import { maybe } from "@saleor/misc"; import { menuListUrl } from "@saleor/navigation/urls"; @@ -22,14 +20,12 @@ import { pageListUrl } from "@saleor/pages/urls"; import { permissionGroupListUrl } from "@saleor/permissionGroups/urls"; import { pluginListUrl } from "@saleor/plugins/urls"; import { productTypeListUrl } from "@saleor/productTypes/urls"; -import { serviceListUrl } from "@saleor/services/urls"; import { shippingZonesListUrl } from "@saleor/shipping/urls"; import { siteSettingsUrl } from "@saleor/siteSettings/urls"; import { staffListUrl } from "@saleor/staff/urls"; import { taxSection } from "@saleor/taxes/urls"; import { PermissionEnum } from "@saleor/types/globalTypes"; import { warehouseSection } from "@saleor/warehouses/urls"; -import { webhookListUrl } from "@saleor/webhooks/urls"; import React from "react"; import { IntlShape, useIntl } from "react-intl"; @@ -186,24 +182,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] { permission: PermissionEnum.MANAGE_PLUGINS, title: intl.formatMessage(sectionNames.plugins), url: pluginListUrl() - }, - { - description: intl.formatMessage({ - defaultMessage: "Manage external integrations accounts" - }), - icon: , - permission: PermissionEnum.MANAGE_APPS, - title: intl.formatMessage(sectionNames.serviceAccounts), - url: serviceListUrl() - }, - { - description: intl.formatMessage({ - defaultMessage: "View and update your webhook and their settings" - }), - icon: , - permission: PermissionEnum.MANAGE_WEBHOOKS, - title: intl.formatMessage(sectionNames.webhooks), - url: webhookListUrl() } ] } diff --git a/src/fixtures.ts b/src/fixtures.ts index 9b42321fe..df7afbf9b 100644 --- a/src/fixtures.ts +++ b/src/fixtures.ts @@ -370,7 +370,7 @@ export const permissions: ShopInfo_shop_permissions[] = [ name: "Manage apps." }, { - code: PermissionEnum.MANAGE_WEBHOOKS, + code: PermissionEnum.MANAGE_APPS, name: "Manage webhooks." } ].map(perm => ({ diff --git a/src/fragments/apps.ts b/src/fragments/apps.ts new file mode 100644 index 000000000..8795330a2 --- /dev/null +++ b/src/fragments/apps.ts @@ -0,0 +1,33 @@ +import gql from "graphql-tag"; + +export const appFragment = gql` + fragment AppFragment on App { + id + name + created + isActive + type + homepageUrl + appUrl + configurationUrl + supportUrl + version + accessToken + privateMetadata { + key + value + } + metadata { + key + value + } + tokens { + authToken + id + name + } + webhooks { + ...WebhookFragment + } + } +`; diff --git a/src/fragments/errors.ts b/src/fragments/errors.ts index 36154150f..0d5eb4896 100644 --- a/src/fragments/errors.ts +++ b/src/fragments/errors.ts @@ -111,3 +111,12 @@ export const invoiceErrorFragment = gql` field } `; + +export const appErrorFragment = gql` + fragment AppErrorFragment on AppError { + field + message + code + permissions + } +`; diff --git a/src/fragments/services.ts b/src/fragments/services.ts deleted file mode 100644 index fa99ae421..000000000 --- a/src/fragments/services.ts +++ /dev/null @@ -1,25 +0,0 @@ -import gql from "graphql-tag"; - -export const serviceFragment = gql` - fragment ServiceFragment on ServiceAccount { - id - name - isActive - } -`; - -export const serviceDetailsFragment = gql` - ${serviceFragment} - fragment ServiceDetailsFragment on ServiceAccount { - ...ServiceFragment - permissions { - code - name - } - tokens { - id - name - authToken - } - } -`; diff --git a/src/fragments/types/AppErrorFragment.ts b/src/fragments/types/AppErrorFragment.ts new file mode 100644 index 000000000..2dca654b1 --- /dev/null +++ b/src/fragments/types/AppErrorFragment.ts @@ -0,0 +1,17 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppErrorCode, PermissionEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppErrorFragment +// ==================================================== + +export interface AppErrorFragment { + __typename: "AppError"; + field: string | null; + message: string | null; + code: AppErrorCode; + permissions: PermissionEnum[] | null; +} diff --git a/src/fragments/types/AppFragment.ts b/src/fragments/types/AppFragment.ts new file mode 100644 index 000000000..ef2f53128 --- /dev/null +++ b/src/fragments/types/AppFragment.ts @@ -0,0 +1,61 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AppTypeEnum } from "./../../types/globalTypes"; + +// ==================================================== +// GraphQL fragment: AppFragment +// ==================================================== + +export interface AppFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface AppFragment_tokens { + __typename: "AppToken"; + authToken: string | null; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks_app { + __typename: "App"; + id: string; + name: string | null; +} + +export interface AppFragment_webhooks { + __typename: "Webhook"; + id: string; + name: string; + isActive: boolean; + app: AppFragment_webhooks_app; +} + +export interface AppFragment { + __typename: "App"; + id: string; + name: string | null; + created: any | null; + isActive: boolean | null; + type: AppTypeEnum | null; + homepageUrl: string | null; + appUrl: string | null; + configurationUrl: string | null; + supportUrl: string | null; + version: string | null; + accessToken: string | null; + privateMetadata: (AppFragment_privateMetadata | null)[]; + metadata: (AppFragment_metadata | null)[]; + tokens: (AppFragment_tokens | null)[] | null; + webhooks: (AppFragment_webhooks | null)[] | null; +} diff --git a/src/fragments/types/ServiceDetailsFragment.ts b/src/fragments/types/ServiceDetailsFragment.ts deleted file mode 100644 index b62e25f3a..000000000 --- a/src/fragments/types/ServiceDetailsFragment.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL fragment: ServiceDetailsFragment -// ==================================================== - -export interface ServiceDetailsFragment_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceDetailsFragment_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceDetailsFragment { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceDetailsFragment_permissions | null)[] | null; - tokens: (ServiceDetailsFragment_tokens | null)[] | null; -} diff --git a/src/fragments/types/ServiceFragment.ts b/src/fragments/types/ServiceFragment.ts deleted file mode 100644 index 5c0e96fec..000000000 --- a/src/fragments/types/ServiceFragment.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: ServiceFragment -// ==================================================== - -export interface ServiceFragment { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} diff --git a/src/fragments/types/WebhookFragment.ts b/src/fragments/types/WebhookFragment.ts index 27bee647d..1c8dcc8f9 100644 --- a/src/fragments/types/WebhookFragment.ts +++ b/src/fragments/types/WebhookFragment.ts @@ -6,8 +6,8 @@ // GraphQL fragment: WebhookFragment // ==================================================== -export interface WebhookFragment_serviceAccount { - __typename: "ServiceAccount"; +export interface WebhookFragment_app { + __typename: "App"; id: string; name: string | null; } @@ -17,5 +17,5 @@ export interface WebhookFragment { id: string; name: string; isActive: boolean; - serviceAccount: WebhookFragment_serviceAccount; + app: WebhookFragment_app; } diff --git a/src/fragments/types/WebhooksDetailsFragment.ts b/src/fragments/types/WebhooksDetailsFragment.ts index 8efe55bba..8eaf7e94f 100644 --- a/src/fragments/types/WebhooksDetailsFragment.ts +++ b/src/fragments/types/WebhooksDetailsFragment.ts @@ -6,8 +6,8 @@ // GraphQL fragment: WebhooksDetailsFragment // ==================================================== -export interface WebhooksDetailsFragment_serviceAccount { - __typename: "ServiceAccount"; +export interface WebhooksDetailsFragment_app { + __typename: "App"; id: string; name: string | null; } @@ -17,5 +17,5 @@ export interface WebhooksDetailsFragment { id: string; name: string; isActive: boolean; - serviceAccount: WebhooksDetailsFragment_serviceAccount; + app: WebhooksDetailsFragment_app; } diff --git a/src/fragments/webhooks.ts b/src/fragments/webhooks.ts index c31e454bd..8d71f9d4f 100644 --- a/src/fragments/webhooks.ts +++ b/src/fragments/webhooks.ts @@ -5,7 +5,7 @@ export const webhooksFragment = gql` id name isActive - serviceAccount { + app { id name } diff --git a/src/index.tsx b/src/index.tsx index 9cc19d811..15250b8cd 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -15,6 +15,8 @@ import TagManager from "react-gtm-module"; import { useIntl } from "react-intl"; import { BrowserRouter, Route, Switch } from "react-router-dom"; +import AppsSection from "./apps"; +import { appsSection } from "./apps/urls"; import AttributeSection from "./attributes"; import { attributeSection } from "./attributes/urls"; import Auth, { getAuthToken, removeAuthToken } from "./auth"; @@ -49,8 +51,6 @@ import PermissionGroupSection from "./permissionGroups"; import PluginsSection from "./plugins"; import ProductSection from "./products"; import ProductTypesSection from "./productTypes"; -import ServiceSection from "./services"; -import { serviceSection } from "./services/urls"; import ShippingSection from "./shipping"; import SiteSettingsSection from "./siteSettings"; import StaffSection from "./staff"; @@ -59,7 +59,6 @@ import TranslationsSection from "./translations"; import { PermissionEnum } from "./types/globalTypes"; import WarehouseSection from "./warehouses"; import { warehouseSection } from "./warehouses/urls"; -import WebhooksSection from "./webhooks"; interface ResponseError extends ErrorResponse { networkError?: Error & { @@ -257,11 +256,6 @@ const Routes: React.FC = () => { path="/translations" component={TranslationsSection} /> - { /> undefined, - onSubmit: () => undefined, - permissions, - saveButtonBarState: "default" -}; -storiesOf("Views / Services / Create service", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ) - .add("form errors", () => ( - ({ - __typename: "AccountError", - code: AccountErrorCode.INVALID, - field - }))} - /> - )); diff --git a/src/services/components/ServiceCreatePage/index.ts b/src/services/components/ServiceCreatePage/index.ts deleted file mode 100644 index c02c29357..000000000 --- a/src/services/components/ServiceCreatePage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceCreatePage"; -export * from "./ServiceCreatePage"; diff --git a/src/services/components/ServiceDefaultToken/index.ts b/src/services/components/ServiceDefaultToken/index.ts deleted file mode 100644 index 554fd2e80..000000000 --- a/src/services/components/ServiceDefaultToken/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDefaultToken"; -export * from "./ServiceDefaultToken"; diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx deleted file mode 100644 index ed1798913..000000000 --- a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import Decorator from "@saleor/storybook/Decorator"; -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import ServiceDeleteDialog, { - ServiceDeleteDialogProps -} from "./ServiceDeleteDialog"; - -const props: ServiceDeleteDialogProps = { - confirmButtonState: "default", - name: "Magento Importer", - onClose: () => undefined, - onConfirm: () => undefined, - open: true -}; - -storiesOf("Views / Services / Delete service", module) - .addDecorator(Decorator) - .add("default", () => ); diff --git a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx b/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx deleted file mode 100644 index e69723343..000000000 --- a/src/services/components/ServiceDeleteDialog/ServiceDeleteDialog.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import DialogContentText from "@material-ui/core/DialogContentText"; -import ActionDialog from "@saleor/components/ActionDialog"; -import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -export interface ServiceDeleteDialogProps { - confirmButtonState: ConfirmButtonTransitionState; - open: boolean; - name: string; - onClose: () => void; - onConfirm: () => void; -} - -const ServiceDeleteDialog: React.FC = ({ - confirmButtonState, - open, - name, - onClose, - onConfirm -}) => { - const intl = useIntl(); - - return ( - - - {name} - }} - /> - - - ); -}; -ServiceDeleteDialog.displayName = "ServiceDeleteDialog"; -export default ServiceDeleteDialog; diff --git a/src/services/components/ServiceDeleteDialog/index.ts b/src/services/components/ServiceDeleteDialog/index.ts deleted file mode 100644 index b43358431..000000000 --- a/src/services/components/ServiceDeleteDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDeleteDialog"; -export * from "./ServiceDeleteDialog"; diff --git a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx b/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx deleted file mode 100644 index d4d22cd0f..000000000 --- a/src/services/components/ServiceDetailsPage/ServiceDetailsPage.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { permissions } from "@saleor/fixtures"; -import Decorator from "@saleor/storybook/Decorator"; -import { AccountErrorCode } from "@saleor/types/globalTypes"; -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import { service } from "../../fixtures"; -import ServiceDetailsPage, { - ServiceDetailsPageProps -} from "./ServiceDetailsPage"; - -const props: ServiceDetailsPageProps = { - apiUri: "https://example.com/graphql/", - disabled: false, - errors: [], - onApiUriClick: () => undefined, - onBack: () => undefined, - onDelete: () => undefined, - onSubmit: () => undefined, - onTokenClose: () => undefined, - onTokenCreate: () => undefined, - onTokenDelete: () => undefined, - permissions, - saveButtonBarState: "default", - service, - token: null -}; -storiesOf("Views / Services / Service details", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ( - - )) - .add("form errors", () => ( - ({ - __typename: "AccountError", - code: AccountErrorCode.INVALID, - field - }))} - /> - )) - .add("default token", () => ( - - )); diff --git a/src/services/components/ServiceDetailsPage/index.ts b/src/services/components/ServiceDetailsPage/index.ts deleted file mode 100644 index 9d3e06e0b..000000000 --- a/src/services/components/ServiceDetailsPage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDetailsPage"; -export * from "./ServiceDetailsPage"; diff --git a/src/services/components/ServiceInfo/index.ts b/src/services/components/ServiceInfo/index.ts deleted file mode 100644 index 2d3a86c07..000000000 --- a/src/services/components/ServiceInfo/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceInfo"; -export * from "./ServiceInfo"; diff --git a/src/services/components/ServiceList/ServiceList.tsx b/src/services/components/ServiceList/ServiceList.tsx deleted file mode 100644 index ea0e01675..000000000 --- a/src/services/components/ServiceList/ServiceList.tsx +++ /dev/null @@ -1,180 +0,0 @@ -import IconButton from "@material-ui/core/IconButton"; -import { makeStyles } from "@material-ui/core/styles"; -import TableBody from "@material-ui/core/TableBody"; -import TableCell from "@material-ui/core/TableCell"; -import TableFooter from "@material-ui/core/TableFooter"; -import TableHead from "@material-ui/core/TableHead"; -import TableRow from "@material-ui/core/TableRow"; -import Typography from "@material-ui/core/Typography"; -import DeleteIcon from "@material-ui/icons/Delete"; -import EditIcon from "@material-ui/icons/Edit"; -import ResponsiveTable from "@saleor/components/ResponsiveTable"; -import Skeleton from "@saleor/components/Skeleton"; -import TableCellHeader from "@saleor/components/TableCellHeader"; -import TablePagination from "@saleor/components/TablePagination"; -import { maybe, renderCollection, stopPropagation } from "@saleor/misc"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { ListProps, SortPage } from "@saleor/types"; -import { getArrowDirection } from "@saleor/utils/sort"; -import React from "react"; -import { FormattedMessage } from "react-intl"; - -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; - -export interface ServiceListProps - extends ListProps, - SortPage { - services: ServiceList_serviceAccounts_edges_node[]; - onRemove: (id: string) => void; -} - -const useStyles = makeStyles( - theme => ({ - [theme.breakpoints.up("lg")]: { - colName: { - "&&": { - width: "auto" - } - } - }, - colAction: { - "&&": { - paddingRight: theme.spacing(1) - }, - textAlign: "right", - width: 140 - }, - colName: { - paddingLeft: 0, - width: 250 - }, - table: { - tableLayout: "fixed" - }, - tableRow: { - cursor: "pointer" - } - }), - { name: "ServiceList" } -); - -const numberOfColumns = 2; - -const ServiceList: React.FC = props => { - const { - settings, - disabled, - onNextPage, - onPreviousPage, - onUpdateListSettings, - onRemove, - onRowClick, - onSort, - pageInfo, - services, - sort - } = props; - - const classes = useStyles(props); - - return ( - - - - onSort(ServiceListUrlSortField.name)} - className={classes.colName} - > - - - - - - - - - - - - {renderCollection( - services, - service => ( - - - - {maybe(() => service.name, )} - - - {maybe(() => - service.isActive ? ( - - ) : ( - - ) - )} - - - - - - - onRemove(service.id)) - : undefined - } - > - - - - - ), - () => ( - - - - - - ) - )} - - - ); -}; -ServiceList.displayName = "ServiceList"; -export default ServiceList; diff --git a/src/services/components/ServiceList/index.ts b/src/services/components/ServiceList/index.ts deleted file mode 100644 index 3cfb6cc3d..000000000 --- a/src/services/components/ServiceList/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceList"; -export * from "./ServiceList"; diff --git a/src/services/components/ServiceListPage/ServiceListPage.stories.tsx b/src/services/components/ServiceListPage/ServiceListPage.stories.tsx deleted file mode 100644 index 88441c338..000000000 --- a/src/services/components/ServiceListPage/ServiceListPage.stories.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { - filterPageProps, - listActionsProps, - pageListProps, - searchPageProps, - sortPageProps, - tabPageProps -} from "@saleor/fixtures"; -import ServiceListPage, { - ServiceListPageProps -} from "@saleor/services/components/ServiceListPage"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import Decorator from "@saleor/storybook/Decorator"; -import { storiesOf } from "@storybook/react"; -import React from "react"; - -import { serviceList } from "../../fixtures"; - -const props: ServiceListPageProps = { - ...listActionsProps, - ...pageListProps.default, - ...searchPageProps, - ...sortPageProps, - ...tabPageProps, - ...filterPageProps, - filterOpts: { - isActive: { - active: false, - value: true - } - }, - onBack: () => undefined, - onRemove: () => undefined, - services: serviceList, - sort: { - ...sortPageProps.sort, - sort: ServiceListUrlSortField.name - } -}; - -storiesOf("Views / Services / Service list", module) - .addDecorator(Decorator) - .add("default", () => ) - .add("loading", () => ( - - )) - .add("no data", () => ); diff --git a/src/services/components/ServiceListPage/ServiceListPage.tsx b/src/services/components/ServiceListPage/ServiceListPage.tsx deleted file mode 100644 index 32c8fe559..000000000 --- a/src/services/components/ServiceListPage/ServiceListPage.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import Button from "@material-ui/core/Button"; -import Card from "@material-ui/core/Card"; -import AppHeader from "@saleor/components/AppHeader"; -import Container from "@saleor/components/Container"; -import FilterBar from "@saleor/components/FilterBar"; -import PageHeader from "@saleor/components/PageHeader"; -import { sectionNames } from "@saleor/intl"; -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { - FilterPageProps, - PageListProps, - SortPage, - TabPageProps -} from "@saleor/types"; -import React from "react"; -import { FormattedMessage, useIntl } from "react-intl"; - -import { ServiceList_serviceAccounts_edges_node } from "../../types/ServiceList"; -import ServiceList from "../ServiceList"; -import { - createFilterStructure, - ServiceFilterKeys, - ServiceListFilterOpts -} from "./filters"; - -export interface ServiceListPageProps - extends PageListProps, - FilterPageProps, - SortPage, - TabPageProps { - services: ServiceList_serviceAccounts_edges_node[]; - onBack: () => void; - onRemove: (id: string) => void; -} - -const ServiceListPage: React.FC = ({ - currencySymbol, - currentTab, - filterOpts, - initialSearch, - onAdd, - onAll, - onBack, - onFilterChange, - onSearchChange, - onTabChange, - onTabDelete, - onTabSave, - tabs, - ...listProps -}) => { - const intl = useIntl(); - - const structure = createFilterStructure(intl, filterOpts); - - return ( - - - {intl.formatMessage(sectionNames.configuration)} - - - - - - - - - - ); -}; -ServiceListPage.displayName = "ServiceListPage"; -export default ServiceListPage; diff --git a/src/services/components/ServiceListPage/filters.ts b/src/services/components/ServiceListPage/filters.ts deleted file mode 100644 index fac9349ac..000000000 --- a/src/services/components/ServiceListPage/filters.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { IFilter } from "@saleor/components/Filter"; -import { commonMessages } from "@saleor/intl"; -import { FilterOpts } from "@saleor/types"; -import { createBooleanField } from "@saleor/utils/filters/fields"; -import { defineMessages, IntlShape } from "react-intl"; - -export enum ServiceFilterKeys { - active = "active" -} - -export interface ServiceListFilterOpts { - isActive: FilterOpts; -} - -const messages = defineMessages({ - active: { - defaultMessage: "Active", - description: "service account" - }, - deactivated: { - defaultMessage: "Inactive", - description: "service account" - } -}); - -export function createFilterStructure( - intl: IntlShape, - opts: ServiceListFilterOpts -): IFilter { - return [ - { - ...createBooleanField( - ServiceFilterKeys.active, - intl.formatMessage(commonMessages.status), - opts.isActive.value, - { - negative: intl.formatMessage(messages.deactivated), - positive: intl.formatMessage(messages.active) - } - ), - active: opts.isActive.active - } - ]; -} - -export default messages; diff --git a/src/services/components/ServiceListPage/index.ts b/src/services/components/ServiceListPage/index.ts deleted file mode 100644 index 44625afe2..000000000 --- a/src/services/components/ServiceListPage/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { default } from "./ServiceListPage"; -export * from "./ServiceListPage"; -export * from "./filters"; diff --git a/src/services/components/ServiceTokenCreateDialog/index.ts b/src/services/components/ServiceTokenCreateDialog/index.ts deleted file mode 100644 index f34be97d4..000000000 --- a/src/services/components/ServiceTokenCreateDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokenCreateDialog"; -export * from "./ServiceTokenCreateDialog"; diff --git a/src/services/components/ServiceTokenDeleteDialog/index.ts b/src/services/components/ServiceTokenDeleteDialog/index.ts deleted file mode 100644 index 8b3a70a9b..000000000 --- a/src/services/components/ServiceTokenDeleteDialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokenDeleteDialog"; -export * from "./ServiceTokenDeleteDialog"; diff --git a/src/services/components/ServiceTokens/index.ts b/src/services/components/ServiceTokens/index.ts deleted file mode 100644 index 4ca5caf39..000000000 --- a/src/services/components/ServiceTokens/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceTokens"; -export * from "./ServiceTokens"; diff --git a/src/services/fixtures.ts b/src/services/fixtures.ts deleted file mode 100644 index 814c5d164..000000000 --- a/src/services/fixtures.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { PermissionEnum } from "@saleor/types/globalTypes"; - -import { ServiceDetails_serviceAccount } from "./types/ServiceDetails"; -import { ServiceList_serviceAccounts_edges_node } from "./types/ServiceList"; - -export const serviceList: ServiceList_serviceAccounts_edges_node[] = [ - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "1", - isActive: true, - name: "Slack" - }, - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "2", - isActive: true, - name: "Facebook Market" - }, - { - __typename: "ServiceAccount" as "ServiceAccount", - id: "3", - isActive: false, - name: "Magento Importer" - } -]; - -export const service: ServiceDetails_serviceAccount = { - __typename: "ServiceAccount" as "ServiceAccount", - id: "1", - isActive: true, - name: "Magento Importer", - permissions: [ - { - __typename: "Permission" as "Permission", - code: PermissionEnum.MANAGE_PRODUCTS, - name: "Manage products." - } - ], - tokens: [ - { - __typename: "ServiceAccountToken", - authToken: "AK05", - id: "t1", - name: "default" - } - ] -}; diff --git a/src/services/index.tsx b/src/services/index.tsx deleted file mode 100644 index 8434da9b2..000000000 --- a/src/services/index.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { sectionNames } from "@saleor/intl"; -import { asSortParams } from "@saleor/utils/sort"; -import { parse as parseQs } from "qs"; -import React from "react"; -import { useIntl } from "react-intl"; -import { Route, RouteComponentProps, Switch } from "react-router-dom"; - -import { WindowTitle } from "../components/WindowTitle"; -import { - serviceAddPath, - serviceListPath, - ServiceListUrlQueryParams, - ServiceListUrlSortField, - servicePath, - ServiceUrlQueryParams -} from "./urls"; -import ServiceCreate from "./views/ServiceCreate"; -import ServiceDetailsComponent from "./views/ServiceDetails"; -import ServiceListComponent from "./views/ServiceList"; - -const ServiceList: React.FC = ({ location }) => { - const qs = parseQs(location.search.substr(1)); - const params: ServiceListUrlQueryParams = asSortParams( - qs, - ServiceListUrlSortField - ); - - return ; -}; - -interface ServiceDetailsProps extends RouteComponentProps<{ id: string }> { - token: string; - onTokenClose: () => void; -} -const ServiceDetails: React.FC = ({ - match, - token, - onTokenClose -}) => { - const qs = parseQs(location.search.substr(1)); - const params: ServiceUrlQueryParams = qs; - - return ( - - ); -}; - -const ServiceSection = () => { - const intl = useIntl(); - const [token, setToken] = React.useState(null); - - return ( - <> - - - - } - /> - ( - setToken(null)} - /> - )} - /> - - - ); -}; - -export default ServiceSection; diff --git a/src/services/mutations.ts b/src/services/mutations.ts deleted file mode 100644 index b6912387a..000000000 --- a/src/services/mutations.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { accountErrorFragment } from "@saleor/fragments/errors"; -import { - serviceDetailsFragment, - serviceFragment -} from "@saleor/fragments/services"; -import gql from "graphql-tag"; - -import { TypedMutation } from "../mutations"; -import { ServiceCreate, ServiceCreateVariables } from "./types/ServiceCreate"; -import { ServiceDelete, ServiceDeleteVariables } from "./types/ServiceDelete"; -import { - ServiceTokenCreate, - ServiceTokenCreateVariables -} from "./types/ServiceTokenCreate"; -import { - ServiceTokenDelete, - ServiceTokenDeleteVariables -} from "./types/ServiceTokenDelete"; -import { ServiceUpdate, ServiceUpdateVariables } from "./types/ServiceUpdate"; - -const serviceCreateMutation = gql` - ${accountErrorFragment} - ${serviceFragment} - mutation ServiceCreate($input: ServiceAccountInput!) { - serviceAccountCreate(input: $input) { - authToken - errors: accountErrors { - ...AccountErrorFragment - } - serviceAccount { - ...ServiceFragment - } - } - } -`; - -export const ServiceCreateMutation = TypedMutation< - ServiceCreate, - ServiceCreateVariables ->(serviceCreateMutation); - -const serviceDeleteMutation = gql` - ${accountErrorFragment} - mutation ServiceDelete($id: ID!) { - serviceAccountDelete(id: $id) { - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceDeleteMutation = TypedMutation< - ServiceDelete, - ServiceDeleteVariables ->(serviceDeleteMutation); - -const serviceUpdateMutation = gql` - ${accountErrorFragment} - ${serviceDetailsFragment} - mutation ServiceUpdate($id: ID!, $input: ServiceAccountInput!) { - serviceAccountUpdate(id: $id, input: $input) { - errors: accountErrors { - ...AccountErrorFragment - } - serviceAccount { - ...ServiceDetailsFragment - } - } - } -`; - -export const ServiceUpdateMutation = TypedMutation< - ServiceUpdate, - ServiceUpdateVariables ->(serviceUpdateMutation); - -const serviceTokenCreate = gql` - ${accountErrorFragment} - mutation ServiceTokenCreate($input: ServiceAccountTokenInput!) { - serviceAccountTokenCreate(input: $input) { - authToken - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceTokenCreateMutation = TypedMutation< - ServiceTokenCreate, - ServiceTokenCreateVariables ->(serviceTokenCreate); - -const serviceTokenDelete = gql` - ${accountErrorFragment} - mutation ServiceTokenDelete($id: ID!) { - serviceAccountTokenDelete(id: $id) { - errors: accountErrors { - ...AccountErrorFragment - } - } - } -`; -export const ServiceTokenDeleteMutation = TypedMutation< - ServiceTokenDelete, - ServiceTokenDeleteVariables ->(serviceTokenDelete); diff --git a/src/services/queries.ts b/src/services/queries.ts deleted file mode 100644 index 84c654796..000000000 --- a/src/services/queries.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { pageInfoFragment } from "@saleor/fragments/pageInfo"; -import { - serviceDetailsFragment, - serviceFragment -} from "@saleor/fragments/services"; -import makeQuery from "@saleor/hooks/makeQuery"; -import gql from "graphql-tag"; - -import { TypedQuery } from "../queries"; -import { - ServiceDetails, - ServiceDetailsVariables -} from "./types/ServiceDetails"; -import { ServiceList, ServiceListVariables } from "./types/ServiceList"; - -const serviceList = gql` - ${pageInfoFragment} - ${serviceFragment} - query ServiceList( - $first: Int - $after: String - $last: Int - $before: String - $filter: ServiceAccountFilterInput - $sort: ServiceAccountSortingInput - ) { - serviceAccounts( - first: $first - after: $after - before: $before - last: $last - filter: $filter - sortBy: $sort - ) { - edges { - node { - ...ServiceFragment - } - } - pageInfo { - ...PageInfoFragment - } - } - } -`; -export const useServiceListQuery = makeQuery( - serviceList -); - -const serviceDetails = gql` - ${serviceDetailsFragment} - query ServiceDetails($id: ID!) { - serviceAccount(id: $id) { - ...ServiceDetailsFragment - } - } -`; -export const ServiceDetailsQuery = TypedQuery< - ServiceDetails, - ServiceDetailsVariables ->(serviceDetails); diff --git a/src/services/types/ServiceCreate.ts b/src/services/types/ServiceCreate.ts deleted file mode 100644 index 74b3a0aea..000000000 --- a/src/services/types/ServiceCreate.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountInput, AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceCreate -// ==================================================== - -export interface ServiceCreate_serviceAccountCreate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceCreate_serviceAccountCreate_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} - -export interface ServiceCreate_serviceAccountCreate { - __typename: "ServiceAccountCreate"; - authToken: string | null; - errors: ServiceCreate_serviceAccountCreate_errors[]; - serviceAccount: ServiceCreate_serviceAccountCreate_serviceAccount | null; -} - -export interface ServiceCreate { - serviceAccountCreate: ServiceCreate_serviceAccountCreate | null; -} - -export interface ServiceCreateVariables { - input: ServiceAccountInput; -} diff --git a/src/services/types/ServiceDelete.ts b/src/services/types/ServiceDelete.ts deleted file mode 100644 index a23793c72..000000000 --- a/src/services/types/ServiceDelete.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceDelete -// ==================================================== - -export interface ServiceDelete_serviceAccountDelete_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceDelete_serviceAccountDelete { - __typename: "ServiceAccountDelete"; - errors: ServiceDelete_serviceAccountDelete_errors[]; -} - -export interface ServiceDelete { - serviceAccountDelete: ServiceDelete_serviceAccountDelete | null; -} - -export interface ServiceDeleteVariables { - id: string; -} diff --git a/src/services/types/ServiceDetails.ts b/src/services/types/ServiceDetails.ts deleted file mode 100644 index 2a0bb4187..000000000 --- a/src/services/types/ServiceDetails.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: ServiceDetails -// ==================================================== - -export interface ServiceDetails_serviceAccount_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceDetails_serviceAccount_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceDetails_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceDetails_serviceAccount_permissions | null)[] | null; - tokens: (ServiceDetails_serviceAccount_tokens | null)[] | null; -} - -export interface ServiceDetails { - serviceAccount: ServiceDetails_serviceAccount | null; -} - -export interface ServiceDetailsVariables { - id: string; -} diff --git a/src/services/types/ServiceList.ts b/src/services/types/ServiceList.ts deleted file mode 100644 index c03bf7bea..000000000 --- a/src/services/types/ServiceList.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountFilterInput, ServiceAccountSortingInput } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: ServiceList -// ==================================================== - -export interface ServiceList_serviceAccounts_edges_node { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; -} - -export interface ServiceList_serviceAccounts_edges { - __typename: "ServiceAccountCountableEdge"; - node: ServiceList_serviceAccounts_edges_node; -} - -export interface ServiceList_serviceAccounts_pageInfo { - __typename: "PageInfo"; - endCursor: string | null; - hasNextPage: boolean; - hasPreviousPage: boolean; - startCursor: string | null; -} - -export interface ServiceList_serviceAccounts { - __typename: "ServiceAccountCountableConnection"; - edges: ServiceList_serviceAccounts_edges[]; - pageInfo: ServiceList_serviceAccounts_pageInfo; -} - -export interface ServiceList { - serviceAccounts: ServiceList_serviceAccounts | null; -} - -export interface ServiceListVariables { - first?: number | null; - after?: string | null; - last?: number | null; - before?: string | null; - filter?: ServiceAccountFilterInput | null; - sort?: ServiceAccountSortingInput | null; -} diff --git a/src/services/types/ServiceTokenCreate.ts b/src/services/types/ServiceTokenCreate.ts deleted file mode 100644 index 7529a10c4..000000000 --- a/src/services/types/ServiceTokenCreate.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountTokenInput, AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceTokenCreate -// ==================================================== - -export interface ServiceTokenCreate_serviceAccountTokenCreate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceTokenCreate_serviceAccountTokenCreate { - __typename: "ServiceAccountTokenCreate"; - authToken: string | null; - errors: ServiceTokenCreate_serviceAccountTokenCreate_errors[]; -} - -export interface ServiceTokenCreate { - serviceAccountTokenCreate: ServiceTokenCreate_serviceAccountTokenCreate | null; -} - -export interface ServiceTokenCreateVariables { - input: ServiceAccountTokenInput; -} diff --git a/src/services/types/ServiceTokenDelete.ts b/src/services/types/ServiceTokenDelete.ts deleted file mode 100644 index 9cfad5249..000000000 --- a/src/services/types/ServiceTokenDelete.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AccountErrorCode } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceTokenDelete -// ==================================================== - -export interface ServiceTokenDelete_serviceAccountTokenDelete_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceTokenDelete_serviceAccountTokenDelete { - __typename: "ServiceAccountTokenDelete"; - errors: ServiceTokenDelete_serviceAccountTokenDelete_errors[]; -} - -export interface ServiceTokenDelete { - serviceAccountTokenDelete: ServiceTokenDelete_serviceAccountTokenDelete | null; -} - -export interface ServiceTokenDeleteVariables { - id: string; -} diff --git a/src/services/types/ServiceUpdate.ts b/src/services/types/ServiceUpdate.ts deleted file mode 100644 index 17feb8dc6..000000000 --- a/src/services/types/ServiceUpdate.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { ServiceAccountInput, AccountErrorCode, PermissionEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL mutation operation: ServiceUpdate -// ==================================================== - -export interface ServiceUpdate_serviceAccountUpdate_errors { - __typename: "AccountError"; - code: AccountErrorCode; - field: string | null; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions { - __typename: "Permission"; - code: PermissionEnum; - name: string; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens { - __typename: "ServiceAccountToken"; - id: string; - name: string | null; - authToken: string | null; -} - -export interface ServiceUpdate_serviceAccountUpdate_serviceAccount { - __typename: "ServiceAccount"; - id: string; - name: string | null; - isActive: boolean | null; - permissions: (ServiceUpdate_serviceAccountUpdate_serviceAccount_permissions | null)[] | null; - tokens: (ServiceUpdate_serviceAccountUpdate_serviceAccount_tokens | null)[] | null; -} - -export interface ServiceUpdate_serviceAccountUpdate { - __typename: "ServiceAccountUpdate"; - errors: ServiceUpdate_serviceAccountUpdate_errors[]; - serviceAccount: ServiceUpdate_serviceAccountUpdate_serviceAccount | null; -} - -export interface ServiceUpdate { - serviceAccountUpdate: ServiceUpdate_serviceAccountUpdate | null; -} - -export interface ServiceUpdateVariables { - id: string; - input: ServiceAccountInput; -} diff --git a/src/services/urls.ts b/src/services/urls.ts deleted file mode 100644 index aef61de6f..000000000 --- a/src/services/urls.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { stringify as stringifyQs } from "qs"; -import urlJoin from "url-join"; - -import { - ActiveTab, - Dialog, - Filters, - Pagination, - SingleAction, - Sort, - TabActionDialog -} from "../types"; - -export const serviceSection = "/services/"; - -export const serviceListPath = serviceSection; -export enum ServiceListUrlFiltersEnum { - active = "active", - query = "query" -} -export type ServiceListUrlFilters = Filters; -export type ServiceListUrlDialog = "remove" | TabActionDialog; -export enum ServiceListUrlSortField { - name = "name", - active = "active" -} -export type ServiceListUrlSort = Sort; -export type ServiceListUrlQueryParams = ActiveTab & - Dialog & - Pagination & - ServiceListUrlFilters & - ServiceListUrlSort & - SingleAction; -export const serviceListUrl = (params?: ServiceListUrlQueryParams) => - serviceListPath + "?" + stringifyQs(params); - -export const servicePath = (id: string) => urlJoin(serviceSection, id); -export type ServiceUrlDialog = "create-token" | "remove" | "remove-token"; -export type ServiceUrlQueryParams = Dialog & SingleAction; -export const serviceUrl = (id: string, params?: ServiceUrlQueryParams) => - servicePath(encodeURIComponent(id)) + "?" + stringifyQs(params); - -export const serviceAddPath = urlJoin(serviceSection, "add"); -export const serviceAddUrl = serviceAddPath; diff --git a/src/services/views/ServiceCreate/ServiceCreate.tsx b/src/services/views/ServiceCreate/ServiceCreate.tsx deleted file mode 100644 index e565c99e5..000000000 --- a/src/services/views/ServiceCreate/ServiceCreate.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { WindowTitle } from "@saleor/components/WindowTitle"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import useShop from "@saleor/hooks/useShop"; -import { commonMessages } from "@saleor/intl"; -import { ServiceCreateMutation } from "@saleor/services/mutations"; -import { ServiceCreate as ServiceCreateData } from "@saleor/services/types/ServiceCreate"; -import React from "react"; -import { useIntl } from "react-intl"; - -import ServiceCreatePage, { - ServiceCreatePageFormData -} from "../../components/ServiceCreatePage"; -import { serviceListUrl, serviceUrl } from "../../urls"; - -interface ServiceCreateProps { - setToken: (token: string) => void; -} -export const ServiceCreate: React.FC = ({ setToken }) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const intl = useIntl(); - const shop = useShop(); - - const onSubmit = (data: ServiceCreateData) => { - if (data.serviceAccountCreate.errors.length === 0) { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(serviceUrl(data.serviceAccountCreate.serviceAccount.id)); - setToken(data.serviceAccountCreate.authToken); - } - }; - - const handleBack = () => navigate(serviceListUrl()); - - return ( - - {(serviceCreate, serviceCreateOpts) => { - const handleSubmit = (data: ServiceCreatePageFormData) => - serviceCreate({ - variables: { - input: { - isActive: data.isActive, - name: data.name, - permissions: data.hasFullAccess - ? shop.permissions.map(permission => permission.code) - : data.permissions - } - } - }); - - return ( - <> - - - - ); - }} - - ); -}; - -export default ServiceCreate; diff --git a/src/services/views/ServiceCreate/index.ts b/src/services/views/ServiceCreate/index.ts deleted file mode 100644 index a6de9b346..000000000 --- a/src/services/views/ServiceCreate/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceCreate"; -export * from "./ServiceCreate"; diff --git a/src/services/views/ServiceDetails/ServiceDetails.tsx b/src/services/views/ServiceDetails/ServiceDetails.tsx deleted file mode 100644 index dfb59af61..000000000 --- a/src/services/views/ServiceDetails/ServiceDetails.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import NotFoundPage from "@saleor/components/NotFoundPage"; -import { WindowTitle } from "@saleor/components/WindowTitle"; -import { API_URI } from "@saleor/config"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import useShop from "@saleor/hooks/useShop"; -import { commonMessages } from "@saleor/intl"; -import { getStringOrPlaceholder, maybe } from "@saleor/misc"; -import ServiceDeleteDialog from "@saleor/services/components/ServiceDeleteDialog"; -import ServiceTokenCreateDialog from "@saleor/services/components/ServiceTokenCreateDialog"; -import ServiceTokenDeleteDialog from "@saleor/services/components/ServiceTokenDeleteDialog"; -import { - ServiceDeleteMutation, - ServiceTokenCreateMutation, - ServiceTokenDeleteMutation, - ServiceUpdateMutation -} from "@saleor/services/mutations"; -import { ServiceDelete } from "@saleor/services/types/ServiceDelete"; -import { ServiceTokenCreate } from "@saleor/services/types/ServiceTokenCreate"; -import { ServiceTokenDelete } from "@saleor/services/types/ServiceTokenDelete"; -import { ServiceUpdate } from "@saleor/services/types/ServiceUpdate"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import React from "react"; -import { useIntl } from "react-intl"; - -import ServiceDetailsPage, { - ServiceDetailsPageFormData -} from "../../components/ServiceDetailsPage"; -import { ServiceDetailsQuery } from "../../queries"; -import { - serviceListUrl, - serviceUrl, - ServiceUrlDialog, - ServiceUrlQueryParams -} from "../../urls"; - -interface OrderListProps { - id: string; - params: ServiceUrlQueryParams; - token: string; - onTokenClose: () => void; -} - -export const ServiceDetails: React.FC = ({ - id, - params, - token, - onTokenClose -}) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const intl = useIntl(); - const shop = useShop(); - - React.useEffect(() => onTokenClose, []); - - const [openModal, closeModal] = createDialogActionHandlers< - ServiceUrlDialog, - ServiceUrlQueryParams - >(navigate, params => serviceUrl(id, params), params); - - const onServiceUpdate = (data: ServiceUpdate) => { - if (maybe(() => data.serviceAccountUpdate.errors.length === 0)) { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges) - }); - } - }; - const onServiceDelete = (data: ServiceDelete) => { - if (data.serviceAccountDelete.errors.length === 0) { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges) - }); - navigate(serviceListUrl()); - } - }; - - const handleBack = () => navigate(serviceListUrl()); - - return ( - - {({ data, loading, refetch }) => { - const service = data?.serviceAccount; - - if (service === null) { - return ; - } - - const onTokenCreate = (data: ServiceTokenCreate) => { - if (maybe(() => data.serviceAccountTokenCreate.errors.length === 0)) { - refetch(); - } - }; - const onTokenDelete = (data: ServiceTokenDelete) => { - if (maybe(() => data.serviceAccountTokenDelete.errors.length === 0)) { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges) - }); - refetch(); - closeModal(); - } - }; - - return ( - - {(updateService, updateServiceOpts) => ( - - {(deleteService, deleteServiceOpts) => ( - - {(createToken, createTokenOpts) => ( - - {(deleteToken, deleteTokenOpts) => { - const handleSubmit = ( - data: ServiceDetailsPageFormData - ) => - updateService({ - variables: { - id, - input: { - isActive: data.isActive, - name: data.name, - permissions: data.hasFullAccess - ? shop.permissions.map( - permission => permission.code - ) - : data.permissions - } - } - }); - - const handleRemoveConfirm = () => - deleteService({ - variables: { - id - } - }); - - const handleTokenCreate = (name: string) => - createToken({ - variables: { - input: { - name, - serviceAccount: id - } - } - }); - - const handleTokenDelete = () => - deleteToken({ - variables: { - id: params.id - } - }); - - return ( - <> - - open(API_URI, "blank")} - onBack={handleBack} - onDelete={() => openModal("remove")} - onSubmit={handleSubmit} - onTokenClose={onTokenClose} - onTokenCreate={() => openModal("create-token")} - onTokenDelete={id => - openModal("remove-token", { - id - }) - } - permissions={shop?.permissions} - service={data?.serviceAccount} - saveButtonBarState={updateServiceOpts.status} - /> - - - { - const token = data.serviceAccount.tokens.find( - token => token.id === params.id - ); - if (token.name) { - return token.name; - } - - return `**** ${token.authToken}`; - }, "...")} - onClose={closeModal} - onConfirm={handleTokenDelete} - open={params.action === "remove-token"} - /> - - ); - }} - - )} - - )} - - )} - - ); - }} - - ); -}; - -export default ServiceDetails; diff --git a/src/services/views/ServiceDetails/index.ts b/src/services/views/ServiceDetails/index.ts deleted file mode 100644 index f7b2a2d0c..000000000 --- a/src/services/views/ServiceDetails/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceDetails"; -export * from "./ServiceDetails"; diff --git a/src/services/views/ServiceList/ServiceList.tsx b/src/services/views/ServiceList/ServiceList.tsx deleted file mode 100644 index 27657f6d9..000000000 --- a/src/services/views/ServiceList/ServiceList.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog"; -import SaveFilterTabDialog, { - SaveFilterTabDialogFormData -} from "@saleor/components/SaveFilterTabDialog"; -import { configurationMenuUrl } from "@saleor/configuration"; -import useListSettings from "@saleor/hooks/useListSettings"; -import useNavigator from "@saleor/hooks/useNavigator"; -import useNotifier from "@saleor/hooks/useNotifier"; -import usePaginator, { - createPaginationState -} from "@saleor/hooks/usePaginator"; -import useShop from "@saleor/hooks/useShop"; -import { commonMessages } from "@saleor/intl"; -import { maybe } from "@saleor/misc"; -import { ServiceDeleteMutation } from "@saleor/services/mutations"; -import { ServiceDelete } from "@saleor/services/types/ServiceDelete"; -import { ListViews } from "@saleor/types"; -import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; -import createFilterHandlers from "@saleor/utils/handlers/filterHandlers"; -import createSortHandler from "@saleor/utils/handlers/sortHandler"; -import { getSortParams } from "@saleor/utils/sort"; -import React from "react"; -import { useIntl } from "react-intl"; - -import ServiceDeleteDialog from "../../components/ServiceDeleteDialog"; -import ServiceListPage from "../../components/ServiceListPage"; -import { useServiceListQuery } from "../../queries"; -import { - serviceAddUrl, - serviceListUrl, - ServiceListUrlDialog, - ServiceListUrlQueryParams, - serviceUrl -} from "../../urls"; -import { - areFiltersApplied, - deleteFilterTab, - getActiveFilters, - getFilterOpts, - getFilterQueryParam, - getFilterTabs, - getFilterVariables, - saveFilterTab -} from "./filters"; -import { getSortQueryVariables } from "./sort"; - -interface ServiceListProps { - params: ServiceListUrlQueryParams; -} - -export const ServiceList: React.FC = ({ params }) => { - const navigate = useNavigator(); - const notify = useNotifier(); - const paginate = usePaginator(); - const shop = useShop(); - const { updateListSettings, settings } = useListSettings( - ListViews.STAFF_MEMBERS_LIST - ); - const intl = useIntl(); - - const paginationState = createPaginationState(settings.rowNumber, params); - const queryVariables = React.useMemo( - () => ({ - ...paginationState, - filter: getFilterVariables(params), - sort: getSortQueryVariables(params) - }), - [params] - ); - const { data, loading, refetch } = useServiceListQuery({ - displayLoader: true, - variables: queryVariables - }); - - const tabs = getFilterTabs(); - - const currentTab = - params.activeTab === undefined - ? areFiltersApplied(params) - ? tabs.length + 1 - : 0 - : parseInt(params.activeTab, 0); - - const [ - changeFilters, - resetFilters, - handleSearchChange - ] = createFilterHandlers({ - createUrl: serviceListUrl, - getFilterQueryParam, - navigate, - params - }); - - const [openModal, closeModal] = createDialogActionHandlers< - ServiceListUrlDialog, - ServiceListUrlQueryParams - >(navigate, serviceListUrl, params); - - const handleTabChange = (tab: number) => { - navigate( - serviceListUrl({ - activeTab: tab.toString(), - ...getFilterTabs()[tab - 1].data - }) - ); - }; - - const handleTabDelete = () => { - deleteFilterTab(currentTab); - navigate(serviceListUrl()); - }; - - const handleTabSave = (data: SaveFilterTabDialogFormData) => { - saveFilterTab(data.name, getActiveFilters(params)); - handleTabChange(tabs.length + 1); - }; - - const { loadNextPage, loadPreviousPage, pageInfo } = paginate( - maybe(() => data.serviceAccounts.pageInfo), - paginationState, - params - ); - - const handleCreate = () => navigate(serviceAddUrl); - - const onRemove = (data: ServiceDelete) => { - if (data.serviceAccountDelete.errors.length === 0) { - notify({ - status: "success", - text: intl.formatMessage(commonMessages.savedChanges) - }); - closeModal(); - refetch(); - } - }; - - const handleSort = createSortHandler(navigate, serviceListUrl, params); - const currencySymbol = maybe(() => shop.defaultCurrency, "USD"); - - return ( - - {(deleteService, deleteServiceOpts) => { - const handleRemoveConfirm = () => - deleteService({ - variables: { - id: params.id - } - }); - - return ( - <> - openModal("delete-search")} - onTabSave={() => openModal("save-search")} - tabs={tabs.map(tab => tab.name)} - disabled={loading} - settings={settings} - pageInfo={pageInfo} - services={maybe(() => - data.serviceAccounts.edges.map(edge => edge.node) - )} - sort={getSortParams(params)} - onAdd={handleCreate} - onBack={() => navigate(configurationMenuUrl)} - onNextPage={loadNextPage} - onPreviousPage={loadPreviousPage} - onUpdateListSettings={updateListSettings} - onRowClick={id => () => navigate(serviceUrl(id))} - onRemove={id => - openModal("remove", { - id - }) - } - onSort={handleSort} - /> - - data.serviceAccounts.edges.find( - edge => edge.node.id === params.id - ).node.name, - "..." - )} - onClose={closeModal} - onConfirm={handleRemoveConfirm} - open={params.action === "remove"} - /> - - tabs[currentTab - 1].name, "...")} - /> - - ); - }} - - ); -}; - -export default ServiceList; diff --git a/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap b/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap deleted file mode 100644 index c63a81372..000000000 --- a/src/services/views/ServiceList/__snapshots__/filters.test.ts.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Filtering URL params should not be empty if active filters are present 1`] = ` -Object { - "active": "false", -} -`; - -exports[`Filtering URL params should not be empty if active filters are present 2`] = `"active=false"`; diff --git a/src/services/views/ServiceList/filters.test.ts b/src/services/views/ServiceList/filters.test.ts deleted file mode 100644 index e05e95c53..000000000 --- a/src/services/views/ServiceList/filters.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { createFilterStructure } from "@saleor/services/components/ServiceListPage"; -import { ServiceListUrlFilters } from "@saleor/services/urls"; -import { getFilterQueryParams } from "@saleor/utils/filters"; -import { getExistingKeys, setFilterOptsStatus } from "@test/filters"; -import { config } from "@test/intl"; -import { stringify as stringifyQs } from "qs"; -import { createIntl } from "react-intl"; - -import { getFilterQueryParam, getFilterVariables } from "./filters"; - -describe("Filtering query params", () => { - it("should be empty object if no params given", () => { - const params: ServiceListUrlFilters = {}; - const filterVariables = getFilterVariables(params); - - expect(getExistingKeys(filterVariables)).toHaveLength(0); - }); - - it("should not be empty object if params given", () => { - const params: ServiceListUrlFilters = { - active: false.toString() - }; - const filterVariables = getFilterVariables(params); - - expect(getExistingKeys(filterVariables)).toHaveLength(1); - }); -}); - -describe("Filtering URL params", () => { - const intl = createIntl(config); - - const filters = createFilterStructure(intl, { - isActive: { - active: false, - value: false - } - }); - - it("should be empty if no active filters", () => { - const filterQueryParams = getFilterQueryParams( - filters, - getFilterQueryParam - ); - - expect(getExistingKeys(filterQueryParams)).toHaveLength(0); - }); - - it("should not be empty if active filters are present", () => { - const filterQueryParams = getFilterQueryParams( - setFilterOptsStatus(filters, true), - getFilterQueryParam - ); - - expect(filterQueryParams).toMatchSnapshot(); - expect(stringifyQs(filterQueryParams)).toMatchSnapshot(); - }); -}); diff --git a/src/services/views/ServiceList/filters.ts b/src/services/views/ServiceList/filters.ts deleted file mode 100644 index 2ff6f36a5..000000000 --- a/src/services/views/ServiceList/filters.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { IFilterElement } from "@saleor/components/Filter"; -import { maybe, parseBoolean } from "@saleor/misc"; -import { - ServiceFilterKeys, - ServiceListFilterOpts -} from "@saleor/services/components/ServiceListPage/filters"; -import { ServiceAccountFilterInput } from "@saleor/types/globalTypes"; - -import { - createFilterTabUtils, - createFilterUtils, - getSingleValueQueryParam -} from "../../../utils/filters"; -import { - ServiceListUrlFilters, - ServiceListUrlFiltersEnum, - ServiceListUrlQueryParams -} from "../../urls"; - -export const STAFF_FILTERS_KEY = "staffFilters"; - -export function getFilterOpts( - params: ServiceListUrlFilters -): ServiceListFilterOpts { - return { - isActive: { - active: maybe(() => params.active !== undefined, false), - value: - params.active !== undefined ? parseBoolean(params.active, true) : true - } - }; -} - -export function getFilterVariables( - params: ServiceListUrlFilters -): ServiceAccountFilterInput { - return { - isActive: - params.active !== undefined - ? parseBoolean(params.active, true) - : undefined, - search: params.query - }; -} - -export function getFilterQueryParam( - filter: IFilterElement -): ServiceListUrlFilters { - const { name } = filter; - - switch (name) { - case ServiceFilterKeys.active: - return getSingleValueQueryParam(filter, ServiceListUrlFiltersEnum.active); - } -} - -export const { - deleteFilterTab, - getFilterTabs, - saveFilterTab -} = createFilterTabUtils(STAFF_FILTERS_KEY); - -export const { areFiltersApplied, getActiveFilters } = createFilterUtils< - ServiceListUrlQueryParams, - ServiceListUrlFilters ->(ServiceListUrlFiltersEnum); diff --git a/src/services/views/ServiceList/index.ts b/src/services/views/ServiceList/index.ts deleted file mode 100644 index 3cfb6cc3d..000000000 --- a/src/services/views/ServiceList/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from "./ServiceList"; -export * from "./ServiceList"; diff --git a/src/services/views/ServiceList/sort.ts b/src/services/views/ServiceList/sort.ts deleted file mode 100644 index a4fc01c77..000000000 --- a/src/services/views/ServiceList/sort.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ServiceListUrlSortField } from "@saleor/services/urls"; -import { ServiceAccountSortField } from "@saleor/types/globalTypes"; -import { createGetSortQueryVariables } from "@saleor/utils/sort"; - -export function getSortQueryField( - sort: ServiceListUrlSortField -): ServiceAccountSortField { - switch (sort) { - case ServiceListUrlSortField.name: - return ServiceAccountSortField.NAME; - default: - return undefined; - } -} - -export const getSortQueryVariables = createGetSortQueryVariables( - getSortQueryField -); diff --git a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx index e1fa5cc78..11ccc1439 100644 --- a/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx +++ b/src/staff/components/StaffDetailsPage/StaffDetailsPage.tsx @@ -1,7 +1,7 @@ import { Card, CardContent, Typography } from "@material-ui/core"; import AccountPermissionGroups from "@saleor/components/AccountPermissionGroups"; -import AccountStatus from "@saleor/components/AccountStatus"; import AppHeader from "@saleor/components/AppHeader"; +import AccountStatus from "@saleor/components/AppStatus"; import CardSpacer from "@saleor/components/CardSpacer"; import CardTitle from "@saleor/components/CardTitle"; import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton"; diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index d6daf7eec..055cf794b 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -9767,6 +9767,6248 @@ exports[`Storyshots SiteSettings / Add key dialog form errors 1`] = ` /> `; +exports[`Storyshots Views / Apps / Activate app default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Activate app unnamed app 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / App details default 1`] = ` +
+
+
+
+ app1 +
+ +
+
+ +
+
+
+
+ + About this app + +
+
+
+
+
+

+ Lorem ipsum +

+
+
+
+
+
+ + App permissions + +
+
+
+
+
+
+ This app has permissions to: +
+
    +
  • + Manage orders. +
  • +
  • + Manage customers. +
  • +
+
+
+
+
+
+ + Data privacy + +
+
+
+
+ +
+
+
+
+`; + +exports[`Storyshots Views / Apps / App details loading 1`] = ` +
+
+
+
+ app1 +
+ +
+
+ +
+
+
+
+ + About this app + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + App permissions + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + Data privacy + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+`; + +exports[`Storyshots Views / Apps / App details settings default 1`] = ` +
+
+
+
+
+
+ app1 +
+
+
+
+ + + + My App + + + + + Support/FAQ + + +
+
+
+
+
+
+
+
+
+`; + +exports[`Storyshots Views / Apps / Apps list default 1`] = ` +
+
+
+
+ Apps +
+
+
+
+
+
+
+
+ + Ongoing Installations + +
+
+
+
+
+
+ + + + + + + + + + + + + + +
+ + app + + +
+ There was a problem during installation + +
+ + +
+ + app pending + + +
+ Installing app... +
+
+
+ + + +
+
+
+ + app success + +
+
+
+
+
+
+
+
+ + Thirdparty Apps + +
+
+
+
+
+
+ + + + + + + + + + + + + + + + +
+ + app + + + + +
+ + app1 + +
+
+ Deactivated +
+
+
+ + +
+
+
+
+
+
+
+
+
+ + Local Apps + +
+
+ +
+
+
+
+
+ + + + + + + +
+ + app custom + + + +
+
+
+
+
+
+
+
+ + Saleor Marketplace + +
+
+
+
+
+
+ Marketplace is coming soon +
+
+
+
+
+
+`; + +exports[`Storyshots Views / Apps / Apps list loading 1`] = ` +
+
+
+
+ Apps +
+
+
+
+
+
+
+
+ + Thirdparty Apps + +
+
+
+
+
+
+ + + + + + + + + + + +
+ + ‌ + +
+
+
+
+
+
+
+
+
+ + Local Apps + +
+
+ +
+
+
+
+
+ + + + + + +
+ + ‌ + +
+
+
+
+
+
+
+
+ + Saleor Marketplace + +
+
+
+
+
+
+ Marketplace is coming soon +
+
+
+
+
+
+`; + +exports[`Storyshots Views / Apps / Apps list no data 1`] = ` +
+
+
+
+ Apps +
+
+
+
+
+
+
+
+ + Thirdparty Apps + +
+
+
+
+
+
+ + + + + + + + + + + +
+
+ You don’t have any installed apps in your dashboard +
+
+
+
+
+
+
+
+
+
+ + Local Apps + +
+
+ +
+
+
+
+
+ + + + + + +
+
+ Your custom created apps will be shown here. +
+
+
+
+
+
+
+
+
+ + Saleor Marketplace + +
+
+
+
+
+
+ Marketplace is coming soon +
+
+
+
+
+
+`; + +exports[`Storyshots Views / Apps / Custom app details / Token delete default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Deactivate app default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Deactivate app unnamed app 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Delete app default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Delete app failed installation default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Delete app failed installation unnamed app 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Delete app unnamed app 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Install App default 1`] = ` +
+
+
+
+
+ + You are about to install app + +
+
+
+
+
+
+
+ +
+ +
+

+ A +

+
+
+
+
+
+
+
+ + App permissions + +
+
+
+
+
+
+ Installing this app will give it following permissions: +
+
    +
  • + Manage users +
  • +
  • + Manage orders +
  • +
+
+
+ Uninstalling the app will remove all your customer’s personal data stored by app. + + Learn more about data privacy + +
+
+
+
+
+
+ +
+
+ +
+
+
+
+`; + +exports[`Storyshots Views / Apps / Install App loading 1`] = ` +
+
+
+
+
+ + + ‌ + + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + App permissions + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ +
+
+ +
+
+
+
+`; + +exports[`Storyshots Views / Apps / Webhooks / Create webhook default 1`] = ` +
+ +
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ This URL will receive webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Create webhook form errors 1`] = ` +
+
+
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Create webhook loading 1`] = ` +
+
+
+
+
+ Create Webhook +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ This URL will receive webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Delete webhook default 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Delete webhook unnamed webhook 1`] = ` +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Webhook details default 1`] = ` +
+
+
+
+
+ Webhook Test 2 Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ This URL will receive webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Webhook details form errors 1`] = ` +
+
+
+
+
+ Webhook Test 2 Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+ +
+ + +
+

+ Invalid value +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Webhook details loading 1`] = ` +
+
+
+
+
+ ... Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ This URL will receive webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + +exports[`Storyshots Views / Apps / Webhooks / Webhook details unnamed 1`] = ` +
+
+
+
+
+ Unnamed Webhook Details +
+
+
+
+
+
+
+
+
+ + Webhook Information + +
+
+
+
+
+
+ General Informations +
+
+ +
+ + +
+
+
+
+
+
+ Webhook specific information +
+
+
+ +
+ + +
+

+ This URL will receive webhook POST requests +

+
+
+
+ +
+ + +
+

+ secret key is used to create a hash signature with each payload. *optional field +

+
+
+
+
+
+
+
+ + Events + +
+
+
+
+
+
+ Expand or restrict webhooks permissions to register certain events in Saleor system. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ + Webhook Status + +
+
+
+
+
+
+ If you want to disable this webhook please uncheck the box below. +
+ +
+
+
+
+
+ +
+`; + exports[`Storyshots Views / Attributes / Attribute details create 1`] = `
-
-
-
- -
-
-
- Service Accounts -
-
- Manage external integrations accounts -
-
-
-
-
-
-
- -
-
-
- Webhooks -
-
- View and update your webhook and their settings -
-
-
-
@@ -90685,7 +96847,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create default class="MuiCardContent-root-id" >
Expand or restrict group's permissions to access certain part of saleor system.
@@ -90699,7 +96861,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create default > @@ -91309,7 +97471,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create default
Expand or restrict group's permissions to access certain part of saleor system.
@@ -91447,7 +97609,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create errors 1 > @@ -92057,7 +98219,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create errors 1
Expand or restrict group's permissions to access certain part of saleor system.
@@ -92191,7 +98353,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create loading > @@ -92803,7 +98965,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Create loading
Expand or restrict group's permissions to access certain part of saleor system.
@@ -93369,7 +99531,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Details default > @@ -93980,7 +100142,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Details default
Expand or restrict group's permissions to access certain part of saleor system.
@@ -94549,7 +100711,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Details loading >
Expand or restrict group's permissions to access certain part of saleor system.
@@ -94790,7 +100952,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Details no memb > @@ -95401,7 +101563,7 @@ exports[`Storyshots Views / Permission Groups / Permission Group Details no memb
`; -exports[`Storyshots Views / Services / Create service default 1`] = ` -
-
-
-
-
- Create New Account -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Create service form errors 1`] = ` -
-
-
-
-
- Create New Account -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-

- Invalid value -

-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Create service loading 1`] = ` -
-
-
-
-
- Create New Account -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Delete service default 1`] = ` -
-`; - -exports[`Storyshots Views / Services / Service details default 1`] = ` -
-
-
-
-
- Magento Importer -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
- - Service Account Information - -
- -
-
-
-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- default - - **** AK05 - - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Service details default token 1`] = ` -
-
-
-
-
- Magento Importer -
-
-
-
-
-
-
-
-
-
-
-
- We’ve created your default token. Make sure to copy your new personal access token now. You won’t be able to see it again. -
-
- This token gives you access to your shop's API, which you'll find here: - - https://example.com/graphql/ - -
-
-
- -
-
-
-
- Generated Token -
-
- 93B4AF3D7E9FD7C61C4C9B32FF82F -
- -
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
- - Service Account Information - -
- -
-
-
-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- default - - **** AK05 - - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Service details form errors 1`] = ` -
-
-
-
-
- Magento Importer -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-

- Invalid value -

-
-
-
-
-
-
- - Service Account Information - -
- -
-
-
-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- default - - **** AK05 - - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Service details loading 1`] = ` -
-
-
-
-
- - ‌ - -
-
-
-
-
-
-
-
-
- - Service Account Information - -
-
-
-
-
-
- -
- - -
-
-
-
-
-
-
- - Service Account Information - -
- -
-
-
-
-
- - - - - - - - - - - - - - - -
- Token Note - - Key - - Actions -
- - ‌ - - - - ‌ - - - -
-
-
-
-
-
-
- - Permissions - -
-
-
-
-
-
- Expand or restrict user's permissions to access certain part of saleor system. -
-
-
- - - - - - -
-
- - User has full access to the store - -
-
-
-
-
-
-
- - - - - - -
-
- - Manage sales and vouchers - -
-
-
-
- - - - - - -
-
- - Manage navigation - -
-
-
-
- - - - - - -
-
- - Manage orders - -
-
-
-
- - - - - - -
-
- - Manage pages - -
-
-
-
- - - - - - -
-
- - Manage products - -
-
-
-
- - - - - - -
-
- - Manage settings - -
-
-
-
- - - - - - -
-
- - Manage shipping - -
-
-
-
- - - - - - -
-
- - Manage staff - -
-
-
-
- - - - - - -
-
- - Manage customers - -
-
-
-
- - - - - - -
-
- - Manage plugins - -
-
-
-
- - - - - - -
-
- - Manage apps - -
-
-
-
- - - - - - -
-
- - Manage webhooks - -
-
-
-
-
-
-
- - Account Status - -
-
-
-
-
-
- If you want to disable this account uncheck the box below -
- -
-
-
-
-
- -
-`; - -exports[`Storyshots Views / Services / Service list default 1`] = ` -
-
-
-
- Service Accounts -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
- -
-
-
- - -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
- Name -
- -
-
-
- - Slack - -
- active -
-
- - -
- - Facebook Market - -
- active -
-
- - -
- - Magento Importer - -
- inactive -
-
- - -
-
-
-
-
-`; - -exports[`Storyshots Views / Services / Service list loading 1`] = ` -
-
-
-
- Service Accounts -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
- -
-
-
- - -
-
-
-
- - - - - - - - - - - - - - - - - -
-
-
- Name -
- -
-
-
- - - ‌ - - -
-
- - -
-
-
-
-
-`; - -exports[`Storyshots Views / Services / Service list no data 1`] = ` -
-
-
-
- Service Accounts -
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
- -
-
-
- - -
-
-
-
- - - - - - - - - - - - - - - - -
-
-
- Name -
- -
-
-
- No service accounts found -
-
-
-
-
-`; - -exports[`Storyshots Views / Services / Token delete default 1`] = ` -
-`; - exports[`Storyshots Views / Shipping / Create shipping zone default 1`] = `
- Account Status + App Status
- If you want to disable this account uncheck the box below + If you want to disable this App please uncheck the box below.