Repository: getredash/redash

Issue:
Remove Flask-Admin
Flask-Admin was a nice stop gap solution when our UI wasn't as evolved, but at this point it's more of a liability than any benefit.

Unless someone has a good use case for keeping it, we're going to remove it in the upcoming release or the one after.


Discussion:

Resolving patch:
diff --git a/redash/__init__.py b/redash/__init__.py
--- a/redash/__init__.py
+++ b/redash/__init__.py
@@ -97,8 +97,8 @@ def to_url(self, value):
         return value
 
 
-def create_app(load_admin=True):
-    from redash import admin, authentication, extensions, handlers
+def create_app():
+    from redash import authentication, extensions, handlers
     from redash.handlers.webpack import configure_webpack
     from redash.handlers import chrome_logger
     from redash.models import db, users
@@ -126,8 +126,6 @@ def create_app(load_admin=True):
     provision_app(app)
     db.init_app(app)
     migrate.init_app(app, db)
-    if load_admin:
-        admin.init_admin(app)
     mail.init_app(app)
     authentication.init_app(app)
     limiter.init_app(app)
diff --git a/redash/admin.py b/redash/admin.py
deleted file mode 100644
--- a/redash/admin.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from flask_admin import Admin
-from flask_admin.base import MenuLink
-from flask_admin.contrib.sqla import ModelView
-from flask_admin.contrib.sqla.form import AdminModelConverter
-from wtforms import fields
-from wtforms.widgets import TextInput
-
-from redash import models
-from redash.permissions import require_super_admin
-from redash.utils import json_loads
-
-
-class ArrayListField(fields.Field):
-    widget = TextInput()
-
-    def _value(self):
-        if self.data:
-            return u', '.join(self.data)
-        else:
-            return u''
-
-    def process_formdata(self, valuelist):
-        if valuelist:
-            self.data = [x.strip() for x in valuelist[0].split(',')]
-        else:
-            self.data = []
-
-
-class JSONTextAreaField(fields.TextAreaField):
-    def process_formdata(self, valuelist):
-        if valuelist:
-            try:
-                json_loads(valuelist[0])
-            except ValueError:
-                raise ValueError(self.gettext(u'Invalid JSON'))
-            self.data = valuelist[0]
-        else:
-            self.data = ''
-
-
-class BaseModelView(ModelView):
-    column_display_pk = True
-    model_form_converter = AdminModelConverter
-    form_excluded_columns = ('created_at', 'updated_at')
-
-    @require_super_admin
-    def is_accessible(self):
-        return True
-
-
-class QueryResultModelView(BaseModelView):
-    column_exclude_list = ('data',)
-
-
-class QueryModelView(BaseModelView):
-    column_exclude_list = ('latest_query_data',)
-    form_excluded_columns = ('version', 'visualizations', 'alerts', 'org', 'created_at',
-                             'updated_at', 'latest_query_data', 'search_vector')
-
-
-class DashboardModelView(BaseModelView):
-    column_searchable_list = ('name', 'slug')
-    column_exclude_list = ('version', )
-    form_excluded_columns = ('version', 'widgets', 'org', 'created_at', 'updated_at')
-
-
-def init_admin(app):
-    admin = Admin(app, name='Redash Admin', template_mode='bootstrap3')
-
-    admin.add_view(QueryModelView(models.Query, models.db.session))
-    admin.add_view(QueryResultModelView(models.QueryResult, models.db.session))
-    admin.add_view(DashboardModelView(models.Dashboard, models.db.session))
-    logout_link = MenuLink('Logout', '/logout', 'logout')
-
-    for m in (models.Visualization, models.Widget, models.Event, models.Organization):
-        admin.add_view(BaseModelView(m, models.db.session))
-
-    admin.add_link(logout_link)


Test patch: