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.9 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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/context"
  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 *context.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 *context.Context, ctxUserID, userID, offset int64, isProfile bool) {
  46. actions, err := models.GetFeeds(ctxUserID, userID, 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 *context.Context) {
  74. ctxUser := getDashboardContextUser(ctx)
  75. ctx.Data["Title"] = ctxUser.DisplayName() + " - " + ctx.Tr("dashboard")
  76. ctx.Data["PageIsDashboard"] = true
  77. ctx.Data["PageIsNews"] = true
  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. var repos []*models.Repository
  97. if ctxUser.IsOrganization() {
  98. if err := ctxUser.GetUserRepositories(ctx.User.Id); err != nil {
  99. ctx.Handle(500, "GetUserRepositories", err)
  100. return
  101. }
  102. repos = ctxUser.Repos
  103. } else {
  104. var err error
  105. repos, err = models.GetRepositories(ctxUser.Id, true)
  106. if err != nil {
  107. ctx.Handle(500, "GetRepositories", err)
  108. return
  109. }
  110. }
  111. ctx.Data["Repos"] = repos
  112. // Get mirror repositories.
  113. mirrors := make([]*models.Repository, 0, 5)
  114. for _, repo := range repos {
  115. if repo.IsMirror {
  116. if err := repo.GetMirror(); err != nil {
  117. ctx.Handle(500, "GetMirror: "+repo.Name, err)
  118. return
  119. }
  120. mirrors = append(mirrors, repo)
  121. }
  122. }
  123. ctx.Data["MirrorCount"] = len(mirrors)
  124. ctx.Data["Mirrors"] = mirrors
  125. retrieveFeeds(ctx, ctxUser.Id, ctx.User.Id, 0, false)
  126. if ctx.Written() {
  127. return
  128. }
  129. ctx.HTML(200, DASHBOARD)
  130. }
  131. func Issues(ctx *context.Context) {
  132. isPullList := ctx.Params(":type") == "pulls"
  133. if isPullList {
  134. ctx.Data["Title"] = ctx.Tr("pull_requests")
  135. ctx.Data["PageIsPulls"] = true
  136. } else {
  137. ctx.Data["Title"] = ctx.Tr("issues")
  138. ctx.Data["PageIsIssues"] = true
  139. }
  140. ctxUser := getDashboardContextUser(ctx)
  141. if ctx.Written() {
  142. return
  143. }
  144. // Organization does not have view type and filter mode.
  145. var (
  146. viewType string
  147. sortType = ctx.Query("sort")
  148. filterMode = models.FM_ALL
  149. assigneeID int64
  150. posterID int64
  151. )
  152. if ctxUser.IsOrganization() {
  153. viewType = "all"
  154. } else {
  155. viewType = ctx.Query("type")
  156. types := []string{"assigned", "created_by"}
  157. if !com.IsSliceContainsStr(types, viewType) {
  158. viewType = "all"
  159. }
  160. switch viewType {
  161. case "assigned":
  162. filterMode = models.FM_ASSIGN
  163. assigneeID = ctxUser.Id
  164. case "created_by":
  165. filterMode = models.FM_CREATE
  166. posterID = ctxUser.Id
  167. }
  168. }
  169. repoID := ctx.QueryInt64("repo")
  170. isShowClosed := ctx.Query("state") == "closed"
  171. // Get repositories.
  172. if ctxUser.IsOrganization() {
  173. if err := ctxUser.GetUserRepositories(ctx.User.Id); err != nil {
  174. ctx.Handle(500, "GetRepositories", err)
  175. return
  176. }
  177. } else {
  178. if err := ctxUser.GetRepositories(); err != nil {
  179. ctx.Handle(500, "GetRepositories", err)
  180. return
  181. }
  182. }
  183. repos := ctxUser.Repos
  184. allCount := 0
  185. repoIDs := make([]int64, 0, len(repos))
  186. showRepos := make([]*models.Repository, 0, len(repos))
  187. for _, repo := range repos {
  188. if (isPullList && repo.NumPulls == 0) ||
  189. (!isPullList && repo.NumIssues == 0) {
  190. continue
  191. }
  192. repoIDs = append(repoIDs, repo.ID)
  193. if isPullList {
  194. allCount += repo.NumOpenPulls
  195. repo.NumOpenIssues = repo.NumOpenPulls
  196. repo.NumClosedIssues = repo.NumClosedPulls
  197. } else {
  198. allCount += repo.NumOpenIssues
  199. }
  200. if filterMode != models.FM_ALL {
  201. // Calculate repository issue count with filter mode.
  202. numOpen, numClosed := repo.IssueStats(ctxUser.Id, filterMode, isPullList)
  203. repo.NumOpenIssues, repo.NumClosedIssues = int(numOpen), int(numClosed)
  204. }
  205. if repo.ID == repoID ||
  206. (isShowClosed && repo.NumClosedIssues > 0) ||
  207. (!isShowClosed && repo.NumOpenIssues > 0) {
  208. showRepos = append(showRepos, repo)
  209. }
  210. }
  211. ctx.Data["Repos"] = showRepos
  212. issueStats := models.GetUserIssueStats(repoID, ctxUser.Id, repoIDs, filterMode, isPullList)
  213. issueStats.AllCount = int64(allCount)
  214. page := ctx.QueryInt("page")
  215. if page <= 1 {
  216. page = 1
  217. }
  218. var total int
  219. if !isShowClosed {
  220. total = int(issueStats.OpenCount)
  221. } else {
  222. total = int(issueStats.ClosedCount)
  223. }
  224. ctx.Data["Page"] = paginater.New(total, setting.IssuePagingNum, page, 5)
  225. // Get issues.
  226. issues, err := models.Issues(&models.IssuesOptions{
  227. UserID: ctxUser.Id,
  228. AssigneeID: assigneeID,
  229. RepoID: repoID,
  230. PosterID: posterID,
  231. RepoIDs: repoIDs,
  232. Page: page,
  233. IsClosed: isShowClosed,
  234. IsPull: isPullList,
  235. SortType: sortType,
  236. })
  237. if err != nil {
  238. ctx.Handle(500, "Issues", err)
  239. return
  240. }
  241. // Get posters and repository.
  242. for i := range issues {
  243. issues[i].Repo, err = models.GetRepositoryByID(issues[i].RepoID)
  244. if err != nil {
  245. ctx.Handle(500, "GetRepositoryByID", fmt.Errorf("[#%d]%v", issues[i].ID, err))
  246. return
  247. }
  248. if err = issues[i].Repo.GetOwner(); err != nil {
  249. ctx.Handle(500, "GetOwner", fmt.Errorf("[#%d]%v", issues[i].ID, err))
  250. return
  251. }
  252. }
  253. ctx.Data["Issues"] = issues
  254. ctx.Data["IssueStats"] = issueStats
  255. ctx.Data["ViewType"] = viewType
  256. ctx.Data["SortType"] = sortType
  257. ctx.Data["RepoID"] = repoID
  258. ctx.Data["IsShowClosed"] = isShowClosed
  259. if isShowClosed {
  260. ctx.Data["State"] = "closed"
  261. } else {
  262. ctx.Data["State"] = "open"
  263. }
  264. ctx.HTML(200, ISSUES)
  265. }
  266. func ShowSSHKeys(ctx *context.Context, uid int64) {
  267. keys, err := models.ListPublicKeys(uid)
  268. if err != nil {
  269. ctx.Handle(500, "ListPublicKeys", err)
  270. return
  271. }
  272. var buf bytes.Buffer
  273. for i := range keys {
  274. buf.WriteString(keys[i].OmitEmail())
  275. buf.WriteString("\n")
  276. }
  277. ctx.PlainText(200, buf.Bytes())
  278. }
  279. func showOrgProfile(ctx *context.Context) {
  280. ctx.SetParams(":org", ctx.Params(":username"))
  281. context.HandleOrgAssignment(ctx)
  282. if ctx.Written() {
  283. return
  284. }
  285. org := ctx.Org.Organization
  286. ctx.Data["Title"] = org.FullName
  287. if ctx.IsSigned {
  288. if ctx.User.IsAdmin {
  289. repos, err := models.GetRepositories(org.Id, true)
  290. if err != nil {
  291. ctx.Handle(500, "GetRepositoriesAsAdmin", err)
  292. return
  293. }
  294. ctx.Data["Repos"] = repos
  295. } else {
  296. if err := org.GetUserRepositories(ctx.User.Id); err != nil {
  297. ctx.Handle(500, "GetUserRepositories", err)
  298. return
  299. }
  300. ctx.Data["Repos"] = org.Repos
  301. }
  302. } else {
  303. repos, err := models.GetRepositories(org.Id, false)
  304. if err != nil {
  305. ctx.Handle(500, "GetRepositories", err)
  306. return
  307. }
  308. ctx.Data["Repos"] = repos
  309. }
  310. if err := org.GetMembers(); err != nil {
  311. ctx.Handle(500, "GetMembers", err)
  312. return
  313. }
  314. ctx.Data["Members"] = org.Members
  315. ctx.Data["Teams"] = org.Teams
  316. ctx.HTML(200, ORG_HOME)
  317. }
  318. func Email2User(ctx *context.Context) {
  319. u, err := models.GetUserByEmail(ctx.Query("email"))
  320. if err != nil {
  321. if models.IsErrUserNotExist(err) {
  322. ctx.Handle(404, "GetUserByEmail", err)
  323. } else {
  324. ctx.Handle(500, "GetUserByEmail", err)
  325. }
  326. return
  327. }
  328. ctx.Redirect(setting.AppSubUrl + "/user/" + u.Name)
  329. }