diff --git a/com.ultimaker.cura.appdata.xml b/com.ultimaker.cura.appdata.xml index 781631e84a..bdd25e5242 100644 --- a/com.ultimaker.cura.appdata.xml +++ b/com.ultimaker.cura.appdata.xml @@ -28,6 +28,6 @@ https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png - https://ultimaker.com/en/products/cura-software?utm_source=cura&utm_medium=software&utm_campaign=resources + https://ultimaker.com/software/ultimaker-cura?utm_source=cura&utm_medium=software&utm_campaign=cura-update-linux Cura diff --git a/cura/CuraActions.py b/cura/CuraActions.py index 4d121338d8..8b232ad1bf 100644 --- a/cura/CuraActions.py +++ b/cura/CuraActions.py @@ -35,7 +35,7 @@ class CuraActions(QObject): # Starting a web browser from a signal handler connected to a menu will crash on windows. # So instead, defer the call to the next run of the event loop, since that does work. # Note that weirdly enough, only signal handlers that open a web browser fail like that. - event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software")], {}) + event = CallFunctionEvent(self._openUrl, [QUrl("https://ultimaker.com/en/resources/manuals/software?utm_source=cura&utm_medium=software&utm_campaign=dropdown-documentation")], {}) cura.CuraApplication.CuraApplication.getInstance().functionEvent(event) @pyqtSlot() diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 8d63e7ec12..9e19af526e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -161,7 +161,7 @@ class CuraApplication(QtApplication): self.default_theme = "cura-light" - self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features" + self.change_log_url = "https://ultimaker.com/ultimaker-cura-latest-features?utm_source=cura&utm_medium=software&utm_campaign=cura-update-features" self._boot_loading_time = time.time() diff --git a/cura/OAuth2/AuthorizationService.py b/cura/OAuth2/AuthorizationService.py index aba9558de8..b2e790cbfc 100644 --- a/cura/OAuth2/AuthorizationService.py +++ b/cura/OAuth2/AuthorizationService.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: from cura.OAuth2.Models import UserProfile, OAuth2Settings from UM.Preferences import Preferences -MYCLOUD_LOGOFF_URL = "https://mycloud.ultimaker.com/logoff" +MYCLOUD_LOGOFF_URL = "https://account.ultimaker.com/logoff?utm_source=cura&utm_medium=software&utm_campaign=change-account-before-adding-printers" class AuthorizationService: """The authorization service is responsible for handling the login flow, storing user credentials and providing @@ -209,10 +209,11 @@ class AuthorizationService: link to force the a browser logout from mycloud.ultimaker.com :return: The authentication URL, properly formatted and encoded """ - auth_url = "{}?{}".format(self._auth_url, urlencode(query_parameters_dict)) + auth_url = f"{self._auth_url}?{urlencode(query_parameters_dict)}" if force_browser_logout: - # The url after '?next=' should be urlencoded - auth_url = "{}?next={}".format(MYCLOUD_LOGOFF_URL, quote_plus(auth_url)) + connecting_char = "&" if "?" in MYCLOUD_LOGOFF_URL else "?" + # The url after 'next=' should be urlencoded + auth_url = f"{MYCLOUD_LOGOFF_URL}{connecting_char}next={quote_plus(auth_url)}" return auth_url def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None: diff --git a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml index 391c3a0fcc..50d3cb61c5 100644 --- a/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml +++ b/plugins/DigitalLibrary/resources/qml/SelectProjectPage.qml @@ -96,7 +96,7 @@ Item visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) tooltip: "Maximum number of projects reached. Please upgrade your subscription to create more projects." - onClicked: Qt.openUrlExternally("https://ultimaker.com/software/ultimaker-essentials/sign-up-cura?utm_source=cura&utm_medium=software&utm_campaign=lib-max") + onClicked: Qt.openUrlExternally("https://ultimaker.com/software/enterprise-software?utm_source=cura&utm_medium=software&utm_campaign=MaxProjLink") } } @@ -139,7 +139,7 @@ Item id: visitDigitalLibraryButton anchors.horizontalCenter: parent.horizontalCenter text: "Visit Digital Library" - onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library") + onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "/app/library?utm_source=cura&utm_medium=software&utm_campaign=empty-library") visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library. } } diff --git a/plugins/DigitalLibrary/src/DFFileExportAndUploadManager.py b/plugins/DigitalLibrary/src/DFFileExportAndUploadManager.py index c8650004e9..c27c3bb612 100644 --- a/plugins/DigitalLibrary/src/DFFileExportAndUploadManager.py +++ b/plugins/DigitalLibrary/src/DFFileExportAndUploadManager.py @@ -319,7 +319,7 @@ class DFFileExportAndUploadManager: def _onMessageActionTriggered(self, message, action): if action == "open_df_project": - project_url = "{}/app/library/project/{}?wait_for_new_files=true".format(CuraApplication.getInstance().ultimakerDigitalFactoryUrl, self._library_project_id) + project_url = "{}/app/library/project/{}?wait_for_new_files=true&utm_source=cura&utm_medium=software&utm_campaign=saved-library-file-message".format(CuraApplication.getInstance().ultimakerDigitalFactoryUrl, self._library_project_id) QDesktopServices.openUrl(QUrl(project_url)) message.hide() diff --git a/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml index b3f6cb42e1..4732de8241 100644 --- a/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml +++ b/plugins/Toolbox/resources/qml/components/ToolboxDownloadsShowcase.qml @@ -39,7 +39,7 @@ Rectangle text: catalog.i18nc("@info:tooltip", "Go to Web Marketplace") Label { - text: "".arg(toolbox.getWebMarketplaceUrl("materials")) + catalog.i18nc("@label", "Search materials") + "" + text: "".arg(toolbox.getWebMarketplaceUrl("materials") + "?utm_source=cura&utm_medium=software&utm_campaign=marketplace-search") + catalog.i18nc("@label", "Search materials") + "" width: contentWidth height: contentHeight horizontalAlignment: Text.AlignRight diff --git a/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml b/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml index 1bdfa80b79..2c43110af9 100644 --- a/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml +++ b/plugins/Toolbox/resources/qml/components/ToolboxHeader.qml @@ -91,7 +91,7 @@ Item verticalCenter: parent.verticalCenter } acceptedButtons: Qt.LeftButton - onClicked: Qt.openUrlExternally(toolbox.getWebMarketplaceUrl("plugins")) + onClicked: Qt.openUrlExternally(toolbox.getWebMarketplaceUrl("plugins") + "?utm_source=cura&utm_medium=software&utm_campaign=marketplace-button") UM.RecolorImage { id: cloudMarketplaceButton diff --git a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml index e6bc464dea..2843e32da4 100644 --- a/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml +++ b/plugins/UM3NetworkPrinting/resources/qml/DiscoverUM3Action.qml @@ -173,7 +173,7 @@ Cura.MachineAction anchors.right: parent.right wrapMode: Text.WordWrap renderType: Text.NativeRendering - text: catalog.i18nc("@label", "If your printer is not listed, read the network printing troubleshooting guide").arg("https://support.ultimaker.com/hc/en-us/articles/360012795419"); + text: catalog.i18nc("@label", "If your printer is not listed, read the network printing troubleshooting guide").arg("https://ultimaker.com/en/cura/troubleshooting/network?utm_source=cura&utm_medium=software&utm_campaign=manage-network-printer"); onLinkActivated: Qt.openUrlExternally(link) } diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py index 9eaa133ef5..5b15a5a0fd 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDevice.py @@ -262,7 +262,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): icon="", description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"), button_align=message.ActionButtonAlignment.ALIGN_RIGHT) - df_url = f"https://digitalfactory.ultimaker.com/app/jobs/{self._cluster.cluster_id}?utm_source=cura&utm_medium=software&utm_campaign=monitor-button" + df_url = f"https://digitalfactory.ultimaker.com/app/jobs/{self._cluster.cluster_id}?utm_source=cura&utm_medium=software&utm_campaign=message-printjob-sent" message.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide())) message.show() @@ -334,11 +334,11 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): @pyqtSlot(name="openPrintJobControlPanel") def openPrintJobControlPanel(self) -> None: - QDesktopServices.openUrl(QUrl(self.clusterCloudUrl)) + QDesktopServices.openUrl(QUrl(self.clusterCloudUrl)+ "?utm_source=cura&utm_medium=software&utm_campaign=monitor-manage-browser") @pyqtSlot(name="openPrinterControlPanel") def openPrinterControlPanel(self) -> None: - QDesktopServices.openUrl(QUrl(self.clusterCloudUrl)) + QDesktopServices.openUrl(QUrl(self.clusterCloudUrl + "?utm_source=cura&utm_medium=software&utm_campaign=monitor-manage-printer")) @property def clusterData(self) -> CloudClusterResponse: @@ -357,4 +357,4 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice): """Gets the URL on which to monitor the cluster via the cloud.""" root_url_prefix = "-staging" if self._account.is_staging else "" - return "https://mycloud{}.ultimaker.com/app/jobs/{}".format(root_url_prefix, self.clusterData.cluster_id) + return "https://digitalfactory{}.ultimaker.com/app/jobs/{}".format(root_url_prefix, self.clusterData.cluster_id) diff --git a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py index a900edeb75..f50a2ec5d9 100644 --- a/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py +++ b/plugins/UM3NetworkPrinting/src/Cloud/CloudOutputDeviceManager.py @@ -332,7 +332,7 @@ class CloudOutputDeviceManager: message_text += self.i18n_catalog.i18nc( "info:status", - "To establish a connection, please visit the {website_link}".format(website_link = "{}.".format(digital_factory_string)) + "To establish a connection, please visit the {website_link}".format(website_link = "{}.".format(digital_factory_string)) ) self._removed_printers_message.setText(message_text) self._removed_printers_message.addAction("keep_printer_configurations_action", @@ -419,7 +419,7 @@ class CloudOutputDeviceManager: machine.setMetaDataEntry("group_name", device.name) machine.setMetaDataEntry("group_size", device.clusterSize) digital_factory_string = self.i18n_catalog.i18nc("info:name", "Ultimaker Digital Factory") - digital_factory_link = "{digital_factory_string}".format(digital_factory_string = digital_factory_string) + digital_factory_link = "{digital_factory_string}".format(digital_factory_string = digital_factory_string) removal_warning_string = self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "{printer_name} will be removed until the next account sync.").format(printer_name = device.name) \ + "
" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "To remove {printer_name} permanently, visit {digital_factory_link}").format(printer_name = device.name, digital_factory_link = digital_factory_link) \ + "

" + self.i18n_catalog.i18nc("@message {printer_name} is replaced with the name of the printer", "Are you sure you want to remove {printer_name} temporarily?").format(printer_name = device.name) diff --git a/resources/qml/Account/GeneralOperations.qml b/resources/qml/Account/GeneralOperations.qml index c78e9ad828..658ce309a6 100644 --- a/resources/qml/Account/GeneralOperations.qml +++ b/resources/qml/Account/GeneralOperations.qml @@ -60,6 +60,6 @@ Column anchors.horizontalCenter: parent.horizontalCenter height: UM.Theme.getSize("account_button").height text: catalog.i18nc("@button", "Create a free Ultimaker account") - onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "/app/create") + onClicked: Qt.openUrlExternally("https://ultimaker.com/ultimaker-cura-account-sign-up?utm_source=cura&utm_medium=software&utm_campaign=menu-signup") } } diff --git a/resources/qml/Account/UserOperations.qml b/resources/qml/Account/UserOperations.qml index f5241596d5..75a81737f2 100644 --- a/resources/qml/Account/UserOperations.qml +++ b/resources/qml/Account/UserOperations.qml @@ -98,7 +98,7 @@ Column width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height text: "Ultimaker Digital Factory" - onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl) + onClicked: Qt.openUrlExternally(CuraApplication.ultimakerDigitalFactoryUrl + "?utm_source=cura&utm_medium=software&utm_campaign=menu-visit-DF") fixedWidthMode: false } @@ -108,7 +108,7 @@ Column width: UM.Theme.getSize("account_button").width height: UM.Theme.getSize("account_button").height text: catalog.i18nc("@button", "Ultimaker Account") - onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl) + onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "?utm_source=cura&utm_medium=software&utm_campaign=menu-visit-account") fixedWidthMode: false } diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 95c6778b87..aa88c9176d 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -79,7 +79,7 @@ Item Action { id: showTroubleShootingAction - onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/troubleshooting") + onTriggered: Qt.openUrlExternally("https://ultimaker.com/en/troubleshooting?utm_source=cura&utm_medium=software&utm_campaign=dropdown-troubleshooting") text: catalog.i18nc("@action:inmenu", "Show Online Troubleshooting Guide"); } diff --git a/resources/qml/WelcomePages/AddCloudPrintersView.qml b/resources/qml/WelcomePages/AddCloudPrintersView.qml index 524bf288a0..e33d519f22 100644 --- a/resources/qml/WelcomePages/AddCloudPrintersView.qml +++ b/resources/qml/WelcomePages/AddCloudPrintersView.qml @@ -12,7 +12,7 @@ import Cura 1.7 as Cura // // This component gets activated when the user presses the "Add cloud printers" button from the "Add a Printer" page. // It contains a busy indicator that remains active until the user logs in and adds a cloud printer in his/her account. -// Once a cloud printer is added in mycloud.ultimaker.com, Cura discovers it (in a time window of 30 sec) and displays +// Once a cloud printer is added in digitalfactory.ultimaker.com, Cura discovers it (in a time window of 30 sec) and displays // the newly added printers in this page. // Item diff --git a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml index 58cadbec37..49d5b57021 100644 --- a/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml +++ b/resources/qml/WelcomePages/AddNetworkPrinterScrollView.qml @@ -251,7 +251,7 @@ Item onClicked: { // open the troubleshooting URL with web browser - const url = "https://ultimaker.com/in/cura/troubleshooting/network" + const url = "https://ultimaker.com/in/cura/troubleshooting/network?utm_source=cura&utm_medium=software&utm_campaign=add-network-printer" Qt.openUrlExternally(url) } onEntered: diff --git a/resources/qml/WelcomePages/CloudContent.qml b/resources/qml/WelcomePages/CloudContent.qml index 26e3a2f87c..9d3e980991 100644 --- a/resources/qml/WelcomePages/CloudContent.qml +++ b/resources/qml/WelcomePages/CloudContent.qml @@ -215,7 +215,7 @@ Item id: createAccountButton anchors.horizontalCenter: parent.horizontalCenter text: catalog.i18nc("@text", "Create a free Ultimaker Account") - onClicked: Qt.openUrlExternally(CuraApplication.ultimakerCloudAccountRootUrl + "/app/create") + onClicked: Qt.openUrlExternally("https://ultimaker.com/ultimaker-cura-account-sign-up?utm_source=cura&utm_medium=software&utm_campaign=onboarding-signup") } } } diff --git a/tests/TestOAuth2.py b/tests/TestOAuth2.py index 731a31690a..2c039b296a 100644 --- a/tests/TestOAuth2.py +++ b/tests/TestOAuth2.py @@ -238,7 +238,7 @@ def test__generate_auth_url() -> None: "response_type": "code" } auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = False) - assert MYCLOUD_LOGOFF_URL + "?next=" not in auth_url + assert MYCLOUD_LOGOFF_URL + "&next=" not in auth_url auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = True) - assert MYCLOUD_LOGOFF_URL + "?next=" in auth_url + assert MYCLOUD_LOGOFF_URL + "&next=" in auth_url