@@ -23,6 +23,7 @@ import (
2323 "code.gitea.io/gitea/modules/setting"
2424 "code.gitea.io/gitea/modules/util"
2525 "code.gitea.io/gitea/modules/web"
26+ shared_user "code.gitea.io/gitea/routers/web/shared/user"
2627 "code.gitea.io/gitea/services/context"
2728 "code.gitea.io/gitea/services/forms"
2829 project_service "code.gitea.io/gitea/services/projects"
@@ -313,7 +314,29 @@ func ViewProject(ctx *context.Context) {
313314 return
314315 }
315316
316- issuesMap , err := issues_model .LoadIssuesFromColumnList (ctx , columns )
317+ var labelIDs []int64
318+ // 1,-2 means including label 1 and excluding label 2
319+ // 0 means issues with no label
320+ // blank means labels will not be filtered for issues
321+ selectLabels := ctx .FormString ("labels" )
322+ if selectLabels == "" {
323+ ctx .Data ["AllLabels" ] = true
324+ } else if selectLabels == "0" {
325+ ctx .Data ["NoLabel" ] = true
326+ }
327+ if len (selectLabels ) > 0 {
328+ labelIDs , err = base .StringsToInt64s (strings .Split (selectLabels , "," ))
329+ if err != nil {
330+ ctx .Flash .Error (ctx .Tr ("invalid_data" , selectLabels ), true )
331+ }
332+ }
333+
334+ assigneeID := ctx .FormInt64 ("assignee" )
335+
336+ issuesMap , err := issues_model .LoadIssuesFromColumnList (ctx , columns , & issues_model.IssuesOptions {
337+ LabelIDs : labelIDs ,
338+ AssigneeID : assigneeID ,
339+ })
317340 if err != nil {
318341 ctx .ServerError ("LoadIssuesOfColumns" , err )
319342 return
@@ -353,6 +376,55 @@ func ViewProject(ctx *context.Context) {
353376 }
354377 ctx .Data ["LinkedPRs" ] = linkedPrsMap
355378
379+ labels , err := issues_model .GetLabelsByRepoID (ctx , project .RepoID , "" , db.ListOptions {})
380+ if err != nil {
381+ ctx .ServerError ("GetLabelsByRepoID" , err )
382+ return
383+ }
384+
385+ if ctx .Repo .Owner .IsOrganization () {
386+ orgLabels , err := issues_model .GetLabelsByOrgID (ctx , ctx .Repo .Owner .ID , "" , db.ListOptions {})
387+ if err != nil {
388+ ctx .ServerError ("GetLabelsByOrgID" , err )
389+ return
390+ }
391+
392+ labels = append (labels , orgLabels ... )
393+ }
394+
395+ // Get the exclusive scope for every label ID
396+ labelExclusiveScopes := make ([]string , 0 , len (labelIDs ))
397+ for _ , labelID := range labelIDs {
398+ foundExclusiveScope := false
399+ for _ , label := range labels {
400+ if label .ID == labelID || label .ID == - labelID {
401+ labelExclusiveScopes = append (labelExclusiveScopes , label .ExclusiveScope ())
402+ foundExclusiveScope = true
403+ break
404+ }
405+ }
406+ if ! foundExclusiveScope {
407+ labelExclusiveScopes = append (labelExclusiveScopes , "" )
408+ }
409+ }
410+
411+ for _ , l := range labels {
412+ l .LoadSelectedLabelsAfterClick (labelIDs , labelExclusiveScopes )
413+ }
414+ ctx .Data ["Labels" ] = labels
415+ ctx .Data ["NumLabels" ] = len (labels )
416+
417+ // Get assignees.
418+ assigneeUsers , err := repo_model .GetRepoAssignees (ctx , ctx .Repo .Repository )
419+ if err != nil {
420+ ctx .ServerError ("GetRepoAssignees" , err )
421+ return
422+ }
423+ ctx .Data ["Assignees" ] = shared_user .MakeSelfOnTop (ctx .Doer , assigneeUsers )
424+
425+ ctx .Data ["SelectLabels" ] = selectLabels
426+ ctx .Data ["AssigneeID" ] = assigneeID
427+
356428 project .RenderedContent , err = markdown .RenderString (& markup.RenderContext {
357429 Links : markup.Links {
358430 Base : ctx .Repo .RepoLink ,
0 commit comments