You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

home.go 8.6 kB

11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package user
  5. import (
  6. "bytes"
  7. "fmt"
  8. "github.com/Unknwon/com"
  9. "github.com/Unknwon/paginater"
  10. "github.com/gogits/gogs/models"
  11. "github.com/gogits/gogs/modules/base"
  12. "github.com/gogits/gogs/modules/middleware"
  13. "github.com/gogits/gogs/modules/setting"
  14. )
  15. const (
  16. DASHBOARD base.TplName = "user/dashboard/dashboard"
  17. ISSUES base.TplName = "user/dashboard/issues"
  18. PROFILE base.TplName = "user/profile"
  19. ORG_HOME base.TplName = "org/home"
  20. )
  21. func getDashboardContextUser(ctx *middleware.Context) *models.User {
  22. ctxUser := ctx.User
  23. orgName := ctx.Params(":org")
  24. if len(orgName) > 0 {
  25. // Organization.
  26. org, err := models.GetUserByName(orgName)
  27. if err != nil {
  28. if models.IsErrUserNotExist(err) {
  29. ctx.Handle(404, "GetUserByName", err)
  30. } else {
  31. ctx.Handle(500, "GetUserByName", err)
  32. }
  33. return nil
  34. }
  35. ctxUser = org
  36. }
  37. ctx.Data["ContextUser"] = ctxUser
  38. if err := ctx.User.GetOrganizations(true); err != nil {
  39. ctx.Handle(500, "GetOrganizations", err)
  40. return nil
  41. }
  42. ctx.Data["Orgs"] = ctx.User.Orgs
  43. return ctxUser
  44. }
  45. func retrieveFeeds(ctx *middleware.Context, uid, offset int64, isProfile bool) {
  46. actions, err := models.GetFeeds(uid, offset, isProfile)
  47. if err != nil {
  48. ctx.Handle(500, "GetFeeds", err)
  49. return
  50. }
  51. // Check access of private repositories.
  52. feeds := make([]*models.Action, 0, len(actions))
  53. unameAvatars := make(map[string]string)
  54. for _, act := range actions {
  55. // Cache results to reduce queries.
  56. _, ok := unameAvatars[act.ActUserName]
  57. if !ok {
  58. u, err := models.GetUserByName(act.ActUserName)
  59. if err != nil {
  60. if models.IsErrUserNotExist(err) {
  61. continue
  62. }
  63. ctx.Handle(500, "GetUserByName", err)
  64. return
  65. }
  66. unameAvatars[act.ActUserName] = u.AvatarLink()
  67. }
  68. act.ActAvatar = unameAvatars[act.ActUserName]
  69. feeds = append(feeds, act)
  70. }
  71. ctx.Data["Feeds"] = feeds
  72. }
  73. func Dashboard(ctx *middleware.Context) {
  74. ctx.Data["Title"] = ctx.Tr("dashboard")
  75. ctx.Data["PageIsDashboard"] = true
  76. ctx.Data["PageIsNews"] = true
  77. ctxUser := getDashboardContextUser(ctx)
  78. if ctx.Written() {
  79. return
  80. }
  81. if !ctxUser.IsOrganization() {
  82. collaborateRepos, err := ctx.User.GetAccessibleRepositories()
  83. if err != nil {
  84. ctx.Handle(500, "GetAccessibleRepositories", err)
  85. return
  86. }
  87. for i := range collaborateRepos {
  88. if err = collaborateRepos[i].GetOwner(); err != nil {
  89. ctx.Handle(500, "GetOwner: "+collaborateRepos[i].Name, err)
  90. return
  91. }
  92. }
  93. ctx.Data["CollaborateCount"] = len(collaborateRepos)
  94. ctx.Data["CollaborativeRepos"] = collaborateRepos
  95. }
  96. repos, err := models.GetRepositories(ctxUser.Id, true)
  97. if err != nil {
  98. ctx.Handle(500, "GetRepositories", err)
  99. return
  100. }
  101. ctx.Data["Repos"] = repos
  102. // Get mirror repositories.
  103. mirrors := make([]*models.Repository, 0, 5)
  104. for _, repo := range repos {
  105. if repo.IsMirror {
  106. if err = repo.GetMirror(); err != nil {
  107. ctx.Handle(500, "GetMirror: "+repo.Name, err)
  108. return
  109. }
  110. mirrors = append(mirrors, repo)
  111. }
  112. }
  113. ctx.Data["MirrorCount"] = len(mirrors)
  114. ctx.Data["Mirrors"] = mirrors
  115. retrieveFeeds(ctx, ctxUser.Id, 0, false)
  116. if ctx.Written() {
  117. return
  118. }
  119. ctx.HTML(200, DASHBOARD)
  120. }
  121. func Issues(ctx *middleware.Context) {
  122. isPullList := ctx.Params(":type") == "pulls"
  123. if isPullList {
  124. ctx.Data["Title"] = ctx.Tr("pull_requests")
  125. ctx.Data["PageIsPulls"] = true
  126. } else {
  127. ctx.Data["Title"] = ctx.Tr("issues")
  128. ctx.Data["PageIsIssues"] = true
  129. }
  130. ctxUser := getDashboardContextUser(ctx)
  131. if ctx.Written() {
  132. return
  133. }
  134. // Organization does not have view type and filter mode.
  135. var (
  136. viewType string
  137. sortType = ctx.Query("sort")
  138. filterMode = models.FM_ALL
  139. assigneeID int64
  140. posterID int64
  141. )
  142. if ctxUser.IsOrganization() {
  143. viewType = "all"
  144. } else {
  145. viewType = ctx.Query("type")
  146. types := []string{"assigned", "created_by"}
  147. if !com.IsSliceContainsStr(types, viewType) {
  148. viewType = "all"
  149. }
  150. switch viewType {
  151. case "assigned":
  152. filterMode = models.FM_ASSIGN
  153. assigneeID = ctxUser.Id
  154. case "created_by":
  155. filterMode = models.FM_CREATE
  156. posterID = ctxUser.Id
  157. }
  158. }
  159. repoID := ctx.QueryInt64("repo")
  160. isShowClosed := ctx.Query("state") == "closed"
  161. // Get repositories.
  162. if ctxUser.IsOrganization() {
  163. if err := ctxUser.GetUserRepositories(ctx.User.Id); err != nil {
  164. ctx.Handle(500, "GetRepositories", err)
  165. return
  166. }
  167. } else {
  168. if err := ctxUser.GetRepositories(); err != nil {
  169. ctx.Handle(500, "GetRepositories", err)
  170. return
  171. }
  172. }
  173. repos := ctxUser.Repos
  174. allCount := 0
  175. repoIDs := make([]int64, 0, len(repos))
  176. showRepos := make([]*models.Repository, 0, len(repos))
  177. for _, repo := range repos {
  178. if (isPullList && repo.NumPulls == 0) ||
  179. (!isPullList && repo.NumIssues == 0) {
  180. continue
  181. }
  182. repoIDs = append(repoIDs, repo.ID)
  183. if isPullList {
  184. allCount += repo.NumOpenPulls
  185. repo.NumOpenIssues = repo.NumOpenPulls
  186. repo.NumClosedIssues = repo.NumClosedPulls
  187. } else {
  188. allCount += repo.NumOpenIssues
  189. }
  190. if filterMode != models.FM_ALL {
  191. // Calculate repository issue count with filter mode.
  192. numOpen, numClosed := repo.IssueStats(ctxUser.Id, filterMode, isPullList)
  193. repo.NumOpenIssues, repo.NumClosedIssues = int(numOpen), int(numClosed)
  194. }
  195. if repo.ID == repoID ||
  196. (isShowClosed && repo.NumClosedIssues > 0) ||
  197. (!isShowClosed && repo.NumOpenIssues > 0) {
  198. showRepos = append(showRepos, repo)
  199. }
  200. }
  201. ctx.Data["Repos"] = showRepos
  202. issueStats := models.GetUserIssueStats(repoID, ctxUser.Id, repoIDs, filterMode, isPullList)
  203. issueStats.AllCount = int64(allCount)
  204. page := ctx.QueryInt("page")
  205. if page <= 1 {
  206. page = 1
  207. }
  208. var total int
  209. if !isShowClosed {
  210. total = int(issueStats.OpenCount)
  211. } else {
  212. total = int(issueStats.ClosedCount)
  213. }
  214. ctx.Data["Page"] = paginater.New(total, setting.IssuePagingNum, page, 5)
  215. // Get issues.
  216. issues, err := models.Issues(&models.IssuesOptions{
  217. UserID: ctxUser.Id,
  218. AssigneeID: assigneeID,
  219. RepoID: repoID,
  220. PosterID: posterID,
  221. RepoIDs: repoIDs,
  222. Page: page,
  223. IsClosed: isShowClosed,
  224. IsPull: isPullList,
  225. SortType: sortType,
  226. })
  227. if err != nil {
  228. ctx.Handle(500, "Issues: %v", err)
  229. return
  230. }
  231. // Get posters and repository.
  232. for i := range issues {
  233. issues[i].Repo, err = models.GetRepositoryByID(issues[i].RepoID)
  234. if err != nil {
  235. ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", issues[i].ID, err))
  236. return
  237. }
  238. if err = issues[i].Repo.GetOwner(); err != nil {
  239. ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", issues[i].ID, err))
  240. return
  241. }
  242. if err = issues[i].GetPoster(); err != nil {
  243. ctx.Handle(500, "GetPoster", fmt.Errorf("[#%d]%v", issues[i].ID, err))
  244. return
  245. }
  246. }
  247. ctx.Data["Issues"] = issues
  248. ctx.Data["IssueStats"] = issueStats
  249. ctx.Data["ViewType"] = viewType
  250. ctx.Data["SortType"] = sortType
  251. ctx.Data["RepoID"] = repoID
  252. ctx.Data["IsShowClosed"] = isShowClosed
  253. if isShowClosed {
  254. ctx.Data["State"] = "closed"
  255. } else {
  256. ctx.Data["State"] = "open"
  257. }
  258. ctx.HTML(200, ISSUES)
  259. }
  260. func ShowSSHKeys(ctx *middleware.Context, uid int64) {
  261. keys, err := models.ListPublicKeys(uid)
  262. if err != nil {
  263. ctx.Handle(500, "ListPublicKeys", err)
  264. return
  265. }
  266. var buf bytes.Buffer
  267. for i := range keys {
  268. buf.WriteString(keys[i].OmitEmail())
  269. buf.WriteString("\n")
  270. }
  271. ctx.PlainText(200, buf.Bytes())
  272. }
  273. func showOrgProfile(ctx *middleware.Context) {
  274. ctx.SetParams(":org", ctx.Params(":username"))
  275. middleware.HandleOrgAssignment(ctx)
  276. if ctx.Written() {
  277. return
  278. }
  279. org := ctx.Org.Organization
  280. ctx.Data["Title"] = org.FullName
  281. if ctx.IsSigned {
  282. if err := org.GetUserRepositories(ctx.User.Id); err != nil {
  283. ctx.Handle(500, "GetUserRepositories", err)
  284. return
  285. }
  286. ctx.Data["Repos"] = org.Repos
  287. } else {
  288. repos, err := models.GetRepositories(org.Id, false)
  289. if err != nil {
  290. ctx.Handle(500, "GetRepositories", err)
  291. return
  292. }
  293. ctx.Data["Repos"] = repos
  294. }
  295. if err := org.GetMembers(); err != nil {
  296. ctx.Handle(500, "GetMembers", err)
  297. return
  298. }
  299. ctx.Data["Members"] = org.Members
  300. ctx.Data["Teams"] = org.Teams
  301. ctx.HTML(200, ORG_HOME)
  302. }
  303. func Email2User(ctx *middleware.Context) {
  304. u, err := models.GetUserByEmail(ctx.Query("email"))
  305. if err != nil {
  306. if models.IsErrUserNotExist(err) {
  307. ctx.Handle(404, "GetUserByEmail", err)
  308. } else {
  309. ctx.Handle(500, "GetUserByEmail", err)
  310. }
  311. return
  312. }
  313. ctx.Redirect(setting.AppSubUrl + "/user/" + u.Name)
  314. }