prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Non blocking widget refresh indicator
  When refreshing a dashboard widget the previous results are hidden by the refresh animation. This can be an issue when refreshing a dashboard frequently, as you might happen to see the spinner for long period of times.
  
  To solve this we can keep showing the old data until new one is available, while showing some indication that refresh is in progress.
  
  Is the following animation enough?
  
  ![](http://g.recordit.co/CyccMD6dFc.gif)
  After refreshing a dashboard, widgets become draggable even when not in edit mode
  
  
  </issue>
  <code>
  [start of redash/handlers/widgets.py]
  1 import json
  2 
  3 from flask import request
  4 from redash import models
  5 from redash.handlers.base import BaseResource
  6 from redash.permissions import (require_access,
  7                                 require_object_modify_permission,
  8                                 require_permission, view_only)
  9 
  10 
  11 class WidgetListResource(BaseResource):
  12     @require_permission('edit_dashboard')
  13     def post(self):
  14         """
  15         Add a widget to a dashboard.
  16 
  17         :<json number dashboard_id: The ID for the dashboard being added to
  18         :<json visualization_id: The ID of the visualization to put in this widget
  19         :<json object options: Widget options
  20         :<json string text: Text box contents
  21         :<json number width: Width for widget display
  22 
  23         :>json object widget: The created widget
  24         """
  25         widget_properties = request.get_json(force=True)
  26         dashboard = models.Dashboard.get_by_id_and_org(widget_properties.pop('dashboard_id'), self.current_org)
  27         require_object_modify_permission(dashboard, self.current_user)
  28 
  29         widget_properties['options'] = json.dumps(widget_properties['options'])
  30         widget_properties.pop('id', None)
  31         widget_properties['dashboard'] = dashboard
  32 
  33         visualization_id = widget_properties.pop('visualization_id')
  34         if visualization_id:
  35             visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)
  36             require_access(visualization.query_rel.groups, self.current_user, view_only)
  37         else:
  38             visualization = None
  39 
  40         widget_properties['visualization'] = visualization
  41 
  42         widget = models.Widget(**widget_properties)
  43         models.db.session.add(widget)
  44         models.db.session.commit()
  45 
  46         models.db.session.commit()
  47         return {'widget': widget.to_dict()}
  48 
  49 
  50 class WidgetResource(BaseResource):
  51     @require_permission('edit_dashboard')
  52     def post(self, widget_id):
  53         """
  54         Updates a widget in a dashboard.
  55         This method currently handles Text Box widgets only.
  56 
  57         :param number widget_id: The ID of the widget to modify
  58 
  59         :<json string text: The new contents of the text box
  60         """
  61         widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
  62         require_object_modify_permission(widget.dashboard, self.current_user)
  63         widget_properties = request.get_json(force=True)
  64         widget.text = widget_properties['text']
  65         widget.options = json.dumps(widget_properties['options'])
  66         models.db.session.commit()
  67         return widget.to_dict()
  68 
  69     @require_permission('edit_dashboard')
  70     def delete(self, widget_id):
  71         """
  72         Remove a widget from a dashboard.
  73 
  74         :param number widget_id: ID of widget to remove
  75         """
  76         widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)
  77         require_object_modify_permission(widget.dashboard, self.current_user)
  78         models.db.session.delete(widget)
  79         models.db.session.commit()
  80
  [end of redash/handlers/widgets.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/redash/handlers/widgets.py b/redash/handlers/widgets.py
  --- a/redash/handlers/widgets.py
  +++ b/redash/handlers/widgets.py
  @@ -44,7 +44,7 @@
           models.db.session.commit()
   
           models.db.session.commit()
  -        return {'widget': widget.to_dict()}
  +        return widget.to_dict()
   
   
   class WidgetResource(BaseResource):
  
verification_info: {"golden_diff": "diff --git a/redash/handlers/widgets.py b/redash/handlers/widgets.py\n--- a/redash/handlers/widgets.py\n+++ b/redash/handlers/widgets.py\n@@ -44,7 +44,7 @@\n         models.db.session.commit()\n \n         models.db.session.commit()\n-        return {'widget': widget.to_dict()}\n+        return widget.to_dict()\n \n \n class WidgetResource(BaseResource):\n", "issue": "Non blocking widget refresh indicator\nWhen refreshing a dashboard widget the previous results are hidden by the refresh animation. This can be an issue when refreshing a dashboard frequently, as you might happen to see the spinner for long period of times.\r\n\r\nTo solve this we can keep showing the old data until new one is available, while showing some indication that refresh is in progress.\r\n\r\nIs the following animation enough?\r\n\r\n![](http://g.recordit.co/CyccMD6dFc.gif)\nAfter refreshing a dashboard, widgets become draggable even when not in edit mode\n\n", "before_files": [{"content": "import json\n\nfrom flask import request\nfrom redash import models\nfrom redash.handlers.base import BaseResource\nfrom redash.permissions import (require_access,\n                                require_object_modify_permission,\n                                require_permission, view_only)\n\n\nclass WidgetListResource(BaseResource):\n    @require_permission('edit_dashboard')\n    def post(self):\n        \"\"\"\n        Add a widget to a dashboard.\n\n        :<json number dashboard_id: The ID for the dashboard being added to\n        :<json visualization_id: The ID of the visualization to put in this widget\n        :<json object options: Widget options\n        :<json string text: Text box contents\n        :<json number width: Width for widget display\n\n        :>json object widget: The created widget\n        \"\"\"\n        widget_properties = request.get_json(force=True)\n        dashboard = models.Dashboard.get_by_id_and_org(widget_properties.pop('dashboard_id'), self.current_org)\n        require_object_modify_permission(dashboard, self.current_user)\n\n        widget_properties['options'] = json.dumps(widget_properties['options'])\n        widget_properties.pop('id', None)\n        widget_properties['dashboard'] = dashboard\n\n        visualization_id = widget_properties.pop('visualization_id')\n        if visualization_id:\n            visualization = models.Visualization.get_by_id_and_org(visualization_id, self.current_org)\n            require_access(visualization.query_rel.groups, self.current_user, view_only)\n        else:\n            visualization = None\n\n        widget_properties['visualization'] = visualization\n\n        widget = models.Widget(**widget_properties)\n        models.db.session.add(widget)\n        models.db.session.commit()\n\n        models.db.session.commit()\n        return {'widget': widget.to_dict()}\n\n\nclass WidgetResource(BaseResource):\n    @require_permission('edit_dashboard')\n    def post(self, widget_id):\n        \"\"\"\n        Updates a widget in a dashboard.\n        This method currently handles Text Box widgets only.\n\n        :param number widget_id: The ID of the widget to modify\n\n        :<json string text: The new contents of the text box\n        \"\"\"\n        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)\n        require_object_modify_permission(widget.dashboard, self.current_user)\n        widget_properties = request.get_json(force=True)\n        widget.text = widget_properties['text']\n        widget.options = json.dumps(widget_properties['options'])\n        models.db.session.commit()\n        return widget.to_dict()\n\n    @require_permission('edit_dashboard')\n    def delete(self, widget_id):\n        \"\"\"\n        Remove a widget from a dashboard.\n\n        :param number widget_id: ID of widget to remove\n        \"\"\"\n        widget = models.Widget.get_by_id_and_org(widget_id, self.current_org)\n        require_object_modify_permission(widget.dashboard, self.current_user)\n        models.db.session.delete(widget)\n        models.db.session.commit()\n", "path": "redash/handlers/widgets.py"}]}