dashboards.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. package models
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/gosimple/slug"
  8. "github.com/grafana/grafana/pkg/components/simplejson"
  9. "github.com/grafana/grafana/pkg/setting"
  10. )
  11. // Typed errors
  12. var (
  13. ErrDashboardNotFound = errors.New("Dashboard not found")
  14. ErrDashboardSnapshotNotFound = errors.New("Dashboard snapshot not found")
  15. ErrDashboardWithSameUIDExists = errors.New("A dashboard with the same uid already exists")
  16. ErrDashboardWithSameNameInFolderExists = errors.New("A dashboard with the same name in the folder already exists")
  17. ErrDashboardVersionMismatch = errors.New("The dashboard has been changed by someone else")
  18. ErrDashboardTitleEmpty = errors.New("Dashboard title cannot be empty")
  19. ErrDashboardFolderCannotHaveParent = errors.New("A Dashboard Folder cannot be added to another folder")
  20. ErrDashboardContainsInvalidAlertData = errors.New("Invalid alert data. Cannot save dashboard")
  21. ErrDashboardFailedToUpdateAlertData = errors.New("Failed to save alert data")
  22. ErrDashboardsWithSameSlugExists = errors.New("Multiple dashboards with the same slug exists")
  23. ErrDashboardFailedGenerateUniqueUid = errors.New("Failed to generate unique dashboard id")
  24. ErrDashboardExistingCannotChangeToDashboard = errors.New("An existing folder cannot be changed to a dashboard")
  25. ErrDashboardTypeMismatch = errors.New("Dashboard cannot be changed to a folder")
  26. ErrDashboardFolderWithSameNameAsDashboard = errors.New("Folder name cannot be the same as one of its dashboards")
  27. ErrDashboardWithSameNameAsFolder = errors.New("Dashboard name cannot be the same as folder")
  28. RootFolderName = "General"
  29. )
  30. type UpdatePluginDashboardError struct {
  31. PluginId string
  32. }
  33. func (d UpdatePluginDashboardError) Error() string {
  34. return "Dashboard belong to plugin"
  35. }
  36. var (
  37. DashTypeJson = "file"
  38. DashTypeDB = "db"
  39. DashTypeScript = "script"
  40. DashTypeSnapshot = "snapshot"
  41. )
  42. // Dashboard model
  43. type Dashboard struct {
  44. Id int64
  45. Uid string
  46. Slug string
  47. OrgId int64
  48. GnetId int64
  49. Version int
  50. PluginId string
  51. Created time.Time
  52. Updated time.Time
  53. UpdatedBy int64
  54. CreatedBy int64
  55. FolderId int64
  56. IsFolder bool
  57. HasAcl bool
  58. Title string
  59. Data *simplejson.Json
  60. }
  61. // NewDashboard creates a new dashboard
  62. func NewDashboard(title string) *Dashboard {
  63. dash := &Dashboard{}
  64. dash.Data = simplejson.New()
  65. dash.Data.Set("title", title)
  66. dash.Title = title
  67. dash.Created = time.Now()
  68. dash.Updated = time.Now()
  69. dash.UpdateSlug()
  70. return dash
  71. }
  72. // NewDashboardFolder creates a new dashboard folder
  73. func NewDashboardFolder(title string) *Dashboard {
  74. folder := NewDashboard(title)
  75. folder.Data.Set("schemaVersion", 16)
  76. folder.Data.Set("editable", true)
  77. folder.Data.Set("hideControls", true)
  78. return folder
  79. }
  80. // GetTags turns the tags in data json into go string array
  81. func (dash *Dashboard) GetTags() []string {
  82. return dash.Data.Get("tags").MustStringArray()
  83. }
  84. func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
  85. dash := &Dashboard{}
  86. dash.Data = data
  87. dash.Title = dash.Data.Get("title").MustString()
  88. dash.UpdateSlug()
  89. update := false
  90. if id, err := dash.Data.Get("id").Float64(); err == nil {
  91. dash.Id = int64(id)
  92. update = true
  93. }
  94. if uid, err := dash.Data.Get("uid").String(); err == nil {
  95. dash.Uid = uid
  96. update = true
  97. }
  98. if version, err := dash.Data.Get("version").Float64(); err == nil && update {
  99. dash.Version = int(version)
  100. dash.Updated = time.Now()
  101. } else {
  102. dash.Data.Set("version", 0)
  103. dash.Created = time.Now()
  104. dash.Updated = time.Now()
  105. }
  106. if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
  107. dash.GnetId = int64(gnetId)
  108. }
  109. return dash
  110. }
  111. // GetDashboardModel turns the command into the savable model
  112. func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
  113. dash := NewDashboardFromJson(cmd.Dashboard)
  114. userId := cmd.UserId
  115. if userId == 0 {
  116. userId = -1
  117. }
  118. if dash.Data.Get("version").MustInt(0) == 0 {
  119. dash.CreatedBy = userId
  120. }
  121. dash.UpdatedBy = userId
  122. dash.OrgId = cmd.OrgId
  123. dash.PluginId = cmd.PluginId
  124. dash.IsFolder = cmd.IsFolder
  125. dash.FolderId = cmd.FolderId
  126. dash.UpdateSlug()
  127. return dash
  128. }
  129. // GetString a
  130. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  131. return dash.Data.Get(prop).MustString(defaultValue)
  132. }
  133. // UpdateSlug updates the slug
  134. func (dash *Dashboard) UpdateSlug() {
  135. title := dash.Data.Get("title").MustString()
  136. dash.Slug = SlugifyTitle(title)
  137. }
  138. func SlugifyTitle(title string) string {
  139. return slug.Make(strings.ToLower(title))
  140. }
  141. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  142. func (dash *Dashboard) GetUrl() string {
  143. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  144. }
  145. // Return the html url for a dashboard
  146. func (dash *Dashboard) GenerateUrl() string {
  147. return GetDashboardUrl(dash.Uid, dash.Slug)
  148. }
  149. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  150. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  151. if isFolder {
  152. return GetFolderUrl(uid, slug)
  153. }
  154. return GetDashboardUrl(uid, slug)
  155. }
  156. // Return the html url for a dashboard
  157. func GetDashboardUrl(uid string, slug string) string {
  158. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  159. }
  160. // Return the full url for a dashboard
  161. func GetFullDashboardUrl(uid string, slug string) string {
  162. return fmt.Sprintf("%s%s", setting.AppUrl, GetDashboardUrl(uid, slug))
  163. }
  164. // GetFolderUrl return the html url for a folder
  165. func GetFolderUrl(folderUid string, slug string) string {
  166. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  167. }
  168. //
  169. // COMMANDS
  170. //
  171. type SaveDashboardCommand struct {
  172. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  173. UserId int64 `json:"userId"`
  174. Overwrite bool `json:"overwrite"`
  175. Message string `json:"message"`
  176. OrgId int64 `json:"-"`
  177. RestoredFrom int `json:"-"`
  178. PluginId string `json:"-"`
  179. FolderId int64 `json:"folderId"`
  180. IsFolder bool `json:"isFolder"`
  181. UpdatedAt time.Time
  182. Result *Dashboard
  183. }
  184. type DeleteDashboardCommand struct {
  185. Id int64
  186. OrgId int64
  187. }
  188. //
  189. // QUERIES
  190. //
  191. type GetDashboardQuery struct {
  192. Slug string // required if no Id or Uid is specified
  193. Id int64 // optional if slug is set
  194. Uid string // optional if slug is set
  195. OrgId int64
  196. Result *Dashboard
  197. }
  198. type DashboardTagCloudItem struct {
  199. Term string `json:"term"`
  200. Count int `json:"count"`
  201. }
  202. type GetDashboardTagsQuery struct {
  203. OrgId int64
  204. Result []*DashboardTagCloudItem
  205. }
  206. type GetDashboardsQuery struct {
  207. DashboardIds []int64
  208. Result []*Dashboard
  209. }
  210. type GetDashboardPermissionsForUserQuery struct {
  211. DashboardIds []int64
  212. OrgId int64
  213. UserId int64
  214. OrgRole RoleType
  215. Result []*DashboardPermissionForUser
  216. }
  217. type GetDashboardsByPluginIdQuery struct {
  218. OrgId int64
  219. PluginId string
  220. Result []*Dashboard
  221. }
  222. type GetDashboardSlugByIdQuery struct {
  223. Id int64
  224. Result string
  225. }
  226. type GetDashboardsBySlugQuery struct {
  227. OrgId int64
  228. Slug string
  229. Result []*Dashboard
  230. }
  231. type GetFoldersForSignedInUserQuery struct {
  232. OrgId int64
  233. SignedInUser *SignedInUser
  234. Title string
  235. Result []*DashboardFolder
  236. }
  237. type DashboardFolder struct {
  238. Id int64 `json:"id"`
  239. Title string `json:"title"`
  240. }
  241. type DashboardPermissionForUser struct {
  242. DashboardId int64 `json:"dashboardId"`
  243. Permission PermissionType `json:"permission"`
  244. PermissionName string `json:"permissionName"`
  245. }
  246. type DashboardRef struct {
  247. Uid string
  248. Slug string
  249. }
  250. type GetDashboardRefByIdQuery struct {
  251. Id int64
  252. Result *DashboardRef
  253. }