Merge branch 'CURA-8441_campaign_links' of github.com:Ultimaker/Cura

This commit is contained in:
Jaime van Kessel 2021-08-09 14:09:27 +02:00
commit 8b2904ee3b
18 changed files with 29 additions and 28 deletions

View file

@ -28,6 +28,6 @@
<image>https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png</image> <image>https://raw.githubusercontent.com/Ultimaker/Cura/master/screenshot.png</image>
</screenshot> </screenshot>
</screenshots> </screenshots>
<url type="homepage">https://ultimaker.com/en/products/cura-software?utm_source=cura&amp;utm_medium=software&amp;utm_campaign=resources</url> <url type="homepage">https://ultimaker.com/software/ultimaker-cura?utm_source=cura&amp;utm_medium=software&amp;utm_campaign=cura-update-linux</url>
<translation type="gettext">Cura</translation> <translation type="gettext">Cura</translation>
</component> </component>

View file

@ -35,7 +35,7 @@ class CuraActions(QObject):
# Starting a web browser from a signal handler connected to a menu will crash on windows. # 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. # 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. # 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) cura.CuraApplication.CuraApplication.getInstance().functionEvent(event)
@pyqtSlot() @pyqtSlot()

View file

@ -161,7 +161,7 @@ class CuraApplication(QtApplication):
self.default_theme = "cura-light" 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() self._boot_loading_time = time.time()

View file

@ -24,7 +24,7 @@ if TYPE_CHECKING:
from cura.OAuth2.Models import UserProfile, OAuth2Settings from cura.OAuth2.Models import UserProfile, OAuth2Settings
from UM.Preferences import Preferences 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: class AuthorizationService:
"""The authorization service is responsible for handling the login flow, storing user credentials and providing """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 link to force the a browser logout from mycloud.ultimaker.com
:return: The authentication URL, properly formatted and encoded :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: if force_browser_logout:
# The url after '?next=' should be urlencoded connecting_char = "&" if "?" in MYCLOUD_LOGOFF_URL else "?"
auth_url = "{}?next={}".format(MYCLOUD_LOGOFF_URL, quote_plus(auth_url)) # The url after 'next=' should be urlencoded
auth_url = f"{MYCLOUD_LOGOFF_URL}{connecting_char}next={quote_plus(auth_url)}"
return auth_url return auth_url
def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None: def _onAuthStateChanged(self, auth_response: AuthenticationResponse) -> None:

View file

@ -96,7 +96,7 @@ Item
visible: createNewProjectButtonVisible && !manager.userAccountCanCreateNewLibraryProject && (manager.retrievingProjectsStatus == DF.RetrievalStatus.Success || manager.retrievingProjectsStatus == DF.RetrievalStatus.Failed) 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." 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 id: visitDigitalLibraryButton
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: "Visit Digital Library" 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. visible: searchBar.text === "" //Show the link to Digital Library when there are no projects in the user's Library.
} }
} }

View file

@ -319,7 +319,7 @@ class DFFileExportAndUploadManager:
def _onMessageActionTriggered(self, message, action): def _onMessageActionTriggered(self, message, action):
if action == "open_df_project": 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)) QDesktopServices.openUrl(QUrl(project_url))
message.hide() message.hide()

View file

@ -39,7 +39,7 @@ Rectangle
text: catalog.i18nc("@info:tooltip", "Go to Web Marketplace") text: catalog.i18nc("@info:tooltip", "Go to Web Marketplace")
Label Label
{ {
text: "<a href='%2'>".arg(toolbox.getWebMarketplaceUrl("materials")) + catalog.i18nc("@label", "Search materials") + "</a>" text: "<a href='%2'>".arg(toolbox.getWebMarketplaceUrl("materials") + "?utm_source=cura&utm_medium=software&utm_campaign=marketplace-search") + catalog.i18nc("@label", "Search materials") + "</a>"
width: contentWidth width: contentWidth
height: contentHeight height: contentHeight
horizontalAlignment: Text.AlignRight horizontalAlignment: Text.AlignRight

View file

@ -91,7 +91,7 @@ Item
verticalCenter: parent.verticalCenter verticalCenter: parent.verticalCenter
} }
acceptedButtons: Qt.LeftButton 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 UM.RecolorImage
{ {
id: cloudMarketplaceButton id: cloudMarketplaceButton

View file

@ -173,7 +173,7 @@ Cura.MachineAction
anchors.right: parent.right anchors.right: parent.right
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
renderType: Text.NativeRendering renderType: Text.NativeRendering
text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://support.ultimaker.com/hc/en-us/articles/360012795419"); text: catalog.i18nc("@label", "If your printer is not listed, read the <a href='%1'>network printing troubleshooting guide</a>").arg("https://ultimaker.com/en/cura/troubleshooting/network?utm_source=cura&utm_medium=software&utm_campaign=manage-network-printer");
onLinkActivated: Qt.openUrlExternally(link) onLinkActivated: Qt.openUrlExternally(link)
} }

View file

@ -262,7 +262,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
icon="", icon="",
description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"), description=I18N_CATALOG.i18nc("@action:tooltip", "Track the print in Ultimaker Digital Factory"),
button_align=message.ActionButtonAlignment.ALIGN_RIGHT) 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.pyQtActionTriggered.connect(lambda message, action: (QDesktopServices.openUrl(QUrl(df_url)), message.hide()))
message.show() message.show()
@ -334,11 +334,11 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
@pyqtSlot(name="openPrintJobControlPanel") @pyqtSlot(name="openPrintJobControlPanel")
def openPrintJobControlPanel(self) -> None: 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") @pyqtSlot(name="openPrinterControlPanel")
def openPrinterControlPanel(self) -> None: 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 @property
def clusterData(self) -> CloudClusterResponse: def clusterData(self) -> CloudClusterResponse:
@ -357,4 +357,4 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
"""Gets the URL on which to monitor the cluster via the cloud.""" """Gets the URL on which to monitor the cluster via the cloud."""
root_url_prefix = "-staging" if self._account.is_staging else "" 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)

View file

@ -332,7 +332,7 @@ class CloudOutputDeviceManager:
message_text += self.i18n_catalog.i18nc( message_text += self.i18n_catalog.i18nc(
"info:status", "info:status",
"To establish a connection, please visit the {website_link}".format(website_link = "<a href='https://digitalfactory.ultimaker.com/'>{}</a>.".format(digital_factory_string)) "To establish a connection, please visit the {website_link}".format(website_link = "<a href='https://digitalfactory.ultimaker.com?utm_source=cura&utm_medium=software&utm_campaign=change-account-connect-printer'>{}</a>.".format(digital_factory_string))
) )
self._removed_printers_message.setText(message_text) self._removed_printers_message.setText(message_text)
self._removed_printers_message.addAction("keep_printer_configurations_action", self._removed_printers_message.addAction("keep_printer_configurations_action",
@ -419,7 +419,7 @@ class CloudOutputDeviceManager:
machine.setMetaDataEntry("group_name", device.name) machine.setMetaDataEntry("group_name", device.name)
machine.setMetaDataEntry("group_size", device.clusterSize) machine.setMetaDataEntry("group_size", device.clusterSize)
digital_factory_string = self.i18n_catalog.i18nc("info:name", "Ultimaker Digital Factory") digital_factory_string = self.i18n_catalog.i18nc("info:name", "Ultimaker Digital Factory")
digital_factory_link = "<a href='https://digitalfactory.ultimaker.com/'>{digital_factory_string}</a>".format(digital_factory_string = digital_factory_string) digital_factory_link = "<a href='https://digitalfactory.ultimaker.com?utm_source=cura&utm_medium=software&utm_campaign=change-account-remove-printer'>{digital_factory_string}</a>".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) \ 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) \
+ "<br>" + 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) \ + "<br>" + 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) \
+ "<br><br>" + 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) + "<br><br>" + 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)

View file

@ -60,6 +60,6 @@ Column
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
height: UM.Theme.getSize("account_button").height height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Create a free Ultimaker account") 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")
} }
} }

View file

@ -98,7 +98,7 @@ Column
width: UM.Theme.getSize("account_button").width width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height height: UM.Theme.getSize("account_button").height
text: "Ultimaker Digital Factory" 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 fixedWidthMode: false
} }
@ -108,7 +108,7 @@ Column
width: UM.Theme.getSize("account_button").width width: UM.Theme.getSize("account_button").width
height: UM.Theme.getSize("account_button").height height: UM.Theme.getSize("account_button").height
text: catalog.i18nc("@button", "Ultimaker Account") 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 fixedWidthMode: false
} }

View file

@ -79,7 +79,7 @@ Item
Action Action
{ {
id: showTroubleShootingAction 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"); text: catalog.i18nc("@action:inmenu", "Show Online Troubleshooting Guide");
} }

View file

@ -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. // 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. // 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. // the newly added printers in this page.
// //
Item Item

View file

@ -251,7 +251,7 @@ Item
onClicked: onClicked:
{ {
// open the troubleshooting URL with web browser // 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) Qt.openUrlExternally(url)
} }
onEntered: onEntered:

View file

@ -215,7 +215,7 @@ Item
id: createAccountButton id: createAccountButton
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: catalog.i18nc("@text", "Create a free Ultimaker Account") 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")
} }
} }
} }

View file

@ -238,7 +238,7 @@ def test__generate_auth_url() -> None:
"response_type": "code" "response_type": "code"
} }
auth_url = authorization_service._generate_auth_url(query_parameters_dict, force_browser_logout = False) 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) 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