From bcaaedf2ff85d4d43d486a1a33a31abacfb28547 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Tue, 22 Dec 2015 02:07:15 -0800 Subject: [PATCH 1/6] Resurrected nikita-graf's work and added playlistType for future use --- pkg/api/api.go | 13 ++ pkg/api/index.go | 6 + pkg/api/playlist.go | 103 +++++++++++++++ pkg/models/playlist.go | 79 +++++++++++ .../sqlstore/migrations/migrations.go | 1 + .../sqlstore/migrations/playlist_mig.go | 20 +++ pkg/services/sqlstore/playlist.go | 125 ++++++++++++++++++ public/app/features/all.js | 1 + public/app/features/playlist/all.js | 5 + .../playlist/partials/playlist-remove.html | 5 + .../features/playlist/partials/playlist.html | 115 ++++++++++++++++ .../features/playlist/partials/playlists.html | 43 ++++++ .../app/features/playlist/playlistEditCtrl.js | 111 ++++++++++++++++ .../app/features/playlist/playlistRoutes.js | 73 ++++++++++ public/app/features/playlist/playlistsCtrl.js | 49 +++++++ 15 files changed, 749 insertions(+) create mode 100644 pkg/api/playlist.go create mode 100644 pkg/models/playlist.go create mode 100644 pkg/services/sqlstore/migrations/playlist_mig.go create mode 100644 pkg/services/sqlstore/playlist.go create mode 100644 public/app/features/playlist/all.js create mode 100644 public/app/features/playlist/partials/playlist-remove.html create mode 100644 public/app/features/playlist/partials/playlist.html create mode 100644 public/app/features/playlist/partials/playlists.html create mode 100644 public/app/features/playlist/playlistEditCtrl.js create mode 100644 public/app/features/playlist/playlistRoutes.js create mode 100644 public/app/features/playlist/playlistsCtrl.js diff --git a/pkg/api/api.go b/pkg/api/api.go index 839978845ab..1e1348a51ab 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -47,6 +47,9 @@ func Register(r *macaron.Macaron) { r.Get("/dashboard/*", reqSignedIn, Index) r.Get("/dashboard-solo/*", reqSignedIn, Index) + r.Get("/playlists/", reqSignedIn, Index) + r.Get("/playlists/*", reqSignedIn, Index) + // sign up r.Get("/signup", Index) r.Get("/api/user/signup/options", wrap(GetSignUpOptions)) @@ -169,6 +172,16 @@ func Register(r *macaron.Macaron) { r.Get("/tags", GetDashboardTags) }) + // Playlist + r.Group("/playlists", func() { + r.Get("/", SearchPlaylists) + r.Get("/:id", ValidateOrgPlaylist, GetPlaylist) + r.Get("/:id/dashboards", ValidateOrgPlaylist, GetPlaylistDashboards) + r.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, DeletePlaylist) + r.Put("/:id", reqEditorRole, bind(m.UpdatePlaylistQuery{}), ValidateOrgPlaylist, UpdatePlaylist) + r.Post("/", reqEditorRole, bind(m.CreatePlaylistQuery{}), CreatePlaylist) + }) + // Search r.Get("/search/", Search) diff --git a/pkg/api/index.go b/pkg/api/index.go index 9a39837261f..ff5a923ebba 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -53,6 +53,12 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { Href: "/", }) + data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ + Text: "Playlists", + Icon: "fa fa-fw fa-list", + Href: "/playlists", + }) + if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", diff --git a/pkg/api/playlist.go b/pkg/api/playlist.go new file mode 100644 index 00000000000..83355418b4b --- /dev/null +++ b/pkg/api/playlist.go @@ -0,0 +1,103 @@ +package api + +import ( + "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/middleware" + m "github.com/grafana/grafana/pkg/models" +) + +func ValidateOrgPlaylist(c *middleware.Context) { + id := c.ParamsInt64(":id") + query := m.GetPlaylistByIdQuery{Id: id} + err := bus.Dispatch(&query) + + if err != nil { + c.JsonApiErr(404, "Playlist not found", err) + return + } + + if query.Result.OrgId != c.OrgId { + c.JsonApiErr(403, "You are not allowed to edit/view playlist", nil) + return + } +} + +func SearchPlaylists(c *middleware.Context) { + query := c.Query("query") + limit := c.QueryInt("limit") + + if limit == 0 { + limit = 1000 + } + + searchQuery := m.PlaylistQuery{ + Title: query, + Limit: limit, + OrgId: c.OrgId, + } + + err := bus.Dispatch(&searchQuery) + if err != nil { + c.JsonApiErr(500, "Search failed", err) + return + } + + c.JSON(200, searchQuery.Result) +} + +func GetPlaylist(c *middleware.Context) { + id := c.ParamsInt64(":id") + cmd := m.GetPlaylistByIdQuery{Id: id} + + if err := bus.Dispatch(&cmd); err != nil { + c.JsonApiErr(500, "Playlist not found", err) + return + } + + c.JSON(200, cmd.Result) +} + +func GetPlaylistDashboards(c *middleware.Context) { + id := c.ParamsInt64(":id") + + query := m.GetPlaylistDashboardsQuery{Id: id} + if err := bus.Dispatch(&query); err != nil { + c.JsonApiErr(500, "Playlist not found", err) + return + } + + c.JSON(200, query.Result) +} + +func DeletePlaylist(c *middleware.Context) { + id := c.ParamsInt64(":id") + + cmd := m.DeletePlaylistQuery{Id: id} + if err := bus.Dispatch(&cmd); err != nil { + c.JsonApiErr(500, "Failed to delete playlist", err) + return + } + + c.JSON(200, "") +} + +func CreatePlaylist(c *middleware.Context, query m.CreatePlaylistQuery) { + query.OrgId = c.OrgId + err := bus.Dispatch(&query) + if err != nil { + c.JsonApiErr(500, "Failed to create playlist", err) + return + } + + c.JSON(200, query.Result) +} + +func UpdatePlaylist(c *middleware.Context, query m.UpdatePlaylistQuery) { + err := bus.Dispatch(&query) + if err != nil { + c.JsonApiErr(500, "Failed to save playlist", err) + return + } + + c.JSON(200, query.Result) +} diff --git a/pkg/models/playlist.go b/pkg/models/playlist.go new file mode 100644 index 00000000000..1bfa5949fe2 --- /dev/null +++ b/pkg/models/playlist.go @@ -0,0 +1,79 @@ +package models + +import ( + "errors" +) + +// Typed errors +var ( + ErrPlaylistNotFound = errors.New("Playlist not found") + ErrPlaylistWithSameNameExists = errors.New("A playlist with the same name already exists") +) + +// Playlist model +type Playlist struct { + Id int64 `json:"id"` + Title string `json:"title"` + Type string `json:"type"` + Timespan string `json:"timespan"` + Data []int `json:"data"` + OrgId int64 `json:"-"` +} + +type PlaylistDashboard struct { + Id int64 `json:"id"` + Slug string `json:"slug"` + Title string `json:"title"` +} + +func (this PlaylistDashboard) TableName() string { + return "dashboard" +} + +type Playlists []*Playlist +type PlaylistDashboards []*PlaylistDashboard + +// +// COMMANDS +// +type PlaylistQuery struct { + Title string + Limit int + OrgId int64 + + Result Playlists +} + +type UpdatePlaylistQuery struct { + Id int64 + Title string + Type string + Timespan string + Data []int + + Result *Playlist +} + +type CreatePlaylistQuery struct { + Title string + Type string + Timespan string + Data []int + OrgId int64 + + Result *Playlist +} + +type GetPlaylistByIdQuery struct { + Id int64 + Result *Playlist +} + +type GetPlaylistDashboardsQuery struct { + Id int64 + Result *PlaylistDashboards +} + +type DeletePlaylistQuery struct { + Id int64 +} diff --git a/pkg/services/sqlstore/migrations/migrations.go b/pkg/services/sqlstore/migrations/migrations.go index 569d26282ed..0faddb144c9 100644 --- a/pkg/services/sqlstore/migrations/migrations.go +++ b/pkg/services/sqlstore/migrations/migrations.go @@ -19,6 +19,7 @@ func AddMigrations(mg *Migrator) { addDashboardSnapshotMigrations(mg) addQuotaMigration(mg) addPluginBundleMigration(mg) + addPlaylistMigrations(mg) } func addMigrationLogMigrations(mg *Migrator) { diff --git a/pkg/services/sqlstore/migrations/playlist_mig.go b/pkg/services/sqlstore/migrations/playlist_mig.go new file mode 100644 index 00000000000..d8625f301ae --- /dev/null +++ b/pkg/services/sqlstore/migrations/playlist_mig.go @@ -0,0 +1,20 @@ +package migrations + +import . "github.com/grafana/grafana/pkg/services/sqlstore/migrator" + +func addPlaylistMigrations(mg *Migrator) { + playlistV1 := Table{ + Name: "playlist", + Columns: []*Column{ + {Name: "id", Type: DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true}, + {Name: "title", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "type", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "data", Type: DB_Text, Nullable: false}, + {Name: "timespan", Type: DB_NVarchar, Length: 255, Nullable: false}, + {Name: "org_id", Type: DB_BigInt, Nullable: false}, + }, + } + + // create table + mg.AddMigration("create playlist table v1", NewAddTableMigration(playlistV1)) +} diff --git a/pkg/services/sqlstore/playlist.go b/pkg/services/sqlstore/playlist.go new file mode 100644 index 00000000000..3e04f65f9d4 --- /dev/null +++ b/pkg/services/sqlstore/playlist.go @@ -0,0 +1,125 @@ +package sqlstore + +import ( + "github.com/go-xorm/xorm" + + "github.com/grafana/grafana/pkg/bus" + m "github.com/grafana/grafana/pkg/models" +) + +func init() { + bus.AddHandler("sql", CreatePlaylist) + bus.AddHandler("sql", UpdatePlaylist) + bus.AddHandler("sql", DeletePlaylist) + bus.AddHandler("sql", SearchPlaylists) + bus.AddHandler("sql", GetPlaylist) + bus.AddHandler("sql", GetPlaylistDashboards) +} + +func CreatePlaylist(query *m.CreatePlaylistQuery) error { + var err error + + playlist := m.Playlist{ + Title: query.Title, + Type: query.Type, + Data: query.Data, + Timespan: query.Timespan, + OrgId: query.OrgId, + } + + _, err = x.Insert(&playlist) + + query.Result = &playlist + return err +} + +func UpdatePlaylist(query *m.UpdatePlaylistQuery) error { + var err error + x.Logger.SetLevel(5) + playlist := m.Playlist{ + Id: query.Id, + Title: query.Title, + Type: query.Type, + Data: query.Data, + Timespan: query.Timespan, + } + + existingPlaylist := x.Where("id = ?", query.Id).Find(m.Playlist{}) + + if existingPlaylist == nil { + return m.ErrPlaylistNotFound + } + + _, err = x.Id(query.Id).Cols("id", "title", "data", "timespan").Update(&playlist) + + query.Result = &playlist + return err +} + +func GetPlaylist(query *m.GetPlaylistByIdQuery) error { + if query.Id == 0 { + return m.ErrCommandValidationFailed + } + + playlist := m.Playlist{} + _, err := x.Id(query.Id).Get(&playlist) + query.Result = &playlist + + return err +} + +func DeletePlaylist(query *m.DeletePlaylistQuery) error { + if query.Id == 0 { + return m.ErrCommandValidationFailed + } + + return inTransaction(func(sess *xorm.Session) error { + var rawSql = "DELETE FROM playlist WHERE id = ?" + _, err := sess.Exec(rawSql, query.Id) + return err + }) +} + +func SearchPlaylists(query *m.PlaylistQuery) error { + var playlists = make(m.Playlists, 0) + + sess := x.Limit(query.Limit) + + if query.Title != "" { + sess.Where("title LIKE ?", query.Title) + } + + sess.Where("org_id = ?", query.OrgId) + err := sess.Find(&playlists) + query.Result = playlists + + return err +} + +func GetPlaylistDashboards(query *m.GetPlaylistDashboardsQuery) error { + if query.Id == 0 { + return m.ErrCommandValidationFailed + } + + var dashboards = make(m.PlaylistDashboards, 0) + var playlist = m.Playlist{} + + hasPlaylist, err := x.Id(query.Id).Get(&playlist) + query.Result = &dashboards + + if err != nil { + return err + } + + if !hasPlaylist || len(playlist.Data) == 0 { + return nil + } + + err = x.In("id", playlist.Data).Find(&dashboards) + + if err != nil { + return err + } + + return nil +} diff --git a/public/app/features/all.js b/public/app/features/all.js index 6519d112b74..9019ec06172 100644 --- a/public/app/features/all.js +++ b/public/app/features/all.js @@ -4,6 +4,7 @@ define([ './annotations/annotationsSrv', './templating/templateSrv', './dashboard/all', + './playlist/all', './panel/all', './profile/profileCtrl', './profile/changePasswordCtrl', diff --git a/public/app/features/playlist/all.js b/public/app/features/playlist/all.js new file mode 100644 index 00000000000..85831247eb7 --- /dev/null +++ b/public/app/features/playlist/all.js @@ -0,0 +1,5 @@ +define([ + './playlistsCtrl', + './playlistEditCtrl', + './playlistRoutes' +], function () {}); diff --git a/public/app/features/playlist/partials/playlist-remove.html b/public/app/features/playlist/partials/playlist-remove.html new file mode 100644 index 00000000000..d40b8b9ca42 --- /dev/null +++ b/public/app/features/playlist/partials/playlist-remove.html @@ -0,0 +1,5 @@ +

Are you sure want to delete "{{ playlist.title }}" playlist?

+

+ + +

diff --git a/public/app/features/playlist/partials/playlist.html b/public/app/features/playlist/partials/playlist.html new file mode 100644 index 00000000000..5b81649f636 --- /dev/null +++ b/public/app/features/playlist/partials/playlist.html @@ -0,0 +1,115 @@ + + +
+
+
+
+
+
    +
  • + Title +
  • +
  • + +
  • +
+
+
+
+
    +
  • + Timespan +
  • +
  • + +
  • +
+
+
+
+ +
+ +
+
+
    +
  • + Search +
  • +
  • + +
  • +
+
+
+
+
+
+
Playlist dashboards
+
+
+ +
+
+ + + + + + + + + + + +
+ {{dashboard.title}} + + +
+ No dashboards found +
+ Playlist empty +
+
+
+ + + + + +
+ {{dashboard.title}} + + +
+
+
+ +
+
+ +
+
+ + +
+
+ +
+
diff --git a/public/app/features/playlist/partials/playlists.html b/public/app/features/playlist/partials/playlists.html new file mode 100644 index 00000000000..d1ce323dcd2 --- /dev/null +++ b/public/app/features/playlist/partials/playlists.html @@ -0,0 +1,43 @@ + + +
+
+ + +
+
+ +
+ No saved playlists +
+ + + + + + + + + + + + + + +
TitleUrl
+ {{playlist.title}} + + {{ playlistUrl(playlist) }} + + + + Edit + + + + + +
+ +
+
diff --git a/public/app/features/playlist/playlistEditCtrl.js b/public/app/features/playlist/playlistEditCtrl.js new file mode 100644 index 00000000000..205086faff6 --- /dev/null +++ b/public/app/features/playlist/playlistEditCtrl.js @@ -0,0 +1,111 @@ +define([ + 'angular', + 'app/core/config', + 'lodash' +], +function (angular, config, _) { + 'use strict'; + + var module = angular.module('grafana.controllers'); + + module.controller('PlaylistEditCtrl', function( + playlist, + dashboards, + $scope, + playlistSrv, + backendSrv, + $location + ) { + $scope.search = function() { + var query = {starred: true, limit: 10}; + + if ($scope.searchQuery) { + query.query = $scope.searchQuery; + query.starred = false; + } + + $scope.loading = true; + + backendSrv.search(query) + .then(function(results) { + $scope.foundDashboards = results; + $scope.filterFoundDashboards(); + }) + .finally(function() { + $scope.loading = false; + }); + }; + + $scope.filterFoundDashboards = function() { + $scope.filteredDashboards = _.reject($scope.foundDashboards, function(dashboard) { + return _.findWhere(dashboards, function(listDashboard) { + return listDashboard.id === dashboard.id; + }); + }); + }; + + $scope.addDashboard = function(dashboard) { + dashboards.push(dashboard); + $scope.filterFoundDashboards(); + }; + + $scope.removeDashboard = function(dashboard) { + _.remove(dashboards, function(listedDashboard) { + return dashboard === listedDashboard; + }); + $scope.filterFoundDashboards(); + }; + + $scope.savePlaylist = function(playlist, dashboards) { + var savePromise; + + playlist.data = dashboards.map(function(dashboard) { + return dashboard.id; + }); + + // Hardcoding playlist type for this iteration + playlist.type = "dashboards"; + + savePromise = playlist.id + ? backendSrv.put('/api/playlists/' + playlist.id, playlist) + : backendSrv.post('/api/playlists', playlist); + + savePromise + .then(function() { + $scope.appEvent('alert-success', ['Playlist saved', '']); + $location.path('/playlists'); + }, function() { + $scope.appEvent('alert-success', ['Unable to save playlist', '']); + }); + }; + + $scope.isPlaylistEmpty = function() { + return !dashboards.length; + }; + + $scope.isSearchResultsEmpty = function() { + return !$scope.foundDashboards.length; + }; + + $scope.isSearchQueryEmpty = function() { + return $scope.searchQuery === ''; + }; + + $scope.backToList = function() { + $location.path('/playlists'); + }; + + $scope.isLoading = function() { + return $scope.loading; + }; + + $scope.playlist = playlist; + $scope.dashboards = dashboards; + $scope.timespan = config.playlist_timespan; + $scope.filteredDashboards = []; + $scope.foundDashboards = []; + $scope.searchQuery = ''; + $scope.loading = false; + $scope.search(); + }); +}); diff --git a/public/app/features/playlist/playlistRoutes.js b/public/app/features/playlist/playlistRoutes.js new file mode 100644 index 00000000000..2c2515200ae --- /dev/null +++ b/public/app/features/playlist/playlistRoutes.js @@ -0,0 +1,73 @@ +define([ + 'angular', + 'app/core/config', + 'lodash' +], +function (angular, config, _) { + 'use strict'; + + var module = angular.module('grafana.routes'); + + module.config(function($routeProvider) { + $routeProvider + .when('/playlists', { + templateUrl: 'app/features/playlist/partials/playlists.html', + controller : 'PlaylistsCtrl', + resolve: { + playlists: function (backendSrv) { + return backendSrv.get('/api/playlists'); + } + } + }) + .when('/playlists/create', { + templateUrl: 'app/features/playlist/partials/playlist.html', + controller : 'PlaylistEditCtrl', + resolve: { + playlist: function() { + return { + timespan: '1m' + }; + }, + dashboards: function() { + return []; + } + } + }) + .when('/playlists/edit/:id', { + templateUrl: 'app/features/playlist/partials/playlist.html', + controller : 'PlaylistEditCtrl', + resolve: { + playlist: function(backendSrv, $route) { + var playlistId = $route.current.params.id; + + return backendSrv.get('/api/playlists/' + playlistId); + }, + dashboards: function(backendSrv, $route) { + var playlistId = $route.current.params.id; + + return backendSrv.get('/api/playlists/' + playlistId + '/dashboards'); + } + } + }) + .when('/playlists/play/:id', { + templateUrl: 'app/partials/dashboard.html', + controller : 'LoadDashboardCtrl', + resolve: { + init: function(backendSrv, playlistSrv, $route) { + var playlistId = $route.current.params.id; + + return backendSrv.get('/api/playlists/' + playlistId) + .then(function(playlist) { + return backendSrv.get('/api/playlists/' + playlistId + '/dashboards') + .then(function(dashboards) { + _.each(dashboards, function(dashboard) { + dashboard.uri = 'db/' + dashboard.slug; + }); + playlistSrv.start(dashboards, playlist.timespan); + }); + }); + } + } + }); + }); +}); diff --git a/public/app/features/playlist/playlistsCtrl.js b/public/app/features/playlist/playlistsCtrl.js new file mode 100644 index 00000000000..57e11bffe21 --- /dev/null +++ b/public/app/features/playlist/playlistsCtrl.js @@ -0,0 +1,49 @@ +define([ + 'angular', + 'lodash' +], +function (angular, _) { + 'use strict'; + + var module = angular.module('grafana.controllers'); + + module.controller('PlaylistsCtrl', function( + playlists, + $scope, + $location, + backendSrv + ) { + $scope.playlists = playlists; + + $scope.playlistUrl = function(playlist) { + return '/playlists/play/' + playlist.id; + }; + + $scope.removePlaylist = function(playlist) { + var modalScope = $scope.$new(true); + + modalScope.playlist = playlist; + modalScope.removePlaylist = function() { + modalScope.dismiss(); + _.remove(playlists, {id: playlist.id}); + + backendSrv.delete('/api/playlists/' + playlist.id) + .then(function() { + $scope.appEvent('alert-success', ['Playlist deleted', '']); + }, function() { + $scope.appEvent('alert-error', ['Unable to delete playlist', '']); + playlists.push(playlist); + }); + }; + + $scope.appEvent('show-modal', { + src: './app/features/playlist/partials/playlist-remove.html', + scope: modalScope + }); + }; + + $scope.createPlaylist = function() { + $location.path('/playlists/create'); + }; + }); +}); From 77768038905b9b392d732aace69d93af3563aa32 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 23 Dec 2015 01:46:23 -0800 Subject: [PATCH 2/6] Removed unused components --- public/app/features/dashboard/all.js | 1 - public/app/features/dashboard/playlistCtrl.js | 55 ---------- public/app/partials/playlist.html | 100 ------------------ public/app/partials/search.html | 4 - 4 files changed, 160 deletions(-) delete mode 100644 public/app/features/dashboard/playlistCtrl.js delete mode 100644 public/app/partials/playlist.html diff --git a/public/app/features/dashboard/all.js b/public/app/features/dashboard/all.js index 0ee3a64a806..524441b7a99 100644 --- a/public/app/features/dashboard/all.js +++ b/public/app/features/dashboard/all.js @@ -4,7 +4,6 @@ define([ './dashboardNavCtrl', './snapshotTopNavCtrl', './saveDashboardAsCtrl', - './playlistCtrl', './rowCtrl', './shareModalCtrl', './shareSnapshotCtrl', diff --git a/public/app/features/dashboard/playlistCtrl.js b/public/app/features/dashboard/playlistCtrl.js deleted file mode 100644 index 9242905405a..00000000000 --- a/public/app/features/dashboard/playlistCtrl.js +++ /dev/null @@ -1,55 +0,0 @@ -define([ - 'angular', - 'lodash', - 'app/core/config' -], -function (angular, _, config) { - 'use strict'; - - var module = angular.module('grafana.controllers'); - - module.controller('PlaylistCtrl', function($scope, playlistSrv, backendSrv) { - - $scope.init = function() { - $scope.playlist = []; - $scope.timespan = config.playlist_timespan; - $scope.search(); - }; - - $scope.search = function() { - var query = {starred: true, limit: 10}; - - if ($scope.searchQuery) { - query.query = $scope.searchQuery; - query.starred = false; - } - - backendSrv.search(query).then(function(results) { - $scope.searchHits = results; - $scope.filterHits(); - }); - }; - - $scope.filterHits = function() { - $scope.filteredHits = _.reject($scope.searchHits, function(dash) { - return _.findWhere($scope.playlist, {uri: dash.uri}); - }); - }; - - $scope.addDashboard = function(dashboard) { - $scope.playlist.push(dashboard); - $scope.filterHits(); - }; - - $scope.removeDashboard = function(dashboard) { - $scope.playlist = _.without($scope.playlist, dashboard); - $scope.filterHits(); - }; - - $scope.start = function() { - playlistSrv.start($scope.playlist, $scope.timespan); - }; - - }); - -}); diff --git a/public/app/partials/playlist.html b/public/app/partials/playlist.html deleted file mode 100644 index 3d12e5af2d6..00000000000 --- a/public/app/partials/playlist.html +++ /dev/null @@ -1,100 +0,0 @@ -
-
-
- - Start dashboard playlist -
- - - -
- -
-
-
-
-
-
    -
  • - Search -
  • -
  • - -
  • -
-
-
-
-
-
- -
-
-
Search result
- - - - - - - - -
- {{dashboard.title}} - - -
- No dashboards found -
-
-
-
Playlist dashboards
- - - - - - - - - -
- {{dashboard.title}} - - -
- Playlist empty -
-
-
- -
-
-
-
-
    -
  • - Timespan between dashboard change -
  • -
  • - -
  • -
  • - -
  • -
-
-
-
- -
- -
-
diff --git a/public/app/partials/search.html b/public/app/partials/search.html index 97bdbc496bf..fab8fd9291a 100644 --- a/public/app/partials/search.html +++ b/public/app/partials/search.html @@ -71,10 +71,6 @@ Import -
From b58e605b991b6b906560f9f0d49d9b397f5b1375 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 23 Dec 2015 02:02:48 -0800 Subject: [PATCH 3/6] Added play button --- .../features/playlist/partials/playlists.html | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/public/app/features/playlist/partials/playlists.html b/public/app/features/playlist/partials/playlists.html index d1ce323dcd2..ad1ad637426 100644 --- a/public/app/features/playlist/partials/playlists.html +++ b/public/app/features/playlist/partials/playlists.html @@ -11,19 +11,29 @@ No saved playlists +
+ Saved playlists +
+ +
+ - - - + +
TitleUrlUrl
{{playlist.title}} - {{ playlistUrl(playlist) }} + {{ playlistUrl(playlist) }} + + + + Play + From a292aedd9c88d479a1c1fcca6311c85504c12571 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 23 Dec 2015 02:15:28 -0800 Subject: [PATCH 4/6] Made playlist URL clickable --- public/app/features/playlist/partials/playlists.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/features/playlist/partials/playlists.html b/public/app/features/playlist/partials/playlists.html index ad1ad637426..7ebfff12e95 100644 --- a/public/app/features/playlist/partials/playlists.html +++ b/public/app/features/playlist/partials/playlists.html @@ -27,7 +27,7 @@ {{playlist.title}} - {{ playlistUrl(playlist) }} + {{ playlistUrl(playlist) }} From 71febeb71f5283849ed3cd41a28977a4abc98447 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Wed, 23 Dec 2015 02:38:27 -0800 Subject: [PATCH 5/6] Playlist can be run without saving too --- public/app/features/playlist/partials/playlist.html | 4 ++++ public/app/features/playlist/playlistEditCtrl.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/public/app/features/playlist/partials/playlist.html b/public/app/features/playlist/partials/playlist.html index 5b81649f636..46598d18c7f 100644 --- a/public/app/features/playlist/partials/playlist.html +++ b/public/app/features/playlist/partials/playlist.html @@ -101,6 +101,10 @@
+