prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Xtheme: there is no warning for usaved changes when switching between plugins
  To reproduce:
  1. Edit some content in Xtheme editor
  2. Select another plugin without saving
  3. See your changes to disappear
  
  There probably should be warning before switching plugins when you have unsaved information.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `shuup/campaigns/admin_module/forms/_basket.py`
  Content:
  ```
  1 # This file is part of Shuup.
  2 #
  3 # Copyright (c) 2012-2019, Shoop Commerce Ltd. All rights reserved.
  4 #
  5 # This source code is licensed under the OSL-3.0 license found in the
  6 # LICENSE file in the root directory of this source tree.
  7 from django import forms
  8 from django.db.models import Q
  9 from django.utils.translation import ugettext_lazy as _
  10 
  11 from shuup.admin.shop_provider import get_shop
  12 from shuup.admin.supplier_provider import get_supplier
  13 from shuup.campaigns.models import BasketCampaign, Coupon
  14 
  15 from ._base import BaseCampaignForm, QuickAddCouponSelect
  16 
  17 
  18 class BasketCampaignForm(BaseCampaignForm):
  19     class Meta(BaseCampaignForm.Meta):
  20         model = BasketCampaign
  21 
  22     def __init__(self, *args, **kwargs):
  23         super(BasketCampaignForm, self).__init__(*args, **kwargs)
  24 
  25         coupons = Coupon.objects.filter(
  26             Q(active=True, shop=get_shop(self.request)),
  27             Q(campaign=None) | Q(campaign=self.instance),
  28         )
  29         supplier = get_supplier(self.request)
  30         if supplier:
  31             coupons = coupons.filter(supplier=supplier)
  32 
  33         coupon_code_choices = [('', '')] + list(coupons.values_list("pk", "code"))
  34         field_kwargs = dict(choices=coupon_code_choices, required=False)
  35         field_kwargs["help_text"] = _("Define the required coupon for this campaign.")
  36         field_kwargs["label"] = _("Coupon")
  37         field_kwargs["widget"] = QuickAddCouponSelect(editable_model="campaigns.Coupon")
  38         if self.instance.pk and self.instance.coupon:
  39             field_kwargs["initial"] = self.instance.coupon.pk
  40 
  41         self.fields["coupon"] = forms.ChoiceField(**field_kwargs)
  42 
  43         # the supplier will be, by default, the current one
  44         if supplier:
  45             self.fields["supplier"].widget = forms.HiddenInput()
  46 
  47     def clean_coupon(self):
  48         coupon = self.cleaned_data.get("coupon")
  49         if coupon:
  50             coupon = Coupon.objects.get(pk=coupon)
  51         return coupon or None
  52 
  53     def clean_supplier(self):
  54         return self.cleaned_data.get("supplier") or get_supplier(self.request)
  55
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/shuup/campaigns/admin_module/forms/_basket.py b/shuup/campaigns/admin_module/forms/_basket.py
  --- a/shuup/campaigns/admin_module/forms/_basket.py
  +++ b/shuup/campaigns/admin_module/forms/_basket.py
  @@ -30,7 +30,7 @@
           if supplier:
               coupons = coupons.filter(supplier=supplier)
   
  -        coupon_code_choices = [('', '')] + list(coupons.values_list("pk", "code"))
  +        coupon_code_choices = [('', '---------')] + list(coupons.values_list("pk", "code"))
           field_kwargs = dict(choices=coupon_code_choices, required=False)
           field_kwargs["help_text"] = _("Define the required coupon for this campaign.")
           field_kwargs["label"] = _("Coupon")
  
verification_info: {"golden_diff": "diff --git a/shuup/campaigns/admin_module/forms/_basket.py b/shuup/campaigns/admin_module/forms/_basket.py\n--- a/shuup/campaigns/admin_module/forms/_basket.py\n+++ b/shuup/campaigns/admin_module/forms/_basket.py\n@@ -30,7 +30,7 @@\n         if supplier:\n             coupons = coupons.filter(supplier=supplier)\n \n-        coupon_code_choices = [('', '')] + list(coupons.values_list(\"pk\", \"code\"))\n+        coupon_code_choices = [('', '---------')] + list(coupons.values_list(\"pk\", \"code\"))\n         field_kwargs = dict(choices=coupon_code_choices, required=False)\n         field_kwargs[\"help_text\"] = _(\"Define the required coupon for this campaign.\")\n         field_kwargs[\"label\"] = _(\"Coupon\")\n", "issue": "Xtheme: there is no warning for usaved changes when switching between plugins\nTo reproduce:\r\n1. Edit some content in Xtheme editor\r\n2. Select another plugin without saving\r\n3. See your changes to disappear\r\n\r\nThere probably should be warning before switching plugins when you have unsaved information.\n", "before_files": [{"content": "# This file is part of Shuup.\n#\n# Copyright (c) 2012-2019, Shoop Commerce Ltd. All rights reserved.\n#\n# This source code is licensed under the OSL-3.0 license found in the\n# LICENSE file in the root directory of this source tree.\nfrom django import forms\nfrom django.db.models import Q\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom shuup.admin.shop_provider import get_shop\nfrom shuup.admin.supplier_provider import get_supplier\nfrom shuup.campaigns.models import BasketCampaign, Coupon\n\nfrom ._base import BaseCampaignForm, QuickAddCouponSelect\n\n\nclass BasketCampaignForm(BaseCampaignForm):\n    class Meta(BaseCampaignForm.Meta):\n        model = BasketCampaign\n\n    def __init__(self, *args, **kwargs):\n        super(BasketCampaignForm, self).__init__(*args, **kwargs)\n\n        coupons = Coupon.objects.filter(\n            Q(active=True, shop=get_shop(self.request)),\n            Q(campaign=None) | Q(campaign=self.instance),\n        )\n        supplier = get_supplier(self.request)\n        if supplier:\n            coupons = coupons.filter(supplier=supplier)\n\n        coupon_code_choices = [('', '')] + list(coupons.values_list(\"pk\", \"code\"))\n        field_kwargs = dict(choices=coupon_code_choices, required=False)\n        field_kwargs[\"help_text\"] = _(\"Define the required coupon for this campaign.\")\n        field_kwargs[\"label\"] = _(\"Coupon\")\n        field_kwargs[\"widget\"] = QuickAddCouponSelect(editable_model=\"campaigns.Coupon\")\n        if self.instance.pk and self.instance.coupon:\n            field_kwargs[\"initial\"] = self.instance.coupon.pk\n\n        self.fields[\"coupon\"] = forms.ChoiceField(**field_kwargs)\n\n        # the supplier will be, by default, the current one\n        if supplier:\n            self.fields[\"supplier\"].widget = forms.HiddenInput()\n\n    def clean_coupon(self):\n        coupon = self.cleaned_data.get(\"coupon\")\n        if coupon:\n            coupon = Coupon.objects.get(pk=coupon)\n        return coupon or None\n\n    def clean_supplier(self):\n        return self.cleaned_data.get(\"supplier\") or get_supplier(self.request)\n", "path": "shuup/campaigns/admin_module/forms/_basket.py"}], "after_files": [{"content": "# This file is part of Shuup.\n#\n# Copyright (c) 2012-2019, Shoop Commerce Ltd. All rights reserved.\n#\n# This source code is licensed under the OSL-3.0 license found in the\n# LICENSE file in the root directory of this source tree.\nfrom django import forms\nfrom django.db.models import Q\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom shuup.admin.shop_provider import get_shop\nfrom shuup.admin.supplier_provider import get_supplier\nfrom shuup.campaigns.models import BasketCampaign, Coupon\n\nfrom ._base import BaseCampaignForm, QuickAddCouponSelect\n\n\nclass BasketCampaignForm(BaseCampaignForm):\n    class Meta(BaseCampaignForm.Meta):\n        model = BasketCampaign\n\n    def __init__(self, *args, **kwargs):\n        super(BasketCampaignForm, self).__init__(*args, **kwargs)\n\n        coupons = Coupon.objects.filter(\n            Q(active=True, shop=get_shop(self.request)),\n            Q(campaign=None) | Q(campaign=self.instance),\n        )\n        supplier = get_supplier(self.request)\n        if supplier:\n            coupons = coupons.filter(supplier=supplier)\n\n        coupon_code_choices = [('', '---------')] + list(coupons.values_list(\"pk\", \"code\"))\n        field_kwargs = dict(choices=coupon_code_choices, required=False)\n        field_kwargs[\"help_text\"] = _(\"Define the required coupon for this campaign.\")\n        field_kwargs[\"label\"] = _(\"Coupon\")\n        field_kwargs[\"widget\"] = QuickAddCouponSelect(editable_model=\"campaigns.Coupon\")\n        if self.instance.pk and self.instance.coupon:\n            field_kwargs[\"initial\"] = self.instance.coupon.pk\n\n        self.fields[\"coupon\"] = forms.ChoiceField(**field_kwargs)\n\n        # the supplier will be, by default, the current one\n        if supplier:\n            self.fields[\"supplier\"].widget = forms.HiddenInput()\n\n    def clean_coupon(self):\n        coupon = self.cleaned_data.get(\"coupon\")\n        if coupon:\n            coupon = Coupon.objects.get(pk=coupon)\n        return coupon or None\n\n    def clean_supplier(self):\n        return self.cleaned_data.get(\"supplier\") or get_supplier(self.request)\n", "path": "shuup/campaigns/admin_module/forms/_basket.py"}]}