code.gitea.io/gitea@v1.21.7/routers/api/v1/repo/issue_pin.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "net/http" 8 9 issues_model "code.gitea.io/gitea/models/issues" 10 "code.gitea.io/gitea/modules/context" 11 api "code.gitea.io/gitea/modules/structs" 12 "code.gitea.io/gitea/services/convert" 13 ) 14 15 // PinIssue pins a issue 16 func PinIssue(ctx *context.APIContext) { 17 // swagger:operation POST /repos/{owner}/{repo}/issues/{index}/pin issue pinIssue 18 // --- 19 // summary: Pin an Issue 20 // parameters: 21 // - name: owner 22 // in: path 23 // description: owner of the repo 24 // type: string 25 // required: true 26 // - name: repo 27 // in: path 28 // description: name of the repo 29 // type: string 30 // required: true 31 // - name: index 32 // in: path 33 // description: index of issue to pin 34 // type: integer 35 // format: int64 36 // required: true 37 // responses: 38 // "204": 39 // "$ref": "#/responses/empty" 40 // "403": 41 // "$ref": "#/responses/forbidden" 42 // "404": 43 // "$ref": "#/responses/notFound" 44 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 45 if err != nil { 46 if issues_model.IsErrIssueNotExist(err) { 47 ctx.NotFound() 48 } else if issues_model.IsErrIssueMaxPinReached(err) { 49 ctx.Error(http.StatusBadRequest, "MaxPinReached", err) 50 } else { 51 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 52 } 53 return 54 } 55 56 // If we don't do this, it will crash when trying to add the pin event to the comment history 57 err = issue.LoadRepo(ctx) 58 if err != nil { 59 ctx.Error(http.StatusInternalServerError, "LoadRepo", err) 60 return 61 } 62 63 err = issue.Pin(ctx, ctx.Doer) 64 if err != nil { 65 ctx.Error(http.StatusInternalServerError, "PinIssue", err) 66 return 67 } 68 69 ctx.Status(http.StatusNoContent) 70 } 71 72 // UnpinIssue unpins a Issue 73 func UnpinIssue(ctx *context.APIContext) { 74 // swagger:operation DELETE /repos/{owner}/{repo}/issues/{index}/pin issue unpinIssue 75 // --- 76 // summary: Unpin an Issue 77 // parameters: 78 // - name: owner 79 // in: path 80 // description: owner of the repo 81 // type: string 82 // required: true 83 // - name: repo 84 // in: path 85 // description: name of the repo 86 // type: string 87 // required: true 88 // - name: index 89 // in: path 90 // description: index of issue to unpin 91 // type: integer 92 // format: int64 93 // required: true 94 // responses: 95 // "204": 96 // "$ref": "#/responses/empty" 97 // "403": 98 // "$ref": "#/responses/forbidden" 99 // "404": 100 // "$ref": "#/responses/notFound" 101 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 102 if err != nil { 103 if issues_model.IsErrIssueNotExist(err) { 104 ctx.NotFound() 105 } else { 106 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 107 } 108 return 109 } 110 111 // If we don't do this, it will crash when trying to add the unpin event to the comment history 112 err = issue.LoadRepo(ctx) 113 if err != nil { 114 ctx.Error(http.StatusInternalServerError, "LoadRepo", err) 115 return 116 } 117 118 err = issue.Unpin(ctx, ctx.Doer) 119 if err != nil { 120 ctx.Error(http.StatusInternalServerError, "UnpinIssue", err) 121 return 122 } 123 124 ctx.Status(http.StatusNoContent) 125 } 126 127 // MoveIssuePin moves a pinned Issue to a new Position 128 func MoveIssuePin(ctx *context.APIContext) { 129 // swagger:operation PATCH /repos/{owner}/{repo}/issues/{index}/pin/{position} issue moveIssuePin 130 // --- 131 // summary: Moves the Pin to the given Position 132 // parameters: 133 // - name: owner 134 // in: path 135 // description: owner of the repo 136 // type: string 137 // required: true 138 // - name: repo 139 // in: path 140 // description: name of the repo 141 // type: string 142 // required: true 143 // - name: index 144 // in: path 145 // description: index of issue 146 // type: integer 147 // format: int64 148 // required: true 149 // - name: position 150 // in: path 151 // description: the new position 152 // type: integer 153 // format: int64 154 // required: true 155 // responses: 156 // "204": 157 // "$ref": "#/responses/empty" 158 // "403": 159 // "$ref": "#/responses/forbidden" 160 // "404": 161 // "$ref": "#/responses/notFound" 162 issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.ParamsInt64(":index")) 163 if err != nil { 164 if issues_model.IsErrIssueNotExist(err) { 165 ctx.NotFound() 166 } else { 167 ctx.Error(http.StatusInternalServerError, "GetIssueByIndex", err) 168 } 169 return 170 } 171 172 err = issue.MovePin(ctx, int(ctx.ParamsInt64(":position"))) 173 if err != nil { 174 ctx.Error(http.StatusInternalServerError, "MovePin", err) 175 return 176 } 177 178 ctx.Status(http.StatusNoContent) 179 } 180 181 // ListPinnedIssues returns a list of all pinned Issues 182 func ListPinnedIssues(ctx *context.APIContext) { 183 // swagger:operation GET /repos/{owner}/{repo}/issues/pinned repository repoListPinnedIssues 184 // --- 185 // summary: List a repo's pinned issues 186 // produces: 187 // - application/json 188 // parameters: 189 // - name: owner 190 // in: path 191 // description: owner of the repo 192 // type: string 193 // required: true 194 // - name: repo 195 // in: path 196 // description: name of the repo 197 // type: string 198 // required: true 199 // responses: 200 // "200": 201 // "$ref": "#/responses/IssueList" 202 // "404": 203 // "$ref": "#/responses/notFound" 204 issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, false) 205 if err != nil { 206 ctx.Error(http.StatusInternalServerError, "LoadPinnedIssues", err) 207 return 208 } 209 210 ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) 211 } 212 213 // ListPinnedPullRequests returns a list of all pinned PRs 214 func ListPinnedPullRequests(ctx *context.APIContext) { 215 // swagger:operation GET /repos/{owner}/{repo}/pulls/pinned repository repoListPinnedPullRequests 216 // --- 217 // summary: List a repo's pinned pull requests 218 // produces: 219 // - application/json 220 // parameters: 221 // - name: owner 222 // in: path 223 // description: owner of the repo 224 // type: string 225 // required: true 226 // - name: repo 227 // in: path 228 // description: name of the repo 229 // type: string 230 // required: true 231 // responses: 232 // "200": 233 // "$ref": "#/responses/PullRequestList" 234 // "404": 235 // "$ref": "#/responses/notFound" 236 issues, err := issues_model.GetPinnedIssues(ctx, ctx.Repo.Repository.ID, true) 237 if err != nil { 238 ctx.Error(http.StatusInternalServerError, "LoadPinnedPullRequests", err) 239 return 240 } 241 242 apiPrs := make([]*api.PullRequest, len(issues)) 243 for i, currentIssue := range issues { 244 pr, err := currentIssue.GetPullRequest() 245 if err != nil { 246 ctx.Error(http.StatusInternalServerError, "GetPullRequest", err) 247 return 248 } 249 250 if err = pr.LoadIssue(ctx); err != nil { 251 ctx.Error(http.StatusInternalServerError, "LoadIssue", err) 252 return 253 } 254 255 if err = pr.LoadAttributes(ctx); err != nil { 256 ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) 257 return 258 } 259 260 if err = pr.LoadBaseRepo(ctx); err != nil { 261 ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err) 262 return 263 } 264 265 if err = pr.LoadHeadRepo(ctx); err != nil { 266 ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err) 267 return 268 } 269 270 apiPrs[i] = convert.ToAPIPullRequest(ctx, pr, ctx.Doer) 271 } 272 273 ctx.JSON(http.StatusOK, &apiPrs) 274 } 275 276 // AreNewIssuePinsAllowed returns if new issues pins are allowed 277 func AreNewIssuePinsAllowed(ctx *context.APIContext) { 278 // swagger:operation GET /repos/{owner}/{repo}/new_pin_allowed repository repoNewPinAllowed 279 // --- 280 // summary: Returns if new Issue Pins are allowed 281 // produces: 282 // - application/json 283 // parameters: 284 // - name: owner 285 // in: path 286 // description: owner of the repo 287 // type: string 288 // required: true 289 // - name: repo 290 // in: path 291 // description: name of the repo 292 // type: string 293 // required: true 294 // responses: 295 // "200": 296 // "$ref": "#/responses/RepoNewIssuePinsAllowed" 297 // "404": 298 // "$ref": "#/responses/notFound" 299 pinsAllowed := api.NewIssuePinsAllowed{} 300 var err error 301 302 pinsAllowed.Issues, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, false) 303 if err != nil { 304 ctx.Error(http.StatusInternalServerError, "IsNewIssuePinAllowed", err) 305 return 306 } 307 308 pinsAllowed.PullRequests, err = issues_model.IsNewPinAllowed(ctx, ctx.Repo.Repository.ID, true) 309 if err != nil { 310 ctx.Error(http.StatusInternalServerError, "IsNewPullRequestPinAllowed", err) 311 return 312 } 313 314 ctx.JSON(http.StatusOK, pinsAllowed) 315 }