diff --git a/rd_ui/app/scripts/app.js b/rd_ui/app/scripts/app.js index 83d9fafa..11f2ab5a 100644 --- a/rd_ui/app/scripts/app.js +++ b/rd_ui/app/scripts/app.js @@ -90,6 +90,10 @@ angular.module('redash', [ templateUrl: '/views/index.html', controller: 'IndexCtrl' }); + $routeProvider.when('/personal', { + templateUrl: '/views/personal.html', + controller: 'PersonalIndexCtrl' + }); $routeProvider.otherwise({ redirectTo: '/' }); diff --git a/rd_ui/app/scripts/controllers/controllers.js b/rd_ui/app/scripts/controllers/controllers.js index a16c012b..d2ca5b6c 100644 --- a/rd_ui/app/scripts/controllers/controllers.js +++ b/rd_ui/app/scripts/controllers/controllers.js @@ -192,7 +192,7 @@ $(window).click(function () { notifications.getPermissions(); }); - } + }; var IndexCtrl = function ($scope, Events, Dashboard) { Events.record(currentUser, "view", "page", "homepage"); @@ -206,11 +206,29 @@ }); } } - } + }; + + var PersonalIndexCtrl = function ($scope, Events, Dashboard, Query) { + Events.record(currentUser, "view", "page", "homepage"); + $scope.$parent.pageTitle = "Home"; + + $scope.recentQueries = Query.recent(); + $scope.recentDashboards = Dashboard.recent(); + + $scope.archiveDashboard = function (dashboard) { + if (confirm('Are you sure you want to delete "' + dashboard.name + '" dashboard?')) { + Events.record(currentUser, "archive", "dashboard", dashboard.id); + dashboard.$delete(function () { + $scope.$parent.reloadDashboards(); + }); + } + } + }; angular.module('redash.controllers', []) .controller('QueriesCtrl', ['$scope', '$http', '$location', '$filter', 'Query', QueriesCtrl]) .controller('IndexCtrl', ['$scope', 'Events', 'Dashboard', IndexCtrl]) + .controller('PersonalIndexCtrl', ['$scope', 'Events', 'Dashboard', 'Query', PersonalIndexCtrl]) .controller('MainCtrl', ['$scope', '$location', 'Dashboard', 'notifications', MainCtrl]) .controller('QuerySearchCtrl', ['$scope', '$location', '$filter', 'Events', 'Query', QuerySearchCtrl]); })(); diff --git a/rd_ui/app/scripts/services/dashboards.js b/rd_ui/app/scripts/services/dashboards.js index 2b515572..6da28c63 100644 --- a/rd_ui/app/scripts/services/dashboards.js +++ b/rd_ui/app/scripts/services/dashboards.js @@ -1,6 +1,12 @@ (function () { var Dashboard = function($resource) { - var resource = $resource('/api/dashboards/:slug', {slug: '@slug'}); + var resource = $resource('/api/dashboards/:slug', {slug: '@slug'}, { + recent: { + method: 'get', + isArray: true, + url: "/api/dashboards/recent" + }}); + resource.prototype.canEdit = function() { return currentUser.hasPermission('admin') || currentUser.canEdit(this); } diff --git a/rd_ui/app/scripts/services/resources.js b/rd_ui/app/scripts/services/resources.js index 08ad8c68..fae28acf 100644 --- a/rd_ui/app/scripts/services/resources.js +++ b/rd_ui/app/scripts/services/resources.js @@ -377,7 +377,18 @@ }; var Query = function ($resource, QueryResult, DataSource) { - var Query = $resource('/api/queries/:id', {id: '@id'}, {search: {method: 'get', isArray: true, url: "/api/queries/search"}}); + var Query = $resource('/api/queries/:id', {id: '@id'}, + { + search: { + method: 'get', + isArray: true, + url: "/api/queries/search" + }, + recent: { + method: 'get', + isArray: true, + url: "/api/queries/recent" + }}); Query.newQuery = function () { return new Query({ diff --git a/rd_ui/app/views/personal.html b/rd_ui/app/views/personal.html new file mode 100644 index 00000000..834f2cd7 --- /dev/null +++ b/rd_ui/app/views/personal.html @@ -0,0 +1,28 @@ +
+
+
+
+ Recent Dashboards + +
+ +
+ +
+
+ Recent Queries +
+ {{query.name}} +
+
+ +
+
+
Admin
+ Status +
+
+
\ No newline at end of file diff --git a/redash/controllers.py b/redash/controllers.py index 82c96bb6..d6eadf54 100644 --- a/redash/controllers.py +++ b/redash/controllers.py @@ -35,6 +35,7 @@ def ping(): @app.route('/queries') @app.route('/queries/') @app.route('/queries//') +@app.route('/personal') @app.route('/') @auth.required def index(**kwargs): @@ -181,6 +182,11 @@ class DataSourceListAPI(BaseResource): api.add_resource(DataSourceListAPI, '/api/data_sources', endpoint='data_sources') +class DashboardRecentAPI(BaseResource): + def get(self): + return [d.to_dict() for d in models.Dashboard.recent(current_user.id).limit(20)] + + class DashboardListAPI(BaseResource): def get(self): dashboards = [d.to_dict() for d in @@ -225,6 +231,7 @@ class DashboardAPI(BaseResource): dashboard.save() api.add_resource(DashboardListAPI, '/api/dashboards', endpoint='dashboards') +api.add_resource(DashboardRecentAPI, '/api/dashboards/recent', endpoint='recent_dashboards') api.add_resource(DashboardAPI, '/api/dashboards/', endpoint='dashboard') @@ -285,6 +292,12 @@ class QuerySearchAPI(BaseResource): return [q.to_dict() for q in models.Query.search(term)] +class QueryRecentAPI(BaseResource): + @require_permission('view_query') + def get(self): + return [q.to_dict() for q in models.Query.recent(current_user.id).limit(20)] + + class QueryListAPI(BaseResource): @require_permission('create_query') def post(self): @@ -334,6 +347,7 @@ class QueryAPI(BaseResource): abort(404, message="Query not found.") api.add_resource(QuerySearchAPI, '/api/queries/search', endpoint='queries_search') +api.add_resource(QueryRecentAPI, '/api/queries/recent', endpoint='recent_queries') api.add_resource(QueryListAPI, '/api/queries', endpoint='queries') api.add_resource(QueryAPI, '/api/queries/', endpoint='query') diff --git a/redash/models.py b/redash/models.py index d143f682..8e3ec4a2 100644 --- a/redash/models.py +++ b/redash/models.py @@ -360,6 +360,17 @@ class Query(BaseModel): return cls.select().where(where) + @classmethod + def recent(cls, user_id): + return cls.select().where(Event.created_at > peewee.SQL("current_date - 7")).\ + join(Event, on=(Query.id == peewee.SQL("t2.object_id::integer"))).\ + where(Event.action << ('edit', 'execute', 'edit_name', 'edit_description', 'view_source')).\ + where(Event.user == user_id).\ + where(~(Event.object_id >> None)).\ + where(Event.object_type == 'query').\ + group_by(Event.object_id, Query.id).\ + order_by(peewee.SQL("count(0) desc")) + @classmethod def update_instance(cls, query_id, **kwargs): if 'query' in kwargs: @@ -448,6 +459,17 @@ class Dashboard(BaseModel): def get_by_slug(cls, slug): return cls.get(cls.slug == slug) + @classmethod + def recent(cls, user_id): + return cls.select().where(Event.created_at > peewee.SQL("current_date - 7")). \ + join(Event, on=(Dashboard.id == peewee.SQL("t2.object_id::integer"))). \ + where(Event.action << ('edit', 'view')).\ + where(Event.user == user_id). \ + where(~(Event.object_id >> None)). \ + where(Event.object_type == 'dashboard'). \ + group_by(Event.object_id, Dashboard.id). \ + order_by(peewee.SQL("count(0) desc")) + def save(self, *args, **kwargs): if not self.slug: self.slug = utils.slugify(self.name)