dashboards.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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. func (d *Dashboard) SetId(id int64) {
  62. d.Id = id
  63. d.Data.Set("id", id)
  64. }
  65. // NewDashboard creates a new dashboard
  66. func NewDashboard(title string) *Dashboard {
  67. dash := &Dashboard{}
  68. dash.Data = simplejson.New()
  69. dash.Data.Set("title", title)
  70. dash.Title = title
  71. dash.Created = time.Now()
  72. dash.Updated = time.Now()
  73. dash.UpdateSlug()
  74. return dash
  75. }
  76. // NewDashboardFolder creates a new dashboard folder
  77. func NewDashboardFolder(title string) *Dashboard {
  78. folder := NewDashboard(title)
  79. folder.IsFolder = true
  80. folder.Data.Set("schemaVersion", 16)
  81. folder.Data.Set("version", 0)
  82. return folder
  83. }
  84. // GetTags turns the tags in data json into go string array
  85. func (dash *Dashboard) GetTags() []string {
  86. return dash.Data.Get("tags").MustStringArray()
  87. }
  88. func NewDashboardFromJson(data *simplejson.Json) *Dashboard {
  89. dash := &Dashboard{}
  90. dash.Data = data
  91. dash.Title = dash.Data.Get("title").MustString()
  92. dash.UpdateSlug()
  93. update := false
  94. if id, err := dash.Data.Get("id").Float64(); err == nil {
  95. dash.Id = int64(id)
  96. update = true
  97. }
  98. if uid, err := dash.Data.Get("uid").String(); err == nil {
  99. dash.Uid = uid
  100. update = true
  101. }
  102. if version, err := dash.Data.Get("version").Float64(); err == nil && update {
  103. dash.Version = int(version)
  104. dash.Updated = time.Now()
  105. } else {
  106. dash.Data.Set("version", 0)
  107. dash.Created = time.Now()
  108. dash.Updated = time.Now()
  109. }
  110. if gnetId, err := dash.Data.Get("gnetId").Float64(); err == nil {
  111. dash.GnetId = int64(gnetId)
  112. }
  113. return dash
  114. }
  115. // GetDashboardModel turns the command into the savable model
  116. func (cmd *SaveDashboardCommand) GetDashboardModel() *Dashboard {
  117. dash := NewDashboardFromJson(cmd.Dashboard)
  118. userId := cmd.UserId
  119. if userId == 0 {
  120. userId = -1
  121. }
  122. if dash.Data.Get("version").MustInt(0) == 0 {
  123. dash.CreatedBy = userId
  124. }
  125. dash.UpdatedBy = userId
  126. dash.OrgId = cmd.OrgId
  127. dash.PluginId = cmd.PluginId
  128. dash.IsFolder = cmd.IsFolder
  129. dash.FolderId = cmd.FolderId
  130. dash.UpdateSlug()
  131. return dash
  132. }
  133. // GetString a
  134. func (dash *Dashboard) GetString(prop string, defaultValue string) string {
  135. return dash.Data.Get(prop).MustString(defaultValue)
  136. }
  137. // UpdateSlug updates the slug
  138. func (dash *Dashboard) UpdateSlug() {
  139. title := dash.Data.Get("title").MustString()
  140. dash.Slug = SlugifyTitle(title)
  141. }
  142. func SlugifyTitle(title string) string {
  143. return slug.Make(strings.ToLower(title))
  144. }
  145. // GetUrl return the html url for a folder if it's folder, otherwise for a dashboard
  146. func (dash *Dashboard) GetUrl() string {
  147. return GetDashboardFolderUrl(dash.IsFolder, dash.Uid, dash.Slug)
  148. }
  149. // Return the html url for a dashboard
  150. func (dash *Dashboard) GenerateUrl() string {
  151. return GetDashboardUrl(dash.Uid, dash.Slug)
  152. }
  153. // GetDashboardFolderUrl return the html url for a folder if it's folder, otherwise for a dashboard
  154. func GetDashboardFolderUrl(isFolder bool, uid string, slug string) string {
  155. if isFolder {
  156. return GetFolderUrl(uid, slug)
  157. }
  158. return GetDashboardUrl(uid, slug)
  159. }
  160. // Return the html url for a dashboard
  161. func GetDashboardUrl(uid string, slug string) string {
  162. return fmt.Sprintf("%s/d/%s/%s", setting.AppSubUrl, uid, slug)
  163. }
  164. // Return the full url for a dashboard
  165. func GetFullDashboardUrl(uid string, slug string) string {
  166. return fmt.Sprintf("%s%s", setting.AppUrl, GetDashboardUrl(uid, slug))
  167. }
  168. // GetFolderUrl return the html url for a folder
  169. func GetFolderUrl(folderUid string, slug string) string {
  170. return fmt.Sprintf("%s/dashboards/f/%s/%s", setting.AppSubUrl, folderUid, slug)
  171. }
  172. //
  173. // COMMANDS
  174. //
  175. type SaveDashboardCommand struct {
  176. Dashboard *simplejson.Json `json:"dashboard" binding:"Required"`
  177. UserId int64 `json:"userId"`
  178. Overwrite bool `json:"overwrite"`
  179. Message string `json:"message"`
  180. OrgId int64 `json:"-"`
  181. RestoredFrom int `json:"-"`
  182. PluginId string `json:"-"`
  183. FolderId int64 `json:"folderId"`
  184. IsFolder bool `json:"isFolder"`
  185. UpdatedAt time.Time
  186. Result *Dashboard
  187. }
  188. type DashboardProvisioning struct {
  189. Id int64
  190. DashboardId int64
  191. Name string
  192. ExternalId string
  193. Updated time.Time
  194. }
  195. type SaveProvisionedDashboardCommand struct {
  196. DashboardCmd *SaveDashboardCommand
  197. DashboardProvisioning *DashboardProvisioning
  198. Result *Dashboard
  199. }
  200. type DeleteDashboardCommand struct {
  201. Id int64
  202. OrgId int64
  203. }
  204. //
  205. // QUERIES
  206. //
  207. type GetDashboardQuery struct {
  208. Slug string // required if no Id or Uid is specified
  209. Id int64 // optional if slug is set
  210. Uid string // optional if slug is set
  211. OrgId int64
  212. Result *Dashboard
  213. }
  214. type DashboardTagCloudItem struct {
  215. Term string `json:"term"`
  216. Count int `json:"count"`
  217. }
  218. type GetDashboardTagsQuery struct {
  219. OrgId int64
  220. Result []*DashboardTagCloudItem
  221. }
  222. type GetDashboardsQuery struct {
  223. DashboardIds []int64
  224. Result []*Dashboard
  225. }
  226. type GetDashboardPermissionsForUserQuery struct {
  227. DashboardIds []int64
  228. OrgId int64
  229. UserId int64
  230. OrgRole RoleType
  231. Result []*DashboardPermissionForUser
  232. }
  233. type GetDashboardsByPluginIdQuery struct {
  234. OrgId int64
  235. PluginId string
  236. Result []*Dashboard
  237. }
  238. type GetDashboardSlugByIdQuery struct {
  239. Id int64
  240. Result string
  241. }
  242. type GetProvisionedDashboardDataQuery struct {
  243. Name string
  244. Result []*DashboardProvisioning
  245. }
  246. type GetDashboardsBySlugQuery struct {
  247. OrgId int64
  248. Slug string
  249. Result []*Dashboard
  250. }
  251. type DashboardPermissionForUser struct {
  252. DashboardId int64 `json:"dashboardId"`
  253. Permission PermissionType `json:"permission"`
  254. PermissionName string `json:"permissionName"`
  255. }
  256. type DashboardRef struct {
  257. Uid string
  258. Slug string
  259. }
  260. type GetDashboardRefByIdQuery struct {
  261. Id int64
  262. Result *DashboardRef
  263. }